html-validate 9.4.0 → 9.4.2-rc.1

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/cjs/core.js CHANGED
@@ -1944,15 +1944,15 @@ function nthChild(node, args) {
1944
1944
  return cur === n;
1945
1945
  }
1946
1946
 
1947
- function scope(node) {
1948
- return node.isSameNode(this.scope);
1947
+ function scope$1(node) {
1948
+ return Boolean(this.scope && node.isSameNode(this.scope));
1949
1949
  }
1950
1950
 
1951
1951
  const table = {
1952
1952
  "first-child": firstChild,
1953
1953
  "last-child": lastChild,
1954
1954
  "nth-child": nthChild,
1955
- scope
1955
+ scope: scope$1
1956
1956
  };
1957
1957
  function factory(name, context) {
1958
1958
  const fn = table[name];
@@ -1963,139 +1963,12 @@ function factory(name, context) {
1963
1963
  }
1964
1964
  }
1965
1965
 
1966
- const escapedCodepoints = ["9", "a", "d"];
1967
- function* splitSelectorElements(selector) {
1968
- let begin = 0;
1969
- let end = 0;
1970
- function initialState(ch, p) {
1971
- if (ch === "\\") {
1972
- return 1 /* ESCAPED */;
1973
- }
1974
- if (ch === " ") {
1975
- end = p;
1976
- return 2 /* WHITESPACE */;
1977
- }
1978
- return 0 /* INITIAL */;
1979
- }
1980
- function escapedState(ch) {
1981
- if (escapedCodepoints.includes(ch)) {
1982
- return 1 /* ESCAPED */;
1983
- }
1984
- return 0 /* INITIAL */;
1985
- }
1986
- function* whitespaceState(ch, p) {
1987
- if (ch === " ") {
1988
- return 2 /* WHITESPACE */;
1989
- }
1990
- yield selector.slice(begin, end);
1991
- begin = p;
1992
- end = p;
1993
- return 0 /* INITIAL */;
1994
- }
1995
- let state = 0 /* INITIAL */;
1996
- for (let p = 0; p < selector.length; p++) {
1997
- const ch = selector[p];
1998
- switch (state) {
1999
- case 0 /* INITIAL */:
2000
- state = initialState(ch, p);
2001
- break;
2002
- case 1 /* ESCAPED */:
2003
- state = escapedState(ch);
2004
- break;
2005
- case 2 /* WHITESPACE */:
2006
- state = yield* whitespaceState(ch, p);
2007
- break;
2008
- }
2009
- }
2010
- if (begin !== selector.length) {
2011
- yield selector.slice(begin);
2012
- }
2013
- }
2014
-
2015
1966
  function stripslashes(value) {
2016
1967
  return value.replace(/\\(.)/g, "$1");
2017
1968
  }
2018
- function unescapeCodepoint(value) {
2019
- const replacement = {
2020
- "\\9 ": " ",
2021
- "\\a ": "\n",
2022
- "\\d ": "\r"
2023
- };
2024
- return value.replace(
2025
- /(\\[\u0039\u0061\u0064] )/g,
2026
- (_, codepoint) => replacement[codepoint]
2027
- );
2028
- }
2029
- function escapeSelectorComponent(text) {
2030
- const codepoints = {
2031
- " ": "\\9 ",
2032
- "\n": "\\a ",
2033
- "\r": "\\d "
2034
- };
2035
- return text.toString().replace(/([\t\n\r]|[^a-z0-9_-])/gi, (_, ch) => {
2036
- if (codepoints[ch]) {
2037
- return codepoints[ch];
2038
- } else {
2039
- return `\\${ch}`;
2040
- }
2041
- });
2042
- }
2043
- function generateIdSelector(id) {
2044
- const escaped = escapeSelectorComponent(id);
2045
- return escaped.match(/^\d/) ? `[id="${escaped}"]` : `#${escaped}`;
2046
- }
2047
- function isDelimiter(ch) {
2048
- return /[.#[:]/.test(ch);
2049
- }
2050
- function isQuotationMark(ch) {
2051
- return /['"]/.test(ch);
2052
- }
2053
- function isPseudoElement(ch, buffer) {
2054
- return ch === ":" && buffer === ":";
2055
- }
2056
- function* splitPattern(pattern) {
2057
- if (pattern === "") {
2058
- return;
2059
- }
2060
- const end = pattern.length;
2061
- let begin = 0;
2062
- let cur = 1;
2063
- let quoted = false;
2064
- while (cur < end) {
2065
- const ch = pattern[cur];
2066
- const buffer = pattern.slice(begin, cur);
2067
- if (ch === "\\") {
2068
- cur += 2;
2069
- continue;
2070
- }
2071
- if (quoted) {
2072
- if (ch === quoted) {
2073
- quoted = false;
2074
- }
2075
- cur += 1;
2076
- continue;
2077
- }
2078
- if (isQuotationMark(ch)) {
2079
- quoted = ch;
2080
- cur += 1;
2081
- continue;
2082
- }
2083
- if (isPseudoElement(ch, buffer)) {
2084
- cur += 1;
2085
- continue;
2086
- }
2087
- if (isDelimiter(ch)) {
2088
- begin = cur;
2089
- yield buffer;
2090
- }
2091
- cur += 1;
2092
- }
2093
- const tail = pattern.slice(begin, cur);
2094
- yield tail;
2095
- }
2096
- class Matcher {
1969
+ class Condition {
2097
1970
  }
2098
- class ClassMatcher extends Matcher {
1971
+ class ClassCondition extends Condition {
2099
1972
  classname;
2100
1973
  constructor(classname) {
2101
1974
  super();
@@ -2105,7 +1978,7 @@ class ClassMatcher extends Matcher {
2105
1978
  return node.classList.contains(this.classname);
2106
1979
  }
2107
1980
  }
2108
- class IdMatcher extends Matcher {
1981
+ class IdCondition extends Condition {
2109
1982
  id;
2110
1983
  constructor(id) {
2111
1984
  super();
@@ -2115,7 +1988,7 @@ class IdMatcher extends Matcher {
2115
1988
  return node.id === this.id;
2116
1989
  }
2117
1990
  }
2118
- class AttrMatcher extends Matcher {
1991
+ class AttributeCondition extends Condition {
2119
1992
  key;
2120
1993
  op;
2121
1994
  value;
@@ -2141,7 +2014,7 @@ class AttrMatcher extends Matcher {
2141
2014
  });
2142
2015
  }
2143
2016
  }
2144
- class PseudoClassMatcher extends Matcher {
2017
+ class PseudoClassCondition extends Condition {
2145
2018
  name;
2146
2019
  args;
2147
2020
  constructor(pseudoclass, context) {
@@ -2159,11 +2032,62 @@ class PseudoClassMatcher extends Matcher {
2159
2032
  return fn(node, this.args);
2160
2033
  }
2161
2034
  }
2162
- class Pattern {
2035
+
2036
+ function isDelimiter(ch) {
2037
+ return /[.#[:]/.test(ch);
2038
+ }
2039
+ function isQuotationMark(ch) {
2040
+ return /['"]/.test(ch);
2041
+ }
2042
+ function isPseudoElement(ch, buffer) {
2043
+ return ch === ":" && buffer === ":";
2044
+ }
2045
+ function* splitCompound(pattern) {
2046
+ if (pattern === "") {
2047
+ return;
2048
+ }
2049
+ const end = pattern.length;
2050
+ let begin = 0;
2051
+ let cur = 1;
2052
+ let quoted = false;
2053
+ while (cur < end) {
2054
+ const ch = pattern[cur];
2055
+ const buffer = pattern.slice(begin, cur);
2056
+ if (ch === "\\") {
2057
+ cur += 2;
2058
+ continue;
2059
+ }
2060
+ if (quoted) {
2061
+ if (ch === quoted) {
2062
+ quoted = false;
2063
+ }
2064
+ cur += 1;
2065
+ continue;
2066
+ }
2067
+ if (isQuotationMark(ch)) {
2068
+ quoted = ch;
2069
+ cur += 1;
2070
+ continue;
2071
+ }
2072
+ if (isPseudoElement(ch, buffer)) {
2073
+ cur += 1;
2074
+ continue;
2075
+ }
2076
+ if (isDelimiter(ch)) {
2077
+ begin = cur;
2078
+ yield buffer;
2079
+ }
2080
+ cur += 1;
2081
+ }
2082
+ const tail = pattern.slice(begin, cur);
2083
+ yield tail;
2084
+ }
2085
+
2086
+ class Compound {
2163
2087
  combinator;
2164
2088
  tagName;
2165
2089
  selector;
2166
- pattern;
2090
+ conditions;
2167
2091
  constructor(pattern) {
2168
2092
  const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)([^]*)$/);
2169
2093
  if (!match) {
@@ -2173,25 +2097,168 @@ class Pattern {
2173
2097
  this.selector = pattern;
2174
2098
  this.combinator = parseCombinator(match.shift(), pattern);
2175
2099
  this.tagName = match.shift() || "*";
2176
- this.pattern = Array.from(splitPattern(match[0]), (it) => this.createMatcher(it));
2100
+ this.conditions = Array.from(splitCompound(match[0]), (it) => this.createCondition(it));
2177
2101
  }
2178
2102
  match(node, context) {
2179
- return node.is(this.tagName) && this.pattern.every((cur) => cur.match(node, context));
2103
+ return node.is(this.tagName) && this.conditions.every((cur) => cur.match(node, context));
2180
2104
  }
2181
- createMatcher(pattern) {
2105
+ createCondition(pattern) {
2182
2106
  switch (pattern[0]) {
2183
2107
  case ".":
2184
- return new ClassMatcher(pattern.slice(1));
2108
+ return new ClassCondition(pattern.slice(1));
2185
2109
  case "#":
2186
- return new IdMatcher(pattern.slice(1));
2110
+ return new IdCondition(pattern.slice(1));
2187
2111
  case "[":
2188
- return new AttrMatcher(pattern.slice(1, -1));
2112
+ return new AttributeCondition(pattern.slice(1, -1));
2189
2113
  case ":":
2190
- return new PseudoClassMatcher(pattern.slice(1), this.selector);
2114
+ return new PseudoClassCondition(pattern.slice(1), this.selector);
2191
2115
  default:
2192
- throw new Error(`Failed to create matcher for "${pattern}"`);
2116
+ throw new Error(`Failed to create selector condition for "${pattern}"`);
2117
+ }
2118
+ }
2119
+ }
2120
+
2121
+ function* ancestors$1(element) {
2122
+ let current = element.parent;
2123
+ while (current && !current.isRootElement()) {
2124
+ yield current;
2125
+ current = current.parent;
2126
+ }
2127
+ }
2128
+ function* parent(element) {
2129
+ const parent2 = element.parent;
2130
+ if (parent2 && !parent2.isRootElement()) {
2131
+ yield parent2;
2132
+ }
2133
+ }
2134
+ function* adjacentSibling(element) {
2135
+ const sibling = element.previousSibling;
2136
+ if (sibling) {
2137
+ yield sibling;
2138
+ }
2139
+ }
2140
+ function* generalSibling(element) {
2141
+ const siblings = element.siblings;
2142
+ const index = siblings.findIndex((it) => it.isSameNode(element));
2143
+ for (let i = 0; i < index; i++) {
2144
+ yield siblings[i];
2145
+ }
2146
+ }
2147
+ function* scope(element) {
2148
+ yield element;
2149
+ }
2150
+ function candidatesFromCombinator(element, combinator) {
2151
+ switch (combinator) {
2152
+ case Combinator.DESCENDANT:
2153
+ return ancestors$1(element);
2154
+ case Combinator.CHILD:
2155
+ return parent(element);
2156
+ case Combinator.ADJACENT_SIBLING:
2157
+ return adjacentSibling(element);
2158
+ case Combinator.GENERAL_SIBLING:
2159
+ return generalSibling(element);
2160
+ case Combinator.SCOPE:
2161
+ return scope(element);
2162
+ }
2163
+ }
2164
+ function matchElement(element, compounds, context) {
2165
+ if (compounds.length === 0) {
2166
+ return true;
2167
+ }
2168
+ const last = compounds[compounds.length - 1];
2169
+ if (!last.match(element, context)) {
2170
+ return false;
2171
+ }
2172
+ const remainder = compounds.slice(0, -1);
2173
+ if (remainder.length === 0) {
2174
+ return true;
2175
+ }
2176
+ const candidates = candidatesFromCombinator(element, last.combinator);
2177
+ for (const candidate of candidates) {
2178
+ if (matchElement(candidate, remainder, context)) {
2179
+ return true;
2193
2180
  }
2194
2181
  }
2182
+ return false;
2183
+ }
2184
+
2185
+ const escapedCodepoints = ["9", "a", "d"];
2186
+ function* splitSelectorElements(selector) {
2187
+ let begin = 0;
2188
+ let end = 0;
2189
+ function initialState(ch, p) {
2190
+ if (ch === "\\") {
2191
+ return 1 /* ESCAPED */;
2192
+ }
2193
+ if (ch === " ") {
2194
+ end = p;
2195
+ return 2 /* WHITESPACE */;
2196
+ }
2197
+ return 0 /* INITIAL */;
2198
+ }
2199
+ function escapedState(ch) {
2200
+ if (escapedCodepoints.includes(ch)) {
2201
+ return 1 /* ESCAPED */;
2202
+ }
2203
+ return 0 /* INITIAL */;
2204
+ }
2205
+ function* whitespaceState(ch, p) {
2206
+ if (ch === " ") {
2207
+ return 2 /* WHITESPACE */;
2208
+ }
2209
+ yield selector.slice(begin, end);
2210
+ begin = p;
2211
+ end = p;
2212
+ return 0 /* INITIAL */;
2213
+ }
2214
+ let state = 0 /* INITIAL */;
2215
+ for (let p = 0; p < selector.length; p++) {
2216
+ const ch = selector[p];
2217
+ switch (state) {
2218
+ case 0 /* INITIAL */:
2219
+ state = initialState(ch, p);
2220
+ break;
2221
+ case 1 /* ESCAPED */:
2222
+ state = escapedState(ch);
2223
+ break;
2224
+ case 2 /* WHITESPACE */:
2225
+ state = yield* whitespaceState(ch, p);
2226
+ break;
2227
+ }
2228
+ }
2229
+ if (begin !== selector.length) {
2230
+ yield selector.slice(begin);
2231
+ }
2232
+ }
2233
+
2234
+ function unescapeCodepoint(value) {
2235
+ const replacement = {
2236
+ "\\9 ": " ",
2237
+ "\\a ": "\n",
2238
+ "\\d ": "\r"
2239
+ };
2240
+ return value.replace(
2241
+ /(\\[\u0039\u0061\u0064] )/g,
2242
+ (_, codepoint) => replacement[codepoint]
2243
+ );
2244
+ }
2245
+ function escapeSelectorComponent(text) {
2246
+ const codepoints = {
2247
+ " ": "\\9 ",
2248
+ "\n": "\\a ",
2249
+ "\r": "\\d "
2250
+ };
2251
+ return text.toString().replace(/([\t\n\r]|[^a-z0-9_-])/gi, (_, ch) => {
2252
+ if (codepoints[ch]) {
2253
+ return codepoints[ch];
2254
+ } else {
2255
+ return `\\${ch}`;
2256
+ }
2257
+ });
2258
+ }
2259
+ function generateIdSelector(id) {
2260
+ const escaped = escapeSelectorComponent(id);
2261
+ return escaped.match(/^\d/) ? `[id="${escaped}"]` : `#${escaped}`;
2195
2262
  }
2196
2263
  class Selector {
2197
2264
  pattern;
@@ -2208,6 +2275,13 @@ class Selector {
2208
2275
  const context = { scope: root };
2209
2276
  yield* this.matchInternal(root, 0, context);
2210
2277
  }
2278
+ /**
2279
+ * Returns `true` if the element matches this selector.
2280
+ */
2281
+ matchElement(element) {
2282
+ const context = { scope: null };
2283
+ return matchElement(element, this.pattern, context);
2284
+ }
2211
2285
  *matchInternal(root, level, context) {
2212
2286
  if (level >= this.pattern.length) {
2213
2287
  yield root;
@@ -2225,7 +2299,7 @@ class Selector {
2225
2299
  static parse(selector) {
2226
2300
  selector = selector.replace(/([+~>]) /g, "$1");
2227
2301
  return Array.from(splitSelectorElements(selector), (element) => {
2228
- return new Pattern(unescapeCodepoint(element));
2302
+ return new Compound(unescapeCodepoint(element));
2229
2303
  });
2230
2304
  }
2231
2305
  static findCandidates(root, pattern) {
@@ -2241,7 +2315,6 @@ class Selector {
2241
2315
  case Combinator.SCOPE:
2242
2316
  return [root];
2243
2317
  }
2244
- return [];
2245
2318
  }
2246
2319
  static findAdjacentSibling(node) {
2247
2320
  let adjacent = false;
@@ -2577,17 +2650,11 @@ class HtmlElement extends DOMNode {
2577
2650
  *
2578
2651
  * Implementation of DOM specification of Element.matches(selectors).
2579
2652
  */
2580
- matches(selector) {
2581
- let root = this;
2582
- while (root.parent) {
2583
- root = root.parent;
2584
- }
2585
- for (const match of root.querySelectorAll(selector)) {
2586
- if (match.unique === this.unique) {
2587
- return true;
2588
- }
2589
- }
2590
- return false;
2653
+ matches(selectorList) {
2654
+ return selectorList.split(",").some((it) => {
2655
+ const selector = new Selector(it.trim());
2656
+ return selector.matchElement(this);
2657
+ });
2591
2658
  }
2592
2659
  get meta() {
2593
2660
  return this.metaElement;
@@ -6635,7 +6702,7 @@ class HeadingLevel extends Rule {
6635
6702
  constructor(options) {
6636
6703
  super({ ...defaults$j, ...options });
6637
6704
  this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
6638
- this.sectionRoots = this.options.sectioningRoots.map((it) => new Pattern(it));
6705
+ this.sectionRoots = this.options.sectioningRoots.map((it) => new Compound(it));
6639
6706
  this.stack.push({
6640
6707
  node: null,
6641
6708
  current: 0,
@@ -11652,7 +11719,7 @@ class EventHandler {
11652
11719
  }
11653
11720
 
11654
11721
  const name = "html-validate";
11655
- const version = "9.4.0";
11722
+ const version = "9.4.2-rc.1";
11656
11723
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11657
11724
 
11658
11725
  function freeze(src) {