forked from eslint/markdown
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathno-html.js
More file actions
116 lines (98 loc) · 2.79 KB
/
Copy pathno-html.js
File metadata and controls
116 lines (98 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
* @fileoverview Rule to disallow HTML inside of content.
* @author Nicholas C. Zakas
*/
//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------
import { findOffsets } from "../util.js";
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
* @import { MarkdownRuleDefinition } from "../types.js";
* @typedef {"disallowedElement"} NoHtmlMessageIds
* @typedef {[{ allowed?: string[] }]} NoHtmlOptions
* @typedef {MarkdownRuleDefinition<{ RuleOptions: NoHtmlOptions, MessageIds: NoHtmlMessageIds }>} NoHtmlRuleDefinition
*/
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
const htmlTagPattern =
/<([a-z0-9]+(?:-[a-z0-9]+)*)(?:\s+(?:[^>"']|"[^"]*"|'[^']*')*)?>/giu;
const lineEndingPattern = /\r\n?|\n/u;
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
/** @type {NoHtmlRuleDefinition} */
export default {
meta: {
type: "problem",
docs: {
description: "Disallow HTML tags",
url: "https://github.com/eslint/markdown/blob/main/docs/rules/no-html.md",
},
messages: {
disallowedElement: 'HTML element "{{name}}" is not allowed.',
},
schema: [
{
type: "object",
properties: {
allowed: {
type: "array",
items: {
type: "string",
},
uniqueItems: true,
},
},
additionalProperties: false,
},
],
defaultOptions: [
{
allowed: [],
},
],
},
create(context) {
const allowed = new Set(context.options[0].allowed);
return {
html(node) {
let match;
while ((match = htmlTagPattern.exec(node.value)) !== null) {
const fullMatch = match[0];
const tagName = match[1];
const { lineOffset, columnOffset } = findOffsets(
node.value,
match.index,
);
const start = {
line: node.position.start.line + lineOffset,
column: node.position.start.column + columnOffset,
};
const firstNewlineIndex =
fullMatch.search(lineEndingPattern);
const endColumn =
firstNewlineIndex === -1
? start.column + fullMatch.length
: start.column + firstNewlineIndex;
const end = {
line: start.line,
column: endColumn,
};
if (allowed.size === 0 || !allowed.has(tagName)) {
context.report({
loc: { start, end },
messageId: "disallowedElement",
data: {
name: tagName,
},
});
}
}
},
};
},
};