htmljs-parser 5.1.1 → 5.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -93,10 +94,23 @@ function htmlEOF() {
93
94
  if (this.activeTag.concise) {
94
95
  this.closeTagEnd(this.pos, this.pos, void 0);
95
96
  } else {
96
- return this.emitError(this.activeTag, 22 /* MISSING_END_TAG */, 'Missing ending "' + this.read(this.activeTag.tagName) + '" tag');
97
+ return this.emitError(
98
+ this.activeTag,
99
+ 22 /* MISSING_END_TAG */,
100
+ 'Missing ending "' + this.read(this.activeTag.tagName) + '" tag'
101
+ );
97
102
  }
98
103
  }
99
104
  }
105
+ function matchesCloseParen(code) {
106
+ return code === 41 /* CLOSE_PAREN */;
107
+ }
108
+ function matchesCloseCurlyBrace(code) {
109
+ return code === 125 /* CLOSE_CURLY_BRACE */;
110
+ }
111
+ function matchesPipe(code) {
112
+ return code === 124 /* PIPE */;
113
+ }
100
114
  function getPosAfterLine(lines, startLine, index) {
101
115
  let max = lines.length - 1;
102
116
  let line = startLine;
@@ -118,34 +132,30 @@ function getPosAfterLine(lines, startLine, index) {
118
132
  var Parser = class {
119
133
  constructor(options) {
120
134
  this.options = options;
121
- this.options = options;
122
135
  }
123
- pos;
124
- maxPos;
125
- data;
126
- activeState;
127
- activeRange;
128
- forward;
129
- activeTag;
130
- activeAttr;
131
- indent;
132
- isConcise;
133
- beginMixedMode;
134
- endingMixedModeAtEOL;
135
- textPos;
136
- lines;
137
136
  read(range) {
138
137
  return this.data.slice(range.start, range.end);
139
138
  }
140
139
  positionAt(offset) {
141
- return getPosition(this.lines || (this.lines = getLines(this.data)), offset);
140
+ return getPosition(
141
+ this.lines || (this.lines = getLines(this.data)),
142
+ offset
143
+ );
142
144
  }
143
145
  locationAt(range) {
144
- return getLocation(this.lines || (this.lines = getLines(this.data)), range.start, range.end);
146
+ return getLocation(
147
+ this.lines || (this.lines = getLines(this.data)),
148
+ range.start,
149
+ range.end
150
+ );
145
151
  }
146
152
  enterState(state) {
147
153
  this.activeState = state;
148
- return this.activeRange = state.enter.call(this, this.activeRange, this.pos);
154
+ return this.activeRange = state.enter.call(
155
+ this,
156
+ this.activeRange,
157
+ this.pos
158
+ );
149
159
  }
150
160
  exitState() {
151
161
  const { activeRange, activeState } = this;
@@ -215,7 +225,9 @@ var Parser = class {
215
225
  }
216
226
  beginHtmlBlock(delimiter, singleLine) {
217
227
  var _a;
218
- const content = this.enterState(((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ ? states_exports.PARSED_TEXT_CONTENT : states_exports.HTML_CONTENT);
228
+ const content = this.enterState(
229
+ ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ ? states_exports.PARSED_TEXT_CONTENT : states_exports.HTML_CONTENT
230
+ );
219
231
  content.singleLine = singleLine;
220
232
  content.delimiter = delimiter;
221
233
  content.indent = this.indent;
@@ -375,461 +387,910 @@ __export(states_exports, {
375
387
  handleDelimitedEOL: () => handleDelimitedEOL
376
388
  });
377
389
 
378
- // src/states/ATTRIBUTE.ts
379
- var HTML_VALUE_TERMINATORS = [
380
- 62 /* CLOSE_ANGLE_BRACKET */,
381
- 44 /* COMMA */,
382
- [47 /* FORWARD_SLASH */, 62 /* CLOSE_ANGLE_BRACKET */]
383
- ];
384
- var CONCISE_VALUE_TERMINATORS = [
385
- 93 /* CLOSE_SQUARE_BRACKET */,
386
- 59 /* SEMICOLON */,
387
- 44 /* COMMA */
388
- ];
389
- var HTML_NAME_TERMINATORS = [
390
- 62 /* CLOSE_ANGLE_BRACKET */,
391
- 44 /* COMMA */,
392
- 40 /* OPEN_PAREN */,
393
- 61 /* EQUAL */,
394
- [58 /* COLON */, 61 /* EQUAL */],
395
- [47 /* FORWARD_SLASH */, 62 /* CLOSE_ANGLE_BRACKET */]
396
- ];
397
- var CONCISE_NAME_TERMINATORS = [
398
- 93 /* CLOSE_SQUARE_BRACKET */,
399
- 59 /* SEMICOLON */,
400
- 61 /* EQUAL */,
401
- 44 /* COMMA */,
402
- 40 /* OPEN_PAREN */,
403
- [58 /* COLON */, 61 /* EQUAL */]
404
- ];
405
- var ATTRIBUTE = {
406
- name: "ATTRIBUTE",
390
+ // src/states/OPEN_TAG.ts
391
+ var TAG_STAGE = /* @__PURE__ */ ((TAG_STAGE2) => {
392
+ TAG_STAGE2[TAG_STAGE2["UNKNOWN"] = 0] = "UNKNOWN";
393
+ TAG_STAGE2[TAG_STAGE2["VAR"] = 1] = "VAR";
394
+ TAG_STAGE2[TAG_STAGE2["ARGUMENT"] = 2] = "ARGUMENT";
395
+ TAG_STAGE2[TAG_STAGE2["PARAMS"] = 3] = "PARAMS";
396
+ TAG_STAGE2[TAG_STAGE2["ATTR_GROUP"] = 4] = "ATTR_GROUP";
397
+ return TAG_STAGE2;
398
+ })(TAG_STAGE || {});
399
+ var OPEN_TAG = {
400
+ name: "OPEN_TAG",
407
401
  enter(parent, start) {
408
- return this.activeAttr = {
409
- state: ATTRIBUTE,
402
+ const tag = this.activeTag = {
403
+ state: OPEN_TAG,
404
+ type: 0 /* html */,
410
405
  parent,
411
406
  start,
412
407
  end: start,
413
- valueStart: start,
414
408
  stage: 0 /* UNKNOWN */,
415
- name: void 0,
416
- args: false,
417
- bound: false,
418
- spread: false
409
+ parentTag: this.activeTag,
410
+ nestedIndent: void 0,
411
+ indent: this.indent,
412
+ hasShorthandId: false,
413
+ hasArgs: false,
414
+ hasAttrs: false,
415
+ selfClosed: false,
416
+ shorthandEnd: -1,
417
+ tagName: void 0,
418
+ concise: this.isConcise,
419
+ beginMixedMode: this.beginMixedMode || this.endingMixedModeAtEOL
419
420
  };
421
+ this.beginMixedMode = false;
422
+ this.endingMixedModeAtEOL = false;
423
+ this.endText();
424
+ return tag;
420
425
  },
421
- exit() {
422
- this.activeAttr = void 0;
423
- },
424
- char(code, attr) {
425
- if (isWhitespaceCode(code)) {
426
- return;
427
- } else if (code === 61 /* EQUAL */ || code === 58 /* COLON */ && this.lookAtCharCodeAhead(1) === 61 /* EQUAL */ || code === 46 /* PERIOD */ && this.lookAheadFor("..")) {
428
- attr.valueStart = this.pos;
429
- this.forward = 0;
430
- if (code === 58 /* COLON */) {
431
- ensureAttrName(this, attr);
432
- attr.bound = true;
433
- this.pos += 2;
434
- this.consumeWhitespace();
435
- } else if (code === 46 /* PERIOD */) {
436
- attr.spread = true;
437
- this.pos += 3;
438
- } else {
439
- ensureAttrName(this, attr);
440
- this.pos++;
441
- this.consumeWhitespace();
426
+ exit(tag) {
427
+ var _a, _b;
428
+ const { selfClosed } = tag;
429
+ (_b = (_a = this.options).onOpenTagEnd) == null ? void 0 : _b.call(_a, {
430
+ start: this.pos - (this.isConcise ? 0 : selfClosed ? 2 : 1),
431
+ end: this.pos,
432
+ selfClosed
433
+ });
434
+ switch (selfClosed ? 2 /* void */ : tag.type) {
435
+ case 2 /* void */:
436
+ case 3 /* statement */: {
437
+ if (tag.beginMixedMode)
438
+ this.endingMixedModeAtEOL = true;
439
+ this.activeTag = tag.parentTag;
440
+ break;
442
441
  }
443
- attr.stage = 2 /* VALUE */;
444
- const expr = this.enterState(states_exports.EXPRESSION);
445
- expr.terminatedByWhitespace = true;
446
- expr.terminator = this.isConcise ? CONCISE_VALUE_TERMINATORS : HTML_VALUE_TERMINATORS;
447
- } else if (code === 40 /* OPEN_PAREN */) {
448
- ensureAttrName(this, attr);
449
- attr.stage = 3 /* ARGUMENT */;
450
- this.pos++;
451
- this.forward = 0;
452
- this.enterState(states_exports.EXPRESSION).terminator = 41 /* CLOSE_PAREN */;
453
- } else if (code === 123 /* OPEN_CURLY_BRACE */ && attr.args) {
454
- ensureAttrName(this, attr);
455
- attr.stage = 4 /* BLOCK */;
456
- this.pos++;
457
- this.forward = 0;
458
- const expr = this.enterState(states_exports.EXPRESSION);
459
- expr.terminatedByWhitespace = false;
460
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
461
- } else if (attr.stage === 0 /* UNKNOWN */) {
462
- attr.stage = 1 /* NAME */;
463
- this.forward = 0;
464
- const expr = this.enterState(states_exports.EXPRESSION);
465
- expr.terminatedByWhitespace = true;
466
- expr.skipOperators = true;
467
- expr.terminator = this.isConcise ? CONCISE_NAME_TERMINATORS : HTML_NAME_TERMINATORS;
468
- } else {
469
- this.exitState();
442
+ case 1 /* text */:
443
+ if (this.isConcise) {
444
+ this.enterState(states_exports.CONCISE_HTML_CONTENT);
445
+ } else {
446
+ this.enterState(states_exports.PARSED_TEXT_CONTENT);
447
+ }
448
+ break;
470
449
  }
471
450
  },
472
- eol() {
473
- if (this.isConcise) {
451
+ eol(_, tag) {
452
+ if (this.isConcise && tag.stage !== 4 /* ATTR_GROUP */) {
474
453
  this.exitState();
475
454
  }
476
455
  },
477
- eof(attr) {
456
+ eof(tag) {
478
457
  if (this.isConcise) {
458
+ if (tag.stage === 4 /* ATTR_GROUP */) {
459
+ this.emitError(
460
+ tag,
461
+ 19 /* MALFORMED_OPEN_TAG */,
462
+ 'EOF reached while within an attribute group (e.g. "[ ... ]").'
463
+ );
464
+ return;
465
+ }
479
466
  this.exitState();
480
467
  } else {
481
- this.emitError(attr, 19 /* MALFORMED_OPEN_TAG */, 'EOF reached while parsing attribute "' + (attr.name ? this.read(attr.name) : "default") + '" for the "' + this.read(this.activeTag.tagName) + '" tag');
468
+ this.emitError(
469
+ tag,
470
+ 19 /* MALFORMED_OPEN_TAG */,
471
+ "EOF reached while parsing open tag"
472
+ );
482
473
  }
483
474
  },
484
- return(child, attr) {
485
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
486
- switch (attr.stage) {
487
- case 1 /* NAME */: {
488
- attr.name = {
489
- start: child.start,
490
- end: child.end
491
- };
492
- (_b = (_a = this.options).onAttrName) == null ? void 0 : _b.call(_a, attr.name);
493
- break;
475
+ char(code, tag) {
476
+ if (this.isConcise) {
477
+ if (code === 59 /* SEMICOLON */) {
478
+ this.pos++;
479
+ this.exitState();
480
+ if (!this.consumeWhitespaceOnLine(0)) {
481
+ switch (this.lookAtCharCodeAhead(0)) {
482
+ case 47 /* FORWARD_SLASH */:
483
+ switch (this.lookAtCharCodeAhead(1)) {
484
+ case 47 /* FORWARD_SLASH */:
485
+ this.enterState(states_exports.JS_COMMENT_LINE);
486
+ this.pos += 2;
487
+ return;
488
+ case 42 /* ASTERISK */:
489
+ this.enterState(states_exports.JS_COMMENT_BLOCK);
490
+ this.pos += 2;
491
+ return;
492
+ }
493
+ break;
494
+ case 60 /* OPEN_ANGLE_BRACKET */:
495
+ if (this.lookAheadFor("!--")) {
496
+ this.enterState(states_exports.HTML_COMMENT);
497
+ this.pos += 4;
498
+ return;
499
+ }
500
+ break;
501
+ }
502
+ this.emitError(
503
+ this.pos,
504
+ 5 /* INVALID_CODE_AFTER_SEMICOLON */,
505
+ "A semicolon indicates the end of a line. Only comments may follow it."
506
+ );
507
+ }
508
+ return;
494
509
  }
495
- case 3 /* ARGUMENT */: {
496
- if (attr.args) {
497
- this.emitError(child, 1 /* INVALID_ATTRIBUTE_ARGUMENT */, "An attribute can only have one set of arguments");
510
+ if (code === 45 /* HTML_BLOCK_DELIMITER */) {
511
+ if (this.lookAtCharCodeAhead(1) !== 45 /* HTML_BLOCK_DELIMITER */) {
512
+ this.emitError(
513
+ tag,
514
+ 19 /* MALFORMED_OPEN_TAG */,
515
+ '"-" not allowed as first character of attribute name'
516
+ );
498
517
  return;
499
518
  }
500
- const start = child.start - 1;
501
- const end = ++this.pos;
502
- const value = {
503
- start: child.start,
504
- end: child.end
505
- };
506
- if (this.consumeWhitespaceIfBefore("{")) {
507
- attr.args = {
508
- start,
509
- end,
510
- value
511
- };
512
- } else {
513
- attr.args = true;
514
- (_d = (_c = this.options).onAttrArgs) == null ? void 0 : _d.call(_c, {
515
- start,
516
- end,
517
- value
518
- });
519
+ if (tag.stage === 4 /* ATTR_GROUP */) {
520
+ this.emitError(
521
+ this.pos,
522
+ 19 /* MALFORMED_OPEN_TAG */,
523
+ "Attribute group was not properly ended"
524
+ );
525
+ return;
519
526
  }
520
- break;
521
- }
522
- case 4 /* BLOCK */: {
523
- const params = attr.args;
524
- const start = params.start;
525
- const end = ++this.pos;
526
- (_f = (_e = this.options).onAttrMethod) == null ? void 0 : _f.call(_e, {
527
- start,
528
- end,
529
- params,
530
- body: {
531
- start: child.start - 1,
532
- end,
533
- value: {
534
- start: child.start,
535
- end: child.end
536
- }
537
- }
538
- });
539
527
  this.exitState();
540
- break;
541
- }
542
- case 2 /* VALUE */: {
543
- if (child.start === child.end) {
544
- return this.emitError(child, 3 /* INVALID_ATTRIBUTE_VALUE */, "Missing value for attribute");
528
+ const maxPos = this.maxPos;
529
+ let curPos = this.pos + 1;
530
+ while (curPos < maxPos && this.data.charCodeAt(++curPos) !== 10 /* NEWLINE */)
531
+ ;
532
+ const indentStart = ++curPos;
533
+ while (curPos < maxPos) {
534
+ const nextCode = this.data.charCodeAt(curPos);
535
+ if (nextCode === 32 /* SPACE */ || nextCode === 9 /* TAB */) {
536
+ curPos++;
537
+ } else {
538
+ break;
539
+ }
545
540
  }
546
- if (attr.spread) {
547
- (_h = (_g = this.options).onAttrSpread) == null ? void 0 : _h.call(_g, {
548
- start: attr.valueStart,
549
- end: child.end,
550
- value: {
551
- start: child.start,
552
- end: child.end
553
- }
554
- });
555
- } else {
556
- (_j = (_i = this.options).onAttrValue) == null ? void 0 : _j.call(_i, {
557
- start: attr.valueStart,
558
- end: child.end,
559
- bound: attr.bound,
560
- value: {
561
- start: child.start,
562
- end: child.end
563
- }
564
- });
541
+ const indentSize = curPos - indentStart;
542
+ if (indentSize > this.indent.length) {
543
+ this.indent = this.data.slice(indentStart, curPos);
565
544
  }
566
- this.exitState();
567
- break;
568
- }
569
- }
570
- }
571
- };
572
- function ensureAttrName(parser, attr) {
573
- var _a, _b;
574
- if (!attr.name) {
575
- (_b = (_a = parser.options).onAttrName) == null ? void 0 : _b.call(_a, {
576
- start: attr.start,
577
- end: attr.start
578
- });
579
- }
580
- }
581
-
582
- // src/states/BEGIN_DELIMITED_HTML_BLOCK.ts
583
- var BEGIN_DELIMITED_HTML_BLOCK = {
584
- name: "BEGIN_DELIMITED_HTML_BLOCK",
585
- enter(parent, start) {
586
- return {
587
- state: BEGIN_DELIMITED_HTML_BLOCK,
588
- parent,
589
- start,
590
- end: start,
591
- indent: this.indent,
592
- delimiter: ""
593
- };
594
- },
595
- exit() {
596
- },
597
- char(code, block) {
598
- if (code === 45 /* HTML_BLOCK_DELIMITER */) {
599
- block.delimiter += "-";
545
+ this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
546
+ return;
547
+ } else if (code === 91 /* OPEN_SQUARE_BRACKET */) {
548
+ if (tag.stage === 4 /* ATTR_GROUP */) {
549
+ this.emitError(
550
+ this.pos,
551
+ 19 /* MALFORMED_OPEN_TAG */,
552
+ 'Unexpected "[" character within open tag.'
553
+ );
554
+ return;
555
+ }
556
+ tag.stage = 4 /* ATTR_GROUP */;
557
+ return;
558
+ } else if (code === 93 /* CLOSE_SQUARE_BRACKET */) {
559
+ if (tag.stage !== 4 /* ATTR_GROUP */) {
560
+ this.emitError(
561
+ this.pos,
562
+ 19 /* MALFORMED_OPEN_TAG */,
563
+ 'Unexpected "]" character within open tag.'
564
+ );
565
+ return;
566
+ }
567
+ tag.stage = 0 /* UNKNOWN */;
568
+ return;
569
+ }
570
+ } else if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
571
+ this.pos++;
572
+ this.exitState();
573
+ return;
574
+ } else if (code === 47 /* FORWARD_SLASH */ && this.lookAtCharCodeAhead(1) === 62 /* CLOSE_ANGLE_BRACKET */) {
575
+ tag.selfClosed = true;
576
+ this.pos += 2;
577
+ this.exitState();
578
+ return;
579
+ }
580
+ if (code === 60 /* OPEN_ANGLE_BRACKET */) {
581
+ return this.emitError(
582
+ this.pos,
583
+ 2 /* INVALID_ATTRIBUTE_NAME */,
584
+ 'Invalid attribute name. Attribute name cannot begin with the "<" character.'
585
+ );
586
+ }
587
+ if (code === 47 /* FORWARD_SLASH */) {
588
+ switch (this.lookAtCharCodeAhead(1)) {
589
+ case 47 /* FORWARD_SLASH */:
590
+ this.enterState(states_exports.JS_COMMENT_LINE);
591
+ this.pos++;
592
+ return;
593
+ case 42 /* ASTERISK */:
594
+ this.enterState(states_exports.JS_COMMENT_BLOCK);
595
+ this.pos++;
596
+ return;
597
+ }
598
+ }
599
+ if (isWhitespaceCode(code)) {
600
+ } else if (code === 44 /* COMMA */) {
601
+ this.pos++;
602
+ this.forward = 0;
603
+ this.consumeWhitespace();
604
+ } else if (code === 47 /* FORWARD_SLASH */ && !tag.hasAttrs) {
605
+ tag.stage = 1 /* VAR */;
606
+ this.pos++;
607
+ this.forward = 0;
608
+ if (isWhitespaceCode(this.lookAtCharCodeAhead(0))) {
609
+ return this.emitError(
610
+ this.pos,
611
+ 23 /* MISSING_TAG_VARIABLE */,
612
+ "A slash was found that was not followed by a variable name or lhs expression"
613
+ );
614
+ }
615
+ const expr = this.enterState(states_exports.EXPRESSION);
616
+ expr.operators = true;
617
+ expr.terminatedByWhitespace = true;
618
+ expr.shouldTerminate = this.isConcise ? shouldTerminateConciseTagVar : shouldTerminateHtmlTagVar;
619
+ } else if (code === 40 /* OPEN_PAREN */ && !tag.hasAttrs) {
620
+ if (tag.hasArgs) {
621
+ this.emitError(
622
+ this.pos,
623
+ 11 /* INVALID_TAG_ARGUMENT */,
624
+ "A tag can only have one argument"
625
+ );
626
+ return;
627
+ }
628
+ tag.stage = 2 /* ARGUMENT */;
629
+ this.pos++;
630
+ this.forward = 0;
631
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseParen;
632
+ } else if (code === 124 /* PIPE */ && !tag.hasAttrs) {
633
+ tag.stage = 3 /* PARAMS */;
634
+ this.pos++;
635
+ this.forward = 0;
636
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesPipe;
600
637
  } else {
601
- const startPos = this.pos;
602
- if (!this.consumeWhitespaceOnLine()) {
603
- this.pos = startPos + 1;
604
- this.forward = 0;
605
- this.beginHtmlBlock(void 0, true);
638
+ this.forward = 0;
639
+ if (tag.tagName) {
640
+ this.enterState(states_exports.ATTRIBUTE);
641
+ tag.hasAttrs = true;
642
+ } else {
643
+ this.enterState(states_exports.TAG_NAME);
606
644
  }
607
645
  }
608
646
  },
609
- eol(len, block) {
610
- this.beginHtmlBlock(block.delimiter, false);
611
- handleDelimitedBlockEOL(this, len, block);
612
- },
613
- eof: htmlEOF,
614
- return() {
647
+ return(child, tag) {
648
+ var _a, _b, _c, _d, _e, _f;
649
+ switch (child.state) {
650
+ case states_exports.JS_COMMENT_BLOCK: {
651
+ break;
652
+ }
653
+ case states_exports.EXPRESSION: {
654
+ switch (tag.stage) {
655
+ case 1 /* VAR */: {
656
+ if (child.start === child.end) {
657
+ return this.emitError(
658
+ child,
659
+ 23 /* MISSING_TAG_VARIABLE */,
660
+ "A slash was found that was not followed by a variable name or lhs expression"
661
+ );
662
+ }
663
+ (_b = (_a = this.options).onTagVar) == null ? void 0 : _b.call(_a, {
664
+ start: child.start - 1,
665
+ end: child.end,
666
+ value: {
667
+ start: child.start,
668
+ end: child.end
669
+ }
670
+ });
671
+ break;
672
+ }
673
+ case 2 /* ARGUMENT */: {
674
+ const start = child.start - 1;
675
+ const end = ++this.pos;
676
+ const value = {
677
+ start: child.start,
678
+ end: child.end
679
+ };
680
+ if (this.consumeWhitespaceIfBefore("{")) {
681
+ const attr = this.enterState(states_exports.ATTRIBUTE);
682
+ attr.start = start;
683
+ attr.args = { start, end, value };
684
+ tag.hasAttrs = true;
685
+ this.forward = 0;
686
+ } else {
687
+ tag.hasArgs = true;
688
+ (_d = (_c = this.options).onTagArgs) == null ? void 0 : _d.call(_c, {
689
+ start,
690
+ end,
691
+ value
692
+ });
693
+ }
694
+ break;
695
+ }
696
+ case 3 /* PARAMS */: {
697
+ const end = ++this.pos;
698
+ (_f = (_e = this.options).onTagParams) == null ? void 0 : _f.call(_e, {
699
+ start: child.start - 1,
700
+ end,
701
+ value: {
702
+ start: child.start,
703
+ end: child.end
704
+ }
705
+ });
706
+ break;
707
+ }
708
+ }
709
+ break;
710
+ }
711
+ }
615
712
  }
616
713
  };
617
- function handleDelimitedEOL(parser, newLineLength, content) {
618
- if (content.singleLine) {
619
- parser.endText();
620
- parser.exitState();
621
- parser.exitState();
622
- return true;
623
- }
624
- if (content.delimiter) {
625
- handleDelimitedBlockEOL(parser, newLineLength, content);
626
- return true;
714
+ function shouldTerminateConciseTagVar(code, data, pos) {
715
+ switch (code) {
716
+ case 44 /* COMMA */:
717
+ case 61 /* EQUAL */:
718
+ case 124 /* PIPE */:
719
+ case 40 /* OPEN_PAREN */:
720
+ case 59 /* SEMICOLON */:
721
+ return true;
722
+ case 58 /* COLON */:
723
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
724
+ default:
725
+ return false;
627
726
  }
628
- return false;
629
727
  }
630
- function handleDelimitedBlockEOL(parser, newLineLength, {
631
- indent,
632
- delimiter
633
- }) {
634
- const endHtmlBlockLookahead = indent + delimiter;
635
- if (parser.lookAheadFor(endHtmlBlockLookahead, parser.pos + newLineLength)) {
636
- parser.startText();
637
- parser.pos += newLineLength;
638
- parser.endText();
639
- parser.pos += endHtmlBlockLookahead.length;
640
- if (parser.consumeWhitespaceOnLine(0)) {
641
- parser.endText();
642
- parser.exitState();
643
- parser.exitState();
644
- } else {
645
- parser.emitError(parser.pos, 4 /* INVALID_CHARACTER */, "A concise mode closing block delimiter can only be followed by whitespace.");
646
- }
647
- } else if (parser.lookAheadFor(indent, parser.pos + newLineLength)) {
648
- parser.startText();
649
- parser.pos += indent.length;
650
- } else if (indent && !parser.onlyWhitespaceRemainsOnLine(newLineLength)) {
651
- parser.endText();
652
- parser.exitState();
653
- parser.exitState();
654
- } else {
655
- parser.startText();
728
+ function shouldTerminateHtmlTagVar(code, data, pos) {
729
+ switch (code) {
730
+ case 124 /* PIPE */:
731
+ case 44 /* COMMA */:
732
+ case 61 /* EQUAL */:
733
+ case 40 /* OPEN_PAREN */:
734
+ case 62 /* CLOSE_ANGLE_BRACKET */:
735
+ return true;
736
+ case 58 /* COLON */:
737
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
738
+ case 47 /* FORWARD_SLASH */:
739
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
740
+ default:
741
+ return false;
656
742
  }
657
743
  }
658
744
 
659
- // src/states/CDATA.ts
660
- var CDATA = {
661
- name: "CDATA",
745
+ // src/states/ATTRIBUTE.ts
746
+ var ATTRIBUTE = {
747
+ name: "ATTRIBUTE",
662
748
  enter(parent, start) {
663
- return {
664
- state: CDATA,
749
+ return this.activeAttr = {
750
+ state: ATTRIBUTE,
665
751
  parent,
666
752
  start,
667
- end: start
753
+ end: start,
754
+ valueStart: start,
755
+ stage: 0 /* UNKNOWN */,
756
+ name: void 0,
757
+ args: false,
758
+ bound: false,
759
+ spread: false
668
760
  };
669
761
  },
670
- exit(cdata) {
671
- var _a, _b;
672
- (_b = (_a = this.options).onCDATA) == null ? void 0 : _b.call(_a, {
673
- start: cdata.start,
674
- end: cdata.end,
675
- value: {
676
- start: cdata.start + 9,
677
- end: cdata.end - 3
678
- }
679
- });
762
+ exit() {
763
+ this.activeAttr = void 0;
680
764
  },
681
- char(code) {
682
- if (code === 93 /* CLOSE_SQUARE_BRACKET */ && this.lookAheadFor("]>")) {
683
- this.pos += 3;
684
- this.exitState();
765
+ char(code, attr) {
766
+ if (isWhitespaceCode(code)) {
685
767
  return;
686
- }
687
- },
688
- eol() {
689
- },
690
- eof(cdata) {
691
- this.emitError(cdata, 14 /* MALFORMED_CDATA */, "EOF reached while parsing CDATA");
692
- },
693
- return() {
694
- }
695
- };
696
- function checkForCDATA(parser) {
697
- if (parser.lookAheadFor("![CDATA[")) {
698
- parser.endText();
699
- parser.enterState(CDATA);
700
- parser.pos += 8;
701
- return true;
702
- }
703
- return false;
704
- }
705
-
706
- // src/states/CLOSE_TAG.ts
707
- var CLOSE_TAG = {
708
- name: "CLOSE_TAG",
709
- enter(parent, start) {
710
- this.endText();
711
- return {
712
- state: CLOSE_TAG,
713
- parent,
714
- start,
715
- end: start
716
- };
717
- },
718
- exit() {
719
- },
720
- char(code, closeTag) {
721
- if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
768
+ } else if (code === 61 /* EQUAL */ || code === 58 /* COLON */ && this.lookAtCharCodeAhead(1) === 61 /* EQUAL */ || code === 46 /* PERIOD */ && this.lookAheadFor("..")) {
769
+ attr.valueStart = this.pos;
770
+ this.forward = 0;
771
+ if (code === 58 /* COLON */) {
772
+ ensureAttrName(this, attr);
773
+ attr.bound = true;
774
+ this.pos += 2;
775
+ this.consumeWhitespace();
776
+ } else if (code === 46 /* PERIOD */) {
777
+ attr.spread = true;
778
+ this.pos += 3;
779
+ } else {
780
+ ensureAttrName(this, attr);
781
+ this.pos++;
782
+ this.consumeWhitespace();
783
+ }
784
+ attr.stage = 2 /* VALUE */;
785
+ const expr = this.enterState(states_exports.EXPRESSION);
786
+ expr.operators = true;
787
+ expr.terminatedByWhitespace = true;
788
+ expr.shouldTerminate = this.isConcise ? this.activeTag.stage === 4 /* ATTR_GROUP */ ? shouldTerminateConciseGroupedAttrValue : shouldTerminateConciseAttrValue : shouldTerminateHtmlAttrValue;
789
+ } else if (code === 40 /* OPEN_PAREN */) {
790
+ ensureAttrName(this, attr);
791
+ attr.stage = 3 /* ARGUMENT */;
792
+ this.pos++;
793
+ this.forward = 0;
794
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseParen;
795
+ } else if (code === 123 /* OPEN_CURLY_BRACE */ && attr.args) {
796
+ ensureAttrName(this, attr);
797
+ attr.stage = 4 /* BLOCK */;
722
798
  this.pos++;
799
+ this.forward = 0;
800
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
801
+ } else if (attr.stage === 0 /* UNKNOWN */) {
802
+ attr.stage = 1 /* NAME */;
803
+ this.forward = 0;
804
+ const expr = this.enterState(states_exports.EXPRESSION);
805
+ expr.terminatedByWhitespace = true;
806
+ expr.shouldTerminate = this.isConcise ? this.activeTag.stage === 4 /* ATTR_GROUP */ ? shouldTerminateConciseGroupedAttrName : shouldTerminateConciseAttrName : shouldTerminateHtmlAttrName;
807
+ } else {
723
808
  this.exitState();
724
- ensureExpectedCloseTag(this, closeTag);
725
809
  }
726
810
  },
727
811
  eol() {
812
+ if (this.isConcise) {
813
+ this.exitState();
814
+ }
728
815
  },
729
- eof(closeTag) {
730
- this.emitError(closeTag, 15 /* MALFORMED_CLOSE_TAG */, "EOF reached while parsing closing tag");
816
+ eof(attr) {
817
+ if (this.isConcise) {
818
+ this.exitState();
819
+ } else {
820
+ this.emitError(
821
+ attr,
822
+ 19 /* MALFORMED_OPEN_TAG */,
823
+ 'EOF reached while parsing attribute "' + (attr.name ? this.read(attr.name) : "default") + '" for the "' + this.read(this.activeTag.tagName) + '" tag'
824
+ );
825
+ }
731
826
  },
732
- return() {
827
+ return(child, attr) {
828
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
829
+ switch (attr.stage) {
830
+ case 1 /* NAME */: {
831
+ attr.name = {
832
+ start: child.start,
833
+ end: child.end
834
+ };
835
+ (_b = (_a = this.options).onAttrName) == null ? void 0 : _b.call(_a, attr.name);
836
+ break;
837
+ }
838
+ case 3 /* ARGUMENT */: {
839
+ if (attr.args) {
840
+ this.emitError(
841
+ child,
842
+ 1 /* INVALID_ATTRIBUTE_ARGUMENT */,
843
+ "An attribute can only have one set of arguments"
844
+ );
845
+ return;
846
+ }
847
+ const start = child.start - 1;
848
+ const end = ++this.pos;
849
+ const value = {
850
+ start: child.start,
851
+ end: child.end
852
+ };
853
+ if (this.consumeWhitespaceIfBefore("{")) {
854
+ attr.args = {
855
+ start,
856
+ end,
857
+ value
858
+ };
859
+ } else {
860
+ attr.args = true;
861
+ (_d = (_c = this.options).onAttrArgs) == null ? void 0 : _d.call(_c, {
862
+ start,
863
+ end,
864
+ value
865
+ });
866
+ }
867
+ break;
868
+ }
869
+ case 4 /* BLOCK */: {
870
+ const params = attr.args;
871
+ const start = params.start;
872
+ const end = ++this.pos;
873
+ (_f = (_e = this.options).onAttrMethod) == null ? void 0 : _f.call(_e, {
874
+ start,
875
+ end,
876
+ params,
877
+ body: {
878
+ start: child.start - 1,
879
+ end,
880
+ value: {
881
+ start: child.start,
882
+ end: child.end
883
+ }
884
+ }
885
+ });
886
+ this.exitState();
887
+ break;
888
+ }
889
+ case 2 /* VALUE */: {
890
+ if (child.start === child.end) {
891
+ return this.emitError(
892
+ child,
893
+ 3 /* INVALID_ATTRIBUTE_VALUE */,
894
+ "Missing value for attribute"
895
+ );
896
+ }
897
+ if (attr.spread) {
898
+ (_h = (_g = this.options).onAttrSpread) == null ? void 0 : _h.call(_g, {
899
+ start: attr.valueStart,
900
+ end: child.end,
901
+ value: {
902
+ start: child.start,
903
+ end: child.end
904
+ }
905
+ });
906
+ } else {
907
+ (_j = (_i = this.options).onAttrValue) == null ? void 0 : _j.call(_i, {
908
+ start: attr.valueStart,
909
+ end: child.end,
910
+ bound: attr.bound,
911
+ value: {
912
+ start: child.start,
913
+ end: child.end
914
+ }
915
+ });
916
+ }
917
+ this.exitState();
918
+ break;
919
+ }
920
+ }
733
921
  }
734
922
  };
735
- function checkForClosingTag(parser) {
923
+ function ensureAttrName(parser, attr) {
736
924
  var _a, _b;
737
- const curPos = parser.pos + 1;
738
- let match = !!parser.lookAheadFor("/>");
739
- let skip = 3;
740
- if (!match) {
741
- const { tagName } = parser.activeTag;
742
- const tagNameLen = tagName.end - tagName.start;
743
- if (tagNameLen) {
744
- skip += tagNameLen;
745
- match = parser.lookAheadFor("/", curPos) && parser.lookAheadFor(">", 1 + curPos + tagNameLen) && parser.matchAtPos(tagName, {
746
- start: 1 + curPos,
747
- end: 1 + curPos + tagNameLen
748
- }) || false;
749
- }
750
- }
751
- if (match) {
752
- parser.endText();
753
- (_b = (_a = parser.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
754
- start: curPos - 1,
755
- end: curPos + 1
925
+ if (!attr.name) {
926
+ (_b = (_a = parser.options).onAttrName) == null ? void 0 : _b.call(_a, {
927
+ start: attr.start,
928
+ end: attr.start
756
929
  });
757
- if (ensureExpectedCloseTag(parser, {
758
- start: parser.pos,
759
- end: parser.pos += skip
760
- })) {
761
- parser.exitState();
762
- }
763
- return true;
764
930
  }
765
- return false;
766
931
  }
767
- function ensureExpectedCloseTag(parser, closeTag) {
768
- const activeTag = parser.activeTag;
769
- const closeTagNameStart = closeTag.start + 2;
770
- const closeTagNameEnd = closeTag.end - 1;
771
- if (!activeTag) {
772
- parser.emitError(closeTag, 0 /* EXTRA_CLOSING_TAG */, 'The closing "' + parser.read({ start: closeTagNameStart, end: closeTagNameEnd }) + '" tag was not expected');
773
- return false;
932
+ function shouldTerminateHtmlAttrName(code, data, pos) {
933
+ switch (code) {
934
+ case 44 /* COMMA */:
935
+ case 61 /* EQUAL */:
936
+ case 40 /* OPEN_PAREN */:
937
+ case 62 /* CLOSE_ANGLE_BRACKET */:
938
+ return true;
939
+ case 58 /* COLON */:
940
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
941
+ case 47 /* FORWARD_SLASH */:
942
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
943
+ default:
944
+ return false;
774
945
  }
775
- const closeTagNamePos = {
776
- start: closeTagNameStart,
777
- end: closeTagNameEnd
778
- };
779
- if (closeTagNameStart < closeTagNameEnd) {
780
- if (!parser.matchAtPos(closeTagNamePos, activeTag.tagName.end > activeTag.tagName.start ? activeTag.tagName : "div")) {
781
- if (activeTag.shorthandEnd === void 0 || !parser.matchAtPos(closeTagNamePos, {
782
- start: activeTag.tagName.start,
783
- end: activeTag.shorthandEnd
784
- })) {
785
- parser.emitError(closeTag, 21 /* MISMATCHED_CLOSING_TAG */, 'The closing "' + parser.read(closeTagNamePos) + '" tag does not match the corresponding opening "' + (parser.read(activeTag.tagName) || "div") + '" tag');
786
- return false;
787
- }
788
- }
946
+ }
947
+ function shouldTerminateHtmlAttrValue(code, data, pos) {
948
+ switch (code) {
949
+ case 44 /* COMMA */:
950
+ return true;
951
+ case 47 /* FORWARD_SLASH */:
952
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
953
+ case 62 /* CLOSE_ANGLE_BRACKET */:
954
+ return pos === this.start || data.charCodeAt(pos - 1) !== 61 /* EQUAL */;
955
+ default:
956
+ return false;
957
+ }
958
+ }
959
+ function shouldTerminateConciseAttrName(code, data, pos) {
960
+ switch (code) {
961
+ case 44 /* COMMA */:
962
+ case 61 /* EQUAL */:
963
+ case 40 /* OPEN_PAREN */:
964
+ case 59 /* SEMICOLON */:
965
+ return true;
966
+ case 58 /* COLON */:
967
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
968
+ case 45 /* HYPHEN */:
969
+ return data.charCodeAt(pos + 1) === 45 /* HYPHEN */ && isWhitespaceCode(data.charCodeAt(pos - 1));
970
+ default:
971
+ return false;
972
+ }
973
+ }
974
+ function shouldTerminateConciseAttrValue(code, data, pos) {
975
+ switch (code) {
976
+ case 44 /* COMMA */:
977
+ case 59 /* SEMICOLON */:
978
+ return true;
979
+ case 45 /* HYPHEN */:
980
+ return data.charCodeAt(pos + 1) === 45 /* HYPHEN */ && isWhitespaceCode(data.charCodeAt(pos - 1));
981
+ default:
982
+ return false;
983
+ }
984
+ }
985
+ function shouldTerminateConciseGroupedAttrName(code, data, pos) {
986
+ switch (code) {
987
+ case 44 /* COMMA */:
988
+ case 61 /* EQUAL */:
989
+ case 40 /* OPEN_PAREN */:
990
+ case 93 /* CLOSE_SQUARE_BRACKET */:
991
+ return true;
992
+ case 58 /* COLON */:
993
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
994
+ default:
995
+ return false;
996
+ }
997
+ }
998
+ function shouldTerminateConciseGroupedAttrValue(code) {
999
+ switch (code) {
1000
+ case 44 /* COMMA */:
1001
+ case 93 /* CLOSE_SQUARE_BRACKET */:
1002
+ return true;
1003
+ default:
1004
+ return false;
789
1005
  }
790
- parser.closeTagEnd(closeTagNameEnd, closeTag.end, closeTagNamePos);
791
- return true;
792
1006
  }
793
1007
 
794
- // src/states/CONCISE_HTML_CONTENT.ts
795
- var CONCISE_HTML_CONTENT = {
796
- name: "CONCISE_HTML_CONTENT",
1008
+ // src/states/BEGIN_DELIMITED_HTML_BLOCK.ts
1009
+ var BEGIN_DELIMITED_HTML_BLOCK = {
1010
+ name: "BEGIN_DELIMITED_HTML_BLOCK",
797
1011
  enter(parent, start) {
798
- this.isConcise = true;
799
- this.indent = "";
800
1012
  return {
801
- state: CONCISE_HTML_CONTENT,
1013
+ state: BEGIN_DELIMITED_HTML_BLOCK,
802
1014
  parent,
803
1015
  start,
804
- end: start
1016
+ end: start,
1017
+ indent: this.indent,
1018
+ delimiter: ""
805
1019
  };
806
1020
  },
807
1021
  exit() {
808
1022
  },
809
- char(code) {
810
- if (isWhitespaceCode(code)) {
811
- this.indent += this.data[this.pos];
1023
+ char(code, block) {
1024
+ if (code === 45 /* HTML_BLOCK_DELIMITER */) {
1025
+ block.delimiter += "-";
812
1026
  } else {
813
- const curIndent = this.indent.length;
814
- const indentStart = this.pos - curIndent - 1;
815
- let parentTag = this.activeTag;
816
- while (parentTag && parentTag.indent.length >= curIndent) {
817
- this.closeTagEnd(indentStart, indentStart, void 0);
818
- parentTag = this.activeTag;
819
- }
820
- if (!parentTag && curIndent) {
821
- this.emitError(this.pos, 7 /* INVALID_INDENTATION */, "Line has extra indentation at the beginning");
822
- return;
1027
+ const startPos = this.pos;
1028
+ if (!this.consumeWhitespaceOnLine()) {
1029
+ this.pos = startPos + 1;
1030
+ this.forward = 0;
1031
+ this.beginHtmlBlock(void 0, true);
823
1032
  }
824
- if (parentTag) {
825
- if (parentTag.type === 1 /* text */ && code !== 45 /* HTML_BLOCK_DELIMITER */) {
826
- this.emitError(this.pos, 8 /* INVALID_LINE_START */, 'A line within a tag that only allows text content must begin with a "-" character');
827
- return;
828
- }
829
- if (parentTag.nestedIndent === void 0) {
1033
+ }
1034
+ },
1035
+ eol(len, block) {
1036
+ this.beginHtmlBlock(block.delimiter, false);
1037
+ handleDelimitedBlockEOL(this, len, block);
1038
+ },
1039
+ eof: htmlEOF,
1040
+ return() {
1041
+ }
1042
+ };
1043
+ function handleDelimitedEOL(parser, newLineLength, content) {
1044
+ if (content.singleLine) {
1045
+ parser.endText();
1046
+ parser.exitState();
1047
+ parser.exitState();
1048
+ return true;
1049
+ }
1050
+ if (content.delimiter) {
1051
+ handleDelimitedBlockEOL(parser, newLineLength, content);
1052
+ return true;
1053
+ }
1054
+ return false;
1055
+ }
1056
+ function handleDelimitedBlockEOL(parser, newLineLength, {
1057
+ indent,
1058
+ delimiter
1059
+ }) {
1060
+ const endHtmlBlockLookahead = indent + delimiter;
1061
+ if (parser.lookAheadFor(endHtmlBlockLookahead, parser.pos + newLineLength)) {
1062
+ parser.startText();
1063
+ parser.pos += newLineLength;
1064
+ parser.endText();
1065
+ parser.pos += endHtmlBlockLookahead.length;
1066
+ if (parser.consumeWhitespaceOnLine(0)) {
1067
+ parser.endText();
1068
+ parser.exitState();
1069
+ parser.exitState();
1070
+ } else {
1071
+ parser.emitError(
1072
+ parser.pos,
1073
+ 4 /* INVALID_CHARACTER */,
1074
+ "A concise mode closing block delimiter can only be followed by whitespace."
1075
+ );
1076
+ }
1077
+ } else if (parser.lookAheadFor(indent, parser.pos + newLineLength)) {
1078
+ parser.startText();
1079
+ parser.pos += indent.length;
1080
+ } else if (indent && !parser.onlyWhitespaceRemainsOnLine(newLineLength)) {
1081
+ parser.endText();
1082
+ parser.exitState();
1083
+ parser.exitState();
1084
+ } else {
1085
+ parser.startText();
1086
+ }
1087
+ }
1088
+
1089
+ // src/states/CDATA.ts
1090
+ var CDATA = {
1091
+ name: "CDATA",
1092
+ enter(parent, start) {
1093
+ return {
1094
+ state: CDATA,
1095
+ parent,
1096
+ start,
1097
+ end: start
1098
+ };
1099
+ },
1100
+ exit(cdata) {
1101
+ var _a, _b;
1102
+ (_b = (_a = this.options).onCDATA) == null ? void 0 : _b.call(_a, {
1103
+ start: cdata.start,
1104
+ end: cdata.end,
1105
+ value: {
1106
+ start: cdata.start + 9,
1107
+ end: cdata.end - 3
1108
+ }
1109
+ });
1110
+ },
1111
+ char(code) {
1112
+ if (code === 93 /* CLOSE_SQUARE_BRACKET */ && this.lookAheadFor("]>")) {
1113
+ this.pos += 3;
1114
+ this.exitState();
1115
+ return;
1116
+ }
1117
+ },
1118
+ eol() {
1119
+ },
1120
+ eof(cdata) {
1121
+ this.emitError(
1122
+ cdata,
1123
+ 14 /* MALFORMED_CDATA */,
1124
+ "EOF reached while parsing CDATA"
1125
+ );
1126
+ },
1127
+ return() {
1128
+ }
1129
+ };
1130
+ function checkForCDATA(parser) {
1131
+ if (parser.lookAheadFor("![CDATA[")) {
1132
+ parser.endText();
1133
+ parser.enterState(CDATA);
1134
+ parser.pos += 8;
1135
+ return true;
1136
+ }
1137
+ return false;
1138
+ }
1139
+
1140
+ // src/states/CLOSE_TAG.ts
1141
+ var CLOSE_TAG = {
1142
+ name: "CLOSE_TAG",
1143
+ enter(parent, start) {
1144
+ this.endText();
1145
+ return {
1146
+ state: CLOSE_TAG,
1147
+ parent,
1148
+ start,
1149
+ end: start
1150
+ };
1151
+ },
1152
+ exit() {
1153
+ },
1154
+ char(code, closeTag) {
1155
+ if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
1156
+ this.pos++;
1157
+ this.exitState();
1158
+ ensureExpectedCloseTag(this, closeTag);
1159
+ }
1160
+ },
1161
+ eol() {
1162
+ },
1163
+ eof(closeTag) {
1164
+ this.emitError(
1165
+ closeTag,
1166
+ 15 /* MALFORMED_CLOSE_TAG */,
1167
+ "EOF reached while parsing closing tag"
1168
+ );
1169
+ },
1170
+ return() {
1171
+ }
1172
+ };
1173
+ function checkForClosingTag(parser) {
1174
+ var _a, _b;
1175
+ const curPos = parser.pos + 1;
1176
+ let match = !!parser.lookAheadFor("/>");
1177
+ let skip = 3;
1178
+ if (!match) {
1179
+ const { tagName } = parser.activeTag;
1180
+ const tagNameLen = tagName.end - tagName.start;
1181
+ if (tagNameLen) {
1182
+ skip += tagNameLen;
1183
+ match = parser.lookAheadFor("/", curPos) && parser.lookAheadFor(">", 1 + curPos + tagNameLen) && parser.matchAtPos(tagName, {
1184
+ start: 1 + curPos,
1185
+ end: 1 + curPos + tagNameLen
1186
+ }) || false;
1187
+ }
1188
+ }
1189
+ if (match) {
1190
+ parser.endText();
1191
+ (_b = (_a = parser.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
1192
+ start: curPos - 1,
1193
+ end: curPos + 1
1194
+ });
1195
+ if (ensureExpectedCloseTag(parser, {
1196
+ start: parser.pos,
1197
+ end: parser.pos += skip
1198
+ })) {
1199
+ parser.exitState();
1200
+ }
1201
+ return true;
1202
+ }
1203
+ return false;
1204
+ }
1205
+ function ensureExpectedCloseTag(parser, closeTag) {
1206
+ const activeTag = parser.activeTag;
1207
+ const closeTagNameStart = closeTag.start + 2;
1208
+ const closeTagNameEnd = closeTag.end - 1;
1209
+ if (!activeTag) {
1210
+ parser.emitError(
1211
+ closeTag,
1212
+ 0 /* EXTRA_CLOSING_TAG */,
1213
+ 'The closing "' + parser.read({ start: closeTagNameStart, end: closeTagNameEnd }) + '" tag was not expected'
1214
+ );
1215
+ return false;
1216
+ }
1217
+ const closeTagNamePos = {
1218
+ start: closeTagNameStart,
1219
+ end: closeTagNameEnd
1220
+ };
1221
+ if (closeTagNameStart < closeTagNameEnd) {
1222
+ if (!parser.matchAtPos(
1223
+ closeTagNamePos,
1224
+ activeTag.tagName.end > activeTag.tagName.start ? activeTag.tagName : "div"
1225
+ )) {
1226
+ if (activeTag.shorthandEnd === void 0 || !parser.matchAtPos(closeTagNamePos, {
1227
+ start: activeTag.tagName.start,
1228
+ end: activeTag.shorthandEnd
1229
+ })) {
1230
+ parser.emitError(
1231
+ closeTag,
1232
+ 21 /* MISMATCHED_CLOSING_TAG */,
1233
+ 'The closing "' + parser.read(closeTagNamePos) + '" tag does not match the corresponding opening "' + (parser.read(activeTag.tagName) || "div") + '" tag'
1234
+ );
1235
+ return false;
1236
+ }
1237
+ }
1238
+ }
1239
+ parser.closeTagEnd(closeTagNameEnd, closeTag.end, closeTagNamePos);
1240
+ return true;
1241
+ }
1242
+
1243
+ // src/states/CONCISE_HTML_CONTENT.ts
1244
+ var CONCISE_HTML_CONTENT = {
1245
+ name: "CONCISE_HTML_CONTENT",
1246
+ enter(parent, start) {
1247
+ this.isConcise = true;
1248
+ this.indent = "";
1249
+ return {
1250
+ state: CONCISE_HTML_CONTENT,
1251
+ parent,
1252
+ start,
1253
+ end: start
1254
+ };
1255
+ },
1256
+ exit() {
1257
+ },
1258
+ char(code) {
1259
+ if (isWhitespaceCode(code)) {
1260
+ this.indent += this.data[this.pos];
1261
+ } else {
1262
+ const curIndent = this.indent.length;
1263
+ const indentStart = this.pos - curIndent - 1;
1264
+ let parentTag = this.activeTag;
1265
+ while (parentTag && parentTag.indent.length >= curIndent) {
1266
+ this.closeTagEnd(indentStart, indentStart, void 0);
1267
+ parentTag = this.activeTag;
1268
+ }
1269
+ if (!parentTag && curIndent) {
1270
+ this.emitError(
1271
+ this.pos,
1272
+ 7 /* INVALID_INDENTATION */,
1273
+ "Line has extra indentation at the beginning"
1274
+ );
1275
+ return;
1276
+ }
1277
+ if (parentTag) {
1278
+ if (parentTag.type === 1 /* text */ && code !== 45 /* HTML_BLOCK_DELIMITER */) {
1279
+ this.emitError(
1280
+ this.pos,
1281
+ 8 /* INVALID_LINE_START */,
1282
+ 'A line within a tag that only allows text content must begin with a "-" character'
1283
+ );
1284
+ return;
1285
+ }
1286
+ if (parentTag.nestedIndent === void 0) {
830
1287
  parentTag.nestedIndent = this.indent;
831
1288
  } else if (parentTag.nestedIndent !== this.indent) {
832
- this.emitError(this.pos, 7 /* INVALID_INDENTATION */, "Line indentation does match indentation of previous line");
1289
+ this.emitError(
1290
+ this.pos,
1291
+ 7 /* INVALID_INDENTATION */,
1292
+ "Line indentation does match indentation of previous line"
1293
+ );
833
1294
  return;
834
1295
  }
835
1296
  }
@@ -851,7 +1312,11 @@ var CONCISE_HTML_CONTENT = {
851
1312
  this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
852
1313
  this.pos--;
853
1314
  } else {
854
- this.emitError(this.pos, 8 /* INVALID_LINE_START */, 'A line in concise mode cannot start with a single hyphen. Use "--" instead. See: https://github.com/marko-js/htmljs-parser/issues/43');
1315
+ this.emitError(
1316
+ this.pos,
1317
+ 8 /* INVALID_LINE_START */,
1318
+ 'A line in concise mode cannot start with a single hyphen. Use "--" instead. See: https://github.com/marko-js/htmljs-parser/issues/43'
1319
+ );
855
1320
  }
856
1321
  return;
857
1322
  case 47 /* FORWARD_SLASH */:
@@ -865,7 +1330,11 @@ var CONCISE_HTML_CONTENT = {
865
1330
  this.pos++;
866
1331
  return;
867
1332
  default:
868
- this.emitError(this.pos, 8 /* INVALID_LINE_START */, 'A line in concise mode cannot start with "/" unless it starts a "//" or "/*" comment');
1333
+ this.emitError(
1334
+ this.pos,
1335
+ 8 /* INVALID_LINE_START */,
1336
+ 'A line in concise mode cannot start with "/" unless it starts a "//" or "/*" comment'
1337
+ );
869
1338
  return;
870
1339
  }
871
1340
  }
@@ -902,7 +1371,11 @@ var CONCISE_HTML_CONTENT = {
902
1371
  }
903
1372
  });
904
1373
  if (!this.consumeWhitespaceOnLine(0)) {
905
- this.emitError(this.pos, 4 /* INVALID_CHARACTER */, "In concise mode a javascript comment block can only be followed by whitespace characters and a newline.");
1374
+ this.emitError(
1375
+ this.pos,
1376
+ 4 /* INVALID_CHARACTER */,
1377
+ "In concise mode a javascript comment block can only be followed by whitespace characters and a newline."
1378
+ );
906
1379
  }
907
1380
  break;
908
1381
  }
@@ -936,7 +1409,11 @@ var DECLARATION = {
936
1409
  eol() {
937
1410
  },
938
1411
  eof(declaration) {
939
- this.emitError(declaration, 17 /* MALFORMED_DECLARATION */, "EOF reached while parsing declaration");
1412
+ this.emitError(
1413
+ declaration,
1414
+ 17 /* MALFORMED_DECLARATION */,
1415
+ "EOF reached while parsing declaration"
1416
+ );
940
1417
  },
941
1418
  return() {
942
1419
  }
@@ -987,16 +1464,29 @@ var DTD = {
987
1464
  eol() {
988
1465
  },
989
1466
  eof(documentType) {
990
- this.emitError(documentType, 18 /* MALFORMED_DOCUMENT_TYPE */, "EOF reached while parsing document type");
1467
+ this.emitError(
1468
+ documentType,
1469
+ 18 /* MALFORMED_DOCUMENT_TYPE */,
1470
+ "EOF reached while parsing document type"
1471
+ );
991
1472
  },
992
1473
  return() {
993
1474
  }
994
1475
  };
995
1476
 
996
1477
  // src/states/EXPRESSION.ts
997
- var htmlAttrsPattern = buildPattern(0 /* HTML_ATTRS */);
998
- var conciseAttrsPattern = buildPattern(1 /* CONCISE_ATTRS */);
999
- var conciseAttrsGroupPattern = buildPattern(2 /* CONCISE_ATTRS_GROUP */);
1478
+ var shouldTerminate = () => false;
1479
+ var unaryKeywords = [
1480
+ "async",
1481
+ "await",
1482
+ "keyof",
1483
+ "class",
1484
+ "function",
1485
+ "new",
1486
+ "typeof",
1487
+ "void"
1488
+ ];
1489
+ var binaryKeywords = ["instanceof", "in", "as", "extends"];
1000
1490
  var EXPRESSION = {
1001
1491
  name: "EXPRESSION",
1002
1492
  enter(parent, start) {
@@ -1006,8 +1496,8 @@ var EXPRESSION = {
1006
1496
  start,
1007
1497
  end: start,
1008
1498
  groupStack: [],
1009
- terminator: -1,
1010
- skipOperators: false,
1499
+ shouldTerminate,
1500
+ operators: false,
1011
1501
  terminatedByEOL: false,
1012
1502
  terminatedByWhitespace: false
1013
1503
  };
@@ -1017,12 +1507,12 @@ var EXPRESSION = {
1017
1507
  char(code, expression) {
1018
1508
  if (!expression.groupStack.length) {
1019
1509
  if (expression.terminatedByWhitespace && isWhitespaceCode(code)) {
1020
- if (!checkForOperators(this, expression)) {
1510
+ if (!checkForOperators(this, expression, false)) {
1021
1511
  this.exitState();
1022
1512
  }
1023
1513
  return;
1024
1514
  }
1025
- if (typeof expression.terminator === "number" ? expression.terminator === code : checkForTerminators(this, code, expression.terminator)) {
1515
+ if (expression.shouldTerminate(code, this.data, this.pos)) {
1026
1516
  this.exitState();
1027
1517
  return;
1028
1518
  }
@@ -1048,7 +1538,7 @@ var EXPRESSION = {
1048
1538
  this.pos++;
1049
1539
  break;
1050
1540
  default: {
1051
- if (canCharCodeBeFollowedByDivision(this.getPreviousNonWhitespaceCharCode())) {
1541
+ if (canFollowDivision(this.getPreviousNonWhitespaceCharCode())) {
1052
1542
  this.pos++;
1053
1543
  this.consumeWhitespace();
1054
1544
  } else {
@@ -1071,18 +1561,26 @@ var EXPRESSION = {
1071
1561
  case 93 /* CLOSE_SQUARE_BRACKET */:
1072
1562
  case 125 /* CLOSE_CURLY_BRACE */: {
1073
1563
  if (!expression.groupStack.length) {
1074
- return this.emitError(expression, 6 /* INVALID_EXPRESSION */, 'Mismatched group. A closing "' + String.fromCharCode(code) + '" character was found but it is not matched with a corresponding opening character.');
1564
+ return this.emitError(
1565
+ expression,
1566
+ 6 /* INVALID_EXPRESSION */,
1567
+ 'Mismatched group. A closing "' + String.fromCharCode(code) + '" character was found but it is not matched with a corresponding opening character.'
1568
+ );
1075
1569
  }
1076
1570
  const expectedCode = expression.groupStack.pop();
1077
1571
  if (expectedCode !== code) {
1078
- return this.emitError(expression, 6 /* INVALID_EXPRESSION */, 'Mismatched group. A "' + String.fromCharCode(code) + '" character was found when "' + String.fromCharCode(expectedCode) + '" was expected.');
1572
+ return this.emitError(
1573
+ expression,
1574
+ 6 /* INVALID_EXPRESSION */,
1575
+ 'Mismatched group. A "' + String.fromCharCode(code) + '" character was found when "' + String.fromCharCode(expectedCode) + '" was expected.'
1576
+ );
1079
1577
  }
1080
1578
  break;
1081
1579
  }
1082
1580
  }
1083
1581
  },
1084
1582
  eol(_, expression) {
1085
- if (!expression.groupStack.length && (expression.terminatedByEOL || expression.terminatedByWhitespace) && !checkForOperators(this, expression)) {
1583
+ if (!expression.groupStack.length && (expression.terminatedByEOL || expression.terminatedByWhitespace) && !checkForOperators(this, expression, true)) {
1086
1584
  this.exitState();
1087
1585
  }
1088
1586
  },
@@ -1095,69 +1593,216 @@ var EXPRESSION = {
1095
1593
  case states_exports.ATTRIBUTE: {
1096
1594
  const attr = parent;
1097
1595
  if (!attr.spread && !attr.name) {
1098
- return this.emitError(expression, 19 /* MALFORMED_OPEN_TAG */, 'EOF reached while parsing attribute name for the "' + this.read(this.activeTag.tagName) + '" tag');
1596
+ return this.emitError(
1597
+ expression,
1598
+ 19 /* MALFORMED_OPEN_TAG */,
1599
+ 'EOF reached while parsing attribute name for the "' + this.read(this.activeTag.tagName) + '" tag'
1600
+ );
1099
1601
  }
1100
- return this.emitError(expression, 19 /* MALFORMED_OPEN_TAG */, `EOF reached while parsing attribute value for the ${attr.spread ? "..." : attr.name ? `"${this.read(attr.name)}"` : `"default"`} attribute`);
1602
+ return this.emitError(
1603
+ expression,
1604
+ 19 /* MALFORMED_OPEN_TAG */,
1605
+ `EOF reached while parsing attribute value for the ${attr.spread ? "..." : attr.name ? `"${this.read(attr.name)}"` : `"default"`} attribute`
1606
+ );
1101
1607
  }
1102
1608
  case states_exports.TAG_NAME:
1103
- return this.emitError(expression, 19 /* MALFORMED_OPEN_TAG */, "EOF reached while parsing tag name");
1609
+ return this.emitError(
1610
+ expression,
1611
+ 19 /* MALFORMED_OPEN_TAG */,
1612
+ "EOF reached while parsing tag name"
1613
+ );
1104
1614
  case states_exports.PLACEHOLDER:
1105
- return this.emitError(expression, 20 /* MALFORMED_PLACEHOLDER */, "EOF reached while parsing placeholder");
1615
+ return this.emitError(
1616
+ expression,
1617
+ 20 /* MALFORMED_PLACEHOLDER */,
1618
+ "EOF reached while parsing placeholder"
1619
+ );
1106
1620
  }
1107
- return this.emitError(expression, 6 /* INVALID_EXPRESSION */, "EOF reached while parsing expression");
1621
+ return this.emitError(
1622
+ expression,
1623
+ 6 /* INVALID_EXPRESSION */,
1624
+ "EOF reached while parsing expression"
1625
+ );
1108
1626
  }
1109
1627
  },
1110
1628
  return() {
1111
1629
  }
1112
1630
  };
1113
- function buildPattern(type) {
1114
- const space = type === 1 /* CONCISE_ATTRS */ ? "[ \\t]" : "\\s";
1115
- const binary = `(?:[!~*%&^|?<]+=*)+|:+(?!=)|[>/+=-]+=|=>|(?<!\\+)[ \\t]*\\+(?:\\s*\\+\\s*\\+)*\\s*(?!\\+)|(?<!-)-${type === 1 /* CONCISE_ATTRS */ ? "" : "(?:\\s*-\\s*-)*\\s*"}(?!-)|(?<!\\.)\\.(?!\\.)|>${type === 0 /* HTML_ATTRS */ ? "{2,}" : "+"}|[ \\t]+(?:in(?:stanceof)?|as|extends)(?=[ \\t]+[^=/,;:>])`;
1116
- const unary = "\\b(?<![.]\\s*)(?:a(?:sync|wait)|keyof|class|function|new|typeof|void)\\b";
1117
- const lookAheadPattern = `${space}*(?:${binary})\\s*|${space}+(?=[{(]|/[^>])`;
1118
- const lookBehindPattern = `(?<=${unary}|${binary})`;
1119
- return new RegExp(`${lookAheadPattern}|${lookBehindPattern}`, "ym");
1120
- }
1121
- function checkForOperators(parser, expression) {
1122
- var _a;
1123
- if (expression.skipOperators) {
1631
+ function checkForOperators(parser, expression, eol) {
1632
+ if (!expression.operators)
1124
1633
  return false;
1634
+ const { pos, data } = parser;
1635
+ if (lookBehindForOperator(data, pos) !== -1) {
1636
+ parser.consumeWhitespace();
1637
+ parser.forward = 0;
1638
+ return true;
1125
1639
  }
1126
- const pattern = parser.isConcise ? ((_a = parser.activeTag) == null ? void 0 : _a.stage) === states_exports.TAG_STAGE.ATTR_GROUP ? conciseAttrsGroupPattern : conciseAttrsPattern : expression.terminatedByEOL ? conciseAttrsPattern : htmlAttrsPattern;
1127
- pattern.lastIndex = parser.pos;
1128
- const matches = pattern.exec(parser.data);
1129
- if (matches) {
1130
- const [match] = matches;
1131
- if (match.length === 0) {
1132
- parser.consumeWhitespace();
1133
- } else {
1134
- parser.pos += match.length;
1640
+ const terminatedByEOL = expression.terminatedByEOL || parser.isConcise;
1641
+ if (!(terminatedByEOL && eol)) {
1642
+ const nextNonSpace = lookAheadWhile(
1643
+ terminatedByEOL ? isIndentCode : isWhitespaceCode,
1644
+ data,
1645
+ pos + 1
1646
+ );
1647
+ if (!expression.shouldTerminate(
1648
+ data.charCodeAt(nextNonSpace),
1649
+ data,
1650
+ nextNonSpace
1651
+ )) {
1652
+ const lookAheadPos = lookAheadForOperator(data, nextNonSpace);
1653
+ if (lookAheadPos !== -1) {
1654
+ parser.pos = lookAheadPos;
1655
+ parser.forward = 0;
1656
+ return true;
1657
+ }
1135
1658
  }
1136
- parser.forward = 0;
1137
- } else {
1138
- return false;
1139
1659
  }
1140
- return true;
1660
+ return false;
1141
1661
  }
1142
- function checkForTerminators(parser, code, terminators) {
1143
- outer:
1144
- for (const terminator of terminators) {
1145
- if (typeof terminator === "number") {
1146
- if (code === terminator)
1147
- return true;
1148
- } else {
1149
- if (terminator[0] === code) {
1150
- for (let i = terminator.length; i-- > 1; ) {
1151
- if (parser.data.charCodeAt(parser.pos + i) !== terminator[i])
1152
- continue outer;
1153
- }
1154
- return true;
1662
+ function lookBehindForOperator(data, pos) {
1663
+ const curPos = pos - 1;
1664
+ const code = data.charCodeAt(curPos);
1665
+ switch (code) {
1666
+ case 38 /* AMPERSAND */:
1667
+ case 42 /* ASTERISK */:
1668
+ case 94 /* CARET */:
1669
+ case 58 /* COLON */:
1670
+ case 61 /* EQUAL */:
1671
+ case 33 /* EXCLAMATION */:
1672
+ case 60 /* OPEN_ANGLE_BRACKET */:
1673
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1674
+ case 37 /* PERCENT */:
1675
+ case 46 /* PERIOD */:
1676
+ case 124 /* PIPE */:
1677
+ case 63 /* QUESTION */:
1678
+ case 126 /* TILDE */:
1679
+ return curPos;
1680
+ case 43 /* PLUS */:
1681
+ case 45 /* HYPHEN */: {
1682
+ if (data.charCodeAt(curPos - 1) === code) {
1683
+ return lookBehindForOperator(
1684
+ data,
1685
+ lookBehindWhile(isWhitespaceCode, data, curPos - 2)
1686
+ );
1687
+ }
1688
+ return curPos;
1689
+ }
1690
+ default: {
1691
+ for (const keyword of unaryKeywords) {
1692
+ const keywordPos = lookBehindFor(data, curPos, keyword);
1693
+ if (keywordPos !== -1) {
1694
+ return data.charCodeAt(keywordPos - 1) === 46 /* PERIOD */ ? -1 : keywordPos;
1695
+ }
1696
+ }
1697
+ return -1;
1698
+ }
1699
+ }
1700
+ }
1701
+ function lookAheadForOperator(data, pos) {
1702
+ switch (data.charCodeAt(pos)) {
1703
+ case 38 /* AMPERSAND */:
1704
+ case 42 /* ASTERISK */:
1705
+ case 94 /* CARET */:
1706
+ case 33 /* EXCLAMATION */:
1707
+ case 60 /* OPEN_ANGLE_BRACKET */:
1708
+ case 37 /* PERCENT */:
1709
+ case 124 /* PIPE */:
1710
+ case 63 /* QUESTION */:
1711
+ case 126 /* TILDE */:
1712
+ case 43 /* PLUS */:
1713
+ case 45 /* HYPHEN */:
1714
+ case 58 /* COLON */:
1715
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1716
+ case 61 /* EQUAL */:
1717
+ return pos + 1;
1718
+ case 47 /* FORWARD_SLASH */:
1719
+ case 123 /* OPEN_CURLY_BRACE */:
1720
+ case 40 /* OPEN_PAREN */:
1721
+ return pos;
1722
+ case 46 /* PERIOD */:
1723
+ return data.charCodeAt(pos + 1) === 46 /* PERIOD */ ? -1 : pos + 1;
1724
+ default: {
1725
+ for (const keyword of binaryKeywords) {
1726
+ let nextPos = lookAheadFor(data, pos, keyword);
1727
+ if (nextPos === -1)
1728
+ continue;
1729
+ const max = data.length - 1;
1730
+ if (nextPos === max)
1731
+ return -1;
1732
+ let nextCode = data.charCodeAt(nextPos + 1);
1733
+ if (isWhitespaceCode(nextCode)) {
1734
+ nextPos = lookAheadWhile(isWhitespaceCode, data, nextPos + 2);
1735
+ if (nextPos === max)
1736
+ return -1;
1737
+ nextCode = data.charCodeAt(nextPos);
1738
+ } else if (isWordCode(nextCode)) {
1739
+ return -1;
1740
+ }
1741
+ switch (nextCode) {
1742
+ case 58 /* COLON */:
1743
+ case 44 /* COMMA */:
1744
+ case 61 /* EQUAL */:
1745
+ case 47 /* FORWARD_SLASH */:
1746
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1747
+ case 59 /* SEMICOLON */:
1748
+ return -1;
1749
+ default:
1750
+ return nextPos;
1155
1751
  }
1156
1752
  }
1753
+ return -1;
1157
1754
  }
1755
+ }
1756
+ }
1757
+ function canFollowDivision(code) {
1758
+ return isWordCode(code) || code === 37 /* PERCENT */ || code === 41 /* CLOSE_PAREN */ || code === 46 /* PERIOD */ || code === 60 /* OPEN_ANGLE_BRACKET */ || code === 93 /* CLOSE_SQUARE_BRACKET */ || code === 125 /* CLOSE_CURLY_BRACE */;
1759
+ }
1760
+ function isWordCode(code) {
1761
+ return code >= 65 /* UPPER_A */ && code <= 90 /* UPPER_Z */ || code >= 97 /* LOWER_A */ && code <= 122 /* LOWER_Z */ || code >= 48 /* NUMBER_0 */ && code <= 57 /* NUMBER_9 */ || code === 95 /* UNDERSCORE */;
1762
+ }
1763
+ function isIndentCode(code) {
1764
+ return code === 9 /* TAB */ || code === 32 /* SPACE */;
1765
+ }
1766
+ function lookAheadWhile(match, data, pos) {
1767
+ const max = data.length;
1768
+ for (let i = pos; i < max; i++) {
1769
+ if (!match(data.charCodeAt(i)))
1770
+ return i;
1771
+ }
1772
+ return max - 1;
1773
+ }
1774
+ function lookBehindWhile(match, data, pos) {
1775
+ let i = pos;
1776
+ do {
1777
+ if (!match(data.charCodeAt(i))) {
1778
+ return i + 1;
1779
+ }
1780
+ } while (i--);
1781
+ return 0;
1782
+ }
1783
+ function lookBehindFor(data, pos, str) {
1784
+ let i = str.length;
1785
+ const endPos = pos - i + 1;
1786
+ if (endPos < 0)
1787
+ return -1;
1788
+ while (i--) {
1789
+ if (data.charCodeAt(endPos + i) !== str.charCodeAt(i)) {
1790
+ return -1;
1791
+ }
1792
+ }
1793
+ return endPos;
1158
1794
  }
1159
- function canCharCodeBeFollowedByDivision(code) {
1160
- return code >= 48 /* NUMBER_0 */ && code <= 57 /* NUMBER_9 */ || code >= 65 /* UPPER_A */ && code <= 90 /* UPPER_Z */ || code >= 97 /* LOWER_A */ && code <= 122 /* LOWER_Z */ || code === 37 /* PERCENT */ || code === 41 /* CLOSE_PAREN */ || code === 46 /* PERIOD */ || code === 60 /* OPEN_ANGLE_BRACKET */ || code === 93 /* CLOSE_SQUARE_BRACKET */ || code === 125 /* CLOSE_CURLY_BRACE */;
1795
+ function lookAheadFor(data, pos, str) {
1796
+ let i = str.length;
1797
+ const endPos = pos + i;
1798
+ if (endPos > data.length)
1799
+ return -1;
1800
+ while (i--) {
1801
+ if (data.charCodeAt(pos + i) !== str.charCodeAt(i)) {
1802
+ return -1;
1803
+ }
1804
+ }
1805
+ return endPos - 1;
1161
1806
  }
1162
1807
 
1163
1808
  // src/states/HTML_COMMENT.ts
@@ -1198,7 +1843,11 @@ var HTML_COMMENT = {
1198
1843
  eol() {
1199
1844
  },
1200
1845
  eof(comment) {
1201
- this.emitError(comment, 16 /* MALFORMED_COMMENT */, "EOF reached while parsing comment");
1846
+ this.emitError(
1847
+ comment,
1848
+ 16 /* MALFORMED_COMMENT */,
1849
+ "EOF reached while parsing comment"
1850
+ );
1202
1851
  },
1203
1852
  return() {
1204
1853
  }
@@ -1372,11 +2021,10 @@ var INLINE_SCRIPT = {
1372
2021
  if (code === 123 /* OPEN_CURLY_BRACE */) {
1373
2022
  inlineScript.block = true;
1374
2023
  this.pos++;
1375
- const expr = this.enterState(states_exports.EXPRESSION);
1376
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
1377
- expr.skipOperators = true;
2024
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1378
2025
  } else {
1379
2026
  const expr = this.enterState(states_exports.EXPRESSION);
2027
+ expr.operators = true;
1380
2028
  expr.terminatedByEOL = true;
1381
2029
  }
1382
2030
  },
@@ -1411,7 +2059,11 @@ var JS_COMMENT_BLOCK = {
1411
2059
  eol() {
1412
2060
  },
1413
2061
  eof(comment) {
1414
- this.emitError(comment, 16 /* MALFORMED_COMMENT */, "EOF reached while parsing multi-line JavaScript comment");
2062
+ this.emitError(
2063
+ comment,
2064
+ 16 /* MALFORMED_COMMENT */,
2065
+ "EOF reached while parsing multi-line JavaScript comment"
2066
+ );
1415
2067
  },
1416
2068
  return() {
1417
2069
  }
@@ -1432,8 +2084,8 @@ var JS_COMMENT_LINE = {
1432
2084
  },
1433
2085
  char(code) {
1434
2086
  var _a;
1435
- if (!this.isConcise && code === 60 /* OPEN_ANGLE_BRACKET */ && ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */) {
1436
- states_exports.checkForClosingTag(this);
2087
+ if (!this.isConcise && code === 60 /* OPEN_ANGLE_BRACKET */ && ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ && states_exports.checkForClosingTag(this)) {
2088
+ this.exitState();
1437
2089
  }
1438
2090
  },
1439
2091
  eol() {
@@ -1465,7 +2117,7 @@ var PARSED_TEXT_CONTENT = {
1465
2117
  char(code) {
1466
2118
  switch (code) {
1467
2119
  case 60 /* OPEN_ANGLE_BRACKET */:
1468
- if (this.isConcise || !(states_exports.checkForClosingTag(this) || states_exports.checkForCDATA(this))) {
2120
+ if (this.isConcise || !states_exports.checkForClosingTag(this)) {
1469
2121
  this.startText();
1470
2122
  }
1471
2123
  break;
@@ -1534,7 +2186,11 @@ var PLACEHOLDER = {
1534
2186
  },
1535
2187
  return(child) {
1536
2188
  if (child.start === child.end) {
1537
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2189
+ this.emitError(
2190
+ child,
2191
+ 20 /* MALFORMED_PLACEHOLDER */,
2192
+ "Invalid placeholder, the expression cannot be missing"
2193
+ );
1538
2194
  }
1539
2195
  this.pos++;
1540
2196
  this.exitState();
@@ -1574,7 +2230,7 @@ function checkForPlaceholder(parser, code) {
1574
2230
  parser.enterState(PLACEHOLDER).escape = escape;
1575
2231
  parser.pos += escape ? 2 : 3;
1576
2232
  parser.forward = 0;
1577
- parser.enterState(states_exports.EXPRESSION).terminator = 125 /* CLOSE_CURLY_BRACE */;
2233
+ parser.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1578
2234
  return true;
1579
2235
  }
1580
2236
  }
@@ -1608,10 +2264,18 @@ var REGULAR_EXPRESSION = {
1608
2264
  }
1609
2265
  },
1610
2266
  eol(_, regExp) {
1611
- this.emitError(regExp, 9 /* INVALID_REGULAR_EXPRESSION */, "EOL reached while parsing regular expression");
2267
+ this.emitError(
2268
+ regExp,
2269
+ 9 /* INVALID_REGULAR_EXPRESSION */,
2270
+ "EOL reached while parsing regular expression"
2271
+ );
1612
2272
  },
1613
2273
  eof(regExp) {
1614
- this.emitError(regExp, 9 /* INVALID_REGULAR_EXPRESSION */, "EOF reached while parsing regular expression");
2274
+ this.emitError(
2275
+ regExp,
2276
+ 9 /* INVALID_REGULAR_EXPRESSION */,
2277
+ "EOF reached while parsing regular expression"
2278
+ );
1615
2279
  },
1616
2280
  return() {
1617
2281
  }
@@ -1645,7 +2309,11 @@ var STRING = {
1645
2309
  eol() {
1646
2310
  },
1647
2311
  eof(string) {
1648
- this.emitError(string, 10 /* INVALID_STRING */, "EOF reached while parsing string expression");
2312
+ this.emitError(
2313
+ string,
2314
+ 10 /* INVALID_STRING */,
2315
+ "EOF reached while parsing string expression"
2316
+ );
1649
2317
  },
1650
2318
  return() {
1651
2319
  }
@@ -1673,7 +2341,11 @@ var TAG_NAME = {
1673
2341
  switch (tagName.shorthandCode) {
1674
2342
  case 35 /* NUMBER_SIGN */:
1675
2343
  if (this.activeTag.hasShorthandId) {
1676
- return this.emitError(tagName, 12 /* INVALID_TAG_SHORTHAND */, "Multiple shorthand ID parts are not allowed on the same tag");
2344
+ return this.emitError(
2345
+ tagName,
2346
+ 12 /* INVALID_TAG_SHORTHAND */,
2347
+ "Multiple shorthand ID parts are not allowed on the same tag"
2348
+ );
1677
2349
  }
1678
2350
  this.activeTag.hasShorthandId = true;
1679
2351
  (_b = (_a = this.options).onTagShorthandId) == null ? void 0 : _b.call(_a, {
@@ -1704,12 +2376,26 @@ var TAG_NAME = {
1704
2376
  tag.type = tagType;
1705
2377
  if (tagType === 3 /* statement */) {
1706
2378
  if (!tag.concise) {
1707
- return this.emitError(tagName, 24 /* RESERVED_TAG_NAME */, `The "${this.read(tagName)}" tag is reserved and cannot be used as an HTML tag.`);
2379
+ return this.emitError(
2380
+ tagName,
2381
+ 24 /* RESERVED_TAG_NAME */,
2382
+ `The "${this.read(
2383
+ tagName
2384
+ )}" tag is reserved and cannot be used as an HTML tag.`
2385
+ );
1708
2386
  }
1709
2387
  if (tag.parentTag) {
1710
- return this.emitError(tagName, 25 /* ROOT_TAG_ONLY */, `"${this.read(tagName)}" can only be used at the root of the template.`);
2388
+ return this.emitError(
2389
+ tagName,
2390
+ 25 /* ROOT_TAG_ONLY */,
2391
+ `"${this.read(
2392
+ tagName
2393
+ )}" can only be used at the root of the template.`
2394
+ );
1711
2395
  }
1712
- this.enterState(states_exports.EXPRESSION).terminatedByEOL = true;
2396
+ const expr = this.enterState(states_exports.EXPRESSION);
2397
+ expr.operators = true;
2398
+ expr.terminatedByEOL = true;
1713
2399
  }
1714
2400
  }
1715
2401
  break;
@@ -1720,7 +2406,7 @@ var TAG_NAME = {
1720
2406
  if (code === 36 /* DOLLAR */ && this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
1721
2407
  this.pos += 2;
1722
2408
  this.forward = 0;
1723
- this.enterState(states_exports.EXPRESSION).terminator = 125 /* CLOSE_CURLY_BRACE */;
2409
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1724
2410
  } else if (isWhitespaceCode(code) || code === 61 /* EQUAL */ || code === 58 /* COLON */ && this.lookAtCharCodeAhead(1) === 61 /* EQUAL */ || code === 40 /* OPEN_PAREN */ || code === 47 /* FORWARD_SLASH */ || code === 124 /* PIPE */ || (this.isConcise ? code === 59 /* SEMICOLON */ : code === 62 /* CLOSE_ANGLE_BRACKET */)) {
1725
2411
  this.activeTag.shorthandEnd = this.pos;
1726
2412
  this.exitState();
@@ -1742,7 +2428,11 @@ var TAG_NAME = {
1742
2428
  if (child.terminatedByEOL)
1743
2429
  return;
1744
2430
  if (child.start === child.end) {
1745
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2431
+ this.emitError(
2432
+ child,
2433
+ 20 /* MALFORMED_PLACEHOLDER */,
2434
+ "Invalid placeholder, the expression cannot be missing"
2435
+ );
1746
2436
  }
1747
2437
  const { quasis, expressions } = tagName;
1748
2438
  const start = child.start - 2;
@@ -1775,334 +2465,43 @@ var TEMPLATE_STRING = {
1775
2465
  exit() {
1776
2466
  },
1777
2467
  char(code) {
1778
- if (code === 36 /* DOLLAR */ && this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
1779
- this.pos++;
1780
- const expr = this.enterState(states_exports.EXPRESSION);
1781
- expr.skipOperators = true;
1782
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
1783
- } else {
1784
- if (code === 92 /* BACK_SLASH */) {
2468
+ switch (code) {
2469
+ case 36 /* DOLLAR */:
2470
+ if (this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
2471
+ this.pos++;
2472
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
2473
+ }
2474
+ break;
2475
+ case 92 /* BACK_SLASH */:
1785
2476
  this.pos++;
1786
- } else if (code === 96 /* BACKTICK */) {
2477
+ break;
2478
+ case 96 /* BACKTICK */:
1787
2479
  this.pos++;
1788
2480
  this.exitState();
1789
- }
2481
+ break;
1790
2482
  }
1791
2483
  },
1792
2484
  eof(templateString) {
1793
- this.emitError(templateString, 13 /* INVALID_TEMPLATE_STRING */, "EOF reached while parsing template string expression");
2485
+ this.emitError(
2486
+ templateString,
2487
+ 13 /* INVALID_TEMPLATE_STRING */,
2488
+ "EOF reached while parsing template string expression"
2489
+ );
1794
2490
  },
1795
2491
  eol() {
1796
2492
  },
1797
2493
  return(child) {
1798
2494
  if (child.start === child.end) {
1799
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2495
+ this.emitError(
2496
+ child,
2497
+ 20 /* MALFORMED_PLACEHOLDER */,
2498
+ "Invalid placeholder, the expression cannot be missing"
2499
+ );
1800
2500
  }
1801
2501
  this.pos++;
1802
2502
  }
1803
2503
  };
1804
2504
 
1805
- // src/states/OPEN_TAG.ts
1806
- var TAG_STAGE = /* @__PURE__ */ ((TAG_STAGE2) => {
1807
- TAG_STAGE2[TAG_STAGE2["UNKNOWN"] = 0] = "UNKNOWN";
1808
- TAG_STAGE2[TAG_STAGE2["VAR"] = 1] = "VAR";
1809
- TAG_STAGE2[TAG_STAGE2["ARGUMENT"] = 2] = "ARGUMENT";
1810
- TAG_STAGE2[TAG_STAGE2["PARAMS"] = 3] = "PARAMS";
1811
- TAG_STAGE2[TAG_STAGE2["ATTR_GROUP"] = 4] = "ATTR_GROUP";
1812
- return TAG_STAGE2;
1813
- })(TAG_STAGE || {});
1814
- var CONCISE_TAG_VAR_TERMINATORS = [
1815
- 59 /* SEMICOLON */,
1816
- 40 /* OPEN_PAREN */,
1817
- 124 /* PIPE */,
1818
- 61 /* EQUAL */,
1819
- 44 /* COMMA */,
1820
- [58 /* COLON */, 61 /* EQUAL */]
1821
- ];
1822
- var HTML_TAG_VAR_TERMINATORS = [
1823
- 62 /* CLOSE_ANGLE_BRACKET */,
1824
- 40 /* OPEN_PAREN */,
1825
- 124 /* PIPE */,
1826
- 61 /* EQUAL */,
1827
- 44 /* COMMA */,
1828
- [58 /* COLON */, 61 /* EQUAL */],
1829
- [47 /* FORWARD_SLASH */, 62 /* CLOSE_ANGLE_BRACKET */]
1830
- ];
1831
- var OPEN_TAG = {
1832
- name: "OPEN_TAG",
1833
- enter(parent, start) {
1834
- const tag = this.activeTag = {
1835
- state: OPEN_TAG,
1836
- type: 0 /* html */,
1837
- parent,
1838
- start,
1839
- end: start,
1840
- stage: 0 /* UNKNOWN */,
1841
- parentTag: this.activeTag,
1842
- nestedIndent: void 0,
1843
- indent: this.indent,
1844
- hasShorthandId: false,
1845
- hasArgs: false,
1846
- hasAttrs: false,
1847
- selfClosed: false,
1848
- shorthandEnd: -1,
1849
- tagName: void 0,
1850
- concise: this.isConcise,
1851
- beginMixedMode: this.beginMixedMode || this.endingMixedModeAtEOL
1852
- };
1853
- this.beginMixedMode = false;
1854
- this.endingMixedModeAtEOL = false;
1855
- this.endText();
1856
- return tag;
1857
- },
1858
- exit(tag) {
1859
- var _a, _b;
1860
- const { selfClosed } = tag;
1861
- (_b = (_a = this.options).onOpenTagEnd) == null ? void 0 : _b.call(_a, {
1862
- start: this.pos - (this.isConcise ? 0 : selfClosed ? 2 : 1),
1863
- end: this.pos,
1864
- selfClosed
1865
- });
1866
- switch (selfClosed ? 2 /* void */ : tag.type) {
1867
- case 2 /* void */:
1868
- case 3 /* statement */: {
1869
- if (tag.beginMixedMode)
1870
- this.endingMixedModeAtEOL = true;
1871
- this.activeTag = tag.parentTag;
1872
- break;
1873
- }
1874
- case 1 /* text */:
1875
- if (this.isConcise) {
1876
- this.enterState(states_exports.CONCISE_HTML_CONTENT);
1877
- } else {
1878
- this.enterState(states_exports.PARSED_TEXT_CONTENT);
1879
- }
1880
- break;
1881
- }
1882
- },
1883
- eol(_, tag) {
1884
- if (this.isConcise && tag.stage !== 4 /* ATTR_GROUP */) {
1885
- this.exitState();
1886
- }
1887
- },
1888
- eof(tag) {
1889
- if (this.isConcise) {
1890
- if (tag.stage === 4 /* ATTR_GROUP */) {
1891
- this.emitError(tag, 19 /* MALFORMED_OPEN_TAG */, 'EOF reached while within an attribute group (e.g. "[ ... ]").');
1892
- return;
1893
- }
1894
- this.exitState();
1895
- } else {
1896
- this.emitError(tag, 19 /* MALFORMED_OPEN_TAG */, "EOF reached while parsing open tag");
1897
- }
1898
- },
1899
- char(code, tag) {
1900
- if (this.isConcise) {
1901
- if (code === 59 /* SEMICOLON */) {
1902
- this.pos++;
1903
- this.exitState();
1904
- if (!this.consumeWhitespaceOnLine(0)) {
1905
- switch (this.lookAtCharCodeAhead(0)) {
1906
- case 47 /* FORWARD_SLASH */:
1907
- switch (this.lookAtCharCodeAhead(1)) {
1908
- case 47 /* FORWARD_SLASH */:
1909
- this.enterState(states_exports.JS_COMMENT_LINE);
1910
- this.pos += 2;
1911
- return;
1912
- case 42 /* ASTERISK */:
1913
- this.enterState(states_exports.JS_COMMENT_BLOCK);
1914
- this.pos += 2;
1915
- return;
1916
- }
1917
- break;
1918
- case 60 /* OPEN_ANGLE_BRACKET */:
1919
- if (this.lookAheadFor("!--")) {
1920
- this.enterState(states_exports.HTML_COMMENT);
1921
- this.pos += 4;
1922
- return;
1923
- }
1924
- break;
1925
- }
1926
- this.emitError(this.pos, 5 /* INVALID_CODE_AFTER_SEMICOLON */, "A semicolon indicates the end of a line. Only comments may follow it.");
1927
- }
1928
- return;
1929
- }
1930
- if (code === 45 /* HTML_BLOCK_DELIMITER */) {
1931
- if (this.lookAtCharCodeAhead(1) !== 45 /* HTML_BLOCK_DELIMITER */) {
1932
- this.emitError(tag, 19 /* MALFORMED_OPEN_TAG */, '"-" not allowed as first character of attribute name');
1933
- return;
1934
- }
1935
- if (tag.stage === 4 /* ATTR_GROUP */) {
1936
- this.emitError(this.pos, 19 /* MALFORMED_OPEN_TAG */, "Attribute group was not properly ended");
1937
- return;
1938
- }
1939
- this.exitState();
1940
- const maxPos = this.maxPos;
1941
- let curPos = this.pos + 1;
1942
- while (curPos < maxPos && this.data.charCodeAt(++curPos) !== 10 /* NEWLINE */)
1943
- ;
1944
- const indentStart = ++curPos;
1945
- while (curPos < maxPos) {
1946
- const nextCode = this.data.charCodeAt(curPos);
1947
- if (nextCode === 32 /* SPACE */ || nextCode === 9 /* TAB */) {
1948
- curPos++;
1949
- } else {
1950
- break;
1951
- }
1952
- }
1953
- const indentSize = curPos - indentStart;
1954
- if (indentSize > this.indent.length) {
1955
- this.indent = this.data.slice(indentStart, curPos);
1956
- }
1957
- this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
1958
- return;
1959
- } else if (code === 91 /* OPEN_SQUARE_BRACKET */) {
1960
- if (tag.stage === 4 /* ATTR_GROUP */) {
1961
- this.emitError(this.pos, 19 /* MALFORMED_OPEN_TAG */, 'Unexpected "[" character within open tag.');
1962
- return;
1963
- }
1964
- tag.stage = 4 /* ATTR_GROUP */;
1965
- return;
1966
- } else if (code === 93 /* CLOSE_SQUARE_BRACKET */) {
1967
- if (tag.stage !== 4 /* ATTR_GROUP */) {
1968
- this.emitError(this.pos, 19 /* MALFORMED_OPEN_TAG */, 'Unexpected "]" character within open tag.');
1969
- return;
1970
- }
1971
- tag.stage = 0 /* UNKNOWN */;
1972
- return;
1973
- }
1974
- } else if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
1975
- this.pos++;
1976
- this.exitState();
1977
- return;
1978
- } else if (code === 47 /* FORWARD_SLASH */ && this.lookAtCharCodeAhead(1) === 62 /* CLOSE_ANGLE_BRACKET */) {
1979
- tag.selfClosed = true;
1980
- this.pos += 2;
1981
- this.exitState();
1982
- return;
1983
- }
1984
- if (code === 60 /* OPEN_ANGLE_BRACKET */) {
1985
- return this.emitError(this.pos, 2 /* INVALID_ATTRIBUTE_NAME */, 'Invalid attribute name. Attribute name cannot begin with the "<" character.');
1986
- }
1987
- if (code === 47 /* FORWARD_SLASH */) {
1988
- switch (this.lookAtCharCodeAhead(1)) {
1989
- case 47 /* FORWARD_SLASH */:
1990
- this.enterState(states_exports.JS_COMMENT_LINE);
1991
- this.pos++;
1992
- return;
1993
- case 42 /* ASTERISK */:
1994
- this.enterState(states_exports.JS_COMMENT_BLOCK);
1995
- this.pos++;
1996
- return;
1997
- }
1998
- }
1999
- if (isWhitespaceCode(code)) {
2000
- } else if (code === 44 /* COMMA */) {
2001
- this.pos++;
2002
- this.forward = 0;
2003
- this.consumeWhitespace();
2004
- } else if (code === 47 /* FORWARD_SLASH */ && !tag.hasAttrs) {
2005
- tag.stage = 1 /* VAR */;
2006
- this.pos++;
2007
- this.forward = 0;
2008
- if (isWhitespaceCode(this.lookAtCharCodeAhead(0))) {
2009
- return this.emitError(this.pos, 23 /* MISSING_TAG_VARIABLE */, "A slash was found that was not followed by a variable name or lhs expression");
2010
- }
2011
- const expr = this.enterState(states_exports.EXPRESSION);
2012
- expr.terminatedByWhitespace = true;
2013
- expr.terminator = this.isConcise ? CONCISE_TAG_VAR_TERMINATORS : HTML_TAG_VAR_TERMINATORS;
2014
- } else if (code === 40 /* OPEN_PAREN */ && !tag.hasAttrs) {
2015
- if (tag.hasArgs) {
2016
- this.emitError(this.pos, 11 /* INVALID_TAG_ARGUMENT */, "A tag can only have one argument");
2017
- return;
2018
- }
2019
- tag.stage = 2 /* ARGUMENT */;
2020
- this.pos++;
2021
- this.forward = 0;
2022
- const expr = this.enterState(states_exports.EXPRESSION);
2023
- expr.skipOperators = true;
2024
- expr.terminator = 41 /* CLOSE_PAREN */;
2025
- } else if (code === 124 /* PIPE */ && !tag.hasAttrs) {
2026
- tag.stage = 3 /* PARAMS */;
2027
- this.pos++;
2028
- this.forward = 0;
2029
- const expr = this.enterState(states_exports.EXPRESSION);
2030
- expr.skipOperators = true;
2031
- expr.terminator = 124 /* PIPE */;
2032
- } else {
2033
- this.forward = 0;
2034
- if (tag.tagName) {
2035
- this.enterState(states_exports.ATTRIBUTE);
2036
- tag.hasAttrs = true;
2037
- } else {
2038
- this.enterState(states_exports.TAG_NAME);
2039
- }
2040
- }
2041
- },
2042
- return(child, tag) {
2043
- var _a, _b, _c, _d, _e, _f;
2044
- switch (child.state) {
2045
- case states_exports.JS_COMMENT_BLOCK: {
2046
- break;
2047
- }
2048
- case states_exports.EXPRESSION: {
2049
- switch (tag.stage) {
2050
- case 1 /* VAR */: {
2051
- if (child.start === child.end) {
2052
- return this.emitError(child, 23 /* MISSING_TAG_VARIABLE */, "A slash was found that was not followed by a variable name or lhs expression");
2053
- }
2054
- (_b = (_a = this.options).onTagVar) == null ? void 0 : _b.call(_a, {
2055
- start: child.start - 1,
2056
- end: child.end,
2057
- value: {
2058
- start: child.start,
2059
- end: child.end
2060
- }
2061
- });
2062
- break;
2063
- }
2064
- case 2 /* ARGUMENT */: {
2065
- const start = child.start - 1;
2066
- const end = ++this.pos;
2067
- const value = {
2068
- start: child.start,
2069
- end: child.end
2070
- };
2071
- if (this.consumeWhitespaceIfBefore("{")) {
2072
- const attr = this.enterState(states_exports.ATTRIBUTE);
2073
- attr.start = start;
2074
- attr.args = { start, end, value };
2075
- tag.hasAttrs = true;
2076
- this.forward = 0;
2077
- } else {
2078
- tag.hasArgs = true;
2079
- (_d = (_c = this.options).onTagArgs) == null ? void 0 : _d.call(_c, {
2080
- start,
2081
- end,
2082
- value
2083
- });
2084
- }
2085
- break;
2086
- }
2087
- case 3 /* PARAMS */: {
2088
- const end = ++this.pos;
2089
- (_f = (_e = this.options).onTagParams) == null ? void 0 : _f.call(_e, {
2090
- start: child.start - 1,
2091
- end,
2092
- value: {
2093
- start: child.start,
2094
- end: child.end
2095
- }
2096
- });
2097
- break;
2098
- }
2099
- }
2100
- break;
2101
- }
2102
- }
2103
- }
2104
- };
2105
-
2106
2505
  // src/index.ts
2107
2506
  function createParser(handlers) {
2108
2507
  const parser = new Parser(handlers);