Skip to content

Commit

Permalink
support utils
Browse files Browse the repository at this point in the history
  • Loading branch information
jonschlinkert committed Sep 28, 2015
1 parent 27ba772 commit 8cde3c8
Show file tree
Hide file tree
Showing 12 changed files with 533 additions and 1 deletion.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ docs
example.js
node_modules
npm-debug.log
support
temp
tmp
TODO.md
Expand Down
137 changes: 137 additions & 0 deletions support/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
'use strict';

var through = require('through2');
var parse = require('parse-comments');
var context = require('code-context');
var extract = require('extract-comments');
var engine = require('engine')();
var forOwn = require('for-own');

var base = [
'/**',
' * @name .<%= name %>',
'<% params.forEach(function(param) { %>' +
' * @param {type} `<%= param %>`',
'<% }) %>' +
' * @return {<%= ret || "" %>}',
' * @api public',
' */',
''
].join('\n');

module.exports = function organize(options) {
return through.obj(function (file, enc, cb) {
var str = file.contents.toString();
str = addComment(str, file.path);

var lines = str.split('\n');
var comments = parse(str);
file.comments = [];

forOwn(comments, function (obj, key) {
var block = lines.slice(obj.comment.begin - 1, obj.comment.end);

var orig = block.join('\n');
var param = paramLine(block, 'param');

// fix spacing
if (param && hasText(block[param - 1])) {
block.splice(param, 0, ' *');
}

// add @name
var idx = paramLine(block, 'name');
if (!idx && param) {
var method = obj.context.name;
block.splice(param, 0, ' * @name .' + method);
}


idx = paramLine(block, 'api');
var ret = paramLine(block, 'return');
if (!ret) {
if (idx) {
ret = idx;
block.splice(ret, 0, ' * @return');
} else {
ret = block.length - 1;
block.splice(ret, 0, ' * @return');
}
}

if (!idx && ret) {
block.splice(ret + 1, 0, ' * @api public');
}

var res = lines.slice(0, obj.comment.begin - 1);
res = res.concat(block);
res = res.concat(lines.slice(obj.comment.end));
var parts = str.split(orig);
if (parts && parts.length) {
var updated = parts.join(res.join('\n'));
if (updated) {

// console.log(updated)
}
// str = parts.join(res.join('\n'));
}

file.comments.push(obj);
});

str = str.split(/^\s*exports\./gm).join('\nhelpers.');

file.contents = new Buffer(str);
cb(null, file);
});
}

function paramLine(lines, param) {
var re = new RegExp('@' + param);
var len = lines.length, i = -1;
while (++i < len) {
if (re.test(lines[i])) {
return i;
}
}
return null;
}

function addComment(str, fp) {
var lines = str.split('\n');
var len = lines.length, i = -1;
while (++i < len) {
var line = lines[i];
if (/^\s*exports\./.test(line)) {
if (!hasComment(lines, i)) {
var ctx = context(line)[0];
if (/comp/.test(fp)) {
ctx.ret = 'Boolean';
} else if (/math|number/.test(fp)) {
ctx.ret = 'Number';
} else if (/object/.test(fp)) {
ctx.ret = 'Object';
} else if (/array/.test(fp)) {
ctx.ret = 'Array';
} else if (/date/.test(fp)) {
ctx.ret = 'Date';
} else {
ctx.ret = 'String';
}
var res = engine.render(base, ctx);
lines = lines.slice(0, i).concat(res.split('\n')).concat(lines.slice(i));
}
}
}
return lines.join('\n');
}

function hasText(line) {
return / \* \w+/.test(line);
}

function hasComment(lines, i) {
return / \*\//.test(lines[i - 1])
|| / \*\//.test(lines[i - 2])
|| / \*\//.test(lines[i - 3]);
}
1 change: 1 addition & 0 deletions support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('export-files')(__dirname);
34 changes: 34 additions & 0 deletions support/lint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

var forIn = require('for-in');
var esprima = require('esprima');
var through = require('through2');

module.exports = function(options) {
var helpers = {};

return through.obj(function (file, enc, cb) {
var str = file.contents.toString();
var res = esprima.parse(str);
file.helpers = [];
helpers[file.path] = [];

res.body.forEach(function (method) {
forIn(method, function (val, key) {

// if (val === 'ExpressionStatement') {
// var exp = method.expression;
// if (exp.left) {
// if (exp.left.object.name === 'helpers') {
// var name = exp.left.property.name;
// file.helpers.push(name);
// helpers[file.path].push(name);
// }
// }
// }
});
});

cb(null, file);
});
}
155 changes: 155 additions & 0 deletions support/methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
'use strict';

var path = require('path');
var File = require('vinyl');
var define = require('define-property');
var esprima = require('esprima');
var through = require('through2');
var toc = require('./utils/toc');

module.exports = function(options) {
options = options || {};
options.cwd = options.cwd || '';
var total = 0;
var data = {};

return through.obj(function (file, enc, cb) {
if (/index/.test(file.path)) {
return cb();
}

var bullets = [];
var count = 0;

var str = file.contents.toString();
var lines = str.split('\n');
var res = esprima.parse(str, {loc: true, comment: true, tolerant: true});
file.data = {};
file.data.methods = {};
var nocomment = [];

file.name = name(file.path);
file.data.codepath = path.join(options.cwd, file.relative);

var comments = res.comments.reduce(function (acc, comment) {
if (comment.type.toLowerCase() === 'block') {
acc.push({
start: comment.loc.start.line,
end: comment.loc.end.line,
raw: comment.value,
lines: stripStars(comment.value)
});
}
return acc;
}, []);

res.body.forEach(function (method) {
if (method.type === 'ExpressionStatement') {
var exp = method.expression;

if (exp.left) {
if (exp.left.object.name === options.name) {
// count the method
total++;
count++;

// get the starting/ending line numbers
var method = exp.left.property.name;
var start = exp.loc.start.line;
var end = exp.loc.end.line;

var code = extract(lines, start, end);
var comment = closest(start, code, comments);
var params = groupParams(exp.right.params);
if (!comment) {
nocomment.push(method);
comment = {};
}

var obj = {
name: method,
path: file.data.codepath,
stats: {
isModule: !params && /require/.test(code),
isBlockHelper: isBlockHelper(code),
},
code: {
start: start,
end: end,
raw: code,
params: params
},
comment: comment,
context: {
parent: file.name,
tests: 'test/' + file.name + '.js'
}
};

bullets.push(toc.bullet(method, obj));

define(obj, 'exp', exp);
file.data.methods[method] = obj;
}
}
}
});

file.data.count = count;
data[file.name] = {
name: file.name,
path: file.data.codepath,
data: file.data,
missingdocs: nocomment
};

cb(null, file);
}, function (cb) {
var file = new File({path: 'summary.md'});
file.data = {};
file.data.methods = data;
file.data.total = total;
this.push(file);
cb();
});
}

function name(fp) {
return path.basename(fp, path.extname(fp));
}

function extract(lines, start, end) {
return lines.slice(start - 1, end).join('\n');
}

function groupParams(arr) {
if (!Array.isArray(arr)) {
return null;
}
return arr.map(function (ele) {
return ele.name;
});
}

function closest(start, code, comments) {
var keys = Object.keys(comments);
var len = keys.length;
while (len--) {
var comment = comments[keys[len]];
if (start <= comment.end + 3) {
return comment;
}
}
return null;
}

function stripStars(str) {
var lines = str.split('\n');
return lines.map(function (line) {
return line.replace(/^[\s*]*/, '');
});
}

function isBlockHelper(str) {
return /(options\.fn|options\.inverse)/.test(str);
}
46 changes: 46 additions & 0 deletions support/modularize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

var path = require('path');
var through = require('through2');
var Vinyl = require('vinyl');

module.exports = function modularize(options) {
var files = {};

return through.obj(function (file, enc, cb) {
var str = file.contents.toString();

var methods = str.split('};\n\n/**');
var len = methods.length;

while (len--) {
var method = '/**' + methods[len] + '};\n\n';
var match = /^helpers\.([\w]+)/gm.exec(method);

if (!match) return cb();
var res = method.split(match[0]).join('module.exports');
res = res.split('<%= ').join('');
res = res.split(' %>').join(';');
files[match[1]] ={ path: file.path, content: res };
}

cb();
}, function (cb) {
for (var key in files) {
if (files.hasOwnProperty(key)) {
var file = files[key];
var ext = path.extname(file.path)
var dir = path.basename(file.path, ext);

var vinyl = new Vinyl({
path: path.join(dir, key + '.js')
});

var str = '\'use strict\';\n\n' + file.content;
vinyl.contents = new Buffer(str);
this.push(vinyl);
}
}
cb();
});
};
Loading

0 comments on commit 8cde3c8

Please sign in to comment.