normalizeProp.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { isArray, isString, isObject, hyphenate } from './'
  2. import { isNoUnitNumericStyleProp } from './domAttrConfig'
  3. export type NormalizedStyle = Record<string, string | number>
  4. export function normalizeStyle(
  5. value: unknown
  6. ): NormalizedStyle | string | undefined {
  7. if (isArray(value)) {
  8. const res: NormalizedStyle = {}
  9. for (let i = 0; i < value.length; i++) {
  10. const item = value[i]
  11. const normalized = isString(item)
  12. ? parseStringStyle(item)
  13. : (normalizeStyle(item) as NormalizedStyle)
  14. if (normalized) {
  15. for (const key in normalized) {
  16. res[key] = normalized[key]
  17. }
  18. }
  19. }
  20. return res
  21. } else if (isString(value)) {
  22. return value
  23. } else if (isObject(value)) {
  24. return value
  25. }
  26. }
  27. const listDelimiterRE = /;(?![^(]*\))/g
  28. const propertyDelimiterRE = /:(.+)/
  29. export function parseStringStyle(cssText: string): NormalizedStyle {
  30. const ret: NormalizedStyle = {}
  31. cssText.split(listDelimiterRE).forEach(item => {
  32. if (item) {
  33. const tmp = item.split(propertyDelimiterRE)
  34. tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim())
  35. }
  36. })
  37. return ret
  38. }
  39. export function stringifyStyle(
  40. styles: NormalizedStyle | string | undefined
  41. ): string {
  42. let ret = ''
  43. if (!styles || isString(styles)) {
  44. return ret
  45. }
  46. for (const key in styles) {
  47. const value = styles[key]
  48. const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key)
  49. if (
  50. isString(value) ||
  51. (typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))
  52. ) {
  53. // only render valid values
  54. ret += `${normalizedKey}:${value};`
  55. }
  56. }
  57. return ret
  58. }
  59. export function normalizeClass(value: unknown): string {
  60. let res = ''
  61. if (isString(value)) {
  62. res = value
  63. } else if (isArray(value)) {
  64. for (let i = 0; i < value.length; i++) {
  65. const normalized = normalizeClass(value[i])
  66. if (normalized) {
  67. res += normalized + ' '
  68. }
  69. }
  70. } else if (isObject(value)) {
  71. for (const name in value) {
  72. if (value[name]) {
  73. res += name + ' '
  74. }
  75. }
  76. }
  77. return res.trim()
  78. }
  79. export function normalizeProps(props: Record<string, any> | null) {
  80. if (!props) return null
  81. let { class: klass, style } = props
  82. if (klass && !isString(klass)) {
  83. props.class = normalizeClass(klass)
  84. }
  85. if (style) {
  86. props.style = normalizeStyle(style)
  87. }
  88. return props
  89. }