@markuplint/rules 5.0.0-alpha.1 → 5.0.0-alpha.2
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/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [5.0.0-alpha.2](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.1...v5.0.0-alpha.2) (2026-02-23)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **rules:** add inline fix callbacks to three rules ([16f9600](https://github.com/markuplint/markuplint/commit/16f9600a1f495046541c195859e218ca6dd61eca))
|
|
11
|
+
|
|
6
12
|
# [5.0.0-alpha.1](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.0...v5.0.0-alpha.1) (2026-02-22)
|
|
7
13
|
|
|
8
14
|
- fix(rules)!: remove complementary from top-level landmark check ([4643651](https://github.com/markuplint/markuplint/commit/4643651d256276ae0473d4756e72277d59398e3d))
|
|
@@ -25,21 +25,23 @@ export default createRule({
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
const quote = attr.startQuote?.raw;
|
|
28
|
-
|
|
28
|
+
const expectedQuote = quoteList[attr.rule.value];
|
|
29
|
+
if (quote !== expectedQuote) {
|
|
29
30
|
report({
|
|
30
31
|
scope: attr,
|
|
31
32
|
message,
|
|
33
|
+
fix: fixer => {
|
|
34
|
+
const edits = [];
|
|
35
|
+
if (attr.startQuote) {
|
|
36
|
+
edits.push(fixer.replaceText(attr.startQuote, expectedQuote));
|
|
37
|
+
}
|
|
38
|
+
if (attr.endQuote) {
|
|
39
|
+
edits.push(fixer.replaceText(attr.endQuote, expectedQuote));
|
|
40
|
+
}
|
|
41
|
+
return edits;
|
|
42
|
+
},
|
|
32
43
|
});
|
|
33
44
|
}
|
|
34
45
|
});
|
|
35
46
|
},
|
|
36
|
-
async fix({ document }) {
|
|
37
|
-
await document.walkOn('Attr', attr => {
|
|
38
|
-
const quote = quoteList[attr.rule.value];
|
|
39
|
-
if (quote && attr.startQuote && attr.startQuote.raw !== quote) {
|
|
40
|
-
attr.startQuote.fix(quote);
|
|
41
|
-
attr.endQuote?.fix(quote);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
},
|
|
45
47
|
});
|
|
@@ -39,44 +39,17 @@ export default createRule({
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
if (deny.test(name)) {
|
|
42
|
+
const nameNode = attr.nameNode;
|
|
43
|
+
const fixedName = value === 'lower' ? name.toLowerCase() : name.toUpperCase();
|
|
42
44
|
report({
|
|
43
45
|
scope: attr,
|
|
44
|
-
line:
|
|
45
|
-
col:
|
|
46
|
-
raw:
|
|
46
|
+
line: nameNode?.startLine,
|
|
47
|
+
col: nameNode?.startCol,
|
|
48
|
+
raw: nameNode?.raw,
|
|
47
49
|
message,
|
|
50
|
+
fix: nameNode ? fixer => fixer.replaceText(nameNode, fixedName) : undefined, // eslint-disable-line @typescript-eslint/strict-boolean-expressions
|
|
48
51
|
});
|
|
49
52
|
}
|
|
50
53
|
});
|
|
51
54
|
},
|
|
52
|
-
async fix({ document }) {
|
|
53
|
-
await document.walkOn('Attr', attr => {
|
|
54
|
-
const el = attr.ownerElement;
|
|
55
|
-
if (el.isForeignElement || el.elementType !== 'html') {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const attrSpecs = getAttrSpecs(el, document.specs);
|
|
59
|
-
const value = attr.rule.value;
|
|
60
|
-
/**
|
|
61
|
-
* Ignore when it has the potential name,
|
|
62
|
-
* it Interprets `tabIndex` to `tabindex` in JSX for example.
|
|
63
|
-
*/
|
|
64
|
-
if (attr.nameNode?.raw !== attr.name) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const name = attr.name;
|
|
68
|
-
if (attrSpecs) {
|
|
69
|
-
const spec = attrSpecs.find(spec => spec.name === name);
|
|
70
|
-
if (spec && spec.caseSensitive) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (value === 'lower') {
|
|
75
|
-
attr.nameNode.fix(name.toLowerCase());
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
attr.nameNode.fix(name.toUpperCase());
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
},
|
|
82
55
|
});
|
|
@@ -22,19 +22,24 @@ export default createRule({
|
|
|
22
22
|
}
|
|
23
23
|
const ms = el.rule.severity === 'error' ? 'must' : 'should';
|
|
24
24
|
const deny = el.rule.value === 'lower' ? /[A-Z]/ : /[a-z]/;
|
|
25
|
+
const fixedName = el.rule.value === 'lower' ? el.rawName.toLowerCase() : el.rawName.toUpperCase();
|
|
25
26
|
const message = t(`{0} ${ms} be {1}`, t('{0} of {1}', 'tag names', 'HTML elements'), `${el.rule.value}case`);
|
|
26
27
|
if (deny.test(el.rawName)) {
|
|
27
28
|
const loc = el.getNameLocation();
|
|
29
|
+
const nameOffset = loc.offset + el.tagOpenChar.length;
|
|
28
30
|
report({
|
|
29
31
|
scope: el,
|
|
30
32
|
message,
|
|
31
33
|
line: loc.line,
|
|
32
34
|
col: loc.col,
|
|
33
35
|
raw: el.rawName,
|
|
36
|
+
fix: fixer => fixer.replaceText({ startOffset: nameOffset, raw: el.rawName }, fixedName),
|
|
34
37
|
});
|
|
35
38
|
}
|
|
36
39
|
const closeTag = el.closeTag;
|
|
37
|
-
if (closeTag && deny.test(closeTag.
|
|
40
|
+
if (closeTag && deny.test(closeTag.rawName)) {
|
|
41
|
+
const closeNameOffset = closeTag.startOffset + el.tagOpenChar.length + '/'.length;
|
|
42
|
+
const fixedCloseName = el.rule.value === 'lower' ? closeTag.rawName.toLowerCase() : closeTag.rawName.toUpperCase();
|
|
38
43
|
report({
|
|
39
44
|
scope: {
|
|
40
45
|
rule: el.rule,
|
|
@@ -43,27 +48,9 @@ export default createRule({
|
|
|
43
48
|
raw: closeTag.raw,
|
|
44
49
|
},
|
|
45
50
|
message,
|
|
51
|
+
fix: fixer => fixer.replaceText({ startOffset: closeNameOffset, raw: closeTag.rawName }, fixedCloseName),
|
|
46
52
|
});
|
|
47
53
|
}
|
|
48
54
|
});
|
|
49
55
|
},
|
|
50
|
-
async fix({ document }) {
|
|
51
|
-
if (document.tagNameCaseSensitive) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
await document.walkOn('Element', el => {
|
|
55
|
-
if (el.isForeignElement || el.elementType !== 'html') {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const deny = el.rule.value === 'lower' ? /[A-Z]/ : /[a-z]/;
|
|
59
|
-
if (deny.test(el.nodeName)) {
|
|
60
|
-
if (el.rule.value === 'lower') {
|
|
61
|
-
el.fixNodeName(el.nodeName.toLowerCase());
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
el.fixNodeName(el.nodeName.toUpperCase());
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
56
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/rules",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.2",
|
|
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>",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@markuplint/html-spec": "5.0.0-alpha.
|
|
31
|
-
"@markuplint/ml-core": "5.0.0-alpha.
|
|
32
|
-
"@markuplint/ml-spec": "5.0.0-alpha.
|
|
33
|
-
"@markuplint/selector": "5.0.0-alpha.
|
|
34
|
-
"@markuplint/shared": "5.0.0-alpha.
|
|
35
|
-
"@markuplint/types": "5.0.0-alpha.
|
|
30
|
+
"@markuplint/html-spec": "5.0.0-alpha.2",
|
|
31
|
+
"@markuplint/ml-core": "5.0.0-alpha.2",
|
|
32
|
+
"@markuplint/ml-spec": "5.0.0-alpha.2",
|
|
33
|
+
"@markuplint/selector": "5.0.0-alpha.2",
|
|
34
|
+
"@markuplint/shared": "5.0.0-alpha.2",
|
|
35
|
+
"@markuplint/types": "5.0.0-alpha.2",
|
|
36
36
|
"@mdn/browser-compat-data": "^7.3.2",
|
|
37
37
|
"@types/debug": "4.1.12",
|
|
38
38
|
"ansi-colors": "4.1.3",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"image-size": "^2.0.2",
|
|
43
43
|
"type-fest": "5.4.4"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "31ccf1e81443ea3f93597d287595211f1823ddcf"
|
|
46
46
|
}
|