svelte-tokenizer.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. "use strict";
  2. const htmlparser = require("htmlparser2");
  3. const { loadModule } = require("../shared/load-module");
  4. const OPEN_BRACE = "{".charCodeAt(0);
  5. module.exports = class SvelteTokenizer extends htmlparser.Tokenizer {
  6. stateBeforeAttributeValue(c) {
  7. if (c === OPEN_BRACE) {
  8. const startIndex = this._index;
  9. const endIndex = getIndexOfExpressionEnd(this.buffer, startIndex + 1);
  10. if (endIndex != null) {
  11. this.sectionStart = startIndex;
  12. this._index = endIndex + 1;
  13. this.cbs.onattribdata(this.getSection());
  14. this.sectionStart = -1;
  15. this.cbs.onattribend(null);
  16. this._state = 8 /* BeforeAttributeName */;
  17. this.stateBeforeAttributeName(this.buffer.charCodeAt(this._index));
  18. return;
  19. }
  20. }
  21. super.stateBeforeAttributeValue(c);
  22. }
  23. };
  24. function getIndexOfExpressionEnd(source, startIndex) {
  25. const acorn = getAcorn();
  26. /* istanbul ignore if */
  27. if (!acorn) {
  28. return null;
  29. }
  30. let node;
  31. try {
  32. node = acorn.parseExpressionAt(source, startIndex, {
  33. sourceType: "module",
  34. ecmaVersion: "latest",
  35. });
  36. } catch (_e) {
  37. /* istanbul ignore next */
  38. return null;
  39. }
  40. let numParens = 0;
  41. for (let i = startIndex; i < node.start; i += 1) {
  42. if (source[i] === "(") numParens += 1;
  43. }
  44. let index = node.end;
  45. while (numParens > 0) {
  46. const char = source[index];
  47. if (char === ")") {
  48. numParens -= 1;
  49. } else if (!char.trim()) {
  50. return null;
  51. }
  52. index += 1;
  53. }
  54. return getIndexOfNextCloseBrace(source, index);
  55. }
  56. function getIndexOfNextCloseBrace(source, startIndex) {
  57. for (let index = startIndex; index < source.length; index++) {
  58. const char = source[index];
  59. if (char === "}") {
  60. return index;
  61. }
  62. if (!char.trim()) {
  63. break;
  64. }
  65. }
  66. return null;
  67. }
  68. let acorn;
  69. function getAcorn() {
  70. return acorn || (acorn = loadModule("acorn"));
  71. }