parse5で
import {
VNode,
Component,
CreateElement,
VNodeData
} from 'vue'
import {
DefaultTreeNode as TreeNode,
DefaultTreeElement as ElementNode,
DefaultTreeTextNode as TextNode,
DefaultTreeCommentNode as CommentNode
} from 'parse5'
export interface Components {
[key:string]: Component
}
const isTextNode = (node: TreeNode): node is TextNode => node.nodeName == '#text'
const isCommentNode = (node: TreeNode): node is CommentNode => node.nodeName == '#comment'
const isElementNode = (node: TreeNode): node is ElementNode => !isTextNode(node)&&!isCommentNode(node)
const remap = (input: any): VNodeData => {
const output = <VNodeData>{}
output.class = input.class
output.style = input.style
delete input.class
delete input.style
return {
...output,
attrs: input
}
}
export class HTML2VNode {
components: Components // スタイルを当てるために事前に各HTML要素に対応したVueコンポーネントを作成、登録
constructor(components: Components) {
this.components = components
}
render(h: CreateElement, node: TreeNode): VNode|string {
return isTextNode(node)
? node.value
: ! isElementNode(node)
? ''
: h(
this.components[node.tagName] || node.tagName,
remap(node.attrs.reduce((attrs, { name, value }) => ({
... attrs || {},
[name]: value
}), {})),
node.childNodes.map(node => {
return this.render(h, node)
})
)
}
}