105 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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;
 |