@markuplint/rules 2.4.2 → 3.0.0-alpha.66

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.
Files changed (92) hide show
  1. package/README.md +1 -5
  2. package/lib/attr-duplication/index.js +10 -7
  3. package/lib/attr-equal-space-after/index.d.ts +1 -1
  4. package/lib/attr-equal-space-before/index.d.ts +1 -1
  5. package/lib/attr-spacing/index.d.ts +3 -3
  6. package/lib/attr-value-quotes/index.js +21 -25
  7. package/lib/case-sensitive-attr-name/index.d.ts +1 -5
  8. package/lib/case-sensitive-attr-name/index.js +51 -81
  9. package/lib/case-sensitive-tag-name/index.js +38 -30
  10. package/lib/character-reference/index.d.ts +2 -1
  11. package/lib/character-reference/index.js +5 -7
  12. package/lib/class-naming/index.js +11 -11
  13. package/lib/deprecated-attr/index.js +17 -18
  14. package/lib/deprecated-element/index.js +5 -7
  15. package/lib/disallowed-element/index.js +8 -9
  16. package/lib/doctype/index.js +7 -7
  17. package/lib/end-tag/index.js +4 -1
  18. package/lib/helper/aria/get-aria.d.ts +7 -0
  19. package/lib/helper/aria/get-aria.js +53 -0
  20. package/lib/helper/aria/get-computed-role.d.ts +10 -0
  21. package/lib/helper/aria/get-computed-role.js +24 -0
  22. package/lib/helper/aria/get-implicit-role.d.ts +7 -0
  23. package/lib/helper/aria/get-implicit-role.js +12 -0
  24. package/lib/helper/aria/get-permitted-roles.d.ts +14 -0
  25. package/lib/helper/aria/get-permitted-roles.js +26 -0
  26. package/lib/helper/aria/resolve-version.d.ts +2 -0
  27. package/lib/helper/aria/resolve-version.js +21 -0
  28. package/lib/helper/spec/aria-spec.d.ts +5 -0
  29. package/lib/helper/spec/aria-spec.js +12 -0
  30. package/lib/helper/spec/get-role-spec.d.ts +11 -0
  31. package/lib/helper/spec/get-role-spec.js +39 -0
  32. package/lib/helper/spec/html-spec.d.ts +2 -0
  33. package/lib/helper/spec/html-spec.js +14 -0
  34. package/lib/helpers.d.ts +10 -28
  35. package/lib/helpers.js +29 -149
  36. package/lib/id-duplication/index.js +4 -6
  37. package/lib/indentation/index.d.ts +3 -3
  38. package/lib/index.d.ts +14 -19
  39. package/lib/index.js +0 -8
  40. package/lib/ineffective-attr/index.js +19 -27
  41. package/lib/invalid-attr/index.js +83 -83
  42. package/lib/landmark-roles/index.d.ts +2 -2
  43. package/lib/landmark-roles/index.js +9 -9
  44. package/lib/no-boolean-attr-value/index.js +33 -34
  45. package/lib/no-default-value/index.js +20 -24
  46. package/lib/no-hard-code-id/index.js +9 -13
  47. package/lib/no-refer-to-non-existent-id/index.d.ts +4 -1
  48. package/lib/no-refer-to-non-existent-id/index.js +77 -83
  49. package/lib/no-use-event-handler-attr/index.js +20 -22
  50. package/lib/permitted-contents/index.d.ts +5 -2
  51. package/lib/permitted-contents/index.js +67 -68
  52. package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +5 -5
  53. package/lib/permitted-contents/permitted-content.spec-to-regexp.js +19 -14
  54. package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +2 -2
  55. package/lib/require-accessible-name/index.d.ts +5 -1
  56. package/lib/require-accessible-name/index.js +6 -3
  57. package/lib/required-attr/index.js +16 -25
  58. package/lib/required-element/index.d.ts +1 -1
  59. package/lib/required-element/index.js +6 -6
  60. package/lib/required-h1/index.d.ts +2 -2
  61. package/lib/required-h1/index.js +3 -3
  62. package/lib/wai-aria/checkings/abstract-role.d.ts +3 -0
  63. package/lib/wai-aria/checkings/abstract-role.js +22 -0
  64. package/lib/wai-aria/checkings/checking-required-owned-elements.d.ts +11 -0
  65. package/lib/wai-aria/checkings/checking-required-owned-elements.js +63 -0
  66. package/lib/wai-aria/checkings/default-value.d.ts +6 -0
  67. package/lib/wai-aria/checkings/default-value.js +17 -0
  68. package/lib/wai-aria/checkings/deprecated-props.d.ts +7 -0
  69. package/lib/wai-aria/checkings/deprecated-props.js +18 -0
  70. package/lib/wai-aria/checkings/disallowed-prop.d.ts +7 -0
  71. package/lib/wai-aria/checkings/disallowed-prop.js +22 -0
  72. package/lib/wai-aria/checkings/implicit-props.d.ts +7 -0
  73. package/lib/wai-aria/checkings/implicit-props.js +50 -0
  74. package/lib/wai-aria/checkings/implicit-role.d.ts +3 -0
  75. package/lib/wai-aria/checkings/implicit-role.js +21 -0
  76. package/lib/wai-aria/checkings/no-global-prop.d.ts +6 -0
  77. package/lib/wai-aria/checkings/no-global-prop.js +14 -0
  78. package/lib/wai-aria/checkings/non-existant-role.d.ts +3 -0
  79. package/lib/wai-aria/checkings/non-existant-role.js +28 -0
  80. package/lib/wai-aria/checkings/permitted-roles.d.ts +3 -0
  81. package/lib/wai-aria/checkings/permitted-roles.js +28 -0
  82. package/lib/wai-aria/checkings/required-prop.d.ts +9 -0
  83. package/lib/wai-aria/checkings/required-prop.js +27 -0
  84. package/lib/wai-aria/checkings/value.d.ts +7 -0
  85. package/lib/wai-aria/checkings/value.js +21 -0
  86. package/lib/wai-aria/index.d.ts +1 -8
  87. package/lib/wai-aria/index.js +56 -207
  88. package/lib/wai-aria/types.d.ts +11 -0
  89. package/lib/wai-aria/types.js +2 -0
  90. package/package.json +5 -5
  91. package/schema.json +0 -12
  92. package/tsconfig.tsbuildinfo +1 -1
@@ -1,106 +1,100 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
- const helpers_1 = require("../helpers");
5
4
  exports.default = (0, ml_core_1.createRule)({
5
+ defaultOptions: {
6
+ ariaVersion: '1.2',
7
+ },
6
8
  async verify({ document, report, t }) {
7
- const { ariaAttrs } = (0, helpers_1.ariaSpec)(document.specs);
8
9
  const idList = new Set();
9
10
  let hasDynamicId = false;
10
- await document.walkOn('Element', el => {
11
- for (const attr of el.attributes) {
12
- if (attr.getName().potential.toLowerCase() !== 'id') {
13
- continue;
14
- }
15
- if (attr.attrType === 'html-attr') {
16
- if (attr.isDynamicValue) {
17
- hasDynamicId = true;
18
- }
19
- idList.add(attr.getValue().potential);
20
- }
21
- else {
22
- if (attr.valueType !== 'code') {
23
- idList.add(attr.getValue().potential);
24
- }
25
- }
11
+ await document.walkOn('Attr', attr => {
12
+ if (attr.name.toLowerCase() !== 'id') {
13
+ return;
14
+ }
15
+ if (attr.isDynamicValue) {
16
+ hasDynamicId = true;
17
+ }
18
+ if (attr.valueType !== 'code') {
19
+ idList.add(attr.value);
26
20
  }
27
21
  });
28
22
  if (hasDynamicId) {
29
23
  return;
30
24
  }
31
- document.walkOn('Element', el => {
32
- const attrSpec = (0, ml_core_1.getAttrSpecs)(el.nameWithNS, document.specs);
25
+ await document.walkOn('Attr', attr => {
26
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
27
+ const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
33
28
  if (!attrSpec) {
34
29
  return;
35
30
  }
36
- for (const attr of el.attributes) {
37
- if (attr.attrType !== 'html-attr' || attr.isDynamicValue) {
38
- continue;
31
+ if (attr.isDynamicValue) {
32
+ return;
33
+ }
34
+ const name = attr.name;
35
+ if (name.toLowerCase() === 'id') {
36
+ return;
37
+ }
38
+ const value = attr.value;
39
+ const spec = attrSpec.find(s => s.name === name);
40
+ if (spec) {
41
+ // DOMID and DOMID List do not become in the array type.
42
+ if (Array.isArray(spec.type)) {
43
+ return;
39
44
  }
40
- const name = attr.getName().potential;
41
- if (name.toLowerCase() === 'id') {
42
- continue;
45
+ if (spec.type === 'DOMID' && !idList.has(value)) {
46
+ report({
47
+ scope: attr,
48
+ line: (_a = attr.valueNode) === null || _a === void 0 ? void 0 : _a.startLine,
49
+ col: (_b = attr.valueNode) === null || _b === void 0 ? void 0 : _b.startCol,
50
+ raw: (_c = attr.valueNode) === null || _c === void 0 ? void 0 : _c.raw,
51
+ message: t('Missing {0}', t('"{0*}" ID', value)),
52
+ });
43
53
  }
44
- const value = attr.getValue().potential;
45
- const spec = attrSpec.find(s => s.name === name);
46
- if (spec) {
47
- // DOMID and DOMID List do not become in the array type.
48
- if (Array.isArray(spec.type)) {
49
- continue;
50
- }
51
- if (spec.type === 'DOMID' && !idList.has(value)) {
52
- report({
53
- scope: el,
54
- line: attr.valueNode.startLine,
55
- col: attr.valueNode.startCol,
56
- raw: attr.valueNode.raw,
57
- message: t('Missing {0}', t('"{0*}" ID', value)),
58
- });
59
- }
60
- if (typeof spec.type !== 'string' && 'token' in spec.type && spec.type.token === 'DOMID') {
61
- const refs = value
62
- .split(spec.type.separator === 'space' ? /\s/ : ',')
63
- .map(id => id.trim())
64
- .filter(_ => _);
65
- for (const ref of refs) {
66
- if (!idList.has(ref)) {
67
- report({
68
- scope: el,
69
- line: attr.valueNode.startLine,
70
- col: attr.valueNode.startCol,
71
- raw: attr.valueNode.raw,
72
- message: t('Missing {0}', t('"{0*}" ID', ref)),
73
- });
74
- }
54
+ if (typeof spec.type !== 'string' && 'token' in spec.type && spec.type.token === 'DOMID') {
55
+ const refs = value
56
+ .split(spec.type.separator === 'space' ? /\s/ : ',')
57
+ .map(id => id.trim())
58
+ .filter(_ => _);
59
+ for (const ref of refs) {
60
+ if (!idList.has(ref)) {
61
+ report({
62
+ scope: attr,
63
+ line: (_d = attr.valueNode) === null || _d === void 0 ? void 0 : _d.startLine,
64
+ col: (_e = attr.valueNode) === null || _e === void 0 ? void 0 : _e.startCol,
65
+ raw: (_f = attr.valueNode) === null || _f === void 0 ? void 0 : _f.raw,
66
+ message: t('Missing {0}', t('"{0*}" ID', ref)),
67
+ });
75
68
  }
76
69
  }
77
70
  }
78
- const aria = ariaAttrs.find(aria => aria.name === name);
79
- if (aria) {
80
- if (aria.value === 'ID reference' && !idList.has(value)) {
81
- report({
82
- scope: el,
83
- line: attr.valueNode.startLine,
84
- col: attr.valueNode.startCol,
85
- raw: attr.valueNode.raw,
86
- message: t('Missing {0}', t('"{0*}" ID', value)),
87
- });
88
- }
89
- else if (aria.value === 'ID reference list') {
90
- const refs = value
91
- .split(/\s/)
92
- .map(id => id.trim())
93
- .filter(_ => _);
94
- for (const ref of refs) {
95
- if (!idList.has(ref)) {
96
- report({
97
- scope: el,
98
- line: attr.valueNode.startLine,
99
- col: attr.valueNode.startCol,
100
- raw: attr.valueNode.raw,
101
- message: t('Missing {0}', t('"{0*}" ID', ref)),
102
- });
103
- }
71
+ }
72
+ const { props } = (0, ml_core_1.ariaSpecs)(document.specs, attr.rule.option.ariaVersion);
73
+ const aria = props.find(prop => prop.name === name);
74
+ if (aria) {
75
+ if (aria.value === 'ID reference' && !idList.has(value)) {
76
+ report({
77
+ scope: attr,
78
+ line: (_g = attr.valueNode) === null || _g === void 0 ? void 0 : _g.startLine,
79
+ col: (_h = attr.valueNode) === null || _h === void 0 ? void 0 : _h.startCol,
80
+ raw: (_j = attr.valueNode) === null || _j === void 0 ? void 0 : _j.raw,
81
+ message: t('Missing {0}', t('"{0*}" ID', value)),
82
+ });
83
+ }
84
+ else if (aria.value === 'ID reference list') {
85
+ const refs = value
86
+ .split(/\s/)
87
+ .map(id => id.trim())
88
+ .filter(_ => _);
89
+ for (const ref of refs) {
90
+ if (!idList.has(ref)) {
91
+ report({
92
+ scope: attr,
93
+ line: (_k = attr.valueNode) === null || _k === void 0 ? void 0 : _k.startLine,
94
+ col: (_l = attr.valueNode) === null || _l === void 0 ? void 0 : _l.startCol,
95
+ raw: (_m = attr.valueNode) === null || _m === void 0 ? void 0 : _m.raw,
96
+ message: t('Missing {0}', t('"{0*}" ID', ref)),
97
+ });
104
98
  }
105
99
  }
106
100
  }
@@ -6,32 +6,30 @@ exports.default = (0, ml_core_1.createRule)({
6
6
  defaultServerity: 'warning',
7
7
  defaultOptions: {},
8
8
  async verify({ document, report, t }) {
9
- await document.walkOn('Element', el => {
10
- if (el.isCustomElement) {
9
+ await document.walkOn('Attr', attr => {
10
+ if (attr.ownerElement.isCustomElement) {
11
11
  return;
12
12
  }
13
- const ignoreList = Array.isArray(el.rule.option.ignore)
14
- ? el.rule.option.ignore
15
- : el.rule.option.ignore
16
- ? [el.rule.option.ignore]
13
+ const ignoreList = Array.isArray(attr.rule.option.ignore)
14
+ ? attr.rule.option.ignore
15
+ : attr.rule.option.ignore
16
+ ? [attr.rule.option.ignore]
17
17
  : [];
18
- el.attributes.forEach(attr => {
19
- const name = attr.getName().potential;
20
- for (const ignore of ignoreList) {
21
- if ((0, helpers_1.match)(name, ignore)) {
22
- return;
23
- }
18
+ const name = attr.name;
19
+ for (const ignore of ignoreList) {
20
+ if ((0, helpers_1.match)(name, ignore)) {
21
+ return;
24
22
  }
25
- if (/^on/i.test(name)) {
26
- report({
27
- scope: el,
28
- raw: attr.raw,
29
- line: attr.startLine,
30
- col: attr.startCol,
31
- message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
32
- });
33
- }
34
- });
23
+ }
24
+ if (/^on/i.test(name)) {
25
+ report({
26
+ scope: attr,
27
+ raw: attr.raw,
28
+ line: attr.startLine,
29
+ col: attr.startCol,
30
+ message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
31
+ });
32
+ }
35
33
  });
36
34
  },
37
35
  });
@@ -1,6 +1,9 @@
1
- import type { PermittedStructuresSchema } from '@markuplint/ml-spec';
1
+ import type { ContentModel } from '@markuplint/ml-spec';
2
+ declare type TagRule = ContentModel & {
3
+ tag: string;
4
+ };
2
5
  declare type Options = {
3
6
  ignoreHasMutableChildren: boolean;
4
7
  };
5
- declare const _default: import("@markuplint/ml-core").RuleSeed<PermittedStructuresSchema[], Options>;
8
+ declare const _default: import("@markuplint/ml-core").RuleSeed<TagRule[], Options>;
6
9
  export default _default;
@@ -2,9 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const ml_core_1 = require("@markuplint/ml-core");
5
- const helpers_1 = require("../helpers");
5
+ const ml_spec_1 = require("@markuplint/ml-spec");
6
6
  const permitted_content_spec_to_regexp_1 = tslib_1.__importDefault(require("./permitted-content.spec-to-regexp"));
7
- const unfold_content_models_to_tags_1 = tslib_1.__importDefault(require("./unfold-content-models-to-tags"));
8
7
  const expMapOnNodeId = new Map();
9
8
  exports.default = (0, ml_core_1.createRule)({
10
9
  defaultValue: [],
@@ -13,51 +12,50 @@ exports.default = (0, ml_core_1.createRule)({
13
12
  },
14
13
  async verify({ document, report, t }) {
15
14
  let idCounter = 0;
16
- await document.walkOn('Element', node => {
15
+ await document.walkOn('Element', el => {
17
16
  var _a;
18
- if (!node.rule.value) {
17
+ if (!el.rule.value) {
19
18
  return;
20
19
  }
21
- if (node.rule.option.ignoreHasMutableChildren && node.hasMutableChildren()) {
20
+ if (el.rule.option.ignoreHasMutableChildren && el.hasMutableChildren()) {
22
21
  return;
23
22
  }
24
- const specType = node.ns === 'html' ? 'HTML' : node.ns === 'svg' ? 'SVG' : 'Any Language';
25
- const childNodes = node.getChildElementsAndTextNodeWithoutWhitespaces();
26
- const spec = !node.isCustomElement && ((_a = (0, helpers_1.htmlSpec)(document.specs, node.nameWithNS)) === null || _a === void 0 ? void 0 : _a.permittedStructures);
27
- const expGen = new permitted_content_spec_to_regexp_1.default(idCounter++);
23
+ const specType = el.namespaceURI === 'http://www.w3.org/1999/xhtml'
24
+ ? 'HTML'
25
+ : el.namespaceURI === 'http://www.w3.org/2000/svg'
26
+ ? 'SVG'
27
+ : 'Any Language';
28
+ const childNodes = el.getChildElementsAndTextNodeWithoutWhitespaces();
29
+ const spec = !el.isCustomElement && ((_a = (0, ml_core_1.getSpec)(el, document.specs)) === null || _a === void 0 ? void 0 : _a.contentModel);
30
+ const expGen = new permitted_content_spec_to_regexp_1.default(document.specs, idCounter++);
28
31
  if (spec) {
29
- if (spec.ancestor && !node.closest(spec.ancestor)) {
32
+ if (spec.descendantOf && !el.closest(spec.descendantOf)) {
30
33
  report({
31
- scope: node,
32
- message: t('{0} must be {1}', t('the "{0*}" {1}', node.nodeName, 'element'), t('{0} of {1}', 'descendant', t('the "{0*}" {1}', spec.ancestor, 'element'))),
34
+ scope: el,
35
+ message: t('{0} must be {1}', t('the "{0*}" {1}', el.localName, 'element'), t('{0} of {1}', 'descendant', t('the "{0*}" {1}', spec.descendantOf, 'element'))),
33
36
  });
34
37
  return;
35
38
  }
36
39
  let matched = false;
37
40
  if (spec.conditional) {
38
41
  for (const conditional of spec.conditional) {
39
- matched =
40
- ('hasAttr' in conditional.condition && node.hasAttribute(conditional.condition.hasAttr)) ||
41
- ('parent' in conditional.condition &&
42
- !!node.parentNode &&
43
- node.parentNode.type === 'Element' &&
44
- node.parentNode.matches(conditional.condition.parent));
42
+ matched = el.matches(conditional.condition);
45
43
  // console.log({ ...conditional, matched });
46
44
  if (matched) {
47
45
  try {
48
- const parentExp = getRegExpFromParentNode(document.specs, node, expGen);
49
- const exp = expGen.specToRegExp(conditional.contents, parentExp, node.ns);
50
- const conditionalResult = match(exp, childNodes, node.ns, false);
46
+ const parentExp = getRegExpFromParentNode(document.specs, el, expGen);
47
+ const exp = expGen.specToRegExp(conditional.contents, parentExp, el.namespaceURI);
48
+ const conditionalResult = match(exp, childNodes, false, document.specs);
51
49
  if (!conditionalResult) {
52
- const message = t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'content'), t('the "{0*}" {1}', node.nodeName, 'element')), 'invalid');
50
+ const message = t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'content'), t('the "{0*}" {1}', el.localName, 'element')), 'invalid');
53
51
  report({
54
- scope: node,
52
+ scope: el,
55
53
  message: specType !== 'Any Language'
56
54
  ? t('{0} according to {1}', message, `the ${specType} specification`)
57
55
  : message,
58
- line: node.startLine,
59
- col: node.startCol,
60
- raw: node.raw,
56
+ line: el.startLine,
57
+ col: el.startCol,
58
+ raw: el.raw,
61
59
  });
62
60
  break;
63
61
  }
@@ -65,7 +63,7 @@ exports.default = (0, ml_core_1.createRule)({
65
63
  catch (e) {
66
64
  if (e instanceof Error) {
67
65
  // eslint-disable-next-line no-console
68
- console.warn(node.raw, 'conditional', conditional, e.message);
66
+ console.warn(el.raw, 'conditional', conditional, e.message);
69
67
  }
70
68
  else {
71
69
  throw e;
@@ -76,12 +74,12 @@ exports.default = (0, ml_core_1.createRule)({
76
74
  }
77
75
  if (!matched) {
78
76
  try {
79
- const exp = getRegExpFromNode(document.specs, node, expGen);
80
- const specResult = match(exp, childNodes, node.ns, false);
77
+ const exp = getRegExpFromNode(document.specs, el, expGen);
78
+ const specResult = match(exp, childNodes, false, document.specs);
81
79
  if (!specResult) {
82
- const message = t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'content'), t('the "{0*}" {1}', node.nodeName, 'element')), 'invalid');
80
+ const message = t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'content'), t('the "{0*}" {1}', el.localName, 'element')), 'invalid');
83
81
  report({
84
- scope: node,
82
+ scope: el,
85
83
  message: specType !== 'Any Language'
86
84
  ? t('{0} according to {1}', message, `the ${specType} specification`)
87
85
  : message,
@@ -91,7 +89,7 @@ exports.default = (0, ml_core_1.createRule)({
91
89
  catch (e) {
92
90
  if (e instanceof Error) {
93
91
  // eslint-disable-next-line no-console
94
- console.warn(node.raw, 'HTML Spec', e.message);
92
+ console.warn(el.raw, 'HTML Spec', e.message);
95
93
  }
96
94
  else {
97
95
  throw e;
@@ -99,22 +97,22 @@ exports.default = (0, ml_core_1.createRule)({
99
97
  }
100
98
  }
101
99
  }
102
- for (const rule of node.rule.value) {
103
- if (rule.tag.toLowerCase() !== node.nodeName.toLowerCase()) {
100
+ for (const rule of el.rule.value) {
101
+ if (rule.tag.toLowerCase() !== el.localName.toLowerCase()) {
104
102
  continue;
105
103
  }
106
- const parentExp = getRegExpFromParentNode(document.specs, node, expGen);
104
+ const parentExp = getRegExpFromParentNode(document.specs, el, expGen);
107
105
  try {
108
- const exp = expGen.specToRegExp(rule.contents, parentExp, node.ns);
106
+ const exp = expGen.specToRegExp(rule.contents, parentExp, el.namespaceURI);
109
107
  // Evaluate the custom element if the optional schema.
110
- const r = match(exp, childNodes, node.ns, node.isCustomElement);
108
+ const r = match(exp, childNodes, el.isCustomElement, document.specs);
111
109
  if (!r) {
112
110
  report({
113
- scope: node,
114
- message: t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'content'), t('the "{0*}" {1}', node.nodeName, 'element')), 'invalid'),
115
- line: node.startLine,
116
- col: node.startCol,
117
- raw: node.raw,
111
+ scope: el,
112
+ message: t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'content'), t('the "{0*}" {1}', el.localName, 'element')), 'invalid'),
113
+ line: el.startLine,
114
+ col: el.startCol,
115
+ raw: el.raw,
118
116
  });
119
117
  return;
120
118
  }
@@ -122,7 +120,7 @@ exports.default = (0, ml_core_1.createRule)({
122
120
  catch (e) {
123
121
  if (e instanceof Error) {
124
122
  // eslint-disable-next-line no-console
125
- console.warn(node.raw, 'rule', rule, e.message);
123
+ console.warn(el.raw, 'rule', rule, e.message);
126
124
  }
127
125
  else {
128
126
  throw e;
@@ -133,53 +131,54 @@ exports.default = (0, ml_core_1.createRule)({
133
131
  expMapOnNodeId.clear();
134
132
  },
135
133
  });
136
- function normalization(nodes, ownNS, evalCustomElement) {
137
- return nodes
134
+ function normalization(el, evalCustomElement) {
135
+ return el
138
136
  .map(node => {
139
137
  // FIXME: https://github.com/markuplint/markuplint/issues/388
140
- if (!evalCustomElement && node.type === 'Element' && node.isCustomElement) {
138
+ if (!evalCustomElement && node.is(node.ELEMENT_NODE) && node.isCustomElement) {
141
139
  return '';
142
140
  }
143
- if (node.type !== 'Element') {
141
+ if (!node.is(node.ELEMENT_NODE)) {
144
142
  return '<#text>';
145
143
  }
146
- ownNS = ownNS || 'html';
147
- const name = node.nameWithNS.replace(new RegExp(`^${ownNS}:`), '');
148
- return `<${name}>`;
144
+ const { localNameWithNS } = (0, ml_core_1.resolveNamespace)(node.localName, node.namespaceURI);
145
+ return `<${localNameWithNS}>`;
149
146
  })
150
147
  .join('');
151
148
  }
152
- function getRegExpFromNode(specs, node, expGen) {
149
+ function getRegExpFromNode(specs, el, expGen) {
153
150
  var _a;
154
151
  // console.log({ n: node.nodeName });
155
- if (expMapOnNodeId.has(node.uuid)) {
156
- return expMapOnNodeId.get(node.uuid);
152
+ if (expMapOnNodeId.has(el.uuid)) {
153
+ return expMapOnNodeId.get(el.uuid);
157
154
  }
158
- const parentExp = node.parentNode ? getRegExpFromNode(specs, node.parentNode, expGen) : null;
159
- const spec = !node.isCustomElement && ((_a = (0, helpers_1.htmlSpec)(specs, node.nameWithNS || node.nodeName.toLowerCase())) === null || _a === void 0 ? void 0 : _a.permittedStructures);
155
+ const parentExp = el.parentNode ? getRegExpFromNode(specs, el.parentNode, expGen) : null;
156
+ const spec = el.nodeType === el.ELEMENT_NODE && !el.isCustomElement && ((_a = (0, ml_core_1.getSpec)(el, specs)) === null || _a === void 0 ? void 0 : _a.contentModel);
160
157
  const contentRule = spec ? spec.contents : true;
161
- const exp = expGen.specToRegExp(contentRule, parentExp, node.ns || null);
162
- expMapOnNodeId.set(node.uuid, exp);
158
+ const exp = expGen.specToRegExp(contentRule, parentExp, el.nodeType === el.ELEMENT_NODE ? el.namespaceURI : undefined);
159
+ expMapOnNodeId.set(el.uuid, exp);
163
160
  return exp;
164
161
  }
165
- function getRegExpFromParentNode(specs, node, expGen) {
162
+ function getRegExpFromParentNode(specs, el, expGen) {
166
163
  // console.log({ p: node.nodeName });
167
- const parentExp = node.parentNode ? getRegExpFromNode(specs, node.parentNode, expGen) : null;
164
+ const parentExp = el.parentNode ? getRegExpFromNode(specs, el.parentNode, expGen) : null;
168
165
  return parentExp;
169
166
  }
170
167
  const matchingCacheMap = new Map();
171
- function match(exp, childNodes, ownNS, evalCustomElement) {
172
- const target = normalization(childNodes, ownNS, evalCustomElement);
173
- const cacheKey = target + exp.source + childNodes.map(n => (n.type == 'Element' ? n.toNormalizeString() : n.originRaw)).join('');
168
+ function match(exp, childNodes, evalCustomElement, specs) {
169
+ const target = normalization(childNodes, evalCustomElement);
170
+ const cacheKey = target +
171
+ exp.source +
172
+ childNodes.map(n => (n.is(n.ELEMENT_NODE) ? n.toNormalizeString() : n.originRaw)).join('');
174
173
  const res = matchingCacheMap.get(cacheKey);
175
174
  if (res != null) {
176
175
  return res;
177
176
  }
178
- const matched = _match(target, exp, childNodes);
177
+ const matched = _match(target, exp, childNodes, specs);
179
178
  matchingCacheMap.set(cacheKey, matched);
180
179
  return matched;
181
180
  }
182
- function _match(target, exp, childNodes) {
181
+ function _match(target, exp, childNodes, specs) {
183
182
  const result = exp.exec(target);
184
183
  if (!result) {
185
184
  return false;
@@ -200,12 +199,12 @@ function _match(target, exp, childNodes) {
200
199
  switch (type) {
201
200
  case 'ACM': {
202
201
  const [model, tag] = _selector;
203
- const selectors = (0, unfold_content_models_to_tags_1.default)(`#${model}`).filter(selector => {
202
+ const selectors = (0, ml_spec_1.contentModelCategoryToTagNames)(`#${model}`, specs).filter(selector => {
204
203
  const [, tagName] = /^([^[\]]+)(?:\[[^\]]+\])?$/.exec(selector) || [];
205
204
  return tagName.toLowerCase() === tag.toLowerCase();
206
205
  });
207
206
  for (const node of childNodes) {
208
- if (node.type === 'Text') {
207
+ if (node.is(node.TEXT_NODE)) {
209
208
  continue;
210
209
  }
211
210
  if (node.nodeName.toLowerCase() !== tag.toLowerCase()) {
@@ -233,7 +232,7 @@ function _match(target, exp, childNodes) {
233
232
  : null;
234
233
  _selector.forEach(content => {
235
234
  if (content[0] === '_') {
236
- (0, unfold_content_models_to_tags_1.default)(content.replace('_', '#')).forEach(tag => contents.add(tag));
235
+ (0, ml_spec_1.contentModelCategoryToTagNames)(content.replace('_', '#'), specs).forEach(tag => contents.add(tag));
237
236
  return;
238
237
  }
239
238
  contents.add(content);
@@ -251,7 +250,7 @@ function _match(target, exp, childNodes) {
251
250
  // });
252
251
  for (const node of childNodes) {
253
252
  for (const target of targetsMaybeIncludesNotAllowedDescendants) {
254
- if (node.type === 'Text') {
253
+ if (node.is(node.TEXT_NODE)) {
255
254
  if (selectors.includes('#text')) {
256
255
  return false;
257
256
  }
@@ -1,9 +1,9 @@
1
- import type { PermittedContent } from '@markuplint/ml-spec';
1
+ import type { NamespaceURI } from '@markuplint/ml-ast';
2
+ import type { MLMLSpec, PermittedContent } from '@markuplint/ml-spec';
2
3
  export default class ExpGenerator {
3
- private _id;
4
- private _idCounter;
5
- constructor(_id: number);
6
- specToRegExp(contentRule: PermittedContent[] | boolean, parentExp?: RegExp | null, ownNS?: string | null): RegExp;
4
+ #private;
5
+ constructor(specs: MLMLSpec, id: number);
6
+ specToRegExp(contentRule: PermittedContent[] | boolean, parentExp?: RegExp | null, ownNS?: NamespaceURI): RegExp;
7
7
  private _toPattern;
8
8
  private _interleavePattern;
9
9
  private _targetTags;
@@ -1,20 +1,23 @@
1
1
  "use strict";
2
- var _TagList_list;
2
+ var _ExpGenerator_id, _ExpGenerator_specs, _ExpGenerator_idCounter, _TagList_list;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const tslib_1 = require("tslib");
5
+ const ml_spec_1 = require("@markuplint/ml-spec");
5
6
  const helpers_1 = require("../helpers");
6
7
  const array_combination_1 = tslib_1.__importDefault(require("./array.combination"));
7
- const unfold_content_models_to_tags_1 = tslib_1.__importDefault(require("./unfold-content-models-to-tags"));
8
8
  const ALL = '(?:<[^>]+>)?';
9
9
  const ___TRANSPARENT___ = '___TRANSPARENT___';
10
10
  const ___InTRANSPARENT = '___InTRANSPARENT';
11
11
  const CUSTOM_ELEMENT = `(?:<[a-z](?:${helpers_1.rePCENChar})*\\-(?:${helpers_1.rePCENChar})*>)`;
12
12
  class ExpGenerator {
13
- constructor(_id) {
14
- this._id = _id;
15
- this._idCounter = 0;
13
+ constructor(specs, id) {
14
+ _ExpGenerator_id.set(this, void 0);
15
+ _ExpGenerator_specs.set(this, void 0);
16
+ _ExpGenerator_idCounter.set(this, 0);
17
+ tslib_1.__classPrivateFieldSet(this, _ExpGenerator_id, id, "f");
18
+ tslib_1.__classPrivateFieldSet(this, _ExpGenerator_specs, specs, "f");
16
19
  }
17
- specToRegExp(contentRule, parentExp = null, ownNS = null) {
20
+ specToRegExp(contentRule, parentExp = null, ownNS = 'http://www.w3.org/1999/xhtml') {
18
21
  if (contentRule === true) {
19
22
  return new RegExp(`^(?:${ALL})+$`);
20
23
  }
@@ -22,10 +25,11 @@ class ExpGenerator {
22
25
  return new RegExp('^$');
23
26
  }
24
27
  const parentPattern = parentExp ? parentExp.source.replace(/^\^|\$$/g, '') : ALL;
25
- const pattern = this._toPattern(contentRule, null, ownNS, 1, 1).replace(___TRANSPARENT___, () => `(?<TRANSPARENT_${this._id}${this._idCounter++}>${parentPattern})`);
28
+ const pattern = this._toPattern(contentRule, null, ownNS, 1, 1).replace(___TRANSPARENT___, () => { var _a, _b; return `(?<TRANSPARENT_${tslib_1.__classPrivateFieldGet(this, _ExpGenerator_id, "f")}${tslib_1.__classPrivateFieldSet(this, _ExpGenerator_idCounter, (_b = tslib_1.__classPrivateFieldGet(this, _ExpGenerator_idCounter, "f"), _a = _b++, _b), "f"), _a}>${parentPattern})`; });
26
29
  return new RegExp(`^${pattern}$`, 'i');
27
30
  }
28
31
  _toPattern(contentRule, ignore, ownNS, min, max) {
32
+ var _a, _b;
29
33
  if (isTarget(contentRule)) {
30
34
  return this._targetTags(contentRule, ignore, ownNS, min, max);
31
35
  }
@@ -87,7 +91,7 @@ class ExpGenerator {
87
91
  }
88
92
  const range = createRange(min, max);
89
93
  const c = notAllowedDescendantsNamedCapture
90
- ? `?<NAD_${this._id}${this._idCounter++}_${notAllowedDescendantsNamedCapture}>`
94
+ ? `?<NAD_${tslib_1.__classPrivateFieldGet(this, _ExpGenerator_id, "f")}${tslib_1.__classPrivateFieldSet(this, _ExpGenerator_idCounter, (_b = tslib_1.__classPrivateFieldGet(this, _ExpGenerator_idCounter, "f"), _a = _b++, _b), "f"), _a}_${notAllowedDescendantsNamedCapture}>`
91
95
  : '?:';
92
96
  if (1 === exp.length && range === '') {
93
97
  if (notAllowedDescendantsNamedCapture) {
@@ -117,6 +121,7 @@ class ExpGenerator {
117
121
  return join(Array.from(tagList), createRange(min, max));
118
122
  }
119
123
  _resolveTags(target, ownNS) {
124
+ var _a, _b;
120
125
  const list = Array.isArray(target) ? target : [target];
121
126
  const tagList = new TagList();
122
127
  for (const name of list) {
@@ -131,8 +136,8 @@ class ExpGenerator {
131
136
  break;
132
137
  }
133
138
  default: {
134
- const selectors = (0, unfold_content_models_to_tags_1.default)(name);
135
- const counter = this._idCounter++;
139
+ const selectors = (0, ml_spec_1.contentModelCategoryToTagNames)(name, tslib_1.__classPrivateFieldGet(this, _ExpGenerator_specs, "f"));
140
+ const counter = (tslib_1.__classPrivateFieldSet(this, _ExpGenerator_idCounter, (_b = tslib_1.__classPrivateFieldGet(this, _ExpGenerator_idCounter, "f"), _a = _b++, _b), "f"), _a);
136
141
  selectors.forEach(selector => {
137
142
  if (selector === '#custom') {
138
143
  tagList.addPattern(CUSTOM_ELEMENT);
@@ -141,7 +146,7 @@ class ExpGenerator {
141
146
  if (/]$/i.test(selector)) {
142
147
  const [, tagName] = /^([^[\]]+)\[[^\]]+\]$/.exec(selector) || [];
143
148
  // ACM = Attributes by content model
144
- const exp = `(?<ACM_${this._id}${counter}_${name.slice(1)}_${tagName}><${tagName}>)`;
149
+ const exp = `(?<ACM_${tslib_1.__classPrivateFieldGet(this, _ExpGenerator_id, "f")}${counter}_${name.slice(1)}_${tagName}><${tagName}>)`;
145
150
  tagList.addPattern(exp);
146
151
  return;
147
152
  }
@@ -157,6 +162,7 @@ class ExpGenerator {
157
162
  }
158
163
  }
159
164
  exports.default = ExpGenerator;
165
+ _ExpGenerator_id = new WeakMap(), _ExpGenerator_specs = new WeakMap(), _ExpGenerator_idCounter = new WeakMap();
160
166
  class TagList {
161
167
  constructor() {
162
168
  _TagList_list.set(this, new Set());
@@ -165,9 +171,8 @@ class TagList {
165
171
  tslib_1.__classPrivateFieldGet(this, _TagList_list, "f").add(pattern);
166
172
  }
167
173
  addTag(tagNameOrSelector, ownNS) {
168
- if (ownNS) {
169
- tagNameOrSelector = tagNameOrSelector.replace(new RegExp(`^${ownNS}:`, 'i'), '');
170
- }
174
+ tagNameOrSelector = tagNameOrSelector.replace(/\|/g, ':');
175
+ tagNameOrSelector = tagNameOrSelector.replace(/^html:/i, '');
171
176
  tslib_1.__classPrivateFieldGet(this, _TagList_list, "f").add(`<${tagNameOrSelector}>`);
172
177
  }
173
178
  result() {