source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/no-unescaped-entities.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 3.8 KB
Line 
1/**
2 * @fileoverview HTML special characters should be escaped.
3 * @author Patrick Hayes
4 */
5
6'use strict';
7
8const docsUrl = require('../util/docsUrl');
9const getSourceCode = require('../util/eslint').getSourceCode;
10const jsxUtil = require('../util/jsx');
11const report = require('../util/report');
12
13// ------------------------------------------------------------------------------
14// Rule Definition
15// ------------------------------------------------------------------------------
16
17// NOTE: '<' and '{' are also problematic characters, but they do not need
18// to be included here because it is a syntax error when these characters are
19// included accidentally.
20const DEFAULTS = [{
21 char: '>',
22 alternatives: ['&gt;'],
23}, {
24 char: '"',
25 alternatives: ['&quot;', '&ldquo;', '&#34;', '&rdquo;'],
26}, {
27 char: '\'',
28 alternatives: ['&apos;', '&lsquo;', '&#39;', '&rsquo;'],
29}, {
30 char: '}',
31 alternatives: ['&#125;'],
32}];
33
34const messages = {
35 unescapedEntity: 'HTML entity, `{{entity}}` , must be escaped.',
36 unescapedEntityAlts: '`{{entity}}` can be escaped with {{alts}}.',
37};
38
39/** @type {import('eslint').Rule.RuleModule} */
40module.exports = {
41 meta: {
42 docs: {
43 description: 'Disallow unescaped HTML entities from appearing in markup',
44 category: 'Possible Errors',
45 recommended: true,
46 url: docsUrl('no-unescaped-entities'),
47 },
48
49 messages,
50
51 schema: [{
52 type: 'object',
53 properties: {
54 forbid: {
55 type: 'array',
56 items: {
57 anyOf: [{
58 type: 'string',
59 }, {
60 type: 'object',
61 properties: {
62 char: {
63 type: 'string',
64 },
65 alternatives: {
66 type: 'array',
67 uniqueItems: true,
68 items: {
69 type: 'string',
70 },
71 },
72 },
73 }],
74 },
75 },
76 },
77 additionalProperties: false,
78 }],
79 },
80
81 create(context) {
82 function reportInvalidEntity(node) {
83 const configuration = context.options[0] || {};
84 const entities = configuration.forbid || DEFAULTS;
85
86 // HTML entities are already escaped in node.value (as well as node.raw),
87 // so pull the raw text from getSourceCode(context)
88 for (let i = node.loc.start.line; i <= node.loc.end.line; i++) {
89 let rawLine = getSourceCode(context).lines[i - 1];
90 let start = 0;
91 let end = rawLine.length;
92 if (i === node.loc.start.line) {
93 start = node.loc.start.column;
94 }
95 if (i === node.loc.end.line) {
96 end = node.loc.end.column;
97 }
98 rawLine = rawLine.slice(start, end);
99 for (let j = 0; j < entities.length; j++) {
100 for (let index = 0; index < rawLine.length; index++) {
101 const c = rawLine[index];
102 if (typeof entities[j] === 'string') {
103 if (c === entities[j]) {
104 report(context, messages.unescapedEntity, 'unescapedEntity', {
105 node,
106 loc: { line: i, column: start + index },
107 data: {
108 entity: entities[j],
109 },
110 });
111 }
112 } else if (c === entities[j].char) {
113 report(context, messages.unescapedEntityAlts, 'unescapedEntityAlts', {
114 node,
115 loc: { line: i, column: start + index },
116 data: {
117 entity: entities[j].char,
118 alts: entities[j].alternatives.map((alt) => `\`${alt}\``).join(', '),
119 },
120 });
121 }
122 }
123 }
124 }
125 }
126
127 return {
128 'Literal, JSXText'(node) {
129 if (jsxUtil.isJSX(node.parent)) {
130 reportInvalidEntity(node);
131 }
132 },
133 };
134 },
135};
Note: See TracBrowser for help on using the repository browser.