@markuplint/rules 3.12.0 → 4.0.0-alpha.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.
Files changed (142) hide show
  1. package/lib/attr-check.js +14 -19
  2. package/lib/attr-duplication/index.js +3 -6
  3. package/lib/attr-value-quotes/index.js +5 -9
  4. package/lib/case-sensitive-attr-name/index.js +9 -13
  5. package/lib/case-sensitive-tag-name/index.js +2 -4
  6. package/lib/character-reference/index.js +6 -8
  7. package/lib/class-naming/index.js +9 -11
  8. package/lib/create-message.js +9 -16
  9. package/lib/debug.js +2 -6
  10. package/lib/deprecated-attr/index.js +6 -9
  11. package/lib/deprecated-element/index.js +3 -5
  12. package/lib/disallowed-element/index.js +2 -4
  13. package/lib/doctype/index.js +2 -4
  14. package/lib/end-tag/index.js +5 -8
  15. package/lib/helpers.d.ts +1 -1
  16. package/lib/helpers.js +17 -28
  17. package/lib/id-duplication/index.js +2 -4
  18. package/lib/index.d.ts +15 -15
  19. package/lib/index.js +63 -66
  20. package/lib/ineffective-attr/index.js +5 -7
  21. package/lib/invalid-attr/index.js +30 -33
  22. package/lib/label-has-control/index.js +2 -4
  23. package/lib/landmark-roles/index.js +3 -6
  24. package/lib/no-boolean-attr-value/index.js +6 -9
  25. package/lib/no-default-value/index.js +9 -12
  26. package/lib/no-empty-palpable-content/index.js +5 -7
  27. package/lib/no-hard-code-id/index.js +2 -4
  28. package/lib/no-refer-to-non-existent-id/index.js +26 -30
  29. package/lib/no-use-event-handler-attr/index.js +4 -6
  30. package/lib/permitted-contents/choice.d.ts +1 -1
  31. package/lib/permitted-contents/choice.js +13 -18
  32. package/lib/permitted-contents/complex-branch.d.ts +1 -1
  33. package/lib/permitted-contents/complex-branch.js +10 -14
  34. package/lib/permitted-contents/content-model.d.ts +1 -1
  35. package/lib/permitted-contents/content-model.js +5 -9
  36. package/lib/permitted-contents/count-pattern.d.ts +1 -1
  37. package/lib/permitted-contents/count-pattern.js +19 -24
  38. package/lib/permitted-contents/debug.browser.js +9 -12
  39. package/lib/permitted-contents/debug.d.ts +8 -1
  40. package/lib/permitted-contents/debug.js +12 -13
  41. package/lib/permitted-contents/index.d.ts +1 -1
  42. package/lib/permitted-contents/index.js +10 -13
  43. package/lib/permitted-contents/matches-selector.d.ts +1 -1
  44. package/lib/permitted-contents/matches-selector.js +12 -17
  45. package/lib/permitted-contents/order.d.ts +1 -1
  46. package/lib/permitted-contents/order.js +17 -22
  47. package/lib/permitted-contents/recursive-branch.d.ts +2 -2
  48. package/lib/permitted-contents/recursive-branch.js +9 -13
  49. package/lib/permitted-contents/represent-transparent-nodes.d.ts +1 -1
  50. package/lib/permitted-contents/represent-transparent-nodes.js +15 -20
  51. package/lib/permitted-contents/start.d.ts +1 -1
  52. package/lib/permitted-contents/start.js +13 -21
  53. package/lib/permitted-contents/transparent.d.ts +1 -1
  54. package/lib/permitted-contents/transparent.js +4 -9
  55. package/lib/permitted-contents/types.js +1 -2
  56. package/lib/permitted-contents/utils.d.ts +1 -1
  57. package/lib/permitted-contents/utils.js +55 -74
  58. package/lib/placeholder-label-option/index.js +5 -9
  59. package/lib/require-accessible-name/index.js +10 -13
  60. package/lib/require-datetime/index.d.ts +1 -1
  61. package/lib/require-datetime/index.js +6 -8
  62. package/lib/require-datetime/types.js +1 -2
  63. package/lib/require-datetime/utils.d.ts +1 -1
  64. package/lib/require-datetime/utils.js +4 -11
  65. package/lib/required-attr/index.js +8 -11
  66. package/lib/required-element/index.js +3 -6
  67. package/lib/required-h1/index.js +3 -6
  68. package/lib/use-list/index.js +6 -10
  69. package/lib/wai-aria/checkings/abstract-role.d.ts +1 -1
  70. package/lib/wai-aria/checkings/abstract-role.js +5 -10
  71. package/lib/wai-aria/checkings/default-value.d.ts +1 -1
  72. package/lib/wai-aria/checkings/default-value.js +2 -6
  73. package/lib/wai-aria/checkings/deprecated-props.d.ts +1 -1
  74. package/lib/wai-aria/checkings/deprecated-props.js +3 -8
  75. package/lib/wai-aria/checkings/disallowed-prop.d.ts +1 -1
  76. package/lib/wai-aria/checkings/disallowed-prop.js +7 -12
  77. package/lib/wai-aria/checkings/implicit-props.d.ts +1 -1
  78. package/lib/wai-aria/checkings/implicit-props.js +6 -11
  79. package/lib/wai-aria/checkings/implicit-role.d.ts +1 -1
  80. package/lib/wai-aria/checkings/implicit-role.js +4 -9
  81. package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +1 -1
  82. package/lib/wai-aria/checkings/interaction-in-hidden.js +4 -8
  83. package/lib/wai-aria/checkings/no-global-prop.d.ts +1 -1
  84. package/lib/wai-aria/checkings/no-global-prop.js +2 -7
  85. package/lib/wai-aria/checkings/non-existent-role.d.ts +1 -1
  86. package/lib/wai-aria/checkings/non-existent-role.js +4 -9
  87. package/lib/wai-aria/checkings/permitted-roles.d.ts +1 -1
  88. package/lib/wai-aria/checkings/permitted-roles.js +4 -9
  89. package/lib/wai-aria/checkings/presentational-children.d.ts +1 -1
  90. package/lib/wai-aria/checkings/presentational-children.js +4 -9
  91. package/lib/wai-aria/checkings/required-owned-elements.d.ts +1 -1
  92. package/lib/wai-aria/checkings/required-owned-elements.js +4 -8
  93. package/lib/wai-aria/checkings/required-prop.d.ts +1 -1
  94. package/lib/wai-aria/checkings/required-prop.js +2 -7
  95. package/lib/wai-aria/checkings/value.d.ts +1 -1
  96. package/lib/wai-aria/checkings/value.js +4 -10
  97. package/lib/wai-aria/index.d.ts +1 -1
  98. package/lib/wai-aria/index.js +38 -40
  99. package/lib/wai-aria/types.js +1 -2
  100. package/package.json +17 -12
  101. package/test/attr-check.spec.js +0 -77
  102. package/test/attr-duplication/index.spec.js +0 -159
  103. package/test/attr-value-quotes/index.spec.js +0 -133
  104. package/test/case-sensitive-attr-name/index.spec.js +0 -65
  105. package/test/case-sensitive-tag-name/index.spec.js +0 -80
  106. package/test/character-reference/index.spec.js +0 -72
  107. package/test/class-naming/index.spec.js +0 -470
  108. package/test/create-message.spec.js +0 -497
  109. package/test/deprecated-attr/index.spec.js +0 -48
  110. package/test/deprecated-element/index.spec.js +0 -35
  111. package/test/disallowed-element/index.spec.js +0 -90
  112. package/test/doctype/index.spec.js +0 -50
  113. package/test/end-tag/index.spec.js +0 -162
  114. package/test/id-duplication/index.spec.js +0 -47
  115. package/test/ineffective-attr/index.spec.js +0 -31
  116. package/test/invalid-attr/index.spec.js +0 -1641
  117. package/test/label-has-control/index.spec.js +0 -29
  118. package/test/landmark-roles/index.spec.js +0 -187
  119. package/test/no-boolean-attr-value/index.spec.js +0 -41
  120. package/test/no-default-value/index.spec.js +0 -74
  121. package/test/no-empty-palpable-content/index.spec.js +0 -115
  122. package/test/no-hard-code-id/index.spec.js +0 -100
  123. package/test/no-refer-to-non-existent-id/index.spec.js +0 -254
  124. package/test/no-use-event-handler-attr/index.spec.js +0 -57
  125. package/test/permitted-contents/choice.spec.js +0 -174
  126. package/test/permitted-contents/count-pattern.spec.js +0 -308
  127. package/test/permitted-contents/index.spec.js +0 -1395
  128. package/test/permitted-contents/matches-selector.spec.js +0 -59
  129. package/test/permitted-contents/order.spec.js +0 -351
  130. package/test/permitted-contents/recursive-branch.spec.js +0 -41
  131. package/test/permitted-contents/represent-transparent-nodes.spec.js +0 -24
  132. package/test/permitted-contents/start.spec.js +0 -67
  133. package/test/placeholder-label-option/index.spec.js +0 -113
  134. package/test/require-accessible-name/index.spec.js +0 -444
  135. package/test/require-datetime/index.spec.js +0 -54
  136. package/test/require-datetime/utils.spec.js +0 -52
  137. package/test/required-attr/index.spec.js +0 -414
  138. package/test/required-element/index.spec.js +0 -188
  139. package/test/required-h1/index.spec.js +0 -69
  140. package/test/use-list/index.spec.js +0 -109
  141. package/test/wai-aria/checkings/value.spec.js +0 -33
  142. package/test/wai-aria/index.spec.js +0 -1203
@@ -1,59 +0,0 @@
1
- const specs = require('@markuplint/html-spec');
2
- const { createTestElement } = require('@markuplint/ml-core');
3
-
4
- const { matchesSelector } = require('../../lib/permitted-contents/matches-selector');
5
-
6
- function c(model, innerHtml, tp) {
7
- const el = createTestElement(`<div>${innerHtml}</div>`, { specs });
8
- const child = Array.from(el.childNodes)[0];
9
- if (tp) {
10
- // @ts-ignore
11
- child.__transparentModel = {
12
- el,
13
- additionalCondition: tp,
14
- };
15
- }
16
- return matchesSelector(model, child, specs, { ignoreHasMutableChildren: true }, 0);
17
- }
18
-
19
- it('a', () => {
20
- expect(c('a', '<a></a>').type).toBe('MATCHED');
21
- expect(c('a', '<b></b>').type).toBe('UNMATCHED_SELECTORS');
22
- expect(c('a', '<c></c>').type).toBe('UNMATCHED_SELECTORS');
23
- expect(c('a', 'text').type).toBe('UNEXPECTED_EXTRA_NODE');
24
- expect(c('a', '').type).toBe('MISSING_NODE');
25
- });
26
-
27
- it('#flow', () => {
28
- expect(c('#flow', '<a></a>').type).toBe('MATCHED');
29
- expect(c('#flow', '<b></b>').type).toBe('MATCHED');
30
- expect(c('#flow', '<c></c>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
31
- expect(c('#flow', 'text').type).toBe('MATCHED');
32
- expect(c('#flow', '').type).toBe('MATCHED_ZERO');
33
- });
34
-
35
- it(':model(flow)', () => {
36
- expect(c(':model(flow)', '<a></a>').type).toBe('MATCHED');
37
- expect(c(':model(flow)', '<b></b>').type).toBe('MATCHED');
38
- expect(c(':model(flow)', '<c></c>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
39
- expect(c(':model(flow)', 'text').type).toBe('MATCHED');
40
- expect(c(':model(flow)', '').type).toBe('MATCHED_ZERO');
41
- });
42
-
43
- it('#text', () => {
44
- expect(c('#text', '<a></a>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
45
- expect(c('#text', '<b></b>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
46
- expect(c('#text', '<c></c>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
47
- expect(c('#text', 'text').type).toBe('MATCHED');
48
- expect(c('#text', '').type).toBe('MATCHED_ZERO');
49
- });
50
-
51
- // it(':model(flow):not(:model(interactive))', () => {
52
- // expect(c(':model(flow)', '<a></a>', ':not(:model(interactive))').type).toBe('MATCHED');
53
- // expect(c(':model(flow)', '<b></b>', ':not(:model(interactive))').type).toBe('MATCHED');
54
- // expect(c(':model(flow)', '<c></c>', ':not(:model(interactive))').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
55
- // expect(c(':model(flow)', 'text', ':not(:model(interactive))').type).toBe('MATCHED');
56
- // expect(c(':model(flow)', '<button></button>', ':not(:model(interactive))').type).toBe(
57
- // 'TRANSPARENT_MODEL_DISALLOWS',
58
- // );
59
- // });
@@ -1,351 +0,0 @@
1
- const specs = require('@markuplint/html-spec');
2
- const { createTestElement } = require('@markuplint/ml-core');
3
-
4
- const { order } = require('../../lib/permitted-contents/order');
5
-
6
- function c(models, innerHtml) {
7
- const el = createTestElement(`<div>${innerHtml}</div>`);
8
- return order(models, Array.from(el.childNodes), specs, { ignoreHasMutableChildren: true }, 0);
9
- }
10
-
11
- it('ordered requires', () => {
12
- const models = [
13
- //
14
- { require: 'a' },
15
- { require: 'b' },
16
- { require: 'c' },
17
- ];
18
-
19
- expect(c(models, '<a></a>').type).toBe('MISSING_NODE_REQUIRED');
20
- expect(c(models, '<a></a><b></b>').type).toBe('MISSING_NODE_REQUIRED');
21
- expect(c(models, '<a></a><b></b><c></c>').type).toBe('MATCHED');
22
- expect(c(models, '<a></a><b></b><c></c><d></d>').type).toBe('UNEXPECTED_EXTRA_NODE');
23
- });
24
-
25
- it('ordered requires with #flow', () => {
26
- const models = [
27
- //
28
- { require: '#flow' },
29
- { require: 'a' },
30
- { require: '#flow' },
31
- { require: 'b' },
32
- ];
33
-
34
- expect(c(models, '').type).toBe('MISSING_NODE_REQUIRED');
35
- expect(c(models, '<a></a>').type).toBe('MISSING_NODE_REQUIRED');
36
- expect(c(models, '<a></a><b></b>').type).toBe('MATCHED');
37
- expect(c(models, '<a></a><b></b><c></c>').type).toBe('UNEXPECTED_EXTRA_NODE');
38
- });
39
-
40
- it('ordered requires and optionals', () => {
41
- const models = [
42
- //
43
- { require: 'a' },
44
- { optional: 'b' },
45
- { require: 'c' },
46
- ];
47
-
48
- expect(c(models, '<a></a><b></b><c></c>').type).toBe('MATCHED');
49
- expect(c(models, '<a></a><b></b><b></b><c></c>').type).toBe('MISSING_NODE_REQUIRED');
50
- expect(c(models, '<a></a>').type).toBe('MISSING_NODE_REQUIRED');
51
- expect(c(models, '<b></b><a></a>').type).toBe('MISSING_NODE_REQUIRED');
52
- expect(c(models, '<a></a><c></c>').type).toBe('MATCHED');
53
- expect(c(models, '<a></a><c></c><b></b>').type).toBe('UNEXPECTED_EXTRA_NODE');
54
- });
55
-
56
- it('ordered requires and optionals with #flow', () => {
57
- const models = [
58
- //
59
- { require: 'a' },
60
- { optional: 'b' },
61
- { optional: 'c' },
62
- { require: '#flow' },
63
- ];
64
-
65
- expect(c(models, '<a></a><b></b><c></c>').type).toBe('MATCHED');
66
- expect(c(models, '<a></a><b></b><b></b><c></c>').type).toBe('UNEXPECTED_EXTRA_NODE');
67
- expect(c(models, '<a></a>').type).toBe('MATCHED');
68
- expect(c(models, '<b></b><a></a>').type).toBe('MISSING_NODE_REQUIRED');
69
- expect(c(models, '<a></a><c></c>').type).toBe('MATCHED');
70
- expect(c(models, '<a></a><c></c><b></b>').type).toBe('MATCHED');
71
- });
72
-
73
- it('ordered zeroOrMore combination', () => {
74
- const models = [
75
- //
76
- { zeroOrMore: 'a' },
77
- { zeroOrMore: 'b' },
78
- { zeroOrMore: 'c' },
79
- ];
80
-
81
- expect(c(models, '<b></b>').type).toBe('MATCHED');
82
- expect(c(models, '<c></c>').type).toBe('MATCHED');
83
- expect(c(models, '').type).toBe('MATCHED_ZERO');
84
- expect(c(models, '<b></b><c></c>').type).toBe('MATCHED');
85
- });
86
-
87
- it('the dl element', () => {
88
- const models = [
89
- {
90
- zeroOrMore: ':model(script-supporting)',
91
- },
92
- {
93
- oneOrMore: 'dt',
94
- },
95
- {
96
- zeroOrMore: ':model(script-supporting)',
97
- },
98
- {
99
- oneOrMore: 'dd',
100
- },
101
- {
102
- zeroOrMore: ':model(script-supporting)',
103
- },
104
- ];
105
-
106
- expect(c(models, '<dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
107
- expect(c(models, '<dt></dt><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
108
- expect(c(models, '<dt></dt><dd></dd>').type).toBe('MATCHED');
109
- expect(c(models, '<dt></dt><dd></dd><dd></dd>').type).toBe('MATCHED');
110
- expect(c(models, '<dt></dt><dd></dd><dt></dt>').type).toBe('UNEXPECTED_EXTRA_NODE');
111
- });
112
-
113
- it('the dl element', () => {
114
- const models = [
115
- {
116
- oneOrMore: [
117
- {
118
- zeroOrMore: ':model(script-supporting)',
119
- },
120
- {
121
- oneOrMore: 'dt',
122
- },
123
- {
124
- zeroOrMore: ':model(script-supporting)',
125
- },
126
- {
127
- oneOrMore: 'dd',
128
- },
129
- {
130
- zeroOrMore: ':model(script-supporting)',
131
- },
132
- ],
133
- },
134
- ];
135
-
136
- expect(c(models, '<dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
137
- expect(c(models, '<dt></dt><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
138
- expect(c(models, '<dt></dt><dd></dd>').type).toBe('MATCHED');
139
- expect(c(models, '<dt></dt><dd></dd><dd></dd>').type).toBe('MATCHED');
140
- expect(c(models, '<dt></dt><dd></dd><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
141
- expect(c(models, '<dt></dt><dd></dd><dt></dt><dd></dd>').type).toBe('MATCHED');
142
- expect(c(models, '<dt></dt><dd></dd><dt></dt><dd></dd><dd></dd><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
143
- });
144
-
145
- it('the dl element', () => {
146
- const models = [
147
- {
148
- choice: [
149
- [
150
- {
151
- oneOrMore: [
152
- {
153
- zeroOrMore: ':model(script-supporting)',
154
- },
155
- {
156
- oneOrMore: 'dt',
157
- },
158
- {
159
- zeroOrMore: ':model(script-supporting)',
160
- },
161
- {
162
- oneOrMore: 'dd',
163
- },
164
- {
165
- zeroOrMore: ':model(script-supporting)',
166
- },
167
- ],
168
- },
169
- ],
170
- [
171
- {
172
- zeroOrMore: ':model(script-supporting)',
173
- },
174
- {
175
- oneOrMore: 'div',
176
- },
177
- {
178
- zeroOrMore: ':model(script-supporting)',
179
- },
180
- ],
181
- ],
182
- },
183
- ];
184
-
185
- expect(c(models, '<dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
186
- expect(c(models, '<dt></dt>').query).toBe('dd');
187
- expect(c(models, '<dt></dt><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
188
- expect(c(models, '<dt></dt><dd></dd>').type).toBe('MATCHED');
189
- expect(c(models, '<dt></dt><dd></dd><dd></dd>').type).toBe('MATCHED');
190
- expect(c(models, '<dt></dt><dd></dd><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
191
- expect(c(models, '<dt></dt><dd></dd><dt></dt><dd></dd>').type).toBe('MATCHED');
192
- expect(c(models, '<dt></dt><dd></dd><dt></dt><dd></dd><dd></dd><dt></dt>').type).toBe('MISSING_NODE_ONE_OR_MORE');
193
- expect(c(models, '<div></div>').type).toBe('MATCHED');
194
- expect(c(models, '<div></div><div></div>').type).toBe('MATCHED');
195
- });
196
-
197
- it('the ruby element', () => {
198
- const models = [
199
- {
200
- oneOrMore: [
201
- {
202
- require: ':model(phrasing):not(ruby, :has(ruby))',
203
- },
204
- {
205
- choice: [
206
- [
207
- {
208
- oneOrMore: 'rt',
209
- },
210
- ],
211
- [
212
- {
213
- oneOrMore: [
214
- {
215
- require: 'rp',
216
- },
217
- {
218
- oneOrMore: [
219
- {
220
- require: 'rt',
221
- },
222
- {
223
- require: 'rp',
224
- },
225
- ],
226
- },
227
- ],
228
- },
229
- ],
230
- ],
231
- },
232
- ],
233
- },
234
- ];
235
-
236
- expect(c(models, '<span></span>').type).toBe('MISSING_NODE_ONE_OR_MORE');
237
- expect(c(models, '<span></span>').query).toBe('rt');
238
- expect(c(models, '<span></span><rt></rt>').type).toBe('MATCHED');
239
- expect(c(models, '<span></span><rp></rp><rt></rt>').type).toBe('MISSING_NODE_REQUIRED');
240
- expect(c(models, '<span></span><rp></rp><rt></rt>').query).toBe('rp');
241
- });
242
-
243
- it('part of the ruby element', () => {
244
- const models = [
245
- {
246
- require: ':model(phrasing):not(ruby, :has(ruby))',
247
- },
248
- {
249
- choice: [
250
- [
251
- {
252
- oneOrMore: 'rt',
253
- },
254
- ],
255
- [
256
- {
257
- oneOrMore: [
258
- {
259
- require: 'rp',
260
- },
261
- {
262
- oneOrMore: [
263
- {
264
- require: 'rt',
265
- },
266
- {
267
- require: 'rp',
268
- },
269
- ],
270
- },
271
- ],
272
- },
273
- ],
274
- ],
275
- },
276
- ];
277
-
278
- expect(c(models, '<span></span>').type).toBe('MISSING_NODE_ONE_OR_MORE');
279
- expect(c(models, '<span></span>').query).toBe('rt');
280
- expect(c(models, '<span></span><rt></rt>').type).toBe('MATCHED');
281
- expect(c(models, '<span></span><rp></rp><rt></rt>').type).toBe('MISSING_NODE_REQUIRED');
282
- expect(c(models, '<span></span><rp></rp><rt></rt>').query).toBe('rp');
283
- });
284
-
285
- it('part of the ruby element', () => {
286
- const models = [
287
- {
288
- oneOrMore: [
289
- {
290
- require: 'rp',
291
- },
292
- {
293
- oneOrMore: [
294
- {
295
- require: 'rt',
296
- },
297
- {
298
- require: 'rp',
299
- },
300
- ],
301
- },
302
- ],
303
- },
304
- ];
305
-
306
- expect(c(models, '<span></span>').type).toBe('MISSING_NODE_REQUIRED');
307
- expect(c(models, '<span></span>').query).toBe('rp');
308
- expect(c(models, '<rp></rp>').type).toBe('MISSING_NODE_REQUIRED');
309
- expect(c(models, '<rp></rp>').query).toBe('rt');
310
- expect(c(models, '<rp></rp><rt></rt><rp></rp>').type).toBe('MATCHED');
311
- expect(c(models, '<rp></rp><rt></rt><rp></rp><rt></rt>').type).toBe('MISSING_NODE_REQUIRED');
312
- expect(c(models, '<rp></rp><rt></rt><rp></rp><rt></rt>').query).toBe('rp');
313
- expect(c(models, '<rp></rp><rt></rt><rp></rp><rt></rt><rp></rp>').type).toBe('MATCHED');
314
- });
315
-
316
- it('part of the ruby element', () => {
317
- const models = [
318
- {
319
- oneOrMore: [
320
- {
321
- require: 'rt',
322
- },
323
- {
324
- require: 'rp',
325
- },
326
- ],
327
- },
328
- ];
329
-
330
- expect(c(models, '<rt></rt>').type).toBe('MISSING_NODE_REQUIRED');
331
- expect(c(models, '<rt></rt>').query).toBe('rp');
332
- expect(c(models, '<rt></rt><rp></rp>').type).toBe('MATCHED');
333
- expect(c(models, '<rt></rt><rp></rp><rt></rt>').type).toBe('MISSING_NODE_REQUIRED');
334
- expect(c(models, '<rt></rt><rp></rp><rt></rt>').query).toBe('rp');
335
- expect(c(models, '<rt></rt><rp></rp><rt></rt><rp></rp>').type).toBe('MATCHED');
336
- });
337
-
338
- it('part of the ruby element', () => {
339
- const models = [
340
- {
341
- require: 'rt',
342
- },
343
- {
344
- require: 'rp',
345
- },
346
- ];
347
-
348
- expect(c(models, '<rt></rt>').type).toBe('MISSING_NODE_REQUIRED');
349
- expect(c(models, '<rt></rt>').query).toBe('rp');
350
- expect(c(models, '<rt></rt><rp></rp>').type).toBe('MATCHED');
351
- });
@@ -1,41 +0,0 @@
1
- const specs = require('@markuplint/html-spec');
2
- const { createTestElement } = require('@markuplint/ml-core');
3
-
4
- const { recursiveBranch } = require('../../lib/permitted-contents/recursive-branch');
5
-
6
- function c(models, innerHtml) {
7
- const el = createTestElement(`<div>${innerHtml}</div>`);
8
- return recursiveBranch(models, Array.from(el.childNodes), specs, { ignoreHasMutableChildren: true }, 0);
9
- }
10
-
11
- it('a', () => {
12
- expect(c('a', '<a></a>').type).toBe('MATCHED');
13
- expect(c('a', '<b></b>').type).toBe('UNMATCHED_SELECTORS');
14
- expect(c('a', '<c></c>').type).toBe('UNMATCHED_SELECTORS');
15
- expect(c('a', 'text').type).toBe('UNEXPECTED_EXTRA_NODE');
16
- expect(c('a', '').type).toBe('MISSING_NODE');
17
- });
18
-
19
- it('#flow', () => {
20
- expect(c('#flow', '<a></a>').type).toBe('MATCHED');
21
- expect(c('#flow', '<b></b>').type).toBe('MATCHED');
22
- expect(c('#flow', '<c></c>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
23
- expect(c('#flow', 'text').type).toBe('MATCHED');
24
- expect(c('#flow', '').type).toBe('MATCHED_ZERO');
25
- });
26
-
27
- it('a, #flow', () => {
28
- expect(c(['a', '#flow'], '<a></a>').type).toBe('MATCHED');
29
- expect(c(['a', '#flow'], '<b></b>').type).toBe('MATCHED');
30
- expect(c(['a', '#flow'], '<c></c>').type).toBe('UNMATCHED_SELECTOR_BUT_MAY_EMPTY');
31
- expect(c(['a', '#flow'], 'text').type).toBe('MATCHED');
32
- expect(c(['a', '#flow'], '').type).toBe('MATCHED_ZERO');
33
- });
34
-
35
- it('c, #flow', () => {
36
- expect(c(['c', '#flow'], '<a></a>').type).toBe('MATCHED');
37
- expect(c(['c', '#flow'], '<b></b>').type).toBe('MATCHED');
38
- expect(c(['c', '#flow'], '<c></c>').type).toBe('MATCHED');
39
- expect(c(['c', '#flow'], 'text').type).toBe('MATCHED');
40
- expect(c(['c', '#flow'], '').type).toBe('MATCHED_ZERO');
41
- });
@@ -1,24 +0,0 @@
1
- const specs = require('@markuplint/html-spec');
2
- const { createTestElement } = require('@markuplint/ml-core');
3
-
4
- const {
5
- representTransparentNodes,
6
- transparentMode,
7
- } = require('../../lib/permitted-contents/represent-transparent-nodes');
8
-
9
- function c(html) {
10
- const el = createTestElement(`<div>${html}</div>`);
11
- const { nodes } = representTransparentNodes(Array.from(el.children), specs, { ignoreHasMutableChildren: true });
12
- return nodes.map(n => n.nodeName.toLowerCase() + (transparentMode.has(n) ? '*' : ''));
13
- }
14
-
15
- it('<div>', () => {
16
- expect(c('<div></div>')).toStrictEqual(['div']);
17
- });
18
-
19
- it('<audio>', () => {
20
- expect(c('<audio></audio>')).toStrictEqual([]);
21
- expect(c('<audio><span></span></audio>')).toStrictEqual(['span*']);
22
- expect(c('<audio><source></source><span></span></audio>')).toStrictEqual(['span*']);
23
- expect(c('<audio><source></source><track></track><span></span></audio>')).toStrictEqual(['span*']);
24
- });
@@ -1,67 +0,0 @@
1
- const specs = require('@markuplint/html-spec');
2
- const { createTestElement } = require('@markuplint/ml-core');
3
- const { getContentModel } = require('@markuplint/ml-spec');
4
-
5
- const { start } = require('../../lib/permitted-contents/start');
6
-
7
- function c(html, target) {
8
- const root = createTestElement(html, specs);
9
- const el = target ? root.querySelector(target) : root;
10
- return start(getContentModel(el, specs.specs), el, specs, { ignoreHasMutableChildren: true });
11
- }
12
-
13
- it('transparent: <a>', () => {
14
- expect(c('<a href><button></button></a>')[0].type).toBe('MATCHED');
15
- expect(c('<a href><button></button></a>')[1].type).toBe('TRANSPARENT_MODEL_DISALLOWS');
16
- expect(c('<a href><b></b></a>')[0].type).toBe('MATCHED');
17
- expect(c('<a href>text</a>')[0].type).toBe('MATCHED');
18
- expect(c('<a href></a>')[0].type).toBe('MATCHED_ZERO');
19
- expect(c('<a><div></div><span></span><em></em></a>')[0].type).toBe('MATCHED');
20
- });
21
-
22
- it('transparent: <del> with <details>', () => {
23
- expect(c('<details><summary></summary><del></del></details>')[0].type).toBe('MATCHED');
24
- expect(c('<details><summary></summary><del>text</del></details>')[0].type).toBe('MATCHED');
25
- expect(c('<details><summary></summary><del><b></b><b></b><b></b></del></details>')[0].type).toBe('MATCHED');
26
- expect(c('<details><summary></summary><del><c></c></del></details>')[0].type).toBe('UNEXPECTED_EXTRA_NODE');
27
- expect(c('<details><summary></summary><del><c></c></del></details>')[0].scope.nodeName).toBe('C');
28
- });
29
-
30
- it('transparent: <a> with <details> (<a> perspective)', () => {
31
- expect(c('<details><summary></summary><a href></a></details>')[0].type).toBe('MATCHED');
32
- expect(c('<details><summary></summary><a href>text</a></details>')[0].type).toBe('MATCHED');
33
- expect(c('<details><summary></summary><a href><button></button></a></details>')[0].type).toBe('MATCHED');
34
- expect(c('<details><summary></summary><a href><button></button></a></details>')[1].type).toBe(
35
- 'TRANSPARENT_MODEL_DISALLOWS',
36
- );
37
- });
38
-
39
- it('transparent: <a> with <div>', () => {
40
- expect(c('<div><a><option></option></a></div>')[0].type).toBe('UNEXPECTED_EXTRA_NODE');
41
- });
42
-
43
- it('transparent: <a> with <svg>', () => {
44
- expect(c('<svg><a><text>text</text></a></svg>')[0].type).toBe('MATCHED');
45
- expect(c('<svg><a><text>text</text></a></svg>', 'a')[0].type).toBe('MATCHED');
46
- expect(c('<svg><a><text>text</text></a></svg>', 'text')[0].type).toBe('MATCHED');
47
- });
48
-
49
- it('conditional transparent: <audio>', () => {
50
- expect(c('<audio src="path/to"><source /></audio>')[0].type).toBe('MATCHED');
51
- expect(c('<div><audio src="path/to"><source /></audio></div>', 'audio')[0].type).toBe('MATCHED');
52
- expect(c('<div><audio src="path/to"><source /></audio></div>')[0].type).toBe('UNEXPECTED_EXTRA_NODE');
53
- });
54
-
55
- it('transparent: <audio> with <audio>', () => {
56
- expect(c('<audio><audio></audio></audio>')[0].type).toBe('MATCHED_ZERO');
57
- expect(c('<audio><audio></audio></audio>')[1].type).toBe('TRANSPARENT_MODEL_DISALLOWS');
58
- });
59
-
60
- it('extra nodes', () => {
61
- expect(c('<ul>TEXT</ul>')[0].type).toBe('UNEXPECTED_EXTRA_NODE');
62
- });
63
-
64
- it(':has', () => {
65
- expect(c('<a><div><div><button></button></div></div></a>')[0].hint.not?.nodeName).toBeUndefined();
66
- expect(c('<a><div><div><button></button></div></div></a>')[1].hint.not?.nodeName).toBe('BUTTON');
67
- });
@@ -1,113 +0,0 @@
1
- const { mlRuleTest } = require('markuplint');
2
-
3
- const rule = require('../../lib/placeholder-label-option').default;
4
-
5
- test('Valid placeholder', async () => {
6
- expect(
7
- (
8
- await mlRuleTest(
9
- rule,
10
- `<select required>
11
- <option value="">Placeholder</option>
12
- <option value="option1">Option 1</option>
13
- <option value="option2">Option 2</option>
14
- </select>`,
15
- )
16
- ).violations,
17
- ).toStrictEqual([]);
18
-
19
- expect(
20
- (
21
- await mlRuleTest(
22
- rule,
23
- `<select required multiple>
24
- <option value="placeholder">Placeholder</option>
25
- <option value="option1">Option 1</option>
26
- <option value="option2">Option 2</option>
27
- </select>`,
28
- )
29
- ).violations,
30
- ).toStrictEqual([]);
31
-
32
- expect(
33
- (
34
- await mlRuleTest(
35
- rule,
36
- `<select required size="2">
37
- <option value="placeholder">Placeholder</option>
38
- <option value="option1">Option 1</option>
39
- <option value="option2">Option 2</option>
40
- </select>`,
41
- )
42
- ).violations,
43
- ).toStrictEqual([]);
44
- });
45
-
46
- test("Invalid: first option element's value is not empty", async () => {
47
- expect(
48
- (
49
- await mlRuleTest(
50
- rule,
51
- `<select required>
52
- <option value="placeholder">Placeholder</option>
53
- <option value="option1">Option 1</option>
54
- <option value="option2">Option 2</option>
55
- </select>`,
56
- )
57
- ).violations,
58
- ).toStrictEqual([
59
- {
60
- severity: 'error',
61
- line: 1,
62
- col: 1,
63
- raw: '<select required>',
64
- message: 'Need the placeholder label option',
65
- },
66
- ]);
67
-
68
- expect(
69
- (
70
- await mlRuleTest(
71
- rule,
72
- `<select required size="1">
73
- <option value="placeholder">Placeholder</option>
74
- <option value="option1">Option 1</option>
75
- <option value="option2">Option 2</option>
76
- </select>`,
77
- )
78
- ).violations,
79
- ).toStrictEqual([
80
- {
81
- severity: 'error',
82
- line: 1,
83
- col: 1,
84
- raw: '<select required size="1">',
85
- message: 'Need the placeholder label option',
86
- },
87
- ]);
88
- });
89
-
90
- test("Invalid: Invalid: first option element's parent is optgroup", async () => {
91
- expect(
92
- (
93
- await mlRuleTest(
94
- rule,
95
- `<select required>
96
- <optgroup label="Group">
97
- <option value="">Placeholder</option>
98
- </optgroup>
99
- <option value="option1">Option 1</option>
100
- <option value="option2">Option 2</option>
101
- </select>`,
102
- )
103
- ).violations,
104
- ).toStrictEqual([
105
- {
106
- severity: 'error',
107
- line: 1,
108
- col: 1,
109
- raw: '<select required>',
110
- message: 'Need the placeholder label option',
111
- },
112
- ]);
113
- });