html-validate 10.14.0 → 10.15.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/esm/core.js CHANGED
@@ -1195,9 +1195,6 @@ function clone(value) {
1195
1195
  return JSON.parse(JSON.stringify(value));
1196
1196
  }
1197
1197
  }
1198
- function overwriteMerge$1(_a, b) {
1199
- return b;
1200
- }
1201
1198
  class MetaTable {
1202
1199
  elements;
1203
1200
  schema;
@@ -1370,15 +1367,22 @@ class MetaTable {
1370
1367
  }
1371
1368
  }
1372
1369
  mergeElement(a, b) {
1373
- const merged = deepmerge(a, b, { arrayMerge: overwriteMerge$1 });
1374
- const filteredAttrs = Object.entries(
1375
- merged.attributes
1376
- ).filter(([, attr]) => {
1377
- const val = !attr.delete;
1378
- delete attr.delete;
1379
- return val;
1380
- });
1381
- merged.attributes = Object.fromEntries(filteredAttrs);
1370
+ const merged = { ...a, ...b };
1371
+ const mergedAttrs = {
1372
+ ...a.attributes,
1373
+ ...b.attributes
1374
+ };
1375
+ for (const [name, attr] of Object.entries(mergedAttrs)) {
1376
+ if (attr.delete) {
1377
+ delete mergedAttrs[name];
1378
+ } else {
1379
+ delete attr.delete;
1380
+ }
1381
+ }
1382
+ merged.attributes = mergedAttrs;
1383
+ if (a.aria) {
1384
+ merged.aria = { ...a.aria, ...b.aria };
1385
+ }
1382
1386
  return merged;
1383
1387
  }
1384
1388
  /**
@@ -1959,71 +1963,68 @@ function factory(name, context) {
1959
1963
  function stripslashes(value) {
1960
1964
  return value.replaceAll(/\\(.)/g, "$1");
1961
1965
  }
1962
- class Condition {
1966
+ function createClassCondition(classname) {
1967
+ return {
1968
+ kind: "class",
1969
+ classname,
1970
+ match(node) {
1971
+ return node.classList.contains(classname);
1972
+ }
1973
+ };
1963
1974
  }
1964
- class ClassCondition extends Condition {
1965
- classname;
1966
- constructor(classname) {
1967
- super();
1968
- this.classname = classname;
1969
- }
1970
- match(node) {
1971
- return node.classList.contains(this.classname);
1972
- }
1975
+ function createIdCondition(raw) {
1976
+ const id = stripslashes(raw);
1977
+ return {
1978
+ kind: "id",
1979
+ id,
1980
+ match(node) {
1981
+ return node.id === id;
1982
+ }
1983
+ };
1973
1984
  }
1974
- class IdCondition extends Condition {
1975
- id;
1976
- constructor(id) {
1977
- super();
1978
- this.id = stripslashes(id);
1979
- }
1980
- match(node) {
1981
- return node.id === this.id;
1982
- }
1985
+ function createAttributeCondition(attr) {
1986
+ const match = /^(.+?)(?:([$*^|~]?=)"([^"]+?)")?$/.exec(attr);
1987
+ const key = match[1];
1988
+ const op = match[2];
1989
+ const rawValue = match[3];
1990
+ const value = typeof rawValue === "string" ? stripslashes(rawValue) : rawValue;
1991
+ return {
1992
+ kind: "attribute",
1993
+ key,
1994
+ op,
1995
+ value,
1996
+ match(node) {
1997
+ const attrs = node.getAttribute(key, true);
1998
+ return attrs.some((cur) => {
1999
+ switch (op) {
2000
+ case void 0:
2001
+ return true;
2002
+ /* attribute exists */
2003
+ case "=":
2004
+ return cur.value === value;
2005
+ default:
2006
+ throw new Error(`Attribute selector operator ${op} is not implemented yet`);
2007
+ }
2008
+ });
2009
+ }
2010
+ };
1983
2011
  }
1984
- class AttributeCondition extends Condition {
1985
- key;
1986
- op;
1987
- value;
1988
- constructor(attr) {
1989
- super();
1990
- const [, key, op, value] = /^(.+?)(?:([$*^|~]?=)"([^"]+?)")?$/.exec(attr);
1991
- this.key = key;
1992
- this.op = op;
1993
- this.value = typeof value === "string" ? stripslashes(value) : value;
1994
- }
1995
- match(node) {
1996
- const attr = node.getAttribute(this.key, true);
1997
- return attr.some((cur) => {
1998
- switch (this.op) {
1999
- case void 0:
2000
- return true;
2001
- /* attribute exists */
2002
- case "=":
2003
- return cur.value === this.value;
2004
- default:
2005
- throw new Error(`Attribute selector operator ${this.op} is not implemented yet`);
2006
- }
2007
- });
2012
+ function createPseudoClassCondition(pseudoclass, context) {
2013
+ const match = /^([^(]+)(?:\((.*)\))?$/.exec(pseudoclass);
2014
+ if (!match) {
2015
+ throw new Error(`Missing pseudo-class after colon in selector pattern "${context}"`);
2008
2016
  }
2009
- }
2010
- class PseudoClassCondition extends Condition {
2011
- name;
2012
- args;
2013
- constructor(pseudoclass, context) {
2014
- super();
2015
- const match = /^([^(]+)(?:\((.*)\))?$/.exec(pseudoclass);
2016
- if (!match) {
2017
- throw new Error(`Missing pseudo-class after colon in selector pattern "${context}"`);
2017
+ const name = match[1];
2018
+ const args = match[2];
2019
+ return {
2020
+ kind: "pseudo",
2021
+ name,
2022
+ args,
2023
+ match(node, selectorContext) {
2024
+ const fn = factory(name, selectorContext);
2025
+ return fn(node, args);
2018
2026
  }
2019
- const [, name, args] = match;
2020
- this.name = name;
2021
- this.args = args;
2022
- }
2023
- match(node, context) {
2024
- const fn = factory(this.name, context);
2025
- return fn(node, this.args);
2026
- }
2027
+ };
2027
2028
  }
2028
2029
 
2029
2030
  function isDelimiter(ch) {
@@ -2098,37 +2099,84 @@ class Compound {
2098
2099
  createCondition(pattern) {
2099
2100
  switch (pattern[0]) {
2100
2101
  case ".":
2101
- return new ClassCondition(pattern.slice(1));
2102
+ return createClassCondition(pattern.slice(1));
2102
2103
  case "#":
2103
- return new IdCondition(pattern.slice(1));
2104
+ return createIdCondition(pattern.slice(1));
2104
2105
  case "[":
2105
- return new AttributeCondition(pattern.slice(1, -1));
2106
+ return createAttributeCondition(pattern.slice(1, -1));
2106
2107
  case ":":
2107
- return new PseudoClassCondition(pattern.slice(1), this.selector);
2108
+ return createPseudoClassCondition(pattern.slice(1), this.selector);
2108
2109
  default:
2109
2110
  throw new Error(`Failed to create selector condition for "${pattern}"`);
2110
2111
  }
2111
2112
  }
2112
2113
  }
2113
2114
 
2114
- const codepoints = {
2115
- " ": "\\9 ",
2116
- "\n": "\\a ",
2117
- "\r": "\\d "
2118
- };
2119
- function escapeSelectorComponent(text) {
2120
- return text.toString().replaceAll(/([\t\n\r]|[^\w-])/gi, (_, ch) => {
2121
- if (codepoints[ch]) {
2122
- return codepoints[ch];
2123
- } else {
2124
- return `\\${ch}`;
2115
+ const escapedCodepoints = /* @__PURE__ */ new Set(["9", "a", "d"]);
2116
+ function* splitSelectorElements(selector) {
2117
+ let begin = 0;
2118
+ let end = 0;
2119
+ function initialState(ch, p) {
2120
+ if (ch === "\\") {
2121
+ return 1 /* ESCAPED */;
2125
2122
  }
2126
- });
2123
+ if (ch === " ") {
2124
+ end = p;
2125
+ return 2 /* WHITESPACE */;
2126
+ }
2127
+ return 0 /* INITIAL */;
2128
+ }
2129
+ function escapedState(ch) {
2130
+ if (escapedCodepoints.has(ch)) {
2131
+ return 1 /* ESCAPED */;
2132
+ }
2133
+ return 0 /* INITIAL */;
2134
+ }
2135
+ function* whitespaceState(ch, p) {
2136
+ if (ch === " ") {
2137
+ return 2 /* WHITESPACE */;
2138
+ }
2139
+ yield selector.slice(begin, end);
2140
+ begin = p;
2141
+ end = p;
2142
+ return 0 /* INITIAL */;
2143
+ }
2144
+ let state = 0 /* INITIAL */;
2145
+ for (let p = 0; p < selector.length; p++) {
2146
+ const ch = selector[p];
2147
+ switch (state) {
2148
+ case 0 /* INITIAL */:
2149
+ state = initialState(ch, p);
2150
+ break;
2151
+ case 1 /* ESCAPED */:
2152
+ state = escapedState(ch);
2153
+ break;
2154
+ case 2 /* WHITESPACE */:
2155
+ state = yield* whitespaceState(ch, p);
2156
+ break;
2157
+ }
2158
+ }
2159
+ if (begin !== selector.length) {
2160
+ yield selector.slice(begin);
2161
+ }
2127
2162
  }
2128
2163
 
2129
- function generateIdSelector(id) {
2130
- const escaped = escapeSelectorComponent(id);
2131
- return /^\d/.test(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
2164
+ function unescapeCodepoint(value) {
2165
+ const replacement = {
2166
+ "\\9 ": " ",
2167
+ "\\a ": "\n",
2168
+ "\\d ": "\r"
2169
+ };
2170
+ return value.replaceAll(
2171
+ /(\\[9ad] )/g,
2172
+ (_, codepoint) => replacement[codepoint]
2173
+ );
2174
+ }
2175
+ function getCompounds(selector) {
2176
+ selector = selector.replaceAll(/([+>~]) /g, "$1");
2177
+ return Array.from(splitSelectorElements(selector), (element) => {
2178
+ return new Compound(unescapeCodepoint(element));
2179
+ });
2132
2180
  }
2133
2181
 
2134
2182
  function* ancestors$1(element) {
@@ -2193,70 +2241,16 @@ function matchElement(element, compounds, context) {
2193
2241
  return false;
2194
2242
  }
2195
2243
 
2196
- const escapedCodepoints = /* @__PURE__ */ new Set(["9", "a", "d"]);
2197
- function* splitSelectorElements(selector) {
2198
- let begin = 0;
2199
- let end = 0;
2200
- function initialState(ch, p) {
2201
- if (ch === "\\") {
2202
- return 1 /* ESCAPED */;
2203
- }
2204
- if (ch === " ") {
2205
- end = p;
2206
- return 2 /* WHITESPACE */;
2207
- }
2208
- return 0 /* INITIAL */;
2244
+ class ComplexSelector {
2245
+ compounds;
2246
+ constructor(compounds) {
2247
+ this.compounds = compounds;
2209
2248
  }
2210
- function escapedState(ch) {
2211
- if (escapedCodepoints.has(ch)) {
2212
- return 1 /* ESCAPED */;
2213
- }
2214
- return 0 /* INITIAL */;
2249
+ static fromString(selector) {
2250
+ return new ComplexSelector(getCompounds(selector));
2215
2251
  }
2216
- function* whitespaceState(ch, p) {
2217
- if (ch === " ") {
2218
- return 2 /* WHITESPACE */;
2219
- }
2220
- yield selector.slice(begin, end);
2221
- begin = p;
2222
- end = p;
2223
- return 0 /* INITIAL */;
2224
- }
2225
- let state = 0 /* INITIAL */;
2226
- for (let p = 0; p < selector.length; p++) {
2227
- const ch = selector[p];
2228
- switch (state) {
2229
- case 0 /* INITIAL */:
2230
- state = initialState(ch, p);
2231
- break;
2232
- case 1 /* ESCAPED */:
2233
- state = escapedState(ch);
2234
- break;
2235
- case 2 /* WHITESPACE */:
2236
- state = yield* whitespaceState(ch, p);
2237
- break;
2238
- }
2239
- }
2240
- if (begin !== selector.length) {
2241
- yield selector.slice(begin);
2242
- }
2243
- }
2244
-
2245
- function unescapeCodepoint(value) {
2246
- const replacement = {
2247
- "\\9 ": " ",
2248
- "\\a ": "\n",
2249
- "\\d ": "\r"
2250
- };
2251
- return value.replaceAll(
2252
- /(\\[9ad] )/g,
2253
- (_, codepoint) => replacement[codepoint]
2254
- );
2255
- }
2256
- class Selector {
2257
- pattern;
2258
- constructor(selector) {
2259
- this.pattern = Selector.parse(selector);
2252
+ static fromCompounds(compounds) {
2253
+ return new ComplexSelector(compounds);
2260
2254
  }
2261
2255
  /**
2262
2256
  * Match this selector against a HtmlElement.
@@ -2273,15 +2267,15 @@ class Selector {
2273
2267
  */
2274
2268
  matchElement(element) {
2275
2269
  const context = { scope: null };
2276
- return matchElement(element, this.pattern, context);
2270
+ return matchElement(element, this.compounds, context);
2277
2271
  }
2278
2272
  *matchInternal(root, level, context) {
2279
- if (level >= this.pattern.length) {
2273
+ if (level >= this.compounds.length) {
2280
2274
  yield root;
2281
2275
  return;
2282
2276
  }
2283
- const pattern = this.pattern[level];
2284
- const matches = Selector.findCandidates(root, pattern);
2277
+ const pattern = this.compounds[level];
2278
+ const matches = ComplexSelector.findCandidates(root, pattern);
2285
2279
  for (const node of matches) {
2286
2280
  if (!pattern.match(node, context)) {
2287
2281
  continue;
@@ -2289,12 +2283,6 @@ class Selector {
2289
2283
  yield* this.matchInternal(node, level + 1, context);
2290
2284
  }
2291
2285
  }
2292
- static parse(selector) {
2293
- selector = selector.replaceAll(/([+>~]) /g, "$1");
2294
- return Array.from(splitSelectorElements(selector), (element) => {
2295
- return new Compound(unescapeCodepoint(element));
2296
- });
2297
- }
2298
2286
  static findCandidates(root, pattern) {
2299
2287
  switch (pattern.combinator) {
2300
2288
  case Combinator.DESCENDANT:
@@ -2302,9 +2290,9 @@ class Selector {
2302
2290
  case Combinator.CHILD:
2303
2291
  return root.childElements.filter((node) => node.is(pattern.tagName));
2304
2292
  case Combinator.ADJACENT_SIBLING:
2305
- return Selector.findAdjacentSibling(root);
2293
+ return ComplexSelector.findAdjacentSibling(root);
2306
2294
  case Combinator.GENERAL_SIBLING:
2307
- return Selector.findGeneralSibling(root);
2295
+ return ComplexSelector.findGeneralSibling(root);
2308
2296
  case Combinator.SCOPE:
2309
2297
  return [root];
2310
2298
  }
@@ -2316,7 +2304,7 @@ class Selector {
2316
2304
  adjacent = false;
2317
2305
  return true;
2318
2306
  }
2319
- if (cur === node) {
2307
+ if (cur.isSameNode(node)) {
2320
2308
  adjacent = true;
2321
2309
  }
2322
2310
  return false;
@@ -2328,7 +2316,7 @@ class Selector {
2328
2316
  if (after) {
2329
2317
  return true;
2330
2318
  }
2331
- if (cur === node) {
2319
+ if (cur.isSameNode(node)) {
2332
2320
  after = true;
2333
2321
  }
2334
2322
  return false;
@@ -2336,6 +2324,31 @@ class Selector {
2336
2324
  }
2337
2325
  }
2338
2326
 
2327
+ const codepoints = {
2328
+ " ": "\\9 ",
2329
+ "\n": "\\a ",
2330
+ "\r": "\\d "
2331
+ };
2332
+ function escapeSelectorComponent(text) {
2333
+ return text.toString().replaceAll(/([\t\n\r]|[^\w-])/gi, (_, ch) => {
2334
+ if (codepoints[ch]) {
2335
+ return codepoints[ch];
2336
+ } else {
2337
+ return `\\${ch}`;
2338
+ }
2339
+ });
2340
+ }
2341
+
2342
+ function generateIdSelector(id) {
2343
+ const escaped = escapeSelectorComponent(id);
2344
+ return /^\d/.test(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
2345
+ }
2346
+
2347
+ function parseSelector(selector) {
2348
+ const compounds = getCompounds(selector);
2349
+ return ComplexSelector.fromCompounds(compounds);
2350
+ }
2351
+
2339
2352
  const TEXT_NODE_NAME = "#text";
2340
2353
  function isTextNode(node) {
2341
2354
  return node?.nodeType === NodeType.TEXT_NODE;
@@ -2649,7 +2662,7 @@ class HtmlElement extends DOMNode {
2649
2662
  */
2650
2663
  matches(selectorList) {
2651
2664
  return selectorList.split(",").some((it) => {
2652
- const selector = new Selector(it.trim());
2665
+ const selector = parseSelector(it.trim());
2653
2666
  return selector.matchElement(this);
2654
2667
  });
2655
2668
  }
@@ -2882,9 +2895,9 @@ class HtmlElement extends DOMNode {
2882
2895
  if (!selectorList) {
2883
2896
  return;
2884
2897
  }
2885
- for (const selector of selectorList.split(/(?<!\\),\s*/)) {
2886
- const pattern = new Selector(selector);
2887
- yield* pattern.match(this);
2898
+ for (const selectorString of selectorList.split(/(?<!\\),\s*/)) {
2899
+ const selector = parseSelector(selectorString);
2900
+ yield* selector.match(this);
2888
2901
  }
2889
2902
  }
2890
2903
  /**
@@ -3737,6 +3750,7 @@ class Rule {
3737
3750
  severity;
3738
3751
  // rule severity
3739
3752
  event;
3753
+ tracker;
3740
3754
  /**
3741
3755
  * Rule name. Defaults to filename without extension but can be overwritten by
3742
3756
  * subclasses.
@@ -3756,6 +3770,7 @@ class Rule {
3756
3770
  this.blockers = [];
3757
3771
  this.severity = Severity.DISABLED;
3758
3772
  this.name = "";
3773
+ this.tracker = null;
3759
3774
  }
3760
3775
  getSeverity() {
3761
3776
  return this.severity;
@@ -3931,7 +3946,15 @@ class Rule {
3931
3946
  return this.parser.on(event, (_event, data) => {
3932
3947
  if (this.isEnabled() && filter(data)) {
3933
3948
  this.event = data;
3934
- callback(data);
3949
+ const { tracker } = this;
3950
+ if (tracker) {
3951
+ const start = performance.now();
3952
+ callback(data);
3953
+ const end = performance.now();
3954
+ tracker.trackRule(this.name, end - start);
3955
+ } else {
3956
+ callback(data);
3957
+ }
3935
3958
  }
3936
3959
  });
3937
3960
  }
@@ -3948,6 +3971,14 @@ class Rule {
3948
3971
  this.severity = severity;
3949
3972
  this.meta = meta;
3950
3973
  }
3974
+ /**
3975
+ * Set (or clear) the performance tracker.
3976
+ *
3977
+ * @internal
3978
+ */
3979
+ setTracker(tracker) {
3980
+ this.tracker = tracker;
3981
+ }
3951
3982
  /**
3952
3983
  * Validate rule options against schema. Throws error if object does not validate.
3953
3984
  *
@@ -12462,8 +12493,10 @@ class StaticConfigLoader extends ConfigLoader {
12462
12493
 
12463
12494
  class EventHandler {
12464
12495
  listeners;
12496
+ tracker;
12465
12497
  constructor() {
12466
12498
  this.listeners = {};
12499
+ this.tracker = null;
12467
12500
  }
12468
12501
  /**
12469
12502
  * Add an event listener.
@@ -12502,6 +12535,14 @@ class EventHandler {
12502
12535
  });
12503
12536
  return deregister;
12504
12537
  }
12538
+ /**
12539
+ * Set (or clear) the performance tracker.
12540
+ *
12541
+ * @internal
12542
+ */
12543
+ setTracker(tracker) {
12544
+ this.tracker = tracker;
12545
+ }
12505
12546
  /**
12506
12547
  * Trigger event causing all listeners to be called.
12507
12548
  *
@@ -12510,8 +12551,18 @@ class EventHandler {
12510
12551
  */
12511
12552
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- technical debt, should be made typesafe */
12512
12553
  trigger(event, data) {
12513
- for (const listener of this.getCallbacks(event)) {
12514
- listener.call(null, event, data);
12554
+ const { tracker } = this;
12555
+ if (tracker) {
12556
+ const start = performance.now();
12557
+ for (const listener of this.getCallbacks(event)) {
12558
+ listener.call(null, event, data);
12559
+ }
12560
+ const end = performance.now();
12561
+ tracker.trackEvent(event, end - start);
12562
+ } else {
12563
+ for (const listener of this.getCallbacks(event)) {
12564
+ listener.call(null, event, data);
12565
+ }
12515
12566
  }
12516
12567
  }
12517
12568
  getCallbacks(event) {
@@ -12523,7 +12574,7 @@ class EventHandler {
12523
12574
  }
12524
12575
 
12525
12576
  const name = "html-validate";
12526
- const version = "10.14.0";
12577
+ const version = "10.15.0";
12527
12578
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12528
12579
 
12529
12580
  function freeze(src) {
@@ -13457,6 +13508,78 @@ class Parser {
13457
13508
  }
13458
13509
  }
13459
13510
 
13511
+ class PerformanceTracker {
13512
+ eventData;
13513
+ ruleData;
13514
+ startTime;
13515
+ accConfigTime;
13516
+ accTransformTime;
13517
+ constructor() {
13518
+ this.eventData = /* @__PURE__ */ new Map();
13519
+ this.ruleData = /* @__PURE__ */ new Map();
13520
+ this.startTime = performance.now();
13521
+ this.accConfigTime = 0;
13522
+ this.accTransformTime = 0;
13523
+ }
13524
+ /**
13525
+ * Record a single event trigger with the time it took to run all listeners.
13526
+ */
13527
+ trackEvent(name, time) {
13528
+ const existing = this.eventData.get(name);
13529
+ if (existing) {
13530
+ existing.count += 1;
13531
+ existing.time += time;
13532
+ } else {
13533
+ this.eventData.set(name, { count: 1, time });
13534
+ }
13535
+ }
13536
+ /**
13537
+ * Record time spent loading configuration.
13538
+ */
13539
+ trackConfig(time) {
13540
+ this.accConfigTime += time;
13541
+ }
13542
+ /**
13543
+ * Record time spent in transformers.
13544
+ */
13545
+ trackTransform(time) {
13546
+ this.accTransformTime += time;
13547
+ }
13548
+ /**
13549
+ * Record a single rule callback invocation with its execution time.
13550
+ */
13551
+ trackRule(ruleName, time) {
13552
+ const existing = this.ruleData.get(ruleName);
13553
+ if (existing) {
13554
+ existing.count += 1;
13555
+ existing.time += time;
13556
+ } else {
13557
+ this.ruleData.set(ruleName, { count: 1, time });
13558
+ }
13559
+ }
13560
+ /**
13561
+ * Returns a snapshot of the recorded performance data, with both arrays
13562
+ * sorted by time (descending).
13563
+ */
13564
+ getResult() {
13565
+ const events = Array.from(
13566
+ this.eventData.entries(),
13567
+ ([event, { count, time }]) => ({ event, count, time })
13568
+ ).toSorted((a, b) => b.time - a.time);
13569
+ const rules = Array.from(
13570
+ this.ruleData.entries(),
13571
+ ([rule, { count, time }]) => ({ rule, count, time })
13572
+ ).toSorted((a, b) => b.time - a.time);
13573
+ return {
13574
+ events,
13575
+ rules,
13576
+ configTime: this.accConfigTime,
13577
+ transformTime: this.accTransformTime,
13578
+ totalTime: performance.now() - this.startTime
13579
+ };
13580
+ }
13581
+ }
13582
+
13460
13583
  const ruleIds = new Set(Object.keys(bundledRules));
13461
13584
  function ruleExists(ruleId) {
13462
13585
  return ruleIds.has(ruleId);
@@ -13504,10 +13627,12 @@ class Engine {
13504
13627
  config;
13505
13628
  ParserClass;
13506
13629
  availableRules;
13507
- constructor(config, ParserClass) {
13630
+ tracker;
13631
+ constructor(config, ParserClass, options) {
13508
13632
  this.report = new Reporter();
13509
13633
  this.config = config;
13510
13634
  this.ParserClass = ParserClass;
13635
+ this.tracker = options.tracker;
13511
13636
  const result = this.initPlugins(this.config);
13512
13637
  this.availableRules = {
13513
13638
  ...bundledRules,
@@ -13523,6 +13648,9 @@ class Engine {
13523
13648
  lint(sources) {
13524
13649
  for (const source of sources) {
13525
13650
  const parser = this.instantiateParser();
13651
+ if (this.tracker) {
13652
+ parser.getEventHandler().setTracker(this.tracker);
13653
+ }
13526
13654
  const { rules } = this.setupPlugins(source, this.config, parser);
13527
13655
  const noUnusedDisable = rules["no-unused-disable"];
13528
13656
  const directiveContext = {
@@ -13799,6 +13927,7 @@ class Engine {
13799
13927
  const rule = this.instantiateRule(ruleId, options);
13800
13928
  rule.name = ruleId;
13801
13929
  rule.init(parser, report, severity, meta);
13930
+ rule.setTracker(this.tracker);
13802
13931
  if (rule.setup) {
13803
13932
  rule.setup();
13804
13933
  }
@@ -15157,5 +15286,5 @@ const engines = {
15157
15286
 
15158
15287
  var workerPath = "./jest-worker.js";
15159
15288
 
15160
- export { engines as $, Attribute as A, TextContent$1 as B, ConfigLoader as C, DOMNode as D, Engine as E, TextNode as F, ariaNaming as G, HtmlElement as H, classifyNodeText as I, presets as J, defineConfig as K, definePlugin as L, MetaCopyableProperty as M, NestedError as N, isUserError as O, Parser as P, keywordPatternMatcher as Q, Reporter as R, StaticConfigLoader as S, TextClassification as T, UserError as U, Validator as V, WrappedError as W, ruleExists as X, sliceLocation as Y, staticResolver as Z, walk as _, transformSourceSync as a, codeFrameColumns as a0, getEndLocation as a1, getStartLocation as a2, workerPath as a3, name as a4, bugs as a5, transformFilename as b, transformFilenameSync as c, configurationSchema as d, ConfigError as e, Config as f, compatibilityCheckImpl as g, ensureError as h, isThenable as i, getFormatter as j, deepmerge as k, ignore as l, DOMTokenList as m, normalizeSource as n, DOMTree as o, DynamicValue as p, EventHandler as q, MetaTable as r, NodeClosed as s, transformSource as t, NodeType as u, version as v, ResolvedConfig as w, Rule as x, SchemaValidationError as y, Severity as z };
15289
+ export { walk as $, Attribute as A, Severity as B, ConfigLoader as C, DOMNode as D, Engine as E, TextContent$1 as F, TextNode as G, HtmlElement as H, ariaNaming as I, classifyNodeText as J, presets as K, defineConfig as L, MetaCopyableProperty as M, NestedError as N, definePlugin as O, PerformanceTracker as P, isUserError as Q, Reporter as R, StaticConfigLoader as S, TextClassification as T, UserError as U, Validator as V, WrappedError as W, keywordPatternMatcher as X, ruleExists as Y, sliceLocation as Z, staticResolver as _, Parser as a, engines as a0, codeFrameColumns as a1, getEndLocation as a2, getStartLocation as a3, workerPath as a4, name as a5, bugs as a6, transformSourceSync as b, transformFilename as c, transformFilenameSync as d, configurationSchema as e, ConfigError as f, Config as g, compatibilityCheckImpl as h, isThenable as i, ensureError as j, getFormatter as k, deepmerge as l, ignore as m, normalizeSource as n, DOMTokenList as o, DOMTree as p, DynamicValue as q, EventHandler as r, MetaTable as s, transformSource as t, NodeClosed as u, version as v, NodeType as w, ResolvedConfig as x, Rule as y, SchemaValidationError as z };
15161
15290
  //# sourceMappingURL=core.js.map