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

main
Last change on this file since 0c6b92a was 0c6b92a, checked in by stefan toskovski <stefantoska84@…>, 5 weeks ago

Pred finalna verzija

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