You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					220 lines
				
				4.3 KiB
			
		
		
			
		
	
	
					220 lines
				
				4.3 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'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;
							 |