@markuplint/rules 1.10.4 → 2.0.0-alpha.0.23
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/README.md +21 -20
- package/lib/attr-check.d.ts +16 -0
- package/lib/attr-check.js +498 -0
- package/lib/attr-duplication/index.d.ts +1 -1
- package/lib/attr-duplication/index.js +5 -8
- package/lib/attr-equal-space-after/index.d.ts +1 -1
- package/lib/attr-equal-space-after/index.js +8 -11
- package/lib/attr-equal-space-before/index.d.ts +1 -1
- package/lib/attr-equal-space-before/index.js +8 -11
- package/lib/attr-spacing/index.d.ts +3 -3
- package/lib/attr-spacing/index.js +19 -21
- package/lib/attr-value-quotes/index.d.ts +1 -1
- package/lib/attr-value-quotes/index.js +9 -12
- package/lib/case-sensitive-attr-name/index.d.ts +1 -1
- package/lib/case-sensitive-attr-name/index.js +11 -14
- package/lib/case-sensitive-tag-name/index.d.ts +1 -1
- package/lib/case-sensitive-tag-name/index.js +8 -11
- package/lib/character-reference/index.d.ts +1 -1
- package/lib/character-reference/index.js +15 -11
- package/lib/class-naming/index.d.ts +1 -1
- package/lib/class-naming/index.js +7 -10
- package/lib/deprecated-attr/index.d.ts +1 -1
- package/lib/deprecated-attr/index.js +6 -9
- package/lib/deprecated-element/index.d.ts +1 -1
- package/lib/deprecated-element/index.js +10 -15
- package/lib/doctype/index.d.ts +1 -1
- package/lib/doctype/index.js +16 -25
- package/lib/helpers.d.ts +12 -11
- package/lib/helpers.js +38 -25
- package/lib/id-duplication/index.d.ts +1 -1
- package/lib/id-duplication/index.js +5 -8
- package/lib/indentation/index.d.ts +3 -3
- package/lib/indentation/index.js +81 -116
- package/lib/index.d.ts +45 -24
- package/lib/index.js +42 -42
- package/lib/invalid-attr/index.d.ts +2 -2
- package/lib/invalid-attr/index.js +23 -25
- package/lib/landmark-roles/index.d.ts +3 -3
- package/lib/landmark-roles/index.js +12 -20
- package/lib/permitted-contents/index.d.ts +2 -2
- package/lib/permitted-contents/index.js +63 -45
- package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +2 -2
- package/lib/permitted-contents/permitted-content.spec-to-regexp.js +49 -30
- package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +1 -1
- package/lib/permitted-contents/unfold-content-models-to-tags.js +2 -3
- package/lib/{type-check.d.ts → primitive-check.d.ts} +24 -7
- package/lib/primitive-check.js +109 -0
- package/lib/required-attr/index.d.ts +1 -1
- package/lib/required-attr/index.js +12 -16
- package/lib/required-h1/index.d.ts +3 -3
- package/lib/required-h1/index.js +8 -13
- package/lib/wai-aria/index.d.ts +1 -1
- package/lib/wai-aria/index.js +57 -64
- package/package.json +6 -6
- package/tsconfig.test.json +1 -24
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/type-check.js +0 -321
package/lib/helpers.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Element, RuleConfigValue } from '@markuplint/ml-core';
|
|
3
|
-
|
|
1
|
+
import type { Translator } from '@markuplint/i18n';
|
|
2
|
+
import type { Element, RuleConfigValue } from '@markuplint/ml-core';
|
|
3
|
+
import type { ARIRRoleAttribute, Attribute, MLMLSpec, PermittedRoles } from '@markuplint/ml-spec';
|
|
4
|
+
export declare function getAttrSpecs(nameWithNS: string, { specs, def }: MLMLSpec): Attribute[] | null;
|
|
4
5
|
export declare function attrMatches<T extends RuleConfigValue, R>(node: Element<T, R>, condition: Attribute['condition']): boolean;
|
|
5
6
|
export declare function match(needle: string, pattern: string): boolean;
|
|
6
7
|
/**
|
|
7
8
|
* PotentialCustomElementName
|
|
8
9
|
*
|
|
9
|
-
* @see https://
|
|
10
|
+
* @see https://spec.whatwg.org/multipage/custom-elements.html#prod-potentialcustomelementname
|
|
10
11
|
*
|
|
11
12
|
* > PotentialCustomElementName ::=
|
|
12
13
|
* > [a-z] (PCENChar)* '-' (PCENChar)*
|
|
@@ -19,19 +20,19 @@ export declare function match(needle: string, pattern: string): boolean;
|
|
|
19
20
|
* Originally, it is not possible to define a name including ASCII upper alphas in the custom element, but it is not treated as illegal by the HTML parser.
|
|
20
21
|
*/
|
|
21
22
|
export declare const rePCENChar: string;
|
|
22
|
-
export declare function htmlSpec(
|
|
23
|
-
export declare function isValidAttr(name: string, value: string, isDynamicValue: boolean, node: Element<any, any>, attrSpecs: Attribute[]): false | {
|
|
23
|
+
export declare function htmlSpec(nameWithNS: string): import("@markuplint/ml-spec").ElementSpec | null;
|
|
24
|
+
export declare function isValidAttr(t: Translator, name: string, value: string, isDynamicValue: boolean, node: Element<any, any>, attrSpecs: Attribute[]): false | {
|
|
24
25
|
invalidType: "non-existent" | "invalid-value";
|
|
25
26
|
message: string;
|
|
26
27
|
};
|
|
27
28
|
export declare function ariaSpec(): {
|
|
28
29
|
roles: ARIRRoleAttribute[];
|
|
29
|
-
ariaAttrs: import("
|
|
30
|
+
ariaAttrs: import("@markuplint/ml-spec").ARIAAttribute[];
|
|
30
31
|
};
|
|
31
32
|
export declare function getRoleSpec(roleName: string): {
|
|
32
33
|
name: string;
|
|
33
34
|
isAbstract: boolean;
|
|
34
|
-
statesAndProps: import("
|
|
35
|
+
statesAndProps: import("@markuplint/ml-spec").ARIARoleOwnedPropOrState[];
|
|
35
36
|
superClassRoles: ARIRRoleAttribute[];
|
|
36
37
|
} | null;
|
|
37
38
|
/**
|
|
@@ -66,13 +67,13 @@ export declare function checkAria(attrName: string, currentValue: string, role?:
|
|
|
66
67
|
type: "property" | "state";
|
|
67
68
|
deprecated?: true | undefined;
|
|
68
69
|
isGlobal?: true | undefined;
|
|
69
|
-
value: import("
|
|
70
|
+
value: import("@markuplint/ml-spec").ARIAAttributeValue;
|
|
70
71
|
conditionalValue?: {
|
|
71
72
|
role: string[];
|
|
72
|
-
value: import("
|
|
73
|
+
value: import("@markuplint/ml-spec").ARIAAttributeValue;
|
|
73
74
|
}[] | undefined;
|
|
74
75
|
enum: string[];
|
|
75
76
|
defaultValue?: string | undefined;
|
|
76
|
-
equivalentHtmlAttrs?: import("
|
|
77
|
+
equivalentHtmlAttrs?: import("@markuplint/ml-spec").EquivalentHtmlAttr[] | undefined;
|
|
77
78
|
valueDescriptions?: Record<string, string> | undefined;
|
|
78
79
|
};
|
package/lib/helpers.js
CHANGED
|
@@ -1,31 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.checkAria = exports.checkAriaValue = exports.getComputedRole = exports.getImplicitRole = exports.getPermittedRoles = exports.getRoleSpec = exports.ariaSpec = exports.isValidAttr = exports.htmlSpec = exports.rePCENChar = exports.match = exports.attrMatches = exports.getAttrSpecs = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
tag = tag.toLowerCase();
|
|
9
|
-
const spec = specs.find(spec => spec.name === tag);
|
|
4
|
+
const html_spec_1 = require("@markuplint/html-spec");
|
|
5
|
+
const attr_check_1 = require("./attr-check");
|
|
6
|
+
function getAttrSpecs(nameWithNS, { specs, def }) {
|
|
7
|
+
const spec = specs.find(spec => spec.name === nameWithNS);
|
|
10
8
|
if (!spec) {
|
|
11
9
|
return null;
|
|
12
10
|
}
|
|
13
|
-
const
|
|
11
|
+
const globalAttrs = def['#globalAttrs'];
|
|
14
12
|
const attrs = [];
|
|
15
|
-
if (
|
|
16
|
-
|
|
13
|
+
if (!/[a-z]:[a-z]/i.test(nameWithNS)) {
|
|
14
|
+
// It's HTML tag
|
|
15
|
+
const hasGlobalAttr = spec.attributes.some(attr => attr === '#globalAttrs');
|
|
16
|
+
if (hasGlobalAttr) {
|
|
17
|
+
attrs.push(...(globalAttrs['#HTMLGlobalAttrs'] || []));
|
|
18
|
+
}
|
|
17
19
|
}
|
|
18
20
|
for (const attr of spec.attributes) {
|
|
19
21
|
if (typeof attr === 'string') {
|
|
22
|
+
const globalAttr = globalAttrs[attr];
|
|
23
|
+
if (!globalAttr) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
attrs.push(...globalAttr);
|
|
20
27
|
continue;
|
|
21
28
|
}
|
|
22
29
|
const definedIndex = attrs.findIndex(a => a.name === attr.name);
|
|
23
30
|
if (definedIndex !== -1) {
|
|
24
|
-
attrs[definedIndex] =
|
|
31
|
+
attrs[definedIndex] = {
|
|
32
|
+
...attrs[definedIndex],
|
|
33
|
+
...attr,
|
|
34
|
+
};
|
|
25
35
|
continue;
|
|
26
36
|
}
|
|
27
37
|
attrs.push(attr);
|
|
28
38
|
}
|
|
39
|
+
attrs.push(...(globalAttrs['#extends'] || []));
|
|
29
40
|
return attrs;
|
|
30
41
|
}
|
|
31
42
|
exports.getAttrSpecs = getAttrSpecs;
|
|
@@ -34,11 +45,11 @@ function attrMatches(node, condition) {
|
|
|
34
45
|
return true;
|
|
35
46
|
}
|
|
36
47
|
let matched = false;
|
|
37
|
-
if (condition.self) {
|
|
48
|
+
if ('self' in condition && condition.self) {
|
|
38
49
|
const condSelector = Array.isArray(condition.self) ? condition.self.join(',') : condition.self;
|
|
39
50
|
matched = node.matches(condSelector);
|
|
40
51
|
}
|
|
41
|
-
if (condition.ancestor) {
|
|
52
|
+
if ('ancestor' in condition && condition.ancestor) {
|
|
42
53
|
let _node = node.parentNode;
|
|
43
54
|
while (_node) {
|
|
44
55
|
if (_node.type === 'Element') {
|
|
@@ -66,7 +77,7 @@ exports.match = match;
|
|
|
66
77
|
/**
|
|
67
78
|
* PotentialCustomElementName
|
|
68
79
|
*
|
|
69
|
-
* @see https://
|
|
80
|
+
* @see https://spec.whatwg.org/multipage/custom-elements.html#prod-potentialcustomelementname
|
|
70
81
|
*
|
|
71
82
|
* > PotentialCustomElementName ::=
|
|
72
83
|
* > [a-z] (PCENChar)* '-' (PCENChar)*
|
|
@@ -98,20 +109,19 @@ exports.rePCENChar = [
|
|
|
98
109
|
'[\uFDF0-\uFFFD]',
|
|
99
110
|
'[\uD800-\uDBFF][\uDC00-\uDFFF]',
|
|
100
111
|
].join('|');
|
|
101
|
-
function htmlSpec(
|
|
102
|
-
|
|
103
|
-
const spec = html_spec_1.default.specs.find(spec => spec.name === tag);
|
|
112
|
+
function htmlSpec(nameWithNS) {
|
|
113
|
+
const spec = html_spec_1.specs.find(spec => spec.name === nameWithNS);
|
|
104
114
|
return spec || null;
|
|
105
115
|
}
|
|
106
116
|
exports.htmlSpec = htmlSpec;
|
|
107
|
-
function isValidAttr(name, value, isDynamicValue, node, attrSpecs) {
|
|
117
|
+
function isValidAttr(t, name, value, isDynamicValue, node, attrSpecs) {
|
|
108
118
|
let invalid = false;
|
|
109
119
|
const spec = attrSpecs.find(s => s.name === name);
|
|
110
|
-
invalid =
|
|
120
|
+
invalid = (0, attr_check_1.attrCheck)(t, name, value, false, spec);
|
|
111
121
|
if (!invalid && spec && spec.condition && !node.hasSpreadAttr && !attrMatches(node, spec.condition)) {
|
|
112
122
|
invalid = {
|
|
113
123
|
invalidType: 'non-existent',
|
|
114
|
-
message:
|
|
124
|
+
message: t('{0} is {1}', t('the "{0}" {1}', name, 'attribute'), 'disallowed'),
|
|
115
125
|
};
|
|
116
126
|
}
|
|
117
127
|
if (invalid && invalid.invalidType === 'invalid-value' && isDynamicValue) {
|
|
@@ -121,8 +131,8 @@ function isValidAttr(name, value, isDynamicValue, node, attrSpecs) {
|
|
|
121
131
|
}
|
|
122
132
|
exports.isValidAttr = isValidAttr;
|
|
123
133
|
function ariaSpec() {
|
|
124
|
-
const roles = html_spec_1.
|
|
125
|
-
const ariaAttrs = html_spec_1.
|
|
134
|
+
const roles = html_spec_1.def['#roles'];
|
|
135
|
+
const ariaAttrs = html_spec_1.def['#ariaAttrs'];
|
|
126
136
|
return {
|
|
127
137
|
roles,
|
|
128
138
|
ariaAttrs,
|
|
@@ -144,7 +154,7 @@ function getRoleSpec(roleName) {
|
|
|
144
154
|
}
|
|
145
155
|
exports.getRoleSpec = getRoleSpec;
|
|
146
156
|
function getRoleByName(roleName) {
|
|
147
|
-
const roles = html_spec_1.
|
|
157
|
+
const roles = html_spec_1.def['#roles'];
|
|
148
158
|
const role = roles.find(r => r.name === roleName);
|
|
149
159
|
return role;
|
|
150
160
|
}
|
|
@@ -282,7 +292,7 @@ function checkAriaValue(type, value, tokenEnum) {
|
|
|
282
292
|
}
|
|
283
293
|
exports.checkAriaValue = checkAriaValue;
|
|
284
294
|
function checkAria(attrName, currentValue, role) {
|
|
285
|
-
const ariaAttrs = html_spec_1.
|
|
295
|
+
const ariaAttrs = html_spec_1.def['#ariaAttrs'];
|
|
286
296
|
const aria = ariaAttrs.find(a => a.name === attrName);
|
|
287
297
|
if (!aria) {
|
|
288
298
|
return {
|
|
@@ -301,7 +311,10 @@ function checkAria(attrName, currentValue, role) {
|
|
|
301
311
|
}
|
|
302
312
|
}
|
|
303
313
|
const isValid = checkAriaValue(valueType, currentValue, aria.enum);
|
|
304
|
-
return
|
|
305
|
-
|
|
314
|
+
return {
|
|
315
|
+
...aria,
|
|
316
|
+
currentValue,
|
|
317
|
+
isValid,
|
|
318
|
+
};
|
|
306
319
|
}
|
|
307
320
|
exports.checkAria = checkAria;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@markuplint/ml-core").
|
|
1
|
+
declare const _default: import("@markuplint/ml-core").RuleSeed<null, null>;
|
|
2
2
|
export default _default;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = ml_core_1.createRule({
|
|
5
|
-
name: 'id-duplication',
|
|
4
|
+
exports.default = (0, ml_core_1.createRule)({
|
|
6
5
|
defaultValue: null,
|
|
7
6
|
defaultOptions: null,
|
|
8
|
-
async verify(document,
|
|
9
|
-
const
|
|
10
|
-
const message = translate('Duplicate {0}', 'attribute id value');
|
|
7
|
+
async verify({ document, report, t }) {
|
|
8
|
+
const message = t('{0} is {1:c}', t('{0} of {1}', t('the {0}', 'value'), t('the "{0}" {1}', 'id', 'attribute')), 'duplicated');
|
|
11
9
|
const idStack = [];
|
|
12
10
|
await document.walkOn('Element', async (node) => {
|
|
13
11
|
const idAttrs = node.getAttributeToken('id');
|
|
@@ -19,8 +17,8 @@ exports.default = ml_core_1.createRule({
|
|
|
19
17
|
}
|
|
20
18
|
const id = idAttr.getValue();
|
|
21
19
|
if (idStack.includes(id.raw)) {
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
report({
|
|
21
|
+
scope: node,
|
|
24
22
|
message,
|
|
25
23
|
line: idAttr.startLine,
|
|
26
24
|
col: idAttr.startCol,
|
|
@@ -30,6 +28,5 @@ exports.default = ml_core_1.createRule({
|
|
|
30
28
|
idStack.push(id.raw);
|
|
31
29
|
}
|
|
32
30
|
});
|
|
33
|
-
return reports;
|
|
34
31
|
},
|
|
35
32
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare type Value = 'tab' | number;
|
|
2
2
|
export interface IndentationOptions {
|
|
3
|
-
alignment
|
|
4
|
-
'indent-nested-nodes'
|
|
3
|
+
alignment?: boolean;
|
|
4
|
+
'indent-nested-nodes'?: boolean | 'always' | 'never';
|
|
5
5
|
}
|
|
6
|
-
declare const _default: import("@markuplint/ml-core").
|
|
6
|
+
declare const _default: import("@markuplint/ml-core").RuleSeed<Value, IndentationOptions>;
|
|
7
7
|
export default _default;
|
package/lib/indentation/index.js
CHANGED
|
@@ -1,47 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = ml_core_1.createRule({
|
|
5
|
-
|
|
6
|
-
defaultLevel: 'warning',
|
|
4
|
+
exports.default = (0, ml_core_1.createRule)({
|
|
5
|
+
defaultServerity: 'warning',
|
|
7
6
|
defaultValue: 2,
|
|
8
7
|
defaultOptions: {
|
|
9
8
|
alignment: true,
|
|
10
9
|
'indent-nested-nodes': true,
|
|
11
10
|
},
|
|
12
|
-
async verify(
|
|
13
|
-
|
|
14
|
-
await document.walk(async (node) => {
|
|
11
|
+
async verify(context) {
|
|
12
|
+
await context.document.walk(async (node) => {
|
|
15
13
|
if (node.rule.disabled) {
|
|
16
14
|
return;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
if (
|
|
16
|
+
const indent = (0, ml_core_1.getIndent)(node);
|
|
17
|
+
if (indent) {
|
|
20
18
|
/**
|
|
21
19
|
* Validate indent type and length.
|
|
22
20
|
*/
|
|
23
|
-
if (
|
|
21
|
+
if (indent.type !== 'none') {
|
|
24
22
|
const ms = node.rule.severity === 'error' ? 'must' : 'should';
|
|
25
23
|
let spec = null;
|
|
26
|
-
if (node.rule.value === 'tab' &&
|
|
24
|
+
if (node.rule.value === 'tab' && indent.type !== 'tab') {
|
|
27
25
|
spec = 'tab';
|
|
28
26
|
}
|
|
29
|
-
else if (typeof node.rule.value === 'number' &&
|
|
27
|
+
else if (typeof node.rule.value === 'number' && indent.type !== 'space') {
|
|
30
28
|
spec = 'space';
|
|
31
29
|
}
|
|
32
30
|
else if (typeof node.rule.value === 'number' &&
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
spec = translate('{0} width spaces', `${node.rule.value}`);
|
|
31
|
+
indent.type === 'space' &&
|
|
32
|
+
indent.width % node.rule.value) {
|
|
33
|
+
spec = context.translate('{0} width spaces', `${node.rule.value}`);
|
|
36
34
|
}
|
|
37
35
|
if (spec) {
|
|
38
|
-
const message = translate(`{0} ${ms} be {1}`, 'Indentation', spec);
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const message = context.translate(`{0} ${ms} be {1}`, 'Indentation', spec);
|
|
37
|
+
context.report({
|
|
38
|
+
scope: node,
|
|
41
39
|
message,
|
|
42
|
-
line:
|
|
40
|
+
line: indent.line,
|
|
43
41
|
col: 1,
|
|
44
|
-
raw:
|
|
42
|
+
raw: indent.raw,
|
|
45
43
|
});
|
|
46
44
|
return;
|
|
47
45
|
}
|
|
@@ -55,41 +53,32 @@ exports.default = ml_core_1.createRule({
|
|
|
55
53
|
}
|
|
56
54
|
const parent = node.syntaxicalParentNode;
|
|
57
55
|
if (parent) {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
56
|
+
const parentIndent = (0, ml_core_1.getIndent)(parent);
|
|
57
|
+
const parentIndentWidth = parentIndent ? parentIndent.width : 0;
|
|
58
|
+
const childIndentWidth = indent.width;
|
|
60
59
|
const expectedWidth = node.rule.value === 'tab' ? 1 : node.rule.value;
|
|
61
60
|
const diff = childIndentWidth - parentIndentWidth;
|
|
62
|
-
// console.log({
|
|
63
|
-
// [parent.raw]: parent.indentation ? parent.indentation.width : 0,
|
|
64
|
-
// [node.raw]: node.indentation.width,
|
|
65
|
-
// rule: node.rule,
|
|
66
|
-
// parentIndentWidth,
|
|
67
|
-
// childIndentWidth,
|
|
68
|
-
// expectedWidth,
|
|
69
|
-
// diff,
|
|
70
|
-
// nested,
|
|
71
|
-
// });
|
|
72
61
|
if (nested === 'never') {
|
|
73
62
|
if (diff !== 0) {
|
|
74
|
-
const message = translate(diff < 1 ? 'Should increase indentation' : 'Should decrease indentation');
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
const message = context.translate(diff < 1 ? 'Should increase indentation' : 'Should decrease indentation');
|
|
64
|
+
context.report({
|
|
65
|
+
scope: node,
|
|
77
66
|
message,
|
|
78
|
-
line:
|
|
67
|
+
line: indent.line,
|
|
79
68
|
col: 1,
|
|
80
|
-
raw:
|
|
69
|
+
raw: indent.raw,
|
|
81
70
|
});
|
|
82
71
|
}
|
|
83
72
|
}
|
|
84
73
|
else {
|
|
85
74
|
if (diff !== expectedWidth) {
|
|
86
|
-
const message = translate(diff < 1 ? 'Should increase indentation' : 'Should decrease indentation');
|
|
87
|
-
|
|
88
|
-
|
|
75
|
+
const message = context.translate(diff < 1 ? 'Should increase indentation' : 'Should decrease indentation');
|
|
76
|
+
context.report({
|
|
77
|
+
scope: node,
|
|
89
78
|
message,
|
|
90
|
-
line:
|
|
79
|
+
line: indent.line,
|
|
91
80
|
col: 1,
|
|
92
|
-
raw:
|
|
81
|
+
raw: indent.raw,
|
|
93
82
|
});
|
|
94
83
|
}
|
|
95
84
|
}
|
|
@@ -104,63 +93,53 @@ exports.default = ml_core_1.createRule({
|
|
|
104
93
|
if (!closeTag.rule.option.alignment) {
|
|
105
94
|
return;
|
|
106
95
|
}
|
|
107
|
-
|
|
96
|
+
const closeTagIndent = (0, ml_core_1.getIndent)(closeTag);
|
|
97
|
+
if (!closeTagIndent) {
|
|
108
98
|
return;
|
|
109
99
|
}
|
|
110
100
|
if (startTag.endLine === closeTag.endLine) {
|
|
111
101
|
return;
|
|
112
102
|
}
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
// [`${startTag}`]: startTagIndentationWidth,
|
|
117
|
-
// [`${closeTag}`]: endTagIndentationWidth,
|
|
118
|
-
// });
|
|
103
|
+
const startTagIndent = (0, ml_core_1.getIndent)(startTag);
|
|
104
|
+
const endTagIndentationWidth = closeTagIndent ? closeTagIndent.width : 0;
|
|
105
|
+
const startTagIndentationWidth = startTagIndent ? startTagIndent.width : 0;
|
|
119
106
|
if (startTagIndentationWidth !== endTagIndentationWidth) {
|
|
120
|
-
const message = translate('Start tag and end tag indentation should align');
|
|
121
|
-
|
|
122
|
-
|
|
107
|
+
const message = context.translate('Start tag and end tag indentation should align');
|
|
108
|
+
context.report({
|
|
109
|
+
scope: closeTag,
|
|
123
110
|
message,
|
|
124
|
-
line:
|
|
111
|
+
line: closeTagIndent ? closeTagIndent.line : closeTag.startLine,
|
|
125
112
|
col: 1,
|
|
126
|
-
raw:
|
|
113
|
+
raw: closeTagIndent ? closeTagIndent.raw : '',
|
|
127
114
|
});
|
|
128
115
|
}
|
|
129
116
|
}
|
|
130
117
|
});
|
|
131
|
-
return reports;
|
|
132
118
|
},
|
|
133
|
-
async fix(document) {
|
|
119
|
+
async fix({ document }) {
|
|
134
120
|
/**
|
|
135
121
|
* Validate indent type and length.
|
|
136
122
|
*/
|
|
137
123
|
await document.walk(async (node) => {
|
|
138
|
-
|
|
139
|
-
|
|
124
|
+
const indent = (0, ml_core_1.getIndent)(node);
|
|
125
|
+
if (!node.rule.disabled && indent) {
|
|
126
|
+
if (indent.type !== 'none') {
|
|
140
127
|
const spec = node.rule.value === 'tab' ? '\t' : ' ';
|
|
141
128
|
const baseWidth = node.rule.value === 'tab' ? 4 : node.rule.value;
|
|
142
129
|
let width;
|
|
143
130
|
if (node.rule.value === 'tab') {
|
|
144
|
-
width =
|
|
145
|
-
node.indentation.type === 'tab'
|
|
146
|
-
? node.indentation.width
|
|
147
|
-
: Math.ceil(node.indentation.width / baseWidth);
|
|
131
|
+
width = indent.type === 'tab' ? indent.width : Math.ceil(indent.width / baseWidth);
|
|
148
132
|
}
|
|
149
133
|
else {
|
|
150
134
|
width =
|
|
151
|
-
|
|
152
|
-
?
|
|
153
|
-
: Math.ceil(
|
|
135
|
+
indent.type === 'tab'
|
|
136
|
+
? indent.width * baseWidth
|
|
137
|
+
: Math.ceil(indent.width / baseWidth) * baseWidth;
|
|
154
138
|
}
|
|
155
|
-
const raw =
|
|
139
|
+
const raw = indent.raw;
|
|
156
140
|
const fixed = spec.repeat(width);
|
|
157
|
-
// console.log({spec, width});
|
|
158
141
|
if (raw !== fixed) {
|
|
159
|
-
|
|
160
|
-
// raw: space(raw),
|
|
161
|
-
// fix: space(fixed),
|
|
162
|
-
// });
|
|
163
|
-
node.indentation.fix(fixed);
|
|
142
|
+
indent.fix(fixed);
|
|
164
143
|
}
|
|
165
144
|
}
|
|
166
145
|
}
|
|
@@ -169,7 +148,8 @@ exports.default = ml_core_1.createRule({
|
|
|
169
148
|
if (node.rule.disabled) {
|
|
170
149
|
return;
|
|
171
150
|
}
|
|
172
|
-
|
|
151
|
+
const indent = (0, ml_core_1.getIndent)(node);
|
|
152
|
+
if (indent) {
|
|
173
153
|
/**
|
|
174
154
|
* Validate nested parent-children nodes.
|
|
175
155
|
*/
|
|
@@ -177,37 +157,28 @@ exports.default = ml_core_1.createRule({
|
|
|
177
157
|
if (!nested) {
|
|
178
158
|
return;
|
|
179
159
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// const raw = node.indentation.raw;
|
|
203
|
-
const fixed = (node.rule.value === 'tab' ? '\t' : ' ').repeat(parentIndentWidth + expectedWidth);
|
|
204
|
-
// console.log('step2-B', {
|
|
205
|
-
// raw: space(raw),
|
|
206
|
-
// fix: space(fixed),
|
|
207
|
-
// });
|
|
208
|
-
node.indentation.fix(fixed);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
160
|
+
const parent = node.syntaxicalParentNode;
|
|
161
|
+
if (!parent) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const parentIndent = (0, ml_core_1.getIndent)(parent);
|
|
165
|
+
if (!parentIndent) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const parentIndentWidth = parentIndent.width;
|
|
169
|
+
const childIndentWidth = indent.width;
|
|
170
|
+
const expectedWidth = node.rule.value === 'tab' ? 1 : node.rule.value;
|
|
171
|
+
const diff = childIndentWidth - parentIndentWidth;
|
|
172
|
+
if (nested === 'never') {
|
|
173
|
+
if (diff !== 0) {
|
|
174
|
+
const fixed = parentIndent.raw;
|
|
175
|
+
indent.fix(fixed);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
if (diff !== expectedWidth) {
|
|
180
|
+
const fixed = (node.rule.value === 'tab' ? '\t' : ' ').repeat(parentIndentWidth + expectedWidth);
|
|
181
|
+
indent.fix(fixed);
|
|
211
182
|
}
|
|
212
183
|
}
|
|
213
184
|
}
|
|
@@ -222,22 +193,16 @@ exports.default = ml_core_1.createRule({
|
|
|
222
193
|
if (!endTag.rule.option.alignment) {
|
|
223
194
|
return;
|
|
224
195
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
196
|
+
const endTagIndent = (0, ml_core_1.getIndent)(endTag);
|
|
197
|
+
const startTagIndent = (0, ml_core_1.getIndent)(endTag.startTag);
|
|
198
|
+
if (endTagIndent && startTagIndent) {
|
|
199
|
+
const endTagIndentationWidth = endTagIndent.width;
|
|
200
|
+
const startTagIndentationWidth = startTagIndent.width;
|
|
228
201
|
if (startTagIndentationWidth !== endTagIndentationWidth) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
// console.log('step3', {
|
|
232
|
-
// raw: space(raw),
|
|
233
|
-
// fix: space(fixed),
|
|
234
|
-
// });
|
|
235
|
-
endTag.indentation.fix(fixed);
|
|
202
|
+
const fixed = startTagIndent.raw;
|
|
203
|
+
endTagIndent.fix(fixed);
|
|
236
204
|
}
|
|
237
205
|
}
|
|
238
206
|
});
|
|
239
207
|
},
|
|
240
208
|
});
|
|
241
|
-
// function space(str: string) {
|
|
242
|
-
// return str.replace(/ /g, $0 => '•').replace(/\t/g, $0 => '→ ');
|
|
243
|
-
// }
|
package/lib/index.d.ts
CHANGED
|
@@ -1,25 +1,46 @@
|
|
|
1
|
-
declare const _default:
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
declare const _default: {
|
|
2
|
+
'attr-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<null, null>;
|
|
3
|
+
'attr-equal-space-after': import("packages/@markuplint/ml-core/lib").RuleSeed<"always" | "never" | "always-single-line" | "never-single-line", null>;
|
|
4
|
+
'attr-equal-space-before': import("packages/@markuplint/ml-core/lib").RuleSeed<"always" | "never" | "always-single-line" | "never-single-line", null>;
|
|
5
|
+
'attr-spacing': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./attr-spacing").AttrSpasingOptions>;
|
|
6
|
+
'attr-value-quotes': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./attr-value-quotes").Type, null>;
|
|
7
|
+
'case-sensitive-attr-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-attr-name").Value, null>;
|
|
8
|
+
'case-sensitive-tag-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-tag-name").Value, null>;
|
|
9
|
+
'character-reference': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, null>;
|
|
10
|
+
'class-naming': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./class-naming").Value, null>;
|
|
11
|
+
'deprecated-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<null, null>;
|
|
12
|
+
'deprecated-element': import("packages/@markuplint/ml-core/lib").RuleSeed<null, null>;
|
|
13
|
+
doctype: import("packages/@markuplint/ml-core/lib").RuleSeed<"always", {
|
|
14
|
+
denyObsolateType: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
'id-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<null, null>;
|
|
17
|
+
indentation: import("packages/@markuplint/ml-core/lib").RuleSeed<import("./indentation").Value, import("./indentation").IndentationOptions>;
|
|
18
|
+
'invalid-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<true, {
|
|
19
|
+
attrs?: Record<string, {
|
|
20
|
+
enum: string[];
|
|
21
|
+
} | {
|
|
22
|
+
pattern: string;
|
|
23
|
+
} | {
|
|
24
|
+
type: import("packages/@markuplint/ml-spec/lib").AttributeType;
|
|
25
|
+
}> | undefined;
|
|
26
|
+
ignoreAttrNamePrefix?: string | string[] | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
'landmark-roles': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
|
|
29
|
+
ignoreRoles?: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[] | undefined;
|
|
30
|
+
labelEachArea?: boolean | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
'permitted-contents': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-spec/lib").PermittedStructuresSchema[], {
|
|
33
|
+
ignoreHasMutableChildren: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
'required-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<string | string[], null>;
|
|
36
|
+
'required-h1': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./required-h1").RequiredH1Options>;
|
|
37
|
+
'wai-aria': import("packages/@markuplint/ml-core/lib").RuleSeed<true, {
|
|
38
|
+
checkingValue?: boolean | undefined;
|
|
39
|
+
checkingDeprecatedProps?: boolean | undefined;
|
|
40
|
+
permittedAriaRoles?: boolean | undefined;
|
|
41
|
+
disallowSetImplicitRole?: boolean | undefined;
|
|
42
|
+
disallowSetImplicitProps?: boolean | undefined;
|
|
43
|
+
disallowDefaultValue?: boolean | undefined;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
25
46
|
export default _default;
|