create.cjs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. 'use strict';
  2. const index = require('../tokenizer/index.cjs');
  3. const sourceMap = require('./sourceMap.cjs');
  4. const tokenBefore = require('./token-before.cjs');
  5. const types = require('../tokenizer/types.cjs');
  6. const REVERSESOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
  7. function processChildren(node, delimeter) {
  8. if (typeof delimeter === 'function') {
  9. let prev = null;
  10. node.children.forEach(node => {
  11. if (prev !== null) {
  12. delimeter.call(this, prev);
  13. }
  14. this.node(node);
  15. prev = node;
  16. });
  17. return;
  18. }
  19. node.children.forEach(this.node, this);
  20. }
  21. function createGenerator(config) {
  22. const types$1 = new Map();
  23. for (let [name, item] of Object.entries(config.node)) {
  24. const fn = item.generate || item;
  25. if (typeof fn === 'function') {
  26. types$1.set(name, item.generate || item);
  27. }
  28. }
  29. return function(node, options) {
  30. let buffer = '';
  31. let prevCode = 0;
  32. let handlers = {
  33. node(node) {
  34. if (types$1.has(node.type)) {
  35. types$1.get(node.type).call(publicApi, node);
  36. } else {
  37. throw new Error('Unknown node type: ' + node.type);
  38. }
  39. },
  40. tokenBefore: tokenBefore.safe,
  41. token(type, value, suppressAutoWhiteSpace) {
  42. prevCode = this.tokenBefore(prevCode, type, value);
  43. if (!suppressAutoWhiteSpace && prevCode & 1) {
  44. this.emit(' ', types.WhiteSpace, true);
  45. }
  46. this.emit(value, type, false);
  47. if (type === types.Delim && value.charCodeAt(0) === REVERSESOLIDUS) {
  48. this.emit('\n', types.WhiteSpace, true);
  49. }
  50. },
  51. emit(value) {
  52. buffer += value;
  53. },
  54. result() {
  55. return buffer;
  56. }
  57. };
  58. if (options) {
  59. if (typeof options.decorator === 'function') {
  60. handlers = options.decorator(handlers);
  61. }
  62. if (options.sourceMap) {
  63. handlers = sourceMap.generateSourceMap(handlers);
  64. }
  65. if (options.mode in tokenBefore) {
  66. handlers.tokenBefore = tokenBefore[options.mode];
  67. }
  68. }
  69. const publicApi = {
  70. node: (node) => handlers.node(node),
  71. children: processChildren,
  72. token: (type, value) => handlers.token(type, value),
  73. tokenize: (raw) =>
  74. index.tokenize(raw, (type, start, end) => {
  75. handlers.token(
  76. type,
  77. raw.slice(start, end),
  78. start !== 0 // suppress auto whitespace for internal value tokens
  79. );
  80. })
  81. };
  82. handlers.node(node);
  83. return handlers.result();
  84. };
  85. }
  86. exports.createGenerator = createGenerator;