ldx-widgets
Version:
widgets
340 lines (295 loc) • 10.8 kB
JavaScript
var gulp = require('gulp');
var sequence = require('run-sequence');
var coffee = require('gulp-coffee');
var gutil = require('gulp-util');
var globby = require('globby');
var fs = require('fs');
var async = require('async');
var del = require('del');
var _ = require('lodash');
var path = require('path');
var package = require('./package.json');
var minimist = require('minimist');
var paths;
var Server = require('karma').Server;
var karmaConfig = {
configFile: __dirname + "/karma.conf.js",
action: "run",
autoWatch: true,
singleRun: false
};
gulp.task('client-build', function() {
return sequence('js');
});
gulp.task('js', function() {
return gulp.src('./src/**/*.coffee').pipe(coffee()).pipe(gulp.dest('./dist'));
});
pathAccessError = function (destination) {
gutil.log(gutil.colors.red("Error accessing project directory " + destination + ". Make sure you have the correct absolute path defined in paths.json, and that the path is writeable."));
}
gulp.task('copyCompiled', function() {
var name = package.name;
if(!paths.length) {
pathAccessError();
process.exit(1);
}
// Make sure the path is valid and writeable
paths.forEach(function(p) {
var PATH = p.PATH;
var destination = path.join(PATH, "node_modules", name);
fs.access(destination, fs.constants.F_OK | fs.constants.W_OK, function (err) {
if (err) {
pathAccessError(destination);
throw err;
}
console.log("Copying compiled source to " + destination + "...");
return gulp.src('./dist/**').pipe(gulp.dest(path.join(destination, 'dist')));
});
});
});
gulp.task('dev', function() {
sequence('js', 'copyCompiled');
gulp.watch('./src/**/*.coffee', ['js', 'copyCompiled']);
});
// Run tests
gulp.task('test', function() {
var args = minimist(process.argv.slice(2));
var tasks = ['js', 'docs'];
if(args.alone !== true) {
tasks.splice(1, 0, 'copyCompiled')
try {
paths = require('./paths.json');
}
catch (err) {
gutil.log(gutil.colors.red("Error accessing paths.json. Make sure you have created paths.json in the root of this repository and specified the paths to your destination projects."));
console.warn(err)
}
}
// Watch & compile Coffee edits
gulp.watch('./src/**/*.coffee', function() {
sequence.apply(null, tasks);
});
// Start the test server
server = new Server(karmaConfig);
server.start();
});
// Run tests
gulp.task('testonce', function(done) {
// Compile the Coffee once
gulp.start('js');
server = new Server({
configFile: `${__dirname}/karma.conf.js`,
port: 9876,
autoWatch: false,
singleRun: true
}, (exitCode) => {
console.log('End Tests -----------------------------------------------------------------------');
if (exitCode > 0) { process.exit(exitCode); }
done();
});
server.start()
});
gulp.task('docs', function () {
var indexFiles = [];
var BLOB_ROOT = "https://github.com/tmfi/ldx-web-utilities/blob/develop";
del('./docs/**/*')
.then(function () {
fs.mkdirSync('./docs/components');
})
.then(function () {
globby(["./src/**/*.coffee"])
.catch(function (err) {
throw err;
})
.then(function (files) {
// Regex patterns
var dnReg = new RegExp(/(?:displayName:[\s]*['"])([\S]+)(?:['"])/);
var mxReg = new RegExp(/(?:mixins:[\s]*\[)(.+)(?:\])/);
var cmReg = new RegExp(/###&([\s\S]+)&###/);
var gnReg = new RegExp(/(?:@general[\n|\r])(([\s\S](?!@(?:props|param)))+)/);
// Matches
var matches = [];
async.each(files, function (file, cb) {
var match = {
file: file,
props: []
};
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
throw err;
}
// Display name
dn = data.match(dnReg);
if (dn != null) {
match.displayName = dn[1];
}
// Mixins
mx = data.match(mxReg);
if (mx != null) {
match.mixins = mx[1];
}
// General comments
gn = data.match(gnReg);
if (gn != null) {
match.general = gn[1]
}
// Comment
cm = data.match(cmReg);
if (cm != null) {
pReg = new RegExp(/^(.*)?@(?:props|param).*/);
var c = cm[1].match(/.+/g);
if (c != null) {
var reachedProps = false;
for (var i = 0, len = c.length; i < len; i++) {
// Start at the first prop
if (c[i].match(/@(?:props|param)/) && !reachedProps) {
reachedProps = true;
}
else if (!reachedProps) {
continue;
}
n = c[i];
p = {
name: '',
desc: []
};
// Check for props definition
if (n.match(pReg)) {
var propDef = n.split(/@(?:props|param)[\.\s]+?/)[1];
var prop = propDef.match(/[\w]+/)[0];
var type = propDef.match(/\[(.+)\]/);
var reqOpt = propDef.match(/\b(Required|Optional)/i);
// Normalize req/opt
if (reqOpt && reqOpt[1].search(/req/i) > -1) {
reqOpt = "Required";
}
else {
reqOpt = "Optional";
}
// Add horizontal lines
if (match.props.length) {
p.name += "\n---\n";
}
p.name += "### " + prop;
// Apply a type
if (type) {
p.desc.push("**`" + type[1] + "`**");
}
// Add required/optional
if (reqOpt) {
p.desc.push(" _" + reqOpt + "_\n");
}
}
// Other lines
else if (n) {
p.desc.push(n + " ");
}
match.props.push(p);
}
}
}
if (Object.keys(match).length) {
matches.push(match);
}
return cb();
});
}, function () {
async.each(matches, function (m, cb) {
var file = m.file;
file = file.split(/([\w]+\.coffee)$/)[1];
var stream = fs.createWriteStream('./docs/components/' + file + '.md');
var absFile = m.file.slice(1);
var fnm = m.displayName || file;
// Camelcase mixins
if (m.file.search('/mixins') > -1) {
// Replace underscores with uppercase
fnm = fnm.split('.coffee')[0];
fnm = fnm.split('_');
for (var i = 1, len = fnm.length - 1; i <= len; i++) {
fnm[i] = fnm[i].charAt(0).toUpperCase() + fnm[i].slice(1);
}
fnm = fnm.join('');
// Add Mixin suffix if not present
if (fnm.toLowerCase().search('mixin') === -1) {
fnm += "Mixin";
}
}
// Uppercase constants
else if (m.file.search('/constants') > -1) {
fnm = fnm.split('.coffee')[0].toUpperCase();
}
else if (m.file.search('.coffee') > -1) {
fnm = fnm.split('.coffee')[0];
}
indexFiles.push({
name: fnm,
path: file
});
stream.once('open', function (fd) {
stream.write("[<< Component Index](../README.md)\n");
stream.write("# " + " [" + (m.displayName || file) + "](" + BLOB_ROOT + absFile + ")\n");
if (m.general != null) {
stream.write(m.general + "\n");
}
if (m.mixins != null) {
stream.write("## Mixins: `" + m.mixins + "`\n");
}
if (m.props != null) {
m.props.forEach(function (p) {
if (p.name) {
stream.write(p.name + "\n");
}
if (p.desc != null) {
p.desc.forEach(function (pd) {
stream.write(pd + "\n");
});
}
});
}
stream.end();
return cb();
});
});
// Build the index file
// Header info
var readme = [
"# Widgets Documentation",
"Component documentation blocks should look as follows:",
"```coffeescript",
"###&",
" @props.myPropName - [Object|Boolean|String|Number|Array|Function] - Optional|Required",
" Here is a description of myPropName. This is where you can leave",
" Multi-line notes to describe the functionality of this prop.",
"&###",
"```"
];
// Sort by name
indexFiles = _.sortBy(indexFiles, 'name');
indexFiles.forEach(function (idf) {
var nm = idf.name;
var pt = idf.path;
var mdpt = "./components/" + idf.path + ".md";
readme.push("[" + nm + "]" + "(" + mdpt + ") `" + pt + "` ");
});
readme = readme.join("\n");
fs.writeFile('./docs/README.md', readme, function (err) {
if (err) throw err;
// Build the doc manifest
var manifest = [
"module.exports = {",
];
indexFiles.forEach(function (idf) {
var nm = idf.name;
var mdpt = "components/" + idf.path + ".md";
manifest.push("\t" + nm + ": '" + mdpt + "',");
});
manifest.push("};");
manifest = manifest.join("\n");
fs.writeFile('./docs/manifest.js', manifest, function (err) {
if (err) throw err;
});
});
});
});
});
});