index.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. 'use strict';
  2. var Base = require('base');
  3. var define = require('define-property');
  4. var Compiler = require('./lib/compiler');
  5. var Parser = require('./lib/parser');
  6. var utils = require('./lib/utils');
  7. var regexCache = {};
  8. var cache = {};
  9. /**
  10. * Create a new instance of `Snapdragon` with the given `options`.
  11. *
  12. * ```js
  13. * var snapdragon = new Snapdragon();
  14. * ```
  15. *
  16. * @param {Object} `options`
  17. * @api public
  18. */
  19. function Snapdragon(options) {
  20. Base.call(this, null, options);
  21. this.options = utils.extend({source: 'string'}, this.options);
  22. this.compiler = new Compiler(this.options);
  23. this.parser = new Parser(this.options);
  24. Object.defineProperty(this, 'compilers', {
  25. get: function() {
  26. return this.compiler.compilers;
  27. }
  28. });
  29. Object.defineProperty(this, 'parsers', {
  30. get: function() {
  31. return this.parser.parsers;
  32. }
  33. });
  34. Object.defineProperty(this, 'regex', {
  35. get: function() {
  36. return this.parser.regex;
  37. }
  38. });
  39. }
  40. /**
  41. * Inherit Base
  42. */
  43. Base.extend(Snapdragon);
  44. /**
  45. * Add a parser to `snapdragon.parsers` for capturing the given `type` using
  46. * the specified regex or parser function. A function is useful if you need
  47. * to customize how the token is created and/or have access to the parser
  48. * instance to check options, etc.
  49. *
  50. * ```js
  51. * snapdragon
  52. * .capture('slash', /^\//)
  53. * .capture('dot', function() {
  54. * var pos = this.position();
  55. * var m = this.match(/^\./);
  56. * if (!m) return;
  57. * return pos({
  58. * type: 'dot',
  59. * val: m[0]
  60. * });
  61. * });
  62. * ```
  63. * @param {String} `type`
  64. * @param {RegExp|Function} `regex`
  65. * @return {Object} Returns the parser instance for chaining
  66. * @api public
  67. */
  68. Snapdragon.prototype.capture = function() {
  69. return this.parser.capture.apply(this.parser, arguments);
  70. };
  71. /**
  72. * Register a plugin `fn`.
  73. *
  74. * ```js
  75. * var snapdragon = new Snapdgragon([options]);
  76. * snapdragon.use(function() {
  77. * console.log(this); //<= snapdragon instance
  78. * console.log(this.parser); //<= parser instance
  79. * console.log(this.compiler); //<= compiler instance
  80. * });
  81. * ```
  82. * @param {Object} `fn`
  83. * @api public
  84. */
  85. Snapdragon.prototype.use = function(fn) {
  86. fn.call(this, this);
  87. return this;
  88. };
  89. /**
  90. * Parse the given `str`.
  91. *
  92. * ```js
  93. * var snapdragon = new Snapdgragon([options]);
  94. * // register parsers
  95. * snapdragon.parser.use(function() {});
  96. *
  97. * // parse
  98. * var ast = snapdragon.parse('foo/bar');
  99. * console.log(ast);
  100. * ```
  101. * @param {String} `str`
  102. * @param {Object} `options` Set `options.sourcemap` to true to enable source maps.
  103. * @return {Object} Returns an AST.
  104. * @api public
  105. */
  106. Snapdragon.prototype.parse = function(str, options) {
  107. this.options = utils.extend({}, this.options, options);
  108. var parsed = this.parser.parse(str, this.options);
  109. // add non-enumerable parser reference
  110. define(parsed, 'parser', this.parser);
  111. return parsed;
  112. };
  113. /**
  114. * Compile the given `AST`.
  115. *
  116. * ```js
  117. * var snapdragon = new Snapdgragon([options]);
  118. * // register plugins
  119. * snapdragon.use(function() {});
  120. * // register parser plugins
  121. * snapdragon.parser.use(function() {});
  122. * // register compiler plugins
  123. * snapdragon.compiler.use(function() {});
  124. *
  125. * // parse
  126. * var ast = snapdragon.parse('foo/bar');
  127. *
  128. * // compile
  129. * var res = snapdragon.compile(ast);
  130. * console.log(res.output);
  131. * ```
  132. * @param {Object} `ast`
  133. * @param {Object} `options`
  134. * @return {Object} Returns an object with an `output` property with the rendered string.
  135. * @api public
  136. */
  137. Snapdragon.prototype.compile = function(ast, options) {
  138. this.options = utils.extend({}, this.options, options);
  139. var compiled = this.compiler.compile(ast, this.options);
  140. // add non-enumerable compiler reference
  141. define(compiled, 'compiler', this.compiler);
  142. return compiled;
  143. };
  144. /**
  145. * Expose `Snapdragon`
  146. */
  147. module.exports = Snapdragon;
  148. /**
  149. * Expose `Parser` and `Compiler`
  150. */
  151. module.exports.Compiler = Compiler;
  152. module.exports.Parser = Parser;