Skip to content

Commit

Permalink
Add scripts to generate the docs for lodash/fp.
Browse files Browse the repository at this point in the history
  • Loading branch information
jfmengels authored and jdalton committed Jan 29, 2016
1 parent 783a8e3 commit 1a9bcd0
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 2 deletions.
122 changes: 122 additions & 0 deletions lib/doc/apply-fp-mapping.js
@@ -0,0 +1,122 @@
var _ = require('lodash'),
j = require('jscodeshift'),
Entry = require('docdown/lib/entry');

var baseGetParams = Entry.prototype.getParams;

// Function copied from docdown/lib/entry that is not exported.
function getMultilineValue(string, tagName) {
var prelude = tagName == 'description' ? '^ */\\*\\*(?: *\\n *\\* *)?' : ('^ *\\*[\\t ]*@' + _.escapeRegExp(tagName) + '\\b'),
postlude = '(?=\\*\\s+\\@[a-z]|\\*/)',
result = _.result(RegExp(prelude + '([\\s\\S]*?)' + postlude, 'gm').exec(string), 1, '');

return _.trim(result.replace(RegExp('(?:^|\\n)[\\t ]*\\*[\\t ]' + (tagName == 'example' ? '?' : '*'), 'g'), '\n'));
}

/**
* Extracts the entry's `name` data.
* Sub-part of Entry.prototype.getCall() that fetches the name. Using `Entry.prototype.getCall()`
* makes a call to getParams(), which itself call getBaseName --> infinite recursion.
*
* @param {Object} entry Entry whose name to extract.
* @returns {string} The entry's `name` data.
*/
function getBaseName(entry) {
var result = /\*\/\s*(?:function\s+([^(]*)|(.*?)(?=[:=,]))/.exec(entry);
if (result) {
result = (result[1] || result[2]).split('.').pop();
result = _.trim(_.trim(result), "'").split('var ').pop();
result = _.trim(result);
}
// Get the function name.
return _.result(/\*[\t ]*@name\s+(.+)/.exec(entry), 1, result || '');
}

/**
* Reorders `params` for a given function definition/call.
*
* @param {Object} mapping Mapping object that defines if and how the `params` will be reordered.
* @param {String} name Name of the function associated to the call/function definition.
* @param {*[]} params Parameters/arguments to reorder.
* @returns {*[]} Reordered parameters/arguments.
*/
function reorderParams(mapping, name, params) {
// Check if reordering is needed.
if (!mapping || mapping.skipRearg[name]) {
return params;
}
var reargOrder = mapping.methodRearg[name] || mapping.aryRearg[params.length];
if (!reargOrder) {
return params;
}
// Reorder params.
var newParams = [];
reargOrder.forEach(function(newPosition, index) {
newParams[newPosition] = params[index];
});
return newParams;
}

/**
* Returns a function that extracts the entry's `param` data, reordered according to `mapping`.
*
* @param {Object} mapping Mapping object that defines if and how the `params` will be reordered.
* @returns {Function} Function that returns the entry's `param` data.
*/
function getReorderedParams(mapping) {
return function(index) {
if (!this._params) {
// Call baseGetParams in order to compute `this._params`.
baseGetParams.call(this);
// Reorder params according to the `mapping`.
this._params = reorderParams(mapping, getBaseName(this.entry), this._params);
}
return baseGetParams.call(this, index);
};
}

/**
* Updates a code sample so that the arguments in the call are reordered according to `mapping`.
*
* @param {Object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {string} codeSample Code sample to update.
* @returns {string} Updated code sample.
*/
function reorderParamsInExample(mapping, codeSample) {
return j(codeSample)
.find(j.CallExpression, { callee: { object: {name: '_' }}})
.replaceWith(function(callExpr) {
var value = callExpr.value;
return j.callExpression(
value.callee,
reorderParams(mapping, value.callee.property.name, value.arguments)
);
})
.toSource();
}

/**
* Returns a function that extracts the entry's `example` data,
* where function call arguments are reordered according to `mapping`.
*
* @param {Object} mapping Mapping object that defines if and how the `params` will be reordered.
* @returns {Function} Function that returns the entry's `example` data.
*/
function getReorderedExample(mapping) {
return function() {
var result = getMultilineValue(this.entry, 'example');
if (!result) {
return result;
}
var resultReordered = reorderParamsInExample(mapping, result);
return '```' + this.lang + '\n' + resultReordered + '\n```';
};
}

/**
* Updates `docdown` `Entry`'s prototype so that parameters/arguments are reordered according to `mapping`.
*/
module.exports = function applyFPMapping(mapping) {
Entry.prototype.getParams = getReorderedParams(mapping);
Entry.prototype.getExample = getReorderedExample(mapping);
};
10 changes: 8 additions & 2 deletions lib/doc/build.js
Expand Up @@ -5,6 +5,9 @@ var _ = require('lodash'),
fs = require('fs-extra'),
path = require('path');

var mapping = require('../../fp/_mapping'),
applyFPMapping = require('./apply-fp-mapping');

var basePath = path.join(__dirname, '..', '..'),
docPath = path.join(basePath, 'doc'),
readmePath = path.join(docPath, 'README.md');
Expand Down Expand Up @@ -45,11 +48,14 @@ function onComplete(error) {
}
}

function build(type) {
function build(fpFlag, type) {
if (fpFlag) {
applyFPMapping(mapping);
}
var options = _.defaults({}, config.base, config[type]),
markdown = docdown(options);

fs.writeFile(readmePath, postprocess(markdown), onComplete);
}

build(_.last(process.argv));
build(_.includes(process.argv, '--fp'), _.last(process.argv));
3 changes: 3 additions & 0 deletions package.json
Expand Up @@ -16,6 +16,7 @@
"glob": "^6.0.4",
"istanbul": "0.4.2",
"jquery": "^2.2.0",
"jscodeshift": "^0.3.13",
"jscs": "^2.9.0",
"lodash": "^3.10.1",
"platform": "^1.3.1",
Expand All @@ -34,6 +35,8 @@
"build:main": "node lib/main/build-dist.js",
"build:main-modules": "node lib/main/build-modules.js",
"doc": "node lib/doc/build github",
"doc:fp": "node lib/doc/build --fp github",
"doc:fp:site": "node lib/doc/build --fp site",
"doc:site": "node lib/doc/build site",
"pretest": "npm run build",
"style": "npm run style:main & npm run style:fp & npm run style:perf & npm run style:test",
Expand Down

0 comments on commit 1a9bcd0

Please sign in to comment.