Skip to content

Commit

Permalink
Add support for stripping all tags
Browse files Browse the repository at this point in the history
Create a `strip-tags` argument
Bump version to 2.3.0
  • Loading branch information
zcolleyz committed Jun 20, 2023
1 parent 04dcbad commit 2e96595
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 16 deletions.
37 changes: 32 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ Vue.use(VueSafeHTML);

In your component:

```html
```jsx
<template>
<div v-safe-html="myUnsafeHTML">
<div v-safe-html="myUnsafeHTML" />
</template>
```

Expand Down Expand Up @@ -91,13 +91,40 @@ Vue.use(VueSafeHTML, {

It is also possible to provide custom allowed tags directly to the directive tag, using directive modifiers. This allows local override of the option:

```html
```jsx
<template>
<div v-safe-html.p.strong="myUnsafeHTML" />
</template>
```

> Only allow p and strong tags
#### Stripping all tags for HTML entity decoding

To decode HTML entities only with no tags you can use the `strip-tags` directive argument:

```jsx
<template>
<!-- only allow p and strong tags -->
<div v-safe-html.p.strong="myUnsafeHTML">
<div v-safe-html:strip-tags="unsafeHTML" />
</template>
```

```js
export default {
computed: {
myUnsafeHTML() {
return '<p><strong>Cats<strong> &amp; <em>&quot;Dogs&quot;</em></p>';
}
}
}
```

Renders to:

```html
<div>Cats &amp; "Dogs"</div>
```

### Nuxt

`vue-safe-html` is written as a Vue plugin so you can easily use it inside Nuxt by following [the Nuxt documentation](https://nuxtjs.org/docs/2.x/directory-structure/plugins#vue-plugins).
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-safe-html",
"version": "2.2.0",
"version": "2.3.0",
"description": "A Vue directive which renders sanitised HTML dynamically",
"main": "dist/main.js",
"repository": "[email protected]:ecosia/vue-safe-html.git",
Expand Down
29 changes: 19 additions & 10 deletions src/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,28 @@ const areTagsValid = (tags) => (

export { defaultTags as allowedTags };

export default (tags) => {
const initialTags = areTagsValid(tags) ? tags : defaultTags;
return (el, binding) => {
let finalTags = initialTags;
const getAllowedTags = (initialTags, binding) => {
if (binding?.arg === 'strip-tags') {
// v-safe-html:strip-tags returns no tags
return [];
}

if (binding.modifiers) {
const directiveTags = Object.keys(binding.modifiers);
if (directiveTags.length > 0 && areTagsValid(directiveTags)) {
finalTags = directiveTags;
}
if (binding.modifiers) {
// v-safe-html.p.strong returns 'p' and 'strong'
const directiveTags = Object.keys(binding.modifiers);
if (directiveTags.length > 0 && areTagsValid(directiveTags)) {
return directiveTags;
}
}

return initialTags;
};

const sanitized = sanitizeHTML(binding.value, finalTags);
export default (tags) => {
const initialTags = areTagsValid(tags) ? tags : defaultTags;
return (el, binding) => {
const allowedTags = getAllowedTags(initialTags, binding);
const sanitized = sanitizeHTML(binding.value, allowedTags);

if (typeof el.innerHTML === 'string') {
// we're client-side and `el` is an HTMLElement
Expand Down
38 changes: 38 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,43 @@ describe('Plugin', () => {
const expected = '<div><section><strong>Safe</strong></section> HTML</div>';
expect(wrapper.element.outerHTML).toBe(expected);
});

describe('Modifiers', () => {
it('Handles allowed tags as modifiers', () => {
const localVue = createLocalVue();
localVue.use(Plugin, {
allowedTags: [
...defaultAllowedTags,
'section',
],
});
// eslint-disable-next-line vue/one-component-per-file
const Component = localVue.component('SafeHtmlComponent', {
template: '<div v-safe-html.p.strong="\'<p><section><strong>Safe</strong></section> HTML<script></script> &amp; <mark>marked text</mark></p>\'"></div>',
});
const wrapper = shallowMount(Component, { localVue });
const expected = '<div><p><strong>Safe</strong> HTML &amp; marked text</p></div>';
expect(wrapper.element.outerHTML).toBe(expected);
});
});

describe('"strip-tags" argument', () => {
it('strips all HTML but leaves HTML entities', () => {
const localVue = createLocalVue();
localVue.use(Plugin, {
allowedTags: [
...defaultAllowedTags,
'section',
],
});
// eslint-disable-next-line vue/one-component-per-file
const Component = localVue.component('SafeHtmlComponent', {
template: '<div v-safe-html:strip-tags="\'<p><strong>Cats<strong> &amp; <em>&quot;Dogs&quot;</em></p>\'"></div>',
});
const wrapper = shallowMount(Component, { localVue });
const expected = '<div>Cats &amp; "Dogs"</div>';
expect(wrapper.element.outerHTML).toBe(expected);
});
});
});
});

0 comments on commit 2e96595

Please sign in to comment.