@markuplint/rules 3.7.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/helpers.d.ts +2 -5
- package/lib/index.d.ts +240 -99
- package/lib/invalid-attr/index.d.ts +38 -31
- package/lib/no-refer-to-non-existent-id/index.d.ts +1 -2
- package/lib/no-refer-to-non-existent-id/index.js +2 -1
- package/lib/require-accessible-name/index.js +1 -1
- package/lib/required-attr/index.d.ts +1 -1
- package/lib/required-attr/index.js +1 -1
- package/lib/wai-aria/checkings/_.d.ts +15 -0
- package/lib/wai-aria/checkings/_.js +27 -0
- package/lib/wai-aria/checkings/required-prop copy.d.ts +15 -0
- package/lib/wai-aria/checkings/required-prop copy.js +27 -0
- package/lib/wai-aria/checkings/unadopted-explicit-roles.d.ts +15 -0
- package/lib/wai-aria/checkings/unadopted-explicit-roles.js +17 -0
- package/lib/wai-aria/index.js +2 -1
- package/lib/xxx/index.d.ts +2 -0
- package/lib/xxx/index.js +32 -0
- package/package.json +11 -13
- package/test/attr-check.spec.js +77 -0
- package/test/attr-duplication/index.spec.js +159 -0
- package/test/attr-value-quotes/index.spec.js +133 -0
- package/test/case-sensitive-attr-name/index.spec.js +65 -0
- package/test/case-sensitive-tag-name/index.spec.js +80 -0
- package/test/character-reference/index.spec.js +57 -0
- package/test/class-naming/index.spec.js +470 -0
- package/test/create-message.spec.js +497 -0
- package/test/deprecated-attr/index.spec.js +48 -0
- package/test/deprecated-element/index.spec.js +48 -0
- package/test/disallowed-element/index.spec.js +90 -0
- package/test/doctype/index.spec.js +50 -0
- package/test/end-tag/index.spec.js +162 -0
- package/test/id-duplication/index.spec.js +47 -0
- package/test/ineffective-attr/index.spec.js +31 -0
- package/test/invalid-attr/index.spec.js +1632 -0
- package/test/label-has-control/index.spec.js +29 -0
- package/test/landmark-roles/index.spec.js +187 -0
- package/test/no-boolean-attr-value/index.spec.js +41 -0
- package/test/no-default-value/index.spec.js +74 -0
- package/test/no-empty-palpable-content/index.spec.js +115 -0
- package/test/no-hard-code-id/index.spec.js +100 -0
- package/test/no-refer-to-non-existent-id/index.spec.js +254 -0
- package/test/no-use-event-handler-attr/index.spec.js +57 -0
- package/test/permitted-contents/choice.spec.js +174 -0
- package/test/permitted-contents/count-pattern.spec.js +308 -0
- package/test/permitted-contents/index.spec.js +1371 -0
- package/test/permitted-contents/matches-selector.spec.js +59 -0
- package/test/permitted-contents/order.spec.js +351 -0
- package/test/permitted-contents/recursive-branch.spec.js +41 -0
- package/test/permitted-contents/represent-transparent-nodes.spec.js +24 -0
- package/test/permitted-contents/start.spec.js +67 -0
- package/test/placeholder-label-option/index.spec.js +113 -0
- package/test/require-accessible-name/index.spec.js +446 -0
- package/test/require-datetime/index.spec.js +54 -0
- package/test/require-datetime/utils.spec.js +52 -0
- package/test/required-attr/index.spec.js +414 -0
- package/test/required-element/index.spec.js +188 -0
- package/test/required-h1/index.spec.js +69 -0
- package/test/use-list/index.spec.js +109 -0
- package/test/wai-aria/checkings/value.spec.js +33 -0
- package/test/wai-aria/index.spec.js +1173 -0
package/lib/xxx/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
+
exports.default = (0, ml_core_1.createRule)({
|
|
5
|
+
defaultValue: true,
|
|
6
|
+
defaultOptions: null,
|
|
7
|
+
async verify({ document, report, t }) {
|
|
8
|
+
// Element
|
|
9
|
+
await document.walkOn("Element", (el) => {
|
|
10
|
+
const raw = el.raw.trim();
|
|
11
|
+
if (/./i.test(raw)) {
|
|
12
|
+
report({
|
|
13
|
+
scope: el,
|
|
14
|
+
message: t("It is {0}", "issue"),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
// Attribute
|
|
19
|
+
await document.walkOn("Attr", (attr) => {
|
|
20
|
+
var _a, _b, _c;
|
|
21
|
+
if (/./i.test(attr.name)) {
|
|
22
|
+
report({
|
|
23
|
+
scope: attr,
|
|
24
|
+
line: (_a = attr.nameNode) === null || _a === void 0 ? void 0 : _a.startLine,
|
|
25
|
+
col: (_b = attr.nameNode) === null || _b === void 0 ? void 0 : _b.startCol,
|
|
26
|
+
raw: (_c = attr.nameNode) === null || _c === void 0 ? void 0 : _c.raw,
|
|
27
|
+
message: t("It is {0}", "issue"),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/rules",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.0",
|
|
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>",
|
|
@@ -20,21 +20,19 @@
|
|
|
20
20
|
"./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@markuplint/html-spec": "3.
|
|
24
|
-
"@markuplint/ml-core": "3.
|
|
25
|
-
"@markuplint/ml-spec": "3.
|
|
26
|
-
"@markuplint/selector": "3.
|
|
27
|
-
"@markuplint/shared": "3.
|
|
28
|
-
"@markuplint/types": "3.
|
|
23
|
+
"@markuplint/html-spec": "3.8.0",
|
|
24
|
+
"@markuplint/ml-core": "3.9.0",
|
|
25
|
+
"@markuplint/ml-spec": "3.8.0",
|
|
26
|
+
"@markuplint/selector": "3.8.0",
|
|
27
|
+
"@markuplint/shared": "3.6.0",
|
|
28
|
+
"@markuplint/types": "3.6.0",
|
|
29
|
+
"@types/debug": "^4.1.7",
|
|
29
30
|
"@ungap/structured-clone": "^1.0.1",
|
|
30
31
|
"ansi-colors": "^4.1.3",
|
|
31
32
|
"chrono-node": "^2.5.0",
|
|
32
33
|
"debug": "^4.3.4",
|
|
33
|
-
"tslib": "^2.4.1"
|
|
34
|
-
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@types/debug": "^4.1.7",
|
|
37
|
-
"type-fest": "^3.6.1"
|
|
34
|
+
"tslib": "^2.4.1",
|
|
35
|
+
"type-fest": "^3.8.0"
|
|
38
36
|
},
|
|
39
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "adc6e432cccba7cfad0dc8bf9f92e5aaf1107359"
|
|
40
38
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const { translator } = require('@markuplint/i18n');
|
|
2
|
+
const { i18n } = require('markuplint');
|
|
3
|
+
|
|
4
|
+
const { valueCheck } = require('../lib/attr-check');
|
|
5
|
+
|
|
6
|
+
let t;
|
|
7
|
+
|
|
8
|
+
beforeAll(async () => {
|
|
9
|
+
const locale = await i18n('en');
|
|
10
|
+
t = translator(locale);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('OneCodePointChar List', () => {
|
|
14
|
+
expect(
|
|
15
|
+
valueCheck(t, 'accesskey', '@ 12', {
|
|
16
|
+
token: 'OneCodePointChar',
|
|
17
|
+
separator: 'space',
|
|
18
|
+
unique: true,
|
|
19
|
+
}),
|
|
20
|
+
).toStrictEqual([
|
|
21
|
+
'the "accesskey" attribute expects space-separated list. the the content of the list part includes unexpected characters. It expects one code point character (https://html.spec.whatwg.org/multipage/interaction.html#the-accesskey-attribute)',
|
|
22
|
+
{
|
|
23
|
+
col: 2,
|
|
24
|
+
line: 0,
|
|
25
|
+
raw: '12',
|
|
26
|
+
},
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('BrowsingContextNameOrKeyword', () => {
|
|
31
|
+
expect(valueCheck(t, 'target', '', 'BrowsingContextNameOrKeyword')).toStrictEqual([
|
|
32
|
+
'the "target" attribute must not be empty. It expects either "_blank", "_self", "_parent", "_top", "browsing context name" (https://html.spec.whatwg.org/multipage/browsers.html#valid-browsing-context-name-or-keyword)',
|
|
33
|
+
{
|
|
34
|
+
col: 0,
|
|
35
|
+
line: 0,
|
|
36
|
+
raw: '',
|
|
37
|
+
},
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('BCP47', () => {
|
|
42
|
+
expect(valueCheck(t, 'lang', '', 'BCP47')).toStrictEqual([
|
|
43
|
+
'the "lang" attribute must not be empty. It expects the BCP47 format (https://tools.ietf.org/rfc/bcp/bcp47.html)',
|
|
44
|
+
{
|
|
45
|
+
col: 0,
|
|
46
|
+
line: 0,
|
|
47
|
+
raw: '',
|
|
48
|
+
},
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('DateTime', () => {
|
|
53
|
+
expect(valueCheck(t, 'datetime', '200-1-1', 'DateTime')).toStrictEqual([
|
|
54
|
+
'the year part of the "datetime" attribute expects four or more digits (https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value)',
|
|
55
|
+
{
|
|
56
|
+
col: 0,
|
|
57
|
+
line: 0,
|
|
58
|
+
raw: '200',
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
expect(valueCheck(t, 'datetime', '2000-1-1', 'DateTime')).toStrictEqual([
|
|
62
|
+
'the month part of the "datetime" attribute expects two digits (https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value)',
|
|
63
|
+
{
|
|
64
|
+
col: 5,
|
|
65
|
+
line: 0,
|
|
66
|
+
raw: '1',
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
expect(valueCheck(t, 'datetime', '00:00:00.0000', 'DateTime')).toStrictEqual([
|
|
70
|
+
'the fractional part part of the "datetime" attribute expects one to three digits (https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value)',
|
|
71
|
+
{
|
|
72
|
+
col: 9,
|
|
73
|
+
line: 0,
|
|
74
|
+
raw: '0000',
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
const { mlRuleTest } = require('markuplint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../../lib/attr-duplication').default;
|
|
4
|
+
|
|
5
|
+
test('is test 1', async () => {
|
|
6
|
+
const { violations } = await mlRuleTest(
|
|
7
|
+
rule,
|
|
8
|
+
`
|
|
9
|
+
<div data-attr="value" data-Attr='db' data-attR=tr>
|
|
10
|
+
lorem
|
|
11
|
+
<p>ipsam</p>
|
|
12
|
+
</div>
|
|
13
|
+
`,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
expect(violations).toStrictEqual([
|
|
17
|
+
{
|
|
18
|
+
severity: 'error',
|
|
19
|
+
message: 'The attribute name is duplicated',
|
|
20
|
+
line: 2,
|
|
21
|
+
col: 26,
|
|
22
|
+
raw: 'data-Attr',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
severity: 'error',
|
|
26
|
+
message: 'The attribute name is duplicated',
|
|
27
|
+
line: 2,
|
|
28
|
+
col: 41,
|
|
29
|
+
raw: 'data-attR',
|
|
30
|
+
},
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('is test 2', async () => {
|
|
35
|
+
const { violations } = await mlRuleTest(
|
|
36
|
+
rule,
|
|
37
|
+
`
|
|
38
|
+
<div
|
|
39
|
+
data-attr="value"
|
|
40
|
+
data-Attr='db'
|
|
41
|
+
data-attR=tr>
|
|
42
|
+
lorem
|
|
43
|
+
<p>ipsam</p>
|
|
44
|
+
</div>
|
|
45
|
+
`,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(violations).toStrictEqual([
|
|
49
|
+
{
|
|
50
|
+
severity: 'error',
|
|
51
|
+
message: 'The attribute name is duplicated',
|
|
52
|
+
line: 4,
|
|
53
|
+
col: 4,
|
|
54
|
+
raw: 'data-Attr',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
severity: 'error',
|
|
58
|
+
message: 'The attribute name is duplicated',
|
|
59
|
+
line: 5,
|
|
60
|
+
col: 4,
|
|
61
|
+
raw: 'data-attR',
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('is test 3', async () => {
|
|
67
|
+
const { violations } = await mlRuleTest(rule, '<img src="/" SRC="/" >', undefined, false, 'ja');
|
|
68
|
+
|
|
69
|
+
expect(violations.map(_ => _.message)).toStrictEqual(['属性名が重複しています']);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('nodeRules disable', async () => {
|
|
73
|
+
const { violations } = await mlRuleTest(rule, '<div><span attr attr></span></div>', {
|
|
74
|
+
nodeRule: [
|
|
75
|
+
{
|
|
76
|
+
selector: 'span',
|
|
77
|
+
rule: false,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(violations.length).toStrictEqual(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('Vue', async () => {
|
|
86
|
+
const { violations } = await mlRuleTest(rule, '<template><div attr v-bind:attr /></template>', {
|
|
87
|
+
parser: {
|
|
88
|
+
'.*': '@markuplint/vue-parser',
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(violations).toStrictEqual([
|
|
93
|
+
{
|
|
94
|
+
severity: 'error',
|
|
95
|
+
line: 1,
|
|
96
|
+
col: 21,
|
|
97
|
+
message: 'The attribute name is duplicated',
|
|
98
|
+
raw: 'v-bind:attr',
|
|
99
|
+
},
|
|
100
|
+
]);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('Vue (exception)', async () => {
|
|
104
|
+
const { violations } = await mlRuleTest(
|
|
105
|
+
rule,
|
|
106
|
+
'<template><div class="foo" v-bind:class="bar" style="a: b;" :style="{c: d}" /></template>',
|
|
107
|
+
{
|
|
108
|
+
parser: {
|
|
109
|
+
'.*': '@markuplint/vue-parser',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
expect(violations.length).toBe(0);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('React', async () => {
|
|
118
|
+
const { violations } = await mlRuleTest(rule, '<div tabindex tabIndex />', {
|
|
119
|
+
parser: {
|
|
120
|
+
'.*': '@markuplint/vue-parser',
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(violations).toStrictEqual([]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('Pug', async () => {
|
|
128
|
+
const { violations } = await mlRuleTest(rule, '.hoge(class="hoge2")&attributes({class: "hoge3"})', {
|
|
129
|
+
parser: {
|
|
130
|
+
'.*': '@markuplint/pug-parser',
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(violations.length).toBe(0);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('Svelte', async () => {
|
|
138
|
+
const { violations } = await mlRuleTest(
|
|
139
|
+
rule,
|
|
140
|
+
'<div class:selected="{isSelected}" class:focused="{isFocused}"></div>',
|
|
141
|
+
{
|
|
142
|
+
parser: {
|
|
143
|
+
'.*': '@markuplint/svelte-parser',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
expect(violations.length).toBe(0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('Astro', async () => {
|
|
152
|
+
const { violations } = await mlRuleTest(rule, '<div class:list="a" class="b"></div>', {
|
|
153
|
+
parser: {
|
|
154
|
+
'.*': '@markuplint/astro-parser',
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(violations.length).toBe(1);
|
|
159
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const { mlRuleTest } = require('markuplint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../../lib/attr-value-quotes').default;
|
|
4
|
+
|
|
5
|
+
describe('verify', () => {
|
|
6
|
+
test('default', async () => {
|
|
7
|
+
const { violations } = await mlRuleTest(
|
|
8
|
+
rule,
|
|
9
|
+
`
|
|
10
|
+
<div data-attr="value" data-Attr='db' data-attR=tr>
|
|
11
|
+
lorem
|
|
12
|
+
<p>ipsam</p>
|
|
13
|
+
</div>
|
|
14
|
+
`,
|
|
15
|
+
);
|
|
16
|
+
expect(violations).toStrictEqual([
|
|
17
|
+
{
|
|
18
|
+
severity: 'warning',
|
|
19
|
+
message: 'Attribute value is must quote on double quotation mark',
|
|
20
|
+
line: 2,
|
|
21
|
+
col: 26,
|
|
22
|
+
raw: "data-Attr='db'",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
severity: 'warning',
|
|
26
|
+
message: 'Attribute value is must quote on double quotation mark',
|
|
27
|
+
line: 2,
|
|
28
|
+
col: 41,
|
|
29
|
+
raw: 'data-attR=tr',
|
|
30
|
+
},
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('double', async () => {
|
|
35
|
+
const { violations } = await mlRuleTest(
|
|
36
|
+
rule,
|
|
37
|
+
`
|
|
38
|
+
<div data-attr="value" data-Attr='db' data-attR=tr>
|
|
39
|
+
lorem
|
|
40
|
+
<p>ipsam</p>
|
|
41
|
+
</div>
|
|
42
|
+
`,
|
|
43
|
+
{
|
|
44
|
+
rule: {
|
|
45
|
+
severity: 'error',
|
|
46
|
+
value: 'double',
|
|
47
|
+
options: null,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
expect(violations).toStrictEqual([
|
|
52
|
+
{
|
|
53
|
+
severity: 'error',
|
|
54
|
+
message: 'Attribute value is must quote on double quotation mark',
|
|
55
|
+
line: 2,
|
|
56
|
+
col: 26,
|
|
57
|
+
raw: "data-Attr='db'",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
severity: 'error',
|
|
61
|
+
message: 'Attribute value is must quote on double quotation mark',
|
|
62
|
+
line: 2,
|
|
63
|
+
col: 41,
|
|
64
|
+
raw: 'data-attR=tr',
|
|
65
|
+
},
|
|
66
|
+
]);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('single', async () => {
|
|
70
|
+
const { violations } = await mlRuleTest(
|
|
71
|
+
rule,
|
|
72
|
+
`
|
|
73
|
+
<div data-attr="value" data-Attr='db' data-attR=tr>
|
|
74
|
+
lorem
|
|
75
|
+
<p>ipsam</p>
|
|
76
|
+
</div>
|
|
77
|
+
`,
|
|
78
|
+
{
|
|
79
|
+
rule: {
|
|
80
|
+
severity: 'error',
|
|
81
|
+
value: 'single',
|
|
82
|
+
options: null,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
expect(violations).toStrictEqual([
|
|
87
|
+
{
|
|
88
|
+
severity: 'error',
|
|
89
|
+
message: 'Attribute value is must quote on single quotation mark',
|
|
90
|
+
line: 2,
|
|
91
|
+
col: 8,
|
|
92
|
+
raw: 'data-attr="value"',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
severity: 'error',
|
|
96
|
+
message: 'Attribute value is must quote on single quotation mark',
|
|
97
|
+
line: 2,
|
|
98
|
+
col: 41,
|
|
99
|
+
raw: 'data-attR=tr',
|
|
100
|
+
},
|
|
101
|
+
]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('empty', async () => {
|
|
105
|
+
const { violations } = await mlRuleTest(
|
|
106
|
+
rule,
|
|
107
|
+
`
|
|
108
|
+
<div data-attr>
|
|
109
|
+
lorem
|
|
110
|
+
<p>ipsam</p>
|
|
111
|
+
</div>
|
|
112
|
+
`,
|
|
113
|
+
);
|
|
114
|
+
expect(violations.length).toBe(0);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// describe('fix', () => {
|
|
119
|
+
// test('empty', async () => {
|
|
120
|
+
// const { fixedCode } = await mlRuleTest(rule, '<div attr noop=noop foo="bar" hoge=\'fuga\'>', undefined, true);
|
|
121
|
+
// expect(fixedCode).toEqual('<div attr noop="noop" foo="bar" hoge="fuga">');
|
|
122
|
+
// });
|
|
123
|
+
|
|
124
|
+
// test('empty', async () => {
|
|
125
|
+
// const { fixedCode } = await mlRuleTest(
|
|
126
|
+
// rule,
|
|
127
|
+
// '<div attr noop=noop foo="bar" hoge=\'fuga\'>',
|
|
128
|
+
// { rule: 'single' },
|
|
129
|
+
// true,
|
|
130
|
+
// );
|
|
131
|
+
// expect(fixedCode).toEqual("<div attr noop='noop' foo='bar' hoge='fuga'>");
|
|
132
|
+
// });
|
|
133
|
+
// });
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const { mlRuleTest } = require('markuplint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../../lib/case-sensitive-attr-name').default;
|
|
4
|
+
|
|
5
|
+
describe('verify', () => {
|
|
6
|
+
test('lower case', async () => {
|
|
7
|
+
const { violations } = await mlRuleTest(rule, '<div data-lowercase></div>');
|
|
8
|
+
expect(violations).toStrictEqual([]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('upper case', async () => {
|
|
12
|
+
const { violations } = await mlRuleTest(rule, '<div data-UPPERCASE="value"></div>');
|
|
13
|
+
expect(violations[0].severity).toBe('warning');
|
|
14
|
+
expect(violations[0].message).toBe('Attribute names of HTML elements should be lowercase');
|
|
15
|
+
expect(violations[0].raw).toBe('data-UPPERCASE');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('upper case', async () => {
|
|
19
|
+
const { violations } = await mlRuleTest(rule, '<div data-UPPERCASE="value"></div>', {
|
|
20
|
+
rule: {
|
|
21
|
+
severity: 'error',
|
|
22
|
+
value: 'upper',
|
|
23
|
+
options: null,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
expect(violations[0].severity).toBe('error');
|
|
27
|
+
expect(violations[0].message).toBe('Attribute names of HTML elements must be uppercase');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('upper case', async () => {
|
|
31
|
+
const { violations } = await mlRuleTest(rule, '<div data-uppercase="value"></div>', {
|
|
32
|
+
rule: {
|
|
33
|
+
severity: 'error',
|
|
34
|
+
value: 'upper',
|
|
35
|
+
options: null,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
expect(violations[0].severity).toBe('error');
|
|
39
|
+
expect(violations[0].message).toBe('Attribute names of HTML elements must be uppercase');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('upper case', async () => {
|
|
43
|
+
const { violations } = await mlRuleTest(rule, '<div DATA-UPPERCASE="value"></div>', {
|
|
44
|
+
rule: { severity: 'error', value: 'upper' },
|
|
45
|
+
});
|
|
46
|
+
expect(violations.length).toBe(0);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('svg', async () => {
|
|
50
|
+
const { violations } = await mlRuleTest(rule, '<svg viewBox="0 0 100 100"></svg>');
|
|
51
|
+
expect(violations.length).toBe(0);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// describe('fix', () => {
|
|
56
|
+
// test('upper case', async () => {
|
|
57
|
+
// const { fixedCode } = await mlRuleTest(rule, '<DIV DATA-LOWERCASE></DIV>', undefined, true);
|
|
58
|
+
// expect(fixedCode).toBe('<DIV data-lowercase></DIV>');
|
|
59
|
+
// });
|
|
60
|
+
|
|
61
|
+
// test('upper case', async () => {
|
|
62
|
+
// const { fixedCode } = await mlRuleTest(rule, '<DIV data-lowercase></DIV>', { rule: 'upper' }, true);
|
|
63
|
+
// expect(fixedCode).toBe('<DIV DATA-LOWERCASE></DIV>');
|
|
64
|
+
// });
|
|
65
|
+
// });
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const { mlRuleTest } = require('markuplint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../../lib/case-sensitive-tag-name').default;
|
|
4
|
+
|
|
5
|
+
describe('verify', () => {
|
|
6
|
+
test('lower case', async () => {
|
|
7
|
+
const { violations } = await mlRuleTest(rule, '<div data-lowercase></div>');
|
|
8
|
+
expect(violations).toStrictEqual([]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('upper case', async () => {
|
|
12
|
+
const { violations } = await mlRuleTest(rule, '<DIV data-lowercase></DIV>');
|
|
13
|
+
expect(violations[0].severity).toBe('warning');
|
|
14
|
+
expect(violations[0].message).toBe('Tag names of HTML elements should be lowercase');
|
|
15
|
+
expect(violations[0].raw).toBe('DIV');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('upper case', async () => {
|
|
19
|
+
const { violations } = await mlRuleTest(rule, '<div data-UPPERCASE="value"></div>', {
|
|
20
|
+
rule: {
|
|
21
|
+
severity: 'error',
|
|
22
|
+
value: 'upper',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
expect(violations[0].severity).toBe('error');
|
|
26
|
+
expect(violations[0].message).toBe('Tag names of HTML elements must be uppercase');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('upper case', async () => {
|
|
30
|
+
const { violations } = await mlRuleTest(rule, '<DIV data-uppercase="value"></DIV>', {
|
|
31
|
+
rule: {
|
|
32
|
+
severity: 'error',
|
|
33
|
+
value: 'upper',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
expect(violations.length).toBe(0);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('upper case', async () => {
|
|
40
|
+
const { violations } = await mlRuleTest(rule, '<DIV DATA-UPPERCASE="value"></div>', {
|
|
41
|
+
rule: {
|
|
42
|
+
severity: 'error',
|
|
43
|
+
value: 'upper',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
expect(violations.length).toBe(1);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('upper case', async () => {
|
|
50
|
+
const { violations } = await mlRuleTest(rule, '<div DATA-UPPERCASE="value"></DIV>', {
|
|
51
|
+
rule: {
|
|
52
|
+
severity: 'error',
|
|
53
|
+
value: 'upper',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
expect(violations.length).toBe(1);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('svg', async () => {
|
|
60
|
+
const { violations } = await mlRuleTest(rule, '<svg viewBox="0 0 100 100"><textPath></textPath></svg>');
|
|
61
|
+
expect(violations.length).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('custom elements', async () => {
|
|
65
|
+
const { violations } = await mlRuleTest(rule, '<xxx-hoge>lorem</xxx-hoge>');
|
|
66
|
+
expect(violations.length).toBe(0);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('custom elements', async () => {
|
|
70
|
+
const { violations } = await mlRuleTest(rule, '<XXX-hoge>lorem</XXX-hoge>');
|
|
71
|
+
expect(violations.length).toBe(0);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// describe('fix', () => {
|
|
76
|
+
// test('upper case', async () => {
|
|
77
|
+
// const { fixedCode } = await mlRuleTest(rule, '<DIV data-lowercase></DIV>', undefined, true);
|
|
78
|
+
// expect(fixedCode).toBe('<div data-lowercase></div>');
|
|
79
|
+
// });
|
|
80
|
+
// });
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const { mlRuleTest } = require('markuplint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../../lib/character-reference').default;
|
|
4
|
+
|
|
5
|
+
test('character-reference', async () => {
|
|
6
|
+
const { violations } = await mlRuleTest(rule, '<div id="a"> > < & " \' &</div>');
|
|
7
|
+
expect(violations.length).toBe(4);
|
|
8
|
+
expect(violations[0]).toStrictEqual({
|
|
9
|
+
severity: 'error',
|
|
10
|
+
message: 'Illegal characters must escape in character reference',
|
|
11
|
+
line: 1,
|
|
12
|
+
col: 14,
|
|
13
|
+
raw: '>',
|
|
14
|
+
});
|
|
15
|
+
expect(violations[1].col).toBe(16);
|
|
16
|
+
expect(violations[1].raw).toBe('<');
|
|
17
|
+
expect(violations[2].col).toBe(18);
|
|
18
|
+
expect(violations[2].raw).toBe('&');
|
|
19
|
+
expect(violations[3].col).toBe(20);
|
|
20
|
+
expect(violations[3].raw).toBe('"');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('character-reference', async () => {
|
|
24
|
+
const { violations } = await mlRuleTest(rule, '<img src="path/to?a=b&c=d">');
|
|
25
|
+
expect(violations).toStrictEqual([
|
|
26
|
+
{
|
|
27
|
+
severity: 'error',
|
|
28
|
+
message: 'Illegal characters must escape in character reference',
|
|
29
|
+
line: 1,
|
|
30
|
+
col: 22,
|
|
31
|
+
raw: '&',
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('character-reference', async () => {
|
|
37
|
+
const { violations } = await mlRuleTest(rule, '<script>if (i < 0) console.log("<markuplint>");</script>');
|
|
38
|
+
expect(violations.length).toBe(0);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('in Vue', async () => {
|
|
42
|
+
const { violations } = await mlRuleTest(rule, '<template><div v-if="a < b"></div></template>', {
|
|
43
|
+
parser: {
|
|
44
|
+
'.*': '@markuplint/vue-parser',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
expect(violations.length).toBe(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('in EJS', async () => {
|
|
51
|
+
const { violations } = await mlRuleTest(rule, '<title><%- "title" _%></title>', {
|
|
52
|
+
parser: {
|
|
53
|
+
'.*': '@markuplint/ejs-parser',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
expect(violations.length).toBe(0);
|
|
57
|
+
});
|