sanitize-html 2.15.0 → 2.17.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/README.md +54 -1
- package/index.js +17 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -745,7 +745,7 @@ This will transform `<disallowed>content <allowed>content</allowed> </disallowed
|
|
|
745
745
|
|
|
746
746
|
#### Escape the disallowed tag and all its children even for allowed tags.
|
|
747
747
|
|
|
748
|
-
if you set `disallowedTagsMode` to `recursiveEscape`, disallowed
|
|
748
|
+
if you set `disallowedTagsMode` to `recursiveEscape`, disallowed tags and their children will be escaped even for allowed tags:
|
|
749
749
|
|
|
750
750
|
```js
|
|
751
751
|
disallowedTagsMode: `recursiveEscape`
|
|
@@ -753,6 +753,15 @@ disallowedTagsMode: `recursiveEscape`
|
|
|
753
753
|
|
|
754
754
|
This will transform `<disallowed>hello<p>world</p></disallowed>` to `<disallowed>hello<p>world</p></disallowed>`
|
|
755
755
|
|
|
756
|
+
#### Escape the disallowed tag, including all its attributes.
|
|
757
|
+
|
|
758
|
+
By default, attributes are not preserved when tags are escaped. You can set `preserveEscapedAttributes` to `true` to
|
|
759
|
+
keep the attributes, which will also be escaped and therefore have no effect on the browser.
|
|
760
|
+
|
|
761
|
+
```js
|
|
762
|
+
preserveEscapedAttributes: true
|
|
763
|
+
```
|
|
764
|
+
|
|
756
765
|
### Ignore style attribute contents
|
|
757
766
|
|
|
758
767
|
Instead of discarding faulty style attributes, you can allow them by disabling the parsing of style attributes:
|
|
@@ -781,6 +790,50 @@ nestingLimit: 6
|
|
|
781
790
|
|
|
782
791
|
This will prevent the user from nesting tags more than 6 levels deep. Tags deeper than that are stripped out exactly as if they were disallowed. Note that this means text is preserved in the usual ways where appropriate.
|
|
783
792
|
|
|
793
|
+
### Advanced filtering
|
|
794
|
+
|
|
795
|
+
For more advanced filtering you can hook directly into the parsing process using tag open and tag close events.
|
|
796
|
+
|
|
797
|
+
The `onOpenTag` event is triggered when an opening tag is encountered. It has two arguments:
|
|
798
|
+
- `tagName`: The name of the tag.
|
|
799
|
+
- `attribs`: An object containing the tag's attributes, e.g. `{ src: "/path/to/tux.png" }`.
|
|
800
|
+
|
|
801
|
+
The `onCloseTag` event is triggered when a closing tag is encountered. It has the following arguments:
|
|
802
|
+
- `tagName`: The name of the tag.
|
|
803
|
+
- `isImplied`: A boolean indicating whether the closing tag is implied (e.g. `<p>foo<p>bar`) or explicit (e.g. `<p>foo</p><p>bar</p>`).
|
|
804
|
+
|
|
805
|
+
For example, you may want to add spaces around a removed tag, like this:
|
|
806
|
+
```js
|
|
807
|
+
const allowedTags = [ 'b' ];
|
|
808
|
+
let addSpace = false;
|
|
809
|
+
const sanitizedHtml = sanitizeHtml(
|
|
810
|
+
'There should be<div><p>spaces</p></div>between <b>these</b> words.',
|
|
811
|
+
{
|
|
812
|
+
allowedTags,
|
|
813
|
+
onOpenTag: (tagName, attribs) => {
|
|
814
|
+
addSpace = !allowedTags.includes(tagName);
|
|
815
|
+
},
|
|
816
|
+
onCloseTag: (tagName, isImplied) => {
|
|
817
|
+
addSpace = !allowedTags.includes(tagName);
|
|
818
|
+
},
|
|
819
|
+
textFilter: (text) => {
|
|
820
|
+
if (addSpace) {
|
|
821
|
+
addSpace = false;
|
|
822
|
+
return ' ' + text;
|
|
823
|
+
}
|
|
824
|
+
return text;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
);
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
In this example, we are setting a flag when a tag that will be removed has been opened or closed. Then we use the `textFilter` to modify the text to include spaces. The example should produce:
|
|
831
|
+
```
|
|
832
|
+
There should be spaces between <b>these</b> words.
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
This is a simplified example that is not meant to be production-ready. For your specific case, you may want to keep track of currently open tags, using the open and close events to push and pop items on the stack, or only insert spaces next to a subset of disallowed tags.
|
|
836
|
+
|
|
784
837
|
## About ApostropheCMS
|
|
785
838
|
|
|
786
839
|
sanitize-html was created at [P'unk Avenue](https://punkave.com) for use in [ApostropheCMS](https://apostrophecms.com), an open-source content management system built on Node.js. If you like sanitize-html you should definitely check out ApostropheCMS.
|
package/index.js
CHANGED
|
@@ -220,6 +220,10 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
220
220
|
|
|
221
221
|
const parser = new htmlparser.Parser({
|
|
222
222
|
onopentag: function(name, attribs) {
|
|
223
|
+
if (options.onOpenTag) {
|
|
224
|
+
options.onOpenTag(name, attribs);
|
|
225
|
+
}
|
|
226
|
+
|
|
223
227
|
// If `enforceHtmlBoundary` is `true` and this has found the opening
|
|
224
228
|
// `html` tag, reset the state.
|
|
225
229
|
if (options.enforceHtmlBoundary && name === 'html') {
|
|
@@ -296,7 +300,14 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
302
|
|
|
299
|
-
|
|
303
|
+
const isBeingEscaped = skip && (options.disallowedTagsMode === 'escape' || options.disallowedTagsMode === 'recursiveEscape');
|
|
304
|
+
const shouldPreserveEscapedAttributes = isBeingEscaped && options.preserveEscapedAttributes;
|
|
305
|
+
|
|
306
|
+
if (shouldPreserveEscapedAttributes) {
|
|
307
|
+
each(attribs, function(value, a) {
|
|
308
|
+
result += ' ' + a + '="' + escapeHtml((value || ''), true) + '"';
|
|
309
|
+
});
|
|
310
|
+
} else if (!allowedAttributesMap || has(allowedAttributesMap, name) || allowedAttributesMap['*']) {
|
|
300
311
|
each(attribs, function(value, a) {
|
|
301
312
|
if (!VALID_HTML_ATTRIBUTE_NAME.test(a)) {
|
|
302
313
|
// This prevents part of an attribute name in the output from being
|
|
@@ -544,6 +555,9 @@ function sanitizeHtml(html, options, _recursing) {
|
|
|
544
555
|
}
|
|
545
556
|
},
|
|
546
557
|
onclosetag: function(name, isImplied) {
|
|
558
|
+
if (options.onCloseTag) {
|
|
559
|
+
options.onCloseTag(name, isImplied);
|
|
560
|
+
}
|
|
547
561
|
|
|
548
562
|
if (skipText) {
|
|
549
563
|
skipTextDepth--;
|
|
@@ -916,7 +930,8 @@ sanitizeHtml.defaults = {
|
|
|
916
930
|
allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
|
|
917
931
|
allowProtocolRelative: true,
|
|
918
932
|
enforceHtmlBoundary: false,
|
|
919
|
-
parseStyleAttributes: true
|
|
933
|
+
parseStyleAttributes: true,
|
|
934
|
+
preserveEscapedAttributes: false
|
|
920
935
|
};
|
|
921
936
|
|
|
922
937
|
sanitizeHtml.simpleTransform = function(newTagName, newAttribs, merge) {
|
package/package.json
CHANGED