123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /** internal
- * class ParserInline
- *
- * Tokenizes paragraph content.
- **/
- 'use strict';
- var Ruler = require('./ruler');
- ////////////////////////////////////////////////////////////////////////////////
- // Parser rules
- var _rules = [
- [ 'text', require('./rules_inline/text') ],
- [ 'linkify', require('./rules_inline/linkify') ],
- [ 'newline', require('./rules_inline/newline') ],
- [ 'escape', require('./rules_inline/escape') ],
- [ 'backticks', require('./rules_inline/backticks') ],
- [ 'strikethrough', require('./rules_inline/strikethrough').tokenize ],
- [ 'emphasis', require('./rules_inline/emphasis').tokenize ],
- [ 'link', require('./rules_inline/link') ],
- [ 'image', require('./rules_inline/image') ],
- [ 'autolink', require('./rules_inline/autolink') ],
- [ 'html_inline', require('./rules_inline/html_inline') ],
- [ 'entity', require('./rules_inline/entity') ]
- ];
- // `rule2` ruleset was created specifically for emphasis/strikethrough
- // post-processing and may be changed in the future.
- //
- // Don't use this for anything except pairs (plugins working with `balance_pairs`).
- //
- var _rules2 = [
- [ 'balance_pairs', require('./rules_inline/balance_pairs') ],
- [ 'strikethrough', require('./rules_inline/strikethrough').postProcess ],
- [ 'emphasis', require('./rules_inline/emphasis').postProcess ],
- // rules for pairs separate '**' into its own text tokens, which may be left unused,
- // rule below merges unused segments back with the rest of the text
- [ 'fragments_join', require('./rules_inline/fragments_join') ]
- ];
- /**
- * new ParserInline()
- **/
- function ParserInline() {
- var i;
- /**
- * ParserInline#ruler -> Ruler
- *
- * [[Ruler]] instance. Keep configuration of inline rules.
- **/
- this.ruler = new Ruler();
- for (i = 0; i < _rules.length; i++) {
- this.ruler.push(_rules[i][0], _rules[i][1]);
- }
- /**
- * ParserInline#ruler2 -> Ruler
- *
- * [[Ruler]] instance. Second ruler used for post-processing
- * (e.g. in emphasis-like rules).
- **/
- this.ruler2 = new Ruler();
- for (i = 0; i < _rules2.length; i++) {
- this.ruler2.push(_rules2[i][0], _rules2[i][1]);
- }
- }
- // Skip single token by running all rules in validation mode;
- // returns `true` if any rule reported success
- //
- ParserInline.prototype.skipToken = function (state) {
- var ok, i, pos = state.pos,
- rules = this.ruler.getRules(''),
- len = rules.length,
- maxNesting = state.md.options.maxNesting,
- cache = state.cache;
- if (typeof cache[pos] !== 'undefined') {
- state.pos = cache[pos];
- return;
- }
- if (state.level < maxNesting) {
- for (i = 0; i < len; i++) {
- // Increment state.level and decrement it later to limit recursion.
- // It's harmless to do here, because no tokens are created. But ideally,
- // we'd need a separate private state variable for this purpose.
- //
- state.level++;
- ok = rules[i](state, true);
- state.level--;
- if (ok) { break; }
- }
- } else {
- // Too much nesting, just skip until the end of the paragraph.
- //
- // NOTE: this will cause links to behave incorrectly in the following case,
- // when an amount of `[` is exactly equal to `maxNesting + 1`:
- //
- // [[[[[[[[[[[[[[[[[[[[[foo]()
- //
- // TODO: remove this workaround when CM standard will allow nested links
- // (we can replace it by preventing links from being parsed in
- // validation mode)
- //
- state.pos = state.posMax;
- }
- if (!ok) { state.pos++; }
- cache[pos] = state.pos;
- };
- // Generate tokens for input range
- //
- ParserInline.prototype.tokenize = function (state) {
- var ok, i,
- rules = this.ruler.getRules(''),
- len = rules.length,
- end = state.posMax,
- maxNesting = state.md.options.maxNesting;
- while (state.pos < end) {
- // Try all possible rules.
- // On success, rule should:
- //
- // - update `state.pos`
- // - update `state.tokens`
- // - return true
- if (state.level < maxNesting) {
- for (i = 0; i < len; i++) {
- ok = rules[i](state, false);
- if (ok) { break; }
- }
- }
- if (ok) {
- if (state.pos >= end) { break; }
- continue;
- }
- state.pending += state.src[state.pos++];
- }
- if (state.pending) {
- state.pushPending();
- }
- };
- /**
- * ParserInline.parse(str, md, env, outTokens)
- *
- * Process input string and push inline tokens into `outTokens`
- **/
- ParserInline.prototype.parse = function (str, md, env, outTokens) {
- var i, rules, len;
- var state = new this.State(str, md, env, outTokens);
- this.tokenize(state);
- rules = this.ruler2.getRules('');
- len = rules.length;
- for (i = 0; i < len; i++) {
- rules[i](state);
- }
- };
- ParserInline.prototype.State = require('./rules_inline/state_inline');
- module.exports = ParserInline;
|