HTMLを解析してVueの描画関数を作る

2019/12/29 11:30#js#ts

parse5HTMLを解析してVueの描画関数を作成します。

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)
                    })
                )
    }
}