Skip to content

Commit b12542f

Browse files
Feature/req mailto (#95)
* Adds new rule `htmlacademy/req-mailto` * Adds description rule * Adds fixture * Update rule list
1 parent 04dd670 commit b12542f

File tree

5 files changed

+86
-0
lines changed

5 files changed

+86
-0
lines changed

docs/list-of-rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
| [htmlacademy/no-px-size](../rules/no-px-size/README.md) | Атрибуты `width` и `height` содержат только цифры, без единиц измерения |
2222
| [htmlacademy/req-charset-utf](../rules/req-charset-utf/README.md) | Требует `UTF-8` для `<meta charset="">` |
2323
| [htmlacademy/req-head-styles](../rules/req-head-styles/README.md) | Запрещает подключение стилей вне `<head>` |
24+
| [htmlacademy/req-mailto](../rules/req-mailto/README.md) | Требует `mailto:` для ссылок c email-текстом |
2425
| [htmlacademy/req-meta-viewport](../rules/req-meta-viewport/README.md) | Проверяет наличие `<meta name="viewport" content="width=device-width,initial-scale=1">` в `<head>` |
2526
| [htmlacademy/req-single-styles](../rules/req-single-styles/README.md) | Разрешает не более одного `link rel="stylesheet"` в `<head>` |
2627
| [htmlacademy/req-stylesheet-link](../rules/req-stylesheet-link/README.md) | Проверяет наличие `<link rel="stylesheet" href="">` с непустым `href` |

rules/req-mailto/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# htmlacademy/req-mailto
2+
3+
Правило осуществляет проверку того, содержит ли атрибут `href` тега `<a>` строку `mailto:`, при условии, что содержимое ссылки представляет собой текст в формате электронной почты.
4+
5+
## true
6+
7+
Проблемными считаются следующие шаблоны:
8+
9+
```html
10+
<a href="example@example.com">example@example.com</a> <!-- отсутствует mailto: -->
11+
12+
<a href="#!">contact@example.com</a> <!-- отсутствует mailto: -->
13+
14+
<a href="http://example.com">user@example.com</a> <!-- отсутствует mailto: -->
15+
16+
<a href="/contact">support@example.com</a> <!-- отсутствует mailto: -->
17+
18+
<a>admin@example.com</a> <!-- отсутствует href с mailto: -->
19+
20+
<a href="javascript:void(0);">info@example.com</a> <!-- отсутствует mailto: -->
21+
```
22+
23+
Следующие шаблоны **не** считаются проблемами:
24+
25+
```html
26+
<a href="mailto:">example@example.com</a> <!-- не проверяет наличие email после mailto: -->
27+
28+
<a href="mailto:example@com">example@com</a> <!-- в теле ссылки не email -->
29+
30+
<a href="mailto:example@example.com">Click here</a> <!-- в теле ссылки не email -->
31+
32+
<a href="mailto:example@example.com">example@example.com</a> <!-- контентом ссылки является email, а href имеет mailto -->
33+
34+
<a href="mailto:example@example.com" onclick="someFunction();">example@example.com</a>
35+
```

rules/req-mailto/fixture/error.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<a href="example@example.com">example@example.com</a>
2+
3+
<a href="#!">contact@example.com</a>
4+
5+
<a href="http://example.com">user@example.com</a>
6+
7+
<a href="/contact">support@example.com</a>
8+
9+
<a>admin@example.com</a>
10+
11+
<a href="javascript:void(0);">info@example.com</a>

rules/req-mailto/fixture/success.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<a href="mailto:">example@example.com</a>
2+
3+
<a href="mailto:example@com">example@com</a>
4+
5+
<a href="mailto:example@example.com">Click here</a>
6+
7+
<a href="mailto:example@example.com">example@example.com</a>
8+
9+
<a href="mailto:example@example.com" onclick="someFunction();">example@example.com</a>

rules/req-mailto/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
const { has_non_empty_attribute, is_tag_node, attribute_value } = require('@linthtml/dom-utils');
3+
4+
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
5+
const isNotEmptyLink = (node) => node.childNodes.length > 0;
6+
const isEmailContent = (node) => emailRegex.test(node.childNodes[0].data);
7+
const reportError = (node) => ({
8+
position: node.loc,
9+
message: 'The href attribute of the <a> tag must start with "mailto:" if it contains an email'
10+
});
11+
12+
module.exports = {
13+
name: 'htmlacademy/req-mailto',
14+
// eslint-disable-next-line camelcase
15+
lint(node, rule_config, { report }) {
16+
if (is_tag_node(node) && node.name === 'a') {
17+
if (isNotEmptyLink(node) && isEmailContent(node)) {
18+
if (has_non_empty_attribute(node, 'href')) {
19+
const hrefValue = attribute_value(node, 'href').chars;
20+
21+
if (!hrefValue.startsWith('mailto:')) {
22+
report(reportError(node));
23+
}
24+
} else {
25+
report(reportError(node));
26+
}
27+
}
28+
}
29+
}
30+
};

0 commit comments

Comments
 (0)