diff --git a/grammars/mediawiki.js b/grammars/mediawiki.js index fe374e1..4f35db1 100644 --- a/grammars/mediawiki.js +++ b/grammars/mediawiki.js @@ -1,4 +1,4 @@ -var mediawiki = { +var mediawiki = rr.Parser({ 'list-blockquote1': rr.Node('blockquote', rr.Sequence( rr.StartOfLine(), rr.Literal(': '), @@ -290,12 +290,9 @@ var mediawiki = { rr.Sequence(rr.EndOfLine(), rr.Literal('\n')), rr.EndOfText()))), - 'wikidoc': rr.Node('wikidoc', rr.Sequence( + 'main': rr.Node('wikidoc', rr.Sequence( rr.ZeroOrMore(rr.Ref('paragraph')), rr.EndOfText())) -}; - - -var mediawiki_filters = { +}, { 'bi': rr.SplitTagAndNest('b', 'i') -}; +}); diff --git a/recentrunes.js b/recentrunes.js index 0647545..34a66e1 100644 --- a/recentrunes.js +++ b/recentrunes.js @@ -4,6 +4,12 @@ var rr = {}; /* ============ typedefs ============ */ +/** + * @typedef {function(Node)} + */ +rr.typeFilter; + + /** * @typedef {{done: boolean, * value: *}} @@ -716,10 +722,14 @@ rr.SingleLineText = function() { -/* ============ Filters ============ */ +/* ============ Filter factories ============ */ -rr.SplitTagAndNest = function() { +/** + * @param {...string} var_args + * @return {rr.typeFilter} + */ +rr.SplitTagAndNest = function(var_args) { var hierarchy = Array.prototype.slice.call(arguments); return function(node) { var outerNode, innerNode; @@ -744,7 +754,6 @@ rr.SplitTagAndNest = function() { /* ============ Scaffolding ============ */ - /** * @param {Node} node * @param {Object.} filters @@ -766,12 +775,12 @@ rr.ApplyFilters = function(node, filters) { * * @param {Object.} rules * @param {string} input - * @param {number} inputIndex + * @param {number=} opt_inputIndex */ -rr.Context = function(rules, input, inputIndex) { +rr.Context = function(rules, input, opt_inputIndex) { this.rules = rules; this.input = input; - this.inputIndex = inputIndex || 0; + this.inputIndex = opt_inputIndex || 0; }; @@ -845,3 +854,44 @@ rr.Context.prototype.advance = function(numChars) { context.inputIndex += numChars; return context; }; + + + +/** + * @constructor + * + * @param {Object.} rules + * @param {Object.} filters + * @private + */ +rr.Parser_ = function(rules, filters) { + this.rules_ = rules; + this.filters_ = filters; +}; + + +/** + * @param {string} input + * @return {?Node} + */ +rr.Parser_.prototype.parseFromString = function(input) { + var context = new rr.Context(this.rules_, input); + var iterable = context.rules['main'].match(context); + var next = iterable.next(); + if (next['done']) { + return null; + } + var rootNode = next['value']['nodes'][0]; + rr.ApplyFilters(rootNode, this.filters_); + return rootNode; +}; + + +/** + * @param {Object.} rules + * @param {Object.} filters + * @return {rr.Parser_} + */ +rr.Parser = function(rules, filters) { + return new rr.Parser_(rules, filters); +}; diff --git a/test.js b/test.js index 279e886..bb45546 100644 --- a/test.js +++ b/test.js @@ -59,11 +59,7 @@ QUnit.test('Base', function(assert) { '

' ].join(''); - var context = new rr.Context(mediawiki, content); - var iterable = context.rules['wikidoc'].match(context); - var rootNode = iterable.next().value.nodes[0]; - rr.ApplyFilters(rootNode, mediawiki_filters); - assert.equal(rootNode.innerHTML, expected); + assert.equal(mediawiki.parseFromString(content).innerHTML, expected); }); QUnit.test('singleline-wikichunk', function(assert) { @@ -78,9 +74,7 @@ QUnit.test('singleline-wikichunk', function(assert) { '

Header 3 with italics

' ].join(''); - var context = new rr.Context(mediawiki, content); - var iterable = context.rules['wikidoc'].match(context); - assert.equal(iterable.next().value.nodes[0].innerHTML, expected); + assert.equal(mediawiki.parseFromString(content).innerHTML, expected); }); QUnit.test('Link', function(assert) { @@ -94,9 +88,7 @@ QUnit.test('Link', function(assert) { 'Test text with formatting

' ].join(''); - var context = new rr.Context(mediawiki, content); - var iterable = context.rules['wikidoc'].match(context); - assert.equal(iterable.next().value.nodes[0].innerHTML, expected); + assert.equal(mediawiki.parseFromString(content).innerHTML, expected); }); QUnit.test('Image', function(assert) { @@ -110,7 +102,5 @@ QUnit.test('Image', function(assert) { 'Test image with formatting

' ].join(''); - var context = new rr.Context(mediawiki, content); - var iterable = context.rules['wikidoc'].match(context); - assert.equal(iterable.next().value.nodes[0].innerHTML, expected); + assert.equal(mediawiki.parseFromString(content).innerHTML, expected); });