Skip to content

Commit

Permalink
Add support for parser, compiler as non-constructors
Browse files Browse the repository at this point in the history
Closes GH-25.
  • Loading branch information
wooorm committed Feb 11, 2017
1 parent 0db0928 commit b17f876
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 19 deletions.
34 changes: 30 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,17 @@ function unified() {
* into a Unist node using the `Parser` on the
* processor. */
function parse(doc) {
var Parser = processor.Parser;
var file = vfile(doc);

assertConcrete('parse');
assertParser('parse');

return new processor.Parser(doc.toString(), file).parse();
if (isConstructor(Parser)) {
return new Parser(String(file), file).parse();
}

return Parser(String(file), file); // eslint-disable-line new-cap
}

/* Run transforms on a Unist node representation of a file
Expand Down Expand Up @@ -279,12 +284,19 @@ function unified() {
/* Stringify a Unist node representation of a file
* (in string or VFile representation) into a string
* using the `Compiler` on the processor. */
function stringify(node, file) {
function stringify(node, doc) {
var Compiler = processor.Compiler;
var file = vfile(doc);

assertConcrete('stringify');
assertCompiler('stringify');
assertNode(node);

return new processor.Compiler(node, vfile(file)).compile();
if (isConstructor(Compiler)) {
return new Compiler(node, file).compile();
}

return Compiler(node, file); // eslint-disable-line new-cap
}

/* Parse a file (in string or VFile representation)
Expand Down Expand Up @@ -320,7 +332,7 @@ function unified() {

/* Check if `node` is a Unist node. */
function isNode(node) {
return node && string(node.type) && node.type.length !== 0;
return node && node.type && string(node.type);
}

/* Check if `fn` is a function. */
Expand All @@ -332,3 +344,17 @@ function isFunction(fn) {
function isProcessor(processor) {
return isFunction(processor) && isFunction(processor.use) && isFunction(processor.process);
}

/* Check if `func` is a constructor. */
function isConstructor(func) {
return isFunction(func) && hasKeys(func.prototype);
}

/* Check if `func` is a constructor. */
function hasKeys(value) {
var key;
for (key in value) {
return true;
}
return false;
}
31 changes: 19 additions & 12 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,16 @@ Parse text to a syntax tree.

#### `processor.Parser`

Constructor handling the parsing of text to a syntax tree.
It’s instantiated by the [**parse**][parse] phase in the process
with a [**VFile**][file], `settings`, and the processor.
Function handling the parsing of text to a syntax tree. Used in the
[**parse**][parse] phase in the process and invoked with a `string`
and [**VFile**][file] representation of the document to parse.

The instance must expose a `parse` method which is invoked without
arguments, and must return a syntax tree representation of the
[**VFile**][file].
If `Parser` is a normal parser, it should return a [`Node`][node]: the syntax
tree representation of the given file.

`Parser` can also be a constructor function, in which case it’s invoked with
`new`. In that case, instances should have a `parse` method, which is invoked
(without arguments), and should return a [`Node`][node].

### `processor.stringify(node[, file])`

Expand All @@ -370,13 +373,17 @@ Compile a syntax tree to text.

#### `processor.Compiler`

Constructor handling the compilation of a syntax tree to text.
It’s instantiated by the [**stringify**][stringify] phase in the
process with a [**VFile**][file], `settings`, and the processor.
Function handling the compilation of syntax tree to a text. Used in the
[**stringify**][stringify] phase in the process and invoked with a
[`Node`][node] and [**VFile**][file] representation of the document to
stringify.

The instance must expose a `compile` method which is invoked with
the syntax tree, and must return a string representation of that
syntax tree.
If `Compiler` is a normal stringifier, it should return a `string`: the text
representation of the given syntax tree.

`Compiler` can also be a constructor function, in which case it’s invoked with
`new`. In that case, instances should have a `compile` method, which is invoked
(without arguments), and should return a `string`.

### `processor.run(node[, file][, done])`

Expand Down
12 changes: 10 additions & 2 deletions test/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ test('parse(file)', function (t) {
var p = unified();
var n;

t.plan(5);
t.plan(8);

t.throws(
function () {
Expand All @@ -20,7 +20,7 @@ test('parse(file)', function (t) {
n = {type: 'delta'};

p.Parser = function (doc, file) {
t.ok(typeof doc, 'string', 'should pass a document');
t.equal(typeof doc, 'string', 'should pass a document');
t.ok('message' in file, 'should pass a file');
};

Expand All @@ -30,4 +30,12 @@ test('parse(file)', function (t) {
};

t.equal(p.parse('charlie'), n, 'should return the result `Parser#parse` returns');

p.Parser = function (doc, file) {
t.equal(typeof doc, 'string', 'should pass a document');
t.ok('message' in file, 'should pass a file');
return n;
};

t.equal(p.parse('charlie'), n, 'should return the result `parser` returns if it’s not a constructor');
});
10 changes: 9 additions & 1 deletion test/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test('stringify(node[, file])', function (t) {
var f;
var n;

t.plan(6);
t.plan(9);

t.throws(
function () {
Expand Down Expand Up @@ -39,6 +39,14 @@ test('stringify(node[, file])', function (t) {
'should return the result `Compiler#compile` returns'
);

p.Compiler = function (node, file) {
t.equal(node, n, 'should pass a node');
t.ok('message' in file, 'should pass a file');
return 'echo';
};

t.equal(p.stringify(n, f), 'echo', 'should return the result `compiler` returns if it’s not a constructor');

p.Compiler = noop.Compiler;

t.throws(
Expand Down

0 comments on commit b17f876

Please sign in to comment.