- Replace calc.ts (150 lines) with expr-eval library - Replace rgbLuminance with culori wcagLuminance - Use @iconify/utils iconToSVG for viewBox normalization in iconify.ts - Extract describe-shared.ts: findAncestorBackground, looksLikeButton, CONTAINER_TYPES - Extract icon-render.ts: shared createIconFromPaths for create.ts and renderer.ts - Inline codegen prompt as TS constant, remove runtime fs.readFile from MCP server - Fix blur effect color alpha (a:1 → a:0) - Encapsulate module-level mutable state in src/ai/tools.ts into RunState class - Add network check to iconify tests (skip gracefully offline) - Remove Caddyfile.dev and components.d.ts from tracking, add to .gitignore
68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
import { parseColor } from './color'
|
|
|
|
import type { Color } from './types'
|
|
import type { SceneGraph, SceneNode, Stroke } from './scene-graph'
|
|
import type { IconData } from './iconify'
|
|
|
|
const STROKE_CAP_MAP: Record<string, SceneNode['strokeCap']> = {
|
|
butt: 'NONE', round: 'ROUND', square: 'SQUARE'
|
|
}
|
|
|
|
const STROKE_JOIN_MAP: Record<string, SceneNode['strokeJoin']> = {
|
|
miter: 'MITER', round: 'ROUND', bevel: 'BEVEL'
|
|
}
|
|
|
|
export function createIconFromPaths(
|
|
graph: SceneGraph,
|
|
icon: IconData,
|
|
name: string,
|
|
size: number,
|
|
color: Color,
|
|
parentId: string,
|
|
overrides?: Partial<SceneNode>
|
|
): SceneNode {
|
|
const frame = graph.createNode('FRAME', parentId, {
|
|
name: `Icon / ${name}`,
|
|
width: size,
|
|
height: size,
|
|
fills: [],
|
|
...overrides
|
|
})
|
|
|
|
for (const path of icon.paths) {
|
|
const vector = graph.createNode('VECTOR', frame.id, {
|
|
name: 'path',
|
|
width: size,
|
|
height: size,
|
|
vectorNetwork: path.vectorNetwork
|
|
})
|
|
vector.x = 0
|
|
vector.y = 0
|
|
|
|
if (path.fill) {
|
|
const fillColor = path.fill === 'currentColor' ? color : parseColor(path.fill)
|
|
graph.updateNode(vector.id, {
|
|
fills: [{ type: 'SOLID', color: fillColor, opacity: 1, visible: true }]
|
|
})
|
|
} else {
|
|
graph.updateNode(vector.id, { fills: [] })
|
|
}
|
|
|
|
if (path.stroke) {
|
|
const strokeColor = path.stroke === 'currentColor' ? color : parseColor(path.stroke)
|
|
const stroke: Stroke = {
|
|
color: strokeColor,
|
|
weight: path.strokeWidth,
|
|
opacity: 1,
|
|
visible: true,
|
|
align: 'CENTER',
|
|
cap: STROKE_CAP_MAP[path.strokeCap] ?? 'NONE',
|
|
join: STROKE_JOIN_MAP[path.strokeJoin] ?? 'MITER'
|
|
}
|
|
graph.updateNode(vector.id, { strokes: [stroke] })
|
|
}
|
|
}
|
|
|
|
return frame
|
|
}
|