diff --git a/AGENTS.md b/AGENTS.md index 886b5af0d..431d68518 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ This file holds the repository map and the rules that apply everywhere. Rules fo | `packages/kiwi` | SceneGraph-independent Kiwi schema/runtime, codecs, containers, parse helpers | `packages/fig/AGENTS.md` | | `packages/fig` | `.fig` archives, SceneGraph conversion, metadata policy, component/instance interpretation, Figma clipboard | `packages/fig/AGENTS.md` | | `packages/core` | Renderer, layout, editor, Figma API, tools, clipboard, vector conversion, document I/O; depends on scene-graph and the format packages (pen, kiwi, fig, dom-css); no browser DOM | `packages/core/AGENTS.md` | -| `packages/dom-css` | DOM/CSS/HTML/JSX/Tailwind projection and browser/headless adapters; depends only on scene-graph and takes engine services such as web-font resolution as injected options | — | +| `packages/dom-css` | DOM/CSS/HTML/JSX/Tailwind projection and browser/headless adapters; depends only on scene-graph and takes engine services such as web-font resolution as injected options | `packages/dom-css/AGENTS.md` | | `packages/vue` | Headless Vue 3 SDK primitives, composables, commands, i18n, menu model | `packages/vue/AGENTS.md` | | `packages/cli` | Headless `.fig` inspection, export, linting, `eval` | `packages/cli/AGENTS.md` | | `packages/mcp` | stdio and Hono HTTP MCP server reusing Core tools | `packages/mcp/AGENTS.md` | diff --git a/packages/dom-css/AGENTS.md b/packages/dom-css/AGENTS.md new file mode 100644 index 000000000..250111460 --- /dev/null +++ b/packages/dom-css/AGENTS.md @@ -0,0 +1,14 @@ +# DOM/CSS + +DOM, CSS, HTML, JSX, and Tailwind projection between documents and SceneGraph, with browser and headless CSS runtimes. Sources are grouped by direction: + +- `src/import/` — HTML, CSS, JSX, and Tailwind to SceneGraph, including the `jsx-runtime` entries and CSS value parsing. +- `src/export/` — SceneGraph to HTML, Tailwind JSX, and Storybook: projection, CSS formatting, the HTML bundle, and printers. `src/export/index.ts` is the `./export` entry. +- `src/runtime/` — browser and headless CSS runtimes. + +Rules: + +- Depend only on `@open-pencil/scene-graph`. Engine services such as web-font resolution come in as options; Core registers the HTML and Tailwind JSX formats (`packages/core/AGENTS.md`). +- Keep the `./export` entry browser-safe: load `node:*` modules and the headless CSS object model lazily inside the functions that need them, so the app never bundles them. +- Build generated code as syntax trees printed with esrap, not string fragments; values JSX or TypeScript would reinterpret go through string literals. +- Imported documents are untrusted: check Base64 with `js-base64`'s `isValid` before decoding. diff --git a/packages/dom-css/package.json b/packages/dom-css/package.json index cafae83ab..28391fba9 100644 --- a/packages/dom-css/package.json +++ b/packages/dom-css/package.json @@ -25,19 +25,19 @@ }, "./export": { "types": "./dist/export.d.ts", - "bun": "./src/export.ts", + "bun": "./src/export/index.ts", "import": "./dist/export.js", "default": "./dist/export.js" }, "./jsx-runtime": { "types": "./dist/jsx-runtime.d.ts", - "bun": "./src/jsx/runtime.ts", + "bun": "./src/import/jsx/runtime.ts", "import": "./dist/jsx-runtime.js", "default": "./dist/jsx-runtime.js" }, "./jsx-dev-runtime": { "types": "./dist/jsx-dev-runtime.d.ts", - "bun": "./src/jsx/dev-runtime.ts", + "bun": "./src/import/jsx/dev-runtime.ts", "import": "./dist/jsx-dev-runtime.js", "default": "./dist/jsx-dev-runtime.js" } diff --git a/packages/dom-css/src/browser.ts b/packages/dom-css/src/browser.ts index f35f73441..e51f2a9d8 100644 --- a/packages/dom-css/src/browser.ts +++ b/packages/dom-css/src/browser.ts @@ -1,14 +1,14 @@ import type { SceneGraph } from '@open-pencil/scene-graph' -import { mergeCSSText } from './css-text' -import { jsxToDesignDocumentCore, type JSXChild } from './jsx/core' +import { mergeCSSText } from './import/css-text' +import { jsxToDesignDocumentCore, type JSXChild } from './import/jsx/core' +import { designDocumentToSceneGraph, type ToSceneGraphOptions } from './import/scene-graph' +import type { CompileTailwindCSSOptions } from './import/tailwind' import { createBrowserCSSRuntime, type BrowserCSSRuntimeOptions } from './runtime/browser' -import type { CompileTailwindCSSOptions } from './tailwind' -import { designDocumentToSceneGraph, type ToSceneGraphOptions } from './to-scene-graph' import type { CSSComputeOptions, DesignDocument } from './types' -export { Fragment, jsx, jsxs } from './jsx/core' -export type { JSXChild, JSXElementProps, JSXStyleInput, JSXTag } from './jsx/core' +export { Fragment, jsx, jsxs } from './import/jsx/core' +export type { JSXChild, JSXElementProps, JSXStyleInput, JSXTag } from './import/jsx/core' export interface BrowserToDesignDocumentOptions extends BrowserCSSRuntimeOptions { cssText?: string @@ -44,7 +44,7 @@ async function compileBrowserTailwindCSS( candidates: string | Iterable, options: CompileTailwindCSSOptions ): Promise { - const { compileTailwindCSS } = await import('./tailwind') + const { compileTailwindCSS } = await import('./import/tailwind') return compileTailwindCSS(candidates, options) } diff --git a/packages/dom-css/src/html-export.ts b/packages/dom-css/src/export/bundle.ts similarity index 99% rename from packages/dom-css/src/html-export.ts rename to packages/dom-css/src/export/bundle.ts index ff66a188e..b877abf12 100644 --- a/packages/dom-css/src/html-export.ts +++ b/packages/dom-css/src/export/bundle.ts @@ -4,8 +4,8 @@ import { parseFragment, serialize, type DefaultTreeAdapterTypes } from 'parse5' import { normalizeFontFamily } from '@open-pencil/scene-graph' -import { mergeClassNames, serializeHTML, splitWhitespace } from './serialize' -import type { DesignDocument, DesignElement, DesignNode, DesignStyleDeclaration } from './types' +import type { DesignDocument, DesignElement, DesignNode, DesignStyleDeclaration } from '../types' +import { mergeClassNames, serializeHTML, splitWhitespace } from './html' /** A font face the exported text uses. */ export interface WebFontFaceRequest { diff --git a/packages/dom-css/src/export/css.ts b/packages/dom-css/src/export/css.ts new file mode 100644 index 000000000..bc4f24b71 --- /dev/null +++ b/packages/dom-css/src/export/css.ts @@ -0,0 +1,59 @@ +import type { Effect, Fill, SceneNode, Stroke } from '@open-pencil/scene-graph' +import { colorToCSS, colorToHex } from '@open-pencil/scene-graph/color' +import type { Color } from '@open-pencil/scene-graph/primitives' + +import type { DesignStyleDeclaration } from '../types' + +/** Opaque colors as hex, which Tailwind matches to its palette; translucent ones as `rgba()`. */ +export function cssColor(color: Color): string { + return color.a >= 1 ? colorToHex(color) : colorToCSS(color) +} + +export function fillToCSS(fill: Fill | undefined): string | undefined { + if (fill?.type !== 'SOLID' || !fill.visible) return undefined + return cssColor({ ...fill.color, a: fill.opacity }) +} + +export function strokeColorToCSS(stroke: Stroke | undefined): string | undefined { + if (!stroke?.visible) return undefined + return cssColor({ ...stroke.color, a: stroke.opacity }) +} + +export function strokeToCSS(stroke: Stroke | undefined): string | undefined { + const color = strokeColorToCSS(stroke) + if (!color || !stroke) return undefined + return `${stroke.weight}px solid ${color}` +} + +function shadowToCSS(effect: Effect): string { + const inset = effect.type === 'INNER_SHADOW' ? 'inset ' : '' + return `${inset}${effect.offset.x}px ${effect.offset.y}px ${effect.radius}px ${effect.spread}px ${cssColor(effect.color)}` +} + +export function dropShadowToCSS(effect: Effect | undefined): string | undefined { + if (effect?.type !== 'DROP_SHADOW' || !effect.visible) return undefined + return shadowToCSS(effect) +} + +/** Every visible shadow, in order, plus layer and background blur. */ +export function effectsToCSS(effects: Effect[]): DesignStyleDeclaration { + const style: DesignStyleDeclaration = {} + const visible = effects.filter((effect) => effect.visible) + const shadows = visible.filter( + (effect) => effect.type === 'DROP_SHADOW' || effect.type === 'INNER_SHADOW' + ) + if (shadows.length > 0) style['box-shadow'] = shadows.map(shadowToCSS).join(', ') + for (const effect of visible) { + if (effect.type === 'LAYER_BLUR' || effect.type === 'FOREGROUND_BLUR') + style.filter = `blur(${effect.radius}px)` + if (effect.type === 'BACKGROUND_BLUR') style['backdrop-filter'] = `blur(${effect.radius}px)` + } + return style +} + +export function sceneNodeSizeStyle(node: SceneNode): DesignStyleDeclaration { + const style: DesignStyleDeclaration = {} + if (node.width > 0) style.width = `${node.width}px` + if (node.height > 0) style.height = `${node.height}px` + return style +} diff --git a/packages/dom-css/src/grid.ts b/packages/dom-css/src/export/grid.ts similarity index 96% rename from packages/dom-css/src/grid.ts rename to packages/dom-css/src/export/grid.ts index b18ff7651..7ad00d6c0 100644 --- a/packages/dom-css/src/grid.ts +++ b/packages/dom-css/src/export/grid.ts @@ -1,6 +1,6 @@ import type { GridTrack, SceneNode } from '@open-pencil/scene-graph' -import type { DesignStyleDeclaration } from './types' +import type { DesignStyleDeclaration } from '../types' function trackToCSS(track: GridTrack): string { if (track.sizing === 'FR') return `${track.value}fr` diff --git a/packages/dom-css/src/serialize.ts b/packages/dom-css/src/export/html.ts similarity index 99% rename from packages/dom-css/src/serialize.ts rename to packages/dom-css/src/export/html.ts index c8e7df63b..69d3c7d86 100644 --- a/packages/dom-css/src/serialize.ts +++ b/packages/dom-css/src/export/html.ts @@ -1,6 +1,6 @@ import { twirl } from 'twirlwind' -import type { DesignDocument, DesignElement, DesignNode, DesignText } from './types' +import type { DesignDocument, DesignElement, DesignNode, DesignText } from '../types' export interface SerializeHTMLOptions { style?: 'inline' | 'tailwind' diff --git a/packages/dom-css/src/export.ts b/packages/dom-css/src/export/index.ts similarity index 71% rename from packages/dom-css/src/export.ts rename to packages/dom-css/src/export/index.ts index a49e11f74..4629a17c9 100644 --- a/packages/dom-css/src/export.ts +++ b/packages/dom-css/src/export/index.ts @@ -1,8 +1,8 @@ // SceneGraph → HTML and JSX without the CSS runtimes, so browsers can bundle it. -export { sceneGraphToDesignDocument, sceneNodeToDesignDocument } from './from-scene-graph' -export { exportHTMLBundle } from './html-export' -export { designDocumentToTailwindJSX, sceneNodesToTailwindJSX } from './jsx/print' -export { serializeHTML } from './serialize' +export { sceneGraphToDesignDocument, sceneNodeToDesignDocument } from './projection' +export { exportHTMLBundle } from './bundle' +export { designDocumentToTailwindJSX, sceneNodesToTailwindJSX } from './tailwind-jsx' +export { serializeHTML } from './html' export type { ExportHTMLBundle, ExportHTMLBundleOptions, @@ -10,5 +10,5 @@ export type { WebFontFaceAsset, WebFontFaceRequest, WebFontFaceResolver -} from './html-export' -export type { DesignDocument, DesignElement, DesignNode } from './types' +} from './bundle' +export type { DesignDocument, DesignElement, DesignNode } from '../types' diff --git a/packages/dom-css/src/from-scene-graph.ts b/packages/dom-css/src/export/projection.ts similarity index 99% rename from packages/dom-css/src/from-scene-graph.ts rename to packages/dom-css/src/export/projection.ts index fe2c55066..503d20b2c 100644 --- a/packages/dom-css/src/from-scene-graph.ts +++ b/packages/dom-css/src/export/projection.ts @@ -4,6 +4,7 @@ import type { SceneGraph, SceneNode } from '@open-pencil/scene-graph' import { BLACK } from '@open-pencil/scene-graph/constants' import { resolveNodeTextDirection } from '@open-pencil/scene-graph/text-direction' +import type { DesignDocument, DesignNode, DesignStyleDeclaration } from '../types' import { cssColor, dropShadowToCSS, @@ -12,9 +13,8 @@ import { sceneNodeSizeStyle, strokeColorToCSS, strokeToCSS -} from './css-values' +} from './css' import { addGridContainer, addGridPlacement } from './grid' -import type { DesignDocument, DesignNode, DesignStyleDeclaration } from './types' const DOM_CSS_PLUGIN_ID = 'open-pencil-dom-css' const IMAGE_SOURCE_URL_KEY = 'image-source-url' diff --git a/packages/dom-css/src/storybook/estree.ts b/packages/dom-css/src/export/storybook/estree.ts similarity index 100% rename from packages/dom-css/src/storybook/estree.ts rename to packages/dom-css/src/export/storybook/estree.ts diff --git a/packages/dom-css/src/storybook/export.ts b/packages/dom-css/src/export/storybook/export.ts similarity index 96% rename from packages/dom-css/src/storybook/export.ts rename to packages/dom-css/src/export/storybook/export.ts index c916b6317..b99ecdf1e 100644 --- a/packages/dom-css/src/storybook/export.ts +++ b/packages/dom-css/src/export/storybook/export.ts @@ -1,8 +1,8 @@ import type { SceneGraph, SceneNode } from '@open-pencil/scene-graph' -import { sceneNodeToDesignDocument } from '../from-scene-graph' -import type { ExportHTMLFile } from '../html-export' -import { serializeHTML } from '../serialize' +import type { ExportHTMLFile } from '../bundle' +import { serializeHTML } from '../html' +import { sceneNodeToDesignDocument } from '../projection' import { collectGroups, type StoryGroup } from './groups' import { printStoryModule, type StoryDesign, type StorybookFramework } from './module' import { claimName, identifierName, storyId } from './names' diff --git a/packages/dom-css/src/storybook/groups.ts b/packages/dom-css/src/export/storybook/groups.ts similarity index 100% rename from packages/dom-css/src/storybook/groups.ts rename to packages/dom-css/src/export/storybook/groups.ts diff --git a/packages/dom-css/src/storybook/module.ts b/packages/dom-css/src/export/storybook/module.ts similarity index 100% rename from packages/dom-css/src/storybook/module.ts rename to packages/dom-css/src/export/storybook/module.ts diff --git a/packages/dom-css/src/storybook/names.ts b/packages/dom-css/src/export/storybook/names.ts similarity index 100% rename from packages/dom-css/src/storybook/names.ts rename to packages/dom-css/src/export/storybook/names.ts diff --git a/packages/dom-css/src/jsx/print.ts b/packages/dom-css/src/export/tailwind-jsx.ts similarity index 96% rename from packages/dom-css/src/jsx/print.ts rename to packages/dom-css/src/export/tailwind-jsx.ts index 2d83f02dd..2298f3ab1 100644 --- a/packages/dom-css/src/jsx/print.ts +++ b/packages/dom-css/src/export/tailwind-jsx.ts @@ -3,9 +3,9 @@ import tsx from 'esrap/languages/tsx' import type { SceneGraph } from '@open-pencil/scene-graph' -import { sceneNodeToDesignDocument } from '../from-scene-graph' -import { mergeClassNames, serializeTailwindClasses } from '../serialize' import type { DesignDocument, DesignElement, DesignNode } from '../types' +import { mergeClassNames, serializeTailwindClasses } from './html' +import { sceneNodeToDesignDocument } from './projection' /** A JSX node as esrap prints it. */ interface JSXNode { diff --git a/packages/dom-css/src/css-text.ts b/packages/dom-css/src/import/css-text.ts similarity index 100% rename from packages/dom-css/src/css-text.ts rename to packages/dom-css/src/import/css-text.ts diff --git a/packages/dom-css/src/css-values.ts b/packages/dom-css/src/import/css-values.ts similarity index 56% rename from packages/dom-css/src/css-values.ts rename to packages/dom-css/src/import/css-values.ts index af2654251..129344b64 100644 --- a/packages/dom-css/src/css-values.ts +++ b/packages/dom-css/src/import/css-values.ts @@ -1,10 +1,10 @@ import valueParser, { type ParsedNode } from 'postcss-value-parser' -import type { Effect, Fill, SceneNode, Stroke } from '@open-pencil/scene-graph' -import { colorToCSS, colorToHex, parseColor } from '@open-pencil/scene-graph/color' +import type { Effect, Fill, Stroke } from '@open-pencil/scene-graph' +import { parseColor } from '@open-pencil/scene-graph/color' import type { Color } from '@open-pencil/scene-graph/primitives' -import type { DesignStyleDeclaration } from './types' +import type { DesignStyleDeclaration } from '../types' const TRANSPARENT_KEYWORDS = new Set(['transparent', 'rgba(0, 0, 0, 0)', 'rgb(0 0 0 / 0)']) @@ -24,33 +24,12 @@ export function parseCSSColor(value: string | undefined): Color | null { return parseColor(trimmed) } -/** Opaque colors as hex, which Tailwind matches to its palette; translucent ones as `rgba()`. */ -export function cssColor(color: Color): string { - return color.a >= 1 ? colorToHex(color) : colorToCSS(color) -} - -export function fillToCSS(fill: Fill | undefined): string | undefined { - if (fill?.type !== 'SOLID' || !fill.visible) return undefined - return cssColor({ ...fill.color, a: fill.opacity }) -} - export function colorToFillFromCSS(value: string | undefined): Fill[] { const color = parseCSSColor(value) if (!color) return [] return [{ type: 'SOLID', color, opacity: color.a, visible: true }] } -export function strokeColorToCSS(stroke: Stroke | undefined): string | undefined { - if (!stroke?.visible) return undefined - return cssColor({ ...stroke.color, a: stroke.opacity }) -} - -export function strokeToCSS(stroke: Stroke | undefined): string | undefined { - const color = strokeColorToCSS(stroke) - if (!color || !stroke) return undefined - return `${stroke.weight}px solid ${color}` -} - export function colorToStrokeFromCSS( colorValue: string | undefined, weightValue: string | undefined @@ -61,32 +40,6 @@ export function colorToStrokeFromCSS( return [{ color, weight, opacity: color.a, visible: true, align: 'INSIDE' }] } -function shadowToCSS(effect: Effect): string { - const inset = effect.type === 'INNER_SHADOW' ? 'inset ' : '' - return `${inset}${effect.offset.x}px ${effect.offset.y}px ${effect.radius}px ${effect.spread}px ${cssColor(effect.color)}` -} - -export function dropShadowToCSS(effect: Effect | undefined): string | undefined { - if (effect?.type !== 'DROP_SHADOW' || !effect.visible) return undefined - return shadowToCSS(effect) -} - -/** Every visible shadow, in order, plus layer and background blur. */ -export function effectsToCSS(effects: Effect[]): DesignStyleDeclaration { - const style: DesignStyleDeclaration = {} - const visible = effects.filter((effect) => effect.visible) - const shadows = visible.filter( - (effect) => effect.type === 'DROP_SHADOW' || effect.type === 'INNER_SHADOW' - ) - if (shadows.length > 0) style['box-shadow'] = shadows.map(shadowToCSS).join(', ') - for (const effect of visible) { - if (effect.type === 'LAYER_BLUR' || effect.type === 'FOREGROUND_BLUR') - style.filter = `blur(${effect.radius}px)` - if (effect.type === 'BACKGROUND_BLUR') style['backdrop-filter'] = `blur(${effect.radius}px)` - } - return style -} - function firstShadowLayerNodes(value: string): ParsedNode[] { const nodes: ParsedNode[] = [] for (const node of valueParser(value).nodes) { @@ -152,10 +105,3 @@ export function mergedStyle(node: { }) { return { ...node.inlineStyle, ...node.computedStyle } } - -export function sceneNodeSizeStyle(node: SceneNode): DesignStyleDeclaration { - const style: DesignStyleDeclaration = {} - if (node.width > 0) style.width = `${node.width}px` - if (node.height > 0) style.height = `${node.height}px` - return style -} diff --git a/packages/dom-css/src/convert.ts b/packages/dom-css/src/import/html.ts similarity index 97% rename from packages/dom-css/src/convert.ts rename to packages/dom-css/src/import/html.ts index 80e2ed8e1..7ac79e748 100644 --- a/packages/dom-css/src/convert.ts +++ b/packages/dom-css/src/import/html.ts @@ -2,11 +2,11 @@ import { parse, type DefaultTreeAdapterTypes } from 'parse5' import type { SceneGraph } from '@open-pencil/scene-graph' +import { createCSSRuntime } from '../runtime' +import type { CSSComputeOptions, CSSRuntime, DesignDocument } from '../types' import { mergeCSSText } from './css-text' -import { createCSSRuntime } from './runtime' +import { designDocumentToSceneGraph, type ToSceneGraphOptions } from './scene-graph' import { compileTailwindCSS, type CompileTailwindCSSOptions } from './tailwind' -import { designDocumentToSceneGraph, type ToSceneGraphOptions } from './to-scene-graph' -import type { CSSComputeOptions, CSSRuntime, DesignDocument } from './types' export interface HTMLToDesignDocumentOptions { cssText?: string diff --git a/packages/dom-css/src/jsx/core.ts b/packages/dom-css/src/import/jsx/core.ts similarity index 99% rename from packages/dom-css/src/jsx/core.ts rename to packages/dom-css/src/import/jsx/core.ts index 19560b40e..f941b418d 100644 --- a/packages/dom-css/src/jsx/core.ts +++ b/packages/dom-css/src/import/jsx/core.ts @@ -1,4 +1,4 @@ -import type { DesignDocument, DesignNode, DesignStyleDeclaration } from '../types' +import type { DesignDocument, DesignNode, DesignStyleDeclaration } from '#dom-css/types' export const Fragment = Symbol.for('open-pencil.dom-css.fragment') diff --git a/packages/dom-css/src/jsx/dev-runtime.ts b/packages/dom-css/src/import/jsx/dev-runtime.ts similarity index 100% rename from packages/dom-css/src/jsx/dev-runtime.ts rename to packages/dom-css/src/import/jsx/dev-runtime.ts diff --git a/packages/dom-css/src/jsx/runtime.ts b/packages/dom-css/src/import/jsx/runtime.ts similarity index 95% rename from packages/dom-css/src/jsx/runtime.ts rename to packages/dom-css/src/import/jsx/runtime.ts index ad85034a7..dea7570bf 100644 --- a/packages/dom-css/src/jsx/runtime.ts +++ b/packages/dom-css/src/import/jsx/runtime.ts @@ -1,8 +1,9 @@ +import type { CSSComputeOptions, CSSRuntime, DesignDocument } from '#dom-css/types' + import type { SceneGraph } from '@open-pencil/scene-graph' +import { designDocumentToSceneGraph, type ToSceneGraphOptions } from '../scene-graph' import { compileTailwindCSS, type CompileTailwindCSSOptions } from '../tailwind' -import { designDocumentToSceneGraph, type ToSceneGraphOptions } from '../to-scene-graph' -import type { CSSComputeOptions, CSSRuntime, DesignDocument } from '../types' import { jsxToDesignDocumentCore, type JSXChild } from './core' export { Fragment, jsx, jsxs } from './core' @@ -31,7 +32,7 @@ export interface TailwindJSXToSceneGraphOptions async function runtimeForOptions(runtime: CSSRuntime | undefined) { if (runtime) return runtime - const { createCSSRuntime } = await import('../runtime') + const { createCSSRuntime } = await import('#dom-css/runtime') return createCSSRuntime() } diff --git a/packages/dom-css/src/to-scene-graph.ts b/packages/dom-css/src/import/scene-graph.ts similarity index 99% rename from packages/dom-css/src/to-scene-graph.ts rename to packages/dom-css/src/import/scene-graph.ts index 03d6c91da..ea752a649 100644 --- a/packages/dom-css/src/to-scene-graph.ts +++ b/packages/dom-css/src/import/scene-graph.ts @@ -10,6 +10,7 @@ import { import { TRANSPARENT } from '@open-pencil/scene-graph/constants' import { computeImageHash } from '@open-pencil/scene-graph/images' +import type { DesignDocument, DesignElement, DesignNode, DesignStyleDeclaration } from '../types' import { colorToFillFromCSS, colorToStrokeFromCSS, @@ -18,7 +19,6 @@ import { parseCSSNumber, pickStyle } from './css-values' -import type { DesignDocument, DesignElement, DesignNode, DesignStyleDeclaration } from './types' const DOM_CSS_PLUGIN_ID = 'open-pencil-dom-css' const IMAGE_SOURCE_URL_KEY = 'image-source-url' diff --git a/packages/dom-css/src/style-attribute.ts b/packages/dom-css/src/import/style-attribute.ts similarity index 93% rename from packages/dom-css/src/style-attribute.ts rename to packages/dom-css/src/import/style-attribute.ts index 7073955ca..213bf7e21 100644 --- a/packages/dom-css/src/style-attribute.ts +++ b/packages/dom-css/src/import/style-attribute.ts @@ -1,7 +1,7 @@ import { parse } from '@acemir/cssom' import type { CSSStyleRuleLike } from '@acemir/cssom' -import type { DesignStyleDeclaration } from './types' +import type { DesignStyleDeclaration } from '../types' function firstStyleRule(cssText: string): CSSStyleRuleLike | null { const [rule] = parse(cssText).cssRules diff --git a/packages/dom-css/src/tailwind.ts b/packages/dom-css/src/import/tailwind.ts similarity index 100% rename from packages/dom-css/src/tailwind.ts rename to packages/dom-css/src/import/tailwind.ts diff --git a/packages/dom-css/src/index.ts b/packages/dom-css/src/index.ts index be535a33a..68cf74ef3 100644 --- a/packages/dom-css/src/index.ts +++ b/packages/dom-css/src/index.ts @@ -1,19 +1,19 @@ import type * as DesignTypes from './types' -export { exportHTMLBundle } from './html-export' -export { exportStorybook, STORYBOOK_FRAMEWORKS } from './storybook/export' -export { serializeHTML, serializeNode } from './serialize' +export { exportHTMLBundle } from './export/bundle' +export { exportStorybook, STORYBOOK_FRAMEWORKS } from './export/storybook/export' +export { serializeHTML, serializeNode } from './export/html' export { createBrowserCSSRuntime, createCSSRuntime, createHeadlessCSSRuntime } from './runtime' export { htmlToDesignDocument, htmlToSceneGraph, tailwindHTMLToDesignDocument, tailwindHTMLToSceneGraph -} from './convert' -export { designDocumentToSceneGraph } from './to-scene-graph' -export { sceneGraphToDesignDocument, sceneNodeToDesignDocument } from './from-scene-graph' -export { designDocumentToTailwindJSX, sceneNodesToTailwindJSX } from './jsx/print' -export { compileTailwindCSS } from './tailwind' +} from './import/html' +export { designDocumentToSceneGraph } from './import/scene-graph' +export { sceneGraphToDesignDocument, sceneNodeToDesignDocument } from './export/projection' +export { designDocumentToTailwindJSX, sceneNodesToTailwindJSX } from './export/tailwind-jsx' +export { compileTailwindCSS } from './import/tailwind' export { browserHTMLToDesignDocument, browserHTMLToSceneGraph, @@ -32,14 +32,14 @@ export { jsxs, tailwindJSXToDesignDocument, tailwindJSXToSceneGraph -} from './jsx/runtime' +} from './import/jsx/runtime' export type { HTMLToDesignDocumentOptions, HTMLToSceneGraphOptions, TailwindHTMLToDesignDocumentOptions, TailwindHTMLToSceneGraphOptions -} from './convert' -export type { ToDesignDocumentOptions } from './from-scene-graph' +} from './import/html' +export type { ToDesignDocumentOptions } from './export/projection' export type { BrowserCSSRuntimeOptions } from './runtime' export type { JSXChild, @@ -52,7 +52,7 @@ export type { JSXToSceneGraphOptions, TailwindJSXToDesignDocumentOptions, TailwindJSXToSceneGraphOptions -} from './jsx/runtime' +} from './import/jsx/runtime' export type { BrowserHTMLToDesignDocumentOptions, BrowserHTMLToSceneGraphOptions, @@ -63,7 +63,7 @@ export type { BrowserToDesignDocumentOptions, BrowserToSceneGraphOptions } from './browser' -export type { CompileTailwindCSSOptions } from './tailwind' +export type { CompileTailwindCSSOptions } from './import/tailwind' export type { ExportHTMLBundle, ExportHTMLBundleOptions, @@ -71,10 +71,14 @@ export type { WebFontFaceAsset, WebFontFaceRequest, WebFontFaceResolver -} from './html-export' -export type { ExportStorybookOptions, StorybookFile, StorybookFramework } from './storybook/export' -export type { SerializeHTMLOptions } from './serialize' -export type { ToSceneGraphOptions } from './to-scene-graph' +} from './export/bundle' +export type { + ExportStorybookOptions, + StorybookFile, + StorybookFramework +} from './export/storybook/export' +export type { SerializeHTMLOptions } from './export/html' +export type { ToSceneGraphOptions } from './import/scene-graph' export type CSSComputeOptions = DesignTypes.CSSComputeOptions export type CSSRuntime = DesignTypes.CSSRuntime export type DesignDocument = DesignTypes.DesignDocument diff --git a/packages/dom-css/src/runtime/browser.ts b/packages/dom-css/src/runtime/browser.ts index 6408d65c9..e34ed6c25 100644 --- a/packages/dom-css/src/runtime/browser.ts +++ b/packages/dom-css/src/runtime/browser.ts @@ -1,4 +1,4 @@ -import { serializeHTML } from '../serialize' +import { serializeHTML } from '../export/html' import type { CSSComputeOptions, CSSRuntime, diff --git a/packages/dom-css/src/headless-css.ts b/packages/dom-css/src/runtime/headless-css.ts similarity index 99% rename from packages/dom-css/src/headless-css.ts rename to packages/dom-css/src/runtime/headless-css.ts index c0910db6f..6c08f65ed 100644 --- a/packages/dom-css/src/headless-css.ts +++ b/packages/dom-css/src/runtime/headless-css.ts @@ -5,7 +5,7 @@ import { type CSSStyleRuleLike } from '@acemir/cssom' -import type { DesignDocument, DesignElement, DesignNode, DesignStyleDeclaration } from './types' +import type { DesignDocument, DesignElement, DesignNode, DesignStyleDeclaration } from '../types' interface HeadlessCSSRule { selector: string diff --git a/packages/dom-css/src/runtime/headless.ts b/packages/dom-css/src/runtime/headless.ts index 309e91c79..8ab98bf58 100644 --- a/packages/dom-css/src/runtime/headless.ts +++ b/packages/dom-css/src/runtime/headless.ts @@ -1,9 +1,9 @@ import { parseFragment, type DefaultTreeAdapterTypes } from 'parse5' -import { computeHeadlessStyles } from '../headless-css' -import { serializeHTML } from '../serialize' -import { parseStyleAttribute } from '../style-attribute' +import { serializeHTML } from '../export/html' +import { parseStyleAttribute } from '../import/style-attribute' import type { CSSRuntime, DesignDocument, DesignElement, DesignNode } from '../types' +import { computeHeadlessStyles } from './headless-css' function attrsToRecord(attrs: DefaultTreeAdapterTypes.Element['attrs']): Record { const result: Record = {} diff --git a/packages/dom-css/tests/storybook/export.test.ts b/packages/dom-css/tests/export/storybook/export.test.ts similarity index 100% rename from packages/dom-css/tests/storybook/export.test.ts rename to packages/dom-css/tests/export/storybook/export.test.ts diff --git a/packages/dom-css/tests/storybook/names.test.ts b/packages/dom-css/tests/export/storybook/names.test.ts similarity index 94% rename from packages/dom-css/tests/storybook/names.test.ts rename to packages/dom-css/tests/export/storybook/names.test.ts index ffb08eb2a..189197903 100644 --- a/packages/dom-css/tests/storybook/names.test.ts +++ b/packages/dom-css/tests/export/storybook/names.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'bun:test' -import { claimName, identifierName, storyId } from '#dom-css/storybook/names' +import { claimName, identifierName, storyId } from '#dom-css/export/storybook/names' import { sanitize } from 'storybook/internal/csf' describe('storyId', () => { diff --git a/packages/dom-css/tests/jsx/print/appearance.test.ts b/packages/dom-css/tests/export/tailwind-jsx/appearance.test.ts similarity index 100% rename from packages/dom-css/tests/jsx/print/appearance.test.ts rename to packages/dom-css/tests/export/tailwind-jsx/appearance.test.ts diff --git a/packages/dom-css/tests/jsx/print/helpers.ts b/packages/dom-css/tests/export/tailwind-jsx/helpers.ts similarity index 100% rename from packages/dom-css/tests/jsx/print/helpers.ts rename to packages/dom-css/tests/export/tailwind-jsx/helpers.ts diff --git a/packages/dom-css/tests/jsx/print/layout.test.ts b/packages/dom-css/tests/export/tailwind-jsx/layout.test.ts similarity index 100% rename from packages/dom-css/tests/jsx/print/layout.test.ts rename to packages/dom-css/tests/export/tailwind-jsx/layout.test.ts diff --git a/packages/dom-css/tests/jsx/print/structure.test.ts b/packages/dom-css/tests/export/tailwind-jsx/structure.test.ts similarity index 100% rename from packages/dom-css/tests/jsx/print/structure.test.ts rename to packages/dom-css/tests/export/tailwind-jsx/structure.test.ts diff --git a/packages/dom-css/tests/conversion.test.ts b/packages/dom-css/tests/import/conversion.test.ts similarity index 99% rename from packages/dom-css/tests/conversion.test.ts rename to packages/dom-css/tests/import/conversion.test.ts index 997494054..1ca4148b0 100644 --- a/packages/dom-css/tests/conversion.test.ts +++ b/packages/dom-css/tests/import/conversion.test.ts @@ -1,9 +1,7 @@ import { describe, expect, it } from 'bun:test' -import type { SceneGraph, SceneNode } from '@open-pencil/scene-graph' - -import { browserHTMLToSceneGraph } from '../src/browser' -import type { DesignElement, DesignNode } from '../src/index' +import { browserHTMLToSceneGraph } from '#dom-css/browser' +import type { DesignElement, DesignNode } from '#dom-css/index' import { createHeadlessCSSRuntime, designDocumentToSceneGraph, @@ -11,8 +9,11 @@ import { htmlToSceneGraph, sceneGraphToDesignDocument, serializeHTML -} from '../src/index' -import { TEST_COLORS, cardCSS, cardHTML, fixtureCSS, fixtureHTML } from './helpers' +} from '#dom-css/index' + +import type { SceneGraph, SceneNode } from '@open-pencil/scene-graph' + +import { TEST_COLORS, cardCSS, cardHTML, fixtureCSS, fixtureHTML } from '../helpers' const TRANSPARENT_PIXEL_DATA_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADElEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' diff --git a/packages/dom-css/tests/jsx.test.tsx b/packages/dom-css/tests/import/jsx.test.tsx similarity index 97% rename from packages/dom-css/tests/jsx.test.tsx rename to packages/dom-css/tests/import/jsx.test.tsx index 948fbab6d..8bc7a18f0 100644 --- a/packages/dom-css/tests/jsx.test.tsx +++ b/packages/dom-css/tests/import/jsx.test.tsx @@ -7,8 +7,9 @@ import { jsxToSceneGraph, serializeHTML, tailwindJSXToSceneGraph -} from '../src/index' -import { tailwindCardClasses } from './helpers' +} from '#dom-css/index' + +import { tailwindCardClasses } from '../helpers' function CardTitle(props: { children?: string }) { return

{props.children}

diff --git a/packages/dom-css/tests/tailwind.test.ts b/packages/dom-css/tests/import/tailwind.test.ts similarity index 96% rename from packages/dom-css/tests/tailwind.test.ts rename to packages/dom-css/tests/import/tailwind.test.ts index fa1d487c2..b531bbe89 100644 --- a/packages/dom-css/tests/tailwind.test.ts +++ b/packages/dom-css/tests/import/tailwind.test.ts @@ -5,8 +5,9 @@ import { createHeadlessCSSRuntime, designDocumentToSceneGraph, tailwindHTMLToSceneGraph -} from '../src/index' -import { tailwindCardClasses, tailwindInputClasses } from './helpers' +} from '#dom-css/index' + +import { tailwindCardClasses, tailwindInputClasses } from '../helpers' describe('@open-pencil/dom-css Tailwind', () => { it('compiles utility candidates through Tailwind', async () => { diff --git a/packages/dom-css/tsconfig.json b/packages/dom-css/tsconfig.json index e7f911fe5..6b8d6aa3d 100644 --- a/packages/dom-css/tsconfig.json +++ b/packages/dom-css/tsconfig.json @@ -19,9 +19,9 @@ "#dom-css/*": ["./src/*"], "@open-pencil/dom-css": ["./src/index.ts"], "@open-pencil/dom-css/browser": ["./src/browser.ts"], - "@open-pencil/dom-css/export": ["./src/export.ts"], - "@open-pencil/dom-css/jsx-runtime": ["./src/jsx/runtime.ts"], - "@open-pencil/dom-css/jsx-dev-runtime": ["./src/jsx/dev-runtime.ts"] + "@open-pencil/dom-css/export": ["./src/export/index.ts"], + "@open-pencil/dom-css/jsx-runtime": ["./src/import/jsx/runtime.ts"], + "@open-pencil/dom-css/jsx-dev-runtime": ["./src/import/jsx/dev-runtime.ts"] } }, "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], diff --git a/packages/dom-css/tsdown.config.ts b/packages/dom-css/tsdown.config.ts index b2d737ed8..498ed8a16 100644 --- a/packages/dom-css/tsdown.config.ts +++ b/packages/dom-css/tsdown.config.ts @@ -4,9 +4,9 @@ export default defineConfig({ entry: { index: './src/index.ts', browser: './src/browser.ts', - export: './src/export.ts', - 'jsx-runtime': './src/jsx/runtime.ts', - 'jsx-dev-runtime': './src/jsx/dev-runtime.ts' + export: './src/export/index.ts', + 'jsx-runtime': './src/import/jsx/runtime.ts', + 'jsx-dev-runtime': './src/import/jsx/dev-runtime.ts' }, platform: 'neutral', format: ['esm'], diff --git a/vite/aliases.ts b/vite/aliases.ts index 41164a64b..00580b3c5 100644 --- a/vite/aliases.ts +++ b/vite/aliases.ts @@ -16,15 +16,15 @@ export function createOpenPencilAliases(rootDir: string) { }, { find: /^@open-pencil\/dom-css\/export$/, - replacement: resolve(rootDir, 'packages/dom-css/src/export.ts') + replacement: resolve(rootDir, 'packages/dom-css/src/export/index.ts') }, { find: /^@open-pencil\/dom-css\/jsx-runtime$/, - replacement: resolve(rootDir, 'packages/dom-css/src/jsx/runtime.ts') + replacement: resolve(rootDir, 'packages/dom-css/src/import/jsx/runtime.ts') }, { find: /^@open-pencil\/dom-css\/jsx-dev-runtime$/, - replacement: resolve(rootDir, 'packages/dom-css/src/jsx/dev-runtime.ts') + replacement: resolve(rootDir, 'packages/dom-css/src/import/jsx/dev-runtime.ts') }, { find: /^@open-pencil\/dom-css$/,