| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- <template>
- <view class="nana-Parse-container" :style="contentStyle">
- <ParseNodeRender v-for="(node, index) in nodes" :key="index" :node="node" />
- </view>
- </template>
- <script setup lang="ts">
- import ParseNodeRender from './ParseNodeRender.vue'
- import { parse, type DefaultTreeAdapterTypes } from 'parse5'
- import { computed, provide, ref, toRef } from 'vue';
- import type { ParseNode } from './Parse'
- export interface ParseProps {
- /**
- * HTML解析内容
- */
- content?: string|null|undefined;
- /**
- * 标签样式。键为标签名,值为样式
- */
- tagStyle?: Record<string, string>;
- /**
- * 容器样式
- */
- contentStyle?: any;
- }
- const props = withDefaults(defineProps<ParseProps>(), {
- tagStyle: () => ({})
- });
- const praseImages = ref<string[]>([]);
- provide('tagStyle', toRef(props, 'tagStyle'));
- provide('praseImages', praseImages);
- const toObj = (attrs: DefaultTreeAdapterTypes.Element['attrs']) => {
- const obj: Record<string, string> = {};
- for (const attr of attrs) {
- obj[attr.name] = attr.value;
- }
- return obj;
- }
- // 解析HTML为节点树
- const parseHtml = (html: string): ParseNode[] => {
- const nodes: ParseNode[] = [];
- const doc = parse(html);
- praseImages.value = [];
-
- const traverse = (element: DefaultTreeAdapterTypes.Element): ParseNode => {
- const node: ParseNode = {
- tag: element.tagName,
- attrs: toObj(element.attrs),
- children: []
- };
-
- // 解析子节点
- if (element.childNodes) {
- for (const child of element.childNodes) {
- if (child.nodeName === '#text') {
- node.children?.push({
- tag: 'text',
- attrs: {
- content: (child as DefaultTreeAdapterTypes.TextNode).value
- }
- });
- } else if (child.nodeName !== '#comment' && child.nodeName !== '#documentType') {
- const childNode = traverse(child as DefaultTreeAdapterTypes.Element);
- node.children?.push(childNode);
- if (childNode.tag === 'img') {
- praseImages.value.push(childNode.attrs?.src as string);
- }
- }
- }
- }
-
- return node;
- };
- for (const child of doc.childNodes) {
- if (child.nodeName === '#text') {
- nodes.push({
- tag: 'text',
- attrs: {
- content: (child as DefaultTreeAdapterTypes.TextNode).value
- }
- });
- } else if (child.nodeName !== '#documentType') {
- nodes.push(traverse(child as DefaultTreeAdapterTypes.Element));
- }
- }
- return nodes;
- };
- // 计算属性,获取解析后的节点树
- const nodes = computed(() => parseHtml(props.content || ''));
- </script>
- <style scoped>
- .nana-Parse-container {
- width: 100%;
- }
- </style>
|