Skip to content

Commit

Permalink
fix: use splitEffects to split multiple effects (#553)
Browse files Browse the repository at this point in the history
We always need to handle mutiple effects. Let's give it a fn and add
some tests
  • Loading branch information
Jackie1210 authored Sep 22, 2023
1 parent fc356ec commit bdd0dca
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 54 deletions.
27 changes: 2 additions & 25 deletions src/handler/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import CssDimension from '../vendor/parse-css-dimension/index.js'
import parseTransformOrigin, {
ParsedTransformOrigin,
} from '../transform-origin.js'
import { isString, lengthToNumber, v } from '../utils.js'
import { isString, lengthToNumber, v, splitEffects } from '../utils.js'
import { MaskProperty, parseMask } from '../parser/mask.js'

// https://react-cn.github.io/react/tips/style-props-value-px.html
Expand Down Expand Up @@ -173,7 +173,7 @@ function handleSpecialCase(
// Handle multiple text shadows if provided.
value = value.toString().trim()
if (value.includes(',')) {
const shadows = splitTextShadow(value)
const shadows = splitEffects(value)
const result = {}
for (const shadow of shadows) {
const styles = getStylesForProperty('textShadow', shadow, true)
Expand All @@ -192,29 +192,6 @@ function handleSpecialCase(
return
}

function splitTextShadow(str: string) {
const result: string[] = []
let skip = false
let startPos = 0
const len = str.length

for (let i = 0; i < len; ++i) {
const t = str[i]
if (t === ')') skip = false
if (skip) continue
if (t === '(') skip = true

if (t === ',') {
result.push(str.substring(startPos, i))
startPos = i + 1
}
}

result.push(str.substring(startPos, len))

return result.map((s) => s.trim())
}

function getErrorHint(name: string) {
if (name === 'transform') {
return ' Only absolute lengths such as `10px` are supported.'
Expand Down
31 changes: 2 additions & 29 deletions src/parser/mask.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getPropertyName } from 'css-to-react-native'
import { splitEffects } from '../utils.js'

function getMaskProperty(style: Record<string, string | number>, name: string) {
const key = getPropertyName(`mask-${name}`)
Expand All @@ -14,34 +15,6 @@ export interface MaskProperty {
clip: string
}

function splitMaskImages(maskImage) {
let maskImages = []
let start = 0
let parenCount = 0

for (let i = 0; i < maskImage.length; i++) {
if (maskImage[i] === '(') {
parenCount++
} else if (maskImage[i] === ')') {
parenCount--
}

if (parenCount === 0 && maskImage[i] === ',') {
maskImages.push(maskImage.slice(start, i).trim())
start = i + 1
}
}

maskImages.push(maskImage.slice(start).trim())

return maskImages
}

/**
* url(https:a.png), linear-gradient(blue, red) => [url(https:a.png), linear-gradient(blue, red)]
* rgba(0,0,0,.7) => [rgba(0,0,0,.7)]
*/

export function parseMask(
style: Record<string, string | number>
): MaskProperty[] {
Expand All @@ -55,7 +28,7 @@ export function parseMask(
clip: getMaskProperty(style, 'origin') || 'border-box',
}

let maskImages = splitMaskImages(maskImage).filter((v) => v && v !== 'none')
let maskImages = splitEffects(maskImage).filter((v) => v && v !== 'none')

return maskImages.reverse().map((m) => ({
image: m,
Expand Down
27 changes: 27 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,30 @@ export const midline = (s: string) => {
(_, letter: string) => `-${letter.toLowerCase()}`
)
}

export function splitEffects(
input: string,
separator: string | RegExp = ','
): string[] {
const result = []
let l = 0
let parenCount = 0
separator = new RegExp(separator)

for (let i = 0; i < input.length; i++) {
if (input[i] === '(') {
parenCount++
} else if (input[i] === ')') {
parenCount--
}

if (parenCount === 0 && separator.test(input[i])) {
result.push(input.slice(l, i).trim())
l = i + 1
}
}

result.push(input.slice(l).trim())

return result
}
34 changes: 34 additions & 0 deletions test/units.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { it, describe, expect } from 'vitest'

import { initFonts, toImage } from './utils.js'
import satori from '../src/index.js'
import { splitEffects } from '../src/utils.js'

describe('Units', () => {
let fonts
Expand Down Expand Up @@ -133,4 +134,37 @@ describe('Units', () => {
)
expect(toImage(svg, 100)).toMatchImageSnapshot()
})

it('should support split multiple effect', () => {
const tests = {
'url(https:a.png), linear-gradient(blue, red)': [
'url(https:a.png)',
'linear-gradient(blue, red)',
],
'rgba(0,0,0,.7)': ['rgba(0,0,0,.7)'],
'1px 1px 2px black, 0 0 1em blue': ['1px 1px 2px black', '0 0 1em blue'],
'2px 2px red, 4px 4px #4bf542, 6px 6px rgba(186, 147, 17, 30%)': [
'2px 2px red',
'4px 4px #4bf542',
'6px 6px rgba(186, 147, 17, 30%)',
],
}

for (const [k, v] of Object.entries(tests)) {
expect(splitEffects(k, ',')).toEqual(v)
}

;[' ', /\s{1}/].forEach((v) => {
expect(
splitEffects(
'drop-shadow(4px 4px 10px blue) blur(4px) saturate(150%)',
v
)
).toEqual([
'drop-shadow(4px 4px 10px blue)',
'blur(4px)',
'saturate(150%)',
])
})
})
})

0 comments on commit bdd0dca

Please sign in to comment.