Socket
Socket
Sign inDemoInstall

remark-usage

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

remark-usage - npm Package Compare versions

Comparing version 4.0.0 to 4.0.1

LICENSE

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 @@ ```

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc