diff --git a/packages/uni-cli-shared/src/utils.ts b/packages/uni-cli-shared/src/utils.ts index 675caa3f95..3568fe7c58 100644 --- a/packages/uni-cli-shared/src/utils.ts +++ b/packages/uni-cli-shared/src/utils.ts @@ -278,3 +278,34 @@ export function isNormalCompileTarget() { // 目前有特殊编译目标 uni_modules 和 ext-api return !process.env.UNI_COMPILE_TARGET } + +/** + * copy from entities 用于转义实体字符 + * @param regex + * @param map + * @returns + */ +export function getEscaper( + regex: RegExp, + map: Map +): (data: string) => string { + return function escape(data: string): string { + let match + let lastIndex = 0 + let result = '' + + while ((match = regex.exec(data))) { + if (lastIndex !== match.index) { + result += data.substring(lastIndex, match.index) + } + + // We know that this character will be in the map. + result += map.get(match[0].charCodeAt(0))! + + // Every match will be of length 1 + lastIndex = match.index + 1 + } + + return result + data.substring(lastIndex) + } +} diff --git a/packages/uni-mp-compiler/src/template/codegen.ts b/packages/uni-mp-compiler/src/template/codegen.ts index 2c7cc84ab1..fd65e77dd1 100644 --- a/packages/uni-mp-compiler/src/template/codegen.ts +++ b/packages/uni-mp-compiler/src/template/codegen.ts @@ -3,6 +3,7 @@ import { SLOT_DEFAULT_NAME, dynamicSlotName } from '@dcloudio/uni-shared' import { type MiniProgramCompilerOptions, formatMiniProgramEvent, + getEscaper, isAttributeNode, isElementNode, isUserComponent, @@ -51,6 +52,26 @@ export interface TemplateCodegenContext { checkPropName: TemplateCodegenOptions['checkPropName'] } +/** + * 注意此处的 escapeText 并未解决用户代码内的实体字符与产物内的不一致的Bug。 + * vue编译器在tokenize阶段会将实体字符转义为对应的字符,因此在codegen阶段无法做到完美还原用户代码。 + * 但是在uni-app-x依然要做反转义,主要考虑以下几点: + * - 用户源码>原产物为>,导致wxml解析错误 + * - 用户源码内不会出现>字符。虽然emsp等字符可以出现在用户的源码里面,但是一般不会有人这么做。因此无论用户写的是 还是\u2003,都被转义为 对用户而言影响不大 + */ +const mpEscapeText = getEscaper( + /[&<>\u2009\u00A0\u2002\u2003]/g, + new Map([ + [38, '&'], + [60, '<'], + [62, '>'], + [0x2009, ' '], + [0xa0, ' '], + [0x2002, ' '], + [0x2003, ' '], + ]) +) + export function generate( { children }: RootNode, { @@ -127,7 +148,11 @@ export function genNode( } function genText(node: TextNode, { push }: TemplateCodegenContext) { - push(node.content) + if (process.env.UNI_APP_X === 'true') { + push(mpEscapeText(node.content)) + } else { + push(node.content) + } } function genExpression(node: ExpressionNode, { push }: TemplateCodegenContext) {