htmljs-parser 5.1.1 → 5.1.2

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.mjs CHANGED
@@ -69,10 +69,23 @@ function htmlEOF() {
69
69
  if (this.activeTag.concise) {
70
70
  this.closeTagEnd(this.pos, this.pos, void 0);
71
71
  } else {
72
- return this.emitError(this.activeTag, 22 /* MISSING_END_TAG */, 'Missing ending "' + this.read(this.activeTag.tagName) + '" tag');
72
+ return this.emitError(
73
+ this.activeTag,
74
+ 22 /* MISSING_END_TAG */,
75
+ 'Missing ending "' + this.read(this.activeTag.tagName) + '" tag'
76
+ );
73
77
  }
74
78
  }
75
79
  }
80
+ function matchesCloseParen(code) {
81
+ return code === 41 /* CLOSE_PAREN */;
82
+ }
83
+ function matchesCloseCurlyBrace(code) {
84
+ return code === 125 /* CLOSE_CURLY_BRACE */;
85
+ }
86
+ function matchesPipe(code) {
87
+ return code === 124 /* PIPE */;
88
+ }
76
89
  function getPosAfterLine(lines, startLine, index) {
77
90
  let max = lines.length - 1;
78
91
  let line = startLine;
@@ -114,14 +127,25 @@ var Parser = class {
114
127
  return this.data.slice(range.start, range.end);
115
128
  }
116
129
  positionAt(offset) {
117
- return getPosition(this.lines || (this.lines = getLines(this.data)), offset);
130
+ return getPosition(
131
+ this.lines || (this.lines = getLines(this.data)),
132
+ offset
133
+ );
118
134
  }
119
135
  locationAt(range) {
120
- return getLocation(this.lines || (this.lines = getLines(this.data)), range.start, range.end);
136
+ return getLocation(
137
+ this.lines || (this.lines = getLines(this.data)),
138
+ range.start,
139
+ range.end
140
+ );
121
141
  }
122
142
  enterState(state) {
123
143
  this.activeState = state;
124
- return this.activeRange = state.enter.call(this, this.activeRange, this.pos);
144
+ return this.activeRange = state.enter.call(
145
+ this,
146
+ this.activeRange,
147
+ this.pos
148
+ );
125
149
  }
126
150
  exitState() {
127
151
  const { activeRange, activeState } = this;
@@ -191,7 +215,9 @@ var Parser = class {
191
215
  }
192
216
  beginHtmlBlock(delimiter, singleLine) {
193
217
  var _a;
194
- const content = this.enterState(((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ ? states_exports.PARSED_TEXT_CONTENT : states_exports.HTML_CONTENT);
218
+ const content = this.enterState(
219
+ ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ ? states_exports.PARSED_TEXT_CONTENT : states_exports.HTML_CONTENT
220
+ );
195
221
  content.singleLine = singleLine;
196
222
  content.delimiter = delimiter;
197
223
  content.indent = this.indent;
@@ -351,294 +377,712 @@ __export(states_exports, {
351
377
  handleDelimitedEOL: () => handleDelimitedEOL
352
378
  });
353
379
 
354
- // src/states/ATTRIBUTE.ts
355
- var HTML_VALUE_TERMINATORS = [
356
- 62 /* CLOSE_ANGLE_BRACKET */,
357
- 44 /* COMMA */,
358
- [47 /* FORWARD_SLASH */, 62 /* CLOSE_ANGLE_BRACKET */]
359
- ];
360
- var CONCISE_VALUE_TERMINATORS = [
361
- 93 /* CLOSE_SQUARE_BRACKET */,
362
- 59 /* SEMICOLON */,
363
- 44 /* COMMA */
364
- ];
365
- var HTML_NAME_TERMINATORS = [
366
- 62 /* CLOSE_ANGLE_BRACKET */,
367
- 44 /* COMMA */,
368
- 40 /* OPEN_PAREN */,
369
- 61 /* EQUAL */,
370
- [58 /* COLON */, 61 /* EQUAL */],
371
- [47 /* FORWARD_SLASH */, 62 /* CLOSE_ANGLE_BRACKET */]
372
- ];
373
- var CONCISE_NAME_TERMINATORS = [
374
- 93 /* CLOSE_SQUARE_BRACKET */,
375
- 59 /* SEMICOLON */,
376
- 61 /* EQUAL */,
377
- 44 /* COMMA */,
378
- 40 /* OPEN_PAREN */,
379
- [58 /* COLON */, 61 /* EQUAL */]
380
- ];
381
- var ATTRIBUTE = {
382
- name: "ATTRIBUTE",
380
+ // src/states/OPEN_TAG.ts
381
+ var TAG_STAGE = /* @__PURE__ */ ((TAG_STAGE2) => {
382
+ TAG_STAGE2[TAG_STAGE2["UNKNOWN"] = 0] = "UNKNOWN";
383
+ TAG_STAGE2[TAG_STAGE2["VAR"] = 1] = "VAR";
384
+ TAG_STAGE2[TAG_STAGE2["ARGUMENT"] = 2] = "ARGUMENT";
385
+ TAG_STAGE2[TAG_STAGE2["PARAMS"] = 3] = "PARAMS";
386
+ TAG_STAGE2[TAG_STAGE2["ATTR_GROUP"] = 4] = "ATTR_GROUP";
387
+ return TAG_STAGE2;
388
+ })(TAG_STAGE || {});
389
+ var OPEN_TAG = {
390
+ name: "OPEN_TAG",
383
391
  enter(parent, start) {
384
- return this.activeAttr = {
385
- state: ATTRIBUTE,
392
+ const tag = this.activeTag = {
393
+ state: OPEN_TAG,
394
+ type: 0 /* html */,
386
395
  parent,
387
396
  start,
388
397
  end: start,
389
- valueStart: start,
390
398
  stage: 0 /* UNKNOWN */,
391
- name: void 0,
392
- args: false,
393
- bound: false,
394
- spread: false
399
+ parentTag: this.activeTag,
400
+ nestedIndent: void 0,
401
+ indent: this.indent,
402
+ hasShorthandId: false,
403
+ hasArgs: false,
404
+ hasAttrs: false,
405
+ selfClosed: false,
406
+ shorthandEnd: -1,
407
+ tagName: void 0,
408
+ concise: this.isConcise,
409
+ beginMixedMode: this.beginMixedMode || this.endingMixedModeAtEOL
395
410
  };
411
+ this.beginMixedMode = false;
412
+ this.endingMixedModeAtEOL = false;
413
+ this.endText();
414
+ return tag;
396
415
  },
397
- exit() {
398
- this.activeAttr = void 0;
399
- },
400
- char(code, attr) {
401
- if (isWhitespaceCode(code)) {
402
- return;
403
- } else if (code === 61 /* EQUAL */ || code === 58 /* COLON */ && this.lookAtCharCodeAhead(1) === 61 /* EQUAL */ || code === 46 /* PERIOD */ && this.lookAheadFor("..")) {
404
- attr.valueStart = this.pos;
405
- this.forward = 0;
406
- if (code === 58 /* COLON */) {
407
- ensureAttrName(this, attr);
408
- attr.bound = true;
409
- this.pos += 2;
410
- this.consumeWhitespace();
411
- } else if (code === 46 /* PERIOD */) {
412
- attr.spread = true;
413
- this.pos += 3;
414
- } else {
415
- ensureAttrName(this, attr);
416
- this.pos++;
417
- this.consumeWhitespace();
416
+ exit(tag) {
417
+ var _a, _b;
418
+ const { selfClosed } = tag;
419
+ (_b = (_a = this.options).onOpenTagEnd) == null ? void 0 : _b.call(_a, {
420
+ start: this.pos - (this.isConcise ? 0 : selfClosed ? 2 : 1),
421
+ end: this.pos,
422
+ selfClosed
423
+ });
424
+ switch (selfClosed ? 2 /* void */ : tag.type) {
425
+ case 2 /* void */:
426
+ case 3 /* statement */: {
427
+ if (tag.beginMixedMode)
428
+ this.endingMixedModeAtEOL = true;
429
+ this.activeTag = tag.parentTag;
430
+ break;
418
431
  }
419
- attr.stage = 2 /* VALUE */;
420
- const expr = this.enterState(states_exports.EXPRESSION);
421
- expr.terminatedByWhitespace = true;
422
- expr.terminator = this.isConcise ? CONCISE_VALUE_TERMINATORS : HTML_VALUE_TERMINATORS;
423
- } else if (code === 40 /* OPEN_PAREN */) {
424
- ensureAttrName(this, attr);
425
- attr.stage = 3 /* ARGUMENT */;
426
- this.pos++;
427
- this.forward = 0;
428
- this.enterState(states_exports.EXPRESSION).terminator = 41 /* CLOSE_PAREN */;
429
- } else if (code === 123 /* OPEN_CURLY_BRACE */ && attr.args) {
430
- ensureAttrName(this, attr);
431
- attr.stage = 4 /* BLOCK */;
432
- this.pos++;
433
- this.forward = 0;
434
- const expr = this.enterState(states_exports.EXPRESSION);
435
- expr.terminatedByWhitespace = false;
436
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
437
- } else if (attr.stage === 0 /* UNKNOWN */) {
438
- attr.stage = 1 /* NAME */;
439
- this.forward = 0;
440
- const expr = this.enterState(states_exports.EXPRESSION);
441
- expr.terminatedByWhitespace = true;
442
- expr.skipOperators = true;
443
- expr.terminator = this.isConcise ? CONCISE_NAME_TERMINATORS : HTML_NAME_TERMINATORS;
444
- } else {
445
- this.exitState();
432
+ case 1 /* text */:
433
+ if (this.isConcise) {
434
+ this.enterState(states_exports.CONCISE_HTML_CONTENT);
435
+ } else {
436
+ this.enterState(states_exports.PARSED_TEXT_CONTENT);
437
+ }
438
+ break;
446
439
  }
447
440
  },
448
- eol() {
449
- if (this.isConcise) {
441
+ eol(_, tag) {
442
+ if (this.isConcise && tag.stage !== 4 /* ATTR_GROUP */) {
450
443
  this.exitState();
451
444
  }
452
445
  },
453
- eof(attr) {
446
+ eof(tag) {
454
447
  if (this.isConcise) {
448
+ if (tag.stage === 4 /* ATTR_GROUP */) {
449
+ this.emitError(
450
+ tag,
451
+ 19 /* MALFORMED_OPEN_TAG */,
452
+ 'EOF reached while within an attribute group (e.g. "[ ... ]").'
453
+ );
454
+ return;
455
+ }
455
456
  this.exitState();
456
457
  } else {
457
- 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');
458
+ this.emitError(
459
+ tag,
460
+ 19 /* MALFORMED_OPEN_TAG */,
461
+ "EOF reached while parsing open tag"
462
+ );
458
463
  }
459
464
  },
460
- return(child, attr) {
461
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
462
- switch (attr.stage) {
463
- case 1 /* NAME */: {
464
- attr.name = {
465
- start: child.start,
466
- end: child.end
467
- };
468
- (_b = (_a = this.options).onAttrName) == null ? void 0 : _b.call(_a, attr.name);
469
- break;
465
+ char(code, tag) {
466
+ if (this.isConcise) {
467
+ if (code === 59 /* SEMICOLON */) {
468
+ this.pos++;
469
+ this.exitState();
470
+ if (!this.consumeWhitespaceOnLine(0)) {
471
+ switch (this.lookAtCharCodeAhead(0)) {
472
+ case 47 /* FORWARD_SLASH */:
473
+ switch (this.lookAtCharCodeAhead(1)) {
474
+ case 47 /* FORWARD_SLASH */:
475
+ this.enterState(states_exports.JS_COMMENT_LINE);
476
+ this.pos += 2;
477
+ return;
478
+ case 42 /* ASTERISK */:
479
+ this.enterState(states_exports.JS_COMMENT_BLOCK);
480
+ this.pos += 2;
481
+ return;
482
+ }
483
+ break;
484
+ case 60 /* OPEN_ANGLE_BRACKET */:
485
+ if (this.lookAheadFor("!--")) {
486
+ this.enterState(states_exports.HTML_COMMENT);
487
+ this.pos += 4;
488
+ return;
489
+ }
490
+ break;
491
+ }
492
+ this.emitError(
493
+ this.pos,
494
+ 5 /* INVALID_CODE_AFTER_SEMICOLON */,
495
+ "A semicolon indicates the end of a line. Only comments may follow it."
496
+ );
497
+ }
498
+ return;
470
499
  }
471
- case 3 /* ARGUMENT */: {
472
- if (attr.args) {
473
- this.emitError(child, 1 /* INVALID_ATTRIBUTE_ARGUMENT */, "An attribute can only have one set of arguments");
500
+ if (code === 45 /* HTML_BLOCK_DELIMITER */) {
501
+ if (this.lookAtCharCodeAhead(1) !== 45 /* HTML_BLOCK_DELIMITER */) {
502
+ this.emitError(
503
+ tag,
504
+ 19 /* MALFORMED_OPEN_TAG */,
505
+ '"-" not allowed as first character of attribute name'
506
+ );
474
507
  return;
475
508
  }
476
- const start = child.start - 1;
477
- const end = ++this.pos;
478
- const value = {
479
- start: child.start,
480
- end: child.end
481
- };
482
- if (this.consumeWhitespaceIfBefore("{")) {
483
- attr.args = {
484
- start,
485
- end,
486
- value
487
- };
488
- } else {
489
- attr.args = true;
490
- (_d = (_c = this.options).onAttrArgs) == null ? void 0 : _d.call(_c, {
491
- start,
492
- end,
493
- value
494
- });
509
+ if (tag.stage === 4 /* ATTR_GROUP */) {
510
+ this.emitError(
511
+ this.pos,
512
+ 19 /* MALFORMED_OPEN_TAG */,
513
+ "Attribute group was not properly ended"
514
+ );
515
+ return;
495
516
  }
496
- break;
497
- }
498
- case 4 /* BLOCK */: {
499
- const params = attr.args;
500
- const start = params.start;
501
- const end = ++this.pos;
502
- (_f = (_e = this.options).onAttrMethod) == null ? void 0 : _f.call(_e, {
503
- start,
504
- end,
505
- params,
506
- body: {
507
- start: child.start - 1,
508
- end,
509
- value: {
510
- start: child.start,
511
- end: child.end
512
- }
513
- }
514
- });
515
517
  this.exitState();
516
- break;
517
- }
518
- case 2 /* VALUE */: {
519
- if (child.start === child.end) {
520
- return this.emitError(child, 3 /* INVALID_ATTRIBUTE_VALUE */, "Missing value for attribute");
518
+ const maxPos = this.maxPos;
519
+ let curPos = this.pos + 1;
520
+ while (curPos < maxPos && this.data.charCodeAt(++curPos) !== 10 /* NEWLINE */)
521
+ ;
522
+ const indentStart = ++curPos;
523
+ while (curPos < maxPos) {
524
+ const nextCode = this.data.charCodeAt(curPos);
525
+ if (nextCode === 32 /* SPACE */ || nextCode === 9 /* TAB */) {
526
+ curPos++;
527
+ } else {
528
+ break;
529
+ }
521
530
  }
522
- if (attr.spread) {
523
- (_h = (_g = this.options).onAttrSpread) == null ? void 0 : _h.call(_g, {
524
- start: attr.valueStart,
525
- end: child.end,
526
- value: {
527
- start: child.start,
528
- end: child.end
529
- }
530
- });
531
- } else {
532
- (_j = (_i = this.options).onAttrValue) == null ? void 0 : _j.call(_i, {
533
- start: attr.valueStart,
534
- end: child.end,
535
- bound: attr.bound,
536
- value: {
537
- start: child.start,
538
- end: child.end
539
- }
540
- });
531
+ const indentSize = curPos - indentStart;
532
+ if (indentSize > this.indent.length) {
533
+ this.indent = this.data.slice(indentStart, curPos);
541
534
  }
542
- this.exitState();
543
- break;
535
+ this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
536
+ return;
537
+ } else if (code === 91 /* OPEN_SQUARE_BRACKET */) {
538
+ if (tag.stage === 4 /* ATTR_GROUP */) {
539
+ this.emitError(
540
+ this.pos,
541
+ 19 /* MALFORMED_OPEN_TAG */,
542
+ 'Unexpected "[" character within open tag.'
543
+ );
544
+ return;
545
+ }
546
+ tag.stage = 4 /* ATTR_GROUP */;
547
+ return;
548
+ } else if (code === 93 /* CLOSE_SQUARE_BRACKET */) {
549
+ if (tag.stage !== 4 /* ATTR_GROUP */) {
550
+ this.emitError(
551
+ this.pos,
552
+ 19 /* MALFORMED_OPEN_TAG */,
553
+ 'Unexpected "]" character within open tag.'
554
+ );
555
+ return;
556
+ }
557
+ tag.stage = 0 /* UNKNOWN */;
558
+ return;
559
+ }
560
+ } else if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
561
+ this.pos++;
562
+ this.exitState();
563
+ return;
564
+ } else if (code === 47 /* FORWARD_SLASH */ && this.lookAtCharCodeAhead(1) === 62 /* CLOSE_ANGLE_BRACKET */) {
565
+ tag.selfClosed = true;
566
+ this.pos += 2;
567
+ this.exitState();
568
+ return;
569
+ }
570
+ if (code === 60 /* OPEN_ANGLE_BRACKET */) {
571
+ return this.emitError(
572
+ this.pos,
573
+ 2 /* INVALID_ATTRIBUTE_NAME */,
574
+ 'Invalid attribute name. Attribute name cannot begin with the "<" character.'
575
+ );
576
+ }
577
+ if (code === 47 /* FORWARD_SLASH */) {
578
+ switch (this.lookAtCharCodeAhead(1)) {
579
+ case 47 /* FORWARD_SLASH */:
580
+ this.enterState(states_exports.JS_COMMENT_LINE);
581
+ this.pos++;
582
+ return;
583
+ case 42 /* ASTERISK */:
584
+ this.enterState(states_exports.JS_COMMENT_BLOCK);
585
+ this.pos++;
586
+ return;
587
+ }
588
+ }
589
+ if (isWhitespaceCode(code)) {
590
+ } else if (code === 44 /* COMMA */) {
591
+ this.pos++;
592
+ this.forward = 0;
593
+ this.consumeWhitespace();
594
+ } else if (code === 47 /* FORWARD_SLASH */ && !tag.hasAttrs) {
595
+ tag.stage = 1 /* VAR */;
596
+ this.pos++;
597
+ this.forward = 0;
598
+ if (isWhitespaceCode(this.lookAtCharCodeAhead(0))) {
599
+ return this.emitError(
600
+ this.pos,
601
+ 23 /* MISSING_TAG_VARIABLE */,
602
+ "A slash was found that was not followed by a variable name or lhs expression"
603
+ );
604
+ }
605
+ const expr = this.enterState(states_exports.EXPRESSION);
606
+ expr.operators = true;
607
+ expr.terminatedByWhitespace = true;
608
+ expr.shouldTerminate = this.isConcise ? shouldTerminateConciseTagVar : shouldTerminateHtmlTagVar;
609
+ } else if (code === 40 /* OPEN_PAREN */ && !tag.hasAttrs) {
610
+ if (tag.hasArgs) {
611
+ this.emitError(
612
+ this.pos,
613
+ 11 /* INVALID_TAG_ARGUMENT */,
614
+ "A tag can only have one argument"
615
+ );
616
+ return;
617
+ }
618
+ tag.stage = 2 /* ARGUMENT */;
619
+ this.pos++;
620
+ this.forward = 0;
621
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseParen;
622
+ } else if (code === 124 /* PIPE */ && !tag.hasAttrs) {
623
+ tag.stage = 3 /* PARAMS */;
624
+ this.pos++;
625
+ this.forward = 0;
626
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesPipe;
627
+ } else {
628
+ this.forward = 0;
629
+ if (tag.tagName) {
630
+ this.enterState(states_exports.ATTRIBUTE);
631
+ tag.hasAttrs = true;
632
+ } else {
633
+ this.enterState(states_exports.TAG_NAME);
634
+ }
635
+ }
636
+ },
637
+ return(child, tag) {
638
+ var _a, _b, _c, _d, _e, _f;
639
+ switch (child.state) {
640
+ case states_exports.JS_COMMENT_BLOCK: {
641
+ break;
642
+ }
643
+ case states_exports.EXPRESSION: {
644
+ switch (tag.stage) {
645
+ case 1 /* VAR */: {
646
+ if (child.start === child.end) {
647
+ return this.emitError(
648
+ child,
649
+ 23 /* MISSING_TAG_VARIABLE */,
650
+ "A slash was found that was not followed by a variable name or lhs expression"
651
+ );
652
+ }
653
+ (_b = (_a = this.options).onTagVar) == null ? void 0 : _b.call(_a, {
654
+ start: child.start - 1,
655
+ end: child.end,
656
+ value: {
657
+ start: child.start,
658
+ end: child.end
659
+ }
660
+ });
661
+ break;
662
+ }
663
+ case 2 /* ARGUMENT */: {
664
+ const start = child.start - 1;
665
+ const end = ++this.pos;
666
+ const value = {
667
+ start: child.start,
668
+ end: child.end
669
+ };
670
+ if (this.consumeWhitespaceIfBefore("{")) {
671
+ const attr = this.enterState(states_exports.ATTRIBUTE);
672
+ attr.start = start;
673
+ attr.args = { start, end, value };
674
+ tag.hasAttrs = true;
675
+ this.forward = 0;
676
+ } else {
677
+ tag.hasArgs = true;
678
+ (_d = (_c = this.options).onTagArgs) == null ? void 0 : _d.call(_c, {
679
+ start,
680
+ end,
681
+ value
682
+ });
683
+ }
684
+ break;
685
+ }
686
+ case 3 /* PARAMS */: {
687
+ const end = ++this.pos;
688
+ (_f = (_e = this.options).onTagParams) == null ? void 0 : _f.call(_e, {
689
+ start: child.start - 1,
690
+ end,
691
+ value: {
692
+ start: child.start,
693
+ end: child.end
694
+ }
695
+ });
696
+ break;
697
+ }
698
+ }
699
+ break;
544
700
  }
545
701
  }
546
702
  }
547
703
  };
548
- function ensureAttrName(parser, attr) {
549
- var _a, _b;
550
- if (!attr.name) {
551
- (_b = (_a = parser.options).onAttrName) == null ? void 0 : _b.call(_a, {
552
- start: attr.start,
553
- end: attr.start
554
- });
704
+ function shouldTerminateConciseTagVar(code, data, pos) {
705
+ switch (code) {
706
+ case 44 /* COMMA */:
707
+ case 61 /* EQUAL */:
708
+ case 124 /* PIPE */:
709
+ case 40 /* OPEN_PAREN */:
710
+ case 59 /* SEMICOLON */:
711
+ return true;
712
+ case 58 /* COLON */:
713
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
714
+ default:
715
+ return false;
716
+ }
717
+ }
718
+ function shouldTerminateHtmlTagVar(code, data, pos) {
719
+ switch (code) {
720
+ case 124 /* PIPE */:
721
+ case 44 /* COMMA */:
722
+ case 61 /* EQUAL */:
723
+ case 40 /* OPEN_PAREN */:
724
+ case 62 /* CLOSE_ANGLE_BRACKET */:
725
+ return true;
726
+ case 58 /* COLON */:
727
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
728
+ case 47 /* FORWARD_SLASH */:
729
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
730
+ default:
731
+ return false;
555
732
  }
556
733
  }
557
734
 
558
- // src/states/BEGIN_DELIMITED_HTML_BLOCK.ts
559
- var BEGIN_DELIMITED_HTML_BLOCK = {
560
- name: "BEGIN_DELIMITED_HTML_BLOCK",
735
+ // src/states/ATTRIBUTE.ts
736
+ var ATTRIBUTE = {
737
+ name: "ATTRIBUTE",
561
738
  enter(parent, start) {
562
- return {
563
- state: BEGIN_DELIMITED_HTML_BLOCK,
739
+ return this.activeAttr = {
740
+ state: ATTRIBUTE,
564
741
  parent,
565
742
  start,
566
743
  end: start,
567
- indent: this.indent,
568
- delimiter: ""
744
+ valueStart: start,
745
+ stage: 0 /* UNKNOWN */,
746
+ name: void 0,
747
+ args: false,
748
+ bound: false,
749
+ spread: false
569
750
  };
570
751
  },
571
752
  exit() {
753
+ this.activeAttr = void 0;
572
754
  },
573
- char(code, block) {
574
- if (code === 45 /* HTML_BLOCK_DELIMITER */) {
575
- block.delimiter += "-";
576
- } else {
577
- const startPos = this.pos;
578
- if (!this.consumeWhitespaceOnLine()) {
579
- this.pos = startPos + 1;
580
- this.forward = 0;
581
- this.beginHtmlBlock(void 0, true);
755
+ char(code, attr) {
756
+ if (isWhitespaceCode(code)) {
757
+ return;
758
+ } else if (code === 61 /* EQUAL */ || code === 58 /* COLON */ && this.lookAtCharCodeAhead(1) === 61 /* EQUAL */ || code === 46 /* PERIOD */ && this.lookAheadFor("..")) {
759
+ attr.valueStart = this.pos;
760
+ this.forward = 0;
761
+ if (code === 58 /* COLON */) {
762
+ ensureAttrName(this, attr);
763
+ attr.bound = true;
764
+ this.pos += 2;
765
+ this.consumeWhitespace();
766
+ } else if (code === 46 /* PERIOD */) {
767
+ attr.spread = true;
768
+ this.pos += 3;
769
+ } else {
770
+ ensureAttrName(this, attr);
771
+ this.pos++;
772
+ this.consumeWhitespace();
582
773
  }
774
+ attr.stage = 2 /* VALUE */;
775
+ const expr = this.enterState(states_exports.EXPRESSION);
776
+ expr.operators = true;
777
+ expr.terminatedByWhitespace = true;
778
+ expr.shouldTerminate = this.isConcise ? this.activeTag.stage === 4 /* ATTR_GROUP */ ? shouldTerminateConciseGroupedAttrValue : shouldTerminateConciseAttrValue : shouldTerminateHtmlAttrValue;
779
+ } else if (code === 40 /* OPEN_PAREN */) {
780
+ ensureAttrName(this, attr);
781
+ attr.stage = 3 /* ARGUMENT */;
782
+ this.pos++;
783
+ this.forward = 0;
784
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseParen;
785
+ } else if (code === 123 /* OPEN_CURLY_BRACE */ && attr.args) {
786
+ ensureAttrName(this, attr);
787
+ attr.stage = 4 /* BLOCK */;
788
+ this.pos++;
789
+ this.forward = 0;
790
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
791
+ } else if (attr.stage === 0 /* UNKNOWN */) {
792
+ attr.stage = 1 /* NAME */;
793
+ this.forward = 0;
794
+ const expr = this.enterState(states_exports.EXPRESSION);
795
+ expr.terminatedByWhitespace = true;
796
+ expr.shouldTerminate = this.isConcise ? this.activeTag.stage === 4 /* ATTR_GROUP */ ? shouldTerminateConciseGroupedAttrName : shouldTerminateConciseAttrName : shouldTerminateHtmlAttrName;
797
+ } else {
798
+ this.exitState();
583
799
  }
584
800
  },
585
- eol(len, block) {
586
- this.beginHtmlBlock(block.delimiter, false);
587
- handleDelimitedBlockEOL(this, len, block);
801
+ eol() {
802
+ if (this.isConcise) {
803
+ this.exitState();
804
+ }
588
805
  },
589
- eof: htmlEOF,
590
- return() {
591
- }
592
- };
593
- function handleDelimitedEOL(parser, newLineLength, content) {
594
- if (content.singleLine) {
595
- parser.endText();
596
- parser.exitState();
597
- parser.exitState();
598
- return true;
599
- }
600
- if (content.delimiter) {
601
- handleDelimitedBlockEOL(parser, newLineLength, content);
602
- return true;
603
- }
604
- return false;
605
- }
606
- function handleDelimitedBlockEOL(parser, newLineLength, {
607
- indent,
608
- delimiter
609
- }) {
610
- const endHtmlBlockLookahead = indent + delimiter;
611
- if (parser.lookAheadFor(endHtmlBlockLookahead, parser.pos + newLineLength)) {
612
- parser.startText();
613
- parser.pos += newLineLength;
614
- parser.endText();
615
- parser.pos += endHtmlBlockLookahead.length;
616
- if (parser.consumeWhitespaceOnLine(0)) {
617
- parser.endText();
618
- parser.exitState();
619
- parser.exitState();
806
+ eof(attr) {
807
+ if (this.isConcise) {
808
+ this.exitState();
620
809
  } else {
621
- parser.emitError(parser.pos, 4 /* INVALID_CHARACTER */, "A concise mode closing block delimiter can only be followed by whitespace.");
810
+ this.emitError(
811
+ attr,
812
+ 19 /* MALFORMED_OPEN_TAG */,
813
+ 'EOF reached while parsing attribute "' + (attr.name ? this.read(attr.name) : "default") + '" for the "' + this.read(this.activeTag.tagName) + '" tag'
814
+ );
622
815
  }
623
- } else if (parser.lookAheadFor(indent, parser.pos + newLineLength)) {
624
- parser.startText();
625
- parser.pos += indent.length;
626
- } else if (indent && !parser.onlyWhitespaceRemainsOnLine(newLineLength)) {
627
- parser.endText();
628
- parser.exitState();
629
- parser.exitState();
630
- } else {
631
- parser.startText();
632
- }
633
- }
634
-
635
- // src/states/CDATA.ts
636
- var CDATA = {
637
- name: "CDATA",
638
- enter(parent, start) {
639
- return {
640
- state: CDATA,
641
- parent,
816
+ },
817
+ return(child, attr) {
818
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
819
+ switch (attr.stage) {
820
+ case 1 /* NAME */: {
821
+ attr.name = {
822
+ start: child.start,
823
+ end: child.end
824
+ };
825
+ (_b = (_a = this.options).onAttrName) == null ? void 0 : _b.call(_a, attr.name);
826
+ break;
827
+ }
828
+ case 3 /* ARGUMENT */: {
829
+ if (attr.args) {
830
+ this.emitError(
831
+ child,
832
+ 1 /* INVALID_ATTRIBUTE_ARGUMENT */,
833
+ "An attribute can only have one set of arguments"
834
+ );
835
+ return;
836
+ }
837
+ const start = child.start - 1;
838
+ const end = ++this.pos;
839
+ const value = {
840
+ start: child.start,
841
+ end: child.end
842
+ };
843
+ if (this.consumeWhitespaceIfBefore("{")) {
844
+ attr.args = {
845
+ start,
846
+ end,
847
+ value
848
+ };
849
+ } else {
850
+ attr.args = true;
851
+ (_d = (_c = this.options).onAttrArgs) == null ? void 0 : _d.call(_c, {
852
+ start,
853
+ end,
854
+ value
855
+ });
856
+ }
857
+ break;
858
+ }
859
+ case 4 /* BLOCK */: {
860
+ const params = attr.args;
861
+ const start = params.start;
862
+ const end = ++this.pos;
863
+ (_f = (_e = this.options).onAttrMethod) == null ? void 0 : _f.call(_e, {
864
+ start,
865
+ end,
866
+ params,
867
+ body: {
868
+ start: child.start - 1,
869
+ end,
870
+ value: {
871
+ start: child.start,
872
+ end: child.end
873
+ }
874
+ }
875
+ });
876
+ this.exitState();
877
+ break;
878
+ }
879
+ case 2 /* VALUE */: {
880
+ if (child.start === child.end) {
881
+ return this.emitError(
882
+ child,
883
+ 3 /* INVALID_ATTRIBUTE_VALUE */,
884
+ "Missing value for attribute"
885
+ );
886
+ }
887
+ if (attr.spread) {
888
+ (_h = (_g = this.options).onAttrSpread) == null ? void 0 : _h.call(_g, {
889
+ start: attr.valueStart,
890
+ end: child.end,
891
+ value: {
892
+ start: child.start,
893
+ end: child.end
894
+ }
895
+ });
896
+ } else {
897
+ (_j = (_i = this.options).onAttrValue) == null ? void 0 : _j.call(_i, {
898
+ start: attr.valueStart,
899
+ end: child.end,
900
+ bound: attr.bound,
901
+ value: {
902
+ start: child.start,
903
+ end: child.end
904
+ }
905
+ });
906
+ }
907
+ this.exitState();
908
+ break;
909
+ }
910
+ }
911
+ }
912
+ };
913
+ function ensureAttrName(parser, attr) {
914
+ var _a, _b;
915
+ if (!attr.name) {
916
+ (_b = (_a = parser.options).onAttrName) == null ? void 0 : _b.call(_a, {
917
+ start: attr.start,
918
+ end: attr.start
919
+ });
920
+ }
921
+ }
922
+ function shouldTerminateHtmlAttrName(code, data, pos) {
923
+ switch (code) {
924
+ case 44 /* COMMA */:
925
+ case 61 /* EQUAL */:
926
+ case 40 /* OPEN_PAREN */:
927
+ case 62 /* CLOSE_ANGLE_BRACKET */:
928
+ return true;
929
+ case 58 /* COLON */:
930
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
931
+ case 47 /* FORWARD_SLASH */:
932
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
933
+ default:
934
+ return false;
935
+ }
936
+ }
937
+ function shouldTerminateHtmlAttrValue(code, data, pos) {
938
+ switch (code) {
939
+ case 44 /* COMMA */:
940
+ return true;
941
+ case 47 /* FORWARD_SLASH */:
942
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
943
+ case 62 /* CLOSE_ANGLE_BRACKET */:
944
+ return data.charCodeAt(pos - 1) !== 61 /* EQUAL */;
945
+ default:
946
+ return false;
947
+ }
948
+ }
949
+ function shouldTerminateConciseAttrName(code, data, pos) {
950
+ switch (code) {
951
+ case 44 /* COMMA */:
952
+ case 61 /* EQUAL */:
953
+ case 40 /* OPEN_PAREN */:
954
+ case 59 /* SEMICOLON */:
955
+ return true;
956
+ case 58 /* COLON */:
957
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
958
+ case 45 /* HYPHEN */:
959
+ return data.charCodeAt(pos + 1) === 45 /* HYPHEN */ && isWhitespaceCode(data.charCodeAt(pos - 1));
960
+ default:
961
+ return false;
962
+ }
963
+ }
964
+ function shouldTerminateConciseAttrValue(code, data, pos) {
965
+ switch (code) {
966
+ case 44 /* COMMA */:
967
+ case 59 /* SEMICOLON */:
968
+ return true;
969
+ case 45 /* HYPHEN */:
970
+ return data.charCodeAt(pos + 1) === 45 /* HYPHEN */ && isWhitespaceCode(data.charCodeAt(pos - 1));
971
+ default:
972
+ return false;
973
+ }
974
+ }
975
+ function shouldTerminateConciseGroupedAttrName(code, data, pos) {
976
+ switch (code) {
977
+ case 44 /* COMMA */:
978
+ case 61 /* EQUAL */:
979
+ case 40 /* OPEN_PAREN */:
980
+ case 93 /* CLOSE_SQUARE_BRACKET */:
981
+ return true;
982
+ case 58 /* COLON */:
983
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
984
+ default:
985
+ return false;
986
+ }
987
+ }
988
+ function shouldTerminateConciseGroupedAttrValue(code) {
989
+ switch (code) {
990
+ case 44 /* COMMA */:
991
+ case 93 /* CLOSE_SQUARE_BRACKET */:
992
+ return true;
993
+ default:
994
+ return false;
995
+ }
996
+ }
997
+
998
+ // src/states/BEGIN_DELIMITED_HTML_BLOCK.ts
999
+ var BEGIN_DELIMITED_HTML_BLOCK = {
1000
+ name: "BEGIN_DELIMITED_HTML_BLOCK",
1001
+ enter(parent, start) {
1002
+ return {
1003
+ state: BEGIN_DELIMITED_HTML_BLOCK,
1004
+ parent,
1005
+ start,
1006
+ end: start,
1007
+ indent: this.indent,
1008
+ delimiter: ""
1009
+ };
1010
+ },
1011
+ exit() {
1012
+ },
1013
+ char(code, block) {
1014
+ if (code === 45 /* HTML_BLOCK_DELIMITER */) {
1015
+ block.delimiter += "-";
1016
+ } else {
1017
+ const startPos = this.pos;
1018
+ if (!this.consumeWhitespaceOnLine()) {
1019
+ this.pos = startPos + 1;
1020
+ this.forward = 0;
1021
+ this.beginHtmlBlock(void 0, true);
1022
+ }
1023
+ }
1024
+ },
1025
+ eol(len, block) {
1026
+ this.beginHtmlBlock(block.delimiter, false);
1027
+ handleDelimitedBlockEOL(this, len, block);
1028
+ },
1029
+ eof: htmlEOF,
1030
+ return() {
1031
+ }
1032
+ };
1033
+ function handleDelimitedEOL(parser, newLineLength, content) {
1034
+ if (content.singleLine) {
1035
+ parser.endText();
1036
+ parser.exitState();
1037
+ parser.exitState();
1038
+ return true;
1039
+ }
1040
+ if (content.delimiter) {
1041
+ handleDelimitedBlockEOL(parser, newLineLength, content);
1042
+ return true;
1043
+ }
1044
+ return false;
1045
+ }
1046
+ function handleDelimitedBlockEOL(parser, newLineLength, {
1047
+ indent,
1048
+ delimiter
1049
+ }) {
1050
+ const endHtmlBlockLookahead = indent + delimiter;
1051
+ if (parser.lookAheadFor(endHtmlBlockLookahead, parser.pos + newLineLength)) {
1052
+ parser.startText();
1053
+ parser.pos += newLineLength;
1054
+ parser.endText();
1055
+ parser.pos += endHtmlBlockLookahead.length;
1056
+ if (parser.consumeWhitespaceOnLine(0)) {
1057
+ parser.endText();
1058
+ parser.exitState();
1059
+ parser.exitState();
1060
+ } else {
1061
+ parser.emitError(
1062
+ parser.pos,
1063
+ 4 /* INVALID_CHARACTER */,
1064
+ "A concise mode closing block delimiter can only be followed by whitespace."
1065
+ );
1066
+ }
1067
+ } else if (parser.lookAheadFor(indent, parser.pos + newLineLength)) {
1068
+ parser.startText();
1069
+ parser.pos += indent.length;
1070
+ } else if (indent && !parser.onlyWhitespaceRemainsOnLine(newLineLength)) {
1071
+ parser.endText();
1072
+ parser.exitState();
1073
+ parser.exitState();
1074
+ } else {
1075
+ parser.startText();
1076
+ }
1077
+ }
1078
+
1079
+ // src/states/CDATA.ts
1080
+ var CDATA = {
1081
+ name: "CDATA",
1082
+ enter(parent, start) {
1083
+ return {
1084
+ state: CDATA,
1085
+ parent,
642
1086
  start,
643
1087
  end: start
644
1088
  };
@@ -664,7 +1108,11 @@ var CDATA = {
664
1108
  eol() {
665
1109
  },
666
1110
  eof(cdata) {
667
- this.emitError(cdata, 14 /* MALFORMED_CDATA */, "EOF reached while parsing CDATA");
1111
+ this.emitError(
1112
+ cdata,
1113
+ 14 /* MALFORMED_CDATA */,
1114
+ "EOF reached while parsing CDATA"
1115
+ );
668
1116
  },
669
1117
  return() {
670
1118
  }
@@ -703,7 +1151,11 @@ var CLOSE_TAG = {
703
1151
  eol() {
704
1152
  },
705
1153
  eof(closeTag) {
706
- this.emitError(closeTag, 15 /* MALFORMED_CLOSE_TAG */, "EOF reached while parsing closing tag");
1154
+ this.emitError(
1155
+ closeTag,
1156
+ 15 /* MALFORMED_CLOSE_TAG */,
1157
+ "EOF reached while parsing closing tag"
1158
+ );
707
1159
  },
708
1160
  return() {
709
1161
  }
@@ -745,7 +1197,11 @@ function ensureExpectedCloseTag(parser, closeTag) {
745
1197
  const closeTagNameStart = closeTag.start + 2;
746
1198
  const closeTagNameEnd = closeTag.end - 1;
747
1199
  if (!activeTag) {
748
- parser.emitError(closeTag, 0 /* EXTRA_CLOSING_TAG */, 'The closing "' + parser.read({ start: closeTagNameStart, end: closeTagNameEnd }) + '" tag was not expected');
1200
+ parser.emitError(
1201
+ closeTag,
1202
+ 0 /* EXTRA_CLOSING_TAG */,
1203
+ 'The closing "' + parser.read({ start: closeTagNameStart, end: closeTagNameEnd }) + '" tag was not expected'
1204
+ );
749
1205
  return false;
750
1206
  }
751
1207
  const closeTagNamePos = {
@@ -753,12 +1209,19 @@ function ensureExpectedCloseTag(parser, closeTag) {
753
1209
  end: closeTagNameEnd
754
1210
  };
755
1211
  if (closeTagNameStart < closeTagNameEnd) {
756
- if (!parser.matchAtPos(closeTagNamePos, activeTag.tagName.end > activeTag.tagName.start ? activeTag.tagName : "div")) {
1212
+ if (!parser.matchAtPos(
1213
+ closeTagNamePos,
1214
+ activeTag.tagName.end > activeTag.tagName.start ? activeTag.tagName : "div"
1215
+ )) {
757
1216
  if (activeTag.shorthandEnd === void 0 || !parser.matchAtPos(closeTagNamePos, {
758
1217
  start: activeTag.tagName.start,
759
1218
  end: activeTag.shorthandEnd
760
1219
  })) {
761
- 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');
1220
+ parser.emitError(
1221
+ closeTag,
1222
+ 21 /* MISMATCHED_CLOSING_TAG */,
1223
+ 'The closing "' + parser.read(closeTagNamePos) + '" tag does not match the corresponding opening "' + (parser.read(activeTag.tagName) || "div") + '" tag'
1224
+ );
762
1225
  return false;
763
1226
  }
764
1227
  }
@@ -794,18 +1257,30 @@ var CONCISE_HTML_CONTENT = {
794
1257
  parentTag = this.activeTag;
795
1258
  }
796
1259
  if (!parentTag && curIndent) {
797
- this.emitError(this.pos, 7 /* INVALID_INDENTATION */, "Line has extra indentation at the beginning");
1260
+ this.emitError(
1261
+ this.pos,
1262
+ 7 /* INVALID_INDENTATION */,
1263
+ "Line has extra indentation at the beginning"
1264
+ );
798
1265
  return;
799
1266
  }
800
1267
  if (parentTag) {
801
1268
  if (parentTag.type === 1 /* text */ && code !== 45 /* HTML_BLOCK_DELIMITER */) {
802
- this.emitError(this.pos, 8 /* INVALID_LINE_START */, 'A line within a tag that only allows text content must begin with a "-" character');
1269
+ this.emitError(
1270
+ this.pos,
1271
+ 8 /* INVALID_LINE_START */,
1272
+ 'A line within a tag that only allows text content must begin with a "-" character'
1273
+ );
803
1274
  return;
804
1275
  }
805
1276
  if (parentTag.nestedIndent === void 0) {
806
1277
  parentTag.nestedIndent = this.indent;
807
1278
  } else if (parentTag.nestedIndent !== this.indent) {
808
- this.emitError(this.pos, 7 /* INVALID_INDENTATION */, "Line indentation does match indentation of previous line");
1279
+ this.emitError(
1280
+ this.pos,
1281
+ 7 /* INVALID_INDENTATION */,
1282
+ "Line indentation does match indentation of previous line"
1283
+ );
809
1284
  return;
810
1285
  }
811
1286
  }
@@ -827,7 +1302,11 @@ var CONCISE_HTML_CONTENT = {
827
1302
  this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
828
1303
  this.pos--;
829
1304
  } else {
830
- 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');
1305
+ this.emitError(
1306
+ this.pos,
1307
+ 8 /* INVALID_LINE_START */,
1308
+ 'A line in concise mode cannot start with a single hyphen. Use "--" instead. See: https://github.com/marko-js/htmljs-parser/issues/43'
1309
+ );
831
1310
  }
832
1311
  return;
833
1312
  case 47 /* FORWARD_SLASH */:
@@ -841,7 +1320,11 @@ var CONCISE_HTML_CONTENT = {
841
1320
  this.pos++;
842
1321
  return;
843
1322
  default:
844
- this.emitError(this.pos, 8 /* INVALID_LINE_START */, 'A line in concise mode cannot start with "/" unless it starts a "//" or "/*" comment');
1323
+ this.emitError(
1324
+ this.pos,
1325
+ 8 /* INVALID_LINE_START */,
1326
+ 'A line in concise mode cannot start with "/" unless it starts a "//" or "/*" comment'
1327
+ );
845
1328
  return;
846
1329
  }
847
1330
  }
@@ -878,7 +1361,11 @@ var CONCISE_HTML_CONTENT = {
878
1361
  }
879
1362
  });
880
1363
  if (!this.consumeWhitespaceOnLine(0)) {
881
- this.emitError(this.pos, 4 /* INVALID_CHARACTER */, "In concise mode a javascript comment block can only be followed by whitespace characters and a newline.");
1364
+ this.emitError(
1365
+ this.pos,
1366
+ 4 /* INVALID_CHARACTER */,
1367
+ "In concise mode a javascript comment block can only be followed by whitespace characters and a newline."
1368
+ );
882
1369
  }
883
1370
  break;
884
1371
  }
@@ -912,7 +1399,11 @@ var DECLARATION = {
912
1399
  eol() {
913
1400
  },
914
1401
  eof(declaration) {
915
- this.emitError(declaration, 17 /* MALFORMED_DECLARATION */, "EOF reached while parsing declaration");
1402
+ this.emitError(
1403
+ declaration,
1404
+ 17 /* MALFORMED_DECLARATION */,
1405
+ "EOF reached while parsing declaration"
1406
+ );
916
1407
  },
917
1408
  return() {
918
1409
  }
@@ -963,16 +1454,29 @@ var DTD = {
963
1454
  eol() {
964
1455
  },
965
1456
  eof(documentType) {
966
- this.emitError(documentType, 18 /* MALFORMED_DOCUMENT_TYPE */, "EOF reached while parsing document type");
1457
+ this.emitError(
1458
+ documentType,
1459
+ 18 /* MALFORMED_DOCUMENT_TYPE */,
1460
+ "EOF reached while parsing document type"
1461
+ );
967
1462
  },
968
1463
  return() {
969
1464
  }
970
1465
  };
971
1466
 
972
1467
  // src/states/EXPRESSION.ts
973
- var htmlAttrsPattern = buildPattern(0 /* HTML_ATTRS */);
974
- var conciseAttrsPattern = buildPattern(1 /* CONCISE_ATTRS */);
975
- var conciseAttrsGroupPattern = buildPattern(2 /* CONCISE_ATTRS_GROUP */);
1468
+ var shouldTerminate = () => false;
1469
+ var unaryKeywords = [
1470
+ "async",
1471
+ "await",
1472
+ "keyof",
1473
+ "class",
1474
+ "function",
1475
+ "new",
1476
+ "typeof",
1477
+ "void"
1478
+ ];
1479
+ var binaryKeywords = ["instanceof", "in", "as", "extends"];
976
1480
  var EXPRESSION = {
977
1481
  name: "EXPRESSION",
978
1482
  enter(parent, start) {
@@ -982,8 +1486,8 @@ var EXPRESSION = {
982
1486
  start,
983
1487
  end: start,
984
1488
  groupStack: [],
985
- terminator: -1,
986
- skipOperators: false,
1489
+ shouldTerminate,
1490
+ operators: false,
987
1491
  terminatedByEOL: false,
988
1492
  terminatedByWhitespace: false
989
1493
  };
@@ -993,12 +1497,12 @@ var EXPRESSION = {
993
1497
  char(code, expression) {
994
1498
  if (!expression.groupStack.length) {
995
1499
  if (expression.terminatedByWhitespace && isWhitespaceCode(code)) {
996
- if (!checkForOperators(this, expression)) {
1500
+ if (!checkForOperators(this, expression, false)) {
997
1501
  this.exitState();
998
1502
  }
999
1503
  return;
1000
1504
  }
1001
- if (typeof expression.terminator === "number" ? expression.terminator === code : checkForTerminators(this, code, expression.terminator)) {
1505
+ if (expression.shouldTerminate(code, this.data, this.pos)) {
1002
1506
  this.exitState();
1003
1507
  return;
1004
1508
  }
@@ -1024,7 +1528,7 @@ var EXPRESSION = {
1024
1528
  this.pos++;
1025
1529
  break;
1026
1530
  default: {
1027
- if (canCharCodeBeFollowedByDivision(this.getPreviousNonWhitespaceCharCode())) {
1531
+ if (canFollowDivision(this.getPreviousNonWhitespaceCharCode())) {
1028
1532
  this.pos++;
1029
1533
  this.consumeWhitespace();
1030
1534
  } else {
@@ -1047,18 +1551,26 @@ var EXPRESSION = {
1047
1551
  case 93 /* CLOSE_SQUARE_BRACKET */:
1048
1552
  case 125 /* CLOSE_CURLY_BRACE */: {
1049
1553
  if (!expression.groupStack.length) {
1050
- 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.');
1554
+ return this.emitError(
1555
+ expression,
1556
+ 6 /* INVALID_EXPRESSION */,
1557
+ 'Mismatched group. A closing "' + String.fromCharCode(code) + '" character was found but it is not matched with a corresponding opening character.'
1558
+ );
1051
1559
  }
1052
1560
  const expectedCode = expression.groupStack.pop();
1053
1561
  if (expectedCode !== code) {
1054
- return this.emitError(expression, 6 /* INVALID_EXPRESSION */, 'Mismatched group. A "' + String.fromCharCode(code) + '" character was found when "' + String.fromCharCode(expectedCode) + '" was expected.');
1562
+ return this.emitError(
1563
+ expression,
1564
+ 6 /* INVALID_EXPRESSION */,
1565
+ 'Mismatched group. A "' + String.fromCharCode(code) + '" character was found when "' + String.fromCharCode(expectedCode) + '" was expected.'
1566
+ );
1055
1567
  }
1056
1568
  break;
1057
1569
  }
1058
1570
  }
1059
1571
  },
1060
1572
  eol(_, expression) {
1061
- if (!expression.groupStack.length && (expression.terminatedByEOL || expression.terminatedByWhitespace) && !checkForOperators(this, expression)) {
1573
+ if (!expression.groupStack.length && (expression.terminatedByEOL || expression.terminatedByWhitespace) && !checkForOperators(this, expression, true)) {
1062
1574
  this.exitState();
1063
1575
  }
1064
1576
  },
@@ -1071,69 +1583,216 @@ var EXPRESSION = {
1071
1583
  case states_exports.ATTRIBUTE: {
1072
1584
  const attr = parent;
1073
1585
  if (!attr.spread && !attr.name) {
1074
- return this.emitError(expression, 19 /* MALFORMED_OPEN_TAG */, 'EOF reached while parsing attribute name for the "' + this.read(this.activeTag.tagName) + '" tag');
1586
+ return this.emitError(
1587
+ expression,
1588
+ 19 /* MALFORMED_OPEN_TAG */,
1589
+ 'EOF reached while parsing attribute name for the "' + this.read(this.activeTag.tagName) + '" tag'
1590
+ );
1075
1591
  }
1076
- 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`);
1592
+ return this.emitError(
1593
+ expression,
1594
+ 19 /* MALFORMED_OPEN_TAG */,
1595
+ `EOF reached while parsing attribute value for the ${attr.spread ? "..." : attr.name ? `"${this.read(attr.name)}"` : `"default"`} attribute`
1596
+ );
1077
1597
  }
1078
1598
  case states_exports.TAG_NAME:
1079
- return this.emitError(expression, 19 /* MALFORMED_OPEN_TAG */, "EOF reached while parsing tag name");
1599
+ return this.emitError(
1600
+ expression,
1601
+ 19 /* MALFORMED_OPEN_TAG */,
1602
+ "EOF reached while parsing tag name"
1603
+ );
1080
1604
  case states_exports.PLACEHOLDER:
1081
- return this.emitError(expression, 20 /* MALFORMED_PLACEHOLDER */, "EOF reached while parsing placeholder");
1605
+ return this.emitError(
1606
+ expression,
1607
+ 20 /* MALFORMED_PLACEHOLDER */,
1608
+ "EOF reached while parsing placeholder"
1609
+ );
1082
1610
  }
1083
- return this.emitError(expression, 6 /* INVALID_EXPRESSION */, "EOF reached while parsing expression");
1611
+ return this.emitError(
1612
+ expression,
1613
+ 6 /* INVALID_EXPRESSION */,
1614
+ "EOF reached while parsing expression"
1615
+ );
1084
1616
  }
1085
1617
  },
1086
1618
  return() {
1087
1619
  }
1088
1620
  };
1089
- function buildPattern(type) {
1090
- const space = type === 1 /* CONCISE_ATTRS */ ? "[ \\t]" : "\\s";
1091
- const binary = `(?:[!~*%&^|?<]+=*)+|:+(?!=)|[>/+=-]+=|=>|(?<!\\+)[ \\t]*\\+(?:\\s*\\+\\s*\\+)*\\s*(?!\\+)|(?<!-)-${type === 1 /* CONCISE_ATTRS */ ? "" : "(?:\\s*-\\s*-)*\\s*"}(?!-)|(?<!\\.)\\.(?!\\.)|>${type === 0 /* HTML_ATTRS */ ? "{2,}" : "+"}|[ \\t]+(?:in(?:stanceof)?|as|extends)(?=[ \\t]+[^=/,;:>])`;
1092
- const unary = "\\b(?<![.]\\s*)(?:a(?:sync|wait)|keyof|class|function|new|typeof|void)\\b";
1093
- const lookAheadPattern = `${space}*(?:${binary})\\s*|${space}+(?=[{(]|/[^>])`;
1094
- const lookBehindPattern = `(?<=${unary}|${binary})`;
1095
- return new RegExp(`${lookAheadPattern}|${lookBehindPattern}`, "ym");
1096
- }
1097
- function checkForOperators(parser, expression) {
1098
- var _a;
1099
- if (expression.skipOperators) {
1621
+ function checkForOperators(parser, expression, eol) {
1622
+ if (!expression.operators)
1100
1623
  return false;
1624
+ const { pos, data } = parser;
1625
+ if (lookBehindForOperator(data, pos) !== -1) {
1626
+ parser.consumeWhitespace();
1627
+ parser.forward = 0;
1628
+ return true;
1101
1629
  }
1102
- const pattern = parser.isConcise ? ((_a = parser.activeTag) == null ? void 0 : _a.stage) === states_exports.TAG_STAGE.ATTR_GROUP ? conciseAttrsGroupPattern : conciseAttrsPattern : expression.terminatedByEOL ? conciseAttrsPattern : htmlAttrsPattern;
1103
- pattern.lastIndex = parser.pos;
1104
- const matches = pattern.exec(parser.data);
1105
- if (matches) {
1106
- const [match] = matches;
1107
- if (match.length === 0) {
1108
- parser.consumeWhitespace();
1109
- } else {
1110
- parser.pos += match.length;
1630
+ const terminatedByEOL = expression.terminatedByEOL || parser.isConcise;
1631
+ if (!(terminatedByEOL && eol)) {
1632
+ const nextNonSpace = lookAheadWhile(
1633
+ terminatedByEOL ? isIndentCode : isWhitespaceCode,
1634
+ data,
1635
+ pos + 1
1636
+ );
1637
+ if (!expression.shouldTerminate(
1638
+ data.charCodeAt(nextNonSpace),
1639
+ data,
1640
+ nextNonSpace
1641
+ )) {
1642
+ const lookAheadPos = lookAheadForOperator(data, nextNonSpace);
1643
+ if (lookAheadPos !== -1) {
1644
+ parser.pos = lookAheadPos;
1645
+ parser.forward = 0;
1646
+ return true;
1647
+ }
1111
1648
  }
1112
- parser.forward = 0;
1113
- } else {
1114
- return false;
1115
1649
  }
1116
- return true;
1650
+ return false;
1117
1651
  }
1118
- function checkForTerminators(parser, code, terminators) {
1119
- outer:
1120
- for (const terminator of terminators) {
1121
- if (typeof terminator === "number") {
1122
- if (code === terminator)
1123
- return true;
1124
- } else {
1125
- if (terminator[0] === code) {
1126
- for (let i = terminator.length; i-- > 1; ) {
1127
- if (parser.data.charCodeAt(parser.pos + i) !== terminator[i])
1128
- continue outer;
1129
- }
1130
- return true;
1652
+ function lookBehindForOperator(data, pos) {
1653
+ const curPos = pos - 1;
1654
+ const code = data.charCodeAt(curPos);
1655
+ switch (code) {
1656
+ case 38 /* AMPERSAND */:
1657
+ case 42 /* ASTERISK */:
1658
+ case 94 /* CARET */:
1659
+ case 58 /* COLON */:
1660
+ case 61 /* EQUAL */:
1661
+ case 33 /* EXCLAMATION */:
1662
+ case 60 /* OPEN_ANGLE_BRACKET */:
1663
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1664
+ case 37 /* PERCENT */:
1665
+ case 46 /* PERIOD */:
1666
+ case 124 /* PIPE */:
1667
+ case 63 /* QUESTION */:
1668
+ case 126 /* TILDE */:
1669
+ return curPos;
1670
+ case 43 /* PLUS */:
1671
+ case 45 /* HYPHEN */: {
1672
+ if (data.charCodeAt(curPos - 1) === code) {
1673
+ return lookBehindForOperator(
1674
+ data,
1675
+ lookBehindWhile(isWhitespaceCode, data, curPos - 2)
1676
+ );
1677
+ }
1678
+ return curPos;
1679
+ }
1680
+ default: {
1681
+ for (const keyword of unaryKeywords) {
1682
+ const keywordPos = lookBehindFor(data, curPos, keyword);
1683
+ if (keywordPos !== -1) {
1684
+ return data.charCodeAt(keywordPos - 1) === 46 /* PERIOD */ ? -1 : keywordPos;
1685
+ }
1686
+ }
1687
+ return -1;
1688
+ }
1689
+ }
1690
+ }
1691
+ function lookAheadForOperator(data, pos) {
1692
+ switch (data.charCodeAt(pos)) {
1693
+ case 38 /* AMPERSAND */:
1694
+ case 42 /* ASTERISK */:
1695
+ case 94 /* CARET */:
1696
+ case 33 /* EXCLAMATION */:
1697
+ case 60 /* OPEN_ANGLE_BRACKET */:
1698
+ case 37 /* PERCENT */:
1699
+ case 124 /* PIPE */:
1700
+ case 63 /* QUESTION */:
1701
+ case 126 /* TILDE */:
1702
+ case 43 /* PLUS */:
1703
+ case 45 /* HYPHEN */:
1704
+ case 58 /* COLON */:
1705
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1706
+ case 61 /* EQUAL */:
1707
+ return pos + 1;
1708
+ case 47 /* FORWARD_SLASH */:
1709
+ case 123 /* OPEN_CURLY_BRACE */:
1710
+ case 40 /* OPEN_PAREN */:
1711
+ return pos;
1712
+ case 46 /* PERIOD */:
1713
+ return data.charCodeAt(pos + 1) === 46 /* PERIOD */ ? -1 : pos + 1;
1714
+ default: {
1715
+ for (const keyword of binaryKeywords) {
1716
+ let nextPos = lookAheadFor(data, pos, keyword);
1717
+ if (nextPos === -1)
1718
+ continue;
1719
+ const max = data.length - 1;
1720
+ if (nextPos === max)
1721
+ return -1;
1722
+ let nextCode = data.charCodeAt(nextPos + 1);
1723
+ if (isWhitespaceCode(nextCode)) {
1724
+ nextPos = lookAheadWhile(isWhitespaceCode, data, nextPos + 2);
1725
+ if (nextPos === max)
1726
+ return -1;
1727
+ nextCode = data.charCodeAt(nextPos);
1728
+ } else if (isWordCode(nextCode)) {
1729
+ return -1;
1730
+ }
1731
+ switch (nextCode) {
1732
+ case 58 /* COLON */:
1733
+ case 44 /* COMMA */:
1734
+ case 61 /* EQUAL */:
1735
+ case 47 /* FORWARD_SLASH */:
1736
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1737
+ case 59 /* SEMICOLON */:
1738
+ return -1;
1739
+ default:
1740
+ return nextPos;
1131
1741
  }
1132
1742
  }
1743
+ return -1;
1744
+ }
1745
+ }
1746
+ }
1747
+ function canFollowDivision(code) {
1748
+ 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 */;
1749
+ }
1750
+ function isWordCode(code) {
1751
+ 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 */;
1752
+ }
1753
+ function isIndentCode(code) {
1754
+ return code === 9 /* TAB */ || code === 32 /* SPACE */;
1755
+ }
1756
+ function lookAheadWhile(match, data, pos) {
1757
+ const max = data.length;
1758
+ for (let i = pos; i < max; i++) {
1759
+ if (!match(data.charCodeAt(i)))
1760
+ return i;
1761
+ }
1762
+ return max - 1;
1763
+ }
1764
+ function lookBehindWhile(match, data, pos) {
1765
+ let i = pos;
1766
+ do {
1767
+ if (!match(data.charCodeAt(i))) {
1768
+ return i + 1;
1769
+ }
1770
+ } while (i--);
1771
+ return 0;
1772
+ }
1773
+ function lookBehindFor(data, pos, str) {
1774
+ let i = str.length;
1775
+ const endPos = pos - i + 1;
1776
+ if (endPos < 0)
1777
+ return -1;
1778
+ while (i--) {
1779
+ if (data.charCodeAt(endPos + i) !== str.charCodeAt(i)) {
1780
+ return -1;
1133
1781
  }
1782
+ }
1783
+ return endPos;
1134
1784
  }
1135
- function canCharCodeBeFollowedByDivision(code) {
1136
- 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 */;
1785
+ function lookAheadFor(data, pos, str) {
1786
+ let i = str.length;
1787
+ const endPos = pos + i;
1788
+ if (endPos > data.length)
1789
+ return -1;
1790
+ while (i--) {
1791
+ if (data.charCodeAt(pos + i) !== str.charCodeAt(i)) {
1792
+ return -1;
1793
+ }
1794
+ }
1795
+ return endPos - 1;
1137
1796
  }
1138
1797
 
1139
1798
  // src/states/HTML_COMMENT.ts
@@ -1174,7 +1833,11 @@ var HTML_COMMENT = {
1174
1833
  eol() {
1175
1834
  },
1176
1835
  eof(comment) {
1177
- this.emitError(comment, 16 /* MALFORMED_COMMENT */, "EOF reached while parsing comment");
1836
+ this.emitError(
1837
+ comment,
1838
+ 16 /* MALFORMED_COMMENT */,
1839
+ "EOF reached while parsing comment"
1840
+ );
1178
1841
  },
1179
1842
  return() {
1180
1843
  }
@@ -1348,11 +2011,10 @@ var INLINE_SCRIPT = {
1348
2011
  if (code === 123 /* OPEN_CURLY_BRACE */) {
1349
2012
  inlineScript.block = true;
1350
2013
  this.pos++;
1351
- const expr = this.enterState(states_exports.EXPRESSION);
1352
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
1353
- expr.skipOperators = true;
2014
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1354
2015
  } else {
1355
2016
  const expr = this.enterState(states_exports.EXPRESSION);
2017
+ expr.operators = true;
1356
2018
  expr.terminatedByEOL = true;
1357
2019
  }
1358
2020
  },
@@ -1387,7 +2049,11 @@ var JS_COMMENT_BLOCK = {
1387
2049
  eol() {
1388
2050
  },
1389
2051
  eof(comment) {
1390
- this.emitError(comment, 16 /* MALFORMED_COMMENT */, "EOF reached while parsing multi-line JavaScript comment");
2052
+ this.emitError(
2053
+ comment,
2054
+ 16 /* MALFORMED_COMMENT */,
2055
+ "EOF reached while parsing multi-line JavaScript comment"
2056
+ );
1391
2057
  },
1392
2058
  return() {
1393
2059
  }
@@ -1510,7 +2176,11 @@ var PLACEHOLDER = {
1510
2176
  },
1511
2177
  return(child) {
1512
2178
  if (child.start === child.end) {
1513
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2179
+ this.emitError(
2180
+ child,
2181
+ 20 /* MALFORMED_PLACEHOLDER */,
2182
+ "Invalid placeholder, the expression cannot be missing"
2183
+ );
1514
2184
  }
1515
2185
  this.pos++;
1516
2186
  this.exitState();
@@ -1550,7 +2220,7 @@ function checkForPlaceholder(parser, code) {
1550
2220
  parser.enterState(PLACEHOLDER).escape = escape;
1551
2221
  parser.pos += escape ? 2 : 3;
1552
2222
  parser.forward = 0;
1553
- parser.enterState(states_exports.EXPRESSION).terminator = 125 /* CLOSE_CURLY_BRACE */;
2223
+ parser.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1554
2224
  return true;
1555
2225
  }
1556
2226
  }
@@ -1584,10 +2254,18 @@ var REGULAR_EXPRESSION = {
1584
2254
  }
1585
2255
  },
1586
2256
  eol(_, regExp) {
1587
- this.emitError(regExp, 9 /* INVALID_REGULAR_EXPRESSION */, "EOL reached while parsing regular expression");
2257
+ this.emitError(
2258
+ regExp,
2259
+ 9 /* INVALID_REGULAR_EXPRESSION */,
2260
+ "EOL reached while parsing regular expression"
2261
+ );
1588
2262
  },
1589
2263
  eof(regExp) {
1590
- this.emitError(regExp, 9 /* INVALID_REGULAR_EXPRESSION */, "EOF reached while parsing regular expression");
2264
+ this.emitError(
2265
+ regExp,
2266
+ 9 /* INVALID_REGULAR_EXPRESSION */,
2267
+ "EOF reached while parsing regular expression"
2268
+ );
1591
2269
  },
1592
2270
  return() {
1593
2271
  }
@@ -1621,7 +2299,11 @@ var STRING = {
1621
2299
  eol() {
1622
2300
  },
1623
2301
  eof(string) {
1624
- this.emitError(string, 10 /* INVALID_STRING */, "EOF reached while parsing string expression");
2302
+ this.emitError(
2303
+ string,
2304
+ 10 /* INVALID_STRING */,
2305
+ "EOF reached while parsing string expression"
2306
+ );
1625
2307
  },
1626
2308
  return() {
1627
2309
  }
@@ -1649,7 +2331,11 @@ var TAG_NAME = {
1649
2331
  switch (tagName.shorthandCode) {
1650
2332
  case 35 /* NUMBER_SIGN */:
1651
2333
  if (this.activeTag.hasShorthandId) {
1652
- return this.emitError(tagName, 12 /* INVALID_TAG_SHORTHAND */, "Multiple shorthand ID parts are not allowed on the same tag");
2334
+ return this.emitError(
2335
+ tagName,
2336
+ 12 /* INVALID_TAG_SHORTHAND */,
2337
+ "Multiple shorthand ID parts are not allowed on the same tag"
2338
+ );
1653
2339
  }
1654
2340
  this.activeTag.hasShorthandId = true;
1655
2341
  (_b = (_a = this.options).onTagShorthandId) == null ? void 0 : _b.call(_a, {
@@ -1680,12 +2366,26 @@ var TAG_NAME = {
1680
2366
  tag.type = tagType;
1681
2367
  if (tagType === 3 /* statement */) {
1682
2368
  if (!tag.concise) {
1683
- return this.emitError(tagName, 24 /* RESERVED_TAG_NAME */, `The "${this.read(tagName)}" tag is reserved and cannot be used as an HTML tag.`);
2369
+ return this.emitError(
2370
+ tagName,
2371
+ 24 /* RESERVED_TAG_NAME */,
2372
+ `The "${this.read(
2373
+ tagName
2374
+ )}" tag is reserved and cannot be used as an HTML tag.`
2375
+ );
1684
2376
  }
1685
2377
  if (tag.parentTag) {
1686
- return this.emitError(tagName, 25 /* ROOT_TAG_ONLY */, `"${this.read(tagName)}" can only be used at the root of the template.`);
2378
+ return this.emitError(
2379
+ tagName,
2380
+ 25 /* ROOT_TAG_ONLY */,
2381
+ `"${this.read(
2382
+ tagName
2383
+ )}" can only be used at the root of the template.`
2384
+ );
1687
2385
  }
1688
- this.enterState(states_exports.EXPRESSION).terminatedByEOL = true;
2386
+ const expr = this.enterState(states_exports.EXPRESSION);
2387
+ expr.operators = true;
2388
+ expr.terminatedByEOL = true;
1689
2389
  }
1690
2390
  }
1691
2391
  break;
@@ -1696,7 +2396,7 @@ var TAG_NAME = {
1696
2396
  if (code === 36 /* DOLLAR */ && this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
1697
2397
  this.pos += 2;
1698
2398
  this.forward = 0;
1699
- this.enterState(states_exports.EXPRESSION).terminator = 125 /* CLOSE_CURLY_BRACE */;
2399
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1700
2400
  } 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 */)) {
1701
2401
  this.activeTag.shorthandEnd = this.pos;
1702
2402
  this.exitState();
@@ -1718,7 +2418,11 @@ var TAG_NAME = {
1718
2418
  if (child.terminatedByEOL)
1719
2419
  return;
1720
2420
  if (child.start === child.end) {
1721
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2421
+ this.emitError(
2422
+ child,
2423
+ 20 /* MALFORMED_PLACEHOLDER */,
2424
+ "Invalid placeholder, the expression cannot be missing"
2425
+ );
1722
2426
  }
1723
2427
  const { quasis, expressions } = tagName;
1724
2428
  const start = child.start - 2;
@@ -1751,334 +2455,43 @@ var TEMPLATE_STRING = {
1751
2455
  exit() {
1752
2456
  },
1753
2457
  char(code) {
1754
- if (code === 36 /* DOLLAR */ && this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
1755
- this.pos++;
1756
- const expr = this.enterState(states_exports.EXPRESSION);
1757
- expr.skipOperators = true;
1758
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
1759
- } else {
1760
- if (code === 92 /* BACK_SLASH */) {
2458
+ switch (code) {
2459
+ case 36 /* DOLLAR */:
2460
+ if (this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
2461
+ this.pos++;
2462
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
2463
+ }
2464
+ break;
2465
+ case 92 /* BACK_SLASH */:
1761
2466
  this.pos++;
1762
- } else if (code === 96 /* BACKTICK */) {
2467
+ break;
2468
+ case 96 /* BACKTICK */:
1763
2469
  this.pos++;
1764
2470
  this.exitState();
1765
- }
2471
+ break;
1766
2472
  }
1767
2473
  },
1768
2474
  eof(templateString) {
1769
- this.emitError(templateString, 13 /* INVALID_TEMPLATE_STRING */, "EOF reached while parsing template string expression");
2475
+ this.emitError(
2476
+ templateString,
2477
+ 13 /* INVALID_TEMPLATE_STRING */,
2478
+ "EOF reached while parsing template string expression"
2479
+ );
1770
2480
  },
1771
2481
  eol() {
1772
2482
  },
1773
2483
  return(child) {
1774
2484
  if (child.start === child.end) {
1775
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2485
+ this.emitError(
2486
+ child,
2487
+ 20 /* MALFORMED_PLACEHOLDER */,
2488
+ "Invalid placeholder, the expression cannot be missing"
2489
+ );
1776
2490
  }
1777
2491
  this.pos++;
1778
2492
  }
1779
2493
  };
1780
2494
 
1781
- // src/states/OPEN_TAG.ts
1782
- var TAG_STAGE = /* @__PURE__ */ ((TAG_STAGE2) => {
1783
- TAG_STAGE2[TAG_STAGE2["UNKNOWN"] = 0] = "UNKNOWN";
1784
- TAG_STAGE2[TAG_STAGE2["VAR"] = 1] = "VAR";
1785
- TAG_STAGE2[TAG_STAGE2["ARGUMENT"] = 2] = "ARGUMENT";
1786
- TAG_STAGE2[TAG_STAGE2["PARAMS"] = 3] = "PARAMS";
1787
- TAG_STAGE2[TAG_STAGE2["ATTR_GROUP"] = 4] = "ATTR_GROUP";
1788
- return TAG_STAGE2;
1789
- })(TAG_STAGE || {});
1790
- var CONCISE_TAG_VAR_TERMINATORS = [
1791
- 59 /* SEMICOLON */,
1792
- 40 /* OPEN_PAREN */,
1793
- 124 /* PIPE */,
1794
- 61 /* EQUAL */,
1795
- 44 /* COMMA */,
1796
- [58 /* COLON */, 61 /* EQUAL */]
1797
- ];
1798
- var HTML_TAG_VAR_TERMINATORS = [
1799
- 62 /* CLOSE_ANGLE_BRACKET */,
1800
- 40 /* OPEN_PAREN */,
1801
- 124 /* PIPE */,
1802
- 61 /* EQUAL */,
1803
- 44 /* COMMA */,
1804
- [58 /* COLON */, 61 /* EQUAL */],
1805
- [47 /* FORWARD_SLASH */, 62 /* CLOSE_ANGLE_BRACKET */]
1806
- ];
1807
- var OPEN_TAG = {
1808
- name: "OPEN_TAG",
1809
- enter(parent, start) {
1810
- const tag = this.activeTag = {
1811
- state: OPEN_TAG,
1812
- type: 0 /* html */,
1813
- parent,
1814
- start,
1815
- end: start,
1816
- stage: 0 /* UNKNOWN */,
1817
- parentTag: this.activeTag,
1818
- nestedIndent: void 0,
1819
- indent: this.indent,
1820
- hasShorthandId: false,
1821
- hasArgs: false,
1822
- hasAttrs: false,
1823
- selfClosed: false,
1824
- shorthandEnd: -1,
1825
- tagName: void 0,
1826
- concise: this.isConcise,
1827
- beginMixedMode: this.beginMixedMode || this.endingMixedModeAtEOL
1828
- };
1829
- this.beginMixedMode = false;
1830
- this.endingMixedModeAtEOL = false;
1831
- this.endText();
1832
- return tag;
1833
- },
1834
- exit(tag) {
1835
- var _a, _b;
1836
- const { selfClosed } = tag;
1837
- (_b = (_a = this.options).onOpenTagEnd) == null ? void 0 : _b.call(_a, {
1838
- start: this.pos - (this.isConcise ? 0 : selfClosed ? 2 : 1),
1839
- end: this.pos,
1840
- selfClosed
1841
- });
1842
- switch (selfClosed ? 2 /* void */ : tag.type) {
1843
- case 2 /* void */:
1844
- case 3 /* statement */: {
1845
- if (tag.beginMixedMode)
1846
- this.endingMixedModeAtEOL = true;
1847
- this.activeTag = tag.parentTag;
1848
- break;
1849
- }
1850
- case 1 /* text */:
1851
- if (this.isConcise) {
1852
- this.enterState(states_exports.CONCISE_HTML_CONTENT);
1853
- } else {
1854
- this.enterState(states_exports.PARSED_TEXT_CONTENT);
1855
- }
1856
- break;
1857
- }
1858
- },
1859
- eol(_, tag) {
1860
- if (this.isConcise && tag.stage !== 4 /* ATTR_GROUP */) {
1861
- this.exitState();
1862
- }
1863
- },
1864
- eof(tag) {
1865
- if (this.isConcise) {
1866
- if (tag.stage === 4 /* ATTR_GROUP */) {
1867
- this.emitError(tag, 19 /* MALFORMED_OPEN_TAG */, 'EOF reached while within an attribute group (e.g. "[ ... ]").');
1868
- return;
1869
- }
1870
- this.exitState();
1871
- } else {
1872
- this.emitError(tag, 19 /* MALFORMED_OPEN_TAG */, "EOF reached while parsing open tag");
1873
- }
1874
- },
1875
- char(code, tag) {
1876
- if (this.isConcise) {
1877
- if (code === 59 /* SEMICOLON */) {
1878
- this.pos++;
1879
- this.exitState();
1880
- if (!this.consumeWhitespaceOnLine(0)) {
1881
- switch (this.lookAtCharCodeAhead(0)) {
1882
- case 47 /* FORWARD_SLASH */:
1883
- switch (this.lookAtCharCodeAhead(1)) {
1884
- case 47 /* FORWARD_SLASH */:
1885
- this.enterState(states_exports.JS_COMMENT_LINE);
1886
- this.pos += 2;
1887
- return;
1888
- case 42 /* ASTERISK */:
1889
- this.enterState(states_exports.JS_COMMENT_BLOCK);
1890
- this.pos += 2;
1891
- return;
1892
- }
1893
- break;
1894
- case 60 /* OPEN_ANGLE_BRACKET */:
1895
- if (this.lookAheadFor("!--")) {
1896
- this.enterState(states_exports.HTML_COMMENT);
1897
- this.pos += 4;
1898
- return;
1899
- }
1900
- break;
1901
- }
1902
- this.emitError(this.pos, 5 /* INVALID_CODE_AFTER_SEMICOLON */, "A semicolon indicates the end of a line. Only comments may follow it.");
1903
- }
1904
- return;
1905
- }
1906
- if (code === 45 /* HTML_BLOCK_DELIMITER */) {
1907
- if (this.lookAtCharCodeAhead(1) !== 45 /* HTML_BLOCK_DELIMITER */) {
1908
- this.emitError(tag, 19 /* MALFORMED_OPEN_TAG */, '"-" not allowed as first character of attribute name');
1909
- return;
1910
- }
1911
- if (tag.stage === 4 /* ATTR_GROUP */) {
1912
- this.emitError(this.pos, 19 /* MALFORMED_OPEN_TAG */, "Attribute group was not properly ended");
1913
- return;
1914
- }
1915
- this.exitState();
1916
- const maxPos = this.maxPos;
1917
- let curPos = this.pos + 1;
1918
- while (curPos < maxPos && this.data.charCodeAt(++curPos) !== 10 /* NEWLINE */)
1919
- ;
1920
- const indentStart = ++curPos;
1921
- while (curPos < maxPos) {
1922
- const nextCode = this.data.charCodeAt(curPos);
1923
- if (nextCode === 32 /* SPACE */ || nextCode === 9 /* TAB */) {
1924
- curPos++;
1925
- } else {
1926
- break;
1927
- }
1928
- }
1929
- const indentSize = curPos - indentStart;
1930
- if (indentSize > this.indent.length) {
1931
- this.indent = this.data.slice(indentStart, curPos);
1932
- }
1933
- this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
1934
- return;
1935
- } else if (code === 91 /* OPEN_SQUARE_BRACKET */) {
1936
- if (tag.stage === 4 /* ATTR_GROUP */) {
1937
- this.emitError(this.pos, 19 /* MALFORMED_OPEN_TAG */, 'Unexpected "[" character within open tag.');
1938
- return;
1939
- }
1940
- tag.stage = 4 /* ATTR_GROUP */;
1941
- return;
1942
- } else if (code === 93 /* CLOSE_SQUARE_BRACKET */) {
1943
- if (tag.stage !== 4 /* ATTR_GROUP */) {
1944
- this.emitError(this.pos, 19 /* MALFORMED_OPEN_TAG */, 'Unexpected "]" character within open tag.');
1945
- return;
1946
- }
1947
- tag.stage = 0 /* UNKNOWN */;
1948
- return;
1949
- }
1950
- } else if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
1951
- this.pos++;
1952
- this.exitState();
1953
- return;
1954
- } else if (code === 47 /* FORWARD_SLASH */ && this.lookAtCharCodeAhead(1) === 62 /* CLOSE_ANGLE_BRACKET */) {
1955
- tag.selfClosed = true;
1956
- this.pos += 2;
1957
- this.exitState();
1958
- return;
1959
- }
1960
- if (code === 60 /* OPEN_ANGLE_BRACKET */) {
1961
- return this.emitError(this.pos, 2 /* INVALID_ATTRIBUTE_NAME */, 'Invalid attribute name. Attribute name cannot begin with the "<" character.');
1962
- }
1963
- if (code === 47 /* FORWARD_SLASH */) {
1964
- switch (this.lookAtCharCodeAhead(1)) {
1965
- case 47 /* FORWARD_SLASH */:
1966
- this.enterState(states_exports.JS_COMMENT_LINE);
1967
- this.pos++;
1968
- return;
1969
- case 42 /* ASTERISK */:
1970
- this.enterState(states_exports.JS_COMMENT_BLOCK);
1971
- this.pos++;
1972
- return;
1973
- }
1974
- }
1975
- if (isWhitespaceCode(code)) {
1976
- } else if (code === 44 /* COMMA */) {
1977
- this.pos++;
1978
- this.forward = 0;
1979
- this.consumeWhitespace();
1980
- } else if (code === 47 /* FORWARD_SLASH */ && !tag.hasAttrs) {
1981
- tag.stage = 1 /* VAR */;
1982
- this.pos++;
1983
- this.forward = 0;
1984
- if (isWhitespaceCode(this.lookAtCharCodeAhead(0))) {
1985
- return this.emitError(this.pos, 23 /* MISSING_TAG_VARIABLE */, "A slash was found that was not followed by a variable name or lhs expression");
1986
- }
1987
- const expr = this.enterState(states_exports.EXPRESSION);
1988
- expr.terminatedByWhitespace = true;
1989
- expr.terminator = this.isConcise ? CONCISE_TAG_VAR_TERMINATORS : HTML_TAG_VAR_TERMINATORS;
1990
- } else if (code === 40 /* OPEN_PAREN */ && !tag.hasAttrs) {
1991
- if (tag.hasArgs) {
1992
- this.emitError(this.pos, 11 /* INVALID_TAG_ARGUMENT */, "A tag can only have one argument");
1993
- return;
1994
- }
1995
- tag.stage = 2 /* ARGUMENT */;
1996
- this.pos++;
1997
- this.forward = 0;
1998
- const expr = this.enterState(states_exports.EXPRESSION);
1999
- expr.skipOperators = true;
2000
- expr.terminator = 41 /* CLOSE_PAREN */;
2001
- } else if (code === 124 /* PIPE */ && !tag.hasAttrs) {
2002
- tag.stage = 3 /* PARAMS */;
2003
- this.pos++;
2004
- this.forward = 0;
2005
- const expr = this.enterState(states_exports.EXPRESSION);
2006
- expr.skipOperators = true;
2007
- expr.terminator = 124 /* PIPE */;
2008
- } else {
2009
- this.forward = 0;
2010
- if (tag.tagName) {
2011
- this.enterState(states_exports.ATTRIBUTE);
2012
- tag.hasAttrs = true;
2013
- } else {
2014
- this.enterState(states_exports.TAG_NAME);
2015
- }
2016
- }
2017
- },
2018
- return(child, tag) {
2019
- var _a, _b, _c, _d, _e, _f;
2020
- switch (child.state) {
2021
- case states_exports.JS_COMMENT_BLOCK: {
2022
- break;
2023
- }
2024
- case states_exports.EXPRESSION: {
2025
- switch (tag.stage) {
2026
- case 1 /* VAR */: {
2027
- if (child.start === child.end) {
2028
- return this.emitError(child, 23 /* MISSING_TAG_VARIABLE */, "A slash was found that was not followed by a variable name or lhs expression");
2029
- }
2030
- (_b = (_a = this.options).onTagVar) == null ? void 0 : _b.call(_a, {
2031
- start: child.start - 1,
2032
- end: child.end,
2033
- value: {
2034
- start: child.start,
2035
- end: child.end
2036
- }
2037
- });
2038
- break;
2039
- }
2040
- case 2 /* ARGUMENT */: {
2041
- const start = child.start - 1;
2042
- const end = ++this.pos;
2043
- const value = {
2044
- start: child.start,
2045
- end: child.end
2046
- };
2047
- if (this.consumeWhitespaceIfBefore("{")) {
2048
- const attr = this.enterState(states_exports.ATTRIBUTE);
2049
- attr.start = start;
2050
- attr.args = { start, end, value };
2051
- tag.hasAttrs = true;
2052
- this.forward = 0;
2053
- } else {
2054
- tag.hasArgs = true;
2055
- (_d = (_c = this.options).onTagArgs) == null ? void 0 : _d.call(_c, {
2056
- start,
2057
- end,
2058
- value
2059
- });
2060
- }
2061
- break;
2062
- }
2063
- case 3 /* PARAMS */: {
2064
- const end = ++this.pos;
2065
- (_f = (_e = this.options).onTagParams) == null ? void 0 : _f.call(_e, {
2066
- start: child.start - 1,
2067
- end,
2068
- value: {
2069
- start: child.start,
2070
- end: child.end
2071
- }
2072
- });
2073
- break;
2074
- }
2075
- }
2076
- break;
2077
- }
2078
- }
2079
- }
2080
- };
2081
-
2082
2495
  // src/index.ts
2083
2496
  function createParser(handlers) {
2084
2497
  const parser = new Parser(handlers);