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.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;
@@ -94,34 +107,30 @@ function getPosAfterLine(lines, startLine, index) {
94
107
  var Parser = class {
95
108
  constructor(options) {
96
109
  this.options = options;
97
- this.options = options;
98
110
  }
99
- pos;
100
- maxPos;
101
- data;
102
- activeState;
103
- activeRange;
104
- forward;
105
- activeTag;
106
- activeAttr;
107
- indent;
108
- isConcise;
109
- beginMixedMode;
110
- endingMixedModeAtEOL;
111
- textPos;
112
- lines;
113
111
  read(range) {
114
112
  return this.data.slice(range.start, range.end);
115
113
  }
116
114
  positionAt(offset) {
117
- return getPosition(this.lines || (this.lines = getLines(this.data)), offset);
115
+ return getPosition(
116
+ this.lines || (this.lines = getLines(this.data)),
117
+ offset
118
+ );
118
119
  }
119
120
  locationAt(range) {
120
- return getLocation(this.lines || (this.lines = getLines(this.data)), range.start, range.end);
121
+ return getLocation(
122
+ this.lines || (this.lines = getLines(this.data)),
123
+ range.start,
124
+ range.end
125
+ );
121
126
  }
122
127
  enterState(state) {
123
128
  this.activeState = state;
124
- return this.activeRange = state.enter.call(this, this.activeRange, this.pos);
129
+ return this.activeRange = state.enter.call(
130
+ this,
131
+ this.activeRange,
132
+ this.pos
133
+ );
125
134
  }
126
135
  exitState() {
127
136
  const { activeRange, activeState } = this;
@@ -191,7 +200,9 @@ var Parser = class {
191
200
  }
192
201
  beginHtmlBlock(delimiter, singleLine) {
193
202
  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);
203
+ const content = this.enterState(
204
+ ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ ? states_exports.PARSED_TEXT_CONTENT : states_exports.HTML_CONTENT
205
+ );
195
206
  content.singleLine = singleLine;
196
207
  content.delimiter = delimiter;
197
208
  content.indent = this.indent;
@@ -351,461 +362,910 @@ __export(states_exports, {
351
362
  handleDelimitedEOL: () => handleDelimitedEOL
352
363
  });
353
364
 
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",
365
+ // src/states/OPEN_TAG.ts
366
+ var TAG_STAGE = /* @__PURE__ */ ((TAG_STAGE2) => {
367
+ TAG_STAGE2[TAG_STAGE2["UNKNOWN"] = 0] = "UNKNOWN";
368
+ TAG_STAGE2[TAG_STAGE2["VAR"] = 1] = "VAR";
369
+ TAG_STAGE2[TAG_STAGE2["ARGUMENT"] = 2] = "ARGUMENT";
370
+ TAG_STAGE2[TAG_STAGE2["PARAMS"] = 3] = "PARAMS";
371
+ TAG_STAGE2[TAG_STAGE2["ATTR_GROUP"] = 4] = "ATTR_GROUP";
372
+ return TAG_STAGE2;
373
+ })(TAG_STAGE || {});
374
+ var OPEN_TAG = {
375
+ name: "OPEN_TAG",
383
376
  enter(parent, start) {
384
- return this.activeAttr = {
385
- state: ATTRIBUTE,
377
+ const tag = this.activeTag = {
378
+ state: OPEN_TAG,
379
+ type: 0 /* html */,
386
380
  parent,
387
381
  start,
388
382
  end: start,
389
- valueStart: start,
390
383
  stage: 0 /* UNKNOWN */,
391
- name: void 0,
392
- args: false,
393
- bound: false,
394
- spread: false
384
+ parentTag: this.activeTag,
385
+ nestedIndent: void 0,
386
+ indent: this.indent,
387
+ hasShorthandId: false,
388
+ hasArgs: false,
389
+ hasAttrs: false,
390
+ selfClosed: false,
391
+ shorthandEnd: -1,
392
+ tagName: void 0,
393
+ concise: this.isConcise,
394
+ beginMixedMode: this.beginMixedMode || this.endingMixedModeAtEOL
395
395
  };
396
+ this.beginMixedMode = false;
397
+ this.endingMixedModeAtEOL = false;
398
+ this.endText();
399
+ return tag;
396
400
  },
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();
401
+ exit(tag) {
402
+ var _a, _b;
403
+ const { selfClosed } = tag;
404
+ (_b = (_a = this.options).onOpenTagEnd) == null ? void 0 : _b.call(_a, {
405
+ start: this.pos - (this.isConcise ? 0 : selfClosed ? 2 : 1),
406
+ end: this.pos,
407
+ selfClosed
408
+ });
409
+ switch (selfClosed ? 2 /* void */ : tag.type) {
410
+ case 2 /* void */:
411
+ case 3 /* statement */: {
412
+ if (tag.beginMixedMode)
413
+ this.endingMixedModeAtEOL = true;
414
+ this.activeTag = tag.parentTag;
415
+ break;
418
416
  }
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();
417
+ case 1 /* text */:
418
+ if (this.isConcise) {
419
+ this.enterState(states_exports.CONCISE_HTML_CONTENT);
420
+ } else {
421
+ this.enterState(states_exports.PARSED_TEXT_CONTENT);
422
+ }
423
+ break;
446
424
  }
447
425
  },
448
- eol() {
449
- if (this.isConcise) {
426
+ eol(_, tag) {
427
+ if (this.isConcise && tag.stage !== 4 /* ATTR_GROUP */) {
450
428
  this.exitState();
451
429
  }
452
430
  },
453
- eof(attr) {
431
+ eof(tag) {
454
432
  if (this.isConcise) {
433
+ if (tag.stage === 4 /* ATTR_GROUP */) {
434
+ this.emitError(
435
+ tag,
436
+ 19 /* MALFORMED_OPEN_TAG */,
437
+ 'EOF reached while within an attribute group (e.g. "[ ... ]").'
438
+ );
439
+ return;
440
+ }
455
441
  this.exitState();
456
442
  } 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');
443
+ this.emitError(
444
+ tag,
445
+ 19 /* MALFORMED_OPEN_TAG */,
446
+ "EOF reached while parsing open tag"
447
+ );
458
448
  }
459
449
  },
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;
450
+ char(code, tag) {
451
+ if (this.isConcise) {
452
+ if (code === 59 /* SEMICOLON */) {
453
+ this.pos++;
454
+ this.exitState();
455
+ if (!this.consumeWhitespaceOnLine(0)) {
456
+ switch (this.lookAtCharCodeAhead(0)) {
457
+ case 47 /* FORWARD_SLASH */:
458
+ switch (this.lookAtCharCodeAhead(1)) {
459
+ case 47 /* FORWARD_SLASH */:
460
+ this.enterState(states_exports.JS_COMMENT_LINE);
461
+ this.pos += 2;
462
+ return;
463
+ case 42 /* ASTERISK */:
464
+ this.enterState(states_exports.JS_COMMENT_BLOCK);
465
+ this.pos += 2;
466
+ return;
467
+ }
468
+ break;
469
+ case 60 /* OPEN_ANGLE_BRACKET */:
470
+ if (this.lookAheadFor("!--")) {
471
+ this.enterState(states_exports.HTML_COMMENT);
472
+ this.pos += 4;
473
+ return;
474
+ }
475
+ break;
476
+ }
477
+ this.emitError(
478
+ this.pos,
479
+ 5 /* INVALID_CODE_AFTER_SEMICOLON */,
480
+ "A semicolon indicates the end of a line. Only comments may follow it."
481
+ );
482
+ }
483
+ return;
470
484
  }
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");
485
+ if (code === 45 /* HTML_BLOCK_DELIMITER */) {
486
+ if (this.lookAtCharCodeAhead(1) !== 45 /* HTML_BLOCK_DELIMITER */) {
487
+ this.emitError(
488
+ tag,
489
+ 19 /* MALFORMED_OPEN_TAG */,
490
+ '"-" not allowed as first character of attribute name'
491
+ );
474
492
  return;
475
493
  }
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
- });
494
+ if (tag.stage === 4 /* ATTR_GROUP */) {
495
+ this.emitError(
496
+ this.pos,
497
+ 19 /* MALFORMED_OPEN_TAG */,
498
+ "Attribute group was not properly ended"
499
+ );
500
+ return;
495
501
  }
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
502
  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");
503
+ const maxPos = this.maxPos;
504
+ let curPos = this.pos + 1;
505
+ while (curPos < maxPos && this.data.charCodeAt(++curPos) !== 10 /* NEWLINE */)
506
+ ;
507
+ const indentStart = ++curPos;
508
+ while (curPos < maxPos) {
509
+ const nextCode = this.data.charCodeAt(curPos);
510
+ if (nextCode === 32 /* SPACE */ || nextCode === 9 /* TAB */) {
511
+ curPos++;
512
+ } else {
513
+ break;
514
+ }
521
515
  }
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
- });
516
+ const indentSize = curPos - indentStart;
517
+ if (indentSize > this.indent.length) {
518
+ this.indent = this.data.slice(indentStart, curPos);
541
519
  }
542
- this.exitState();
543
- break;
544
- }
545
- }
546
- }
547
- };
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
- });
555
- }
556
- }
557
-
558
- // src/states/BEGIN_DELIMITED_HTML_BLOCK.ts
559
- var BEGIN_DELIMITED_HTML_BLOCK = {
560
- name: "BEGIN_DELIMITED_HTML_BLOCK",
561
- enter(parent, start) {
562
- return {
563
- state: BEGIN_DELIMITED_HTML_BLOCK,
564
- parent,
565
- start,
566
- end: start,
567
- indent: this.indent,
568
- delimiter: ""
569
- };
570
- },
571
- exit() {
572
- },
573
- char(code, block) {
574
- if (code === 45 /* HTML_BLOCK_DELIMITER */) {
575
- block.delimiter += "-";
520
+ this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
521
+ return;
522
+ } else if (code === 91 /* OPEN_SQUARE_BRACKET */) {
523
+ if (tag.stage === 4 /* ATTR_GROUP */) {
524
+ this.emitError(
525
+ this.pos,
526
+ 19 /* MALFORMED_OPEN_TAG */,
527
+ 'Unexpected "[" character within open tag.'
528
+ );
529
+ return;
530
+ }
531
+ tag.stage = 4 /* ATTR_GROUP */;
532
+ return;
533
+ } else if (code === 93 /* CLOSE_SQUARE_BRACKET */) {
534
+ if (tag.stage !== 4 /* ATTR_GROUP */) {
535
+ this.emitError(
536
+ this.pos,
537
+ 19 /* MALFORMED_OPEN_TAG */,
538
+ 'Unexpected "]" character within open tag.'
539
+ );
540
+ return;
541
+ }
542
+ tag.stage = 0 /* UNKNOWN */;
543
+ return;
544
+ }
545
+ } else if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
546
+ this.pos++;
547
+ this.exitState();
548
+ return;
549
+ } else if (code === 47 /* FORWARD_SLASH */ && this.lookAtCharCodeAhead(1) === 62 /* CLOSE_ANGLE_BRACKET */) {
550
+ tag.selfClosed = true;
551
+ this.pos += 2;
552
+ this.exitState();
553
+ return;
554
+ }
555
+ if (code === 60 /* OPEN_ANGLE_BRACKET */) {
556
+ return this.emitError(
557
+ this.pos,
558
+ 2 /* INVALID_ATTRIBUTE_NAME */,
559
+ 'Invalid attribute name. Attribute name cannot begin with the "<" character.'
560
+ );
561
+ }
562
+ if (code === 47 /* FORWARD_SLASH */) {
563
+ switch (this.lookAtCharCodeAhead(1)) {
564
+ case 47 /* FORWARD_SLASH */:
565
+ this.enterState(states_exports.JS_COMMENT_LINE);
566
+ this.pos++;
567
+ return;
568
+ case 42 /* ASTERISK */:
569
+ this.enterState(states_exports.JS_COMMENT_BLOCK);
570
+ this.pos++;
571
+ return;
572
+ }
573
+ }
574
+ if (isWhitespaceCode(code)) {
575
+ } else if (code === 44 /* COMMA */) {
576
+ this.pos++;
577
+ this.forward = 0;
578
+ this.consumeWhitespace();
579
+ } else if (code === 47 /* FORWARD_SLASH */ && !tag.hasAttrs) {
580
+ tag.stage = 1 /* VAR */;
581
+ this.pos++;
582
+ this.forward = 0;
583
+ if (isWhitespaceCode(this.lookAtCharCodeAhead(0))) {
584
+ return this.emitError(
585
+ this.pos,
586
+ 23 /* MISSING_TAG_VARIABLE */,
587
+ "A slash was found that was not followed by a variable name or lhs expression"
588
+ );
589
+ }
590
+ const expr = this.enterState(states_exports.EXPRESSION);
591
+ expr.operators = true;
592
+ expr.terminatedByWhitespace = true;
593
+ expr.shouldTerminate = this.isConcise ? shouldTerminateConciseTagVar : shouldTerminateHtmlTagVar;
594
+ } else if (code === 40 /* OPEN_PAREN */ && !tag.hasAttrs) {
595
+ if (tag.hasArgs) {
596
+ this.emitError(
597
+ this.pos,
598
+ 11 /* INVALID_TAG_ARGUMENT */,
599
+ "A tag can only have one argument"
600
+ );
601
+ return;
602
+ }
603
+ tag.stage = 2 /* ARGUMENT */;
604
+ this.pos++;
605
+ this.forward = 0;
606
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseParen;
607
+ } else if (code === 124 /* PIPE */ && !tag.hasAttrs) {
608
+ tag.stage = 3 /* PARAMS */;
609
+ this.pos++;
610
+ this.forward = 0;
611
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesPipe;
576
612
  } 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);
613
+ this.forward = 0;
614
+ if (tag.tagName) {
615
+ this.enterState(states_exports.ATTRIBUTE);
616
+ tag.hasAttrs = true;
617
+ } else {
618
+ this.enterState(states_exports.TAG_NAME);
582
619
  }
583
620
  }
584
621
  },
585
- eol(len, block) {
586
- this.beginHtmlBlock(block.delimiter, false);
587
- handleDelimitedBlockEOL(this, len, block);
588
- },
589
- eof: htmlEOF,
590
- return() {
622
+ return(child, tag) {
623
+ var _a, _b, _c, _d, _e, _f;
624
+ switch (child.state) {
625
+ case states_exports.JS_COMMENT_BLOCK: {
626
+ break;
627
+ }
628
+ case states_exports.EXPRESSION: {
629
+ switch (tag.stage) {
630
+ case 1 /* VAR */: {
631
+ if (child.start === child.end) {
632
+ return this.emitError(
633
+ child,
634
+ 23 /* MISSING_TAG_VARIABLE */,
635
+ "A slash was found that was not followed by a variable name or lhs expression"
636
+ );
637
+ }
638
+ (_b = (_a = this.options).onTagVar) == null ? void 0 : _b.call(_a, {
639
+ start: child.start - 1,
640
+ end: child.end,
641
+ value: {
642
+ start: child.start,
643
+ end: child.end
644
+ }
645
+ });
646
+ break;
647
+ }
648
+ case 2 /* ARGUMENT */: {
649
+ const start = child.start - 1;
650
+ const end = ++this.pos;
651
+ const value = {
652
+ start: child.start,
653
+ end: child.end
654
+ };
655
+ if (this.consumeWhitespaceIfBefore("{")) {
656
+ const attr = this.enterState(states_exports.ATTRIBUTE);
657
+ attr.start = start;
658
+ attr.args = { start, end, value };
659
+ tag.hasAttrs = true;
660
+ this.forward = 0;
661
+ } else {
662
+ tag.hasArgs = true;
663
+ (_d = (_c = this.options).onTagArgs) == null ? void 0 : _d.call(_c, {
664
+ start,
665
+ end,
666
+ value
667
+ });
668
+ }
669
+ break;
670
+ }
671
+ case 3 /* PARAMS */: {
672
+ const end = ++this.pos;
673
+ (_f = (_e = this.options).onTagParams) == null ? void 0 : _f.call(_e, {
674
+ start: child.start - 1,
675
+ end,
676
+ value: {
677
+ start: child.start,
678
+ end: child.end
679
+ }
680
+ });
681
+ break;
682
+ }
683
+ }
684
+ break;
685
+ }
686
+ }
591
687
  }
592
688
  };
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;
689
+ function shouldTerminateConciseTagVar(code, data, pos) {
690
+ switch (code) {
691
+ case 44 /* COMMA */:
692
+ case 61 /* EQUAL */:
693
+ case 124 /* PIPE */:
694
+ case 40 /* OPEN_PAREN */:
695
+ case 59 /* SEMICOLON */:
696
+ return true;
697
+ case 58 /* COLON */:
698
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
699
+ default:
700
+ return false;
603
701
  }
604
- return false;
605
702
  }
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();
620
- } else {
621
- parser.emitError(parser.pos, 4 /* INVALID_CHARACTER */, "A concise mode closing block delimiter can only be followed by whitespace.");
622
- }
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();
703
+ function shouldTerminateHtmlTagVar(code, data, pos) {
704
+ switch (code) {
705
+ case 124 /* PIPE */:
706
+ case 44 /* COMMA */:
707
+ case 61 /* EQUAL */:
708
+ case 40 /* OPEN_PAREN */:
709
+ case 62 /* CLOSE_ANGLE_BRACKET */:
710
+ return true;
711
+ case 58 /* COLON */:
712
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
713
+ case 47 /* FORWARD_SLASH */:
714
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
715
+ default:
716
+ return false;
632
717
  }
633
718
  }
634
719
 
635
- // src/states/CDATA.ts
636
- var CDATA = {
637
- name: "CDATA",
720
+ // src/states/ATTRIBUTE.ts
721
+ var ATTRIBUTE = {
722
+ name: "ATTRIBUTE",
638
723
  enter(parent, start) {
639
- return {
640
- state: CDATA,
724
+ return this.activeAttr = {
725
+ state: ATTRIBUTE,
641
726
  parent,
642
727
  start,
643
- end: start
728
+ end: start,
729
+ valueStart: start,
730
+ stage: 0 /* UNKNOWN */,
731
+ name: void 0,
732
+ args: false,
733
+ bound: false,
734
+ spread: false
644
735
  };
645
736
  },
646
- exit(cdata) {
647
- var _a, _b;
648
- (_b = (_a = this.options).onCDATA) == null ? void 0 : _b.call(_a, {
649
- start: cdata.start,
650
- end: cdata.end,
651
- value: {
652
- start: cdata.start + 9,
653
- end: cdata.end - 3
654
- }
655
- });
737
+ exit() {
738
+ this.activeAttr = void 0;
656
739
  },
657
- char(code) {
658
- if (code === 93 /* CLOSE_SQUARE_BRACKET */ && this.lookAheadFor("]>")) {
659
- this.pos += 3;
660
- this.exitState();
740
+ char(code, attr) {
741
+ if (isWhitespaceCode(code)) {
661
742
  return;
662
- }
663
- },
664
- eol() {
665
- },
666
- eof(cdata) {
667
- this.emitError(cdata, 14 /* MALFORMED_CDATA */, "EOF reached while parsing CDATA");
668
- },
669
- return() {
670
- }
671
- };
672
- function checkForCDATA(parser) {
673
- if (parser.lookAheadFor("![CDATA[")) {
674
- parser.endText();
675
- parser.enterState(CDATA);
676
- parser.pos += 8;
677
- return true;
678
- }
679
- return false;
680
- }
681
-
682
- // src/states/CLOSE_TAG.ts
683
- var CLOSE_TAG = {
684
- name: "CLOSE_TAG",
685
- enter(parent, start) {
686
- this.endText();
687
- return {
688
- state: CLOSE_TAG,
689
- parent,
690
- start,
691
- end: start
692
- };
693
- },
694
- exit() {
695
- },
696
- char(code, closeTag) {
697
- if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
743
+ } else if (code === 61 /* EQUAL */ || code === 58 /* COLON */ && this.lookAtCharCodeAhead(1) === 61 /* EQUAL */ || code === 46 /* PERIOD */ && this.lookAheadFor("..")) {
744
+ attr.valueStart = this.pos;
745
+ this.forward = 0;
746
+ if (code === 58 /* COLON */) {
747
+ ensureAttrName(this, attr);
748
+ attr.bound = true;
749
+ this.pos += 2;
750
+ this.consumeWhitespace();
751
+ } else if (code === 46 /* PERIOD */) {
752
+ attr.spread = true;
753
+ this.pos += 3;
754
+ } else {
755
+ ensureAttrName(this, attr);
756
+ this.pos++;
757
+ this.consumeWhitespace();
758
+ }
759
+ attr.stage = 2 /* VALUE */;
760
+ const expr = this.enterState(states_exports.EXPRESSION);
761
+ expr.operators = true;
762
+ expr.terminatedByWhitespace = true;
763
+ expr.shouldTerminate = this.isConcise ? this.activeTag.stage === 4 /* ATTR_GROUP */ ? shouldTerminateConciseGroupedAttrValue : shouldTerminateConciseAttrValue : shouldTerminateHtmlAttrValue;
764
+ } else if (code === 40 /* OPEN_PAREN */) {
765
+ ensureAttrName(this, attr);
766
+ attr.stage = 3 /* ARGUMENT */;
767
+ this.pos++;
768
+ this.forward = 0;
769
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseParen;
770
+ } else if (code === 123 /* OPEN_CURLY_BRACE */ && attr.args) {
771
+ ensureAttrName(this, attr);
772
+ attr.stage = 4 /* BLOCK */;
698
773
  this.pos++;
774
+ this.forward = 0;
775
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
776
+ } else if (attr.stage === 0 /* UNKNOWN */) {
777
+ attr.stage = 1 /* NAME */;
778
+ this.forward = 0;
779
+ const expr = this.enterState(states_exports.EXPRESSION);
780
+ expr.terminatedByWhitespace = true;
781
+ expr.shouldTerminate = this.isConcise ? this.activeTag.stage === 4 /* ATTR_GROUP */ ? shouldTerminateConciseGroupedAttrName : shouldTerminateConciseAttrName : shouldTerminateHtmlAttrName;
782
+ } else {
699
783
  this.exitState();
700
- ensureExpectedCloseTag(this, closeTag);
701
784
  }
702
785
  },
703
786
  eol() {
787
+ if (this.isConcise) {
788
+ this.exitState();
789
+ }
704
790
  },
705
- eof(closeTag) {
706
- this.emitError(closeTag, 15 /* MALFORMED_CLOSE_TAG */, "EOF reached while parsing closing tag");
791
+ eof(attr) {
792
+ if (this.isConcise) {
793
+ this.exitState();
794
+ } else {
795
+ this.emitError(
796
+ attr,
797
+ 19 /* MALFORMED_OPEN_TAG */,
798
+ 'EOF reached while parsing attribute "' + (attr.name ? this.read(attr.name) : "default") + '" for the "' + this.read(this.activeTag.tagName) + '" tag'
799
+ );
800
+ }
707
801
  },
708
- return() {
802
+ return(child, attr) {
803
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
804
+ switch (attr.stage) {
805
+ case 1 /* NAME */: {
806
+ attr.name = {
807
+ start: child.start,
808
+ end: child.end
809
+ };
810
+ (_b = (_a = this.options).onAttrName) == null ? void 0 : _b.call(_a, attr.name);
811
+ break;
812
+ }
813
+ case 3 /* ARGUMENT */: {
814
+ if (attr.args) {
815
+ this.emitError(
816
+ child,
817
+ 1 /* INVALID_ATTRIBUTE_ARGUMENT */,
818
+ "An attribute can only have one set of arguments"
819
+ );
820
+ return;
821
+ }
822
+ const start = child.start - 1;
823
+ const end = ++this.pos;
824
+ const value = {
825
+ start: child.start,
826
+ end: child.end
827
+ };
828
+ if (this.consumeWhitespaceIfBefore("{")) {
829
+ attr.args = {
830
+ start,
831
+ end,
832
+ value
833
+ };
834
+ } else {
835
+ attr.args = true;
836
+ (_d = (_c = this.options).onAttrArgs) == null ? void 0 : _d.call(_c, {
837
+ start,
838
+ end,
839
+ value
840
+ });
841
+ }
842
+ break;
843
+ }
844
+ case 4 /* BLOCK */: {
845
+ const params = attr.args;
846
+ const start = params.start;
847
+ const end = ++this.pos;
848
+ (_f = (_e = this.options).onAttrMethod) == null ? void 0 : _f.call(_e, {
849
+ start,
850
+ end,
851
+ params,
852
+ body: {
853
+ start: child.start - 1,
854
+ end,
855
+ value: {
856
+ start: child.start,
857
+ end: child.end
858
+ }
859
+ }
860
+ });
861
+ this.exitState();
862
+ break;
863
+ }
864
+ case 2 /* VALUE */: {
865
+ if (child.start === child.end) {
866
+ return this.emitError(
867
+ child,
868
+ 3 /* INVALID_ATTRIBUTE_VALUE */,
869
+ "Missing value for attribute"
870
+ );
871
+ }
872
+ if (attr.spread) {
873
+ (_h = (_g = this.options).onAttrSpread) == null ? void 0 : _h.call(_g, {
874
+ start: attr.valueStart,
875
+ end: child.end,
876
+ value: {
877
+ start: child.start,
878
+ end: child.end
879
+ }
880
+ });
881
+ } else {
882
+ (_j = (_i = this.options).onAttrValue) == null ? void 0 : _j.call(_i, {
883
+ start: attr.valueStart,
884
+ end: child.end,
885
+ bound: attr.bound,
886
+ value: {
887
+ start: child.start,
888
+ end: child.end
889
+ }
890
+ });
891
+ }
892
+ this.exitState();
893
+ break;
894
+ }
895
+ }
709
896
  }
710
897
  };
711
- function checkForClosingTag(parser) {
898
+ function ensureAttrName(parser, attr) {
712
899
  var _a, _b;
713
- const curPos = parser.pos + 1;
714
- let match = !!parser.lookAheadFor("/>");
715
- let skip = 3;
716
- if (!match) {
717
- const { tagName } = parser.activeTag;
718
- const tagNameLen = tagName.end - tagName.start;
719
- if (tagNameLen) {
720
- skip += tagNameLen;
721
- match = parser.lookAheadFor("/", curPos) && parser.lookAheadFor(">", 1 + curPos + tagNameLen) && parser.matchAtPos(tagName, {
722
- start: 1 + curPos,
723
- end: 1 + curPos + tagNameLen
724
- }) || false;
725
- }
726
- }
727
- if (match) {
728
- parser.endText();
729
- (_b = (_a = parser.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
730
- start: curPos - 1,
731
- end: curPos + 1
900
+ if (!attr.name) {
901
+ (_b = (_a = parser.options).onAttrName) == null ? void 0 : _b.call(_a, {
902
+ start: attr.start,
903
+ end: attr.start
732
904
  });
733
- if (ensureExpectedCloseTag(parser, {
734
- start: parser.pos,
735
- end: parser.pos += skip
736
- })) {
737
- parser.exitState();
738
- }
739
- return true;
740
905
  }
741
- return false;
742
906
  }
743
- function ensureExpectedCloseTag(parser, closeTag) {
744
- const activeTag = parser.activeTag;
745
- const closeTagNameStart = closeTag.start + 2;
746
- const closeTagNameEnd = closeTag.end - 1;
747
- if (!activeTag) {
748
- parser.emitError(closeTag, 0 /* EXTRA_CLOSING_TAG */, 'The closing "' + parser.read({ start: closeTagNameStart, end: closeTagNameEnd }) + '" tag was not expected');
749
- return false;
907
+ function shouldTerminateHtmlAttrName(code, data, pos) {
908
+ switch (code) {
909
+ case 44 /* COMMA */:
910
+ case 61 /* EQUAL */:
911
+ case 40 /* OPEN_PAREN */:
912
+ case 62 /* CLOSE_ANGLE_BRACKET */:
913
+ return true;
914
+ case 58 /* COLON */:
915
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
916
+ case 47 /* FORWARD_SLASH */:
917
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
918
+ default:
919
+ return false;
750
920
  }
751
- const closeTagNamePos = {
752
- start: closeTagNameStart,
753
- end: closeTagNameEnd
754
- };
755
- if (closeTagNameStart < closeTagNameEnd) {
756
- if (!parser.matchAtPos(closeTagNamePos, activeTag.tagName.end > activeTag.tagName.start ? activeTag.tagName : "div")) {
757
- if (activeTag.shorthandEnd === void 0 || !parser.matchAtPos(closeTagNamePos, {
758
- start: activeTag.tagName.start,
759
- end: activeTag.shorthandEnd
760
- })) {
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');
762
- return false;
763
- }
764
- }
921
+ }
922
+ function shouldTerminateHtmlAttrValue(code, data, pos) {
923
+ switch (code) {
924
+ case 44 /* COMMA */:
925
+ return true;
926
+ case 47 /* FORWARD_SLASH */:
927
+ return data.charCodeAt(pos + 1) === 62 /* CLOSE_ANGLE_BRACKET */;
928
+ case 62 /* CLOSE_ANGLE_BRACKET */:
929
+ return pos === this.start || data.charCodeAt(pos - 1) !== 61 /* EQUAL */;
930
+ default:
931
+ return false;
932
+ }
933
+ }
934
+ function shouldTerminateConciseAttrName(code, data, pos) {
935
+ switch (code) {
936
+ case 44 /* COMMA */:
937
+ case 61 /* EQUAL */:
938
+ case 40 /* OPEN_PAREN */:
939
+ case 59 /* SEMICOLON */:
940
+ return true;
941
+ case 58 /* COLON */:
942
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
943
+ case 45 /* HYPHEN */:
944
+ return data.charCodeAt(pos + 1) === 45 /* HYPHEN */ && isWhitespaceCode(data.charCodeAt(pos - 1));
945
+ default:
946
+ return false;
947
+ }
948
+ }
949
+ function shouldTerminateConciseAttrValue(code, data, pos) {
950
+ switch (code) {
951
+ case 44 /* COMMA */:
952
+ case 59 /* SEMICOLON */:
953
+ return true;
954
+ case 45 /* HYPHEN */:
955
+ return data.charCodeAt(pos + 1) === 45 /* HYPHEN */ && isWhitespaceCode(data.charCodeAt(pos - 1));
956
+ default:
957
+ return false;
958
+ }
959
+ }
960
+ function shouldTerminateConciseGroupedAttrName(code, data, pos) {
961
+ switch (code) {
962
+ case 44 /* COMMA */:
963
+ case 61 /* EQUAL */:
964
+ case 40 /* OPEN_PAREN */:
965
+ case 93 /* CLOSE_SQUARE_BRACKET */:
966
+ return true;
967
+ case 58 /* COLON */:
968
+ return data.charCodeAt(pos + 1) === 61 /* EQUAL */;
969
+ default:
970
+ return false;
971
+ }
972
+ }
973
+ function shouldTerminateConciseGroupedAttrValue(code) {
974
+ switch (code) {
975
+ case 44 /* COMMA */:
976
+ case 93 /* CLOSE_SQUARE_BRACKET */:
977
+ return true;
978
+ default:
979
+ return false;
765
980
  }
766
- parser.closeTagEnd(closeTagNameEnd, closeTag.end, closeTagNamePos);
767
- return true;
768
981
  }
769
982
 
770
- // src/states/CONCISE_HTML_CONTENT.ts
771
- var CONCISE_HTML_CONTENT = {
772
- name: "CONCISE_HTML_CONTENT",
983
+ // src/states/BEGIN_DELIMITED_HTML_BLOCK.ts
984
+ var BEGIN_DELIMITED_HTML_BLOCK = {
985
+ name: "BEGIN_DELIMITED_HTML_BLOCK",
773
986
  enter(parent, start) {
774
- this.isConcise = true;
775
- this.indent = "";
776
987
  return {
777
- state: CONCISE_HTML_CONTENT,
988
+ state: BEGIN_DELIMITED_HTML_BLOCK,
778
989
  parent,
779
990
  start,
780
- end: start
991
+ end: start,
992
+ indent: this.indent,
993
+ delimiter: ""
781
994
  };
782
995
  },
783
996
  exit() {
784
997
  },
785
- char(code) {
786
- if (isWhitespaceCode(code)) {
787
- this.indent += this.data[this.pos];
998
+ char(code, block) {
999
+ if (code === 45 /* HTML_BLOCK_DELIMITER */) {
1000
+ block.delimiter += "-";
788
1001
  } else {
789
- const curIndent = this.indent.length;
790
- const indentStart = this.pos - curIndent - 1;
791
- let parentTag = this.activeTag;
792
- while (parentTag && parentTag.indent.length >= curIndent) {
793
- this.closeTagEnd(indentStart, indentStart, void 0);
794
- parentTag = this.activeTag;
795
- }
796
- if (!parentTag && curIndent) {
797
- this.emitError(this.pos, 7 /* INVALID_INDENTATION */, "Line has extra indentation at the beginning");
798
- return;
1002
+ const startPos = this.pos;
1003
+ if (!this.consumeWhitespaceOnLine()) {
1004
+ this.pos = startPos + 1;
1005
+ this.forward = 0;
1006
+ this.beginHtmlBlock(void 0, true);
799
1007
  }
800
- if (parentTag) {
801
- 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');
803
- return;
804
- }
805
- if (parentTag.nestedIndent === void 0) {
1008
+ }
1009
+ },
1010
+ eol(len, block) {
1011
+ this.beginHtmlBlock(block.delimiter, false);
1012
+ handleDelimitedBlockEOL(this, len, block);
1013
+ },
1014
+ eof: htmlEOF,
1015
+ return() {
1016
+ }
1017
+ };
1018
+ function handleDelimitedEOL(parser, newLineLength, content) {
1019
+ if (content.singleLine) {
1020
+ parser.endText();
1021
+ parser.exitState();
1022
+ parser.exitState();
1023
+ return true;
1024
+ }
1025
+ if (content.delimiter) {
1026
+ handleDelimitedBlockEOL(parser, newLineLength, content);
1027
+ return true;
1028
+ }
1029
+ return false;
1030
+ }
1031
+ function handleDelimitedBlockEOL(parser, newLineLength, {
1032
+ indent,
1033
+ delimiter
1034
+ }) {
1035
+ const endHtmlBlockLookahead = indent + delimiter;
1036
+ if (parser.lookAheadFor(endHtmlBlockLookahead, parser.pos + newLineLength)) {
1037
+ parser.startText();
1038
+ parser.pos += newLineLength;
1039
+ parser.endText();
1040
+ parser.pos += endHtmlBlockLookahead.length;
1041
+ if (parser.consumeWhitespaceOnLine(0)) {
1042
+ parser.endText();
1043
+ parser.exitState();
1044
+ parser.exitState();
1045
+ } else {
1046
+ parser.emitError(
1047
+ parser.pos,
1048
+ 4 /* INVALID_CHARACTER */,
1049
+ "A concise mode closing block delimiter can only be followed by whitespace."
1050
+ );
1051
+ }
1052
+ } else if (parser.lookAheadFor(indent, parser.pos + newLineLength)) {
1053
+ parser.startText();
1054
+ parser.pos += indent.length;
1055
+ } else if (indent && !parser.onlyWhitespaceRemainsOnLine(newLineLength)) {
1056
+ parser.endText();
1057
+ parser.exitState();
1058
+ parser.exitState();
1059
+ } else {
1060
+ parser.startText();
1061
+ }
1062
+ }
1063
+
1064
+ // src/states/CDATA.ts
1065
+ var CDATA = {
1066
+ name: "CDATA",
1067
+ enter(parent, start) {
1068
+ return {
1069
+ state: CDATA,
1070
+ parent,
1071
+ start,
1072
+ end: start
1073
+ };
1074
+ },
1075
+ exit(cdata) {
1076
+ var _a, _b;
1077
+ (_b = (_a = this.options).onCDATA) == null ? void 0 : _b.call(_a, {
1078
+ start: cdata.start,
1079
+ end: cdata.end,
1080
+ value: {
1081
+ start: cdata.start + 9,
1082
+ end: cdata.end - 3
1083
+ }
1084
+ });
1085
+ },
1086
+ char(code) {
1087
+ if (code === 93 /* CLOSE_SQUARE_BRACKET */ && this.lookAheadFor("]>")) {
1088
+ this.pos += 3;
1089
+ this.exitState();
1090
+ return;
1091
+ }
1092
+ },
1093
+ eol() {
1094
+ },
1095
+ eof(cdata) {
1096
+ this.emitError(
1097
+ cdata,
1098
+ 14 /* MALFORMED_CDATA */,
1099
+ "EOF reached while parsing CDATA"
1100
+ );
1101
+ },
1102
+ return() {
1103
+ }
1104
+ };
1105
+ function checkForCDATA(parser) {
1106
+ if (parser.lookAheadFor("![CDATA[")) {
1107
+ parser.endText();
1108
+ parser.enterState(CDATA);
1109
+ parser.pos += 8;
1110
+ return true;
1111
+ }
1112
+ return false;
1113
+ }
1114
+
1115
+ // src/states/CLOSE_TAG.ts
1116
+ var CLOSE_TAG = {
1117
+ name: "CLOSE_TAG",
1118
+ enter(parent, start) {
1119
+ this.endText();
1120
+ return {
1121
+ state: CLOSE_TAG,
1122
+ parent,
1123
+ start,
1124
+ end: start
1125
+ };
1126
+ },
1127
+ exit() {
1128
+ },
1129
+ char(code, closeTag) {
1130
+ if (code === 62 /* CLOSE_ANGLE_BRACKET */) {
1131
+ this.pos++;
1132
+ this.exitState();
1133
+ ensureExpectedCloseTag(this, closeTag);
1134
+ }
1135
+ },
1136
+ eol() {
1137
+ },
1138
+ eof(closeTag) {
1139
+ this.emitError(
1140
+ closeTag,
1141
+ 15 /* MALFORMED_CLOSE_TAG */,
1142
+ "EOF reached while parsing closing tag"
1143
+ );
1144
+ },
1145
+ return() {
1146
+ }
1147
+ };
1148
+ function checkForClosingTag(parser) {
1149
+ var _a, _b;
1150
+ const curPos = parser.pos + 1;
1151
+ let match = !!parser.lookAheadFor("/>");
1152
+ let skip = 3;
1153
+ if (!match) {
1154
+ const { tagName } = parser.activeTag;
1155
+ const tagNameLen = tagName.end - tagName.start;
1156
+ if (tagNameLen) {
1157
+ skip += tagNameLen;
1158
+ match = parser.lookAheadFor("/", curPos) && parser.lookAheadFor(">", 1 + curPos + tagNameLen) && parser.matchAtPos(tagName, {
1159
+ start: 1 + curPos,
1160
+ end: 1 + curPos + tagNameLen
1161
+ }) || false;
1162
+ }
1163
+ }
1164
+ if (match) {
1165
+ parser.endText();
1166
+ (_b = (_a = parser.options).onCloseTagStart) == null ? void 0 : _b.call(_a, {
1167
+ start: curPos - 1,
1168
+ end: curPos + 1
1169
+ });
1170
+ if (ensureExpectedCloseTag(parser, {
1171
+ start: parser.pos,
1172
+ end: parser.pos += skip
1173
+ })) {
1174
+ parser.exitState();
1175
+ }
1176
+ return true;
1177
+ }
1178
+ return false;
1179
+ }
1180
+ function ensureExpectedCloseTag(parser, closeTag) {
1181
+ const activeTag = parser.activeTag;
1182
+ const closeTagNameStart = closeTag.start + 2;
1183
+ const closeTagNameEnd = closeTag.end - 1;
1184
+ if (!activeTag) {
1185
+ parser.emitError(
1186
+ closeTag,
1187
+ 0 /* EXTRA_CLOSING_TAG */,
1188
+ 'The closing "' + parser.read({ start: closeTagNameStart, end: closeTagNameEnd }) + '" tag was not expected'
1189
+ );
1190
+ return false;
1191
+ }
1192
+ const closeTagNamePos = {
1193
+ start: closeTagNameStart,
1194
+ end: closeTagNameEnd
1195
+ };
1196
+ if (closeTagNameStart < closeTagNameEnd) {
1197
+ if (!parser.matchAtPos(
1198
+ closeTagNamePos,
1199
+ activeTag.tagName.end > activeTag.tagName.start ? activeTag.tagName : "div"
1200
+ )) {
1201
+ if (activeTag.shorthandEnd === void 0 || !parser.matchAtPos(closeTagNamePos, {
1202
+ start: activeTag.tagName.start,
1203
+ end: activeTag.shorthandEnd
1204
+ })) {
1205
+ parser.emitError(
1206
+ closeTag,
1207
+ 21 /* MISMATCHED_CLOSING_TAG */,
1208
+ 'The closing "' + parser.read(closeTagNamePos) + '" tag does not match the corresponding opening "' + (parser.read(activeTag.tagName) || "div") + '" tag'
1209
+ );
1210
+ return false;
1211
+ }
1212
+ }
1213
+ }
1214
+ parser.closeTagEnd(closeTagNameEnd, closeTag.end, closeTagNamePos);
1215
+ return true;
1216
+ }
1217
+
1218
+ // src/states/CONCISE_HTML_CONTENT.ts
1219
+ var CONCISE_HTML_CONTENT = {
1220
+ name: "CONCISE_HTML_CONTENT",
1221
+ enter(parent, start) {
1222
+ this.isConcise = true;
1223
+ this.indent = "";
1224
+ return {
1225
+ state: CONCISE_HTML_CONTENT,
1226
+ parent,
1227
+ start,
1228
+ end: start
1229
+ };
1230
+ },
1231
+ exit() {
1232
+ },
1233
+ char(code) {
1234
+ if (isWhitespaceCode(code)) {
1235
+ this.indent += this.data[this.pos];
1236
+ } else {
1237
+ const curIndent = this.indent.length;
1238
+ const indentStart = this.pos - curIndent - 1;
1239
+ let parentTag = this.activeTag;
1240
+ while (parentTag && parentTag.indent.length >= curIndent) {
1241
+ this.closeTagEnd(indentStart, indentStart, void 0);
1242
+ parentTag = this.activeTag;
1243
+ }
1244
+ if (!parentTag && curIndent) {
1245
+ this.emitError(
1246
+ this.pos,
1247
+ 7 /* INVALID_INDENTATION */,
1248
+ "Line has extra indentation at the beginning"
1249
+ );
1250
+ return;
1251
+ }
1252
+ if (parentTag) {
1253
+ if (parentTag.type === 1 /* text */ && code !== 45 /* HTML_BLOCK_DELIMITER */) {
1254
+ this.emitError(
1255
+ this.pos,
1256
+ 8 /* INVALID_LINE_START */,
1257
+ 'A line within a tag that only allows text content must begin with a "-" character'
1258
+ );
1259
+ return;
1260
+ }
1261
+ if (parentTag.nestedIndent === void 0) {
806
1262
  parentTag.nestedIndent = this.indent;
807
1263
  } else if (parentTag.nestedIndent !== this.indent) {
808
- this.emitError(this.pos, 7 /* INVALID_INDENTATION */, "Line indentation does match indentation of previous line");
1264
+ this.emitError(
1265
+ this.pos,
1266
+ 7 /* INVALID_INDENTATION */,
1267
+ "Line indentation does match indentation of previous line"
1268
+ );
809
1269
  return;
810
1270
  }
811
1271
  }
@@ -827,7 +1287,11 @@ var CONCISE_HTML_CONTENT = {
827
1287
  this.enterState(states_exports.BEGIN_DELIMITED_HTML_BLOCK);
828
1288
  this.pos--;
829
1289
  } 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');
1290
+ this.emitError(
1291
+ this.pos,
1292
+ 8 /* INVALID_LINE_START */,
1293
+ 'A line in concise mode cannot start with a single hyphen. Use "--" instead. See: https://github.com/marko-js/htmljs-parser/issues/43'
1294
+ );
831
1295
  }
832
1296
  return;
833
1297
  case 47 /* FORWARD_SLASH */:
@@ -841,7 +1305,11 @@ var CONCISE_HTML_CONTENT = {
841
1305
  this.pos++;
842
1306
  return;
843
1307
  default:
844
- this.emitError(this.pos, 8 /* INVALID_LINE_START */, 'A line in concise mode cannot start with "/" unless it starts a "//" or "/*" comment');
1308
+ this.emitError(
1309
+ this.pos,
1310
+ 8 /* INVALID_LINE_START */,
1311
+ 'A line in concise mode cannot start with "/" unless it starts a "//" or "/*" comment'
1312
+ );
845
1313
  return;
846
1314
  }
847
1315
  }
@@ -878,7 +1346,11 @@ var CONCISE_HTML_CONTENT = {
878
1346
  }
879
1347
  });
880
1348
  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.");
1349
+ this.emitError(
1350
+ this.pos,
1351
+ 4 /* INVALID_CHARACTER */,
1352
+ "In concise mode a javascript comment block can only be followed by whitespace characters and a newline."
1353
+ );
882
1354
  }
883
1355
  break;
884
1356
  }
@@ -912,7 +1384,11 @@ var DECLARATION = {
912
1384
  eol() {
913
1385
  },
914
1386
  eof(declaration) {
915
- this.emitError(declaration, 17 /* MALFORMED_DECLARATION */, "EOF reached while parsing declaration");
1387
+ this.emitError(
1388
+ declaration,
1389
+ 17 /* MALFORMED_DECLARATION */,
1390
+ "EOF reached while parsing declaration"
1391
+ );
916
1392
  },
917
1393
  return() {
918
1394
  }
@@ -963,16 +1439,29 @@ var DTD = {
963
1439
  eol() {
964
1440
  },
965
1441
  eof(documentType) {
966
- this.emitError(documentType, 18 /* MALFORMED_DOCUMENT_TYPE */, "EOF reached while parsing document type");
1442
+ this.emitError(
1443
+ documentType,
1444
+ 18 /* MALFORMED_DOCUMENT_TYPE */,
1445
+ "EOF reached while parsing document type"
1446
+ );
967
1447
  },
968
1448
  return() {
969
1449
  }
970
1450
  };
971
1451
 
972
1452
  // 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 */);
1453
+ var shouldTerminate = () => false;
1454
+ var unaryKeywords = [
1455
+ "async",
1456
+ "await",
1457
+ "keyof",
1458
+ "class",
1459
+ "function",
1460
+ "new",
1461
+ "typeof",
1462
+ "void"
1463
+ ];
1464
+ var binaryKeywords = ["instanceof", "in", "as", "extends"];
976
1465
  var EXPRESSION = {
977
1466
  name: "EXPRESSION",
978
1467
  enter(parent, start) {
@@ -982,8 +1471,8 @@ var EXPRESSION = {
982
1471
  start,
983
1472
  end: start,
984
1473
  groupStack: [],
985
- terminator: -1,
986
- skipOperators: false,
1474
+ shouldTerminate,
1475
+ operators: false,
987
1476
  terminatedByEOL: false,
988
1477
  terminatedByWhitespace: false
989
1478
  };
@@ -993,12 +1482,12 @@ var EXPRESSION = {
993
1482
  char(code, expression) {
994
1483
  if (!expression.groupStack.length) {
995
1484
  if (expression.terminatedByWhitespace && isWhitespaceCode(code)) {
996
- if (!checkForOperators(this, expression)) {
1485
+ if (!checkForOperators(this, expression, false)) {
997
1486
  this.exitState();
998
1487
  }
999
1488
  return;
1000
1489
  }
1001
- if (typeof expression.terminator === "number" ? expression.terminator === code : checkForTerminators(this, code, expression.terminator)) {
1490
+ if (expression.shouldTerminate(code, this.data, this.pos)) {
1002
1491
  this.exitState();
1003
1492
  return;
1004
1493
  }
@@ -1024,7 +1513,7 @@ var EXPRESSION = {
1024
1513
  this.pos++;
1025
1514
  break;
1026
1515
  default: {
1027
- if (canCharCodeBeFollowedByDivision(this.getPreviousNonWhitespaceCharCode())) {
1516
+ if (canFollowDivision(this.getPreviousNonWhitespaceCharCode())) {
1028
1517
  this.pos++;
1029
1518
  this.consumeWhitespace();
1030
1519
  } else {
@@ -1047,18 +1536,26 @@ var EXPRESSION = {
1047
1536
  case 93 /* CLOSE_SQUARE_BRACKET */:
1048
1537
  case 125 /* CLOSE_CURLY_BRACE */: {
1049
1538
  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.');
1539
+ return this.emitError(
1540
+ expression,
1541
+ 6 /* INVALID_EXPRESSION */,
1542
+ 'Mismatched group. A closing "' + String.fromCharCode(code) + '" character was found but it is not matched with a corresponding opening character.'
1543
+ );
1051
1544
  }
1052
1545
  const expectedCode = expression.groupStack.pop();
1053
1546
  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.');
1547
+ return this.emitError(
1548
+ expression,
1549
+ 6 /* INVALID_EXPRESSION */,
1550
+ 'Mismatched group. A "' + String.fromCharCode(code) + '" character was found when "' + String.fromCharCode(expectedCode) + '" was expected.'
1551
+ );
1055
1552
  }
1056
1553
  break;
1057
1554
  }
1058
1555
  }
1059
1556
  },
1060
1557
  eol(_, expression) {
1061
- if (!expression.groupStack.length && (expression.terminatedByEOL || expression.terminatedByWhitespace) && !checkForOperators(this, expression)) {
1558
+ if (!expression.groupStack.length && (expression.terminatedByEOL || expression.terminatedByWhitespace) && !checkForOperators(this, expression, true)) {
1062
1559
  this.exitState();
1063
1560
  }
1064
1561
  },
@@ -1071,69 +1568,216 @@ var EXPRESSION = {
1071
1568
  case states_exports.ATTRIBUTE: {
1072
1569
  const attr = parent;
1073
1570
  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');
1571
+ return this.emitError(
1572
+ expression,
1573
+ 19 /* MALFORMED_OPEN_TAG */,
1574
+ 'EOF reached while parsing attribute name for the "' + this.read(this.activeTag.tagName) + '" tag'
1575
+ );
1075
1576
  }
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`);
1577
+ return this.emitError(
1578
+ expression,
1579
+ 19 /* MALFORMED_OPEN_TAG */,
1580
+ `EOF reached while parsing attribute value for the ${attr.spread ? "..." : attr.name ? `"${this.read(attr.name)}"` : `"default"`} attribute`
1581
+ );
1077
1582
  }
1078
1583
  case states_exports.TAG_NAME:
1079
- return this.emitError(expression, 19 /* MALFORMED_OPEN_TAG */, "EOF reached while parsing tag name");
1584
+ return this.emitError(
1585
+ expression,
1586
+ 19 /* MALFORMED_OPEN_TAG */,
1587
+ "EOF reached while parsing tag name"
1588
+ );
1080
1589
  case states_exports.PLACEHOLDER:
1081
- return this.emitError(expression, 20 /* MALFORMED_PLACEHOLDER */, "EOF reached while parsing placeholder");
1590
+ return this.emitError(
1591
+ expression,
1592
+ 20 /* MALFORMED_PLACEHOLDER */,
1593
+ "EOF reached while parsing placeholder"
1594
+ );
1082
1595
  }
1083
- return this.emitError(expression, 6 /* INVALID_EXPRESSION */, "EOF reached while parsing expression");
1596
+ return this.emitError(
1597
+ expression,
1598
+ 6 /* INVALID_EXPRESSION */,
1599
+ "EOF reached while parsing expression"
1600
+ );
1084
1601
  }
1085
1602
  },
1086
1603
  return() {
1087
1604
  }
1088
1605
  };
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) {
1606
+ function checkForOperators(parser, expression, eol) {
1607
+ if (!expression.operators)
1100
1608
  return false;
1609
+ const { pos, data } = parser;
1610
+ if (lookBehindForOperator(data, pos) !== -1) {
1611
+ parser.consumeWhitespace();
1612
+ parser.forward = 0;
1613
+ return true;
1101
1614
  }
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;
1615
+ const terminatedByEOL = expression.terminatedByEOL || parser.isConcise;
1616
+ if (!(terminatedByEOL && eol)) {
1617
+ const nextNonSpace = lookAheadWhile(
1618
+ terminatedByEOL ? isIndentCode : isWhitespaceCode,
1619
+ data,
1620
+ pos + 1
1621
+ );
1622
+ if (!expression.shouldTerminate(
1623
+ data.charCodeAt(nextNonSpace),
1624
+ data,
1625
+ nextNonSpace
1626
+ )) {
1627
+ const lookAheadPos = lookAheadForOperator(data, nextNonSpace);
1628
+ if (lookAheadPos !== -1) {
1629
+ parser.pos = lookAheadPos;
1630
+ parser.forward = 0;
1631
+ return true;
1632
+ }
1111
1633
  }
1112
- parser.forward = 0;
1113
- } else {
1114
- return false;
1115
1634
  }
1116
- return true;
1635
+ return false;
1117
1636
  }
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;
1637
+ function lookBehindForOperator(data, pos) {
1638
+ const curPos = pos - 1;
1639
+ const code = data.charCodeAt(curPos);
1640
+ switch (code) {
1641
+ case 38 /* AMPERSAND */:
1642
+ case 42 /* ASTERISK */:
1643
+ case 94 /* CARET */:
1644
+ case 58 /* COLON */:
1645
+ case 61 /* EQUAL */:
1646
+ case 33 /* EXCLAMATION */:
1647
+ case 60 /* OPEN_ANGLE_BRACKET */:
1648
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1649
+ case 37 /* PERCENT */:
1650
+ case 46 /* PERIOD */:
1651
+ case 124 /* PIPE */:
1652
+ case 63 /* QUESTION */:
1653
+ case 126 /* TILDE */:
1654
+ return curPos;
1655
+ case 43 /* PLUS */:
1656
+ case 45 /* HYPHEN */: {
1657
+ if (data.charCodeAt(curPos - 1) === code) {
1658
+ return lookBehindForOperator(
1659
+ data,
1660
+ lookBehindWhile(isWhitespaceCode, data, curPos - 2)
1661
+ );
1662
+ }
1663
+ return curPos;
1664
+ }
1665
+ default: {
1666
+ for (const keyword of unaryKeywords) {
1667
+ const keywordPos = lookBehindFor(data, curPos, keyword);
1668
+ if (keywordPos !== -1) {
1669
+ return data.charCodeAt(keywordPos - 1) === 46 /* PERIOD */ ? -1 : keywordPos;
1670
+ }
1671
+ }
1672
+ return -1;
1673
+ }
1674
+ }
1675
+ }
1676
+ function lookAheadForOperator(data, pos) {
1677
+ switch (data.charCodeAt(pos)) {
1678
+ case 38 /* AMPERSAND */:
1679
+ case 42 /* ASTERISK */:
1680
+ case 94 /* CARET */:
1681
+ case 33 /* EXCLAMATION */:
1682
+ case 60 /* OPEN_ANGLE_BRACKET */:
1683
+ case 37 /* PERCENT */:
1684
+ case 124 /* PIPE */:
1685
+ case 63 /* QUESTION */:
1686
+ case 126 /* TILDE */:
1687
+ case 43 /* PLUS */:
1688
+ case 45 /* HYPHEN */:
1689
+ case 58 /* COLON */:
1690
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1691
+ case 61 /* EQUAL */:
1692
+ return pos + 1;
1693
+ case 47 /* FORWARD_SLASH */:
1694
+ case 123 /* OPEN_CURLY_BRACE */:
1695
+ case 40 /* OPEN_PAREN */:
1696
+ return pos;
1697
+ case 46 /* PERIOD */:
1698
+ return data.charCodeAt(pos + 1) === 46 /* PERIOD */ ? -1 : pos + 1;
1699
+ default: {
1700
+ for (const keyword of binaryKeywords) {
1701
+ let nextPos = lookAheadFor(data, pos, keyword);
1702
+ if (nextPos === -1)
1703
+ continue;
1704
+ const max = data.length - 1;
1705
+ if (nextPos === max)
1706
+ return -1;
1707
+ let nextCode = data.charCodeAt(nextPos + 1);
1708
+ if (isWhitespaceCode(nextCode)) {
1709
+ nextPos = lookAheadWhile(isWhitespaceCode, data, nextPos + 2);
1710
+ if (nextPos === max)
1711
+ return -1;
1712
+ nextCode = data.charCodeAt(nextPos);
1713
+ } else if (isWordCode(nextCode)) {
1714
+ return -1;
1715
+ }
1716
+ switch (nextCode) {
1717
+ case 58 /* COLON */:
1718
+ case 44 /* COMMA */:
1719
+ case 61 /* EQUAL */:
1720
+ case 47 /* FORWARD_SLASH */:
1721
+ case 62 /* CLOSE_ANGLE_BRACKET */:
1722
+ case 59 /* SEMICOLON */:
1723
+ return -1;
1724
+ default:
1725
+ return nextPos;
1131
1726
  }
1132
1727
  }
1728
+ return -1;
1133
1729
  }
1730
+ }
1731
+ }
1732
+ function canFollowDivision(code) {
1733
+ 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 */;
1734
+ }
1735
+ function isWordCode(code) {
1736
+ 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 */;
1737
+ }
1738
+ function isIndentCode(code) {
1739
+ return code === 9 /* TAB */ || code === 32 /* SPACE */;
1740
+ }
1741
+ function lookAheadWhile(match, data, pos) {
1742
+ const max = data.length;
1743
+ for (let i = pos; i < max; i++) {
1744
+ if (!match(data.charCodeAt(i)))
1745
+ return i;
1746
+ }
1747
+ return max - 1;
1748
+ }
1749
+ function lookBehindWhile(match, data, pos) {
1750
+ let i = pos;
1751
+ do {
1752
+ if (!match(data.charCodeAt(i))) {
1753
+ return i + 1;
1754
+ }
1755
+ } while (i--);
1756
+ return 0;
1757
+ }
1758
+ function lookBehindFor(data, pos, str) {
1759
+ let i = str.length;
1760
+ const endPos = pos - i + 1;
1761
+ if (endPos < 0)
1762
+ return -1;
1763
+ while (i--) {
1764
+ if (data.charCodeAt(endPos + i) !== str.charCodeAt(i)) {
1765
+ return -1;
1766
+ }
1767
+ }
1768
+ return endPos;
1134
1769
  }
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 */;
1770
+ function lookAheadFor(data, pos, str) {
1771
+ let i = str.length;
1772
+ const endPos = pos + i;
1773
+ if (endPos > data.length)
1774
+ return -1;
1775
+ while (i--) {
1776
+ if (data.charCodeAt(pos + i) !== str.charCodeAt(i)) {
1777
+ return -1;
1778
+ }
1779
+ }
1780
+ return endPos - 1;
1137
1781
  }
1138
1782
 
1139
1783
  // src/states/HTML_COMMENT.ts
@@ -1174,7 +1818,11 @@ var HTML_COMMENT = {
1174
1818
  eol() {
1175
1819
  },
1176
1820
  eof(comment) {
1177
- this.emitError(comment, 16 /* MALFORMED_COMMENT */, "EOF reached while parsing comment");
1821
+ this.emitError(
1822
+ comment,
1823
+ 16 /* MALFORMED_COMMENT */,
1824
+ "EOF reached while parsing comment"
1825
+ );
1178
1826
  },
1179
1827
  return() {
1180
1828
  }
@@ -1348,11 +1996,10 @@ var INLINE_SCRIPT = {
1348
1996
  if (code === 123 /* OPEN_CURLY_BRACE */) {
1349
1997
  inlineScript.block = true;
1350
1998
  this.pos++;
1351
- const expr = this.enterState(states_exports.EXPRESSION);
1352
- expr.terminator = 125 /* CLOSE_CURLY_BRACE */;
1353
- expr.skipOperators = true;
1999
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1354
2000
  } else {
1355
2001
  const expr = this.enterState(states_exports.EXPRESSION);
2002
+ expr.operators = true;
1356
2003
  expr.terminatedByEOL = true;
1357
2004
  }
1358
2005
  },
@@ -1387,7 +2034,11 @@ var JS_COMMENT_BLOCK = {
1387
2034
  eol() {
1388
2035
  },
1389
2036
  eof(comment) {
1390
- this.emitError(comment, 16 /* MALFORMED_COMMENT */, "EOF reached while parsing multi-line JavaScript comment");
2037
+ this.emitError(
2038
+ comment,
2039
+ 16 /* MALFORMED_COMMENT */,
2040
+ "EOF reached while parsing multi-line JavaScript comment"
2041
+ );
1391
2042
  },
1392
2043
  return() {
1393
2044
  }
@@ -1408,8 +2059,8 @@ var JS_COMMENT_LINE = {
1408
2059
  },
1409
2060
  char(code) {
1410
2061
  var _a;
1411
- if (!this.isConcise && code === 60 /* OPEN_ANGLE_BRACKET */ && ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */) {
1412
- states_exports.checkForClosingTag(this);
2062
+ if (!this.isConcise && code === 60 /* OPEN_ANGLE_BRACKET */ && ((_a = this.activeTag) == null ? void 0 : _a.type) === 1 /* text */ && states_exports.checkForClosingTag(this)) {
2063
+ this.exitState();
1413
2064
  }
1414
2065
  },
1415
2066
  eol() {
@@ -1441,7 +2092,7 @@ var PARSED_TEXT_CONTENT = {
1441
2092
  char(code) {
1442
2093
  switch (code) {
1443
2094
  case 60 /* OPEN_ANGLE_BRACKET */:
1444
- if (this.isConcise || !(states_exports.checkForClosingTag(this) || states_exports.checkForCDATA(this))) {
2095
+ if (this.isConcise || !states_exports.checkForClosingTag(this)) {
1445
2096
  this.startText();
1446
2097
  }
1447
2098
  break;
@@ -1510,7 +2161,11 @@ var PLACEHOLDER = {
1510
2161
  },
1511
2162
  return(child) {
1512
2163
  if (child.start === child.end) {
1513
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2164
+ this.emitError(
2165
+ child,
2166
+ 20 /* MALFORMED_PLACEHOLDER */,
2167
+ "Invalid placeholder, the expression cannot be missing"
2168
+ );
1514
2169
  }
1515
2170
  this.pos++;
1516
2171
  this.exitState();
@@ -1550,7 +2205,7 @@ function checkForPlaceholder(parser, code) {
1550
2205
  parser.enterState(PLACEHOLDER).escape = escape;
1551
2206
  parser.pos += escape ? 2 : 3;
1552
2207
  parser.forward = 0;
1553
- parser.enterState(states_exports.EXPRESSION).terminator = 125 /* CLOSE_CURLY_BRACE */;
2208
+ parser.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1554
2209
  return true;
1555
2210
  }
1556
2211
  }
@@ -1584,10 +2239,18 @@ var REGULAR_EXPRESSION = {
1584
2239
  }
1585
2240
  },
1586
2241
  eol(_, regExp) {
1587
- this.emitError(regExp, 9 /* INVALID_REGULAR_EXPRESSION */, "EOL reached while parsing regular expression");
2242
+ this.emitError(
2243
+ regExp,
2244
+ 9 /* INVALID_REGULAR_EXPRESSION */,
2245
+ "EOL reached while parsing regular expression"
2246
+ );
1588
2247
  },
1589
2248
  eof(regExp) {
1590
- this.emitError(regExp, 9 /* INVALID_REGULAR_EXPRESSION */, "EOF reached while parsing regular expression");
2249
+ this.emitError(
2250
+ regExp,
2251
+ 9 /* INVALID_REGULAR_EXPRESSION */,
2252
+ "EOF reached while parsing regular expression"
2253
+ );
1591
2254
  },
1592
2255
  return() {
1593
2256
  }
@@ -1621,7 +2284,11 @@ var STRING = {
1621
2284
  eol() {
1622
2285
  },
1623
2286
  eof(string) {
1624
- this.emitError(string, 10 /* INVALID_STRING */, "EOF reached while parsing string expression");
2287
+ this.emitError(
2288
+ string,
2289
+ 10 /* INVALID_STRING */,
2290
+ "EOF reached while parsing string expression"
2291
+ );
1625
2292
  },
1626
2293
  return() {
1627
2294
  }
@@ -1649,7 +2316,11 @@ var TAG_NAME = {
1649
2316
  switch (tagName.shorthandCode) {
1650
2317
  case 35 /* NUMBER_SIGN */:
1651
2318
  if (this.activeTag.hasShorthandId) {
1652
- return this.emitError(tagName, 12 /* INVALID_TAG_SHORTHAND */, "Multiple shorthand ID parts are not allowed on the same tag");
2319
+ return this.emitError(
2320
+ tagName,
2321
+ 12 /* INVALID_TAG_SHORTHAND */,
2322
+ "Multiple shorthand ID parts are not allowed on the same tag"
2323
+ );
1653
2324
  }
1654
2325
  this.activeTag.hasShorthandId = true;
1655
2326
  (_b = (_a = this.options).onTagShorthandId) == null ? void 0 : _b.call(_a, {
@@ -1680,12 +2351,26 @@ var TAG_NAME = {
1680
2351
  tag.type = tagType;
1681
2352
  if (tagType === 3 /* statement */) {
1682
2353
  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.`);
2354
+ return this.emitError(
2355
+ tagName,
2356
+ 24 /* RESERVED_TAG_NAME */,
2357
+ `The "${this.read(
2358
+ tagName
2359
+ )}" tag is reserved and cannot be used as an HTML tag.`
2360
+ );
1684
2361
  }
1685
2362
  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.`);
2363
+ return this.emitError(
2364
+ tagName,
2365
+ 25 /* ROOT_TAG_ONLY */,
2366
+ `"${this.read(
2367
+ tagName
2368
+ )}" can only be used at the root of the template.`
2369
+ );
1687
2370
  }
1688
- this.enterState(states_exports.EXPRESSION).terminatedByEOL = true;
2371
+ const expr = this.enterState(states_exports.EXPRESSION);
2372
+ expr.operators = true;
2373
+ expr.terminatedByEOL = true;
1689
2374
  }
1690
2375
  }
1691
2376
  break;
@@ -1696,7 +2381,7 @@ var TAG_NAME = {
1696
2381
  if (code === 36 /* DOLLAR */ && this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
1697
2382
  this.pos += 2;
1698
2383
  this.forward = 0;
1699
- this.enterState(states_exports.EXPRESSION).terminator = 125 /* CLOSE_CURLY_BRACE */;
2384
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
1700
2385
  } 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
2386
  this.activeTag.shorthandEnd = this.pos;
1702
2387
  this.exitState();
@@ -1718,7 +2403,11 @@ var TAG_NAME = {
1718
2403
  if (child.terminatedByEOL)
1719
2404
  return;
1720
2405
  if (child.start === child.end) {
1721
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2406
+ this.emitError(
2407
+ child,
2408
+ 20 /* MALFORMED_PLACEHOLDER */,
2409
+ "Invalid placeholder, the expression cannot be missing"
2410
+ );
1722
2411
  }
1723
2412
  const { quasis, expressions } = tagName;
1724
2413
  const start = child.start - 2;
@@ -1751,334 +2440,43 @@ var TEMPLATE_STRING = {
1751
2440
  exit() {
1752
2441
  },
1753
2442
  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 */) {
2443
+ switch (code) {
2444
+ case 36 /* DOLLAR */:
2445
+ if (this.lookAtCharCodeAhead(1) === 123 /* OPEN_CURLY_BRACE */) {
2446
+ this.pos++;
2447
+ this.enterState(states_exports.EXPRESSION).shouldTerminate = matchesCloseCurlyBrace;
2448
+ }
2449
+ break;
2450
+ case 92 /* BACK_SLASH */:
1761
2451
  this.pos++;
1762
- } else if (code === 96 /* BACKTICK */) {
2452
+ break;
2453
+ case 96 /* BACKTICK */:
1763
2454
  this.pos++;
1764
2455
  this.exitState();
1765
- }
2456
+ break;
1766
2457
  }
1767
2458
  },
1768
2459
  eof(templateString) {
1769
- this.emitError(templateString, 13 /* INVALID_TEMPLATE_STRING */, "EOF reached while parsing template string expression");
2460
+ this.emitError(
2461
+ templateString,
2462
+ 13 /* INVALID_TEMPLATE_STRING */,
2463
+ "EOF reached while parsing template string expression"
2464
+ );
1770
2465
  },
1771
2466
  eol() {
1772
2467
  },
1773
2468
  return(child) {
1774
2469
  if (child.start === child.end) {
1775
- this.emitError(child, 20 /* MALFORMED_PLACEHOLDER */, "Invalid placeholder, the expression cannot be missing");
2470
+ this.emitError(
2471
+ child,
2472
+ 20 /* MALFORMED_PLACEHOLDER */,
2473
+ "Invalid placeholder, the expression cannot be missing"
2474
+ );
1776
2475
  }
1777
2476
  this.pos++;
1778
2477
  }
1779
2478
  };
1780
2479
 
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
2480
  // src/index.ts
2083
2481
  function createParser(handlers) {
2084
2482
  const parser = new Parser(handlers);