html-validate 6.3.2 → 6.6.0

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/es/core.js CHANGED
@@ -1476,8 +1476,8 @@ class DOMTokenList extends Array {
1476
1476
  constructor(value, location) {
1477
1477
  if (value && typeof value === "string") {
1478
1478
  /* replace all whitespace with a single space for easier parsing */
1479
- const condensed = value.replace(/[\t\r\n ]+/g, " ");
1480
- const { tokens, locations } = parse(condensed, location);
1479
+ const normalized = value.replace(/[\t\r\n]/g, " ");
1480
+ const { tokens, locations } = parse(normalized, location);
1481
1481
  super(...tokens);
1482
1482
  this.locations = locations;
1483
1483
  }
@@ -1880,10 +1880,13 @@ class HtmlElement extends DOMNode {
1880
1880
  }
1881
1881
  /**
1882
1882
  * @internal
1883
+ *
1884
+ * @param namespace - If given it is appended to the tagName.
1883
1885
  */
1884
- static fromTokens(startToken, endToken, parent, metaTable) {
1885
- const tagName = startToken.data[2];
1886
- if (!tagName) {
1886
+ static fromTokens(startToken, endToken, parent, metaTable, namespace = "") {
1887
+ const name = startToken.data[2];
1888
+ const tagName = namespace ? `${namespace}:${name}` : name;
1889
+ if (!name) {
1887
1890
  throw new Error("tagName cannot be empty");
1888
1891
  }
1889
1892
  const meta = metaTable ? metaTable.getMetaFor(tagName) : null;
@@ -2945,7 +2948,7 @@ var TRANSFORMER_API;
2945
2948
  /** @public */
2946
2949
  const name = "html-validate";
2947
2950
  /** @public */
2948
- const version = "6.3.2";
2951
+ const version = "6.6.0";
2949
2952
  /** @public */
2950
2953
  const homepage = "https://html-validate.org";
2951
2954
  /** @public */
@@ -2984,6 +2987,42 @@ function parseSeverity(value) {
2984
2987
  }
2985
2988
  }
2986
2989
 
2990
+ function escape(value) {
2991
+ return value.replace(/'/g, "\\'");
2992
+ }
2993
+ function format(value, quote = false) {
2994
+ if (value === null) {
2995
+ return "null";
2996
+ }
2997
+ if (typeof value === "number") {
2998
+ return value.toString();
2999
+ }
3000
+ if (typeof value === "string") {
3001
+ return quote ? `'${escape(value)}'` : value;
3002
+ }
3003
+ if (Array.isArray(value)) {
3004
+ const content = value.map((it) => format(it, true)).join(", ");
3005
+ return `[ ${content} ]`;
3006
+ }
3007
+ if (typeof value === "object") {
3008
+ const content = Object.entries(value)
3009
+ .map(([key, nested]) => `${key}: ${format(nested, true)}`)
3010
+ .join(", ");
3011
+ return `{ ${content} }`;
3012
+ }
3013
+ return String(value);
3014
+ }
3015
+ /**
3016
+ * Replaces placeholder `{{ ... }}` with values from given object.
3017
+ *
3018
+ * @internal
3019
+ */
3020
+ function interpolate(text, data) {
3021
+ return text.replace(/{{\s*([^\s]+)\s*}}/g, (match, key) => {
3022
+ return typeof data[key] !== "undefined" ? format(data[key]) : match;
3023
+ });
3024
+ }
3025
+
2987
3026
  const remapEvents = {
2988
3027
  "tag:open": "tag:start",
2989
3028
  "tag:close": "tag:end",
@@ -3118,7 +3157,8 @@ class Rule {
3118
3157
  report(node, message, location, context) {
3119
3158
  if (this.isEnabled() && (!node || node.ruleEnabled(this.name))) {
3120
3159
  const where = this.findLocation({ node, location, event: this.event });
3121
- this.reporter.add(this, message, this.severity, node, where, context);
3160
+ const interpolated = interpolate(message, context !== null && context !== void 0 ? context : {});
3161
+ this.reporter.add(this, interpolated, this.severity, node, where, context);
3122
3162
  }
3123
3163
  }
3124
3164
  findLocation(src) {
@@ -3643,22 +3683,21 @@ var TokenType;
3643
3683
  (function (TokenType) {
3644
3684
  TokenType[TokenType["UNICODE_BOM"] = 1] = "UNICODE_BOM";
3645
3685
  TokenType[TokenType["WHITESPACE"] = 2] = "WHITESPACE";
3646
- TokenType[TokenType["NEWLINE"] = 3] = "NEWLINE";
3647
- TokenType[TokenType["DOCTYPE_OPEN"] = 4] = "DOCTYPE_OPEN";
3648
- TokenType[TokenType["DOCTYPE_VALUE"] = 5] = "DOCTYPE_VALUE";
3649
- TokenType[TokenType["DOCTYPE_CLOSE"] = 6] = "DOCTYPE_CLOSE";
3650
- TokenType[TokenType["TAG_OPEN"] = 7] = "TAG_OPEN";
3651
- TokenType[TokenType["TAG_CLOSE"] = 8] = "TAG_CLOSE";
3652
- TokenType[TokenType["ATTR_NAME"] = 9] = "ATTR_NAME";
3653
- TokenType[TokenType["ATTR_VALUE"] = 10] = "ATTR_VALUE";
3654
- TokenType[TokenType["TEXT"] = 11] = "TEXT";
3655
- TokenType[TokenType["TEMPLATING"] = 12] = "TEMPLATING";
3656
- TokenType[TokenType["SCRIPT"] = 13] = "SCRIPT";
3657
- TokenType[TokenType["STYLE"] = 14] = "STYLE";
3658
- TokenType[TokenType["COMMENT"] = 15] = "COMMENT";
3659
- TokenType[TokenType["CONDITIONAL"] = 16] = "CONDITIONAL";
3660
- TokenType[TokenType["DIRECTIVE"] = 17] = "DIRECTIVE";
3661
- TokenType[TokenType["EOF"] = 18] = "EOF";
3686
+ TokenType[TokenType["DOCTYPE_OPEN"] = 3] = "DOCTYPE_OPEN";
3687
+ TokenType[TokenType["DOCTYPE_VALUE"] = 4] = "DOCTYPE_VALUE";
3688
+ TokenType[TokenType["DOCTYPE_CLOSE"] = 5] = "DOCTYPE_CLOSE";
3689
+ TokenType[TokenType["TAG_OPEN"] = 6] = "TAG_OPEN";
3690
+ TokenType[TokenType["TAG_CLOSE"] = 7] = "TAG_CLOSE";
3691
+ TokenType[TokenType["ATTR_NAME"] = 8] = "ATTR_NAME";
3692
+ TokenType[TokenType["ATTR_VALUE"] = 9] = "ATTR_VALUE";
3693
+ TokenType[TokenType["TEXT"] = 10] = "TEXT";
3694
+ TokenType[TokenType["TEMPLATING"] = 11] = "TEMPLATING";
3695
+ TokenType[TokenType["SCRIPT"] = 12] = "SCRIPT";
3696
+ TokenType[TokenType["STYLE"] = 13] = "STYLE";
3697
+ TokenType[TokenType["COMMENT"] = 14] = "COMMENT";
3698
+ TokenType[TokenType["CONDITIONAL"] = 15] = "CONDITIONAL";
3699
+ TokenType[TokenType["DIRECTIVE"] = 16] = "DIRECTIVE";
3700
+ TokenType[TokenType["EOF"] = 17] = "EOF";
3662
3701
  })(TokenType || (TokenType = {}));
3663
3702
 
3664
3703
  /* eslint-disable no-useless-escape */
@@ -3683,7 +3722,7 @@ const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
3683
3722
  const MATCH_SCRIPT_END = /^<(\/)(script)/;
3684
3723
  const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
3685
3724
  const MATCH_STYLE_END = /^<(\/)(style)/;
3686
- const MATCH_DIRECTIVE = /^<!--\s*\[html-validate-(.*?)]\s*-->/;
3725
+ const MATCH_DIRECTIVE = /^<!--\s*(\[)html-validate-([a-z0-9-]+)\s*(.*?)(]?)\s*-->/;
3687
3726
  const MATCH_COMMENT = /^<!--([^]*?)-->/;
3688
3727
  const MATCH_CONDITIONAL = /^<!\[([^\]]*?)\]>/;
3689
3728
  class InvalidTokenError extends Error {
@@ -3738,15 +3777,15 @@ class Lexer {
3738
3777
  previousState = context.state;
3739
3778
  previousLength = context.string.length;
3740
3779
  }
3741
- yield this.token(context, TokenType.EOF);
3780
+ yield this.token(context, TokenType.EOF, []);
3742
3781
  }
3743
3782
  token(context, type, data) {
3744
- const size = data ? data[0].length : 0;
3783
+ const size = data.length > 0 ? data[0].length : 0;
3745
3784
  const location = context.getLocation(size);
3746
3785
  return {
3747
3786
  type,
3748
3787
  location,
3749
- data: data ? Array.from(data) : null,
3788
+ data: Array.from(data),
3750
3789
  };
3751
3790
  }
3752
3791
  /* istanbul ignore next: used to provide a better error when an unhandled state happens */
@@ -3771,17 +3810,18 @@ class Lexer {
3771
3810
  }
3772
3811
  }
3773
3812
  *match(context, tests, error) {
3774
- let match = null;
3775
3813
  const n = tests.length;
3776
3814
  for (let i = 0; i < n; i++) {
3777
3815
  const [regex, nextState, tokenType] = tests[i];
3778
- if (regex === false || (match = context.string.match(regex))) {
3816
+ const match = regex ? context.string.match(regex) : [""];
3817
+ if (match) {
3779
3818
  let token = null;
3780
3819
  if (tokenType !== false) {
3781
- yield (token = this.token(context, tokenType, match));
3820
+ token = this.token(context, tokenType, match);
3821
+ yield token;
3782
3822
  }
3783
3823
  const state = this.evalNextState(nextState, token);
3784
- context.consume(match || 0, state);
3824
+ context.consume(match, state);
3785
3825
  this.enter(context, state, match);
3786
3826
  return;
3787
3827
  }
@@ -3828,18 +3868,19 @@ class Lexer {
3828
3868
  *tokenizeTag(context) {
3829
3869
  /* eslint-disable-next-line consistent-return -- exhaustive switch handled by typescript */
3830
3870
  function nextState(token) {
3871
+ const tagCloseToken = token;
3831
3872
  switch (context.contentModel) {
3832
3873
  case ContentModel.TEXT:
3833
3874
  return State.TEXT;
3834
3875
  case ContentModel.SCRIPT:
3835
- if (token && token.data[0][0] !== "/") {
3876
+ if (tagCloseToken && tagCloseToken.data[0][0] !== "/") {
3836
3877
  return State.SCRIPT;
3837
3878
  }
3838
3879
  else {
3839
3880
  return State.TEXT; /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
3840
3881
  }
3841
3882
  case ContentModel.STYLE:
3842
- if (token && token.data[0][0] !== "/") {
3883
+ if (tagCloseToken && tagCloseToken.data[0][0] !== "/") {
3843
3884
  return State.STYLE;
3844
3885
  }
3845
3886
  else {
@@ -5987,7 +6028,7 @@ class NoConditionalComment extends Rule {
5987
6028
  }
5988
6029
  setup() {
5989
6030
  this.on("conditional", (event) => {
5990
- this.report(null, "Use of conditional comments are deprecated", event.location);
6031
+ this.report(event.parent, "Use of conditional comments are deprecated", event.location);
5991
6032
  });
5992
6033
  }
5993
6034
  }
@@ -9567,7 +9608,7 @@ const config$3 = {
9567
9608
  "no-redundant-for": "error",
9568
9609
  "no-redundant-role": "error",
9569
9610
  "prefer-native-element": "error",
9570
- "svg-focusable": "error",
9611
+ "svg-focusable": "off",
9571
9612
  "text-content": "error",
9572
9613
  "wcag/h30": "error",
9573
9614
  "wcag/h32": "error",
@@ -9638,7 +9679,7 @@ const config$1 = {
9638
9679
  "prefer-tbody": "error",
9639
9680
  "script-element": "error",
9640
9681
  "script-type": "error",
9641
- "svg-focusable": "error",
9682
+ "svg-focusable": "off",
9642
9683
  "text-content": "error",
9643
9684
  "unrecognized-char-ref": "error",
9644
9685
  void: "off",
@@ -10413,6 +10454,12 @@ class ParserError extends Error {
10413
10454
  }
10414
10455
  }
10415
10456
 
10457
+ function isAttrValueToken(token) {
10458
+ return Boolean(token && token.type === TokenType.ATTR_VALUE);
10459
+ }
10460
+ function svgShouldRetainTag(foreignTagName, tagName) {
10461
+ return foreignTagName === "svg" && ["title", "desc"].includes(tagName);
10462
+ }
10416
10463
  /**
10417
10464
  * Parse HTML document into a DOM tree.
10418
10465
  *
@@ -10425,6 +10472,7 @@ class Parser {
10425
10472
  * @param config - Configuration
10426
10473
  */
10427
10474
  constructor(config) {
10475
+ this.currentNamespace = "";
10428
10476
  this.event = new EventHandler();
10429
10477
  this.dom = null;
10430
10478
  this.metaTable = config.getMetaTable();
@@ -10435,7 +10483,6 @@ class Parser {
10435
10483
  * @param source - HTML markup.
10436
10484
  * @returns DOM tree representing the HTML markup.
10437
10485
  */
10438
- // eslint-disable-next-line complexity
10439
10486
  parseHtml(source) {
10440
10487
  var _a, _b, _c, _d;
10441
10488
  if (typeof source === "string") {
@@ -10466,43 +10513,7 @@ class Parser {
10466
10513
  let it = this.next(tokenStream);
10467
10514
  while (!it.done) {
10468
10515
  const token = it.value;
10469
- switch (token.type) {
10470
- case TokenType.UNICODE_BOM:
10471
- /* ignore */
10472
- break;
10473
- case TokenType.TAG_OPEN:
10474
- this.consumeTag(source, token, tokenStream);
10475
- break;
10476
- case TokenType.WHITESPACE:
10477
- this.trigger("whitespace", {
10478
- text: token.data[0],
10479
- location: token.location,
10480
- });
10481
- this.appendText(token.data[0], token.location);
10482
- break;
10483
- case TokenType.DIRECTIVE:
10484
- this.consumeDirective(token);
10485
- break;
10486
- case TokenType.CONDITIONAL:
10487
- this.trigger("conditional", {
10488
- condition: token.data[1],
10489
- location: token.location,
10490
- });
10491
- break;
10492
- case TokenType.COMMENT:
10493
- this.consumeComment(token);
10494
- break;
10495
- case TokenType.DOCTYPE_OPEN:
10496
- this.consumeDoctype(token, tokenStream);
10497
- break;
10498
- case TokenType.TEXT:
10499
- case TokenType.TEMPLATING:
10500
- this.appendText(token.data, token.location);
10501
- break;
10502
- case TokenType.EOF:
10503
- this.closeTree(source, token.location);
10504
- break;
10505
- }
10516
+ this.consume(source, token, tokenStream);
10506
10517
  it = this.next(tokenStream);
10507
10518
  }
10508
10519
  /* resolve any dynamic meta element properties */
@@ -10549,13 +10560,50 @@ class Parser {
10549
10560
  return Boolean(active.parent && active.parent.is(tagName) && meta.includes(active.tagName));
10550
10561
  }
10551
10562
  }
10563
+ /* eslint-disable-next-line complexity */
10564
+ consume(source, token, tokenStream) {
10565
+ switch (token.type) {
10566
+ case TokenType.UNICODE_BOM:
10567
+ /* ignore */
10568
+ break;
10569
+ case TokenType.TAG_OPEN:
10570
+ this.consumeTag(source, token, tokenStream);
10571
+ break;
10572
+ case TokenType.WHITESPACE:
10573
+ this.trigger("whitespace", {
10574
+ text: token.data[0],
10575
+ location: token.location,
10576
+ });
10577
+ this.appendText(token.data[0], token.location);
10578
+ break;
10579
+ case TokenType.DIRECTIVE:
10580
+ this.consumeDirective(token);
10581
+ break;
10582
+ case TokenType.CONDITIONAL:
10583
+ this.consumeConditional(token);
10584
+ break;
10585
+ case TokenType.COMMENT:
10586
+ this.consumeComment(token);
10587
+ break;
10588
+ case TokenType.DOCTYPE_OPEN:
10589
+ this.consumeDoctype(token, tokenStream);
10590
+ break;
10591
+ case TokenType.TEXT:
10592
+ case TokenType.TEMPLATING:
10593
+ this.appendText(token.data[0], token.location);
10594
+ break;
10595
+ case TokenType.EOF:
10596
+ this.closeTree(source, token.location);
10597
+ break;
10598
+ }
10599
+ }
10552
10600
  /* eslint-disable-next-line complexity, sonarjs/cognitive-complexity */
10553
10601
  consumeTag(source, startToken, tokenStream) {
10554
10602
  const tokens = Array.from(this.consumeUntil(tokenStream, TokenType.TAG_CLOSE, startToken.location));
10555
10603
  const endToken = tokens.slice(-1)[0];
10556
10604
  const closeOptional = this.closeOptional(startToken);
10557
10605
  const parent = closeOptional ? this.dom.getActive().parent : this.dom.getActive();
10558
- const node = HtmlElement.fromTokens(startToken, endToken, parent, this.metaTable);
10606
+ const node = HtmlElement.fromTokens(startToken, endToken, parent, this.metaTable, this.currentNamespace);
10559
10607
  const isStartTag = !startToken.data[1];
10560
10608
  const isClosing = !isStartTag || node.closed !== NodeClosed.Open;
10561
10609
  const isForeign = node.meta && node.meta.foreign;
@@ -10660,6 +10708,15 @@ class Parser {
10660
10708
  const tokens = Array.from(this.consumeUntil(tokenStream, TokenType.TAG_OPEN, errorLocation));
10661
10709
  const [last] = tokens.slice(-1);
10662
10710
  const [, tagClosed, tagName] = last.data;
10711
+ /* special case: svg <title> and <desc> should be intact as it affects accessibility */
10712
+ if (!tagClosed && svgShouldRetainTag(foreignTagName, tagName)) {
10713
+ const oldNamespace = this.currentNamespace;
10714
+ this.currentNamespace = "svg";
10715
+ this.consumeTag(source, last, tokenStream);
10716
+ this.consumeUntilMatchingTag(source, tokenStream, tagName);
10717
+ this.currentNamespace = oldNamespace;
10718
+ continue;
10719
+ }
10663
10720
  /* keep going unless the new tag matches the foreign root element */
10664
10721
  if (tagName !== foreignTagName) {
10665
10722
  continue;
@@ -10692,15 +10749,15 @@ class Parser {
10692
10749
  const keyLocation = this.getAttributeKeyLocation(token);
10693
10750
  const valueLocation = this.getAttributeValueLocation(next);
10694
10751
  const location = this.getAttributeLocation(token, next);
10695
- const haveValue = next && next.type === TokenType.ATTR_VALUE;
10752
+ const haveValue = isAttrValueToken(next);
10696
10753
  const attrData = {
10697
10754
  key: token.data[1],
10698
10755
  value: null,
10699
10756
  quote: null,
10700
10757
  };
10701
- if (next && haveValue) {
10758
+ if (haveValue) {
10702
10759
  const [, , value, quote] = next.data;
10703
- attrData.value = value !== null && value !== void 0 ? value : null;
10760
+ attrData.value = value;
10704
10761
  attrData.quote = quote !== null && quote !== void 0 ? quote : null;
10705
10762
  }
10706
10763
  /* get callback to process attributes, default is to just return attribute
@@ -10779,12 +10836,16 @@ class Parser {
10779
10836
  };
10780
10837
  }
10781
10838
  consumeDirective(token) {
10782
- const directive = token.data[1];
10783
- const match = directive.match(/^([a-zA-Z0-9-]+)\s*(.*?)(?:\s*:\s*(.*))?$/);
10839
+ const [text, , action, directive, end] = token.data;
10840
+ if (end === "") {
10841
+ throw new Error(`Missing end bracket "]" on directive "${text}"`);
10842
+ }
10843
+ const match = directive.match(/^(.*?)(?:\s*(?:--|:)\s*(.*))?$/);
10844
+ /* istanbul ignore next: should not be possible, would be emitted as comment token */
10784
10845
  if (!match) {
10785
- throw new Error(`Failed to parse directive "${directive}"`);
10846
+ throw new Error(`Failed to parse directive "${text}"`);
10786
10847
  }
10787
- const [, action, data, comment] = match;
10848
+ const [, data, comment] = match;
10788
10849
  this.trigger("directive", {
10789
10850
  action,
10790
10851
  data,
@@ -10792,17 +10853,33 @@ class Parser {
10792
10853
  location: token.location,
10793
10854
  });
10794
10855
  }
10856
+ /**
10857
+ * Consumes conditional comment in tag form.
10858
+ *
10859
+ * See also the related [[consumeCommend]] method.
10860
+ */
10861
+ consumeConditional(token) {
10862
+ const element = this.dom.getActive();
10863
+ this.trigger("conditional", {
10864
+ condition: token.data[1],
10865
+ location: token.location,
10866
+ parent: element,
10867
+ });
10868
+ }
10795
10869
  /**
10796
10870
  * Consumes comment token.
10797
10871
  *
10798
- * Tries to find IE conditional comments and emits conditional token if found.
10872
+ * Tries to find IE conditional comments and emits conditional token if
10873
+ * found. See also the related [[consumeConditional]] method.
10799
10874
  */
10800
10875
  consumeComment(token) {
10801
10876
  const comment = token.data[0];
10877
+ const element = this.dom.getActive();
10802
10878
  for (const conditional of parseConditionalComment(comment, token.location)) {
10803
10879
  this.trigger("conditional", {
10804
10880
  condition: conditional.expression,
10805
10881
  location: conditional.location,
10882
+ parent: element,
10806
10883
  });
10807
10884
  }
10808
10885
  }
@@ -10811,7 +10888,8 @@ class Parser {
10811
10888
  */
10812
10889
  consumeDoctype(startToken, tokenStream) {
10813
10890
  const tokens = Array.from(this.consumeUntil(tokenStream, TokenType.DOCTYPE_CLOSE, startToken.location));
10814
- const doctype = tokens[0]; /* first token is the doctype, second is the closing ">" */
10891
+ /* first token is the doctype, second is the closing ">" */
10892
+ const doctype = tokens[0];
10815
10893
  const value = doctype.data[0];
10816
10894
  this.dom.doctype = value;
10817
10895
  this.trigger("doctype", {
@@ -10837,6 +10915,35 @@ class Parser {
10837
10915
  }
10838
10916
  throw new ParserError(errorLocation, `stream ended before ${TokenType[search]} token was found`);
10839
10917
  }
10918
+ /**
10919
+ * Consumes tokens until a matching close-tag is found. Tags are appended to
10920
+ * the document.
10921
+ *
10922
+ * @internal
10923
+ */
10924
+ consumeUntilMatchingTag(source, tokenStream, searchTag) {
10925
+ let numOpen = 1;
10926
+ let it = this.next(tokenStream);
10927
+ while (!it.done) {
10928
+ const token = it.value;
10929
+ this.consume(source, token, tokenStream);
10930
+ if (token.type === TokenType.TAG_OPEN) {
10931
+ const [, close, tagName] = token.data;
10932
+ if (tagName === searchTag) {
10933
+ if (close) {
10934
+ numOpen--;
10935
+ }
10936
+ else {
10937
+ numOpen++;
10938
+ }
10939
+ if (numOpen === 0) {
10940
+ return;
10941
+ }
10942
+ }
10943
+ }
10944
+ it = this.next(tokenStream);
10945
+ }
10946
+ }
10840
10947
  next(tokenStream) {
10841
10948
  const it = tokenStream.next();
10842
10949
  if (!it.done) {
@@ -10844,7 +10951,7 @@ class Parser {
10844
10951
  this.trigger("token", {
10845
10952
  location: token.location,
10846
10953
  type: token.type,
10847
- data: token.data ? Array.from(token.data) : undefined,
10954
+ data: Array.from(token.data),
10848
10955
  });
10849
10956
  }
10850
10957
  return it;
@@ -11104,11 +11211,12 @@ class Engine {
11104
11211
  return lines;
11105
11212
  }
11106
11213
  dumpTokens(source) {
11214
+ var _a;
11107
11215
  const lexer = new Lexer();
11108
11216
  const lines = [];
11109
11217
  for (const src of source) {
11110
11218
  for (const token of lexer.tokenize(src)) {
11111
- const data = token.data ? token.data[0] : null;
11219
+ const data = (_a = token.data[0]) !== null && _a !== void 0 ? _a : "";
11112
11220
  lines.push({
11113
11221
  token: TokenType[token.type],
11114
11222
  data,