create.cjs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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 processChunk(chunk) {
  22. index.tokenize(chunk, (type, start, end) => {
  23. this.token(type, chunk.slice(start, end));
  24. });
  25. }
  26. function createGenerator(config) {
  27. const types$1 = new Map();
  28. for (let [name, item] of Object.entries(config.node)) {
  29. const fn = item.generate || item;
  30. if (typeof fn === 'function') {
  31. types$1.set(name, item.generate || item);
  32. }
  33. }
  34. return function(node, options) {
  35. let buffer = '';
  36. let prevCode = 0;
  37. let handlers = {
  38. node(node) {
  39. if (types$1.has(node.type)) {
  40. types$1.get(node.type).call(publicApi, node);
  41. } else {
  42. throw new Error('Unknown node type: ' + node.type);
  43. }
  44. },
  45. tokenBefore: tokenBefore.safe,
  46. token(type, value) {
  47. prevCode = this.tokenBefore(prevCode, type, value);
  48. this.emit(value, type, false);
  49. if (type === types.Delim && value.charCodeAt(0) === REVERSESOLIDUS) {
  50. this.emit('\n', types.WhiteSpace, true);
  51. }
  52. },
  53. emit(value) {
  54. buffer += value;
  55. },
  56. result() {
  57. return buffer;
  58. }
  59. };
  60. if (options) {
  61. if (typeof options.decorator === 'function') {
  62. handlers = options.decorator(handlers);
  63. }
  64. if (options.sourceMap) {
  65. handlers = sourceMap.generateSourceMap(handlers);
  66. }
  67. if (options.mode in tokenBefore) {
  68. handlers.tokenBefore = tokenBefore[options.mode];
  69. }
  70. }
  71. const publicApi = {
  72. node: (node) => handlers.node(node),
  73. children: processChildren,
  74. token: (type, value) => handlers.token(type, value),
  75. tokenize: processChunk
  76. };
  77. handlers.node(node);
  78. return handlers.result();
  79. };
  80. }
  81. exports.createGenerator = createGenerator;