175 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			175 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 'use strict'; | ||
|  | 
 | ||
|  | var Base = require('base'); | ||
|  | var define = require('define-property'); | ||
|  | var Compiler = require('./lib/compiler'); | ||
|  | var Parser = require('./lib/parser'); | ||
|  | var utils = require('./lib/utils'); | ||
|  | var regexCache = {}; | ||
|  | var cache = {}; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Create a new instance of `Snapdragon` with the given `options`. | ||
|  |  * | ||
|  |  * ```js
 | ||
|  |  * var snapdragon = new Snapdragon(); | ||
|  |  * ```
 | ||
|  |  * | ||
|  |  * @param {Object} `options` | ||
|  |  * @api public | ||
|  |  */ | ||
|  | 
 | ||
|  | function Snapdragon(options) { | ||
|  |   Base.call(this, null, options); | ||
|  |   this.options = utils.extend({source: 'string'}, this.options); | ||
|  |   this.compiler = new Compiler(this.options); | ||
|  |   this.parser = new Parser(this.options); | ||
|  | 
 | ||
|  |   Object.defineProperty(this, 'compilers', { | ||
|  |     get: function() { | ||
|  |       return this.compiler.compilers; | ||
|  |     } | ||
|  |   }); | ||
|  | 
 | ||
|  |   Object.defineProperty(this, 'parsers', { | ||
|  |     get: function() { | ||
|  |       return this.parser.parsers; | ||
|  |     } | ||
|  |   }); | ||
|  | 
 | ||
|  |   Object.defineProperty(this, 'regex', { | ||
|  |     get: function() { | ||
|  |       return this.parser.regex; | ||
|  |     } | ||
|  |   }); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Inherit Base | ||
|  |  */ | ||
|  | 
 | ||
|  | Base.extend(Snapdragon); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Add a parser to `snapdragon.parsers` for capturing the given `type` using | ||
|  |  * the specified regex or parser function. A function is useful if you need | ||
|  |  * to customize how the token is created and/or have access to the parser | ||
|  |  * instance to check options, etc. | ||
|  |  * | ||
|  |  * ```js
 | ||
|  |  * snapdragon | ||
|  |  *   .capture('slash', /^\//) | ||
|  |  *   .capture('dot', function() { | ||
|  |  *     var pos = this.position(); | ||
|  |  *     var m = this.match(/^\./); | ||
|  |  *     if (!m) return; | ||
|  |  *     return pos({ | ||
|  |  *       type: 'dot', | ||
|  |  *       val: m[0] | ||
|  |  *     }); | ||
|  |  *   }); | ||
|  |  * ```
 | ||
|  |  * @param {String} `type` | ||
|  |  * @param {RegExp|Function} `regex` | ||
|  |  * @return {Object} Returns the parser instance for chaining | ||
|  |  * @api public | ||
|  |  */ | ||
|  | 
 | ||
|  | Snapdragon.prototype.capture = function() { | ||
|  |   return this.parser.capture.apply(this.parser, arguments); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Register a plugin `fn`. | ||
|  |  * | ||
|  |  * ```js
 | ||
|  |  * var snapdragon = new Snapdgragon([options]); | ||
|  |  * snapdragon.use(function() { | ||
|  |  *   console.log(this);          //<= snapdragon instance
 | ||
|  |  *   console.log(this.parser);   //<= parser instance
 | ||
|  |  *   console.log(this.compiler); //<= compiler instance
 | ||
|  |  * }); | ||
|  |  * ```
 | ||
|  |  * @param {Object} `fn` | ||
|  |  * @api public | ||
|  |  */ | ||
|  | 
 | ||
|  | Snapdragon.prototype.use = function(fn) { | ||
|  |   fn.call(this, this); | ||
|  |   return this; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Parse the given `str`. | ||
|  |  * | ||
|  |  * ```js
 | ||
|  |  * var snapdragon = new Snapdgragon([options]); | ||
|  |  * // register parsers
 | ||
|  |  * snapdragon.parser.use(function() {}); | ||
|  |  * | ||
|  |  * // parse
 | ||
|  |  * var ast = snapdragon.parse('foo/bar'); | ||
|  |  * console.log(ast); | ||
|  |  * ```
 | ||
|  |  * @param {String} `str` | ||
|  |  * @param {Object} `options` Set `options.sourcemap` to true to enable source maps. | ||
|  |  * @return {Object} Returns an AST. | ||
|  |  * @api public | ||
|  |  */ | ||
|  | 
 | ||
|  | Snapdragon.prototype.parse = function(str, options) { | ||
|  |   this.options = utils.extend({}, this.options, options); | ||
|  |   var parsed = this.parser.parse(str, this.options); | ||
|  | 
 | ||
|  |   // add non-enumerable parser reference
 | ||
|  |   define(parsed, 'parser', this.parser); | ||
|  |   return parsed; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Compile the given `AST`. | ||
|  |  * | ||
|  |  * ```js
 | ||
|  |  * var snapdragon = new Snapdgragon([options]); | ||
|  |  * // register plugins
 | ||
|  |  * snapdragon.use(function() {}); | ||
|  |  * // register parser plugins
 | ||
|  |  * snapdragon.parser.use(function() {}); | ||
|  |  * // register compiler plugins
 | ||
|  |  * snapdragon.compiler.use(function() {}); | ||
|  |  * | ||
|  |  * // parse
 | ||
|  |  * var ast = snapdragon.parse('foo/bar'); | ||
|  |  * | ||
|  |  * // compile
 | ||
|  |  * var res = snapdragon.compile(ast); | ||
|  |  * console.log(res.output); | ||
|  |  * ```
 | ||
|  |  * @param {Object} `ast` | ||
|  |  * @param {Object} `options` | ||
|  |  * @return {Object} Returns an object with an `output` property with the rendered string. | ||
|  |  * @api public | ||
|  |  */ | ||
|  | 
 | ||
|  | Snapdragon.prototype.compile = function(ast, options) { | ||
|  |   this.options = utils.extend({}, this.options, options); | ||
|  |   var compiled = this.compiler.compile(ast, this.options); | ||
|  | 
 | ||
|  |   // add non-enumerable compiler reference
 | ||
|  |   define(compiled, 'compiler', this.compiler); | ||
|  |   return compiled; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Expose `Snapdragon` | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports = Snapdragon; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Expose `Parser` and `Compiler` | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports.Compiler = Compiler; | ||
|  | module.exports.Parser = Parser; |