From 43a38070e3205f6a68d10f15348e6a206bf4abdc Mon Sep 17 00:00:00 2001 From: yurj26 <1816387074@qq.com> Date: Thu, 4 May 2023 10:57:34 +0800 Subject: [PATCH] feat(uts): transformText --- .../transforms/transformText.spec.ts | 30 +++++ .../src/plugins/uvue/compiler/index.ts | 2 + .../uvue/compiler/transforms/transformText.ts | 107 ++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 packages/uni-app-uts/__tests__/transforms/transformText.spec.ts create mode 100644 packages/uni-app-uts/src/plugins/uvue/compiler/transforms/transformText.ts diff --git a/packages/uni-app-uts/__tests__/transforms/transformText.spec.ts b/packages/uni-app-uts/__tests__/transforms/transformText.spec.ts new file mode 100644 index 0000000000..35318b4cb5 --- /dev/null +++ b/packages/uni-app-uts/__tests__/transforms/transformText.spec.ts @@ -0,0 +1,30 @@ +import { assert } from '../testUtils' + +describe('compiler: transform text', () => { + test('transform text', () => { + assert( + `hello`, + `createElementVNode("view", null, [ + createElementVNode("text", null, "hello") +])` + ) + assert( + `hello`, + `createElementVNode("view", null, [ + createElementVNode("text", null, "hello") +])` + ) + assert( + `hello{{a}}aaa{{a}}{{b}}`, + `createElementVNode("view", null, [ + createElementVNode("text", null, "hello"), + createElementVNode("text", null, toDisplayString(_ctx.a), 1 /* TEXT */), + createElementVNode("view", null, [ + createElementVNode("text", null, "aaa"), + createElementVNode("text", null, toDisplayString(_ctx.a), 1 /* TEXT */) + ]), + createElementVNode("text", null, toDisplayString(_ctx.b), 1 /* TEXT */) +])` + ) + }) +}) diff --git a/packages/uni-app-uts/src/plugins/uvue/compiler/index.ts b/packages/uni-app-uts/src/plugins/uvue/compiler/index.ts index 39d281336d..d987d9bc40 100644 --- a/packages/uni-app-uts/src/plugins/uvue/compiler/index.ts +++ b/packages/uni-app-uts/src/plugins/uvue/compiler/index.ts @@ -18,6 +18,7 @@ import { transformIf } from './transforms/vIf' import { transformFor } from './transforms/vFor' import { transformModel } from './transforms/vModel' import { transformShow } from './transforms/vShow' +import { transformText } from './transforms/transformText' export type TransformPreset = [ NodeTransform[], @@ -36,6 +37,7 @@ export function getBaseTransformPreset( transformExpression, transformElement, trackSlotScopes, + transformText, ] as any, { on: transformOn, diff --git a/packages/uni-app-uts/src/plugins/uvue/compiler/transforms/transformText.ts b/packages/uni-app-uts/src/plugins/uvue/compiler/transforms/transformText.ts new file mode 100644 index 0000000000..c89f8990ad --- /dev/null +++ b/packages/uni-app-uts/src/plugins/uvue/compiler/transforms/transformText.ts @@ -0,0 +1,107 @@ +import { isElementNode } from '@dcloudio/uni-cli-shared' +import { + CompoundExpressionNode, + ElementNode, + ElementTypes, + InterpolationNode, + NodeTransform, + NodeTypes, + TemplateChildNode, + TextCallNode, + TextNode, +} from '@vue/compiler-core' + +function isTextNode({ tag }: ElementNode) { + return tag === 'text' || tag === 'u-text' || tag === 'button' +} + +function isTextElement(node: TemplateChildNode) { + return node.type === NodeTypes.ELEMENT && node.tag === 'text' +} + +function isText( + node: TemplateChildNode +): node is + | TextNode + | TextCallNode + | InterpolationNode + | CompoundExpressionNode { + const { type } = node + return ( + type === NodeTypes.TEXT || + type === NodeTypes.TEXT_CALL || + type === NodeTypes.INTERPOLATION || + type === NodeTypes.COMPOUND_EXPRESSION + ) +} + +export const transformText: NodeTransform = (node, _) => { + if (!isElementNode(node)) { + return + } + if (isTextNode(node)) { + return + } + const { children } = node + if (!children.length) { + return + } + children.forEach((child, index) => { + if (isTextElement(child)) { + parseText(child as ElementNode) + } + + if (isText(child)) { + children.splice(index, 1, createText(node, child)) + } + }) +} + +/* + 1. 转换 \\n 为 \n + 2. u-text 下只能有一个文本节点(不支持 children),需要移除子组件并合并文本 +*/ +function parseText(node: ElementNode) { + if (node.children.length) { + let firstTextChild + for (let i = 0; i < node.children.length; i++) { + const child = node.children[i] + if (isText(child) && typeof (child as TextNode).content === 'string') { + if (!firstTextChild) { + firstTextChild = child + ;(firstTextChild as TextNode).content = ( + firstTextChild as TextNode + ).content.replace(/\\n/g, '\n') + } else { + ;(firstTextChild as TextNode).content += ( + child as TextNode + ).content.replace(/\\n/g, '\n') + node.children.splice(i, 1) + i-- + } + } else if (child.type === 1 || child.type === 3) { + node.children.splice(i, 1) + i-- + } else { + firstTextChild = null + } + } + } +} + +function createText( + parent: ElementNode, + node: TextNode | TextCallNode | InterpolationNode | CompoundExpressionNode +): ElementNode { + return { + tag: 'text', + type: NodeTypes.ELEMENT, + tagType: ElementTypes.ELEMENT, + props: [], + isSelfClosing: false, + children: [node], + codegenNode: undefined, + ns: parent.ns, + loc: node.loc, + } +} -- GitLab