@markuplint/rules 3.0.0-dev.25 → 3.0.0-dev.290
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/attr-check.d.ts +3 -2
- package/lib/attr-check.js +42 -38
- package/lib/attr-duplication/index.d.ts +1 -1
- package/lib/attr-duplication/index.js +3 -5
- package/lib/attr-value-quotes/index.d.ts +1 -1
- package/lib/attr-value-quotes/index.js +5 -9
- package/lib/case-sensitive-attr-name/index.d.ts +1 -1
- package/lib/case-sensitive-attr-name/index.js +9 -13
- package/lib/case-sensitive-tag-name/index.d.ts +1 -1
- package/lib/case-sensitive-tag-name/index.js +2 -4
- package/lib/character-reference/index.d.ts +1 -1
- package/lib/character-reference/index.js +7 -9
- package/lib/class-naming/index.d.ts +1 -1
- package/lib/class-naming/index.js +9 -13
- package/lib/create-message.d.ts +3 -2
- package/lib/create-message.js +15 -17
- package/lib/debug.js +2 -6
- 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 +5 -7
- package/lib/disallowed-element/index.d.ts +1 -1
- package/lib/disallowed-element/index.js +2 -4
- package/lib/doctype/index.d.ts +1 -1
- package/lib/doctype/index.js +2 -4
- package/lib/end-tag/index.d.ts +1 -1
- package/lib/end-tag/index.js +5 -8
- package/lib/helpers.d.ts +10 -13
- package/lib/helpers.js +39 -37
- package/lib/id-duplication/index.d.ts +1 -1
- package/lib/id-duplication/index.js +2 -4
- package/lib/index.d.ts +102 -3
- package/lib/index.js +64 -62
- package/lib/ineffective-attr/index.d.ts +1 -1
- package/lib/ineffective-attr/index.js +5 -10
- package/lib/invalid-attr/index.d.ts +25 -5
- package/lib/invalid-attr/index.js +166 -43
- package/lib/label-has-control/index.d.ts +1 -1
- package/lib/label-has-control/index.js +2 -4
- package/lib/landmark-roles/index.d.ts +1 -1
- package/lib/landmark-roles/index.js +10 -9
- package/lib/no-boolean-attr-value/index.d.ts +1 -1
- package/lib/no-boolean-attr-value/index.js +6 -9
- package/lib/no-default-value/index.d.ts +1 -1
- package/lib/no-default-value/index.js +9 -12
- package/lib/no-empty-palpable-content/index.d.ts +1 -1
- package/lib/no-empty-palpable-content/index.js +13 -7
- package/lib/no-hard-code-id/index.d.ts +1 -1
- package/lib/no-hard-code-id/index.js +2 -4
- package/lib/no-refer-to-non-existent-id/index.d.ts +4 -4
- package/lib/no-refer-to-non-existent-id/index.js +79 -23
- package/lib/no-use-event-handler-attr/index.d.ts +1 -1
- package/lib/no-use-event-handler-attr/index.js +4 -6
- package/lib/permitted-contents/choice.d.ts +3 -2
- package/lib/permitted-contents/choice.js +54 -14
- package/lib/permitted-contents/complex-branch.d.ts +3 -2
- package/lib/permitted-contents/complex-branch.js +12 -14
- package/lib/permitted-contents/content-model.d.ts +2 -2
- package/lib/permitted-contents/content-model.js +11 -11
- package/lib/permitted-contents/count-pattern.d.ts +3 -2
- package/lib/permitted-contents/count-pattern.js +76 -74
- package/lib/permitted-contents/debug.browser.js +9 -12
- package/lib/permitted-contents/debug.d.ts +8 -1
- package/lib/permitted-contents/debug.js +12 -13
- package/lib/permitted-contents/index.d.ts +2 -2
- package/lib/permitted-contents/index.js +18 -24
- package/lib/permitted-contents/matches-selector.d.ts +2 -2
- package/lib/permitted-contents/matches-selector.js +17 -20
- package/lib/permitted-contents/order.d.ts +3 -2
- package/lib/permitted-contents/order.js +33 -28
- package/lib/permitted-contents/recursive-branch.d.ts +4 -3
- package/lib/permitted-contents/recursive-branch.js +11 -13
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +1 -1
- package/lib/permitted-contents/represent-transparent-nodes.js +18 -21
- package/lib/permitted-contents/start.d.ts +3 -2
- package/lib/permitted-contents/start.js +16 -22
- package/lib/permitted-contents/transparent.d.ts +2 -2
- package/lib/permitted-contents/transparent.js +6 -9
- package/lib/permitted-contents/types.d.ts +20 -13
- package/lib/permitted-contents/types.js +1 -2
- package/lib/permitted-contents/utils.d.ts +27 -8
- package/lib/permitted-contents/utils.js +164 -65
- package/lib/placeholder-label-option/index.d.ts +2 -0
- package/lib/placeholder-label-option/index.js +84 -0
- package/lib/require-accessible-name/index.d.ts +1 -1
- package/lib/require-accessible-name/index.js +10 -13
- package/lib/require-datetime/index.d.ts +6 -0
- package/lib/require-datetime/index.js +32 -0
- package/lib/require-datetime/types.d.ts +10 -0
- package/lib/require-datetime/types.js +1 -0
- package/lib/require-datetime/utils.d.ts +11 -0
- package/lib/require-datetime/utils.js +130 -0
- package/lib/required-attr/index.d.ts +2 -2
- package/lib/required-attr/index.js +24 -24
- package/lib/required-element/index.d.ts +1 -1
- package/lib/required-element/index.js +3 -5
- package/lib/required-h1/index.d.ts +1 -1
- package/lib/required-h1/index.js +4 -6
- package/lib/use-list/index.d.ts +2 -2
- package/lib/use-list/index.js +7 -9
- package/lib/wai-aria/checkings/abstract-role.d.ts +1 -1
- package/lib/wai-aria/checkings/abstract-role.js +5 -10
- package/lib/wai-aria/checkings/default-value.d.ts +2 -2
- package/lib/wai-aria/checkings/default-value.js +2 -6
- package/lib/wai-aria/checkings/deprecated-props.d.ts +2 -2
- package/lib/wai-aria/checkings/deprecated-props.js +3 -8
- package/lib/wai-aria/checkings/disallowed-prop.d.ts +2 -2
- package/lib/wai-aria/checkings/disallowed-prop.js +27 -8
- package/lib/wai-aria/checkings/implicit-props.d.ts +3 -3
- package/lib/wai-aria/checkings/implicit-props.js +7 -11
- package/lib/wai-aria/checkings/implicit-role.d.ts +1 -1
- package/lib/wai-aria/checkings/implicit-role.js +4 -9
- package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +1 -1
- package/lib/wai-aria/checkings/interaction-in-hidden.js +7 -9
- package/lib/wai-aria/checkings/no-global-prop.d.ts +2 -2
- package/lib/wai-aria/checkings/no-global-prop.js +2 -7
- package/lib/wai-aria/checkings/non-existent-role.d.ts +1 -1
- package/lib/wai-aria/checkings/non-existent-role.js +4 -9
- package/lib/wai-aria/checkings/permitted-roles.d.ts +1 -1
- package/lib/wai-aria/checkings/permitted-roles.js +4 -9
- package/lib/wai-aria/checkings/presentational-children.d.ts +1 -1
- package/lib/wai-aria/checkings/presentational-children.js +7 -10
- package/lib/wai-aria/checkings/required-owned-elements.d.ts +1 -1
- package/lib/wai-aria/checkings/required-owned-elements.js +10 -12
- package/lib/wai-aria/checkings/required-prop.d.ts +2 -2
- package/lib/wai-aria/checkings/required-prop.js +2 -7
- package/lib/wai-aria/checkings/value.d.ts +3 -3
- package/lib/wai-aria/checkings/value.js +7 -11
- package/lib/wai-aria/index.d.ts +2 -2
- package/lib/wai-aria/index.js +38 -39
- package/lib/wai-aria/types.js +1 -2
- package/package.json +21 -14
- package/schema.json +6 -0
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
package/lib/attr-check.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Translator } from '@markuplint/i18n';
|
|
2
2
|
import type { Attribute as AttrSpec, AttributeType } from '@markuplint/ml-spec';
|
|
3
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
3
4
|
type Invalid = {
|
|
4
|
-
invalidType: 'non-existent' | 'invalid-value';
|
|
5
|
+
invalidType: 'non-existent' | 'invalid-value' | 'disallowed-attr';
|
|
5
6
|
message: string;
|
|
6
7
|
loc?: Loc;
|
|
7
8
|
};
|
|
@@ -19,5 +20,5 @@ type Loc = {
|
|
|
19
20
|
* @param spec
|
|
20
21
|
*/
|
|
21
22
|
export declare function attrCheck(t: Translator, name: string, value: string, isCustomRule: boolean, spec?: AttrSpec): Invalid | false;
|
|
22
|
-
export declare function valueCheck(t: Translator, name: string, value: string, type: AttributeType):
|
|
23
|
+
export declare function valueCheck(t: Translator, name: string, value: string, type: ReadonlyDeep<AttributeType>): [string, Loc] | false;
|
|
23
24
|
export {};
|
package/lib/attr-check.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const create_message_1 = require("./create-message");
|
|
6
|
-
const debug_1 = require("./debug");
|
|
1
|
+
import { toNonNullableArrayFromItemOrArray } from '@markuplint/shared';
|
|
2
|
+
import { check } from '@markuplint/types';
|
|
3
|
+
import { createMessageValueExpected } from './create-message.js';
|
|
4
|
+
import { log } from './debug.js';
|
|
7
5
|
/**
|
|
8
6
|
* Use in rules `invalid-attr` and `wai-aria`
|
|
9
7
|
*
|
|
@@ -12,7 +10,7 @@ const debug_1 = require("./debug");
|
|
|
12
10
|
* @param isCustomRule
|
|
13
11
|
* @param spec
|
|
14
12
|
*/
|
|
15
|
-
function attrCheck(t, name, value, isCustomRule, spec) {
|
|
13
|
+
export function attrCheck(t, name, value, isCustomRule, spec) {
|
|
16
14
|
if (!isCustomRule) {
|
|
17
15
|
if (/^data-.+$/.test(name)) {
|
|
18
16
|
// Ignore checking because "data-*" attribute is any type
|
|
@@ -22,10 +20,16 @@ function attrCheck(t, name, value, isCustomRule, spec) {
|
|
|
22
20
|
// Ignore checking because ARIA attributes are check on another rule
|
|
23
21
|
return false;
|
|
24
22
|
}
|
|
23
|
+
// @see https://www.w3.org/TR/adapt/
|
|
24
|
+
// It is an experimental
|
|
25
|
+
if (/^adapt-.+$/.test(name)) {
|
|
26
|
+
// Ignore checking because "adapt-*" attribute is any type
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
// Existence
|
|
27
31
|
if (!spec) {
|
|
28
|
-
|
|
32
|
+
log('The "%s" attribute DOES\'NT EXIST in the spec', name);
|
|
29
33
|
return {
|
|
30
34
|
invalidType: 'non-existent',
|
|
31
35
|
message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed'),
|
|
@@ -33,7 +37,7 @@ function attrCheck(t, name, value, isCustomRule, spec) {
|
|
|
33
37
|
}
|
|
34
38
|
const nameCaseSensitive = /[A-Z]/.test(spec.name);
|
|
35
39
|
if (nameCaseSensitive && name !== spec.name) {
|
|
36
|
-
|
|
40
|
+
log('The "%s" attribute name is unmatched in case-sensitive', name);
|
|
37
41
|
return {
|
|
38
42
|
invalidType: 'non-existent',
|
|
39
43
|
message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
|
|
@@ -41,45 +45,46 @@ function attrCheck(t, name, value, isCustomRule, spec) {
|
|
|
41
45
|
t('Did you mean "{0*}"?', spec.name),
|
|
42
46
|
};
|
|
43
47
|
}
|
|
44
|
-
|
|
48
|
+
if (spec.noUse) {
|
|
49
|
+
return {
|
|
50
|
+
invalidType: 'disallowed-attr',
|
|
51
|
+
message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed'),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const types = toNonNullableArrayFromItemOrArray(spec.type);
|
|
45
55
|
const invalidList = types.map(type => {
|
|
46
|
-
if (!type) {
|
|
47
|
-
(0, debug_1.log)('attrCheck: %o', arguments);
|
|
48
|
-
throw new Error('type is empty in spec');
|
|
49
|
-
}
|
|
50
56
|
const invalid = valueCheck(t, name, value, type);
|
|
51
|
-
if (invalid) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
if (invalid === false) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (typeof invalid === 'string') {
|
|
61
|
+
return {
|
|
62
|
+
invalidType: 'invalid-value',
|
|
63
|
+
message: invalid,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
return {
|
|
68
|
+
invalidType: 'invalid-value',
|
|
69
|
+
message: invalid[0],
|
|
70
|
+
loc: invalid[1],
|
|
71
|
+
};
|
|
65
72
|
}
|
|
66
|
-
return false;
|
|
67
73
|
});
|
|
68
|
-
if (invalidList.some(i =>
|
|
74
|
+
if (invalidList.some(i => i === false)) {
|
|
69
75
|
return false;
|
|
70
76
|
}
|
|
71
77
|
const invalid = invalidList.find(i => i);
|
|
72
|
-
return invalid
|
|
78
|
+
return invalid ?? false;
|
|
73
79
|
}
|
|
74
|
-
|
|
75
|
-
function valueCheck(t, name, value, type) {
|
|
80
|
+
export function valueCheck(t, name, value, type) {
|
|
76
81
|
if (type === 'Boolean') {
|
|
77
82
|
// Valid because an attribute is exist
|
|
78
83
|
return false;
|
|
79
84
|
}
|
|
80
|
-
const matches =
|
|
81
|
-
if (
|
|
82
|
-
|
|
85
|
+
const matches = check(value, type);
|
|
86
|
+
if (log.enabled) {
|
|
87
|
+
log(`Result ([${name}="${value}"]): %O`, { ...matches, type });
|
|
83
88
|
}
|
|
84
89
|
if (!matches.matched) {
|
|
85
90
|
const location = {
|
|
@@ -88,9 +93,8 @@ function valueCheck(t, name, value, type) {
|
|
|
88
93
|
col: matches.column - 1,
|
|
89
94
|
};
|
|
90
95
|
const base = t('the "{0*}" {1}', name, 'attribute');
|
|
91
|
-
const message =
|
|
96
|
+
const message = createMessageValueExpected(t, base, type, matches);
|
|
92
97
|
return [message, location];
|
|
93
98
|
}
|
|
94
99
|
return false;
|
|
95
100
|
}
|
|
96
|
-
exports.valueCheck = valueCheck;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue,
|
|
1
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
async verify({ document, report, t }) {
|
|
6
4
|
const message = t('{0} is {1:c}', t('the {0}', 'attribute name'), 'duplicated');
|
|
7
5
|
await document.walkOn('Element', node => {
|
|
@@ -13,7 +11,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
13
11
|
const attrName = attr.name;
|
|
14
12
|
const name = node.elementType === 'html' ? attrName.toLowerCase() : attrName;
|
|
15
13
|
if (attrNameStack.includes(name)) {
|
|
16
|
-
const scope = attr.nameNode
|
|
14
|
+
const scope = attr.nameNode ?? attr;
|
|
17
15
|
report({
|
|
18
16
|
scope: {
|
|
19
17
|
rule: node.rule,
|
|
@@ -3,5 +3,5 @@ export type Quote = '"' | "'";
|
|
|
3
3
|
export type QuoteMap = {
|
|
4
4
|
[P in Type]: Quote;
|
|
5
5
|
};
|
|
6
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<Type,
|
|
6
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<Type, undefined>>;
|
|
7
7
|
export default _default;
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
4
2
|
const quoteList = {
|
|
5
3
|
double: '"',
|
|
6
4
|
single: "'",
|
|
7
5
|
};
|
|
8
|
-
|
|
6
|
+
export default createRule({
|
|
9
7
|
defaultSeverity: 'warning',
|
|
10
8
|
defaultValue: 'double',
|
|
11
9
|
async verify({ document, report, t }) {
|
|
12
10
|
await document.walkOn('Attr', attr => {
|
|
13
|
-
var _a, _b;
|
|
14
11
|
const message = t('{0} is must {1} on {2}', 'Attribute value', 'quote', `${attr.rule.value} quotation mark`);
|
|
15
|
-
if (attr.isDynamicValue || attr.isDirective || !attr.equal ||
|
|
12
|
+
if (attr.isDynamicValue || attr.isDirective || !attr.equal || attr.equal?.raw === '') {
|
|
16
13
|
return;
|
|
17
14
|
}
|
|
18
|
-
const quote =
|
|
15
|
+
const quote = attr.startQuote?.raw;
|
|
19
16
|
if (quote !== quoteList[attr.rule.value]) {
|
|
20
17
|
report({
|
|
21
18
|
scope: attr,
|
|
@@ -26,12 +23,11 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
26
23
|
},
|
|
27
24
|
async fix({ document }) {
|
|
28
25
|
await document.walkOn('Attr', attr => {
|
|
29
|
-
var _a;
|
|
30
26
|
const quote = quoteList[attr.rule.value];
|
|
31
27
|
if (quote && attr.startQuote && attr.startQuote.raw !== quote) {
|
|
32
28
|
attr.startQuote.fix(quote);
|
|
33
29
|
// TODO: attr.endQuote = new MLToken(quote);
|
|
34
|
-
|
|
30
|
+
attr.endQuote?.fix(quote);
|
|
35
31
|
}
|
|
36
32
|
});
|
|
37
33
|
},
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule, getAttrSpecs } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
defaultSeverity: 'warning',
|
|
6
4
|
defaultValue: 'lower',
|
|
7
5
|
async verify({ document, report, t }) {
|
|
8
6
|
await document.walkOn('Attr', attr => {
|
|
9
|
-
var _a, _b, _c, _d;
|
|
10
7
|
const el = attr.ownerElement;
|
|
11
8
|
if (el.isForeignElement || el.elementType !== 'html') {
|
|
12
9
|
return;
|
|
@@ -16,12 +13,12 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
16
13
|
const deny = value === 'lower' ? /[A-Z]/ : /[a-z]/;
|
|
17
14
|
const cases = value === 'lower' ? 'lower' : 'upper';
|
|
18
15
|
const message = t(`{0} ${ms} be {1}`, t('{0} of {1}', 'attribute names', 'HTML elements'), `${cases}case`);
|
|
19
|
-
const attrSpecs =
|
|
16
|
+
const attrSpecs = getAttrSpecs(el, document.specs);
|
|
20
17
|
/**
|
|
21
18
|
* Ignore when it has the potential name,
|
|
22
19
|
* it Interprets `tabIndex` to `tabindex` in JSX for example.
|
|
23
20
|
*/
|
|
24
|
-
if (
|
|
21
|
+
if (attr.nameNode?.raw !== attr.name) {
|
|
25
22
|
return;
|
|
26
23
|
}
|
|
27
24
|
const name = attr.name;
|
|
@@ -34,9 +31,9 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
34
31
|
if (deny.test(name)) {
|
|
35
32
|
report({
|
|
36
33
|
scope: attr,
|
|
37
|
-
line:
|
|
38
|
-
col:
|
|
39
|
-
raw:
|
|
34
|
+
line: attr.nameNode?.startLine,
|
|
35
|
+
col: attr.nameNode?.startCol,
|
|
36
|
+
raw: attr.nameNode?.raw,
|
|
40
37
|
message,
|
|
41
38
|
});
|
|
42
39
|
}
|
|
@@ -44,18 +41,17 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
44
41
|
},
|
|
45
42
|
async fix({ document }) {
|
|
46
43
|
await document.walkOn('Attr', attr => {
|
|
47
|
-
var _a;
|
|
48
44
|
const el = attr.ownerElement;
|
|
49
45
|
if (el.isForeignElement || el.elementType !== 'html') {
|
|
50
46
|
return;
|
|
51
47
|
}
|
|
52
|
-
const attrSpecs =
|
|
48
|
+
const attrSpecs = getAttrSpecs(el, document.specs);
|
|
53
49
|
const value = attr.rule.value;
|
|
54
50
|
/**
|
|
55
51
|
* Ignore when it has the potential name,
|
|
56
52
|
* it Interprets `tabIndex` to `tabindex` in JSX for example.
|
|
57
53
|
*/
|
|
58
|
-
if (
|
|
54
|
+
if (attr.nameNode?.raw !== attr.name) {
|
|
59
55
|
return;
|
|
60
56
|
}
|
|
61
57
|
const name = attr.name;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
defaultSeverity: 'warning',
|
|
6
4
|
defaultValue: 'lower',
|
|
7
5
|
async verify({ document, report, t }) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { RuleConfigValue } from '@markuplint/ml-config';
|
|
2
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<RuleConfigValue,
|
|
2
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<RuleConfigValue, undefined>>;
|
|
3
3
|
export default _default;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
1
|
+
import { createRule, getLocationFromChars } from '@markuplint/ml-core';
|
|
4
2
|
const defaultChars = ['"', '&', '<', '>'];
|
|
5
3
|
const ignoreParentElement = ['script', 'style'];
|
|
6
|
-
|
|
4
|
+
export default createRule({
|
|
7
5
|
async verify({ document, report, t }) {
|
|
8
6
|
const targetNodes = [];
|
|
9
7
|
await document.walkOn('Text', node => {
|
|
@@ -32,9 +30,9 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
32
30
|
const valueNode = attr.valueNode;
|
|
33
31
|
targetNodes.push({
|
|
34
32
|
scope: node,
|
|
35
|
-
line: valueNode
|
|
36
|
-
col: valueNode
|
|
37
|
-
raw: valueNode
|
|
33
|
+
line: valueNode?.startLine,
|
|
34
|
+
col: valueNode?.startCol,
|
|
35
|
+
raw: valueNode?.raw,
|
|
38
36
|
message,
|
|
39
37
|
});
|
|
40
38
|
}
|
|
@@ -43,8 +41,8 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
43
41
|
if (!('scope' in targetNode && 'line' in targetNode && targetNode.line != null)) {
|
|
44
42
|
continue;
|
|
45
43
|
}
|
|
46
|
-
const escapedText = targetNode.raw.replace(/&(?:[a-z]+|#[0-9]
|
|
47
|
-
|
|
44
|
+
const escapedText = targetNode.raw.replace(/&(?:[a-z]+|#[0-9]+|#x[0-9a-f]+);/gi, $0 => '*'.repeat($0.length));
|
|
45
|
+
getLocationFromChars(defaultChars, escapedText, targetNode.line, targetNode.col).forEach(location => {
|
|
48
46
|
report({
|
|
49
47
|
scope: targetNode.scope,
|
|
50
48
|
message: targetNode.message,
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import { toNoEmptyStringArrayFromStringOrArray } from '@markuplint/shared';
|
|
3
|
+
import { match } from '../helpers.js';
|
|
4
|
+
export default createRule({
|
|
6
5
|
defaultSeverity: 'warning',
|
|
7
6
|
defaultValue: null,
|
|
8
7
|
async verify({ document, report, t }) {
|
|
9
8
|
await document.walkOn('Element', el => {
|
|
10
|
-
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
const classPatterns = (Array.isArray(el.rule.value) ? el.rule.value : [el.rule.value]).filter(className => className && typeof className === 'string');
|
|
9
|
+
const classPatterns = toNoEmptyStringArrayFromStringOrArray(el.rule.value).filter(className => className && typeof className === 'string');
|
|
14
10
|
const attrs = el.getAttributeToken('class');
|
|
15
11
|
for (const attr of attrs) {
|
|
16
12
|
if (attr.isDynamicValue) {
|
|
@@ -22,13 +18,13 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
22
18
|
.map(c => c.trim())
|
|
23
19
|
.filter(c => c);
|
|
24
20
|
for (const className of classList) {
|
|
25
|
-
if (!classPatterns.some(pattern =>
|
|
21
|
+
if (!classPatterns.some(pattern => match(className, pattern))) {
|
|
26
22
|
report({
|
|
27
23
|
scope: attr,
|
|
28
24
|
message: t('{0} is unmatched with the below patterns: {1}', t('the "{0*}" {1}', className, 'class name'), `"${classPatterns.join('", "')}"`),
|
|
29
|
-
line: classAttr
|
|
30
|
-
col: classAttr
|
|
31
|
-
raw: classAttr
|
|
25
|
+
line: classAttr?.startLine,
|
|
26
|
+
col: classAttr?.startCol,
|
|
27
|
+
raw: classAttr?.raw,
|
|
32
28
|
});
|
|
33
29
|
}
|
|
34
30
|
}
|
package/lib/create-message.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Translator } from '@markuplint/i18n';
|
|
2
2
|
import type { AttributeType } from '@markuplint/ml-spec';
|
|
3
3
|
import type { UnmatchedResult } from '@markuplint/types';
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
4
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
5
|
+
export declare function createMessageValueExpected(t: Translator, baseTarget: string, type: ReadonlyDeep<AttributeType>, matches: UnmatchedResult): string;
|
|
6
|
+
export declare function __createMessageValueExpected(t: Translator, baseTarget: string, expected: string | null, matches: Pick<UnmatchedResult, 'partName' | 'reason' | 'raw' | 'candidate' | 'ref' | 'extra' | 'fallbackTo'>): string;
|
package/lib/create-message.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.__createMessageValueExpected = exports.createMessageValueExpected = void 0;
|
|
4
|
-
const types_1 = require("@markuplint/types");
|
|
5
|
-
function createMessageValueExpected(t, baseTarget, type, matches) {
|
|
1
|
+
import { isList, isKeyword, isEnum } from '@markuplint/types';
|
|
2
|
+
export function createMessageValueExpected(t, baseTarget, type, matches) {
|
|
6
3
|
let target = baseTarget;
|
|
7
4
|
let listDescriptionPart;
|
|
8
5
|
let tokenType;
|
|
9
|
-
if (
|
|
6
|
+
if (isList(type)) {
|
|
10
7
|
listDescriptionPart = t('{0} expects {1:c}', target, type.separator === 'space' ? 'space-separated list' : 'comma-separated list');
|
|
11
8
|
tokenType = type.token;
|
|
12
9
|
target = 'the content of the list';
|
|
@@ -20,13 +17,13 @@ function createMessageValueExpected(t, baseTarget, type, matches) {
|
|
|
20
17
|
.join(t('. '));
|
|
21
18
|
return message;
|
|
22
19
|
}
|
|
23
|
-
|
|
24
|
-
function __createMessageValueExpected(t, baseTarget, expected, matches) {
|
|
20
|
+
export function __createMessageValueExpected(t, baseTarget, expected, matches) {
|
|
25
21
|
let target = baseTarget;
|
|
26
22
|
let reasonPart;
|
|
27
23
|
let expectPart;
|
|
28
24
|
let unnecessaryPart;
|
|
29
25
|
let candidatePart;
|
|
26
|
+
let fallbackToPart;
|
|
30
27
|
let expectOrNeed = 'expects';
|
|
31
28
|
if (matches.partName) {
|
|
32
29
|
if (matches.partName === 'the content of the list') {
|
|
@@ -51,7 +48,7 @@ function __createMessageValueExpected(t, baseTarget, expected, matches) {
|
|
|
51
48
|
break;
|
|
52
49
|
}
|
|
53
50
|
case 'extra-token': {
|
|
54
|
-
const token = matches.partName
|
|
51
|
+
const token = matches.partName ?? 'token';
|
|
55
52
|
reasonPart = t('Found {0}', t('extra {0}', token)) + ' ' + t([matches.raw]);
|
|
56
53
|
if (matches.extra) {
|
|
57
54
|
const extra = expectValueToWord(t, matches.extra, 'Any');
|
|
@@ -191,27 +188,28 @@ function __createMessageValueExpected(t, baseTarget, expected, matches) {
|
|
|
191
188
|
if (matches.candidate) {
|
|
192
189
|
candidatePart = t('Did you mean "{0*}"?', matches.candidate);
|
|
193
190
|
}
|
|
194
|
-
|
|
191
|
+
if (matches.fallbackTo) {
|
|
192
|
+
fallbackToPart = t('The user agent will automatically use "{0*}" instead', matches.fallbackTo);
|
|
193
|
+
}
|
|
194
|
+
let message = [reasonPart, unnecessaryPart, expectPart, candidatePart, fallbackToPart].filter(s => s).join(t('. '));
|
|
195
195
|
if (matches.ref) {
|
|
196
196
|
message += ` (${matches.ref})`;
|
|
197
197
|
}
|
|
198
198
|
return message;
|
|
199
199
|
}
|
|
200
|
-
exports.__createMessageValueExpected = __createMessageValueExpected;
|
|
201
200
|
function createExpectedObject(type, matches, t) {
|
|
202
|
-
var _a;
|
|
203
201
|
const expectedObject = [];
|
|
204
|
-
if (
|
|
202
|
+
if (matches.expects && matches.expects.length > 0) {
|
|
205
203
|
expectedObject.push(...matches.expects.map(expect => {
|
|
206
204
|
return expectValueToWord(t, expect, type);
|
|
207
205
|
}));
|
|
208
206
|
}
|
|
209
|
-
else if (
|
|
207
|
+
else if (isKeyword(type)) {
|
|
210
208
|
if (type[0] === '<') {
|
|
211
209
|
expectedObject.push(t('the CSS Syntax "{0}"', type));
|
|
212
210
|
}
|
|
213
211
|
}
|
|
214
|
-
else if (
|
|
212
|
+
else if (isEnum(type)) {
|
|
215
213
|
expectedObject.push(...type.enum);
|
|
216
214
|
}
|
|
217
215
|
else {
|
|
@@ -221,7 +219,7 @@ function createExpectedObject(type, matches, t) {
|
|
|
221
219
|
? null
|
|
222
220
|
: 1 < expectedObject.length
|
|
223
221
|
? t('either {0}', t(expectedObject))
|
|
224
|
-
: expectedObject[0];
|
|
222
|
+
: expectedObject[0] ?? null;
|
|
225
223
|
return expects;
|
|
226
224
|
}
|
|
227
225
|
function expectValueToWord(t, expect, type) {
|
|
@@ -235,7 +233,7 @@ function expectValueToWord(t, expect, type) {
|
|
|
235
233
|
case 'regexp':
|
|
236
234
|
return t('{0} ({1})', 'regular expression', expect.value);
|
|
237
235
|
case 'syntax':
|
|
238
|
-
if (
|
|
236
|
+
if (isKeyword(type) && type[0] === '<') {
|
|
239
237
|
return t('the CSS Syntax "{0}"', expect.value);
|
|
240
238
|
}
|
|
241
239
|
return t('{0} syntax', expect.value);
|
package/lib/debug.js
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.log = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
6
|
-
exports.log = (0, debug_1.default)('markuplint-rules');
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
export const log = debug('ml-rules');
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue,
|
|
1
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule, getAttrSpecs } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
async verify({ document, report, t }) {
|
|
6
4
|
await document.walkOn('Attr', attr => {
|
|
7
|
-
|
|
8
|
-
const attrSpecs = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
|
|
5
|
+
const attrSpecs = getAttrSpecs(attr.ownerElement, document.specs);
|
|
9
6
|
if (!attrSpecs) {
|
|
10
7
|
return;
|
|
11
8
|
}
|
|
@@ -18,9 +15,9 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
18
15
|
const message = t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), attrSpec.obsolete ? 'obsolete' : 'deprecated');
|
|
19
16
|
report({
|
|
20
17
|
scope: attr,
|
|
21
|
-
line:
|
|
22
|
-
col:
|
|
23
|
-
raw:
|
|
18
|
+
line: attr.nameNode?.startLine,
|
|
19
|
+
col: attr.nameNode?.startCol,
|
|
20
|
+
raw: attr.nameNode?.raw,
|
|
24
21
|
message,
|
|
25
22
|
});
|
|
26
23
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue,
|
|
1
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule, getSpec } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
async verify({ document, report, t }) {
|
|
6
4
|
await document.walkOn('Element', el => {
|
|
7
5
|
if (!(el.namespaceURI === 'http://www.w3.org/1999/xhtml' ||
|
|
@@ -9,9 +7,9 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
9
7
|
el.elementType !== 'html') {
|
|
10
8
|
return;
|
|
11
9
|
}
|
|
12
|
-
const spec =
|
|
13
|
-
if (spec && (spec.obsolete || spec.deprecated || spec.nonStandard)) {
|
|
14
|
-
const message = t('{0} is {1:c}', t('the "{0*}" {1}', el.localName, 'element'), spec.deprecated ? 'deprecated' : spec.obsolete ? 'obsolete' : 'non-standard');
|
|
10
|
+
const spec = getSpec(el, document.specs.specs);
|
|
11
|
+
if (spec && (spec.obsolete != null || spec.deprecated || spec.nonStandard)) {
|
|
12
|
+
const message = t('{0} is {1:c}', t('the "{0*}" {1}', el.localName, 'element'), spec.deprecated ? 'deprecated' : spec.obsolete != null ? 'obsolete' : 'non-standard');
|
|
15
13
|
report({
|
|
16
14
|
scope: el,
|
|
17
15
|
message,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<string[],
|
|
1
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<string[], undefined>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
defaultValue: [],
|
|
6
4
|
async verify({ document, report, t }) {
|
|
7
5
|
for (const query of document.rule.value) {
|
package/lib/doctype/index.d.ts
CHANGED
package/lib/doctype/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
exports.default = (0, ml_core_1.createRule)({
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
export default createRule({
|
|
5
3
|
defaultValue: 'always',
|
|
6
4
|
defaultOptions: {
|
|
7
5
|
denyObsoleteType: true,
|
package/lib/end-tag/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@markuplint/ml-core").RuleSeed<boolean,
|
|
1
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
2
2
|
export default _default;
|