Skip to content

Commit

Permalink
feat: add lowercase
Browse files Browse the repository at this point in the history
  • Loading branch information
yeonjuan committed Nov 18, 2023
1 parent 32ebe14 commit c226d51
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 0 deletions.
62 changes: 62 additions & 0 deletions docs/rules/lowercase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
id: lowercase
title: "lowercase"
---

# lowercase

Enforce to use lowercase for tag and attribute names.

## How to use

.eslintrc.js

```js
module.exports = {
rules: {
"@html-eslint/lowercase": "error",
},
};
```

## Rule Details

Examples of **incorrect** code for this rule:

<!-- prettier-ignore -->
```html
<Div></Div>
```

<!-- prettier-ignore -->
```html
<div ID="foo"></div>
```

<!-- prettier-ignore -->
```html
<SCRIPT></SCRIPT>
```

<!-- prettier-ignore -->
```html
<sTyle></sTyle>
```

Examples of **correct** code for this rule:

```html
<div></div>
```

```html
<div id="foo"></div>
```

```html
<script></script>
```

```html
<style></style>
```
2 changes: 2 additions & 0 deletions packages/eslint-plugin/lib/rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const noTrailingSpaces = require("./no-trailing-spaces");
const requireAttrs = require("./require-attrs");
const noRestrictedAttrValues = require("./no-restricted-attr-values");
const noScriptStyleType = require("./no-script-style-type");
const lowercase = require("./lowercase");

module.exports = {
"require-lang": requireLang,
Expand Down Expand Up @@ -68,4 +69,5 @@ module.exports = {
"no-trailing-spaces": noTrailingSpaces,
"no-restricted-attr-values": noRestrictedAttrValues,
"no-script-style-type": noScriptStyleType,
lowercase: lowercase,
};
93 changes: 93 additions & 0 deletions packages/eslint-plugin/lib/rules/lowercase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const { NODE_TYPES } = require("@html-eslint/parser");
const { RULE_CATEGORY } = require("../constants");

const MESSAGE_IDS = {
UNEXPECTED: "unexpected",
};

/**
* @type {Rule}
*/
module.exports = {
meta: {
type: "suggestion",

docs: {
description: "Enforce to use lowercase for tag and attribute names.",
category: RULE_CATEGORY.STYLE,
recommended: false,
},

fixable: "code",
schema: [],
messages: {
[MESSAGE_IDS.UNEXPECTED]: "'{{name}}' is not in lowercase.",
},
},

create(context) {
/**
* @param {TagNode | StyleTagNode | ScriptTagNode} node
*/
function nameOf(node) {
if (node.type === NODE_TYPES.ScriptTag) return "script";
if (node.type === NODE_TYPES.StyleTag) return "style";
return node.name;
}

/**
* @param {TagNode | StyleTagNode | ScriptTagNode} node
*/
function check(node) {
const raw = node.openStart.value.slice(1);
if (nameOf(node) !== raw) {
context.report({
node: node.openStart,
messageId: MESSAGE_IDS.UNEXPECTED,
data: {
name: raw,
},
fix(fixer) {
const name = nameOf(node);
const fixes = [
fixer.replaceTextRange(node.openStart.range, `<${name}`),
];

if (node.close) {
fixes.push(
fixer.replaceTextRange(node.close.range, `</${name}>`)
);
}

return fixes;
},
});
}
if (node.attributes && node.attributes.length) {
node.attributes.forEach((attribute) => {
if (attribute.key.value !== attribute.key.value.toLowerCase()) {
context.report({
node: attribute.key,
messageId: MESSAGE_IDS.UNEXPECTED,
data: {
name: attribute.key.value,
},
fix(fixer) {
return fixer.replaceText(
attribute.key,
attribute.key.value.toLowerCase()
);
},
});
}
});
}
}

return {
Tag: check,
StyleTag: check,
ScriptTag: check,
};
},
};
68 changes: 68 additions & 0 deletions packages/eslint-plugin/tests/rules/lowercase.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const createRuleTester = require("../rule-tester");
const rule = require("../../lib/rules/lowercase");

const ruleTester = createRuleTester();

ruleTester.run("lowercase", rule, {
valid: [
{
code: "<div></div>",
},
{
code: "<div id='foo'></div>",
},
{
code: "<script></script>",
},
{
code: "<style></style>",
},
],
invalid: [
{
code: '<IMG src="img.png">',
output: '<img src="img.png">',
errors: [
{
message: "'IMG' is not in lowercase.",
},
],
},
{
code: "<Script></Script>",
output: "<script></script>",
errors: [
{
message: "'Script' is not in lowercase.",
},
],
},
{
code: "<Style type='text/css'></Style>",
output: "<style type='text/css'></style>",
errors: [
{
message: "'Style' is not in lowercase.",
},
],
},
{
code: "<sTyle type='text/css'></sTyle>",
output: "<style type='text/css'></style>",
errors: [
{
message: "'sTyle' is not in lowercase.",
},
],
},
{
code: "<div ID='1'></div>",
output: "<div id='1'></div>",
errors: [
{
message: "'ID' is not in lowercase.",
},
],
},
],
});

0 comments on commit c226d51

Please sign in to comment.