@markuplint/rules 4.0.0-alpha.2 → 4.0.0-dev.28

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/lib/attr-check.js CHANGED
@@ -71,10 +71,10 @@ export function attrCheck(t, name, value, isCustomRule, spec) {
71
71
  };
72
72
  }
73
73
  });
74
- if (invalidList.some(i => i === false)) {
74
+ if (invalidList.includes(false)) {
75
75
  return false;
76
76
  }
77
- const invalid = invalidList.find(i => i);
77
+ const invalid = invalidList.find(Boolean);
78
78
  return invalid ?? false;
79
79
  }
80
80
  export function valueCheck(t, name, value, type) {
@@ -1,11 +1,11 @@
1
1
  import { createRule, getLocationFromChars } from '@markuplint/ml-core';
2
2
  const defaultChars = ['"', '&', '<', '>'];
3
- const ignoreParentElement = ['script', 'style'];
3
+ const ignoreParentElement = new Set(['script', 'style']);
4
4
  export default createRule({
5
5
  async verify({ document, report, t }) {
6
6
  const targetNodes = [];
7
7
  await document.walkOn('Text', node => {
8
- if (node.parentNode && ignoreParentElement.includes(node.parentNode.nodeName.toLowerCase())) {
8
+ if (node.parentNode && ignoreParentElement.has(node.parentNode.nodeName.toLowerCase())) {
9
9
  return;
10
10
  }
11
11
  const severity = node.rule.severity;
@@ -41,14 +41,14 @@ export default createRule({
41
41
  if (!('scope' in targetNode && 'line' in targetNode && targetNode.line != null)) {
42
42
  continue;
43
43
  }
44
- const escapedText = targetNode.raw.replace(/&(?:[a-z]+|#[0-9]+|#x[0-9a-f]+);/gi, $0 => '*'.repeat($0.length));
45
- getLocationFromChars(defaultChars, escapedText, targetNode.line, targetNode.col).forEach(location => {
44
+ const escapedText = targetNode.raw.replaceAll(/&(?:[a-z]+|#\d+|#x[\da-f]+);/gi, $0 => '*'.repeat($0.length));
45
+ for (const location of getLocationFromChars(defaultChars, escapedText, targetNode.line, targetNode.col)) {
46
46
  report({
47
47
  scope: targetNode.scope,
48
48
  message: targetNode.message,
49
49
  ...location,
50
50
  });
51
- });
51
+ }
52
52
  }
53
53
  },
54
54
  });
@@ -16,7 +16,7 @@ export default createRule({
16
16
  const classList = attr.value
17
17
  .split(/\s+/g)
18
18
  .map(c => c.trim())
19
- .filter(c => c);
19
+ .filter(Boolean);
20
20
  for (const className of classList) {
21
21
  if (!classPatterns.some(pattern => match(className, pattern))) {
22
22
  report({
@@ -13,7 +13,7 @@ export function createMessageValueExpected(t, baseTarget, type, matches) {
13
13
  }
14
14
  const expected = createExpectedObject(tokenType, matches, t);
15
15
  const message = [listDescriptionPart, __createMessageValueExpected(t, target, expected, matches)]
16
- .filter(s => s)
16
+ .filter(Boolean)
17
17
  .join(t('. '));
18
18
  return message;
19
19
  }
@@ -136,11 +136,11 @@ export function __createMessageValueExpected(t, baseTarget, expected, matches) {
136
136
  if (lte != null && gte === lte) {
137
137
  expectedDigits = t('{0} digits', gte);
138
138
  }
139
- else if (lte != null) {
140
- expectedDigits = t('{0} to {1} digits', gte, lte);
139
+ else if (lte == null) {
140
+ expectedDigits = t('{0} or more digits', gte);
141
141
  }
142
142
  else {
143
- expectedDigits = t('{0} or more digits', gte);
143
+ expectedDigits = t('{0} to {1} digits', gte, lte);
144
144
  }
145
145
  if (!expected) {
146
146
  expected = expectedDigits;
@@ -191,7 +191,9 @@ export function __createMessageValueExpected(t, baseTarget, expected, matches) {
191
191
  if (matches.fallbackTo) {
192
192
  fallbackToPart = t('The user agent will automatically use "{0*}" instead', matches.fallbackTo);
193
193
  }
194
- let message = [reasonPart, unnecessaryPart, expectPart, candidatePart, fallbackToPart].filter(s => s).join(t('. '));
194
+ let message = [reasonPart, unnecessaryPart, expectPart, candidatePart, fallbackToPart]
195
+ .filter(Boolean)
196
+ .join(t('. '));
195
197
  if (matches.ref) {
196
198
  message += ` (${matches.ref})`;
197
199
  }
@@ -224,19 +226,24 @@ function createExpectedObject(type, matches, t) {
224
226
  }
225
227
  function expectValueToWord(t, expect, type) {
226
228
  switch (expect.type) {
227
- case 'common':
229
+ case 'common': {
228
230
  return expect.value;
229
- case 'const':
231
+ }
232
+ case 'const': {
230
233
  return expect.value ? `%${expect.value}%` : '';
231
- case 'format':
234
+ }
235
+ case 'format': {
232
236
  return t('the {0} format', expect.value);
233
- case 'regexp':
237
+ }
238
+ case 'regexp': {
234
239
  return t('{0} ({1})', 'regular expression', expect.value);
235
- case 'syntax':
240
+ }
241
+ case 'syntax': {
236
242
  if (isKeyword(type) && type[0] === '<') {
237
243
  return t('the CSS Syntax "{0}"', expect.value);
238
244
  }
239
245
  return t('{0} syntax', expect.value);
246
+ }
240
247
  }
241
248
  }
242
249
  function createExpectedNumber(t, type) {
@@ -9,7 +9,7 @@ export default createRule({
9
9
  }
10
10
  const spec = getSpec(el, document.specs.specs);
11
11
  if (spec && (spec.obsolete != null || spec.deprecated || spec.nonStandard)) {
12
- const message = t('{0} is {1:c}', t('the "{0*}" {1}', el.localName, 'element'), spec.deprecated ? 'deprecated' : spec.obsolete != null ? 'obsolete' : 'non-standard');
12
+ const message = t('{0} is {1:c}', t('the "{0*}" {1}', el.localName, 'element'), spec.deprecated ? 'deprecated' : spec.obsolete == null ? 'non-standard' : 'obsolete');
13
13
  report({
14
14
  scope: el,
15
15
  message,
@@ -4,13 +4,13 @@ export default createRule({
4
4
  async verify({ document, report, t }) {
5
5
  for (const query of document.rule.value) {
6
6
  const elements = document.querySelectorAll(query);
7
- elements.forEach(el => {
7
+ for (const el of elements) {
8
8
  const message = t('{0} is disallowed', t('the "{0*}" {1}', query, 'element'));
9
9
  report({
10
10
  scope: el,
11
11
  message,
12
12
  });
13
- });
13
+ }
14
14
  }
15
15
  await document.walkOn('Element', el => {
16
16
  if (el.rule.value === document.rule.value) {
@@ -18,13 +18,13 @@ export default createRule({
18
18
  }
19
19
  for (const query of el.rule.value) {
20
20
  const elements = el.querySelectorAll(query);
21
- elements.forEach(el => {
21
+ for (const el of elements) {
22
22
  const message = t('{0} is disallowed', t('the "{0*}" {1}', query, 'element'));
23
23
  report({
24
24
  scope: el,
25
25
  message,
26
26
  });
27
- });
27
+ }
28
28
  }
29
29
  });
30
30
  },
package/lib/helpers.js CHANGED
@@ -1,5 +1,9 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
1
6
  var _Collection_items;
2
- import { __classPrivateFieldGet } from "tslib";
3
7
  // @ts-ignore
4
8
  import structuredClone from '@ungap/structured-clone';
5
9
  import { attrCheck } from './attr-check.js';
@@ -13,7 +17,7 @@ node, condition) {
13
17
  return node.matches(condSelector);
14
18
  }
15
19
  export function match(needle, pattern) {
16
- const matches = pattern.match(/^\/(.*)\/(i|g|m)*$/);
20
+ const matches = pattern.match(/^\/(.*)\/([gim])*$/);
17
21
  if (matches && matches[1]) {
18
22
  const re = matches[1];
19
23
  const flag = matches[2];
@@ -87,7 +91,7 @@ export function toNormalizedValue(value, spec) {
87
91
  }
88
92
  if (typeof spec.type === 'string') {
89
93
  if (spec.type[0] === '<') {
90
- normalized = normalized.toLowerCase().trim().replace(/\s+/g, ' ');
94
+ normalized = normalized.toLowerCase().trim().replaceAll(/\s+/g, ' ');
91
95
  }
92
96
  }
93
97
  else {
@@ -99,10 +103,10 @@ export function toNormalizedValue(value, spec) {
99
103
  normalized = normalized.trim();
100
104
  }
101
105
  if (spec.type.separator === 'space') {
102
- normalized = normalized.replace(/\s+/g, ' ');
106
+ normalized = normalized.replaceAll(/\s+/g, ' ');
103
107
  }
104
108
  if (spec.type.separator === 'comma') {
105
- normalized = normalized.replace(/\s*,\s*/g, ',');
109
+ normalized = normalized.replaceAll(/\s*,\s*/g, ',');
106
110
  }
107
111
  }
108
112
  }
@@ -157,7 +161,7 @@ export class Collection {
157
161
  }
158
162
  }
159
163
  toArray() {
160
- return Object.freeze(Array.from(__classPrivateFieldGet(this, _Collection_items, "f")));
164
+ return Object.freeze([...__classPrivateFieldGet(this, _Collection_items, "f")]);
161
165
  }
162
166
  }
163
167
  export function deepCopy(value) {
package/lib/index.d.ts CHANGED
@@ -72,7 +72,7 @@ declare const rules: {
72
72
  }>>;
73
73
  readonly 'no-hard-code-id': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
74
74
  readonly 'no-refer-to-non-existent-id': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
75
- ariaVersion: "1.1" | "1.2" | "1.3";
75
+ ariaVersion: "1.2" | "1.1" | "1.3";
76
76
  fragmentRefersNameAttr: boolean;
77
77
  }>>;
78
78
  readonly 'no-use-event-handler-attr': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
@@ -81,7 +81,7 @@ declare const rules: {
81
81
  readonly 'permitted-contents': Readonly<import("@markuplint/ml-core").RuleSeed<import("./permitted-contents/types.js").TagRule[], import("./permitted-contents/types.js").Options>>;
82
82
  readonly 'placeholder-label-option': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
83
83
  readonly 'require-accessible-name': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
84
- ariaVersion: "1.1" | "1.2" | "1.3";
84
+ ariaVersion: "1.2" | "1.1" | "1.3";
85
85
  }>>;
86
86
  readonly 'require-datetime': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
87
87
  langs?: import("./require-datetime/types.js").Lang[] | undefined;
@@ -20,13 +20,13 @@ export default createRule({
20
20
  return;
21
21
  }
22
22
  const roles = {
23
- complementary: Array.from(document.querySelectorAll(selectors.complementary.join(','))),
24
- contentinfo: Array.from(document.querySelectorAll(selectors.contentinfo.join(','))),
25
- form: Array.from(document.querySelectorAll(selectors.form.join(','))),
26
- banner: Array.from(document.querySelectorAll(selectors.banner.join(','))),
27
- main: Array.from(document.querySelectorAll(selectors.main.join(','))),
28
- navigation: Array.from(document.querySelectorAll(selectors.navigation.join(','))),
29
- region: Array.from(document.querySelectorAll(selectors.region.join(','))),
23
+ complementary: [...document.querySelectorAll(selectors.complementary.join(','))],
24
+ contentinfo: [...document.querySelectorAll(selectors.contentinfo.join(','))],
25
+ form: [...document.querySelectorAll(selectors.form.join(','))],
26
+ banner: [...document.querySelectorAll(selectors.banner.join(','))],
27
+ main: [...document.querySelectorAll(selectors.main.join(','))],
28
+ navigation: [...document.querySelectorAll(selectors.navigation.join(','))],
29
+ region: [...document.querySelectorAll(selectors.region.join(','))],
30
30
  };
31
31
  /**
32
32
  * `<header>`
@@ -40,7 +40,7 @@ export default createRule({
40
40
  * > - nav
41
41
  * > - section
42
42
  */
43
- const headers = Array.from(document.querySelectorAll('header')).filter(header => {
43
+ const headers = [...document.querySelectorAll('header')].filter(header => {
44
44
  return !header.closest('article, aside, main, nav, section');
45
45
  });
46
46
  roles.banner.push(...headers);
@@ -56,7 +56,7 @@ export default createRule({
56
56
  * > - nav
57
57
  * > - section
58
58
  */
59
- const footers = Array.from(document.querySelectorAll('footer')).filter(footer => {
59
+ const footers = [...document.querySelectorAll('footer')].filter(footer => {
60
60
  return !footer.closest('article, aside, main, nav, section');
61
61
  });
62
62
  roles.contentinfo.push(...footers);
@@ -106,9 +106,7 @@ export default createRule({
106
106
  function landmarkRoleElementUUIDList(
107
107
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
108
108
  roleset) {
109
- return Object.values(roleset)
110
- .map(elements => elements.map(element => element.uuid))
111
- .flat();
109
+ return Object.values(roleset).flatMap(elements => elements.map(element => element.uuid));
112
110
  }
113
111
  function hasLabel(
114
112
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
@@ -28,7 +28,7 @@ export default createRule({
28
28
  if (el.rule.options.ignoreIfAriaBusy && el.getAttribute('aria-busy') === 'true') {
29
29
  return;
30
30
  }
31
- const isEmpty = Array.from(el.childNodes).every(node => node.is(node.TEXT_NODE) && node.isWhitespace());
31
+ const isEmpty = [...el.childNodes].every(node => node.is(node.TEXT_NODE) && node.isWhitespace());
32
32
  if (isEmpty) {
33
33
  report({
34
34
  scope: el,
@@ -1,5 +1,5 @@
1
1
  declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
2
- ariaVersion: "1.1" | "1.2" | "1.3";
2
+ ariaVersion: "1.2" | "1.1" | "1.3";
3
3
  fragmentRefersNameAttr: boolean;
4
4
  }>>;
5
5
  export default _default;
@@ -16,10 +16,10 @@ export default createRule({
16
16
  if (isMutable) {
17
17
  return;
18
18
  }
19
- document.querySelectorAll('[id]').forEach(el => {
19
+ for (const el of document.querySelectorAll('[id]')) {
20
20
  const attr = el.getAttributeNode('id');
21
21
  if (!attr) {
22
- return;
22
+ continue;
23
23
  }
24
24
  if (attr.isDynamicValue) {
25
25
  hasDynamicId = true;
@@ -27,14 +27,14 @@ export default createRule({
27
27
  if (attr.valueType !== 'code') {
28
28
  idList.add(decodeEntities(attr.value));
29
29
  }
30
- });
30
+ }
31
31
  if (hasDynamicId) {
32
32
  return;
33
33
  }
34
- document.querySelectorAll('[name]').forEach(el => {
34
+ for (const el of document.querySelectorAll('[name]')) {
35
35
  const attr = el.getAttributeNode('name');
36
36
  if (!attr) {
37
- return;
37
+ continue;
38
38
  }
39
39
  if (attr.isDynamicValue) {
40
40
  hasDynamicName = true;
@@ -42,7 +42,7 @@ export default createRule({
42
42
  if (attr.valueType !== 'code') {
43
43
  nameList.add(decodeEntities(attr.value));
44
44
  }
45
- });
45
+ }
46
46
  await document.walkOn('Attr', attr => {
47
47
  const attrSpec = getAttrSpecs(attr.ownerElement, document.specs);
48
48
  if (!attrSpec) {
@@ -75,7 +75,7 @@ export default createRule({
75
75
  const refs = value
76
76
  .split(spec.type.separator === 'space' ? /\s/ : ',')
77
77
  .map(id => id.trim())
78
- .filter(_ => _);
78
+ .filter(Boolean);
79
79
  for (const ref of refs) {
80
80
  if (!idList.has(ref)) {
81
81
  report({
@@ -105,7 +105,7 @@ export default createRule({
105
105
  const refs = value
106
106
  .split(/\s/)
107
107
  .map(id => id.trim())
108
- .filter(_ => _);
108
+ .filter(Boolean);
109
109
  for (const ref of refs) {
110
110
  if (!idList.has(ref)) {
111
111
  report({
@@ -14,7 +14,7 @@ elements, specs, options, depth) {
14
14
  const result = order(some, collection.unmatched, specs, options, depth + 1);
15
15
  if (result.type === 'MATCHED' ||
16
16
  result.type === 'MATCHED_ZERO' ||
17
- (result.type === 'UNEXPECTED_EXTRA_NODE' && result.matched.length >= 1)) {
17
+ (result.type === 'UNEXPECTED_EXTRA_NODE' && result.matched.length > 0)) {
18
18
  choiceLog('Results[%s]: %s', i, choiceLogString(pattern.choice, i));
19
19
  return {
20
20
  type: result.type,
@@ -41,9 +41,9 @@ nodes, specs, options, depth) {
41
41
  if (!barelyMatchedResult) {
42
42
  throw new Error('Unreachable code');
43
43
  }
44
- orderLog('Result (%s): %s%s', result.type, collection.toString(true), barelyMatchedResult.hint.missing?.barelyMatchedElements != null
45
- ? `; But ${barelyMatchedResult.hint.missing.barelyMatchedElements} elements hit out of pattern`
46
- : '');
44
+ orderLog('Result (%s): %s%s', result.type, collection.toString(true), barelyMatchedResult.hint.missing?.barelyMatchedElements == null
45
+ ? ''
46
+ : `; But ${barelyMatchedResult.hint.missing.barelyMatchedElements} elements hit out of pattern`);
47
47
  return {
48
48
  type: barelyMatchedResult.type,
49
49
  matched: collection.matched,
@@ -30,7 +30,7 @@ nodes, specs, options) {
30
30
  const collection = new Collection(getChildNodesWithoutWhitespaces(node));
31
31
  let unmatched;
32
32
  if (noTransparentModels.length > 0) {
33
- const result = order(noTransparentModels, collection.unmatched, specs, options, Infinity);
33
+ const result = order(noTransparentModels, collection.unmatched, specs, options, Number.POSITIVE_INFINITY);
34
34
  unmatched = result.unmatched;
35
35
  }
36
36
  else {
@@ -7,7 +7,7 @@ nodes) {
7
7
  transparentLog('Skipped');
8
8
  return {
9
9
  type: nodes.length === 0 ? 'MATCHED_ZERO' : 'MATCHED',
10
- matched: nodes.slice(),
10
+ matched: [...nodes],
11
11
  unmatched: [],
12
12
  zeroMatch: nodes.length === 0,
13
13
  query: 'transparent',
@@ -17,7 +17,7 @@ nodes) {
17
17
  transparentLog('Transparent model element is component root');
18
18
  return {
19
19
  type: 'MATCHED',
20
- matched: nodes.slice(),
20
+ matched: [...nodes],
21
21
  unmatched: [],
22
22
  zeroMatch: false,
23
23
  query: 'transparent',
@@ -1,5 +1,15 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
1
12
  var _Collection_locked, _Collection_matched, _Collection_nodes, _Collection_origin;
2
- import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
13
  import { createSelector } from '@markuplint/selector';
4
14
  import { bgGreen, green, bgRed, bgBlue, blue, bgMagenta, cyan } from './debug.js';
5
15
  import { transparentMode } from './represent-transparent-nodes.js';
@@ -11,7 +21,7 @@ el) {
11
21
  if (nodes) {
12
22
  return nodes;
13
23
  }
14
- nodes = Array.from(el.childNodes).filter(node => {
24
+ nodes = [...el.childNodes].filter(node => {
15
25
  return !(node.is(node.TEXT_NODE) && node.isWhitespace());
16
26
  });
17
27
  getChildNodesWithoutWhitespacesCaches.set(el, nodes);
@@ -44,10 +54,8 @@ node, specs) {
44
54
  };
45
55
  }
46
56
  const not = selectorResult
47
- .map(r => (r.matched ? [] : r.not ?? []))
48
- .flat()
49
- .map(descendants)
50
- .flat()
57
+ .flatMap(r => (r.matched ? [] : r.not ?? []))
58
+ .flatMap(descendants)
51
59
  .shift();
52
60
  return {
53
61
  matched: false,
@@ -57,7 +65,7 @@ node, specs) {
57
65
  function descendants(
58
66
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
59
67
  selectorResult) {
60
- let nodes = selectorResult.nodes.slice();
68
+ let nodes = [...selectorResult.nodes];
61
69
  while (selectorResult.has.length > 0) {
62
70
  for (const dep of selectorResult.has) {
63
71
  if (dep.has.length === 0) {
@@ -109,13 +117,13 @@ export function normalizeModel(pattern) {
109
117
  else if (isOneOrMore(pattern)) {
110
118
  model = pattern.oneOrMore;
111
119
  min = 1;
112
- max = Math.max(pattern.max ?? Infinity, 1);
120
+ max = Math.max(pattern.max ?? Number.POSITIVE_INFINITY, 1);
113
121
  missingType = 'MISSING_NODE_ONE_OR_MORE';
114
122
  }
115
123
  else if (isZeroOrMore(pattern)) {
116
124
  model = pattern.zeroOrMore;
117
125
  min = 0;
118
- max = Math.max(pattern.max ?? Infinity, 1);
126
+ max = Math.max(pattern.max ?? Number.POSITIVE_INFINITY, 1);
119
127
  }
120
128
  else {
121
129
  throw new Error('Unreachable code');
@@ -157,11 +165,11 @@ b) {
157
165
  }
158
166
  export function cleanObject(object) {
159
167
  const newObject = {};
160
- Object.entries(object).forEach(([key, value]) => {
168
+ for (const [key, value] of Object.entries(object)) {
161
169
  if (value !== undefined) {
162
170
  newObject[key] = value;
163
171
  }
164
- });
172
+ }
165
173
  return newObject;
166
174
  }
167
175
  export class Collection {
@@ -172,20 +180,20 @@ export class Collection {
172
180
  _Collection_matched.set(this, new Set());
173
181
  _Collection_nodes.set(this, void 0);
174
182
  _Collection_origin.set(this, void 0);
175
- __classPrivateFieldSet(this, _Collection_origin, origin.slice(), "f");
183
+ __classPrivateFieldSet(this, _Collection_origin, [...origin], "f");
176
184
  __classPrivateFieldSet(this, _Collection_nodes, new Set(__classPrivateFieldGet(this, _Collection_origin, "f")), "f");
177
185
  }
178
186
  get matched() {
179
- return Array.from(__classPrivateFieldGet(this, _Collection_matched, "f"));
187
+ return [...__classPrivateFieldGet(this, _Collection_matched, "f")];
180
188
  }
181
189
  get matchedCount() {
182
190
  return __classPrivateFieldGet(this, _Collection_matched, "f").size;
183
191
  }
184
192
  get nodes() {
185
- return __classPrivateFieldGet(this, _Collection_origin, "f").slice();
193
+ return [...__classPrivateFieldGet(this, _Collection_origin, "f")];
186
194
  }
187
195
  get unmatched() {
188
- return Array.from(__classPrivateFieldGet(this, _Collection_nodes, "f")).filter(n => !__classPrivateFieldGet(this, _Collection_matched, "f").has(n));
196
+ return [...__classPrivateFieldGet(this, _Collection_nodes, "f")].filter(n => !__classPrivateFieldGet(this, _Collection_matched, "f").has(n));
189
197
  }
190
198
  addMatched(
191
199
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
@@ -206,13 +214,14 @@ export class Collection {
206
214
  __classPrivateFieldSet(this, _Collection_locked, new Set(__classPrivateFieldGet(this, _Collection_matched, "f")), "f");
207
215
  }
208
216
  max(max) {
209
- const sliced = Array.from(__classPrivateFieldGet(this, _Collection_matched, "f")).slice(max);
210
- sliced.forEach(n => __classPrivateFieldGet(this, _Collection_matched, "f").delete(n));
217
+ const sliced = [...__classPrivateFieldGet(this, _Collection_matched, "f")].slice(max);
218
+ for (const n of sliced)
219
+ __classPrivateFieldGet(this, _Collection_matched, "f").delete(n);
211
220
  }
212
221
  toString(highlightExtraNodes = false) {
213
222
  const out = [];
214
223
  for (const n of __classPrivateFieldGet(this, _Collection_origin, "f")) {
215
- const raw = n.is(n.TEXT_NODE) ? `:text(${n.raw.replace(/\n/g, '\\n')})` : n.raw;
224
+ const raw = n.is(n.TEXT_NODE) ? `:text(${n.raw.replaceAll('\n', '\\n')})` : n.raw;
216
225
  if (__classPrivateFieldGet(this, _Collection_locked, "f").has(n)) {
217
226
  if (transparentMode.has(n)) {
218
227
  out.push(bgBlue.bold(raw));
@@ -1,18 +1,18 @@
1
1
  import { createRule } from '@markuplint/ml-core';
2
2
  export default createRule({
3
3
  verify({ document, report, t }) {
4
- document.querySelectorAll('select').forEach(select => {
4
+ for (const select of document.querySelectorAll('select')) {
5
5
  if (hasPlaceholderLabelOption(select)) {
6
- return;
6
+ continue;
7
7
  }
8
8
  if (!needPlaceholderLabelOption(select)) {
9
- return;
9
+ continue;
10
10
  }
11
11
  report({
12
12
  scope: select,
13
13
  message: t('need {0}', t('the {0}', 'placeholder label option')),
14
14
  });
15
- });
15
+ }
16
16
  },
17
17
  });
18
18
  /**
@@ -6,14 +6,14 @@ export default createRule({
6
6
  langs: undefined,
7
7
  },
8
8
  verify({ document, report, t }) {
9
- document.querySelectorAll('time:not([datetime])').forEach(time => {
9
+ for (const time of document.querySelectorAll('time:not([datetime])')) {
10
10
  if (time.hasMutableChildren()) {
11
- return;
11
+ continue;
12
12
  }
13
13
  const content = time.textContent.trim();
14
14
  const result = check(content, 'DateTime');
15
15
  if (result.matched) {
16
- return;
16
+ continue;
17
17
  }
18
18
  const candidate = getCandidateDatetimeString(content, time.rule.options.langs);
19
19
  if (candidate) {
@@ -21,12 +21,12 @@ export default createRule({
21
21
  scope: time,
22
22
  message: t('need {0*}', `datetime="${candidate}"`),
23
23
  });
24
- return;
24
+ continue;
25
25
  }
26
26
  report({
27
27
  scope: time,
28
28
  message: t('need {0}', t('the "{0*}" {1}', 'datetime', 'attribute')),
29
29
  });
30
- });
30
+ }
31
31
  },
32
32
  });
@@ -94,7 +94,7 @@ function parseTryMultipleLangs(content, langs, base) {
94
94
  for (const lang of langs) {
95
95
  const results = chrono[lang].casual.parse(content, base);
96
96
  // Is not multiple datetime contents
97
- if (results.length < 1) {
97
+ if (results.length === 0) {
98
98
  continue;
99
99
  }
100
100
  const result = results[0];
@@ -28,7 +28,7 @@ export default createRule({
28
28
  return;
29
29
  }
30
30
  for (const query of el.rule.value) {
31
- const exists = Array.from(el.children).find(child => child.matches(query));
31
+ const exists = [...el.children].find(child => child.matches(query));
32
32
  if (!exists) {
33
33
  const message = t('Require {0}', t('the "{0*}" {1}', query, 'element'));
34
34
  report({
@@ -76,7 +76,7 @@ export default createRule({
76
76
  },
77
77
  });
78
78
  function isMayListItem(text, bullets, spaceNeededBullets) {
79
- const textArray = Array.from(text);
79
+ const textArray = [...text];
80
80
  const firstLetter = textArray[0] ?? '';
81
81
  const isBullet = bullets.includes(firstLetter);
82
82
  const needSpace = spaceNeededBullets.includes(firstLetter);
@@ -34,13 +34,13 @@ export const checkingImplicitProps = ({ attr, propSpecs, attrSpecs }) => t => {
34
34
  message: t('{0} contradicts {1}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec.type}`), t('the current "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute')),
35
35
  };
36
36
  }
37
- else if (value === 'true') {
38
- if (!equivalentHtmlAttr.isNotStrictEquivalent && htmlAttrSpec?.type === 'Boolean') {
39
- return {
40
- scope: attr,
41
- message: t('{0} contradicts {1}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec.type}`), t('the implicit "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute')),
42
- };
43
- }
37
+ else if (value === 'true' &&
38
+ !equivalentHtmlAttr.isNotStrictEquivalent &&
39
+ htmlAttrSpec?.type === 'Boolean') {
40
+ return {
41
+ scope: attr,
42
+ message: t('{0} contradicts {1}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec.type}`), t('the implicit "{0}" {1}', equivalentHtmlAttr.htmlAttrName, 'attribute')),
43
+ };
44
44
  }
45
45
  }
46
46
  };
@@ -33,7 +33,7 @@ export const checkingPresentationalChildren = ({ el }) => t => {
33
33
  if (!ancestor.role) {
34
34
  return;
35
35
  }
36
- const hasAriaAttr = Array.from(el.attributes).some(attr => /^aria-|^role$/i.test(attr.name));
36
+ const hasAriaAttr = [...el.attributes].some(attr => /^aria-|^role$/i.test(attr.name));
37
37
  if (!hasAriaAttr) {
38
38
  return;
39
39
  }
@@ -25,7 +25,7 @@ export const checkingRequiredOwnedElements = ({ el, role }) => t => {
25
25
  return;
26
26
  }
27
27
  // TODO: Needs to resolve `aria-own`
28
- const children = Array.from(el.childNodes).map(child => {
28
+ const children = [...el.childNodes].map(child => {
29
29
  if (child.is(child.ELEMENT_NODE)) {
30
30
  if (child.matches('[aria-busy="true" i]')) {
31
31
  return [child, 'BUSY'];
@@ -93,7 +93,7 @@ el) {
93
93
  if (el.isEmpty()) {
94
94
  return true;
95
95
  }
96
- return Array.from(el.children).every(child => {
96
+ return [...el.children].every(child => {
97
97
  return ['script', 'template'].includes(child.localName);
98
98
  });
99
99
  }
@@ -76,10 +76,10 @@ export function checkAriaValue(type, value, tokenEnum, booleanish) {
76
76
  return ['true', 'false', 'undefined'].includes(value);
77
77
  }
78
78
  case 'integer': {
79
- return parseInt(value).toString() === value;
79
+ return Number.parseInt(value).toString() === value;
80
80
  }
81
81
  case 'number': {
82
- return parseFloat(value).toString() === value;
82
+ return Number.parseFloat(value).toString() === value;
83
83
  }
84
84
  }
85
85
  // For skipping checking
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/rules",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.0.0-dev.28+0131de5e",
4
4
  "description": "Built-in rules of markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
@@ -25,19 +25,18 @@
25
25
  "./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
26
26
  },
27
27
  "dependencies": {
28
- "@markuplint/html-spec": "4.0.0-alpha.2",
29
- "@markuplint/ml-core": "4.0.0-alpha.2",
30
- "@markuplint/ml-spec": "4.0.0-alpha.2",
31
- "@markuplint/selector": "4.0.0-alpha.2",
32
- "@markuplint/shared": "4.0.0-alpha.2",
33
- "@markuplint/types": "4.0.0-alpha.2",
34
- "@types/debug": "^4.1.9",
28
+ "@markuplint/html-spec": "4.0.0-dev.28+0131de5e",
29
+ "@markuplint/ml-core": "4.0.0-dev.28+0131de5e",
30
+ "@markuplint/ml-spec": "4.0.0-dev.28+0131de5e",
31
+ "@markuplint/selector": "4.0.0-dev.28+0131de5e",
32
+ "@markuplint/shared": "4.0.0-dev.28+0131de5e",
33
+ "@markuplint/types": "4.0.0-dev.28+0131de5e",
34
+ "@types/debug": "^4.1.10",
35
35
  "@ungap/structured-clone": "^1.2.0",
36
36
  "ansi-colors": "^4.1.3",
37
37
  "chrono-node": "^2.7.0",
38
38
  "debug": "^4.3.4",
39
- "tslib": "^2.6.2",
40
- "type-fest": "^4.3.1"
39
+ "type-fest": "^4.5.0"
41
40
  },
42
- "gitHead": "51ad52c760435641f9bff8685707d8178b0787eb"
41
+ "gitHead": "0131de5ea9dd6d3fd5472d7b414b66644c758881"
43
42
  }