Blame view

node_modules/braces/lib/braces.js 2.4 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  'use strict';
  
  var extend = require('extend-shallow');
  var Snapdragon = require('snapdragon');
  var compilers = require('./compilers');
  var parsers = require('./parsers');
  var utils = require('./utils');
  
  /**
   * Customize Snapdragon parser and renderer
   */
  
  function Braces(options) {
    this.options = extend({}, options);
  }
  
  /**
   * Initialize braces
   */
  
  Braces.prototype.init = function(options) {
    if (this.isInitialized) return;
    this.isInitialized = true;
    var opts = utils.createOptions({}, this.options, options);
    this.snapdragon = this.options.snapdragon || new Snapdragon(opts);
    this.compiler = this.snapdragon.compiler;
    this.parser = this.snapdragon.parser;
  
    compilers(this.snapdragon, opts);
    parsers(this.snapdragon, opts);
  
    /**
     * Call Snapdragon `.parse` method. When AST is returned, we check to
     * see if any unclosed braces are left on the stack and, if so, we iterate
     * over the stack and correct the AST so that compilers are called in the correct
     * order and unbalance braces are properly escaped.
     */
  
    utils.define(this.snapdragon, 'parse', function(pattern, options) {
      var parsed = Snapdragon.prototype.parse.apply(this, arguments);
      this.parser.ast.input = pattern;
  
      var stack = this.parser.stack;
      while (stack.length) {
        addParent({type: 'brace.close', val: ''}, stack.pop());
      }
  
      function addParent(node, parent) {
        utils.define(node, 'parent', parent);
        parent.nodes.push(node);
      }
  
      // add non-enumerable parser reference
      utils.define(parsed, 'parser', this.parser);
      return parsed;
    });
  };
  
  /**
   * Decorate `.parse` method
   */
  
  Braces.prototype.parse = function(ast, options) {
    if (ast && typeof ast === 'object' && ast.nodes) return ast;
    this.init(options);
    return this.snapdragon.parse(ast, options);
  };
  
  /**
   * Decorate `.compile` method
   */
  
  Braces.prototype.compile = function(ast, options) {
    if (typeof ast === 'string') {
      ast = this.parse(ast, options);
    } else {
      this.init(options);
    }
    return this.snapdragon.compile(ast, options);
  };
  
  /**
   * Expand
   */
  
  Braces.prototype.expand = function(pattern) {
    var ast = this.parse(pattern, {expand: true});
    return this.compile(ast, {expand: true});
  };
  
  /**
   * Optimize
   */
  
  Braces.prototype.optimize = function(pattern) {
    var ast = this.parse(pattern, {optimize: true});
    return this.compile(ast, {optimize: true});
  };
  
  /**
   * Expose `Braces`
   */
  
  module.exports = Braces;