From 6a09e5e0f3290babf4586ffe46e37c56ecb46a58 Mon Sep 17 00:00:00 2001 From: Justineo Date: Sun, 8 Feb 2026 10:11:00 +0800 Subject: [PATCH] refactor(graphic): simplify runtime internals --- src/graphic/build-helpers.ts | 26 ++--- src/graphic/build.ts | 59 ++++++----- src/graphic/collector.ts | 113 +++++++------------- src/graphic/component-factory.ts | 55 ++++------ src/graphic/extension.ts | 128 ++++++++++------------- src/graphic/mount.ts | 26 ++--- tests/graphic-components.browser.test.ts | 4 - tests/graphic-extension.node.test.ts | 6 +- tests/graphic-mount.node.test.ts | 10 +- tests/graphic.node.test.ts | 3 - 10 files changed, 185 insertions(+), 245 deletions(-) diff --git a/src/graphic/build-helpers.ts b/src/graphic/build-helpers.ts index 7f056ae..0f0bc26 100644 --- a/src/graphic/build-helpers.ts +++ b/src/graphic/build-helpers.ts @@ -11,43 +11,43 @@ export function mergeProps( keys: readonly string[], props: Record, ): void { - keys.forEach((key) => { + for (const key of keys) { if (props[key] !== undefined) { target[key] = props[key]; } - }); + } } export function buildStyle( props: Record, extraKeys: readonly string[], ): Record | undefined { - const style = { ...(props.style as Record | undefined) }; - mergeProps(style, BASE_STYLE_KEYS, props); - mergeProps(style, extraKeys, props); + const out = { ...(props.style as Record | undefined) }; + mergeProps(out, BASE_STYLE_KEYS, props); + mergeProps(out, extraKeys, props); if (props.styleTransition !== undefined) { - style.transition = props.styleTransition; + out.transition = props.styleTransition; } - return Object.keys(style).length > 0 ? style : undefined; + return Object.keys(out).length ? out : undefined; } export function buildShape( type: string, props: Record, ): Record | undefined { - const shape = { ...(props.shape as Record | undefined) }; - const shapeKeys = SHAPE_KEYS_BY_TYPE[type]; - if (shapeKeys) { - mergeProps(shape, shapeKeys, props); + const out = { ...(props.shape as Record | undefined) }; + const keys = SHAPE_KEYS_BY_TYPE[type]; + if (keys) { + mergeProps(out, keys, props); } if (props.shapeTransition !== undefined) { - shape.transition = props.shapeTransition; + out.transition = props.shapeTransition; } - return Object.keys(shape).length > 0 ? shape : undefined; + return Object.keys(out).length ? out : undefined; } export function buildInfo(node: GraphicNode): unknown { diff --git a/src/graphic/build.ts b/src/graphic/build.ts index 39b5d69..3f0d132 100644 --- a/src/graphic/build.ts +++ b/src/graphic/build.ts @@ -16,45 +16,43 @@ type BuildResult = { snapshot: GraphicSnapshot; }; -function buildElementOption(node: GraphicNode, children: Option[] | undefined): Option { - const element: Record = { +function toElement(node: GraphicNode, children?: Option[]): Option { + const out: Record = { type: node.type, id: node.id, }; - const common = pruneCommonPropsByType(node.type, pickCommonProps(node.props)); - Object.assign(element, common); + Object.assign(out, pruneCommonPropsByType(node.type, pickCommonProps(node.props))); if (isGroupGraphic(node.type)) { - if (children) { - element.children = children; + if (children?.length) { + out.children = children; } const info = buildInfo(node); if (info !== undefined) { - element.info = info; + out.info = info; } - return element as Option; + return out as Option; } - const shapeKeys = SHAPE_KEYS_BY_TYPE[node.type]; - if (shapeKeys) { + if (SHAPE_KEYS_BY_TYPE[node.type]) { const shape = buildShape(node.type, node.props); if (shape) { - element.shape = shape; + out.shape = shape; } } const style = buildStyle(node.props, styleKeysByType(node.type)); if (style) { - element.style = style; + out.style = style; } const info = buildInfo(node); if (info !== undefined) { - element.info = info; + out.info = info; } - return element as Option; + return out as Option; } export function buildGraphicOption(nodes: Iterable, rootId: string): BuildResult { @@ -65,9 +63,12 @@ export function buildGraphicOption(nodes: Iterable, rootId: string) let hasDuplicateId = false; for (const node of nodes) { - const list = byParent.get(node.parentId) ?? []; - list.push(node); - byParent.set(node.parentId, list); + const list = byParent.get(node.parentId); + if (list) { + list.push(node); + } else { + byParent.set(node.parentId, [node]); + } if (ids.has(node.id)) { hasDuplicateId = true; @@ -82,24 +83,24 @@ export function buildGraphicOption(nodes: Iterable, rootId: string) const snapshot: GraphicSnapshot = { ids, parentById, hasDuplicateId }; - const buildChildren = (parentId: string | null): Option[] => { - const children = byParent.get(parentId) ?? []; - return children.map((child) => - buildElementOption(child, child.type === "group" ? buildChildren(child.id) : undefined), + const childrenOf = (parentId: string | null): Option[] => { + const list = byParent.get(parentId) ?? []; + return list.map((node) => + toElement(node, node.type === "group" ? childrenOf(node.id) : undefined), ); }; - const root: Record = { - type: "group", - id: rootId, - $action: "replace", - children: buildChildren(null), - }; - return { option: { graphic: { - elements: [root], + elements: [ + { + type: "group", + id: rootId, + $action: "replace", + children: childrenOf(null), + }, + ], }, } as Option, snapshot, diff --git a/src/graphic/collector.ts b/src/graphic/collector.ts index 8334a5c..9134d3b 100644 --- a/src/graphic/collector.ts +++ b/src/graphic/collector.ts @@ -29,49 +29,39 @@ export type GraphicCollector = { optionRef: Ref