Skip to content

Commit 172db70

Browse files
committed
impl
1 parent b7e5e85 commit 172db70

File tree

7 files changed

+64
-20
lines changed

7 files changed

+64
-20
lines changed

docs/rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
| [require-li-container](rules/require-li-container) | Enforce `<li>` to be in `<ul>`, `<ol>` or `<menu>`. ||
3030
| [require-meta-charset](rules/require-meta-charset) | Enforce to use `<meta charset="...">` in `<head>` | |
3131
| [use-baseline](rules/use-baseline) | Enforce the use of baseline features. ||
32+
| [use-standard-html](rules/use-standard-html) | TBD | 🔧 |
3233

3334
## SEO
3435

packages/eslint-plugin/lib/rules/use-standard-html/check-content-model.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const CONTINUE = true;
2929
const MESSAGE_IDS = {
3030
REQUIRED: "required",
3131
NOT_ALLOWED: "notAllowed",
32+
NOT_ALLOWED_DESCENDANT: "notAllowedDescendant",
3233
};
3334

3435
/**
@@ -104,6 +105,7 @@ function checkContentModel(
104105
break;
105106
}
106107
case "either": {
108+
result = EXIT;
107109
break;
108110
}
109111
default: {
@@ -145,8 +147,15 @@ function required(model, context, state, node) {
145147
child = getChild(state);
146148
}
147149
if (!child) {
150+
if (model.contents.has("#text")) {
151+
return EXIT;
152+
}
148153
context.report({
149154
node: node.openStart,
155+
data: {
156+
parent: getDisplayNodeName(node),
157+
child: Array.from(model.contents.keys()).join(","),
158+
},
150159
messageId: MESSAGE_IDS.REQUIRED,
151160
});
152161
return EXIT;
@@ -206,6 +215,29 @@ function zeroOrMore(model, state) {
206215
* @returns {boolean}
207216
*/
208217
function oneOrMore(model, context, state, node) {
218+
if (model.constraints && model.constraints.children) {
219+
const childrenConstraints = Array.from(
220+
model.constraints.children.entries()
221+
);
222+
const required = childrenConstraints.filter(
223+
([, value]) => value.required === true
224+
);
225+
const missings = required.filter(
226+
([name]) => !node.children.some((child) => getNodeName(child) === name)
227+
);
228+
if (missings.length) {
229+
context.report({
230+
messageId: MESSAGE_IDS.REQUIRED,
231+
data: {
232+
parent: getDisplayNodeName(node),
233+
child: missings.map(([name]) => name).join(","),
234+
},
235+
node,
236+
});
237+
return EXIT;
238+
}
239+
}
240+
209241
let child = getChild(state);
210242
if (!child) {
211243
state.childIndex++;

packages/eslint-plugin/lib/rules/use-standard-html/helpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function shouldIgnoreChild(child) {
2424
*/
2525
function getNodeName(node) {
2626
if (isTag(node)) {
27-
return node.name;
27+
return node.name.toLowerCase();
2828
}
2929
if (isText(node)) {
3030
return "#text";

packages/eslint-plugin/lib/rules/use-standard-html/use-standard-html.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ module.exports = {
4040
},
4141
],
4242
messages: {
43-
[MESSAGE_IDS.REQUIRED]: "required",
43+
[MESSAGE_IDS.REQUIRED]:
44+
"Element '{{parent}}' is missing a required instance of child element '{{child}}'",
4445
[MESSAGE_IDS.NOT_ALLOWED]:
4546
"Element '{{child}}' not allowed as child of element '{{parent}}'",
4647
},

packages/eslint-plugin/tests/rules/use-standard-html.test.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ ruleTester.run("use-standard-html", rule, {
2121
code: `<slot></slot>`,
2222
},
2323
{
24-
code: `<html><head></head><body></body></html>`,
24+
code: `<html><head><title></title></head><body></body></html>`,
2525
},
2626
{
2727
code: `<menu><li></li></menu>`,
@@ -60,7 +60,7 @@ ruleTester.run("use-standard-html", rule, {
6060
code: "<custom-element>content</custom-element>",
6161
},
6262
{
63-
code: "<head><style> div {} </style> <script> console.log('hello'); </script></head>",
63+
code: "<head><title></title><style> div {} </style> <script> console.log('hello'); </script></head>",
6464
},
6565
{
6666
code: `
@@ -171,5 +171,14 @@ ruleTester.run("use-standard-html", rule, {
171171
},
172172
],
173173
},
174+
// constraints
175+
{
176+
code: `<address><header></header></address>`,
177+
errors: [
178+
{
179+
messageId: "notAllowed",
180+
},
181+
],
182+
},
174183
],
175184
});

packages/website/src/components/header/header.html

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@
55
flex-direction: column;
66
}
77

8-
.burger > div {
8+
.burger > span {
9+
display: block;
910
height: 2px;
1011
transition: 0.2s ease-out;
1112
z-index: 999;
1213
}
1314

14-
.menuInput:checked ~ .burger > div:nth-child(1) {
15+
.menuInput:checked ~ .burger > span:nth-child(1) {
1516
transform: translateY(6.5px) rotate(45deg);
1617
}
17-
.menuInput:checked ~ .burger > div:nth-child(2) {
18+
.menuInput:checked ~ .burger > span:nth-child(2) {
1819
opacity: 0;
1920
}
20-
.menuInput:checked ~ .burger > div:nth-child(3) {
21+
.menuInput:checked ~ .burger > span:nth-child(3) {
2122
transform: translateY(-6.5px) rotate(-45deg);
2223
}
2324
</style>
@@ -44,11 +45,11 @@
4445
<span
4546
for="menu"
4647
aria-label="menu button"
47-
class="burger flex flex-col justify-between ml-auto h-[21px] w-[21px] px-[1px] py-[3px] [&>div]:h-[2px] [&>div]:w-[18px] [&>div]:bg-black-900 md:hidden hover:cursor-pointer"
48+
class="burger flex flex-col justify-between ml-auto h-[21px] w-[21px] px-[1px] py-[3px] [&>span]:h-[2px] [&>span]:w-[18px] [&>span]:bg-black-900 md:hidden hover:cursor-pointer"
4849
>
49-
<div></div>
50-
<div></div>
51-
<div></div>
50+
<span></span>
51+
<span></span>
52+
<span></span>
5253
</span>
5354
<module href="/components/header/nav.html"></module>
5455
</header>

packages/website/src/components/playground.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
<div class="w-full">
2-
<style>
3-
.CodeMirror {
4-
font-size: 14px;
5-
}
6-
.editor_error {
7-
text-decoration: underline dashed red;
1+
<style>
2+
.CodeMirror {
3+
font-size: 14px;
4+
}
5+
.editor_error {
6+
text-decoration: underline dashed red;
87
}
9-
</style>
8+
</style>
9+
<div class="w-full">
1010
<h1 class="sr-only">Playground</h1>
1111
<div class="flex flex-col mt-3 px-2 w-full ">
1212
<div class="flex" id="language-tabs">

0 commit comments

Comments
 (0)