Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

retext

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

retext - npm Package Compare versions

Comparing version 0.2.0-rc.1 to 0.2.0-rc.2

51

benchmark/index.js
'use strict';
var Retext, sentence, paragraph, section, article;
var Retext,
sentence,
paragraph,
section,
article;
/**
* Module dependencies (retext).
*/
Retext = require('..');
/* Test data */
/**
* Test data.
*
* This includes:
*
* - An average sentence (w/ 20 words);
* - An average paragraph (w/ 5 sentences);
* - A (big?) section (w/ 10 paragraphs);
* - A (big?) article (w/ 10 sections);
*
* Source:
* http://www.gutenberg.org/files/10745/10745-h/10745-h.htm
*/
/* Source: http://www.gutenberg.org/files/10745/10745-h/10745-h.htm */
/* A sentence, 20 words. */
sentence = 'Where she had stood was clear, and she was gone since Sir ' +
'Kay does not choose to assume my quarrel.';
/* A paragraph, 5 sentences, 100 words. */
paragraph = 'Thou art a churlish knight to so affront a lady ' +

@@ -26,14 +42,21 @@ 'he could not sit upon his horse any longer. ' +

/* A section, 10 paragraphs, 50 sentences, 1,000 words. */
section = paragraph + Array(10).join('\n\n' + paragraph);
/* An article, 100 paragraphs, 500 sentences, 10,000 words. */
article = section + Array(10).join('\n\n' + section);
/* Benchmarks */
/**
* Benchmark suite.
*/
suite('retext.parse(source);', function () {
var retext = new Retext();
var retext;
retext = new Retext();
set('mintime', 100);
/**
* Benchmark a paragraph.
*/
bench('A paragraph (5 sentences, 100 words)', function () {

@@ -43,2 +66,6 @@ retext.parse(paragraph);

/**
* Benchmark a section.
*/
bench('A section (10 paragraphs, 50 sentences, 1,000 words)',

@@ -50,2 +77,6 @@ function () {

/**
* Benchmark an article.
*/
bench('An article (100 paragraphs, 500 sentences, 10,000 words)',

@@ -52,0 +83,0 @@ function () {

2

component.json

@@ -5,3 +5,3 @@ {

"description": "Extensible system for analysing and manipulating natural language",
"version": "0.2.0-rc.1",
"version": "0.2.0-rc.2",
"keywords": [

@@ -8,0 +8,0 @@ "natural",

0.2.0-rc.2 / 2014-09-21
==================
* Merge branch 'feature/rename-apply-plugins-to-run'
* Rename `applyPlugins` > `run`
* Merge branch 'refactor/api'
* Refactor API
* Merge branch 'feature/fail-without-callback'
* Add interface for error on omitted `done` for `parse`
* Add spec for error on omitted `done` for `parse`
* Merge branch 'feature/chainable-parse'
* Add chainable `parse` and `applyPlugins`
* Add spec for chainable `parse` and `applyPlugins`
* Fix throwing interdependent plugins
* Add spec for throwing interdependent plugins
* Refactor spec
* Refactor benchmark
* Update benchmark results in docs
* Update docs for async changes in 27dbfd7
* Remove flashy demos from docs
* Update and fix Installation in docs
* Remove sauce labs from travis
* Merge branch 'feature/async'
0.2.0-rc.1 / 2014-09-19

@@ -3,0 +27,0 @@ ==================

'use strict';
var TextOMConstructor = require('textom'),
ParseLatin = require('parse-latin'),
Ware = require('ware');
var TextOMConstructor,
ParseLatin,
Ware,
has;
function fromAST(TextOM, ast) {
var iterator = -1,
children, node, data, attribute;
/**
* Module dependencies.
*/
node = new TextOM[ast.type]();
TextOMConstructor = require('textom');
ParseLatin = require('parse-latin');
Ware = require('ware');
if ('children' in ast) {
iterator = -1;
children = ast.children;
/**
* Cached, fast, secure existence test.
*/
while (children[++iterator]) {
node.append(fromAST(TextOM, children[iterator]));
has = Object.prototype.hasOwnProperty;
/**
* Transform a concrete syntax tree into a tree constructed
* from a given object model.
*
* @param {Object} TextOM - the object model.
* @param {Object} cst - the concrete syntax tree to
* transform.
* @return {Node} the node constructed from the
* CST and the object model.
*/
function fromCST(TextOM, cst) {
var index,
node,
children,
data,
attribute;
node = new TextOM[cst.type]();
if ('children' in cst) {
index = -1;
children = cst.children;
while (children[++index]) {
node.append(fromCST(TextOM, children[index]));
}
} else {
node.fromString(ast.value);
node.fromString(cst.value);
}
/**
* Currently, `data` properties are not really
* specified or documented. Therefore, the following
* branch is ignored by Istanbul.
*
* The idea is that plugins and parsers can each
* attach data to nodes, in a similar fashion to the
* DOMs dataset, which can be stringified and parsed
* back and forth between the concrete syntax tree
* and the node.
*/
/* istanbul ignore if: TODO, Untestable, will change soon. */
if ('data' in ast) {
data = ast.data;
if ('data' in cst) {
data = cst.data;
for (attribute in data) {
if (data.hasOwnProperty(attribute)) {
if (has.call(data, attribute)) {
node.data[attribute] = data[attribute];

@@ -39,11 +80,12 @@ }

/**
* Define `Retext`. Exported above, and used to instantiate a new
* `Retext`.
* Construct an instance of `Retext`.
*
* @param {Function?} parser - the parser to use. Defaults to parse-latin.
* @public
* @param {Function?} parser - the parser to use. Defaults
* to a new instance of `parse-latin`.
* @constructor
*/
function Retext(parser) {
var self = this;
var self,
TextOM;

@@ -54,40 +96,62 @@ if (!parser) {

self = this;
TextOM = new TextOMConstructor();
self.ware = new Ware();
self.parser = parser;
self.TextOM = parser.TextOM = new TextOMConstructor();
self.TextOM.parser = parser;
self.TextOM = TextOM;
/**
* Expose `TextOM` on `parser`, and vice versa.
*/
parser.TextOM = TextOM;
TextOM.parser = parser;
}
/**
* `Retext#use` takes a plugin-a humble function-and when the parse
* method of the Retext instance is called, the plugin will be called
* with the parsed tree, and the retext instance as arguments.
* Attaches `plugin`: a humble function.
*
* Note that, during the parsing stage, when the `use` method is called
* by a plugin, the nested plugin is immediately called, before continuing
* on with its parent plugin.
* When `parse` or `run` is invoked, `plugin` is
* invoked with `node` and a `retext` instance.
*
* @param {Function} plugin - the plugin to call when parsing.
* @param {Function?} plugin.attach - called only once with a Retext
* instance. If you're planning on
* modifying TextOM or a parser, do it
* in this method.
* If `plugin` contains asynchronous functionality, it
* should accept a third argument (`next`) and invoke
* it on completion.
*
* `plugin.attach` is invoked with a `retext` instance
* when attached, enabling `plugin` to depend on other
* plugins.
*
* Code to initialize `plugin` should go into its `attach`
* method, such as functionality to modify the object model
* (TextOM), the parser (e.g., `parse-latin`), or the
* `retext` instance. `plugin.attach` is invoked when
* `plugin` is attached to a `retext` instance.
*
* @param {function(Node, Retext, Function?)} plugin -
* functionality to analyze and manipulate a node.
* @param {function(Retext)} plugin.attach - functionality
* to initialize `plugin`.
* @return this
* @public
*/
Retext.prototype.use = function (plugin) {
var self;
if (typeof plugin !== 'function') {
throw new TypeError('Illegal invocation: \'' + plugin +
'\' is not a valid argument for \'Retext.prototype.use\'');
throw new TypeError(
'Illegal invocation: `' + plugin + '` ' +
'is not a valid argument for `Retext#use(plugin)`'
);
}
var self = this,
ware = self.ware;
self = this;
if (ware.fns.indexOf(plugin) === -1) {
if (self.ware.fns.indexOf(plugin) === -1) {
self.ware.use(plugin);
if (plugin.attach) {
plugin.attach(self);
}
ware.use(plugin);
}

@@ -99,40 +163,71 @@

/**
* `Retext#parse` takes a source to be given (and parsed) by the parser.
* Then, `parse` iterates over all plugins, and allows them to modify the
* TextOM tree created by the parser.
* Transform a given value into a node, applies attached
* plugins to the node, and invokes `done` with either an
* error (first argument) or the transformed node (second
* argument).
*
* @param {String?} source - The source to convert.
* @param {Function<Error, Node>} done - Callback with a RootNode containing
* the tokenized source.
* @public
* @param {string?} value - The value to transform.
* @param {function(Error, Node)} done - Callback to
* invoke when the transformations have completed.
* @return this
*/
Retext.prototype.parse = function (source, done) {
var self = this,
rootNode = fromAST(self.TextOM, self.parser.tokenizeRoot(source));
self.applyPlugins(rootNode, done);
Retext.prototype.parse = function (value, done) {
var self,
cst;
if (typeof done !== 'function') {
throw new TypeError(
'Illegal invocation: `' + done + '` ' +
'is not a valid argument for `Retext#parse(value, done)`.\n' +
'This breaking change occurred in 0.2.0-rc.1, see GitHub for ' +
'more information.'
);
}
self = this;
cst = self.parser.parse(value);
self.run(fromCST(self.TextOM, cst), done);
return self;
};
/**
* `Retext#applyPlugins` applies the plugins bound to the retext instance to a
* given tree.
* Applies attached plugins to `node` and invokes `done`
* with either an error (first argument) or the transformed
* `node` (second argument).
*
* Note that, during the parsing stage, when the `use` plugin is called
* by a plugin, the nested plugin is immediately called, before continuing
* on with its parent plugin.
*
* @param {Node} tree - The tree to apply plugins to.
* @param {Function<Error, Node>} done - Callback with the result of
* parsing the tree.
* @public
* @param {Node} node - The node to apply attached
* plugins to.
* @param {function(Error, Node)} done - Callback to
* invoke when the transformations have completed.
* @return this
*/
Retext.prototype.applyPlugins = function (tree, done) {
var self = this;
self.ware.run(tree, self, done);
Retext.prototype.run = function (node, done) {
var self;
if (typeof done !== 'function') {
throw new TypeError(
'Illegal invocation: `' + done + '` ' +
'is not a valid argument for ' +
'`Retext#run(node, done)`.\n' +
'This breaking change occurred in 0.2.0-rc.1, see GitHub for ' +
'more information.'
);
}
self = this;
self.ware.run(node, self, done);
return self;
};
/**
* Expose `Retext`. Used to instantiate a new Retext object.
* Expose `Retext`.
*/
exports = module.exports = Retext;
module.exports = Retext;
{
"name": "retext",
"version": "0.2.0-rc.1",
"version": "0.2.0-rc.2",
"description": "Extensible system for analysing and manipulating natural language",

@@ -5,0 +5,0 @@ "keywords": [

@@ -23,3 +23,3 @@ # ![Retext logo](http://i58.tinypic.com/5xpx5z.png)

NPM:
npm:
```sh

@@ -29,3 +29,3 @@ $ npm install retext

Component.js:
Component:
```sh

@@ -35,45 +35,77 @@ $ component install wooorm/retext

## Flashy demos
Bower:
```sh
$ bower install retext
```
Most [plugins](https://github.com/wooorm/retext#plugins) have working examples. All available demos are listed under the plugins section, but some of the coolest include:
- [retext-smartypants](http://wooorm.github.io/retext-smartypants/);
- [retext-emoji](http://wooorm.github.io/retext-emoji/);
- [retext-double-metaphone](http://wooorm.github.io/retext-double-metaphone/);
- [retext-search](http://wooorm.github.io/retext-search/);
- [retext-porter-stemmer](http://wooorm.github.io/retext-porter-stemmer/);
## Usage
```js
var Retext = require('retext'),
emoji = require('retext-emoji'),
smartypants = require('retext-smartypants'),
var Retext,
retext,
emoji,
smartypants,
input;
// Modified first paragraph from:
// http://en.wikipedia.org/wiki/Three_wise_monkeys
/**
* Dependencies.
*
* - retext-emoji transforms short-codes into emoji.
* - retext-smartypants transforms dumb quotes and such
* into smart punctuation.
*/
Retext = require('retext');
emoji = require('retext-emoji');
smartypants = require('retext-smartypants');
/**
* The source to analyse and manipulate, a (modified)
* first paragraph from WikiPedia:
* http://en.wikipedia.org/wiki/Three_wise_monkeys
*/
input = 'The three wise monkeys [. . .] sometimes called the ' +
'three mystic apes--are a pictorial maxim. Together ' +
'they embody the proverbial principle to ("see no evil, ' +
'hear no evil, speak no evil"). The three monkeys are ' +
'Mizaru (:see_no_evil:), covering his eyes, who sees no ' +
'evil; Kikazaru (:hear_no_evil:), covering his ears, ' +
'who hears no evil; and Iwazaru (:speak_no_evil:), ' +
'covering his mouth, who speaks no evil.';
'three mystic apes--are a pictorial maxim. Together ' +
'they embody the proverbial principle to ("see no evil, ' +
'hear no evil, speak no evil"). The three monkeys are ' +
'Mizaru (:see_no_evil:), covering his eyes, who sees no ' +
'evil; Kikazaru (:hear_no_evil:), covering his ears, ' +
'who hears no evil; and Iwazaru (:speak_no_evil:), ' +
'covering his mouth, who speaks no evil.';
var text = new Retext()
/**
* Create a retext instance which uses retext-emoji and -smartypants.
*/
retext = new Retext()
.use(emoji({
'convert' : 'encode'
}))
.use(smartypants())
.parse(input)
.toString();
// The three wise monkeys […] sometimes called the three
// mystic apes—are a pictorial maxim. Together they
// embody the proverbial principle to (“see no evil,
// hear no evil, speak no evil”). The three monkeys are
// Mizaru (🙈), covering his eyes, who sees no evil;
// Kikazaru (🙉), covering his ears, who hears no evil;
// and Iwazaru (🙊), covering his mouth, who speaks no evil.
.use(smartypants());
retext.parse(input, function (err, tree) {
/**
* Handle errors.
*/
if (err) {
throw err;
}
/**
* Log the text content of the tree (the transformed input).
*
* This logs the following:
* The three wise monkeys […] sometimes called the three
* mystic apes—are a pictorial maxim. Together they
* embody the proverbial principle to (“see no evil,
* hear no evil, speak no evil”). The three monkeys are
* Mizaru (🙈), covering his eyes, who sees no evil;
* Kikazaru (🙉), covering his ears, who hears no evil;
* and Iwazaru (🙊), covering his mouth, who speaks no evil.
*/
console.log(tree.toString());
});
```

@@ -87,9 +119,28 @@

```js
var Retext = require('retext'),
ParseEnglish = require('parse-english');
var Retext,
ParseEnglish,
retext;
var retext = new Retext(new ParseEnglish()).parse(/* ...some english... */);
/**
* parse-english works better on English input.
*/
Retext = require('./');
ParseEnglish = require('parse-english');
/**
* Create a retext instance which uses an instance
* of parse-english.
*/
retext = new Retext(new ParseEnglish());
/**
* There, ol' chap.
*/
retext.parse(/* ...some English... */, function (err, tree) {/* ... */});
```
Return a new `Retext` instance with the given parser (defaults to parse-latin).
Return a new `Retext` instance with the given [parser](#parsers) (defaults to an instance of parse-latin).

@@ -100,5 +151,5 @@ ### Retext.prototype.use(plugin)

### Retext.prototype.parse(source)
### Retext.prototype.parse(source, callback)
Parses the given source and returns the (by `use`d plugins, modified) tree.
Parses the given source and when done passes either an error (the first argument), or the (by `use`d plugins, modified) tree (the second argument) to the callback.

@@ -157,9 +208,9 @@ ## Plugins

On a MacBook Air, it parses about 2 big articles, 24 sections, or 218 paragraphs per second.
On a MacBook Air, it parses about 2 big articles, 22 sections, or 206 paragraphs per second.
```
retext.parse(source);
218 op/s » A paragraph (5 sentences, 100 words)
24 op/s » A section (10 paragraphs, 50 sentences, 1,000 words)
2 op/s » An article (100 paragraphs, 500 sentences, 10,000 words)
206 op/s » A paragraph (5 sentences, 100 words)
22 op/s » A section (10 paragraphs, 50 sentences, 1,000 words)
2 op/s » An article (100 paragraphs, 500 sentences, 10,000 words)
```

@@ -166,0 +217,0 @@

'use strict';
var Retext = require('..'),
assert = require('assert');
var Retext,
assert;
/* istanbul ignore next: noop */
/**
* Module dependencies (retext, assert).
*/
Retext = require('..');
assert = require('assert');
/**
* Cache a (by istanbul ignored) no-operation function.
*/
/* istanbul ignore next */
function noop() {}
describe('Retext()', function () {
it('should be of type `function`', function () {
/**
* Test `Retext`.
*/
describe('new Retext()', function () {
it('should be a `function`', function () {
assert(typeof Retext === 'function');
});
it('should return a newly initialized `Retext` object, when invoked ' +
'without arguments', function () {
assert(new Retext() instanceof Retext);
}
);
it('should return a newly initialized `Retext` object', function () {
assert(new Retext(noop) instanceof Retext);
assert(new Retext() instanceof Retext);
});
it('should set the `parser` attribute to `parse-latin`, when invoked ' +
'without arguments', function () {
var retext = new Retext();
assert('parser' in retext);
assert('TextOM' in retext.parser);
}
);
it('should set `parser` to an instance of parse-latin', function () {
var retext;
it('should set the `parser` attribute to the passed in parser, ' +
'when given', function () {
var retext = new Retext(noop);
assert('parser' in retext);
assert(retext.parser === noop);
}
);
retext = new Retext();
it('should create a new context/parser/textom when required, thus ' +
'not requiring from memory', function (done) {
new Retext().parse(null, function (err, rootNode1) {
/* istanbul ignore if: won't error. */
if (err) {
done(err);
}
assert('parser' in retext);
assert('TextOM' in retext.parser);
});
new Retext().parse(null, function (err, rootNode2) {
assert(rootNode1 instanceof rootNode1.constructor);
assert(!(rootNode1 instanceof rootNode2.constructor));
assert(rootNode2 instanceof rootNode2.constructor);
assert(!(rootNode2 instanceof rootNode1.constructor));
/**
* The following sounds a bit weird, but can best be thought of as
* a test for multiple contexts, similar to how different frames on
* the client side use different Array constructors.
*/
done(err);
});
it('should create a new object model', function (done) {
new Retext().parse(null, function (err, tree1) {
/* istanbul ignore if: should not error. */
if (err) {
throw err;
}
new Retext().parse(null, function (err, tree2) {
assert(tree1 instanceof tree1.constructor);
assert(!(tree1 instanceof tree2.constructor));
assert(tree2 instanceof tree2.constructor);
assert(!(tree2 instanceof tree1.constructor));
done(err);
});
}
);
});
});
});
describe('Retext#use', function () {
it('should be of type `function`', function () {
/**
* Test `Retext` when given a parser.
*/
describe('new Retext(parser)', function () {
it('should set `parser` to the given parser', function () {
var retext;
retext = new Retext(noop);
assert('parser' in retext);
assert(retext.parser === noop);
});
});
/**
* Test `Retext#use(plugin)`.
*/
describe('Retext#use(plugin)', function () {
it('should be a `function`', function () {
assert(typeof Retext.prototype.use === 'function');

@@ -64,44 +94,179 @@ assert(typeof (new Retext()).use === 'function');

it('should return self', function () {
var retext = new Retext();
var retext;
retext = new Retext();
assert(retext.use(noop) === retext);
});
it('should throw, when something other than a function was given',
function () {
var retext = new Retext();
it('should throw when not given a function', function () {
var retext;
assert.throws(function () {
retext.use();
}, 'undefined');
retext = new Retext();
assert.throws(function () {
retext.use(null);
}, 'null');
assert.throws(function () {
retext.use();
}, 'undefined');
assert.throws(function () {
retext.use(undefined);
}, 'undefined');
assert.throws(function () {
retext.use(null);
}, 'null');
assert.throws(function () {
retext.use(true);
}, 'true');
assert.throws(function () {
retext.use(undefined);
}, 'undefined');
assert.throws(function () {
retext.use({});
}, 'object Object');
}
);
assert.throws(function () {
retext.use(true);
}, 'true');
it('should attach `use`d plugins', function () {
var retext = new Retext();
assert.throws(function () {
retext.use({});
}, 'object Object');
});
it('should attach a plugin', function () {
var retext;
retext = new Retext();
assert(retext.ware.fns.length === 0);
retext.use(noop);
assert(retext.ware.fns.length === 1);
});
it('should not attach `use`d plugins multiple times', function () {
var retext = new Retext();
it('should invoke `attach` on an attached plugin', function () {
var retext,
isInvoked;
/* istanbul ignore next: noop */
function plugin() {}
retext = new Retext();
plugin.attach = function () {
isInvoked = true;
};
retext.use(plugin);
assert(isInvoked === true);
});
it('should invoke `attach` with `retext`', function (done) {
var retext,
root,
args;
function plugin() {}
retext = new Retext();
root = new retext.TextOM.RootNode();
plugin.attach = function () {
args = arguments;
};
retext.use(plugin);
retext.run(root, function (err) {
assert(args[0] === retext);
assert(args.length === 1);
done(err);
});
});
it('should invoke `attach` on plugins in order', function (done) {
var retext,
isInvoked;
function firstPlugin() {}
function secondPlugin() {}
retext = new Retext();
isInvoked = false;
firstPlugin.attach = function () {
assert(isInvoked === false);
isInvoked = true;
};
secondPlugin.attach = function () {
assert(isInvoked === true);
isInvoked = true;
};
retext
.use(firstPlugin)
.use(secondPlugin)
.parse(null, done);
});
it('should invoke `attach` on dependencies in order', function (done) {
var retext,
invokeCount;
function firstPlugin() {}
function secondPlugin() {}
function thirdPlugin() {}
retext = new Retext();
invokeCount = 0;
thirdPlugin.attach = function () {
assert(invokeCount === 2);
retext
.use(firstPlugin)
.use(secondPlugin);
invokeCount++;
};
secondPlugin.attach = function () {
assert(invokeCount === 1);
invokeCount++;
retext
.use(firstPlugin)
.use(thirdPlugin);
};
firstPlugin.attach = function () {
assert(invokeCount === 0);
invokeCount++;
retext
.use(secondPlugin)
.use(thirdPlugin);
};
retext
.use(firstPlugin)
.use(secondPlugin)
.use(thirdPlugin)
.parse(null, done);
});
it('should not re-attach an attached plugin', function () {
var retext;
retext = new Retext();
retext.use(noop);
assert(retext.ware.fns.length === 1);
retext.use(noop);
assert(retext.ware.fns.length === 1);

@@ -111,4 +276,8 @@ });

describe('Retext#parse', function () {
it('should be of type `function`', function () {
/**
* Test Retext#parse(value, done).
*/
describe('Retext#parse(value, done)', function () {
it('should be a `function`', function () {
assert(typeof Retext.prototype.parse === 'function');

@@ -118,8 +287,44 @@ assert(typeof (new Retext()).parse === 'function');

it('should return an instance of RootNode', function (done) {
var retext = new Retext();
it('should return self', function (done) {
var retext;
retext.parse(null, function (err, rootNode) {
assert(rootNode instanceof retext.parser.TextOM.RootNode);
retext = new Retext();
assert(retext.parse(null, done) === retext);
});
it('should throw when `done` is not a `function`', function () {
var retext;
retext = new Retext();
assert.throws(function () {
retext.parse(null);
}, 'undefined');
assert.throws(function () {
retext.parse(null, null);
}, 'null');
assert.throws(function () {
retext.parse(null, undefined);
}, 'undefined');
assert.throws(function () {
retext.parse(null, true);
}, 'true');
assert.throws(function () {
retext.parse(null, {});
}, 'object Object');
});
it('should invoke `done` with a `RootNode`', function (done) {
var retext;
retext = new Retext();
retext.parse(null, function (err, tree) {
assert(tree instanceof retext.parser.TextOM.RootNode);
done(err);

@@ -129,57 +334,55 @@ });

it('should immediately call the `attach` method on a plugin, when ' +
'`use` is called', function () {
var retext = new Retext(),
isCalled = false;
it('should transform `value` into a `TextOM` object', function (done) {
new Retext().parse('Something something', function (err, root) {
assert('head' in root);
assert('tail' in root);
assert(root.head.parent === root);
assert('TextOM' in root);
assert(root.toString() === 'Something something');
/* istanbul ignore next: noop */
function plugin () {}
done(err);
});
});
plugin.attach = function () {
isCalled = true;
};
it('should not invoke `attach` on an attached plugin', function (done) {
var retext,
isInvoked;
retext.use(plugin);
function plugin() {}
assert(isCalled === true);
}
);
retext = new Retext();
it('should not call the `attach` method, when `parse` is called',
function (done) {
var retext = new Retext(),
isCalled = false;
plugin.attach = function () {
isInvoked = true;
};
function plugin () {}
retext.use(plugin);
plugin.attach = function () {
isCalled = true;
};
assert(isInvoked === true);
retext.use(plugin);
isInvoked = false;
isCalled = false;
retext.parse(null, function (err) {
assert(isInvoked !== true);
retext.parse(null, function (err) {
assert(isCalled === false);
done(err);
});
});
done(err);
});
it('should invoke an attached plugin', function (done) {
var retext,
isInvoked;
function plugin() {
isInvoked = true;
}
);
it('should call `use`d plugins, when `parse` is called', function (done) {
var retext = new Retext(),
isCalled = false;
retext = new Retext();
function plugin () {
isCalled = true;
}
retext.use(plugin);
assert(isCalled === false);
assert(isInvoked !== true);
retext.parse(null, function (err) {
assert(isCalled === true);
assert(isInvoked === true);

@@ -190,11 +393,13 @@ done(err);

it('should call `use`d plugins with an instance of RootNode and ' +
'Retext, when `parse` is called', function (done) {
var retext = new Retext(),
it('should invoke an attached plugin with a `RootNode` and retext',
function (done) {
var retext,
args;
function plugin () {
function plugin() {
args = arguments;
}
retext = new Retext();
retext.use(plugin);

@@ -212,35 +417,381 @@

it('should not call (during parsing) `use`d plugins, when already used',
function (done) {
var retext = new Retext();
it('should invoke attached plugins in order', function (done) {
var retext,
isInvoked;
function nestedPlugin () {}
function firstPlugin() {
assert(isInvoked === false);
function plugin (tree, retext) {
var length = retext.ware.fns.length;
retext.use(nestedPlugin);
assert(length === retext.ware.fns.length);
}
isInvoked = true;
}
retext.use(nestedPlugin).use(plugin).parse(null, done);
function secondPlugin() {
assert(isInvoked === true);
isInvoked = true;
}
);
it('should parse something into a Text Object Model', function (done) {
new Retext().parse('Something something', function (err, root) {
assert('head' in root);
assert('tail' in root);
assert(root.head.parent === root);
assert('TextOM' in root);
retext = new Retext();
isInvoked = false;
retext
.use(firstPlugin)
.use(secondPlugin)
.parse(null, done);
});
it('should invoke dependencies in order', function (done) {
var retext,
invokeCount;
/* eslint-disable no-use-before-define */
function thirdPlugin() {
assert(invokeCount === 2);
retext
.use(firstPlugin)
.use(secondPlugin);
invokeCount++;
}
function secondPlugin() {
assert(invokeCount === 1);
invokeCount++;
retext
.use(firstPlugin)
.use(thirdPlugin);
}
function firstPlugin() {
assert(invokeCount === 0);
invokeCount++;
retext
.use(secondPlugin)
.use(thirdPlugin);
}
/* eslint-enable no-use-before-define */
retext = new Retext();
invokeCount = 0;
retext
.use(firstPlugin)
.use(secondPlugin)
.use(thirdPlugin)
.parse(null, done);
});
it('should not re-invoke an attached plugin', function (done) {
var retext,
isInvoked;
function nestedPlugin() {
assert(isInvoked !== true);
isInvoked = true;
}
function plugin(tree, retext) {
retext.use(nestedPlugin);
}
retext = new Retext();
retext
.use(nestedPlugin)
.use(plugin)
.parse(null, done);
});
it('should not re-attach an attached plugin', function (done) {
var retext;
function nestedPlugin() {}
function plugin(tree, retext) {
var length;
length = retext.ware.fns.length;
retext.use(nestedPlugin);
assert(length === retext.ware.fns.length);
}
retext = new Retext();
retext
.use(nestedPlugin)
.use(plugin)
.parse(null, done);
});
});
/**
* Test Retext#run(tree, done).
*/
describe('Retext#run(tree, done)', function () {
it('should be a `function`', function () {
assert(typeof Retext.prototype.run === 'function');
assert(typeof (new Retext()).run === 'function');
});
it('should return self', function (done) {
var retext,
root;
retext = new Retext();
root = new retext.TextOM.RootNode();
assert(retext.run(root, done) === retext);
});
it('should throw when `done` is not a `function`', function () {
var retext,
root;
retext = new Retext();
root = new retext.TextOM.RootNode();
assert.throws(function () {
retext.run(root);
}, 'undefined');
assert.throws(function () {
retext.run(root, null);
}, 'null');
assert.throws(function () {
retext.run(root, undefined);
}, 'undefined');
assert.throws(function () {
retext.run(root, true);
}, 'true');
assert.throws(function () {
retext.run(root, {});
}, 'object Object');
});
it('should invoke `done` with `tree`', function (done) {
var retext,
root;
retext = new Retext();
root = new retext.TextOM.RootNode();
retext.run(root, function (err, tree) {
assert(root === tree);
done(err);
});
});
});
describe('Retext#applyPlugins', function () {
it('should be of type `function`', function () {
assert(typeof Retext.prototype.applyPlugins === 'function');
assert(typeof (new Retext()).applyPlugins === 'function');
it('should not invoke `attach` on an attached plugin', function (done) {
var retext,
root,
isInvoked;
function plugin() {}
retext = new Retext();
root = new retext.TextOM.RootNode();
plugin.attach = function () {
isInvoked = true;
};
retext.use(plugin);
assert(isInvoked === true);
isInvoked = false;
retext.run(root, function (err) {
assert(isInvoked !== true);
done(err);
});
});
it('should invoke an attached plugin', function (done) {
var retext,
root,
isInvoked;
function plugin() {
isInvoked = true;
}
retext = new Retext();
root = new retext.TextOM.RootNode();
retext.use(plugin);
assert(isInvoked !== true);
retext.run(root, function (err) {
assert(isInvoked === true);
done(err);
});
});
it('should invoke an attached plugin with a `RootNode`', function (done) {
var retext,
root,
args;
function plugin() {
args = arguments;
}
retext = new Retext();
root = new retext.TextOM.RootNode();
retext.use(plugin);
retext.run(root, function (err) {
assert(args[0] === root);
assert(args[1] === retext);
assert(args.length === 2);
done(err);
});
});
it('should invoke attached plugins in order', function (done) {
var retext,
root,
isInvoked;
function firstPlugin() {
assert(isInvoked === false);
isInvoked = true;
}
function secondPlugin() {
assert(isInvoked === true);
isInvoked = true;
}
retext = new Retext();
root = new retext.TextOM.RootNode();
isInvoked = false;
retext
.use(firstPlugin)
.use(secondPlugin)
.run(root, done);
});
it('should invoke dependencies in order', function (done) {
var retext,
root,
invokeCount;
/* eslint-disable no-use-before-define */
function thirdPlugin() {
assert(invokeCount === 2);
retext
.use(firstPlugin)
.use(secondPlugin);
invokeCount++;
}
function secondPlugin() {
assert(invokeCount === 1);
invokeCount++;
retext
.use(firstPlugin)
.use(thirdPlugin);
}
function firstPlugin() {
assert(invokeCount === 0);
invokeCount++;
retext
.use(secondPlugin)
.use(thirdPlugin);
}
/* eslint-enable no-use-before-define */
retext = new Retext();
root = new retext.TextOM.RootNode();
invokeCount = 0;
retext
.use(firstPlugin)
.use(secondPlugin)
.use(thirdPlugin)
.run(root, done);
});
it('should not re-invoke an attached plugin', function (done) {
var retext,
root,
isInvoked;
function nestedPlugin() {
assert(isInvoked !== true);
isInvoked = true;
}
function plugin(tree, retext) {
retext.use(nestedPlugin);
}
retext = new Retext();
root = new retext.TextOM.RootNode();
retext
.use(nestedPlugin)
.use(plugin)
.run(root, done);
});
it('should not re-attach an attached plugin', function (done) {
var retext,
root;
function nestedPlugin() {}
function plugin(tree, retext) {
var length;
length = retext.ware.fns.length;
retext.use(nestedPlugin);
assert(length === retext.ware.fns.length);
}
retext = new Retext();
root = new retext.TextOM.RootNode();
retext
.use(nestedPlugin)
.use(plugin)
.run(root, done);
});
});
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