On the Vue discord someone mentioned wanting to display sanitized html. I was wondering if this could be done with a recursive vue element running on a parse tree.
Let's say we want to render something like <b>blabla</b> asdadasd <b><i>bla</i>bla</b> and we already have a parse tree version of it (note: I didn't implement anything here to actually parse the html – I'm assuming you have that already):
let parsed = [ 'span', ['b', 'blabla'], ' asdadasd ', ['b', ['i', 'bla'], 'bla'] ];
A render function can inspect that parse tree and output the right type of node, but only allows some tags:
Vue.component('v-html-subset', { functional: true, props: ['allowed', 'tree'], render(h, context) { function traverse(tree) { let [type, ...children] = tree; return h(type, children.map(child => typeof child === 'string'? child : traverse(child))); } return traverse(context.props.tree); } });
Let's make an interactive demo:
new Vue({ el: "#vue", data: {tree: JSON.stringify(parsed, null, 4)}, template: ` <div> <textarea cols="40" rows="15" v-model="tree"/> <p id="output"> <v-html-subset v-bind:tree="parsed"/> </p> </div>`, computed: { parsed() { try { return JSON.parse(this.tree); } catch (e) { return ['b', 'parse error']; } }, }, });
Try it out:
Sanitization could be done at the parsing step, or the component could check the types and output span
for any disallowed tags.