UNPKG

@fesjs/fes-design

Version:
119 lines (110 loc) 3.74 kB
import { defineComponent, createVNode, isVNode, Text } from 'vue'; import { isArray, isString, isObject } from 'lodash-es'; import getPrefixCls from '../_util/getPrefixCls'; import { useTheme } from '../_theme/useTheme'; import FText from '../text'; import { textHighlightProps } from './props'; const prefixCls = getPrefixCls('text-highlight'); var textHighlight = defineComponent({ name: 'FTextHighlight', props: textHighlightProps, setup(props, _ref) { let { slots } = _ref; useTheme(); const createRegExp = value => { const flags = props.strict ? 'g' : 'gi'; return new RegExp(`(${value})`, flags); }; // 判断是否相等 const judgeEqual = (word, text) => { return props.strict && text === word || !props.strict && text.toLowerCase() === word.toLowerCase(); }; // 渲染高亮的部分 const renderHighLight = part => { return createVNode(FText, { "tag": "mark", "class": "highlight", "style": props.markTextStyle }, { default: () => [part] }); }; // 渲染文本 const renderText = text => { let parts = [text]; props.searchValues.forEach(value => { const regExp = createRegExp(value); parts = parts.reduce((result, part) => { if (isString(part)) { const split = part.split(regExp); return result.concat(split.map(txt => { return judgeEqual(value, txt) ? renderHighLight(txt) : txt; })); } else { return [...result, part]; } }, []); }); return parts; }; // 渲染节点 const renderNode = node => { // 节点的标签 const NodeType = node.type; let children; // 处理children if (isArray(node.children)) { // 如果是数组,对每个子节点进行处理 children = node.children.map(child => { // 如果子节点是字符串,使用 renderText 函数处理 if (isString(child)) { return renderText(child); } else if (isVNode(child)) { // 如果子节点是 VNode,递归使用 renderNode 函数处理 return renderNode(child); } else { // 如果子节点既不是字符串也不是 VNode,直接返回它 return child; } }); } else if (isString(node.children)) { // node.children 是字符串,使用 renderText 函数处理 children = renderText(node.children); } else { // 如果 node.children 既不是数组也不是字符串,直接返回它 children = node.children; } if (NodeType === Text) { // 如果是纯文本,渲染一个空标签 return createVNode("span", node.props, [children]); } else if (isString(NodeType)) { // 字符串(对应 HTML 标签名) return createVNode(NodeType, node.props, { default: () => [children] }); } else if (isObject(NodeType)) { // 用户自定义的组件对象 const ChildComponent = NodeType; const child = node.children; const childSlots = child && child.default ? child.default() : []; return createVNode(ChildComponent, node.props, { default: () => [childSlots.map(renderNode)] }); } }; // 渲染内容 const renderContent = () => { if (!slots.default) { return ''; } // 遍历内容的所有节点 return slots.default().map(renderNode); }; return () => createVNode("div", { "class": prefixCls }, [renderContent()]); } }); export { textHighlight as default };