Skip to content

Commit

Permalink
fix: remove some any (vercel#547)
Browse files Browse the repository at this point in the history
## Description
There are many uses of `any` throughout the codebase. We could aim to
tighten up the typings to be more precise. This PR makes only small
improvements, but please share any thoughts on further changes we could
make or naming conventions to standardize on. I want you to know that
all feedback is welcome. <3

@Jackie1210 @shuding.
  • Loading branch information
LuciNyan authored and sahithyandev committed Apr 26, 2024
1 parent 23199e1 commit 0bf5f49
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 103 deletions.
66 changes: 28 additions & 38 deletions src/handler/index.ts → src/handler/compute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ import type { Node as YogaNode } from 'yoga-wasm-web'
import getYoga from '../yoga/index.js'
import presets from './presets.js'
import inheritable from './inheritable.js'
import expand from './expand.js'
import expand, { SerializedStyle } from './expand.js'
import { lengthToNumber, parseViewBox, v } from '../utils.js'
import { resolveImageData } from './image.js'

type SatoriElement = keyof typeof presets

export default async function handler(
export default async function compute(
node: YogaNode,
type: SatoriElement | string,
inheritedStyle: Record<string, string | number>,
inheritedStyle: SerializedStyle,
definedStyle: Record<string, string | number>,
props: Record<string, any>
): Promise<[Record<string, string | number>, Record<string, string | number>]> {
): Promise<[SerializedStyle, SerializedStyle]> {
const Yoga = await getYoga()

// Extend the default style with defined and inherited styles.
const style = {
const style: SerializedStyle = {
...inheritedStyle,
...expand(presets[type], inheritedStyle),
...expand(definedStyle, inheritedStyle),
Expand All @@ -52,15 +52,15 @@ export default async function handler(
// we must subtract the padding and border due to how box model works.
// TODO: Ensure these are absolute length values, not relative values.
let extraHorizontal =
((style.borderLeftWidth as number) || 0) +
((style.borderRightWidth as number) || 0) +
((style.paddingLeft as number) || 0) +
((style.paddingRight as number) || 0)
(style.borderLeftWidth || 0) +
(style.borderRightWidth || 0) +
(style.paddingLeft || 0) +
(style.paddingRight || 0)
let extraVertical =
((style.borderTopWidth as number) || 0) +
((style.borderBottomWidth as number) || 0) +
((style.paddingTop as number) || 0) +
((style.paddingBottom as number) || 0)
(style.borderTopWidth || 0) +
(style.borderBottomWidth || 0) +
(style.paddingTop || 0) +
(style.paddingBottom || 0)

let contentBoxWidth = style.width || props.width
let contentBoxHeight = style.height || props.height
Expand Down Expand Up @@ -122,7 +122,7 @@ export default async function handler(
} else {
height = lengthToNumber(
height,
inheritedStyle.fontSize as number,
inheritedStyle.fontSize,
1,
inheritedStyle
)
Expand All @@ -136,7 +136,7 @@ export default async function handler(
} else {
width = lengthToNumber(
width,
inheritedStyle.fontSize as number,
inheritedStyle.fontSize,
1,
inheritedStyle
)
Expand All @@ -145,21 +145,13 @@ export default async function handler(
} else {
if (typeof width !== 'undefined') {
width =
lengthToNumber(
width,
inheritedStyle.fontSize as number,
1,
inheritedStyle
) || width
lengthToNumber(width, inheritedStyle.fontSize, 1, inheritedStyle) ||
width
}
if (typeof height !== 'undefined') {
height =
lengthToNumber(
height,
inheritedStyle.fontSize as number,
1,
inheritedStyle
) || height
lengthToNumber(height, inheritedStyle.fontSize, 1, inheritedStyle) ||
height
}
width ||= viewBoxSize?.[2]
height ||= viewBoxSize?.[3]
Expand Down Expand Up @@ -275,27 +267,25 @@ export default async function handler(
)

if (typeof style.gap !== 'undefined') {
node.setGap(Yoga.GUTTER_ALL, style.gap as number)
node.setGap(Yoga.GUTTER_ALL, style.gap)
}

if (typeof style.rowGap !== 'undefined') {
node.setGap(Yoga.GUTTER_ROW, style.rowGap as number)
node.setGap(Yoga.GUTTER_ROW, style.rowGap)
}

if (typeof style.columnGap !== 'undefined') {
node.setGap(Yoga.GUTTER_COLUMN, style.columnGap as number)
node.setGap(Yoga.GUTTER_COLUMN, style.columnGap)
}

// @TODO: node.setFlex

if (typeof style.flexBasis !== 'undefined') {
node.setFlexBasis(style.flexBasis)
}
node.setFlexGrow(
typeof style.flexGrow === 'undefined' ? 0 : (style.flexGrow as number)
)
node.setFlexGrow(typeof style.flexGrow === 'undefined' ? 0 : style.flexGrow)
node.setFlexShrink(
typeof style.flexShrink === 'undefined' ? 0 : (style.flexShrink as number)
typeof style.flexShrink === 'undefined' ? 0 : style.flexShrink
)

if (typeof style.maxHeight !== 'undefined') {
Expand Down Expand Up @@ -328,10 +318,10 @@ export default async function handler(
node.setMargin(Yoga.EDGE_LEFT, style.marginLeft || 0)
node.setMargin(Yoga.EDGE_RIGHT, style.marginRight || 0)

node.setBorder(Yoga.EDGE_TOP, (style.borderTopWidth as number) || 0)
node.setBorder(Yoga.EDGE_BOTTOM, (style.borderBottomWidth as number) || 0)
node.setBorder(Yoga.EDGE_LEFT, (style.borderLeftWidth as number) || 0)
node.setBorder(Yoga.EDGE_RIGHT, (style.borderRightWidth as number) || 0)
node.setBorder(Yoga.EDGE_TOP, style.borderTopWidth || 0)
node.setBorder(Yoga.EDGE_BOTTOM, style.borderBottomWidth || 0)
node.setBorder(Yoga.EDGE_LEFT, style.borderLeftWidth || 0)
node.setBorder(Yoga.EDGE_RIGHT, style.borderRightWidth || 0)

node.setPadding(Yoga.EDGE_TOP, style.paddingTop || 0)
node.setPadding(Yoga.EDGE_BOTTOM, style.paddingBottom || 0)
Expand Down
114 changes: 78 additions & 36 deletions src/handler/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { parse as parseBoxShadow } from 'css-box-shadow'
import cssColorParse from 'parse-css-color'

import CssDimension from '../vendor/parse-css-dimension/index.js'
import parseTransformOrigin from '../transform-origin.js'
import parseTransformOrigin, {
ParsedTransformOrigin,
} from '../transform-origin.js'
import { isString, lengthToNumber, v } from '../utils.js'
import { parseMask } from '../parser/mask.js'
import { MaskProperty, parseMask } from '../parser/mask.js'

// https://react-cn.github.io/react/tips/style-props-value-px.html
const optOutPx = new Set([
Expand Down Expand Up @@ -242,24 +244,58 @@ function normalizeColor(value: string | object) {
return value
}

type MainStyle = {
color: string
fontSize: number
transformOrigin: ParsedTransformOrigin
maskImage: MaskProperty[]
opacity: number
textTransform: string
whiteSpace: string
wordBreak: string
textAlign: string
lineHeight: number

borderTopWidth: number
borderLeftWidth: number
borderRightWidth: number
borderBottomWidth: number

paddingTop: number
paddingLeft: number
paddingRight: number
paddingBottom: number

flexGrow: number
flexShrink: number

gap: number
rowGap: number
columnGap: number
}

type OtherStyle = Exclude<Record<PropertyKey, string | number>, keyof MainStyle>

export type SerializedStyle = Partial<MainStyle & OtherStyle>

export default function expand(
style: Record<string, string | number> | undefined,
inheritedStyle: Record<string, string | number>
): Record<string, string | number> {
const transformedStyle = {} as any
inheritedStyle: SerializedStyle
): SerializedStyle {
const serializedStyle: SerializedStyle = {}

if (style) {
const currentColor = getCurrentColor(
style.color as string,
inheritedStyle.color as string
inheritedStyle.color
)

transformedStyle.color = currentColor
serializedStyle.color = currentColor

for (const prop in style) {
// Internal properties.
if (prop.startsWith('_')) {
transformedStyle[prop] = style[prop]
serializedStyle[prop] = style[prop]
continue
}

Expand All @@ -280,7 +316,7 @@ export default function expand(
currentColor
)

Object.assign(transformedStyle, resolvedStyle)
Object.assign(serializedStyle, resolvedStyle)
} catch (err) {
throw new Error(
err.message +
Expand All @@ -295,39 +331,38 @@ export default function expand(
}

// Parse background images.
if (transformedStyle.backgroundImage) {
const { backgrounds } = parseElementStyle(transformedStyle)
transformedStyle.backgroundImage = backgrounds
if (serializedStyle.backgroundImage) {
const { backgrounds } = parseElementStyle(serializedStyle)
serializedStyle.backgroundImage = backgrounds
}

if (transformedStyle.maskImage || transformedStyle['WebkitMaskImage']) {
const mask = parseMask(transformedStyle)
transformedStyle.maskImage = mask
if (serializedStyle.maskImage || serializedStyle['WebkitMaskImage']) {
serializedStyle.maskImage = parseMask(serializedStyle)
}

// Calculate the base font size.
const baseFontSize = calcBaseFontSize(
transformedStyle.fontSize,
inheritedStyle.fontSize as number
serializedStyle.fontSize,
inheritedStyle.fontSize
)
if (typeof transformedStyle.fontSize !== 'undefined') {
transformedStyle.fontSize = baseFontSize
if (typeof serializedStyle.fontSize !== 'undefined') {
serializedStyle.fontSize = baseFontSize
}

if (transformedStyle.transformOrigin) {
transformedStyle.transformOrigin = parseTransformOrigin(
transformedStyle.transformOrigin,
if (serializedStyle.transformOrigin) {
serializedStyle.transformOrigin = parseTransformOrigin(
serializedStyle.transformOrigin as any,
baseFontSize
)
}

for (const prop in transformedStyle) {
let value = transformedStyle[prop]
for (const prop in serializedStyle) {
let value = serializedStyle[prop]

// Line height needs to be relative.
if (prop === 'lineHeight') {
if (typeof value === 'string') {
value = transformedStyle[prop] =
value = serializedStyle[prop] =
lengthToNumber(
value,
baseFontSize,
Expand All @@ -345,25 +380,26 @@ export default function expand(
baseFontSize,
inheritedStyle
)
if (typeof len !== 'undefined') transformedStyle[prop] = len
value = transformedStyle[prop]
if (typeof len !== 'undefined') serializedStyle[prop] = len
value = serializedStyle[prop]
}

if (typeof value === 'string' || typeof value === 'object') {
const color = normalizeColor(value)
if (color) transformedStyle[prop] = color
value = transformedStyle[prop]
if (color) {
serializedStyle[prop] = color as any
}
value = serializedStyle[prop]
}
}

// Inherit the opacity.
if (prop === 'opacity') {
value = transformedStyle[prop] =
value * (inheritedStyle.opacity as number)
if (prop === 'opacity' && typeof value === 'number') {
serializedStyle.opacity = value * inheritedStyle.opacity
}

if (prop === 'transform') {
const transforms = value as { [type: string]: number | string }[]
const transforms = value as any as { [type: string]: number | string }[]

for (const transform of transforms) {
const type = Object.keys(transform)[0]
Expand All @@ -380,10 +416,13 @@ export default function expand(
}
}

return transformedStyle
return serializedStyle
}

function calcBaseFontSize(size: number | string, inheritedSize: number) {
function calcBaseFontSize(
size: number | string,
inheritedSize: number
): number {
if (typeof size === 'number') return size

try {
Expand Down Expand Up @@ -415,7 +454,10 @@ function refineHSL(color: string) {
return color
}

function getCurrentColor(color: string | undefined, inheritedColor: string) {
function getCurrentColor(
color: string | undefined,
inheritedColor: string
): string {
if (color && color.toLowerCase() !== 'currentcolor') {
return refineHSL(color)
}
Expand Down
6 changes: 4 additions & 2 deletions src/handler/inheritable.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SerializedStyle } from './expand.js'

const list = new Set([
'color',
'font',
Expand Down Expand Up @@ -33,8 +35,8 @@ const list = new Set([
'_inheritedBackgroundClipTextPath',
])

export default function inheritable(style: Record<string, any>) {
const inheritedStyle: Record<string, any> = {}
export default function inheritable(style: SerializedStyle): SerializedStyle {
const inheritedStyle: SerializedStyle = {}
for (const prop in style) {
if (list.has(prop)) {
inheritedStyle[prop] = style[prop]
Expand Down
Loading

0 comments on commit 0bf5f49

Please sign in to comment.