Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .agents/skills/mpx2rn/references/rn-style-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ Mpx 在 RN 平台支持 CSS 背景图及渐变背景,框架会自动处理样
| `line-height` | `length` \| `number` \| `%` | - | 行高,纯数字值自动转换为百分比(如 `1.5` → `150%`),最终按文本节点合并后的 `font-size` 解析;运行时数值型 `lineHeight` 表示绝对行高;多字号混排需统一设置外层行高 | `line-height: 40rpx`;`line-height: 1.5` |
| `text-align` | `left` \| `right` \| `center` \| `justify` | `auto` | 文本对齐;`auto` 是 RN 默认值,不支持在用户源码中显式书写 | `text-align: center` 文本居中 |
| `vertical-align` | `auto` \| `top` \| `bottom` \| `middle` | - | 垂直对齐(Android / Harmony 支持,iOS 不支持) | `vertical-align: middle` |
| `text-decoration` | `line \|\| style \|\| color` | - | 装饰线简写;`text-decoration-style` / `text-decoration-color` 仅 iOS 支持;line 支持多值组合 `underline line-through` | `text-decoration: underline`;`text-decoration: line-through solid red` |
| `text-decoration` | `line \|\| style \|\| color` | - | 装饰线简写;`text-decoration-style` / `text-decoration-color` 仅 iOS 按差异化样式与颜色生效;Android / Harmony 下 style 固定等效为 `solid`,color 跟随文本色;line 支持多值组合 `underline line-through` | `text-decoration: underline`;`text-decoration: line-through solid red` |
| `text-transform` | `none` \| `uppercase` \| `lowercase` \| `capitalize` | `none` | 大小写转换 | `text-transform: uppercase` 全部大写 |
| `letter-spacing` | `length` | - | 字符间距 | `letter-spacing: 2rpx` |
| `text-shadow` | `offset-x offset-y blur color` | - | 文本阴影(Mpx 增强) | `text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3)` |
Expand Down Expand Up @@ -632,4 +632,4 @@ Mpx 在 RN 平台支持 CSS 背景图及渐变背景,框架会自动处理样
以下属性存在平台差异:

- iOS 不支持 `vertical-align`
- Android / Harmony 不支持 `text-decoration-style`、`text-decoration-color``shadow-offset`、`shadow-opacity`、`shadow-radius`
- Android / Harmony 不支持差异化的 `text-decoration-style`、`text-decoration-color`:`text-decoration-style` 会按 `solid` 生效,`text-decoration-color` 会跟随文本色;Android / Harmony 不支持 `shadow-offset`、`shadow-opacity`、`shadow-radius`
4 changes: 2 additions & 2 deletions docs-vitepress/guide/rn/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -1387,13 +1387,13 @@ vertical-align: top; /* 顶部对齐 */
> - `text-decoration-line` 唯一支持的多值组合是 `underline line-through`;`none` 只作为单值生效
> - 赋值过程中,如遇到不支持的属性会忽略该属性;若属性值校验不合法,则忽略该值,继续校验下一个值是否合法,合法则赋值,不合法则继续校验下一个值
> - RN 原生不支持 `text-decoration` 简写,可使用是由框架编译和运行时处理
> - android 下仅转换`<text-decoration-line>`,`<text-decoration-style>`/`<text-decoration-color>` 因不支持不会添加
> - Android / Harmony 下 `text-decoration-style` 仅等效为 `solid`,非 `solid` 值会提示并降级为 `solid`;`text-decoration-color` 不生效,装饰线颜色跟随文本色,编译时会提示并忽略该值
> - 遵循[文本样式继承规则](#inheritance-rule)

```css
text-decoration: underline; /* 下划线 */
text-decoration: line-through; /* 删除线 */
text-decoration: underline dotted red; /* 样式 + 颜色(iOS) */
text-decoration: underline dotted red; /* 样式 + 颜色(iOS,Android/Harmony 下 style 降级为 solid 且 color 跟随文本色) */
text-decoration: red underline solid; /* 顺序不敏感(iOS) */
text-decoration: underline line-through red; /* 下划线 + 删除线 */
```
Expand Down
45 changes: 42 additions & 3 deletions packages/webpack-plugin/lib/platform/style/wx/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ module.exports = function getSpec ({ warn, error }) {
// React Native ios 不支持的 CSS property
ios: /^(vertical-align)$/,
// React Native android 不支持的 CSS property
android: /^(text-decoration-style|text-decoration-color|shadow-offset|shadow-opacity|shadow-radius)$/,
android: /^(shadow-offset|shadow-opacity|shadow-radius)$/,
// TODO: rnoh 文档暂未找到 css 属性支持说明,暂时同步 android,同时需要注意此处校验是否有缺失,类似 will-change 之类属性
harmony: /^(text-decoration-style|text-decoration-color|shadow-offset|shadow-opacity|shadow-radius)$/
harmony: /^(shadow-offset|shadow-opacity|shadow-radius)$/
}
const isNum = (v) => !isNaN(+v)
// var(xx)
Expand Down Expand Up @@ -338,6 +338,19 @@ module.exports = function getSpec ({ warn, error }) {
})
}

const normalizeTextDecorationValue = (prop, value, selector, mode) => {
if (mode !== 'android' && mode !== 'harmony') return value
if (prop === 'textDecorationStyle' && value !== 'solid') {
warn(`Property [text-decoration-style] on ${selector} only supports value "solid" in ${mode} environment, received [${value}], will use "solid" instead!`)
return 'solid'
}
if (prop === 'textDecorationColor') {
warn(`Property [text-decoration-color] on ${selector} is ignored in ${mode} environment, decoration color follows text color instead!`)
return false
}
return value
}

const formatUnorderedAbbreviation = ({ prop, value, selector }, { mode }) => {
const originalValue = value
const values = Array.isArray(value) ? value : parseValues(value)
Expand Down Expand Up @@ -373,7 +386,11 @@ module.exports = function getSpec ({ warn, error }) {
return
}
used[matchedProp] = true
pushAbbreviationValue(cssMap, matchedProp, value)
const normalizedValue = prop === 'text-decoration'
? normalizeTextDecorationValue(matchedProp, value, selector, mode)
: value
if (normalizedValue === false) return
pushAbbreviationValue(cssMap, matchedProp, normalizedValue)
})
if (prop === 'text-decoration') {
if (hasUnderline || hasLineThrough) {
Expand Down Expand Up @@ -929,6 +946,18 @@ module.exports = function getSpec ({ warn, error }) {
return formatUnorderedAbbreviation({ prop, value, selector }, { mode })
}

// Android/Harmony 平台的 text-decoration-style 只按 solid 生效
const formatTextDecorationStyle = ({ prop, value, selector }, { mode }) => {
Comment thread
dos1in marked this conversation as resolved.
value = value.trim()
if (!verifyValues({ prop, value, selector })) return false
return { prop, value: normalizeTextDecorationValue('textDecorationStyle', value, selector, mode) }
}

const formatTextDecorationColor = ({ prop, value, selector }, { mode }) => {
value = value.trim()
return verifyValues({ prop, value, selector }) && normalizeTextDecorationValue('textDecorationColor', value, selector, mode) && { prop, value }
}

return {
supportedModes: ['ios', 'android', 'harmony'],
rules: [
Expand Down Expand Up @@ -986,6 +1015,16 @@ module.exports = function getSpec ({ warn, error }) {
android: formatBorder,
harmony: formatBorder
},
{
test: 'text-decoration-style',
android: formatTextDecorationStyle,
harmony: formatTextDecorationStyle
},
{
test: 'text-decoration-color',
android: formatTextDecorationColor,
harmony: formatTextDecorationColor
},
// 通用的简写格式匹配
{
test: new RegExp('^(' + Object.keys(AbbreviationMap).join('|') + ')$'),
Expand Down
44 changes: 44 additions & 0 deletions packages/webpack-plugin/test/platform/wx/style/style-rn.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,50 @@ describe('React Native style validation for CSS variables', () => {
expect(config.error).not.toHaveBeenCalled()
})

test('should normalize text-decoration style and drop color on android', () => {
const css = '.dec { text-decoration: underline dotted red; } .style { text-decoration-style: dashed; } .color { text-decoration-color: blue; }'
const config = createConfig('android')

const result = getClassMap({
content: css,
filename: 'test.css',
...config
})

expect(result.dec).toEqual({
textDecorationLine: '"underline"',
textDecorationStyle: '"solid"'
})
expect(result.style).toEqual({
textDecorationStyle: '"solid"'
})
expect(result.color).toBeUndefined()
expect(config.warn).toHaveBeenCalledTimes(4)
expect(config.error).not.toHaveBeenCalled()
})

test('should normalize text-decoration style and drop color on harmony', () => {
const css = '.dec { text-decoration: underline dotted red; } .style { text-decoration-style: dashed; } .color { text-decoration-color: blue; }'
const config = createConfig('harmony')

const result = getClassMap({
content: css,
filename: 'test.css',
...config
})

expect(result.dec).toEqual({
textDecorationLine: '"underline"',
textDecorationStyle: '"solid"'
})
expect(result.style).toEqual({
textDecorationStyle: '"solid"'
})
expect(result.color).toBeUndefined()
expect(config.warn).toHaveBeenCalledTimes(4)
expect(config.error).not.toHaveBeenCalled()
})

test('should expand unordered flex-flow and text-shadow shorthand', () => {
const css = '.flow { flex-flow: wrap row; } .shadow { text-shadow: red 1px 2px 3px; } .shadow2 { text-shadow: 1px 2px red; }'
const config = createConfig()
Expand Down
Loading