@pyreon/vite-plugin 0.25.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +219 -21
- package/lib/index.js.map +1 -1
- package/lib/{rocketstyle-collapse-DGnwgDhC.js → rocketstyle-collapse-XIiHU85Y.js} +57 -38
- package/lib/rocketstyle-collapse-XIiHU85Y.js.map +1 -0
- package/lib/types/index.d.ts +123 -2
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/lib/rocketstyle-collapse-DGnwgDhC.js.map +0 -1
|
@@ -81,49 +81,68 @@ async function createCollapseResolver(projectRoot) {
|
|
|
81
81
|
};
|
|
82
82
|
let server = await withSilent(() => createServer(inline));
|
|
83
83
|
const cache = /* @__PURE__ */ new Map();
|
|
84
|
+
let resolveChain = Promise.resolve();
|
|
84
85
|
async function load(spec) {
|
|
85
86
|
return withSilent(() => server.ssrLoadModule(spec));
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
} catch {
|
|
88
|
+
/**
|
|
89
|
+
* Rebuild real child VNodes from a static child subtree via `h()`.
|
|
90
|
+
* `tag` is a lowercase DOM string (component children never reach
|
|
91
|
+
* here — the detector bails on them), `props` are string literals,
|
|
92
|
+
* and children are text strings or nested static elements. The
|
|
93
|
+
* resulting VNodes render byte-faithfully to a real mount because the
|
|
94
|
+
* tree was produced with the compiler's own JSX-text normalization.
|
|
95
|
+
*/
|
|
96
|
+
function buildChildVNodes(tree, h) {
|
|
97
|
+
return tree.map((c) => typeof c === "string" ? c : h(c.tag, c.props, ...buildChildVNodes(c.children, h)));
|
|
98
|
+
}
|
|
99
|
+
async function doResolve(input) {
|
|
100
|
+
const ck = JSON.stringify([
|
|
101
|
+
input.component,
|
|
102
|
+
input.props,
|
|
103
|
+
input.childrenText,
|
|
104
|
+
input.childTree ?? null,
|
|
105
|
+
input.config.provider,
|
|
106
|
+
input.config.theme
|
|
107
|
+
]);
|
|
108
|
+
if (cache.has(ck)) return cache.get(ck) ?? null;
|
|
109
|
+
try {
|
|
110
|
+
if (!server) return null;
|
|
111
|
+
const rs = await load("@pyreon/runtime-server");
|
|
112
|
+
const core = await load("@pyreon/core");
|
|
113
|
+
const styler = await load("@pyreon/styler");
|
|
114
|
+
const prov = await load(input.config.provider.source);
|
|
115
|
+
const thm = await load(input.config.theme.source);
|
|
116
|
+
const comp = await load(input.component.source);
|
|
117
|
+
const renderToString = rs.renderToString;
|
|
118
|
+
const h = core.h;
|
|
119
|
+
const Provider = prov[input.config.provider.name];
|
|
120
|
+
const themeVal = thm[input.config.theme.name];
|
|
121
|
+
const Component = comp[input.component.name];
|
|
122
|
+
const sheet = styler.sheet;
|
|
123
|
+
if (typeof Component !== "function" || Provider == null || themeVal == null) {
|
|
124
124
|
cache.set(ck, null);
|
|
125
125
|
return null;
|
|
126
126
|
}
|
|
127
|
+
sheet.resetSSRBuffer();
|
|
128
|
+
const childArgs = input.childTree ? buildChildVNodes(input.childTree, h) : input.childrenText ? [input.childrenText] : [];
|
|
129
|
+
const node = (mode) => h(Provider, {
|
|
130
|
+
theme: themeVal,
|
|
131
|
+
mode
|
|
132
|
+
}, h(Component, input.props, ...childArgs));
|
|
133
|
+
const result = deriveCollapse(await renderToString(node("light")), await renderToString(node("dark")), sheet.getStyleRules().slice());
|
|
134
|
+
cache.set(ck, result);
|
|
135
|
+
return result;
|
|
136
|
+
} catch {
|
|
137
|
+
cache.set(ck, null);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
resolve(input) {
|
|
143
|
+
const next = resolveChain.then(() => doResolve(input), () => doResolve(input));
|
|
144
|
+
resolveChain = next;
|
|
145
|
+
return next;
|
|
127
146
|
},
|
|
128
147
|
async dispose() {
|
|
129
148
|
const s = server;
|
|
@@ -136,4 +155,4 @@ async function createCollapseResolver(projectRoot) {
|
|
|
136
155
|
|
|
137
156
|
//#endregion
|
|
138
157
|
export { createCollapseResolver };
|
|
139
|
-
//# sourceMappingURL=rocketstyle-collapse-
|
|
158
|
+
//# sourceMappingURL=rocketstyle-collapse-XIiHU85Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rocketstyle-collapse-XIiHU85Y.js","names":[],"sources":["../src/rocketstyle-collapse.ts"],"sourcesContent":["/**\n * P0 — build-time rocketstyle-collapse resolver.\n *\n * For a collapsible call site (`<Button state=\"primary\" size=\"md\">Save</Button>`\n * — every dimension prop a string literal, children static text) this\n * resolves the FULL rocketstyle/styler pipeline ONCE by SSR-rendering the\n * REAL component, light AND dark, and returns: the resolved styler class\n * per mode, the styler rule text, and a class-stripped `_tpl` template.\n *\n * The render runs through a programmatic Vite SSR server bound to the\n * CONSUMER's own `vite.config` — so module resolution is identical to\n * the app's real build (workspace `bun` condition, app aliases,\n * app-local relative imports, whatever). Parity with the runtime-mounted\n * class is then guaranteed BY CONSTRUCTION: it is literally the same\n * `renderToString` + `@pyreon/styler` code path the client uses, and\n * styler's FNV-1a class hashing is identical in SSR and DOM (styler's\n * hydration contract). No reimplementation, no closure re-execution, no\n * drift (RFC decision 2).\n *\n * Every failure returns `null` (graceful bail → the call site keeps its\n * normal rocketstyle mount). Correct-but-slow is acceptable; wrong\n * output is not.\n */\nimport { withSilent } from '@pyreon/reactivity'\nimport type { StaticChild } from '@pyreon/compiler'\nimport type { InlineConfig, ViteDevServer } from 'vite'\n\n// Inline FNV-1a (same algorithm as @pyreon/styler/hash) — avoids pulling\n// the styler module graph into the vite-plugin's cheap entry path.\nfunction fnv1a(str: string): string {\n let h = 2166136261\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n return (h >>> 0).toString(36)\n}\n\nexport interface CollapseImportSpec {\n /** Imported binding name, e.g. `PyreonUI` / `theme` / `useMode`. */\n name: string\n /** Module specifier, e.g. `@pyreon/ui-core` / `@pyreon/ui-theme`. */\n source: string\n}\n\nexport interface CollapseConfig {\n /** Theme/mode provider component. Default: PyreonUI from @pyreon/ui-core. */\n provider: CollapseImportSpec\n /** Theme object. Default: theme from @pyreon/ui-theme. */\n theme: CollapseImportSpec\n /** Live mode accessor — emitted into the collapsed site for dual-emit. */\n mode: CollapseImportSpec\n}\n\nexport const DEFAULT_COLLAPSE_CONFIG: CollapseConfig = {\n provider: { name: 'PyreonUI', source: '@pyreon/ui-core' },\n theme: { name: 'theme', source: '@pyreon/ui-theme' },\n mode: { name: 'useMode', source: '@pyreon/ui-core' },\n}\n\nexport interface ResolveInput {\n /** The collapsible component's import. */\n component: CollapseImportSpec\n /** Literal dimension/HTML props, e.g. `{ state: 'primary', size: 'md' }`. */\n props: Record<string, string>\n /** Static text children (empty ⇒ no children). For element-child sites\n * this is the `serializeStaticChildren` key-string (cache discriminator\n * only — the actual children come from `childTree`). */\n childrenText: string\n /** Element-child sites only: the recursively-static child subtree.\n * When present, the resolver rebuilds it via `h()` and renders the real\n * child VNodes instead of `childrenText` as a string (PR 2). */\n childTree?: StaticChild[]\n config: CollapseConfig\n}\n\nexport interface ResolvedCollapse {\n /** Element HTML with the root `class=\"...\"` removed (the `_tpl` template). */\n templateHtml: string\n lightClass: string\n darkClass: string\n /** Pre-resolved styler rule text (full snapshot) for `injectRules`. */\n rules: string[]\n /** FNV over the rule set — `injectRules` idempotency + cross-site dedupe. */\n key: string\n}\n\nconst FIRST_CLASS_RE = /^(\\s*<[a-zA-Z][\\w-]*)([^>]*?)\\sclass=\"([^\"]*)\"([^>]*>)/\n\n/** Strip the FIRST element's `class=\"...\"`, returning [stripped, class]. */\nexport function stripRootClass(html: string): { stripped: string; cls: string } | null {\n const m = FIRST_CLASS_RE.exec(html)\n if (!m) return null\n const stripped = html.replace(FIRST_CLASS_RE, '$1$2$4')\n return { stripped, cls: m[3] ?? '' }\n}\n\n/**\n * Pure extraction half — given the two rendered HTML strings and the\n * styler rule snapshot, derive the ResolvedCollapse (or null on a shape\n * the slice doesn't collapse). Separated for direct unit-testing without\n * spinning Vite.\n */\nexport function deriveCollapse(\n lightHtml: string,\n darkHtml: string,\n rules: string[],\n): ResolvedCollapse | null {\n const light = stripRootClass(lightHtml)\n const dark = stripRootClass(darkHtml)\n if (!light || !dark || !light.cls || !dark.cls) return null\n // The structural template must be identical between modes (only the\n // class differs). Divergent markup ⇒ not a simple single-root\n // collapsible — bail.\n if (light.stripped !== dark.stripped) return null\n return {\n templateHtml: light.stripped.trim(),\n lightClass: light.cls,\n darkClass: dark.cls,\n rules,\n key: fnv1a(rules.join('\\u0000')),\n }\n}\n\nexport interface CollapseResolver {\n resolve(input: ResolveInput): Promise<ResolvedCollapse | null>\n dispose(): Promise<void>\n}\n\n/**\n * Create a resolver backed by ONE programmatic Vite SSR server bound to\n * `projectRoot`'s vite config. Reused across every call site in a build;\n * `dispose()` at buildEnd. Module loads are cached by Vite's own SSR\n * module graph (provider/theme/component import once).\n */\nexport async function createCollapseResolver(projectRoot: string): Promise<CollapseResolver> {\n const { createServer } = (await import('vite')) as typeof import('vite')\n const inline: InlineConfig = {\n // No `configFile` override — Vite auto-loads the project's own\n // vite.config from `root`, so module resolution (workspace `bun`\n // condition, app aliases) matches the real build exactly.\n root: projectRoot,\n server: { middlewareMode: true },\n appType: 'custom',\n logLevel: 'silent',\n optimizeDeps: { noDiscovery: true, include: [] },\n }\n // `createServer` evaluates the consumer's vite.config + plugin chain,\n // which may itself load `@pyreon/*` packages via the `node` condition\n // (different path than the outer process's `bun`-conditioned `src/`).\n // That's a legitimate dual-load — scope the opt-out across the entire\n // server lifecycle since every `load(spec)` below also touches the\n // dual graph.\n let server: ViteDevServer | null = await withSilent(() => createServer(inline))\n\n // Resolved-bundle cache — identical input must hit the same result\n // without a second double-render (deterministic by construction).\n const cache = new Map<string, ResolvedCollapse | null>()\n\n // Serialize all `resolve()` calls. The Vite `transform` hook runs in\n // parallel across files (audit #7), so two concurrent `resolve()` calls\n // would interleave their renderToString invocations against the SAME\n // singleton styler sheet — A's rules pollute B's `getStyleRules()` slice\n // and vice versa. The chain forces strict FIFO ordering; combined with\n // the `sheet.resetSSRBuffer()` call at the head of every `doResolve`\n // (audit #8), each render-pair sees a fresh capture buffer.\n // `.then(success, failure)` pair: a single rejected resolve must not\n // poison the chain for subsequent calls.\n let resolveChain: Promise<unknown> = Promise.resolve()\n\n async function load(spec: string): Promise<Record<string, unknown>> {\n // The nested Vite SSR server loads its own copy of @pyreon/* packages for\n // the SSR snapshot. This is a legitimate dual-load — the outer process has\n // its own @pyreon/* graph; the nested server has its own. `withSilent`\n // from @pyreon/reactivity scopes the sentinel opt-out via a refcount\n // (race-safe under concurrency; the prior env-var dance leaked `silent`\n // permanently when N opt-out scopes overlapped — see withSilent JSDoc).\n return withSilent(\n () => server!.ssrLoadModule(spec) as Promise<Record<string, unknown>>,\n )\n }\n\n /**\n * Rebuild real child VNodes from a static child subtree via `h()`.\n * `tag` is a lowercase DOM string (component children never reach\n * here — the detector bails on them), `props` are string literals,\n * and children are text strings or nested static elements. The\n * resulting VNodes render byte-faithfully to a real mount because the\n * tree was produced with the compiler's own JSX-text normalization.\n */\n function buildChildVNodes(\n tree: StaticChild[],\n h: (t: unknown, p: unknown, ...c: unknown[]) => unknown,\n ): unknown[] {\n return tree.map((c) =>\n typeof c === 'string' ? c : h(c.tag, c.props, ...buildChildVNodes(c.children, h)),\n )\n }\n\n async function doResolve(input: ResolveInput): Promise<ResolvedCollapse | null> {\n const ck = JSON.stringify([\n input.component,\n input.props,\n input.childrenText,\n input.childTree ?? null,\n input.config.provider,\n input.config.theme,\n ])\n // Cache-hit fast path: short-circuit BEFORE touching the sheet, so\n // repeat lookups don't clobber an in-flight neighbouring resolve's\n // buffer. The chain serialization already guarantees ordering for\n // in-flight calls; a cache hit is observably free either way.\n if (cache.has(ck)) return cache.get(ck) ?? null\n try {\n if (!server) return null\n const rs = await load('@pyreon/runtime-server')\n const core = await load('@pyreon/core')\n const styler = await load('@pyreon/styler')\n const prov = await load(input.config.provider.source)\n const thm = await load(input.config.theme.source)\n const comp = await load(input.component.source)\n const renderToString = rs.renderToString as (n: unknown) => Promise<string>\n const h = core.h as (t: unknown, p: unknown, ...c: unknown[]) => unknown\n const Provider = prov[input.config.provider.name]\n const themeVal = thm[input.config.theme.name]\n const Component = comp[input.component.name]\n const sheet = styler.sheet as {\n getStyleRules(): readonly string[]\n resetSSRBuffer(): void\n }\n if (typeof Component !== 'function' || Provider == null || themeVal == null) {\n cache.set(ck, null)\n return null\n }\n // Reset the SSR rule-capture buffer IMMEDIATELY BEFORE the render\n // pair (audit #8). Sheet identity invariant: `ssrLoadModule` caches\n // by spec, so every `load('@pyreon/styler')` returns the SAME module\n // namespace and hence the SAME singleton sheet — reset + getStyleRules\n // target the same instance by construction. The chain serialization\n // (`resolveChain` above) ensures no other in-flight `doResolve` can\n // append between this reset and the `getStyleRules()` capture below.\n sheet.resetSSRBuffer()\n // Element-child sites carry a structured `childTree` — rebuild\n // the real child VNodes via `h()` so the SSR render bakes the\n // full subtree HTML (byte-faithful to a real mount because the\n // tree was normalized with the compiler's own `cleanJsxText`).\n // Full / dynamic sites use `childrenText` as a plain string.\n const childArgs: unknown[] = input.childTree\n ? buildChildVNodes(input.childTree, h)\n : input.childrenText\n ? [input.childrenText]\n : []\n const node = (mode: string) =>\n h(Provider, { theme: themeVal, mode }, h(Component, input.props, ...childArgs))\n const lightHtml = await renderToString(node('light'))\n const darkHtml = await renderToString(node('dark'))\n const rules = sheet.getStyleRules().slice()\n const result = deriveCollapse(lightHtml, darkHtml, rules)\n cache.set(ck, result)\n return result\n } catch {\n cache.set(ck, null)\n return null\n }\n }\n\n return {\n resolve(input) {\n // Chain every call through `resolveChain` so the resets + renders\n // run in strict FIFO. `.then(success, failure)` pair: an upstream\n // rejection must not poison the chain — both branches route through\n // a fresh `doResolve`, so the next caller always gets a real result.\n const next = resolveChain.then(\n () => doResolve(input),\n () => doResolve(input),\n )\n resolveChain = next\n return next\n },\n async dispose() {\n const s = server\n server = null\n cache.clear()\n if (s) await s.close()\n },\n }\n}\n"],"mappings":"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"}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -95,6 +95,68 @@ interface PyreonPluginOptions {
|
|
|
95
95
|
* @example pyreon({ collapse: { components: ['Button', 'Badge'] } })
|
|
96
96
|
*/
|
|
97
97
|
collapse?: boolean | PyreonCollapseOptions;
|
|
98
|
+
/**
|
|
99
|
+
* **JSX auto-import for canonical primitives** — closes the Phase D2
|
|
100
|
+
* gap toward "literally same .tsx file across all three targets".
|
|
101
|
+
*
|
|
102
|
+
* When `true` (the default), scans each `.tsx` file for bare JSX
|
|
103
|
+
* references to canonical primitives (`<Stack>`, `<Inline>`, `<Text>`,
|
|
104
|
+
* `<Button>`, `<Press>`, `<Field>`, `<Toggle>`) and auto-injects
|
|
105
|
+
* `import { ... } from '@pyreon/primitives'` at the top of the file
|
|
106
|
+
* for every primitive used but not yet imported.
|
|
107
|
+
*
|
|
108
|
+
* **Why this matters**: the PMTC native compiler resolves bare JSX
|
|
109
|
+
* tags via its canonical-primitives table at compile time + emits
|
|
110
|
+
* SwiftUI/Kotlin directly — imports would be no-ops on native targets
|
|
111
|
+
* (treated as type-only). So the native source stays import-free for
|
|
112
|
+
* minimal surface. The web build needs the imports for symbol
|
|
113
|
+
* resolution. This auto-import lets ONE `.tsx` file work on all three
|
|
114
|
+
* targets without manual import maintenance.
|
|
115
|
+
*
|
|
116
|
+
* Already-imported names pass through untouched (the plugin diffs the
|
|
117
|
+
* existing imports against the used set before injecting). Components
|
|
118
|
+
* with the same name imported from another source (e.g. a user-defined
|
|
119
|
+
* `<Button>` from a local file) take precedence — the auto-import
|
|
120
|
+
* only fires when the name is used + NOT already in scope.
|
|
121
|
+
*
|
|
122
|
+
* Defaults to `true`. Set to `false` to opt out (e.g. if your
|
|
123
|
+
* project defines its own primitives or you want explicit imports
|
|
124
|
+
* throughout). The scan is regex-based and runs only on `.tsx`
|
|
125
|
+
* files; cost is negligible vs the JSX transform itself.
|
|
126
|
+
*
|
|
127
|
+
* @example pyreon({ jsxAutoImport: true })
|
|
128
|
+
* @example pyreon({ jsxAutoImport: false })
|
|
129
|
+
* @example pyreon({ jsxAutoImport: { source: '@my/primitives', names: ['Box', 'Row'] } })
|
|
130
|
+
*/
|
|
131
|
+
jsxAutoImport?: boolean | PyreonJsxAutoImportOptions;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Override the source / name mappings for the JSX auto-import pass.
|
|
135
|
+
* Default: imports the 7 implemented canonical primitives (`Stack` /
|
|
136
|
+
* `Inline` / `Text` / `Button` / `Press` / `Field` / `Toggle`) from
|
|
137
|
+
* `@pyreon/primitives` AND the 2 most-used control-flow helpers
|
|
138
|
+
* (`For` / `Show`) from `@pyreon/core` — so a TSX source written for
|
|
139
|
+
* native (zero imports — PMTC resolves bare tags) also runs on web
|
|
140
|
+
* with no manual imports.
|
|
141
|
+
*
|
|
142
|
+
* Pass a custom mappings array to apply the same mechanism to a
|
|
143
|
+
* different primitive library, OR to extend the default set with
|
|
144
|
+
* project-specific primitives.
|
|
145
|
+
*/
|
|
146
|
+
interface PyreonJsxAutoImportOptions {
|
|
147
|
+
/**
|
|
148
|
+
* Source → names mappings. Each entry says "auto-import these names
|
|
149
|
+
* from this source". Order matters: the first mapping that includes
|
|
150
|
+
* a used name wins.
|
|
151
|
+
*/
|
|
152
|
+
mappings?: Array<{
|
|
153
|
+
source: string;
|
|
154
|
+
names: string[];
|
|
155
|
+
}>;
|
|
156
|
+
/** @deprecated use `mappings` instead. Kept for back-compat. */
|
|
157
|
+
source?: string;
|
|
158
|
+
/** @deprecated use `mappings` instead. Kept for back-compat. */
|
|
159
|
+
names?: string[];
|
|
98
160
|
}
|
|
99
161
|
interface PyreonCollapseOptions {
|
|
100
162
|
/**
|
|
@@ -146,6 +208,40 @@ interface PyreonLpihOptions {
|
|
|
146
208
|
*/
|
|
147
209
|
cachePath?: string;
|
|
148
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Detect whether a file id resolves to a `@pyreon/*` framework-package source
|
|
213
|
+
* (i.e. a published Pyreon package whose .tsx is being pulled in via the
|
|
214
|
+
* `bun` condition workspace-link, NOT user code, NOT an example app).
|
|
215
|
+
*
|
|
216
|
+
* Why this exists: in compat mode, OXC's per-project `importSource` is set
|
|
217
|
+
* to `@pyreon/core` and the resolveId hook redirects `@pyreon/core/jsx-runtime`
|
|
218
|
+
* to the compat package. That's correct for user code (the whole point of
|
|
219
|
+
* compat mode) but WRONG for framework-internal sources like
|
|
220
|
+
* `@pyreon/zero/src/link.tsx`, which need the real `@pyreon/core` runtime.
|
|
221
|
+
* The fix skips the redirect when the importer is a `@pyreon/*` framework
|
|
222
|
+
* file. Result: published-package consumers (where `@pyreon/zero` resolves
|
|
223
|
+
* to its pre-built `lib/`) and workspace-dev consumers (where it resolves
|
|
224
|
+
* to source) both get correct JSX runtime resolution.
|
|
225
|
+
*
|
|
226
|
+
* Detection heuristic: walk to nearest `package.json`, require BOTH:
|
|
227
|
+
* 1. `name` starts with `@pyreon/` (workspace member of the @pyreon scope)
|
|
228
|
+
* 2. file path contains `/packages/` AND NOT `/examples/`
|
|
229
|
+
*
|
|
230
|
+
* Step 2 excludes the existing `@pyreon/example-{react,vue,solid,preact}-compat`
|
|
231
|
+
* apps under `examples/`. Without it, user code in those apps would skip the
|
|
232
|
+
* compat-mode JSX-runtime redirect and import `@pyreon/core/jsx-runtime`
|
|
233
|
+
* directly — breaking the React/Vue/Solid/Preact compat layer's contract.
|
|
234
|
+
*
|
|
235
|
+
* Result cached per directory. The `/packages/` + `/examples/` check is a
|
|
236
|
+
* structural property of the monorepo (workspace layout), not the package
|
|
237
|
+
* name — so it's robust against renames.
|
|
238
|
+
*/
|
|
239
|
+
declare function _isPyreonWorkspaceFile(id: string, cache: Map<string, boolean>): boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Return the Pyreon compat target for an import specifier, or undefined if
|
|
242
|
+
* the import should not be redirected.
|
|
243
|
+
*/
|
|
244
|
+
declare function _getCompatTarget(compat: CompatFramework | undefined, id: string): string | undefined;
|
|
149
245
|
/**
|
|
150
246
|
* Truthy env-var parser. Accepts `1` / `true` / `yes` / `on`
|
|
151
247
|
* (case-insensitive). Returns `false` for `undefined`, empty string,
|
|
@@ -159,7 +255,8 @@ interface PyreonLpihOptions {
|
|
|
159
255
|
* @internal
|
|
160
256
|
*/
|
|
161
257
|
declare function _isTruthyEnv(v: string | undefined): boolean;
|
|
162
|
-
declare function pyreonPlugin(options?: PyreonPluginOptions): Plugin
|
|
258
|
+
declare function pyreonPlugin(options?: PyreonPluginOptions): Plugin<any>;
|
|
259
|
+
declare function _handleSsrRequest(server: ViteDevServer, entry: string, url: string, req: import('node:http').IncomingMessage, res: import('node:http').ServerResponse, next: (err?: unknown) => void): Promise<void>;
|
|
163
260
|
/**
|
|
164
261
|
* Resolve the LPIH cache-file path for a given project root. Matches the
|
|
165
262
|
* convention `@pyreon/reactivity/lpih`'s `getDefaultLpihCachePath()` uses
|
|
@@ -201,6 +298,8 @@ declare function writeLpihCacheFile(path: string, body: string): Promise<void>;
|
|
|
201
298
|
* @internal — exported for tests.
|
|
202
299
|
*/
|
|
203
300
|
declare function buildLpihClientScript(intervalMs: number): string;
|
|
301
|
+
declare function _skipStringLiteral(code: string, start: number, quote: string): number;
|
|
302
|
+
declare function _extractBalancedArgs(code: string, start: number): string | null;
|
|
204
303
|
/**
|
|
205
304
|
* Mask string-literal / template-literal / comment regions in `code` by
|
|
206
305
|
* replacing their content with spaces. Returns a SAME-LENGTH string so
|
|
@@ -243,6 +342,28 @@ declare function _offsetToLineCol(offset: number, lineStarts: number[]): {
|
|
|
243
342
|
line: number;
|
|
244
343
|
col: number;
|
|
245
344
|
};
|
|
345
|
+
/**
|
|
346
|
+
* Replace JS comments with spaces while preserving line/column
|
|
347
|
+
* positions. Used by the auto-import scanner so `<Stack>` text inside
|
|
348
|
+
* JSDoc doesn't false-positive as a JSX usage. Position preservation
|
|
349
|
+
* lets the caller use the masked code for regex SEARCH and the
|
|
350
|
+
* original code for SPLICE.
|
|
351
|
+
*
|
|
352
|
+
* String literals are deliberately LEFT VISIBLE — they often carry
|
|
353
|
+
* the package name we need to match (`from '@pyreon/primitives'`).
|
|
354
|
+
* The trade-off: a literal `'<Stack/>'` inside a string would
|
|
355
|
+
* false-positive, but that's vanishingly rare compared to JSDoc
|
|
356
|
+
* examples + the cost of either making string-aware AST parsing OR
|
|
357
|
+
* masking only the LITERAL TEXT (not the quotes) is not worth it
|
|
358
|
+
* for the marginal correctness gain.
|
|
359
|
+
*
|
|
360
|
+
* Handles:
|
|
361
|
+
* - line comments `// ... newline`
|
|
362
|
+
* - block comments `/* ... */`
|
|
363
|
+
*/
|
|
364
|
+
declare function _maskCommentsAndStrings(code: string): string;
|
|
365
|
+
/** Collect every name imported via `import { ... }` / `import X` / `import * as X`. */
|
|
366
|
+
declare function _collectImportedNames(code: string): Set<string>;
|
|
246
367
|
//#endregion
|
|
247
|
-
export { CompatFramework, PyreonCollapseOptions, PyreonLpihOptions, PyreonPluginOptions, _computeLineStarts, _isTruthyEnv, _maskStringsAndComments, _offsetToLineCol, buildLpihClientScript, pyreonPlugin as default, registerLpihMiddleware, resolveLpihCachePath, writeLpihCacheFile };
|
|
368
|
+
export { CompatFramework, PyreonCollapseOptions, PyreonJsxAutoImportOptions, PyreonLpihOptions, PyreonPluginOptions, _collectImportedNames, _computeLineStarts, _extractBalancedArgs, _getCompatTarget, _handleSsrRequest, _isPyreonWorkspaceFile, _isTruthyEnv, _maskCommentsAndStrings, _maskStringsAndComments, _offsetToLineCol, _skipStringLiteral, buildLpihClientScript, pyreonPlugin as default, registerLpihMiddleware, resolveLpihCachePath, writeLpihCacheFile };
|
|
248
369
|
//# sourceMappingURL=index2.d.ts.map
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/index.ts"],"mappings":";;;KA4EY,eAAA;AAAA,UAEK,mBAAA;
|
|
1
|
+
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/index.ts"],"mappings":";;;KA4EY,eAAA;AAAA,UAEK,mBAAA;EA0JI;;;;;AAId;AAGP;;;;;;;EAnJE,MAAA,GAAS,eAAA;EAmKkB;;;;;;;;AAIE;AAG/B;EA9JE,GAAA;IA8JgC,4DA5J9B,KAAA;EAAA;EAgPY;;;;;;;;AAA8D;AA2C9E;;;;;;;;AAAgF;AAkGhF;;;;AAAkD;AAIjD;;EArWC,OAAA;EAgXyE;;;;;AAAA;AAonB3E;;;;;;;;;;;;;;;;AAOU;EAl9BR,IAAA,aAAiB,iBAAA;EA2gCiB;;;AAAoB;AAaxD;;;;;;;;;;EAxgCE,QAAA,aAAqB,qBAAA;EA+jCD;;;;;;;;AAAuD;AAsD7E;;;;AAAwD;AA6ExD;;;;;;;;AAA6E;AAa7E;;;;AAAgE;AAkPhE;;;;AAAoD;EA95ClD,aAAA,aAA0B,0BAAA;AAAA;;;AAqhDmB;AAc/C;;;;;;;;;AAGsB;UAthDL,0BAAA;EAuyDsB;;;AAAa;AAgCpD;EAj0DE,QAAA,GAAW,KAAK;IAAG,MAAA;IAAgB,KAAA;EAAA;;EAEnC,MAAA;;EAEA,KAAA;AAAA;AAAA,UAGe,qBAAA;;;;;;;;EAQf,OAAA;;;;;;EAMA,UAAA;;EAEA,QAAA;IAAa,IAAA;IAAc,MAAA;EAAA;;EAE3B,KAAA;IAAU,IAAA;IAAc,MAAA;EAAA;;EAExB,IAAA;IAAS,IAAA;IAAc,MAAA;EAAA;AAAA;AAAA,UAGR,iBAAA;;;;;;;;;;EAUf,UAAA;;;;;;;EAOA,SAAS;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmEK,sBAAA,CAAuB,EAAA,UAAY,KAAA,EAAO,GAAG;;;;;iBA2C7C,gBAAA,CAAiB,MAAA,EAAQ,eAAe,cAAc,EAAA;;;;;;;;;;;;;iBAkGtD,YAAA,CAAa,CAAqB;AAAA,iBAe1B,YAAA,CAAa,OAAA,GAAU,mBAAA,GAAsB,MAAM;AAAA,iBAonBrD,iBAAA,CACpB,MAAA,EAAQ,aAAA,EACR,KAAA,UACA,GAAA,UACA,GAAA,sBAAyB,eAAA,EACzB,GAAA,sBAAyB,cAAA,EACzB,IAAA,GAAO,GAAA,sBACN,OAAO;;;;;;;;iBAyDM,oBAAA,CAAqB,WAAmB;;;;;;;;;;iBAaxC,sBAAA,CACd,MAAA,EAAQ,aAAA,EACR,WAAA,UACA,OAAA,EAAS,iBAAiB;;;;;;;;;;iBAoDN,kBAAA,CAAmB,IAAA,UAAc,IAAA,WAAe,OAAO;;;;;;;;;;;;;iBAsD7D,qBAAA,CAAsB,UAAkB;AAAA,iBA6ExC,kBAAA,CAAmB,IAAA,UAAc,KAAA,UAAe,KAAA;AAAA,iBAahD,oBAAA,CAAqB,IAAA,UAAc,KAAa;;;;;;;;;;;;;;;;;;;;;;;;iBAkPhD,uBAAA,CAAwB,IAAY;;;;;;;;iBAuHpC,kBAAA,CAAmB,IAAY;;;;;;;iBAc/B,gBAAA,CACd,MAAA,UACA,UAAA;EACG,IAAA;EAAc,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;iBAiRH,uBAAA,CAAwB,IAAY;;iBAgCpC,qBAAA,CAAsB,IAAA,WAAe,GAAG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Vite plugin for Pyreon — .pyreon SFC support, HMR, compiler integration",
|
|
5
5
|
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/vite-plugin#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -40,13 +40,15 @@
|
|
|
40
40
|
"prepublishOnly": "bun run build"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@pyreon/compiler": "^0.
|
|
44
|
-
"@pyreon/reactivity": "^0.
|
|
43
|
+
"@pyreon/compiler": "^0.26.0",
|
|
44
|
+
"@pyreon/reactivity": "^0.26.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"
|
|
47
|
+
"@pyreon/vitest-config": "0.13.1",
|
|
48
|
+
"vite": "^8.0.14"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
51
|
+
"@pyreon/runtime-dom": "^0.26.0",
|
|
50
52
|
"vite": ">=8.0.0"
|
|
51
53
|
}
|
|
52
54
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rocketstyle-collapse-DGnwgDhC.js","names":[],"sources":["../src/rocketstyle-collapse.ts"],"sourcesContent":["/**\n * P0 — build-time rocketstyle-collapse resolver.\n *\n * For a collapsible call site (`<Button state=\"primary\" size=\"md\">Save</Button>`\n * — every dimension prop a string literal, children static text) this\n * resolves the FULL rocketstyle/styler pipeline ONCE by SSR-rendering the\n * REAL component, light AND dark, and returns: the resolved styler class\n * per mode, the styler rule text, and a class-stripped `_tpl` template.\n *\n * The render runs through a programmatic Vite SSR server bound to the\n * CONSUMER's own `vite.config` — so module resolution is identical to\n * the app's real build (workspace `bun` condition, app aliases,\n * app-local relative imports, whatever). Parity with the runtime-mounted\n * class is then guaranteed BY CONSTRUCTION: it is literally the same\n * `renderToString` + `@pyreon/styler` code path the client uses, and\n * styler's FNV-1a class hashing is identical in SSR and DOM (styler's\n * hydration contract). No reimplementation, no closure re-execution, no\n * drift (RFC decision 2).\n *\n * Every failure returns `null` (graceful bail → the call site keeps its\n * normal rocketstyle mount). Correct-but-slow is acceptable; wrong\n * output is not.\n */\nimport { withSilent } from '@pyreon/reactivity'\nimport type { InlineConfig, ViteDevServer } from 'vite'\n\n// Inline FNV-1a (same algorithm as @pyreon/styler/hash) — avoids pulling\n// the styler module graph into the vite-plugin's cheap entry path.\nfunction fnv1a(str: string): string {\n let h = 2166136261\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n return (h >>> 0).toString(36)\n}\n\nexport interface CollapseImportSpec {\n /** Imported binding name, e.g. `PyreonUI` / `theme` / `useMode`. */\n name: string\n /** Module specifier, e.g. `@pyreon/ui-core` / `@pyreon/ui-theme`. */\n source: string\n}\n\nexport interface CollapseConfig {\n /** Theme/mode provider component. Default: PyreonUI from @pyreon/ui-core. */\n provider: CollapseImportSpec\n /** Theme object. Default: theme from @pyreon/ui-theme. */\n theme: CollapseImportSpec\n /** Live mode accessor — emitted into the collapsed site for dual-emit. */\n mode: CollapseImportSpec\n}\n\nexport const DEFAULT_COLLAPSE_CONFIG: CollapseConfig = {\n provider: { name: 'PyreonUI', source: '@pyreon/ui-core' },\n theme: { name: 'theme', source: '@pyreon/ui-theme' },\n mode: { name: 'useMode', source: '@pyreon/ui-core' },\n}\n\nexport interface ResolveInput {\n /** The collapsible component's import. */\n component: CollapseImportSpec\n /** Literal dimension/HTML props, e.g. `{ state: 'primary', size: 'md' }`. */\n props: Record<string, string>\n /** Static text children (empty ⇒ no children). */\n childrenText: string\n config: CollapseConfig\n}\n\nexport interface ResolvedCollapse {\n /** Element HTML with the root `class=\"...\"` removed (the `_tpl` template). */\n templateHtml: string\n lightClass: string\n darkClass: string\n /** Pre-resolved styler rule text (full snapshot) for `injectRules`. */\n rules: string[]\n /** FNV over the rule set — `injectRules` idempotency + cross-site dedupe. */\n key: string\n}\n\nconst FIRST_CLASS_RE = /^(\\s*<[a-zA-Z][\\w-]*)([^>]*?)\\sclass=\"([^\"]*)\"([^>]*>)/\n\n/** Strip the FIRST element's `class=\"...\"`, returning [stripped, class]. */\nexport function stripRootClass(html: string): { stripped: string; cls: string } | null {\n const m = FIRST_CLASS_RE.exec(html)\n if (!m) return null\n const stripped = html.replace(FIRST_CLASS_RE, '$1$2$4')\n return { stripped, cls: m[3] ?? '' }\n}\n\n/**\n * Pure extraction half — given the two rendered HTML strings and the\n * styler rule snapshot, derive the ResolvedCollapse (or null on a shape\n * the slice doesn't collapse). Separated for direct unit-testing without\n * spinning Vite.\n */\nexport function deriveCollapse(\n lightHtml: string,\n darkHtml: string,\n rules: string[],\n): ResolvedCollapse | null {\n const light = stripRootClass(lightHtml)\n const dark = stripRootClass(darkHtml)\n if (!light || !dark || !light.cls || !dark.cls) return null\n // The structural template must be identical between modes (only the\n // class differs). Divergent markup ⇒ not a simple single-root\n // collapsible — bail.\n if (light.stripped !== dark.stripped) return null\n return {\n templateHtml: light.stripped.trim(),\n lightClass: light.cls,\n darkClass: dark.cls,\n rules,\n key: fnv1a(rules.join('\\u0000')),\n }\n}\n\nexport interface CollapseResolver {\n resolve(input: ResolveInput): Promise<ResolvedCollapse | null>\n dispose(): Promise<void>\n}\n\n/**\n * Create a resolver backed by ONE programmatic Vite SSR server bound to\n * `projectRoot`'s vite config. Reused across every call site in a build;\n * `dispose()` at buildEnd. Module loads are cached by Vite's own SSR\n * module graph (provider/theme/component import once).\n */\nexport async function createCollapseResolver(projectRoot: string): Promise<CollapseResolver> {\n const { createServer } = (await import('vite')) as typeof import('vite')\n const inline: InlineConfig = {\n // No `configFile` override — Vite auto-loads the project's own\n // vite.config from `root`, so module resolution (workspace `bun`\n // condition, app aliases) matches the real build exactly.\n root: projectRoot,\n server: { middlewareMode: true },\n appType: 'custom',\n logLevel: 'silent',\n optimizeDeps: { noDiscovery: true, include: [] },\n }\n // `createServer` evaluates the consumer's vite.config + plugin chain,\n // which may itself load `@pyreon/*` packages via the `node` condition\n // (different path than the outer process's `bun`-conditioned `src/`).\n // That's a legitimate dual-load — scope the opt-out across the entire\n // server lifecycle since every `load(spec)` below also touches the\n // dual graph.\n let server: ViteDevServer | null = await withSilent(() => createServer(inline))\n\n // Resolved-bundle cache — identical input must hit the same result\n // without a second double-render (deterministic by construction).\n const cache = new Map<string, ResolvedCollapse | null>()\n\n async function load(spec: string): Promise<Record<string, unknown>> {\n // The nested Vite SSR server loads its own copy of @pyreon/* packages for\n // the SSR snapshot. This is a legitimate dual-load — the outer process has\n // its own @pyreon/* graph; the nested server has its own. `withSilent`\n // from @pyreon/reactivity scopes the sentinel opt-out via a refcount\n // (race-safe under concurrency; the prior env-var dance leaked `silent`\n // permanently when N opt-out scopes overlapped — see withSilent JSDoc).\n return withSilent(\n () => server!.ssrLoadModule(spec) as Promise<Record<string, unknown>>,\n )\n }\n\n return {\n async resolve(input) {\n const ck = JSON.stringify([\n input.component,\n input.props,\n input.childrenText,\n input.config.provider,\n input.config.theme,\n ])\n if (cache.has(ck)) return cache.get(ck) ?? null\n try {\n if (!server) return null\n const rs = await load('@pyreon/runtime-server')\n const core = await load('@pyreon/core')\n const styler = await load('@pyreon/styler')\n const prov = await load(input.config.provider.source)\n const thm = await load(input.config.theme.source)\n const comp = await load(input.component.source)\n const renderToString = rs.renderToString as (n: unknown) => Promise<string>\n const h = core.h as (t: unknown, p: unknown, ...c: unknown[]) => unknown\n const Provider = prov[input.config.provider.name]\n const themeVal = thm[input.config.theme.name]\n const Component = comp[input.component.name]\n const sheet = styler.sheet as { getStyleRules(): readonly string[] }\n if (typeof Component !== 'function' || Provider == null || themeVal == null) {\n cache.set(ck, null)\n return null\n }\n const childArgs = input.childrenText ? [input.childrenText] : []\n const node = (mode: string) =>\n h(Provider, { theme: themeVal, mode }, h(Component, input.props, ...childArgs))\n const lightHtml = await renderToString(node('light'))\n const darkHtml = await renderToString(node('dark'))\n const rules = sheet.getStyleRules().slice()\n const result = deriveCollapse(lightHtml, darkHtml, rules)\n cache.set(ck, result)\n return result\n } catch {\n cache.set(ck, null)\n return null\n }\n },\n async dispose() {\n const s = server\n server = null\n cache.clear()\n if (s) await s.close()\n },\n }\n}\n"],"mappings":"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"}
|