sanitize-html 2.3.3 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/README.md +21 -7
- package/index.js +29 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.4.0 (2021-05-19):
|
|
4
|
+
- Added support for class names with wildcards in `allowedClasses`. Thanks to [zhangbenber](https://github.com/zhangbenber) for the contribution.
|
|
5
|
+
|
|
3
6
|
## 2.3.3 (2021-03-19):
|
|
4
7
|
- Security fix: `allowedSchemes` and related options did not properly block schemes containing a hyphen, plus sign, period or digit, such as `ms-calculator:`. Thanks to Lukas Euler for pointing out the issue.
|
|
5
8
|
- Added a security note about the known risks associated with using the `parser` option, especially `decodeEntities: false`. See the documentation.
|
package/README.md
CHANGED
|
@@ -26,9 +26,19 @@ HTML comments are not preserved.
|
|
|
26
26
|
|
|
27
27
|
sanitize-html is intended for use with Node.js and supports Node 10+. All of its npm dependencies are pure JavaScript. sanitize-html is built on the excellent `htmlparser2` module.
|
|
28
28
|
|
|
29
|
-
### Regarding
|
|
29
|
+
### Regarding TypeScript
|
|
30
30
|
|
|
31
|
-
sanitize-html is not written in
|
|
31
|
+
sanitize-html is not written in TypeScript and there is no plan to directly support it. There is a community supported typing definition, [`@types/sanitize-html`](https://www.npmjs.com/package/@types/sanitize-html), however.
|
|
32
|
+
```bash
|
|
33
|
+
npm install -D @types/sanitize-html
|
|
34
|
+
```
|
|
35
|
+
If `esModuleInterop=true` is not set in your `tsconfig.json` file, you have to import it with:
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import * as sanitizeHtml from 'sanitize-html';
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Any questions or problems while using `@types/sanitize-html` should be directed to its maintainers as directed by that project's contribution guidelines.
|
|
32
42
|
|
|
33
43
|
## How to use
|
|
34
44
|
|
|
@@ -38,11 +48,14 @@ sanitize-html is not written in Typescript and there is no plan to directly supp
|
|
|
38
48
|
|
|
39
49
|
But, perhaps you'd like to display sanitized HTML immediately in the browser for preview. Or ask the browser to do the sanitization work on every page load. You can if you want to!
|
|
40
50
|
|
|
41
|
-
*
|
|
42
|
-
* Run npm install and:
|
|
51
|
+
* Install the package:
|
|
43
52
|
|
|
44
53
|
```bash
|
|
45
|
-
npm install sanitize-html
|
|
54
|
+
npm install sanitize-html
|
|
55
|
+
```
|
|
56
|
+
or
|
|
57
|
+
```
|
|
58
|
+
yarn add sanitize-html
|
|
46
59
|
```
|
|
47
60
|
|
|
48
61
|
The primary change in the 2.x version of sanitize-html is that it no longer includes a build that is ready for browser use. Developers are expected to include sanitize-html in their project builds (e.g., webpack) as they would any other dependency. So while sanitize-html is no longer ready to link to directly in HTML, developers can now more easily process it according to their needs.
|
|
@@ -69,7 +82,7 @@ npm install sanitize-html
|
|
|
69
82
|
|
|
70
83
|
Import the module:
|
|
71
84
|
|
|
72
|
-
```
|
|
85
|
+
```js
|
|
73
86
|
// In ES modules
|
|
74
87
|
import sanitizeHtml from 'sanitize-html';
|
|
75
88
|
|
|
@@ -224,9 +237,10 @@ const clean = sanitizeHtml(dirty, {
|
|
|
224
237
|
});
|
|
225
238
|
```
|
|
226
239
|
|
|
227
|
-
Similar to `allowedAttributes`, you can use `*` as a tag name
|
|
240
|
+
Similar to `allowedAttributes`, you can use `*` to allow classes with a certain prefix, or use `*` as a tag name to allow listed classes to be valid for any tag:
|
|
228
241
|
```js
|
|
229
242
|
allowedClasses: {
|
|
243
|
+
'code': [ 'language-*', 'lang-*' ],
|
|
230
244
|
'*': [ 'fancy', 'simple' ]
|
|
231
245
|
}
|
|
232
246
|
```
|
package/index.js
CHANGED
|
@@ -146,10 +146,13 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
146
146
|
allowedAttributesMap[tag].push(obj);
|
|
147
147
|
}
|
|
148
148
|
});
|
|
149
|
-
|
|
149
|
+
if (globRegex.length) {
|
|
150
|
+
allowedAttributesGlobMap[tag] = new RegExp('^(' + globRegex.join('|') + ')$');
|
|
151
|
+
}
|
|
150
152
|
});
|
|
151
153
|
}
|
|
152
154
|
const allowedClassesMap = {};
|
|
155
|
+
const allowedClassesGlobMap = {};
|
|
153
156
|
each(options.allowedClasses, function(classes, tag) {
|
|
154
157
|
// Implicitly allows the class attribute
|
|
155
158
|
if (allowedAttributesMap) {
|
|
@@ -159,7 +162,18 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
159
162
|
allowedAttributesMap[tag].push('class');
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
allowedClassesMap[tag] =
|
|
165
|
+
allowedClassesMap[tag] = [];
|
|
166
|
+
const globRegex = [];
|
|
167
|
+
classes.forEach(function(obj) {
|
|
168
|
+
if (typeof obj === 'string' && obj.indexOf('*') >= 0) {
|
|
169
|
+
globRegex.push(escapeStringRegexp(obj).replace(/\\\*/g, '.*'));
|
|
170
|
+
} else {
|
|
171
|
+
allowedClassesMap[tag].push(obj);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
if (globRegex.length) {
|
|
175
|
+
allowedClassesGlobMap[tag] = new RegExp('^(' + globRegex.join('|') + ')$');
|
|
176
|
+
}
|
|
163
177
|
});
|
|
164
178
|
|
|
165
179
|
const transformTagsMap = {};
|
|
@@ -379,10 +393,17 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
379
393
|
if (a === 'class') {
|
|
380
394
|
const allowedSpecificClasses = allowedClassesMap[name];
|
|
381
395
|
const allowedWildcardClasses = allowedClassesMap['*'];
|
|
396
|
+
const allowedSpecificClassesGlob = allowedClassesGlobMap[name];
|
|
397
|
+
const allowedWildcardClassesGlob = allowedClassesGlobMap['*'];
|
|
398
|
+
const allowedClassesGlobs = [ allowedSpecificClassesGlob, allowedWildcardClassesGlob ].filter(
|
|
399
|
+
function(t) {
|
|
400
|
+
return t;
|
|
401
|
+
}
|
|
402
|
+
);
|
|
382
403
|
if (allowedSpecificClasses && allowedWildcardClasses) {
|
|
383
|
-
value = filterClasses(value, deepmerge(allowedSpecificClasses, allowedWildcardClasses));
|
|
404
|
+
value = filterClasses(value, deepmerge(allowedSpecificClasses, allowedWildcardClasses), allowedClassesGlobs);
|
|
384
405
|
} else {
|
|
385
|
-
value = filterClasses(value, allowedSpecificClasses || allowedWildcardClasses);
|
|
406
|
+
value = filterClasses(value, allowedSpecificClasses || allowedWildcardClasses, allowedClassesGlobs);
|
|
386
407
|
}
|
|
387
408
|
if (!value.length) {
|
|
388
409
|
delete frame.attribs[a];
|
|
@@ -669,14 +690,16 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
669
690
|
};
|
|
670
691
|
}
|
|
671
692
|
|
|
672
|
-
function filterClasses(classes, allowed) {
|
|
693
|
+
function filterClasses(classes, allowed, allowedGlobs) {
|
|
673
694
|
if (!allowed) {
|
|
674
695
|
// The class attribute is allowed without filtering on this tag
|
|
675
696
|
return classes;
|
|
676
697
|
}
|
|
677
698
|
classes = classes.split(/\s+/);
|
|
678
699
|
return classes.filter(function(clss) {
|
|
679
|
-
return allowed.indexOf(clss) !== -1
|
|
700
|
+
return allowed.indexOf(clss) !== -1 || allowedGlobs.some(function(glob) {
|
|
701
|
+
return glob.test(clss);
|
|
702
|
+
});
|
|
680
703
|
}).join(' ');
|
|
681
704
|
}
|
|
682
705
|
}
|
package/package.json
CHANGED