Skip to content

Commit fc6d97a

Browse files
committed
fix: 修复innerHTML生成小程序时的相关逻辑
1. 对于a标签,逻辑保持跟 直接a标签基本一致 2. img=>image时,如果有width和height,把这2个值写入style属性内。style内如果有width和height,style内的更高优
1 parent adffe26 commit fc6d97a

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

packages/taro-runtime/src/dom-external/inner-html/parser.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { isFunction } from '@tarojs/shared'
33
import { options } from '../../options'
44
import { Scaner, Token } from './scaner'
55
import StyleTagParser from './style'
6-
import { isBlockElements, isInlineElements, isMiniElements, specialMiniElements } from './tags'
6+
import { getSpecialElementMapping, isBlockElements, isInlineElements, isMiniElements, isSpecialElements, specialMiniElements } from './tags'
77
import { unquote } from './utils'
88

99
import type { TaroDocument } from '../../dom/document'
@@ -47,7 +47,7 @@ export interface Element extends Node {
4747
attributes: string[]
4848
}
4949

50-
export interface ParsedTaroElement extends TaroElement{
50+
export interface ParsedTaroElement extends TaroElement {
5151
h5tagName?: string
5252
}
5353

@@ -71,7 +71,23 @@ function hasTerminalParent (tagName: string, stack: Element[]) {
7171
return false
7272
}
7373

74-
function getTagName (tag: string) {
74+
/**
75+
* 将属性数组转换为属性对象
76+
* @param attributes 字符串数组,包含属性信息
77+
* @returns 属性对象,键为属性名,值为属性值或true
78+
*/
79+
function attributesArray2Props (attributes: string[]): Record<string, string | true> {
80+
const props: Record<string, string | true> = {}
81+
for (let i = 0; i < attributes.length; i++) {
82+
const attr = attributes[i]
83+
const [key, value] = splitEqual(attr)
84+
props[key] = value == null ? true : unquote(value)
85+
}
86+
87+
return props
88+
}
89+
90+
function getTagName (tag: string, attributes: string[]) {
7591
if (options.html!.renderHTMLTag) {
7692
return tag
7793
}
@@ -84,6 +100,14 @@ function getTagName (tag: string) {
84100
return 'view'
85101
} else if (isInlineElements(tag)) {
86102
return 'text'
103+
} else if (isSpecialElements(tag)) {
104+
// if it's special tag, the real tag is determined by the config mapping
105+
const mapping = getSpecialElementMapping(tag)
106+
const props = attributesArray2Props(attributes)
107+
108+
if (mapping) {
109+
return mapping.mapName(props)
110+
}
87111
}
88112

89113
return 'view'
@@ -127,8 +151,26 @@ function format (
127151
parent?.appendChild(text)
128152
return text
129153
}
154+
// img标签,把width和height写入style,删除原有的width、height和style属性
155+
if (child.tagName === 'img') {
156+
let styleText = ''
157+
const toBeRemovedIndexs: number[] = []
158+
for (let i = 0; i < child.attributes.length; i++) {
159+
const attr = child.attributes[i]
160+
const [key, value] = splitEqual(attr)
161+
if (key === 'width' || key === 'height') {
162+
styleText += `${key}:${value};`
163+
toBeRemovedIndexs.push(i)
164+
} else if (key === 'style') {
165+
styleText = `${styleText}${value};`
166+
toBeRemovedIndexs.push(i)
167+
}
168+
}
169+
child.attributes = child.attributes.filter((_, index) => !toBeRemovedIndexs.includes(index))
170+
child.attributes.push(`style=${styleText.replace(/['"]/g, '')}`)
171+
}
130172

131-
const el: ParsedTaroElement = document.createElement(getTagName(child.tagName))
173+
const el: ParsedTaroElement = document.createElement(getTagName(child.tagName, child.attributes))
132174
el.h5tagName = child.tagName
133175

134176
parent?.appendChild(el)

packages/taro-runtime/src/dom-external/inner-html/tags.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { internalComponents } from '@tarojs/shared'
1+
import { internalComponents, isString } from '@tarojs/shared'
22

33
export function makeMap (
44
str: string,
@@ -17,6 +17,25 @@ export const specialMiniElements = {
1717
iframe: 'web-view'
1818
}
1919

20+
interface SpecialMap {
21+
mapName: (props: Record<string, string | boolean>) => string
22+
}
23+
24+
const specialElements = new Map<string, SpecialMap>([
25+
['a', {
26+
mapName (props) {
27+
if (props.as && isString(props.as)) return props.as.toLowerCase()
28+
return !props.href || isString(props.href) && (/^javascript/.test(props.href)) ? 'view' : 'navigator'
29+
}
30+
}],
31+
])
32+
33+
export const getSpecialElementMapping = (tag: string, expectsLowerCase:boolean = true) => {
34+
tag = expectsLowerCase ? tag.toLowerCase() : tag
35+
return specialElements.get(tag)
36+
}
37+
38+
2039
const internalCompsList = Object.keys(internalComponents)
2140
.map(i => i.toLowerCase())
2241
.join(',')
@@ -25,7 +44,10 @@ const internalCompsList = Object.keys(internalComponents)
2544
export const isMiniElements = makeMap(internalCompsList, true)
2645

2746
// https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements
28-
export const isInlineElements = makeMap('a,i,abbr,iframe,select,acronym,slot,small,span,bdi,kbd,strong,big,map,sub,sup,br,mark,mark,meter,template,canvas,textarea,cite,object,time,code,output,u,data,picture,tt,datalist,var,dfn,del,q,em,s,embed,samp,b', true)
47+
export const isInlineElements = makeMap('i,abbr,iframe,select,acronym,slot,small,span,bdi,kbd,strong,big,map,sub,sup,br,mark,mark,meter,template,canvas,textarea,cite,object,time,code,output,u,data,picture,tt,datalist,var,dfn,del,q,em,s,embed,samp,b', true)
2948

3049
// https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
3150
export const isBlockElements = makeMap('address,fieldset,li,article,figcaption,main,aside,figure,nav,blockquote,footer,ol,details,form,p,dialog,h1,h2,h3,h4,h5,h6,pre,dd,header,section,div,hgroup,table,dl,hr,ul,dt', true)
51+
52+
// specialElements
53+
export const isSpecialElements = makeMap('a', true)

0 commit comments

Comments
 (0)