| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 | 'use strict';var utils = require('./utils');var define = require('define-property');/** * Text regex */var TEXT_REGEX = '(\\[(?=.*\\])|\\])+';var not = utils.createRegex(TEXT_REGEX);/** * Brackets parsers */function parsers(brackets) {  brackets.state = brackets.state || {};  brackets.parser.sets.bracket = brackets.parser.sets.bracket || [];  brackets.parser    .capture('escape', function() {      if (this.isInside('bracket')) return;      var pos = this.position();      var m = this.match(/^\\(.)/);      if (!m) return;      return pos({        type: 'escape',        val: m[0]      });    })    /**     * Text parser     */    .capture('text', function() {      if (this.isInside('bracket')) return;      var pos = this.position();      var m = this.match(not);      if (!m || !m[0]) return;      return pos({        type: 'text',        val: m[0]      });    })    /**     * POSIX character classes: "[[:alpha:][:digits:]]"     */    .capture('posix', function() {      var pos = this.position();      var m = this.match(/^\[:(.*?):\](?=.*\])/);      if (!m) return;      var inside = this.isInside('bracket');      if (inside) {        brackets.posix++;      }      return pos({        type: 'posix',        insideBracket: inside,        inner: m[1],        val: m[0]      });    })    /**     * Bracket (noop)     */    .capture('bracket', function() {})    /**     * Open: '['     */    .capture('bracket.open', function() {      var parsed = this.parsed;      var pos = this.position();      var m = this.match(/^\[(?=.*\])/);      if (!m) return;      var prev = this.prev();      var last = utils.last(prev.nodes);      if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) {        last.val = last.val.slice(0, last.val.length - 1);        return pos({          type: 'escape',          val: m[0]        });      }      var open = pos({        type: 'bracket.open',        val: m[0]      });      if (last.type === 'bracket.open' || this.isInside('bracket')) {        open.val = '\\' + open.val;        open.type = 'bracket.inner';        open.escaped = true;        return open;      }      var node = pos({        type: 'bracket',        nodes: [open]      });      define(node, 'parent', prev);      define(open, 'parent', node);      this.push('bracket', node);      prev.nodes.push(node);    })    /**     * Bracket text     */    .capture('bracket.inner', function() {      if (!this.isInside('bracket')) return;      var pos = this.position();      var m = this.match(not);      if (!m || !m[0]) return;      var next = this.input.charAt(0);      var val = m[0];      var node = pos({        type: 'bracket.inner',        val: val      });      if (val === '\\\\') {        return node;      }      var first = val.charAt(0);      var last = val.slice(-1);      if (first === '!') {        val = '^' + val.slice(1);      }      if (last === '\\' || (val === '^' && next === ']')) {        val += this.input[0];        this.consume(1);      }      node.val = val;      return node;    })    /**     * Close: ']'     */    .capture('bracket.close', function() {      var parsed = this.parsed;      var pos = this.position();      var m = this.match(/^\]/);      if (!m) return;      var prev = this.prev();      var last = utils.last(prev.nodes);      if (parsed.slice(-1) === '\\' && !this.isInside('bracket')) {        last.val = last.val.slice(0, last.val.length - 1);        return pos({          type: 'escape',          val: m[0]        });      }      var node = pos({        type: 'bracket.close',        rest: this.input,        val: m[0]      });      if (last.type === 'bracket.open') {        node.type = 'bracket.inner';        node.escaped = true;        return node;      }      var bracket = this.pop('bracket');      if (!this.isType(bracket, 'bracket')) {        if (this.options.strict) {          throw new Error('missing opening "["');        }        node.type = 'bracket.inner';        node.escaped = true;        return node;      }      bracket.nodes.push(node);      define(node, 'parent', bracket);    });}/** * Brackets parsers */module.exports = parsers;/** * Expose text regex */module.exports.TEXT_REGEX = TEXT_REGEX;
 |