remark-usage
Advanced tools
Comparing version 4.0.0 to 4.0.1
541
index.js
@@ -11,11 +11,5 @@ /** | ||
/* eslint-env node */ | ||
/* | ||
* Dependencies. | ||
*/ | ||
/* Dependencies. */ | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var remark = require('remark'); | ||
var uncached = require('require-uncached'); | ||
@@ -27,6 +21,6 @@ var heading = require('mdast-util-heading-range'); | ||
/* | ||
* Methods. | ||
*/ | ||
/* Expose `attacher`. */ | ||
module.exports = attacher; | ||
/* Methods. */ | ||
var exists = fs.existsSync; | ||
@@ -38,18 +32,12 @@ var read = fs.readFileSync; | ||
/* | ||
* List of locations to look for an example. | ||
*/ | ||
/* List of locations to look for an example. */ | ||
var EXAMPLES = [ | ||
'docs/example.js', | ||
'doc/example.js', | ||
'examples', | ||
'example', | ||
'example.js' | ||
'docs/example.js', | ||
'doc/example.js', | ||
'examples', | ||
'example', | ||
'example.js' | ||
]; | ||
/* | ||
* Expressions. | ||
*/ | ||
/* Expressions. */ | ||
var EXPRESSION_LOG = /(console\.log\()(.+)(\);?)/g; | ||
@@ -59,206 +47,150 @@ var EXPRESSION_REQUIRE = /(require\()(.+)(\);?)/g; | ||
/* | ||
* Constants. | ||
*/ | ||
/* Constants. */ | ||
var DEFAULT_HEADING = 'usage'; | ||
/** | ||
* Transform a string into an applicable expression. | ||
* Post-process the example document. | ||
* | ||
* @param {string} value - Content to expressionise. | ||
* @return {RegExp} - Expression from `value`. | ||
*/ | ||
function toExpression(value) { | ||
return new RegExp('^(' + value + ')$', 'i'); | ||
} | ||
/** | ||
* Preprocess `value` to add IDs to | ||
* `console.log` invocations. | ||
* | ||
* @param {string} value - Content to process. | ||
* @return {string} - Preprocessed `value`. | ||
* @param {Object} logs - List of logs. | ||
* @param {Object} options - Configuration. | ||
* @return {Array.<Node>} - List of mdast nodes. | ||
*/ | ||
function preprocess(value) { | ||
var index = 0; | ||
function postprocess(value, logs, options, processor) { | ||
var tokens = []; | ||
var start = 0; | ||
var match; | ||
var content; | ||
var info; | ||
var parameters; | ||
var end; | ||
var markdown; | ||
value = value.replace(EXPRESSION_LOG, function ($0, $1, $2, $3) { | ||
index++; | ||
return $1 + '"remark-usage-' + index + '",' + $2 + $3; | ||
}); | ||
EXPRESSION_LOG.lastIndex = 0; | ||
return value; | ||
} | ||
while (match = EXPRESSION_LOG.exec(value)) { | ||
end = EXPRESSION_LOG.lastIndex; | ||
/** | ||
* Transform a script into an intermediate nodes, | ||
* removes the IDs from `console.log` invocations, | ||
* and resolves the main `require` call. | ||
* | ||
* @param {string} source - Scripts source. | ||
* @param {Object} options - Configuration. | ||
* @return {Array.<Object>} - List of tokens. | ||
*/ | ||
function script(source, options) { | ||
var tokens; | ||
content = value.slice(start, end - match[0].length); | ||
/* | ||
* Make sure the require to the main module | ||
* is showed as if it was a require from | ||
* `./node_modules`. | ||
* | ||
* For example, when the example file | ||
* (`test/example.js`) requires the main file (as | ||
* listed in `test/package.json`, `main: "module.js"`) | ||
* as `./module`, it is replaced with `test`. | ||
*/ | ||
parameters = match[2].split(/\s*,\s*/); | ||
source = source.replace(EXPRESSION_REQUIRE, function ($0, $1, $2, $3) { | ||
var filepath = resolve(options.example, '../', unquote($2)); | ||
var quote; | ||
info = parameters[0]; | ||
info = unquote(info.trim()); | ||
info = logs[info]; | ||
if (options.main === filepath && options.name) { | ||
/* | ||
* Honour quote style. | ||
*/ | ||
if (info && info.value) { | ||
tokens = tokens.concat(script(content, options), log(info)); | ||
} else { | ||
parameters = parameters.slice(1).join(', '); | ||
quote = $2.charAt(0); | ||
tokens = tokens.concat(script( | ||
content + match[1] + parameters + match[3], options | ||
)); | ||
} | ||
return $1 + quote + options.name + quote + $3; | ||
} | ||
start = end; | ||
} | ||
return $0; | ||
}); | ||
if (start < value.length) { | ||
tokens = tokens.concat(script(value.slice(start))); | ||
} | ||
/* | ||
* Transform comments into markdown: | ||
*/ | ||
markdown = []; | ||
tokens = []; | ||
tokens.forEach(function (token) { | ||
var prev; | ||
var lang; | ||
source.split('\n').forEach(function (line) { | ||
var match = line.match(EXPRESSION_COMMENT); | ||
if (token.type === 'markdown') { | ||
markdown = markdown.concat(parse(token.value, processor)); | ||
} else { | ||
prev = markdown[markdown.length - 1]; | ||
lang = 'lang' in token ? token.lang : token.type; | ||
tokens.push({ | ||
'type': match ? 'markdown' : 'javascript', | ||
'value': match ? match[4] : line | ||
if (prev && prev.type === 'code' && prev.lang === lang) { | ||
prev.value += token.value ? '\n' + token.value : ''; | ||
} else { | ||
markdown.push({ | ||
type: 'code', | ||
lang: lang, | ||
value: token.value | ||
}); | ||
}); | ||
} | ||
} | ||
}); | ||
return tokens; | ||
} | ||
markdown = markdown.filter(function (token) { | ||
if ('value' in token) { | ||
token.value = trimTrailingLines(token.value); | ||
/** | ||
* Transform a log into an mdast `code` node. | ||
* | ||
* @param {Object} info - Code node. | ||
* @return {Node} - mdast node. | ||
*/ | ||
function log(info) { | ||
return { | ||
'type': 'code', | ||
'lang': info.lang, | ||
'value': info.value | ||
}; | ||
} | ||
return token.value !== ''; | ||
} | ||
/** | ||
* Parse markdown into nodes, without positional | ||
* information. | ||
* | ||
* @param {string} value - Value to parse. | ||
* @return {Array.<Node>} - List of mdast nodes. | ||
*/ | ||
function parse(value) { | ||
return remark().parse(value, { | ||
'position': false | ||
}).children; | ||
return true; | ||
}); | ||
return markdown; | ||
} | ||
/** | ||
* Post-process the example document. | ||
* Adds an npm version badge to the main heading, | ||
* when available. | ||
* | ||
* @param {string} value - Content to process. | ||
* @param {Object} logs - List of logs. | ||
* @param {Object} options - Configuration. | ||
* @return {Array.<Node>} - List of mdast nodes. | ||
* @param {Unified} processor - Instance | ||
* @param {Object?} options - Configuration. | ||
*/ | ||
function postprocess(value, logs, options) { | ||
var tokens = []; | ||
var start = 0; | ||
var match; | ||
var content; | ||
var info; | ||
var parameters; | ||
var end; | ||
var markdown; | ||
function attacher(processor, options) { | ||
var settings = {}; | ||
var pack; | ||
var main; | ||
var example; | ||
var name; | ||
var cwd; | ||
var header; | ||
EXPRESSION_LOG.lastIndex = 0; | ||
if (!options) { | ||
options = {}; | ||
} | ||
/* eslint-disable no-cond-assign */ | ||
while (match = EXPRESSION_LOG.exec(value)) { | ||
end = EXPRESSION_LOG.lastIndex; | ||
cwd = options.cwd || process.cwd(); | ||
content = value.slice(start, end - match[0].length); | ||
try { | ||
pack = require(resolve(cwd, 'package.json')); | ||
} catch (err) { | ||
pack = {}; | ||
} | ||
parameters = match[2].split(/\s*,\s*/); | ||
name = options.name || pack.name || null; | ||
info = parameters[0]; | ||
info = unquote(info.trim()); | ||
info = logs[info]; | ||
main = options.main; | ||
main = main ? require.resolve(resolve(cwd, main)) : resolve(cwd, pack.main || 'index.js'); | ||
if (info && info.value) { | ||
tokens = tokens.concat(script(content, options), log(info)); | ||
} else { | ||
parameters = parameters.slice(1).join(', '); | ||
example = options.example; | ||
tokens = tokens.concat(script( | ||
content + match[1] + parameters + match[3], options | ||
)); | ||
} | ||
if (example) { | ||
example = require.resolve(resolve(cwd, example)); | ||
} else { | ||
EXAMPLES.some(function (filepath) { | ||
filepath = resolve(cwd, filepath); | ||
start = end; | ||
} | ||
/* eslint-enable no-cond-assign */ | ||
if (exists(filepath)) { | ||
example = require.resolve(filepath); | ||
return true; | ||
} | ||
if (start < value.length) { | ||
tokens = tokens.concat(script(value.slice(start))); | ||
} | ||
markdown = []; | ||
tokens.forEach(function (token) { | ||
var prev; | ||
var lang; | ||
if (token.type === 'markdown') { | ||
markdown = markdown.concat(parse(token.value)); | ||
} else { | ||
prev = markdown[markdown.length - 1]; | ||
lang = 'lang' in token ? token.lang : token.type; | ||
if (prev && prev.type === 'code' && prev.lang === lang) { | ||
prev.value += token.value ? '\n' + token.value : ''; | ||
} else { | ||
markdown.push({ | ||
'type': 'code', | ||
'lang': lang, | ||
'value': token.value | ||
}); | ||
} | ||
} | ||
return false; | ||
}); | ||
} | ||
markdown = markdown.filter(function (token) { | ||
if ('value' in token) { | ||
token.value = trimTrailingLines(token.value); | ||
settings.cwd = cwd; | ||
settings.name = name; | ||
settings.main = main; | ||
settings.example = example; | ||
return token.value !== ''; | ||
} | ||
header = toExpression(options.heading || DEFAULT_HEADING); | ||
return true; | ||
}); | ||
return markdown; | ||
return function (tree) { | ||
heading(tree, header, runFactory(settings, processor)); | ||
}; | ||
} | ||
@@ -272,156 +204,147 @@ | ||
*/ | ||
function runFactory(options) { | ||
/** | ||
* Adds an example section based on a valid example | ||
* JavaScript document to a `Usage` section. | ||
* | ||
* @param {Node} start - Starting heading. | ||
* @param {Array.<Node>} nodes - Content. | ||
* @param {Node} end - Ending heading. | ||
*/ | ||
return function (start, nodes, end) { | ||
var logs = {}; | ||
var example; | ||
var source; | ||
var tmp; | ||
var stop; | ||
function runFactory(options, processor) { | ||
/** | ||
* Adds an example section based on a valid example | ||
* JavaScript document to a `Usage` section. | ||
* | ||
* @param {Node} start - Starting heading. | ||
* @param {Array.<Node>} nodes - Content. | ||
* @param {Node} end - Ending heading. | ||
*/ | ||
return function (start, nodes, end) { | ||
var logs = {}; | ||
var example; | ||
var source; | ||
var tmp; | ||
var stop; | ||
example = options.example; | ||
example = options.example; | ||
if (!exists(example)) { | ||
throw new Error( | ||
'Missing example: `' + example + '`. ' + | ||
'Pass an `example` or use a file at: ' + | ||
EXAMPLES.join(', ') | ||
); | ||
} | ||
if (!exists(example)) { | ||
throw new Error( | ||
'Missing example: `' + example + '`. ' + | ||
'Pass an `example` or use a file at: ' + | ||
EXAMPLES.join(', ') | ||
); | ||
} | ||
tmp = example + '-tmp'; | ||
tmp = example + '-tmp'; | ||
source = preprocess(read(example, 'utf-8')); | ||
source = preprocess(read(example, 'utf-8')); | ||
write(tmp, source, 'utf-8'); | ||
write(tmp, source, 'utf-8'); | ||
/* | ||
* TODO: better tmp file management. | ||
*/ | ||
/* to do: better tmp file management. */ | ||
stop = cept(console, 'log', function (id, lang, value) { | ||
if (!value) { | ||
value = lang; | ||
lang = null; | ||
} | ||
stop = cept(console, 'log', function (id, lang, value) { | ||
if (!value) { | ||
value = lang; | ||
lang = null; | ||
} | ||
if (typeof value === 'string' && typeof id === 'string') { | ||
logs[id] = {id: id, lang: lang, value: value}; | ||
} | ||
}); | ||
if (typeof value === 'string' && typeof id === 'string') { | ||
logs[id] = { | ||
'id': id, | ||
'lang': lang, | ||
'value': value | ||
}; | ||
} | ||
}); | ||
try { | ||
uncached(tmp); | ||
} catch (err) { | ||
err.message = | ||
'Invalid example `' + example + '`. ' + | ||
'Ensure example is a valid JavaScript file:\n\n' + | ||
err.message; | ||
try { | ||
uncached(tmp); | ||
} catch (exception) { | ||
exception.message = | ||
'Invalid example `' + example + '`. ' + | ||
'Ensure example is a valid JavaScript file:\n\n' + | ||
exception.message; | ||
throw err; | ||
} finally { | ||
stop(); | ||
throw exception; | ||
} finally { | ||
stop(); | ||
/* istanbul ignore next */ | ||
if (exists(tmp)) { | ||
remove(tmp); | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
if (exists(tmp)) { | ||
remove(tmp); | ||
} | ||
} | ||
/* | ||
* Add markdown. | ||
*/ | ||
return [start].concat(postprocess(source, logs, options), end); | ||
}; | ||
/* Add markdown. */ | ||
return [start].concat( | ||
postprocess(source, logs, options, processor), | ||
end | ||
); | ||
}; | ||
} | ||
/** | ||
* Adds an npm version badge to the main heading, | ||
* when available. | ||
* Transform a script into an intermediate nodes, | ||
* removes the IDs from `console.log` invocations, | ||
* and resolves the main `require` call. | ||
* | ||
* @param {Remark} remark - Instance | ||
* @param {Object?} options - Configuration. | ||
* @param {string} source - Scripts source. | ||
* @param {Object} options - Configuration. | ||
* @return {Array.<Object>} - List of tokens. | ||
*/ | ||
function attacher(remark, options) { | ||
var settings = {}; | ||
var pack; | ||
var main; | ||
var example; | ||
var name; | ||
var cwd; | ||
var header; | ||
function script(source, options) { | ||
var tokens; | ||
if (options === null || options === undefined) { | ||
options = {}; | ||
} | ||
/* Make sure the require to the main module | ||
* is showed as if it was a require from | ||
* `./node_modules`. | ||
* | ||
* For example, when the example file | ||
* (`test/example.js`) requires the main file (as | ||
* listed in `test/package.json`, `main: "module.js"`) | ||
* as `./module`, it is replaced with `test`. */ | ||
source = source.replace(EXPRESSION_REQUIRE, function ($0, $1, $2, $3) { | ||
var filepath = resolve(options.example, '../', unquote($2)); | ||
var quote; | ||
cwd = options.cwd; | ||
if (options.main === filepath && options.name) { | ||
/* Honour quote style. */ | ||
quote = $2.charAt(0); | ||
if (cwd === null || cwd === undefined) { | ||
cwd = process.cwd(); | ||
return $1 + quote + options.name + quote + $3; | ||
} | ||
try { | ||
pack = require(resolve(cwd, 'package.json')); | ||
} catch (exception) { | ||
pack = {}; | ||
} | ||
return $0; | ||
}); | ||
name = options.name; | ||
/* Transform comments into markdown: */ | ||
tokens = []; | ||
if (name === null || name === undefined) { | ||
name = pack.name || null; | ||
} | ||
source.split('\n').forEach(function (line) { | ||
var match = line.match(EXPRESSION_COMMENT); | ||
main = options.main; | ||
tokens.push({ | ||
type: match ? 'markdown' : 'javascript', | ||
value: match ? match[4] : line | ||
}); | ||
}); | ||
if (main === null || main === undefined) { | ||
main = resolve(cwd, pack.main || 'index.js'); | ||
} else { | ||
main = require.resolve(resolve(cwd, main)); | ||
} | ||
return tokens; | ||
} | ||
example = options.example; | ||
/* Preprocess `value` to add IDs to `console.log` invocations. */ | ||
function preprocess(value) { | ||
var index = 0; | ||
if (example === null || example === undefined) { | ||
EXAMPLES.some(function (filepath) { | ||
filepath = resolve(cwd, filepath); | ||
value = value.replace(EXPRESSION_LOG, function ($0, $1, $2, $3) { | ||
index++; | ||
return $1 + '"remark-usage-' + index + '",' + $2 + $3; | ||
}); | ||
if (exists(filepath)) { | ||
example = require.resolve(filepath); | ||
return true; | ||
} | ||
}); | ||
} else { | ||
example = require.resolve(resolve(cwd, example)); | ||
} | ||
return value; | ||
} | ||
settings.cwd = cwd; | ||
settings.name = name; | ||
settings.main = main; | ||
settings.example = example; | ||
/* Parse markdown into nodes, without positional | ||
* information. */ | ||
function parse(value, processor) { | ||
return processor.parse(value, {position: false}).children; | ||
} | ||
header = toExpression(options.heading || DEFAULT_HEADING); | ||
/* Transform a log into an mdast `code` node. */ | ||
function log(info) { | ||
return {type: 'code', lang: info.lang, value: info.value}; | ||
} | ||
return function (tree) { | ||
heading(tree, header, runFactory(settings)); | ||
}; | ||
/* Transform a string into an applicable expression. */ | ||
function toExpression(value) { | ||
return new RegExp('^(' + value + ')$', 'i'); | ||
} | ||
/* | ||
* Expose `attacher`. | ||
*/ | ||
module.exports = attacher; |
{ | ||
"name": "remark-usage", | ||
"version": "4.0.0", | ||
"version": "4.0.1", | ||
"description": "Add a usage example to your README", | ||
@@ -12,6 +12,3 @@ "license": "MIT", | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/wooorm/remark-usage.git" | ||
}, | ||
"repository": "https://github.com/wooorm/remark-usage", | ||
"bugs": "https://github.com/wooorm/remark-usage/issues", | ||
@@ -27,3 +24,2 @@ "author": "Titus Wormer <tituswormer@gmail.com> (http://wooorm.com)", | ||
"cept": "^1.0.0", | ||
"remark": "^5.0.0", | ||
"mdast-util-heading-range": "^2.0.0", | ||
@@ -35,24 +31,45 @@ "require-uncached": "^1.0.2", | ||
"devDependencies": { | ||
"eslint": "^2.0.0", | ||
"istanbul": "^0.4.0", | ||
"jscs": "^3.0.0", | ||
"jscs-jsdoc": "^2.0.0", | ||
"remark-cli": "^1.0.0", | ||
"remark-comment-config": "^4.0.0", | ||
"remark-github": "^5.0.0", | ||
"remark-lint": "^4.0.0", | ||
"remark-slug": "^4.1.1", | ||
"remark-validate-links": "^4.0.0", | ||
"tape": "^4.0.0" | ||
"is-hidden": "^1.0.1", | ||
"negate": "^1.0.0", | ||
"nyc": "^8.1.0", | ||
"remark": "^6.0.0", | ||
"remark-cli": "^2.0.0", | ||
"remark-preset-wooorm": "^1.0.0", | ||
"tape": "^4.0.0", | ||
"xo": "^0.16.0" | ||
}, | ||
"scripts": { | ||
"build-md": "remark . --quiet --frail", | ||
"build-md": "remark *.md --quiet --frail", | ||
"build": "npm run build-md", | ||
"lint-api": "eslint .", | ||
"lint-style": "jscs --reporter inline .", | ||
"lint": "npm run lint-api && npm run lint-style", | ||
"test-api": "node test/index.js", | ||
"test-coverage": "istanbul cover test/index.js", | ||
"lint": "xo", | ||
"test-api": "node test", | ||
"test-coverage": "nyc --reporter lcov tape test/index.js", | ||
"test": "npm run build && npm run lint && npm run test-coverage" | ||
}, | ||
"nyc": { | ||
"check-coverage": true, | ||
"lines": 100, | ||
"functions": 100, | ||
"branches": 100 | ||
}, | ||
"xo": { | ||
"space": true, | ||
"rules": { | ||
"max-lines": "off", | ||
"no-cond-assign": "off" | ||
}, | ||
"ignore": [ | ||
"example.js" | ||
] | ||
}, | ||
"remarkConfig": { | ||
"output": true, | ||
"presets": "wooorm", | ||
"plugins": { | ||
"./": null, | ||
"lint": { | ||
"fenced-code-flag": false | ||
} | ||
} | ||
} | ||
} |
# remark-usage [![Build Status][build-badge]][build-status] [![Coverage Status][coverage-badge]][coverage-status] [![Chat][chat-badge]][chat] | ||
<!--lint disable heading-increment list-item-spacing--> | ||
Add a [usage][] example to a README with [**remark**][remark]. | ||
@@ -15,4 +13,2 @@ | ||
<!--lint disable code-block-style--> | ||
## Usage | ||
@@ -40,3 +36,3 @@ | ||
```markdown | ||
Add a [usage][] example to a README with [**remark**][remark]. | ||
## Installation | ||
``` | ||
@@ -46,3 +42,5 @@ | ||
## Installation | ||
``` | ||
[npm][]: | ||
``` | ||
@@ -53,3 +51,3 @@ Log something which is never captured: | ||
function neverCalled() { | ||
console.log('javascript', 'alert("test")'); | ||
console.log('javascript', 'alert("test")'); | ||
} | ||
@@ -56,0 +54,0 @@ ``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5
8
13870
280
127
6
1
- Removedremark@^5.0.0
- Removedbail@1.0.5(transitive)
- Removedccount@1.1.0(transitive)
- Removedcharacter-entities@1.2.4(transitive)
- Removedcharacter-entities-html4@1.1.4(transitive)
- Removedcharacter-entities-legacy@1.1.4(transitive)
- Removedcharacter-reference-invalid@1.1.4(transitive)
- Removedcollapse-white-space@1.0.6(transitive)
- Removedextend@3.0.2(transitive)
- Removedhas@1.0.4(transitive)
- Removedinherits@2.0.4(transitive)
- Removedis-alphabetical@1.0.4(transitive)
- Removedis-alphanumerical@1.0.4(transitive)
- Removedis-decimal@1.0.4(transitive)
- Removedis-hexadecimal@1.0.4(transitive)
- Removedlongest-streak@1.0.0(transitive)
- Removedmarkdown-table@0.4.0(transitive)
- Removedonce@1.4.0(transitive)
- Removedparse-entities@1.2.2(transitive)
- Removedremark@5.1.0(transitive)
- Removedremark-parse@1.1.0(transitive)
- Removedremark-stringify@1.1.0(transitive)
- Removedrepeat-string@1.6.1(transitive)
- Removedstringify-entities@1.3.2(transitive)
- Removedtrim@0.0.1(transitive)
- Removedtrough@1.0.5(transitive)
- Removedunherit@1.1.3(transitive)
- Removedunified@4.2.1(transitive)
- Removedunist-util-is@3.0.0(transitive)
- Removedunist-util-remove-position@1.1.4(transitive)
- Removedunist-util-visit@1.4.1(transitive)
- Removedunist-util-visit-parents@2.1.2(transitive)
- Removedvfile@1.4.0(transitive)
- Removedvfile-location@2.0.6(transitive)
- Removedwrappy@1.0.2(transitive)
- Removedxtend@4.0.2(transitive)