From bb3e9f5a51343d575a5900b15629559f81ac09c0 Mon Sep 17 00:00:00 2001 From: "Alexis H. Munsayac" Date: Wed, 11 Nov 2026 22:04:15 +0800 Subject: [PATCH 1/3] refactor: rewrite the compiler with oxc and magic-string The compiler parses with oxc-parser and applies every rewrite as a span edit over a MagicString, which also gives a hires source map. This drops @babel/core and @solid-mediakit/shared from the dependencies, and babel-plugin-tester and @babel/preset-typescript from the tests. Behavior changes from the Babel version: - Object property values inside a DynamicImage become arguments. Babel skipped them, so style={{ color: color() }} left color() unresolved in the server function. - A shorthand property keeps its key ({ a } becomes { a: r0 }). - An optional chain is one argument. - TypeScript type annotations are skipped instead of being searched for identifiers. - Generated server functions follow source order. - A module without a DynamicImage is returned unchanged (null). The fixture runner compares prettier-formatted output, and new fixtures cover object values, optional chains and TypeScript. Co-Authored-By: Claude Opus 5.5 --- oxlint.config.ts | 16 + packages/ogp/package.json | 11 +- packages/ogp/src/compiler/ast.ts | 40 ++ packages/ogp/src/compiler/index.ts | 293 ++++++++- packages/ogp/src/compiler/utils.ts | 226 ------- packages/ogp/src/unplugin/index.ts | 30 +- packages/ogp/tests/compiler.test.ts | 89 ++- .../ogp/tests/fixtures/solid/basic/output.js | 12 +- .../solid/custom-image-options/output.js | 15 +- .../fixtures/solid/exclude-static/output.js | 21 +- .../solid/multiple-children/output.js | 11 +- .../fixtures/solid/multiple-images/output.js | 34 +- .../solid/nested-expressions/output.js | 16 +- .../fixtures/solid/nested-in-jsx/output.js | 16 +- .../fixtures/solid/no-dynamic-image/output.js | 3 +- .../fixtures/solid/object-values/code.js | 5 + .../fixtures/solid/object-values/output.js | 18 + .../fixtures/solid/optional-chain/code.js | 5 + .../fixtures/solid/optional-chain/output.js | 16 + .../solid/partially-dynamic-object/output.js | 21 +- .../fixtures/solid/realistic-styles/output.js | 11 +- .../tests/fixtures/solid/typescript/code.tsx | 5 + .../tests/fixtures/solid/typescript/output.js | 23 + .../tests/fixtures/solid/variables/output.js | 11 +- .../fixtures/tanstack-start/basic/output.js | 14 +- .../custom-image-options/output.js | 17 +- .../tanstack-start/multiple-images/output.js | 42 +- .../tanstack-start/nested-in-jsx/output.js | 18 +- .../tanstack-start/no-dynamic-image/output.js | 3 +- .../tanstack-start/variables/output.js | 13 +- packages/ogp/tests/unplugin.test.ts | 6 +- packages/ogp/tsconfig.json | 2 +- packages/ogp/vitest.config.ts | 2 - pnpm-lock.yaml | 607 ++++++++---------- 34 files changed, 817 insertions(+), 855 deletions(-) create mode 100644 packages/ogp/src/compiler/ast.ts delete mode 100644 packages/ogp/src/compiler/utils.ts create mode 100644 packages/ogp/tests/fixtures/solid/object-values/code.js create mode 100644 packages/ogp/tests/fixtures/solid/object-values/output.js create mode 100644 packages/ogp/tests/fixtures/solid/optional-chain/code.js create mode 100644 packages/ogp/tests/fixtures/solid/optional-chain/output.js create mode 100644 packages/ogp/tests/fixtures/solid/typescript/code.tsx create mode 100644 packages/ogp/tests/fixtures/solid/typescript/output.js diff --git a/oxlint.config.ts b/oxlint.config.ts index b9109f8..1a6c30d 100644 --- a/oxlint.config.ts +++ b/oxlint.config.ts @@ -6,4 +6,20 @@ export default defineConfig({ // Compiler fixtures are test data: their outputs must match the compiler byte for byte. // Agent worktrees under .claude/ hold other branches' work in progress. ignorePatterns: ['dist/**', '**/tests/fixtures/**', '.claude/**'], + overrides: [ + { + // The compiler works on a structural AST type, so property access is + // untyped there. + files: ['packages/ogp/src/compiler/**'], + rules: { + 'typescript/no-unsafe-argument': 'off', + 'typescript/no-unsafe-assignment': 'off', + 'typescript/no-unsafe-call': 'off', + 'typescript/no-unsafe-member-access': 'off', + 'typescript/no-unsafe-return': 'off', + 'typescript/no-unsafe-type-assertion': 'off', + 'typescript/no-explicit-any': 'off', + }, + }, + ], }); diff --git a/packages/ogp/package.json b/packages/ogp/package.json index 369fd93..a91a091 100644 --- a/packages/ogp/package.json +++ b/packages/ogp/package.json @@ -96,20 +96,19 @@ "test": "vitest run" }, "dependencies": { - "@babel/core": "^7.28.0", - "@solid-mediakit/shared": "^0.0.6", "@vercel/og": "^1.0.1", + "magic-string": "^1.4.5", + "oxc-parser": "^0.158.0", "satori-html": "^0.3.2", - "unplugin": "^3.3.0" + "unplugin": "^3.3.0", + "unplugin-utils": "^0.3.2" }, "devDependencies": { "@arethetypeswrong/core": "^0.18.5", - "@babel/preset-typescript": "^7.27.0", "@solidjs/vite-plugin": "3.0.0-next.27", "@solidjs/web": "2.0.0-rc.21", - "@types/babel__core": "^7.20.5", "@types/node": "^26.2.0", - "babel-plugin-tester": "^12.0.0", + "prettier": "^3.9.10", "publint": "^0.3.23", "solid-js": "2.0.0-rc.21", "tsdown": "^0.22.14", diff --git a/packages/ogp/src/compiler/ast.ts b/packages/ogp/src/compiler/ast.ts new file mode 100644 index 0000000..864cfc8 --- /dev/null +++ b/packages/ogp/src/compiler/ast.ts @@ -0,0 +1,40 @@ +export interface Node { + type: string; + start: number; + end: number; + // The compiler walks a structural AST; property access is untyped by design. + [key: string]: any; +} + +/** Keys that hold TypeScript type-space nodes; never traversed. */ +const TYPE_KEYS = new Set([ + 'typeAnnotation', + 'typeArguments', + 'typeParameters', + 'returnType', + 'superTypeArguments', + 'implements', +]); + +function isNode(value: unknown): value is Node { + return value != null && typeof value === 'object' && typeof (value as Node).type === 'string'; +} + +/** Invokes `cb` for every direct child node, skipping TypeScript type-space keys. */ +export function eachChild(node: Node, cb: (child: Node) => void): void { + for (const key of Object.keys(node)) { + if (TYPE_KEYS.has(key)) { + continue; + } + const value = node[key]; + if (Array.isArray(value)) { + for (const item of value) { + if (isNode(item)) { + cb(item); + } + } + } else if (isNode(value)) { + cb(value); + } + } +} diff --git a/packages/ogp/src/compiler/index.ts b/packages/ogp/src/compiler/index.ts index 9caf6ac..ff019f2 100644 --- a/packages/ogp/src/compiler/index.ts +++ b/packages/ogp/src/compiler/index.ts @@ -1,7 +1,8 @@ -import type babel from '@babel/core'; -import type { PluginObj } from '@babel/core'; -import { babel as babelUtils } from '@solid-mediakit/shared'; -import { addDynamicImages, addDynamicImagesTanstack, replaceDynamicImages } from './utils'; +import MagicString from 'magic-string'; +import type { SourceMap } from 'magic-string'; +import { parseSync } from 'oxc-parser'; +import { eachChild } from './ast'; +import type { Node } from './ast'; /** * Which server function runtime the compiled output targets. `Solid` is Solid @@ -9,28 +10,274 @@ import { addDynamicImages, addDynamicImagesTanstack, replaceDynamicImages } from */ export type Runtime = 'Solid' | 'TanstackStart'; -type PluginFactory = (api: { types: typeof babel.types }) => PluginObj; +export interface CompileOptions { + runtime?: Runtime; +} + +export interface CompileOutput { + code: string; + map: SourceMap; +} + +interface DynamicImage { + /** The JSX the server function renders, with each reactive replaced by `r`. */ + jsx: string; + /** Source text of the expressions passed to the server function. */ + values: string[]; + /** Source text of an inline `imageOptions` object. */ + imageOptions?: string; +} + +const TS_FILE = /\.[mc]?tsx?$/i; + +/** JSX stays on for plain `.ts` too, so components written in `.ts` files compile. */ +function getLanguage(filename: string): 'jsx' | 'tsx' { + return TS_FILE.test(filename) ? 'tsx' : 'jsx'; +} + +function isDynamicImage(node: Node): boolean { + return ( + node.type === 'JSXElement' && + node.openingElement.name.type === 'JSXIdentifier' && + node.openingElement.name.name === 'DynamicImage' + ); +} -export function transformOG(runtime?: Runtime): PluginFactory { - return ({ types: t }) => ({ - visitor: { - Program(path) { - const dynamicImages = replaceDynamicImages(t, path); - if (dynamicImages.length === 0) { +/** Reads an inline object literal passed as `imageOptions`. */ +function readImageOptions(code: string, element: Node): string | undefined { + for (const attr of element.openingElement.attributes as Node[]) { + if (attr.type !== 'JSXAttribute' || attr.name.name !== 'imageOptions') { + continue; + } + // Only an inline object literal can move to the server function. + const value = attr.value as Node | null; + if (value?.type === 'JSXExpressionContainer' && value.expression.type === 'ObjectExpression') { + const expression = value.expression as Node; + return code.slice(expression.start, expression.end); + } + return undefined; + } + return undefined; +} + +/** + * Replaces each expression in the subtree that may change between renders with + * `r`, and appends its source text to `values`. They become the server + * function's arguments. + */ +function replaceReactives(s: MagicString, code: string, root: Node, values: string[]): void { + function replace(node: Node, prefix = ''): void { + s.overwrite(node.start, node.end, `${prefix}r${values.length}`); + values.push(code.slice(node.start, node.end)); + } + + function visit(node: Node): void { + switch (node.type) { + // Any call or read could return a different value. Replace the whole + // expression rather than descending into it, otherwise the property + // names of `a.b.c` are each extracted as their own reactive. + case 'Identifier': + case 'CallExpression': + case 'MemberExpression': + case 'ChainExpression': + replace(node); + return; + case 'Property': + if (node.shorthand) { + // `{ a }` keeps its key: it becomes `{ a: r0 }`. + replace(node.value as Node, `${(node.key as Node).name as string}: `); return; } - babelUtils.importIfNotThere(path, t, 'createMemo', 'solid-js'); - babelUtils.importIfNotThere(path, t, 'createOpenGraphImage', '@solidjs/ogp/server'); - if (runtime === 'TanstackStart') { - addDynamicImagesTanstack(dynamicImages, t, path); - return; + // A plain key is a static name. A computed key is an expression. + if (node.computed) { + visit(node.key as Node); } - // Solid 2.0 server functions: GET declares a read with a url, - // and serverFunctionUrl builds that url with the arguments. - babelUtils.importIfNotThere(path, t, 'GET', '@solidjs/web/server-functions'); - babelUtils.importIfNotThere(path, t, 'serverFunctionUrl', '@solidjs/web/server-functions'); - addDynamicImages(dynamicImages, t, path); - }, - }, + visit(node.value as Node); + return; + default: + eachChild(node, visit); + } + } + + visit(root); +} + +function extractDynamicImage(s: MagicString, code: string, element: Node): DynamicImage { + const children: Node[] = []; + for (const child of element.children as Node[]) { + if (child.type === 'JSXElement') { + children.push(child); + } + } + if (children.length === 0) { + throw new Error('DynamicImage must have a child element'); + } + const values: string[] = []; + const parts: string[] = []; + for (const child of children) { + replaceReactives(s, code, child, values); + parts.push(s.slice(child.start, child.end)); + } + return { + // Satori needs one root, so wrap several children in a div. + jsx: parts.length === 1 ? parts[0] : `
${parts.join('')}
`, + values, + imageOptions: readImageOptions(code, element), + }; +} + +function createArgumentDeclaration(image: DynamicImage): string { + if (image.values.length === 0) { + return ''; + } + const names: string[] = []; + for (let i = 0; i < image.values.length; i++) { + names.push(`r${i}`); + } + return `const [${names.join(', ')}] = args;\n `; +} + +function createRenderCall(image: DynamicImage): string { + const options = image.imageOptions ? `, ${image.imageOptions}` : ''; + return `return createOpenGraphImage(${image.jsx}${options});`; +} + +function createSolidImage(image: DynamicImage, id: number): string { + const serverFn = `DynamicImage${id}ServerFunction`; + return `const ${serverFn} = GET((...args) => { + 'use server'; + ${createArgumentDeclaration(image)}${createRenderCall(image)} +}); +const DynamicImage${id} = (props) => { + const url = createMemo(() => serverFunctionUrl(${serverFn}, ...props.values)); + return url; +}; +`; +} + +function createTanstackImage(image: DynamicImage, id: number): string { + const serverFn = `DynamicImage${id}ServerFunction`; + return `const ${serverFn} = createServerFn({ + method: "GET", + response: "raw", +}).handler((ctx) => { + const args = ctx.data.values; + ${createArgumentDeclaration(image)}${createRenderCall(image)} +}); +const DynamicImage${id} = (props) => { + const payload = () => ({ data: { values: props.values }, context: {} }); + const url = createMemo(() => \`\${${serverFn}.url}?payload=\${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw\`); + return url; +}; +`; +} + +/** Collects the names each module already imports, by source. */ +function readImports(program: Node): Map> { + const imports = new Map>(); + for (const statement of program.body as Node[]) { + if (statement.type !== 'ImportDeclaration') { + continue; + } + const source = statement.source.value as string; + const names = imports.get(source) ?? new Set(); + for (const specifier of statement.specifiers as Node[]) { + if (specifier.type === 'ImportSpecifier') { + names.add(specifier.imported.name as string); + } + } + imports.set(source, names); + } + return imports; +} + +/** + * Compiles each `` into a server function that renders the image + * and a component that returns the image url. Returns null when the module has + * no ``. + */ +export function compile( + id: string, + code: string, + options: CompileOptions = {}, +): CompileOutput | null { + if (!code.includes('DynamicImage')) { + return null; + } + const filename = id.split('?')[0]; + const result = parseSync(filename, code, { + lang: getLanguage(filename), + sourceType: 'module', + preserveParens: false, }); + if (result.errors.length > 0) { + throw new SyntaxError(result.errors[0].message); + } + const program = result.program as unknown as Node; + const s = new MagicString(code); + const images: DynamicImage[] = []; + + function visit(node: Node, parent: Node | null): void { + if (!isDynamicImage(node)) { + eachChild(node, (child) => { + visit(child, node); + }); + return; + } + const image = extractDynamicImage(s, code, node); + images.push(image); + // Call the generated component with the reactive values. + const call = `DynamicImage${images.length}({ values: [${image.values.join(', ')}] })`; + const inJsx = parent?.type === 'JSXElement' || parent?.type === 'JSXFragment'; + s.overwrite(node.start, node.end, inJsx ? `{${call}}` : call); + } + visit(program, null); + + if (images.length === 0) { + return null; + } + + // Add the generated code after the imports. + const runtime = options.runtime ?? 'Solid'; + let generated = ''; + for (let i = 0; i < images.length; i++) { + generated += + runtime === 'TanstackStart' + ? createTanstackImage(images[i], i + 1) + : createSolidImage(images[i], i + 1); + } + let lastImportEnd = 0; + for (const statement of program.body as Node[]) { + if (statement.type === 'ImportDeclaration') { + lastImportEnd = statement.end; + } + } + if (lastImportEnd > 0) { + s.appendLeft(lastImportEnd, `\n${generated}`); + } else { + s.prepend(generated); + } + + // Import what the generated code uses, unless the module already does. + const needed: [string, string][] = [ + ['createMemo', 'solid-js'], + ['createOpenGraphImage', '@solidjs/ogp/server'], + ]; + if (runtime === 'Solid') { + needed.push(['GET', '@solidjs/web/server-functions']); + needed.push(['serverFunctionUrl', '@solidjs/web/server-functions']); + } + const imports = readImports(program); + let header = ''; + for (const [name, source] of needed) { + if (!imports.get(source)?.has(name)) { + header += `import { ${name} } from '${source}';\n`; + } + } + s.prepend(header); + + return { + code: s.toString(), + map: s.generateMap({ source: filename, includeContent: true, hires: true }), + }; } diff --git a/packages/ogp/src/compiler/utils.ts b/packages/ogp/src/compiler/utils.ts deleted file mode 100644 index f0ca09e..0000000 --- a/packages/ogp/src/compiler/utils.ts +++ /dev/null @@ -1,226 +0,0 @@ -import * as babel from '@babel/core'; -import { babel as babelUtils } from '@solid-mediakit/shared'; - -type Types = typeof babel.types; - -export interface DynamicImage { - element: babel.types.JSXElement; - reactives: number; - imageOptions?: babel.types.ObjectExpression; -} - -function extractChild(t: Types, element: babel.types.JSXElement): babel.types.JSXElement | null { - const elementChildren: babel.types.JSXElement[] = []; - for (const child of element.children) { - if (t.isJSXElement(child)) { - elementChildren.push(child); - } - } - if (elementChildren.length === 0) { - return null; - } - if (elementChildren.length === 1) { - return elementChildren[0]; - } - // Satori needs one root, so wrap several children in a div. - return t.jsxElement( - t.jsxOpeningElement(t.jsxIdentifier('div'), []), - t.jsxClosingElement(t.jsxIdentifier('div')), - elementChildren, - false, - ); -} - -function extractImageOptions( - element: babel.types.JSXElement, -): babel.types.ObjectExpression | undefined { - const attributes = element.openingElement.attributes; - for (let index = 0; index < attributes.length; index++) { - const attr = attributes[index]; - if (attr.type !== 'JSXAttribute' || attr.name.name !== 'imageOptions') { - continue; - } - // Only an inline object literal can move to the server function. - if ( - attr.value?.type !== 'JSXExpressionContainer' || - attr.value.expression.type !== 'ObjectExpression' - ) { - return undefined; - } - attributes.splice(index, 1); - return attr.value.expression; - } - return undefined; -} - -/** - * Replaces each expression that may change between renders with `r`, and - * returns the replaced expressions in order. They become the server function's - * arguments. - */ -export function extractAndReplaceReactives( - t: Types, - elementPath: babel.NodePath, -): babel.types.Expression[] { - const reactives: babel.types.Expression[] = []; - - function replaceExpression( - path: babel.NodePath< - babel.types.CallExpression | babel.types.MemberExpression | babel.types.Identifier - >, - ): void { - const expr = path.node; - path.replaceWith(t.identifier(`r${reactives.length}`)); - reactives.push(t.cloneNode(expr)); - path.skip(); - } - - elementPath.traverse({ - Property(path) { - if (path.node.type === 'ClassPrivateProperty') { - return; - } - // A computed key is an expression. A plain key is a static name. - const key = path.node.key; - if (path.node.computed && key.type !== 'PrivateName') { - path.node.key = t.identifier(`r${reactives.length}`); - reactives.push(t.cloneNode(key)); - } - path.skip(); - }, - // Any call could return a different value. - CallExpression: replaceExpression, - // Replace the whole access rather than descending into it, otherwise the - // property names of `a.b.c` are each extracted as their own reactive. - MemberExpression: replaceExpression, - Identifier: replaceExpression, - }); - return reactives; -} - -export function replaceDynamicImages( - t: Types, - programPath: babel.NodePath, -): DynamicImage[] { - const images: DynamicImage[] = []; - programPath.traverse({ - JSXElement(elementPath) { - const name = elementPath.node.openingElement.name; - if (!t.isJSXIdentifier(name) || name.name !== 'DynamicImage') { - return; - } - const imageOptions = extractImageOptions(elementPath.node); - const reactives = extractAndReplaceReactives(t, elementPath); - const child = extractChild(t, elementPath.node); - if (!child) { - throw new Error('DynamicImage must have a child element'); - } - images.push({ - reactives: reactives.length, - element: t.cloneNode(child), - imageOptions, - }); - - // Call the generated component with the reactive values. - const call = t.callExpression(t.identifier(`DynamicImage${images.length}`), [ - t.objectExpression([ - t.objectProperty(t.identifier('values'), t.arrayExpression(reactives)), - ]), - ]); - const parent = elementPath.parentPath; - elementPath.replaceWith( - parent.isJSXElement() || parent.isJSXFragment() - ? t.jsxExpressionContainer(call) - : t.expressionStatement(call), - ); - }, - }); - return images; -} - -/** Creates `const [r0, r1, ...] = args`, or null when there are no arguments. */ -export function createArgumentDeclaration( - t: Types, - image: DynamicImage, -): babel.types.VariableDeclaration | null { - if (image.reactives === 0) { - return null; - } - const args: babel.types.Identifier[] = []; - for (let i = 0; i < image.reactives; i++) { - args.push(t.identifier(`r${i}`)); - } - return t.variableDeclaration('const', [ - t.variableDeclarator(t.arrayPattern(args), t.identifier('args')), - ]); -} - -function pushDynamicImages( - images: DynamicImage[], - t: Types, - programPath: babel.NodePath, - template: ( - replacements: Record, - ) => babel.types.Statement | babel.types.Statement[], -): void { - for (let i = 0; i < images.length; i++) { - const image = images[i]; - babelUtils.pushStmts( - template({ - compName: `DynamicImage${i + 1}`, - serverFnName: `DynamicImage${i + 1}ServerFunction`, - jsx: image.element, - args: createArgumentDeclaration(t, image), - imageOptions: image.imageOptions, - }), - programPath, - true, - ); - } -} - -/** Adds the server functions and url components for Solid 2.0 server functions. */ -export function addDynamicImages( - images: DynamicImage[], - t: Types, - programPath: babel.NodePath, -): void { - const template = babel.template( - `const %%serverFnName%% = GET((...args)=>{ - 'use server'; - %%args%% - return createOpenGraphImage(%%jsx%%, %%imageOptions%%); - }); - const %%compName%% = (props)=>{ - const url = createMemo(()=>serverFunctionUrl(%%serverFnName%%, ...props.values)); - return url; - };`, - { plugins: ['jsx'] }, - ); - pushDynamicImages(images, t, programPath, template); -} - -/** Adds the server functions and url components for TanStack Start. */ -export function addDynamicImagesTanstack( - images: DynamicImage[], - t: Types, - programPath: babel.NodePath, -): void { - const template = babel.template( - `const %%serverFnName%% = createServerFn({ - method: "GET", - response: "raw", - }).handler((ctx) => { - const args = ctx.data.values; - %%args%% - return createOpenGraphImage(%%jsx%%, %%imageOptions%%); - }) - const %%compName%% = (props) => { - const payload = () => ({"data":{"values":props.values},"context":{}}) - const url = createMemo(() => \`\${%%serverFnName%%.url}?payload=\${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw\`) - return url - } - `, - ); - pushDynamicImages(images, t, programPath, template); -} diff --git a/packages/ogp/src/unplugin/index.ts b/packages/ogp/src/unplugin/index.ts index 00f7c0a..06e776e 100644 --- a/packages/ogp/src/unplugin/index.ts +++ b/packages/ogp/src/unplugin/index.ts @@ -1,9 +1,8 @@ -import babel from '@babel/core'; -import { babel as babelUtils } from '@solid-mediakit/shared'; import type { FilterPattern } from 'unplugin'; import { createUnplugin } from 'unplugin'; +import { createFilter } from 'unplugin-utils'; import type { Runtime } from '../compiler'; -import { transformOG } from '../compiler'; +import { compile } from '../compiler'; export type Options = { filter?: { @@ -14,31 +13,32 @@ export type Options = { runtime?: Runtime; }; +const DEFAULT_INCLUDE = 'src/**/*.{jsx,tsx,ts,js,mjs,cjs}'; +const DEFAULT_EXCLUDE = 'node_modules/**/*.{jsx,tsx,ts,js,mjs,cjs}'; + export const unplugin = createUnplugin((opts?: Options) => { - const filter = babelUtils.getFilter(opts?.filter); + const filter = createFilter( + opts?.filter?.include ?? DEFAULT_INCLUDE, + opts?.filter?.exclude ?? DEFAULT_EXCLUDE, + ); const log = opts?.log; return { enforce: 'pre', name: 'unplugin-dynamic-image', - async transform(code, id) { - if (!filter(id)) { + transform(code, id) { + if (!filter(id.split('?')[0])) { return null; } - const plugins: babel.ParserOptions['plugins'] = ['typescript', 'jsx']; - - const res = await babel.transformAsync(code, { - plugins: [[transformOG(opts?.runtime)]], - parserOpts: { plugins }, - }); - if (!res?.code) { + const result = compile(id, code, { runtime: opts?.runtime }); + if (!result) { return null; } // The log option prints the compiled output for debugging. if (log === true || (log instanceof RegExp && log.test(id))) { // oxlint-disable-next-line no-console - console.log(id, res.code); + console.log(id, result.code); } - return { code: res.code, map: res.map }; + return result; }, }; }); diff --git a/packages/ogp/tests/compiler.test.ts b/packages/ogp/tests/compiler.test.ts index d626fe1..06f1747 100644 --- a/packages/ogp/tests/compiler.test.ts +++ b/packages/ogp/tests/compiler.test.ts @@ -1,39 +1,60 @@ -import type babel from '@babel/core'; -import type { ResultFormatter } from 'babel-plugin-tester'; -import { pluginTester, prettierFormatter } from 'babel-plugin-tester'; +import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; -import { transformOG } from '../src/compiler'; +import { format } from 'prettier'; +import { describe, expect, it } from 'vitest'; +import type { Runtime } from '../src/compiler'; +import { compile } from '../src/compiler'; -const plugins: babel.ParserOptions['plugins'] = ['typescript', 'jsx']; +interface FixtureOptions { + error?: string; +} -// The fixture outputs are stored in this prettier style. Pinning it here keeps -// the outputs stable whatever formatter config the repo uses. -const prettierOptions = { semi: false, singleQuote: true }; +// The fixture outputs are stored in this prettier style, so the comparison +// ignores how the compiler lays out its output. +async function formatCode(code: string, parser: string): Promise { + return await format(code, { parser, semi: false, singleQuote: true }); +} -const formatResult: ResultFormatter = async (code, options) => - prettierFormatter(code, { ...options, prettierOptions }); +function readOptions(dir: string): FixtureOptions { + const file = join(dir, 'options.json'); + if (!existsSync(file)) { + return {}; + } + const options: unknown = JSON.parse(readFileSync(file, 'utf8')); + if (typeof options === 'object' && options !== null && 'error' in options) { + return { error: String(options.error) }; + } + return {}; +} -pluginTester({ - pluginName: 'OGPlugin', - formatResult, - plugin: transformOG('Solid'), - babelOptions: { - presets: [['@babel/preset-typescript']], - parserOpts: { - plugins, - }, - }, - fixtures: join(import.meta.dirname, 'fixtures/solid'), -}); -pluginTester({ - pluginName: 'OGPlugin', - formatResult, - plugin: transformOG('TanstackStart'), - babelOptions: { - presets: [['@babel/preset-typescript']], - parserOpts: { - plugins, - }, - }, - fixtures: join(import.meta.dirname, 'fixtures/tanstack-start'), -}); +const RUNTIMES: [Runtime, string][] = [ + ['Solid', 'solid'], + ['TanstackStart', 'tanstack-start'], +]; + +for (const [runtime, folder] of RUNTIMES) { + const root = join(import.meta.dirname, 'fixtures', folder); + describe(`compile (${runtime})`, () => { + for (const name of readdirSync(root)) { + const dir = join(root, name); + it(name, async () => { + const isTs = existsSync(join(dir, 'code.tsx')); + const file = join(dir, isTs ? 'code.tsx' : 'code.js'); + const code = readFileSync(file, 'utf8'); + const options = readOptions(dir); + if (options.error) { + expect(() => compile(file, code, { runtime })).toThrow(options.error); + return; + } + const result = compile(file, code, { runtime }); + const actual = await formatCode(result?.code ?? code, isTs ? 'babel-ts' : 'babel'); + const outputFile = join(dir, 'output.js'); + // A missing output is written, so a new fixture only needs its code. + if (!existsSync(outputFile)) { + writeFileSync(outputFile, actual); + } + expect(actual).toBe(readFileSync(outputFile, 'utf8')); + }); + } + }); +} diff --git a/packages/ogp/tests/fixtures/solid/basic/output.js b/packages/ogp/tests/fixtures/solid/basic/output.js index 90551e2..856c296 100644 --- a/packages/ogp/tests/fixtures/solid/basic/output.js +++ b/packages/ogp/tests/fixtures/solid/basic/output.js @@ -1,11 +1,10 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0] = args return createOpenGraphImage(
{r0}
) }) @@ -15,7 +14,6 @@ const DynamicImage1 = (props) => { ) return url } + const [signal] = createSignal('') -const coolVar = DynamicImage1({ - values: [signal()], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [signal()] }) diff --git a/packages/ogp/tests/fixtures/solid/custom-image-options/output.js b/packages/ogp/tests/fixtures/solid/custom-image-options/output.js index 18cda32..6aebf79 100644 --- a/packages/ogp/tests/fixtures/solid/custom-image-options/output.js +++ b/packages/ogp/tests/fixtures/solid/custom-image-options/output.js @@ -1,13 +1,10 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - - return createOpenGraphImage(
Hi!
, { - emoji: 'openmoji', - }) + return createOpenGraphImage(
Hi!
, { emoji: 'openmoji' }) }) const DynamicImage1 = (props) => { const url = createMemo(() => @@ -15,6 +12,4 @@ const DynamicImage1 = (props) => { ) return url } -DynamicImage1({ - values: [], -}) \ No newline at end of file +DynamicImage1({ values: [] }) diff --git a/packages/ogp/tests/fixtures/solid/exclude-static/output.js b/packages/ogp/tests/fixtures/solid/exclude-static/output.js index cecff3c..a8cead7 100644 --- a/packages/ogp/tests/fixtures/solid/exclude-static/output.js +++ b/packages/ogp/tests/fixtures/solid/exclude-static/output.js @@ -1,19 +1,10 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - - return createOpenGraphImage( -
- Hello -
, - ) + return createOpenGraphImage(
Hello
) }) const DynamicImage1 = (props) => { const url = createMemo(() => @@ -21,6 +12,4 @@ const DynamicImage1 = (props) => { ) return url } -const coolVar = DynamicImage1({ - values: [], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [] }) diff --git a/packages/ogp/tests/fixtures/solid/multiple-children/output.js b/packages/ogp/tests/fixtures/solid/multiple-children/output.js index 85cdf90..ea3eaec 100644 --- a/packages/ogp/tests/fixtures/solid/multiple-children/output.js +++ b/packages/ogp/tests/fixtures/solid/multiple-children/output.js @@ -1,10 +1,9 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - return createOpenGraphImage(
@@ -18,6 +17,4 @@ const DynamicImage1 = (props) => { ) return url } -const coolVar = DynamicImage1({ - values: [], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [] }) diff --git a/packages/ogp/tests/fixtures/solid/multiple-images/output.js b/packages/ogp/tests/fixtures/solid/multiple-images/output.js index 200270e..d1ea998 100644 --- a/packages/ogp/tests/fixtures/solid/multiple-images/output.js +++ b/packages/ogp/tests/fixtures/solid/multiple-images/output.js @@ -1,36 +1,28 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' -const DynamicImage2ServerFunction = GET((...args) => { +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' +const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0] = args - return createOpenGraphImage(
{r0}
, { - width: 800, - }) + return createOpenGraphImage(
{r0}
) }) -const DynamicImage2 = (props) => { +const DynamicImage1 = (props) => { const url = createMemo(() => - serverFunctionUrl(DynamicImage2ServerFunction, ...props.values), + serverFunctionUrl(DynamicImage1ServerFunction, ...props.values), ) return url } -const DynamicImage1ServerFunction = GET((...args) => { +const DynamicImage2ServerFunction = GET((...args) => { 'use server' - const [r0] = args - return createOpenGraphImage(
{r0}
) + return createOpenGraphImage(
{r0}
, { width: 800 }) }) -const DynamicImage1 = (props) => { +const DynamicImage2 = (props) => { const url = createMemo(() => - serverFunctionUrl(DynamicImage1ServerFunction, ...props.values), + serverFunctionUrl(DynamicImage2ServerFunction, ...props.values), ) return url } -const first = DynamicImage1({ - values: [a()], -}) -const second = DynamicImage2({ - values: [b()], -}) \ No newline at end of file +const first = DynamicImage1({ values: [a()] }) +const second = DynamicImage2({ values: [b()] }) diff --git a/packages/ogp/tests/fixtures/solid/nested-expressions/output.js b/packages/ogp/tests/fixtures/solid/nested-expressions/output.js index 268ee46..c64550a 100644 --- a/packages/ogp/tests/fixtures/solid/nested-expressions/output.js +++ b/packages/ogp/tests/fixtures/solid/nested-expressions/output.js @@ -1,10 +1,9 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0, r1] = args return createOpenGraphImage(
{r1}
) }) @@ -15,10 +14,5 @@ const DynamicImage1 = (props) => { return url } const coolVar = DynamicImage1({ - values: [ - user.profile.name, - format(count(), { - pad: 2, - }), - ], -}) \ No newline at end of file + values: [user.profile.name, format(count(), { pad: 2 })], +}) diff --git a/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js b/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js index 5fecf02..6f1639e 100644 --- a/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js +++ b/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js @@ -1,12 +1,11 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' import { Image } from '@solidjs/ogp' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0] = args return createOpenGraphImage(
{`Hello ${r0 * 2}!`}
) }) @@ -16,15 +15,12 @@ const DynamicImage1 = (props) => { ) return url } + export default function Home() { const [count] = createSignal(0) return (
- - {DynamicImage1({ - values: [count()], - })} - + {DynamicImage1({ values: [count()] })}
) -} \ No newline at end of file +} diff --git a/packages/ogp/tests/fixtures/solid/no-dynamic-image/output.js b/packages/ogp/tests/fixtures/solid/no-dynamic-image/output.js index 40ea08c..114497e 100644 --- a/packages/ogp/tests/fixtures/solid/no-dynamic-image/output.js +++ b/packages/ogp/tests/fixtures/solid/no-dynamic-image/output.js @@ -1,3 +1,4 @@ import { createSignal } from 'solid-js' + const [signal] = createSignal('') -const coolVar =
{signal()}
\ No newline at end of file +const coolVar =
{signal()}
diff --git a/packages/ogp/tests/fixtures/solid/object-values/code.js b/packages/ogp/tests/fixtures/solid/object-values/code.js new file mode 100644 index 0000000..3cfa07f --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/object-values/code.js @@ -0,0 +1,5 @@ +const coolVar = ( + +
Hi
+
+) diff --git a/packages/ogp/tests/fixtures/solid/object-values/output.js b/packages/ogp/tests/fixtures/solid/object-values/output.js new file mode 100644 index 0000000..6879a7d --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/object-values/output.js @@ -0,0 +1,18 @@ +import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' +const DynamicImage1ServerFunction = GET((...args) => { + 'use server' + const [r0, r1, r2, r3] = args + return createOpenGraphImage( +
Hi
, + ) +}) +const DynamicImage1 = (props) => { + const url = createMemo(() => + serverFunctionUrl(DynamicImage1ServerFunction, ...props.values), + ) + return url +} +const coolVar = DynamicImage1({ values: [color(), background, key, size] }) diff --git a/packages/ogp/tests/fixtures/solid/optional-chain/code.js b/packages/ogp/tests/fixtures/solid/optional-chain/code.js new file mode 100644 index 0000000..4732025 --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/optional-chain/code.js @@ -0,0 +1,5 @@ +const coolVar = ( + +
{user?.profile.name}
+
+) diff --git a/packages/ogp/tests/fixtures/solid/optional-chain/output.js b/packages/ogp/tests/fixtures/solid/optional-chain/output.js new file mode 100644 index 0000000..a5373a0 --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/optional-chain/output.js @@ -0,0 +1,16 @@ +import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' +const DynamicImage1ServerFunction = GET((...args) => { + 'use server' + const [r0] = args + return createOpenGraphImage(
{r0}
) +}) +const DynamicImage1 = (props) => { + const url = createMemo(() => + serverFunctionUrl(DynamicImage1ServerFunction, ...props.values), + ) + return url +} +const coolVar = DynamicImage1({ values: [user?.profile.name] }) diff --git a/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js b/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js index b692e47..87ec217 100644 --- a/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js +++ b/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js @@ -1,21 +1,13 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0] = args return createOpenGraphImage( -
- {} -
, +
{}
, ) }) const DynamicImage1 = (props) => { @@ -24,7 +16,6 @@ const DynamicImage1 = (props) => { ) return url } + const [signal] = createSignal('hello') -const coolVar = DynamicImage1({ - values: [signal()], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [signal()] }) diff --git a/packages/ogp/tests/fixtures/solid/realistic-styles/output.js b/packages/ogp/tests/fixtures/solid/realistic-styles/output.js index 5a190b5..accfc16 100644 --- a/packages/ogp/tests/fixtures/solid/realistic-styles/output.js +++ b/packages/ogp/tests/fixtures/solid/realistic-styles/output.js @@ -1,10 +1,9 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0] = args return createOpenGraphImage(
{ ) return url } -const coolVar = DynamicImage1({ - values: [count()], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [count()] }) diff --git a/packages/ogp/tests/fixtures/solid/typescript/code.tsx b/packages/ogp/tests/fixtures/solid/typescript/code.tsx new file mode 100644 index 0000000..424ab78 --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/typescript/code.tsx @@ -0,0 +1,5 @@ +const coolVar = ( + +
{(title() as string).toUpperCase()}{count satisfies number}
+
+) diff --git a/packages/ogp/tests/fixtures/solid/typescript/output.js b/packages/ogp/tests/fixtures/solid/typescript/output.js new file mode 100644 index 0000000..ef08ee6 --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/typescript/output.js @@ -0,0 +1,23 @@ +import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' +const DynamicImage1ServerFunction = GET((...args) => { + 'use server' + const [r0, r1] = args + return createOpenGraphImage( +
+ {r0} + {r1 satisfies number} +
, + ) +}) +const DynamicImage1 = (props) => { + const url = createMemo(() => + serverFunctionUrl(DynamicImage1ServerFunction, ...props.values), + ) + return url +} +const coolVar = DynamicImage1({ + values: [(title() as string).toUpperCase(), count], +}) diff --git a/packages/ogp/tests/fixtures/solid/variables/output.js b/packages/ogp/tests/fixtures/solid/variables/output.js index 44d315c..d22c5a5 100644 --- a/packages/ogp/tests/fixtures/solid/variables/output.js +++ b/packages/ogp/tests/fixtures/solid/variables/output.js @@ -1,10 +1,9 @@ -import { serverFunctionUrl } from '@solidjs/web/server-functions' -import { GET } from '@solidjs/web/server-functions' -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET } from '@solidjs/web/server-functions' +import { serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' - const [r0] = args return createOpenGraphImage(
{r0}
) }) @@ -14,6 +13,4 @@ const DynamicImage1 = (props) => { ) return url } -const coolVar = DynamicImage1({ - values: [nonSignal], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [nonSignal] }) diff --git a/packages/ogp/tests/fixtures/tanstack-start/basic/output.js b/packages/ogp/tests/fixtures/tanstack-start/basic/output.js index 42cdfde..aabbfa8 100644 --- a/packages/ogp/tests/fixtures/tanstack-start/basic/output.js +++ b/packages/ogp/tests/fixtures/tanstack-start/basic/output.js @@ -1,5 +1,5 @@ -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = createServerFn({ method: 'GET', @@ -10,19 +10,13 @@ const DynamicImage1ServerFunction = createServerFn({ return createOpenGraphImage(
{r0}
) }) const DynamicImage1 = (props) => { - const payload = () => ({ - data: { - values: props.values, - }, - context: {}, - }) + const payload = () => ({ data: { values: props.values }, context: {} }) const url = createMemo( () => `${DynamicImage1ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, ) return url } + const [signal] = createSignal('') -const coolVar = DynamicImage1({ - values: [signal()], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [signal()] }) diff --git a/packages/ogp/tests/fixtures/tanstack-start/custom-image-options/output.js b/packages/ogp/tests/fixtures/tanstack-start/custom-image-options/output.js index b2b24bc..031d907 100644 --- a/packages/ogp/tests/fixtures/tanstack-start/custom-image-options/output.js +++ b/packages/ogp/tests/fixtures/tanstack-start/custom-image-options/output.js @@ -1,27 +1,18 @@ -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' const DynamicImage1ServerFunction = createServerFn({ method: 'GET', response: 'raw', }).handler((ctx) => { const args = ctx.data.values - return createOpenGraphImage(
Hi!
, { - emoji: 'openmoji', - }) + return createOpenGraphImage(
Hi!
, { emoji: 'openmoji' }) }) const DynamicImage1 = (props) => { - const payload = () => ({ - data: { - values: props.values, - }, - context: {}, - }) + const payload = () => ({ data: { values: props.values }, context: {} }) const url = createMemo( () => `${DynamicImage1ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, ) return url } -DynamicImage1({ - values: [], -}) \ No newline at end of file +DynamicImage1({ values: [] }) diff --git a/packages/ogp/tests/fixtures/tanstack-start/multiple-images/output.js b/packages/ogp/tests/fixtures/tanstack-start/multiple-images/output.js index f03aa03..0a3e031 100644 --- a/packages/ogp/tests/fixtures/tanstack-start/multiple-images/output.js +++ b/packages/ogp/tests/fixtures/tanstack-start/multiple-images/output.js @@ -1,52 +1,36 @@ -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' -const DynamicImage2ServerFunction = createServerFn({ +import { createOpenGraphImage } from '@solidjs/ogp/server' +const DynamicImage1ServerFunction = createServerFn({ method: 'GET', response: 'raw', }).handler((ctx) => { const args = ctx.data.values const [r0] = args - return createOpenGraphImage(
{r0}
, { - width: 800, - }) + return createOpenGraphImage(
{r0}
) }) -const DynamicImage2 = (props) => { - const payload = () => ({ - data: { - values: props.values, - }, - context: {}, - }) +const DynamicImage1 = (props) => { + const payload = () => ({ data: { values: props.values }, context: {} }) const url = createMemo( () => - `${DynamicImage2ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, + `${DynamicImage1ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, ) return url } -const DynamicImage1ServerFunction = createServerFn({ +const DynamicImage2ServerFunction = createServerFn({ method: 'GET', response: 'raw', }).handler((ctx) => { const args = ctx.data.values const [r0] = args - return createOpenGraphImage(
{r0}
) + return createOpenGraphImage(
{r0}
, { width: 800 }) }) -const DynamicImage1 = (props) => { - const payload = () => ({ - data: { - values: props.values, - }, - context: {}, - }) +const DynamicImage2 = (props) => { + const payload = () => ({ data: { values: props.values }, context: {} }) const url = createMemo( () => - `${DynamicImage1ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, + `${DynamicImage2ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, ) return url } -const first = DynamicImage1({ - values: [a()], -}) -const second = DynamicImage2({ - values: [b()], -}) \ No newline at end of file +const first = DynamicImage1({ values: [a()] }) +const second = DynamicImage2({ values: [b()] }) diff --git a/packages/ogp/tests/fixtures/tanstack-start/nested-in-jsx/output.js b/packages/ogp/tests/fixtures/tanstack-start/nested-in-jsx/output.js index e103b3a..d4e0327 100644 --- a/packages/ogp/tests/fixtures/tanstack-start/nested-in-jsx/output.js +++ b/packages/ogp/tests/fixtures/tanstack-start/nested-in-jsx/output.js @@ -1,5 +1,5 @@ -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' import { Image } from '@solidjs/ogp' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = createServerFn({ @@ -11,27 +11,19 @@ const DynamicImage1ServerFunction = createServerFn({ return createOpenGraphImage(
{`Hello ${r0 * 2}!`}
) }) const DynamicImage1 = (props) => { - const payload = () => ({ - data: { - values: props.values, - }, - context: {}, - }) + const payload = () => ({ data: { values: props.values }, context: {} }) const url = createMemo( () => `${DynamicImage1ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, ) return url } + export default function Home() { const [count] = createSignal(0) return (
- - {DynamicImage1({ - values: [count()], - })} - + {DynamicImage1({ values: [count()] })}
) -} \ No newline at end of file +} diff --git a/packages/ogp/tests/fixtures/tanstack-start/no-dynamic-image/output.js b/packages/ogp/tests/fixtures/tanstack-start/no-dynamic-image/output.js index 40ea08c..114497e 100644 --- a/packages/ogp/tests/fixtures/tanstack-start/no-dynamic-image/output.js +++ b/packages/ogp/tests/fixtures/tanstack-start/no-dynamic-image/output.js @@ -1,3 +1,4 @@ import { createSignal } from 'solid-js' + const [signal] = createSignal('') -const coolVar =
{signal()}
\ No newline at end of file +const coolVar =
{signal()}
diff --git a/packages/ogp/tests/fixtures/tanstack-start/variables/output.js b/packages/ogp/tests/fixtures/tanstack-start/variables/output.js index 7103424..b89023f 100644 --- a/packages/ogp/tests/fixtures/tanstack-start/variables/output.js +++ b/packages/ogp/tests/fixtures/tanstack-start/variables/output.js @@ -1,5 +1,5 @@ -import { createOpenGraphImage } from '@solidjs/ogp/server' import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' const DynamicImage1ServerFunction = createServerFn({ method: 'GET', response: 'raw', @@ -9,18 +9,11 @@ const DynamicImage1ServerFunction = createServerFn({ return createOpenGraphImage(
{r0}
) }) const DynamicImage1 = (props) => { - const payload = () => ({ - data: { - values: props.values, - }, - context: {}, - }) + const payload = () => ({ data: { values: props.values }, context: {} }) const url = createMemo( () => `${DynamicImage1ServerFunction.url}?payload=${encodeURIComponent(JSON.stringify(payload()))}&createServerFn&raw`, ) return url } -const coolVar = DynamicImage1({ - values: [nonSignal], -}) \ No newline at end of file +const coolVar = DynamicImage1({ values: [nonSignal] }) diff --git a/packages/ogp/tests/unplugin.test.ts b/packages/ogp/tests/unplugin.test.ts index 2a03a46..2399e08 100644 --- a/packages/ogp/tests/unplugin.test.ts +++ b/packages/ogp/tests/unplugin.test.ts @@ -48,7 +48,7 @@ describe('transform', () => { const res = await transform(SOURCE, src('routes/index.tsx')); expect(res!.code).toContain('DynamicImage1ServerFunction'); expect(res!.code).toContain("'use server'"); - expect(res!.code).toContain('import { createOpenGraphImage } from "@solidjs/ogp/server"'); + expect(res!.code).toContain("import { createOpenGraphImage } from '@solidjs/ogp/server'"); expect(res!.code).toContain('DynamicImage1({'); }); @@ -62,9 +62,7 @@ describe('transform', () => { }); it('leaves files without a DynamicImage alone', async () => { - const res = await transform(`const x =
{signal()}
`, src('plain.tsx')); - expect(res!.code).not.toContain('ServerFunction'); - expect(res!.code).not.toContain('createOpenGraphImage'); + expect(await transform(`const x =
{signal()}
`, src('plain.tsx'))).toBeNull(); }); it('surfaces a DynamicImage that has no element child', async () => { diff --git a/packages/ogp/tsconfig.json b/packages/ogp/tsconfig.json index 2876e4a..96b6edf 100644 --- a/packages/ogp/tsconfig.json +++ b/packages/ogp/tsconfig.json @@ -1,5 +1,5 @@ { - "exclude": ["node_modules", "dist"], + "exclude": ["node_modules", "dist", "tests/fixtures"], "include": ["src", "tests", "tsdown.config.ts"], "compilerOptions": { "module": "ESNext", diff --git a/packages/ogp/vitest.config.ts b/packages/ogp/vitest.config.ts index a469994..f557930 100644 --- a/packages/ogp/vitest.config.ts +++ b/packages/ogp/vitest.config.ts @@ -7,7 +7,5 @@ export default defineConfig({ test: { // The plugin sets a browser environment. These tests run on the server. environment: 'node', - // babel-plugin-tester calls `describe`/`it` off the global scope. - globals: true, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de176f5..4435b4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -187,43 +187,40 @@ importers: packages/ogp: dependencies: - '@babel/core': - specifier: ^7.28.0 - version: 7.29.7(supports-color@8.1.1) - '@solid-mediakit/shared': - specifier: ^0.0.6 - version: 0.0.6(supports-color@8.1.1) '@vercel/og': specifier: ^1.0.1 version: 1.0.1(@types/node@26.2.0) + magic-string: + specifier: ^1.4.5 + version: 1.4.5 + oxc-parser: + specifier: ^0.158.0 + version: 0.158.0 satori-html: specifier: ^0.3.2 version: 0.3.2 unplugin: specifier: ^3.3.0 version: 3.3.0(rolldown@1.2.3)(vite@8.2.1(@types/node@26.2.0)(yaml@2.9.1)) + unplugin-utils: + specifier: ^0.3.2 + version: 0.3.2 devDependencies: '@arethetypeswrong/core': specifier: ^0.18.5 version: 0.18.5 - '@babel/preset-typescript': - specifier: ^7.27.0 - version: 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) '@solidjs/vite-plugin': specifier: 3.0.0-next.27 version: 3.0.0-next.27(@solidjs/web@2.0.0-rc.21(solid-js@2.0.0-rc.21))(solid-js@2.0.0-rc.21)(supports-color@8.1.1)(vite@8.2.1(@types/node@26.2.0)(yaml@2.9.1)) '@solidjs/web': specifier: 2.0.0-rc.21 version: 2.0.0-rc.21(solid-js@2.0.0-rc.21) - '@types/babel__core': - specifier: ^7.20.5 - version: 7.20.5 '@types/node': specifier: ^26.2.0 version: 26.2.0 - babel-plugin-tester: - specifier: ^12.0.0 - version: 12.0.0(@babel/core@7.29.7(supports-color@8.1.1)) + prettier: + specifier: ^3.9.10 + version: 3.9.10 publint: specifier: ^0.3.23 version: 0.3.23 @@ -245,14 +242,6 @@ importers: packages: - '@-xun/debug@2.0.2': - resolution: {integrity: sha512-qGaZ4bUZJuWc+YzndcaeOudFmHu4plOcjQGdod/8gafcZY+9oHkrsZNmA1tWrEpQwJV9AJ4QkYgfpreZp9W/Hg==} - engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} - - '@-xun/fs@2.0.0': - resolution: {integrity: sha512-252CZ4OJRszsbP0n+vQRrhdFyDyEzt4NqYvJ/P2Iha4dw/jtmQvAF0wYqARPDZe7uuUG6Og0uQxMUfXFO2BQ7g==} - engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} - '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -272,10 +261,6 @@ packages: resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/core@7.25.2': - resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} - engines: {node: '>=6.9.0'} - '@babel/core@7.29.7': resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} @@ -284,28 +269,14 @@ packages: resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.29.7': - resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} - engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.29.7': resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.29.7': - resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-globals@7.29.7': resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} - '@babel/helper-member-expression-to-functions@7.29.7': - resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.18.6': resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} @@ -320,24 +291,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.29.7': - resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} - engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.29.7': resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} - '@babel/helper-replace-supers@7.29.7': - resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': - resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} @@ -365,30 +322,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.29.7': - resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-commonjs@7.29.7': - resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typescript@7.29.7': - resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/preset-typescript@7.29.7': - resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} @@ -686,10 +619,6 @@ packages: cpu: [x64] os: [win32] - '@jest/schemas@30.4.1': - resolution: {integrity: sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -703,6 +632,9 @@ packages: '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} @@ -733,9 +665,134 @@ packages: '@emnapi/core': ^1.7.1 || 2.0.0-beta.2 || 2.0.0-beta.3 '@emnapi/runtime': ^1.7.1 || 2.0.0-beta.2 || 2.0.0-beta.3 + '@oxc-parser/binding-android-arm-eabi@0.158.0': + resolution: {integrity: sha512-eZ4sHtg/u9mzPaRPWXZ7MmJ3tSFYPDCoDrnAJEXBOIQfdAy0TnzlaJx7nq0HZwE8DkYLQg6GqGZlcjaJrnijKg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.158.0': + resolution: {integrity: sha512-Jqfn2GRXFkEukYBke/d1Hc9a3gB/qA3YRZ1u0D6HecjoOc3d9QvB7YFWyaLDWc139pfH+fIMIeOQ2SNOe1mnvQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.158.0': + resolution: {integrity: sha512-C3/Sl4HE0DE5r64UWBljMTua5aFh14/Urc6o45gK7J8HWjEttJJP26M0bK2eSWcas2zpJZrJlcvwyIxR7YqSZA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.158.0': + resolution: {integrity: sha512-IlU6PMqlk2pbqiidJ1dU5moOeVtzQf4x1n8fXixupLUixA6Sdd3a5WHclvGEZhJom4SjSan0EIpPQkXl9TnjeA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.158.0': + resolution: {integrity: sha512-0uQD/66qKMzcz99yudx7yPWdPziXXl4S4bMxyOwXFPQ6F53Vr2DYM8Tfl9gd/32R2FXlAIqK9g8aNfwJEa0/Kg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.158.0': + resolution: {integrity: sha512-B5ZAgT/cwKVtGa14Z3PEgim8hBTAK//uX/QpwdO2ZKGMqLFDq8myV3jDU1FAGJ0aPZ24SC8X362kKrpFOYmbHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.158.0': + resolution: {integrity: sha512-ZLuYVsBUejzfdFmOlY9yW+g/iCInw+pirfTu+eMk27wFcpyCG6yfTmS/qzzvKARI/VmoUdaXmEcDNUm9hdq5Cg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.158.0': + resolution: {integrity: sha512-QHKIX2SW3pnUFfhAKU8P9t36QlkGGfxgodwoKkp+pQNZmA/PF3DbkA8OgUHoeCIE0aFL1t9Sse+2wr6+zohdRA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.158.0': + resolution: {integrity: sha512-Z57mkQZMjUHh0KxxjmZLNUpqJUT5lPYYpihAOudh4PnQC79Kq7Ujy8KJsmsbla3rU0xV4aCpUKDCfVx0wnYn+Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.158.0': + resolution: {integrity: sha512-jl6537qMp3Tb2D0J1oYzU/xzvYOM7ZDBf4Dhg8WvgkV+wgept/r2rX30PdWTE5gNo6QdHkOTz7le+9yldU1VwQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.158.0': + resolution: {integrity: sha512-BFwDkCZ2K6VuSfBlKLItXkTYMN/8SAcFpZgBohU6qjlq4HrRKBqOXW/J0ViwZ4BHZuNFxgrhUXcM3hcalZnQaA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.158.0': + resolution: {integrity: sha512-3YcZPBhpDhD9BUWQct+70To5wJhY36pvn+gA04ArMCdREd76EIXB14IgYsDsRqIgOXSXT1okMpHA6UEamM/QQg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.158.0': + resolution: {integrity: sha512-C+HBtM/aauGsp1sRuKHnB6yqrFCfGzGgS/3b/Alwz+bGIgOCm6DiNnFEnA14MOQ1YA63ikjpmTN7LPb505pkCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.158.0': + resolution: {integrity: sha512-COR5cFRE6DqmxZGE9QCJG1X7uUYxNdSYkMR7J9igRLnZqZ8ki6kJIa5S4czYHeIjdNyYn4vo1CsK3rQsK5sjrA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.158.0': + resolution: {integrity: sha512-lF8YZdySxTjYnHfitZpbFWpyyxDchZj+TIyvDnzH3AGZlUvyrsu7BeORPdf05cLFwiyb+RPqAae4EJ7uu5xAhg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.158.0': + resolution: {integrity: sha512-m2HMKQgNNatcwOeCDCewrW5gvmHE61WFKl2J4KHiCGNpJb6ZI8n3T/JzwxFkt8kY3E27fJwvHM6t3WIEgtPiAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-win32-arm64-msvc@0.158.0': + resolution: {integrity: sha512-Kksc5jIB7cE9vgoePyIQ8sRkXA4kAfO5oDEI6X+JJMGGTRnvtGafQniLXAHur9XU+5hUgMOGoZcyA8L+JvBu6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.158.0': + resolution: {integrity: sha512-HhxU9z7t6gqSh7UslTwD/wha5U2uD44Ss7GKtrBSJfG061iDrJ1Qk63N0Dzh3clax9pjJgYFnMpQRt72Q1bP8w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.158.0': + resolution: {integrity: sha512-/SLN0ot62iL6XhmsWyLdU+37vjVCgDP96sOqeCPIFov63odr4DPv9vgq+lIkZMBMOxpWsSMcwDfpERsRAyCl8A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-project/types@0.143.0': resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} + '@oxc-project/types@0.158.0': + resolution: {integrity: sha512-xZ66qA4WmLbTLlxH3mqMd8f9UKbaOzOT0ATwFf4DH/14pMgpUrtqtjyYzOQmgfl2a0iRAAMbQ9G1th/67jRzGw==} + '@oxfmt/binding-android-arm-eabi@0.78.0': resolution: {integrity: sha512-1x9NPGQG5WMOOT8spRP4hPbeqwB/P9ayxFo4EUDSle6mLmtYRqE6suXgHr93/S2nnszy77LlIa8klkKdWtHbMw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1118,26 +1175,11 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@rollup/pluginutils@5.4.0': - resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@shuding/opentype.js@1.4.0-beta.0': resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} engines: {node: '>= 8.0.0'} hasBin: true - '@sinclair/typebox@0.34.52': - resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==} - - '@solid-mediakit/shared@0.0.6': - resolution: {integrity: sha512-OFy6QAS9fXQicV4+FmLtOzgWAjYuO1FjQlta09qBjgpRENr+xZqiPP8gUlRT0nph/dr7NP18b1cWiCzThZWqkw==} - '@solidjs/signals@2.0.0-rc.21': resolution: {integrity: sha512-F1TUMO/nd1XC//+tcaWxibOOgXBHQGmNQnAeiDnpLh+1smnlwIgKF6pc20evlyfQwqf0gP6rH4sNEqCPBNcpgg==} engines: {node: '>=22.12.0'} @@ -1180,18 +1222,12 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - '@types/debug@4.1.13': - resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} - '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/ms@2.1.0': - resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@26.2.0': resolution: {integrity: sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==} @@ -1507,10 +1543,6 @@ packages: '@yuku-toolchain/types@0.8.4': resolution: {integrity: sha512-p7JE8flrj7ijZ/qLjHi4UwKqMarMD6zumbKXhrjp2I2iLJOuTYiQyci2U36VlXcUlNyzsY7E/mLnKCHotbzJVw==} - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansis@4.3.1: resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} engines: {node: '>=14'} @@ -1519,12 +1551,6 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - babel-plugin-tester@12.0.0: - resolution: {integrity: sha512-V3ZFYmXPV9fm3ArpLHbvh0R5IfwnyFwlvdZ2FFQ49af4seC10U0JDWssjhXInuDDli6hyQsoOybGFSTCovrGyA==} - engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} - peerDependencies: - '@babel/core': '>=7.22.0' - babel-preset-solid@2.0.0-beta.34: resolution: {integrity: sha512-r06URXFAiHtT9dIKG4sF2mgqxh6rpd6KOYtPNX4HFxC5nZLsNSybLZcuZ30cONUl//n/Tav6IzZQiSwxqCkLfg==} peerDependencies: @@ -1562,10 +1588,6 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} - chalk@5.6.2: - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} @@ -1575,9 +1597,6 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js@3.50.0: - resolution: {integrity: sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==} - css-background-parser@0.1.0: resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==} @@ -1648,16 +1667,9 @@ packages: escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - exit-hook@4.0.0: - resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} - engines: {node: '>=18'} - expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} @@ -1827,9 +1839,6 @@ packages: linebreak@1.1.0: resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==} - lodash.mergewith@4.6.2: - resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} - lru-cache@11.5.2: resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} @@ -1840,14 +1849,13 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.4.5: + resolution: {integrity: sha512-oLLC2+YvQUfAa+vxoufE/yc1icb87M9iXIRqAoR/2EhE/8cb3SF/+Gi0c2By1B+5Vz2e2vQtUvHiu1+63Znh+w==} + merge-anything@5.1.7: resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} engines: {node: '>=12.13'} - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1868,6 +1876,10 @@ packages: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + oxc-parser@0.158.0: + resolution: {integrity: sha512-BKmaZZXp667kLC8Od/ivIkbw6yaxTSqw8ViI1Tvl21E6r+6NLdwDmo43LpL2Ebt/PDMu1d4tcdBucMSor+cL1g==} + engines: {node: ^20.19.0 || >=22.12.0} + oxfmt@0.78.0: resolution: {integrity: sha512-uagX+70mKqh/YqxB6ON/lkxVPH6E1Z7pfP2x6XVRPPyiDCZtX6o1xIEeXAIXJ/2wA5ViX4RFuW+IAQn85yJdWg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1934,15 +1946,11 @@ packages: resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} engines: {node: ^10 || ^12 || >=14} - prettier@3.9.6: - resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} + prettier@3.9.10: + resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==} engines: {node: '>=14'} hasBin: true - pretty-format@30.4.1: - resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - publint@0.3.23: resolution: {integrity: sha512-5MQipUPcB7MWw84zLUkHrg/H/UBtk3LL+A0GngTTBSsiNJLQurMUaSIRG3edlOrRz4UFe0AOKK9TZdIWviV+jQ==} engines: {node: '>=18'} @@ -1951,16 +1959,6 @@ packages: quansync@1.0.0: resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - react-is@19.2.8: - resolution: {integrity: sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==} - - rejoinder@2.1.0: - resolution: {integrity: sha512-dLN0+SBPutC6bVFCH2+1o2VrHrvAj/PX6MzTemeaEKlCL10JKPMRlqszkitLQnHVgm90QQ94wxoBJRgfIEkstg==} - engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} - resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} @@ -2055,10 +2053,6 @@ packages: string.prototype.codepointat@0.2.1: resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} @@ -2130,10 +2124,6 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} - typescript@5.6.1-rc: resolution: {integrity: sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ==} engines: {node: '>=14.17'} @@ -2156,6 +2146,10 @@ packages: unicode-trie@2.0.0: resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} + unplugin-utils@0.3.2: + resolution: {integrity: sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==} + engines: {node: '>=20.19.0'} + unplugin@3.3.0: resolution: {integrity: sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2328,17 +2322,6 @@ packages: snapshots: - '@-xun/debug@2.0.2': - dependencies: - '@types/debug': 4.1.13 - debug: 4.4.3(supports-color@8.1.1) - supports-color: 8.1.1 - type-fest: 4.41.0 - - '@-xun/fs@2.0.0': - dependencies: - type-fest: 4.41.0 - '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -2365,26 +2348,6 @@ snapshots: '@babel/compat-data@7.29.7': {} - '@babel/core@7.25.2(supports-color@8.1.1)': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.8 - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.25.2(supports-color@8.1.1))(supports-color@8.1.1) - '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.8 - '@babel/template': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@8.1.1) - '@babel/types': 7.29.8 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/core@7.29.7(supports-color@8.1.1)': dependencies: '@babel/code-frame': 7.29.7 @@ -2413,10 +2376,6 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.29.7': - dependencies: - '@babel/types': 7.29.8 - '@babel/helper-compilation-targets@7.29.7': dependencies: '@babel/compat-data': 7.29.7 @@ -2425,28 +2384,8 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) - '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) - '@babel/traverse': 7.29.8(supports-color@8.1.1) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/helper-globals@7.29.7': {} - '@babel/helper-member-expression-to-functions@7.29.7(supports-color@8.1.1)': - dependencies: - '@babel/traverse': 7.29.8(supports-color@8.1.1) - '@babel/types': 7.29.8 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-imports@7.18.6': dependencies: '@babel/types': 7.29.8 @@ -2458,15 +2397,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.25.2(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.25.2(supports-color@8.1.1) - '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) - '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -2476,28 +2406,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-optimise-call-expression@7.29.7': - dependencies: - '@babel/types': 7.29.8 - '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) - '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/traverse': 7.29.8(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - '@babel/helper-skip-transparent-expression-wrappers@7.29.7(supports-color@8.1.1)': - dependencies: - '@babel/traverse': 7.29.8(supports-color@8.1.1) - '@babel/types': 7.29.8 - transitivePeerDependencies: - - supports-color - '@babel/helper-string-parser@7.29.7': {} '@babel/helper-validator-identifier@7.29.7': {} @@ -2518,41 +2428,6 @@ snapshots: '@babel/core': 7.29.7(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.29.7 - - '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) - '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) - transitivePeerDependencies: - - supports-color - - '@babel/preset-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.7(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-validator-option': 7.29.7 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) - '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) - '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 @@ -2864,10 +2739,6 @@ snapshots: '@img/sharp-win32-x64@0.35.3': optional: true - '@jest/schemas@30.4.1': - dependencies: - '@sinclair/typebox': 0.34.52 - '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2882,6 +2753,8 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} + '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -2917,8 +2790,67 @@ snapshots: '@tybys/wasm-util': 0.10.4 optional: true + '@oxc-parser/binding-android-arm-eabi@0.158.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.158.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.158.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.158.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.158.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.158.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.158.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.158.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.158.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.158.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.158.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.158.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.158.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.158.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.158.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.158.0': + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.158.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.158.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.158.0': + optional: true + '@oxc-project/types@0.143.0': {} + '@oxc-project/types@0.158.0': {} + '@oxfmt/binding-android-arm-eabi@0.78.0': optional: true @@ -3107,27 +3039,11 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@rollup/pluginutils@5.4.0': - dependencies: - '@types/estree': 1.0.9 - estree-walker: 2.0.2 - picomatch: 4.0.5 - '@shuding/opentype.js@1.4.0-beta.0': dependencies: fflate: 0.7.5 string.prototype.codepointat: 0.2.1 - '@sinclair/typebox@0.34.52': {} - - '@solid-mediakit/shared@0.0.6(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.25.2(supports-color@8.1.1) - '@rollup/pluginutils': 5.4.0 - transitivePeerDependencies: - - rollup - - supports-color - '@solidjs/signals@2.0.0-rc.21': {} '@solidjs/vite-plugin@3.0.0-next.27(@solidjs/web@2.0.0-rc.21(solid-js@2.0.0-rc.21))(solid-js@2.0.0-rc.21)(supports-color@8.1.1)(vite@8.2.1(@types/node@26.2.0)(yaml@2.9.1))': @@ -3184,16 +3100,10 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - '@types/debug@4.1.13': - dependencies: - '@types/ms': 2.1.0 - '@types/deep-eql@4.0.2': {} '@types/estree@1.0.9': {} - '@types/ms@2.1.0': {} - '@types/node@26.2.0': dependencies: undici-types: 8.3.0 @@ -3382,24 +3292,10 @@ snapshots: '@yuku-toolchain/types@0.8.4': {} - ansi-styles@5.2.0: {} - ansis@4.3.1: {} assertion-error@2.0.1: {} - babel-plugin-tester@12.0.0(@babel/core@7.29.7(supports-color@8.1.1)): - dependencies: - '@-xun/fs': 2.0.0 - '@babel/core': 7.29.7(supports-color@8.1.1) - core-js: 3.50.0 - lodash.mergewith: 4.6.2 - prettier: 3.9.6 - pretty-format: 30.4.1 - rejoinder: 2.1.0 - strip-indent~3: strip-indent@3.0.0 - type-fest: 4.41.0 - babel-preset-solid@2.0.0-beta.34(@babel/core@7.29.7(supports-color@8.1.1))(solid-js@2.0.0-rc.21): dependencies: '@babel/core': 7.29.7(supports-color@8.1.1) @@ -3427,16 +3323,12 @@ snapshots: chai@6.2.2: {} - chalk@5.6.2: {} - cjs-module-lexer@1.4.3: {} color-name@1.1.4: {} convert-source-map@2.0.0: {} - core-js@3.50.0: {} - css-background-parser@0.1.0: {} css-box-shadow@1.0.0-3: {} @@ -3479,14 +3371,10 @@ snapshots: escape-html@1.0.3: {} - estree-walker@2.0.2: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 - exit-hook@4.0.0: {} - expect-type@1.4.0: {} fast-string-truncated-width@3.0.3: {} @@ -3516,7 +3404,8 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 - has-flag@4.0.0: {} + has-flag@4.0.0: + optional: true hex-rgb@4.3.0: {} @@ -3601,8 +3490,6 @@ snapshots: base64-js: 0.0.8 unicode-trie: 2.0.0 - lodash.mergewith@4.6.2: {} - lru-cache@11.5.2: {} lru-cache@5.1.1: @@ -3613,12 +3500,14 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@1.4.5: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + merge-anything@5.1.7: dependencies: is-what: 4.1.16 - min-indent@1.0.1: {} - mri@1.2.0: {} ms@2.1.3: {} @@ -3629,6 +3518,30 @@ snapshots: obug@2.1.4: {} + oxc-parser@0.158.0: + dependencies: + '@oxc-project/types': 0.158.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.158.0 + '@oxc-parser/binding-android-arm64': 0.158.0 + '@oxc-parser/binding-darwin-arm64': 0.158.0 + '@oxc-parser/binding-darwin-x64': 0.158.0 + '@oxc-parser/binding-freebsd-x64': 0.158.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.158.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.158.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.158.0 + '@oxc-parser/binding-linux-arm64-musl': 0.158.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.158.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.158.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.158.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.158.0 + '@oxc-parser/binding-linux-x64-gnu': 0.158.0 + '@oxc-parser/binding-linux-x64-musl': 0.158.0 + '@oxc-parser/binding-openharmony-arm64': 0.158.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.158.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.158.0 + '@oxc-parser/binding-win32-x64-msvc': 0.158.0 + oxfmt@0.78.0: dependencies: tinypool: 2.2.0 @@ -3714,14 +3627,7 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - prettier@3.9.6: {} - - pretty-format@30.4.1: - dependencies: - '@jest/schemas': 30.4.1 - ansi-styles: 5.2.0 - react-is-18: react-is@18.3.1 - react-is-19: react-is@19.2.8 + prettier@3.9.10: {} publint@0.3.23: dependencies: @@ -3732,17 +3638,6 @@ snapshots: quansync@1.0.0: {} - react-is@18.3.1: {} - - react-is@19.2.8: {} - - rejoinder@2.1.0: - dependencies: - '@-xun/debug': 2.0.2 - chalk: 5.6.2 - core-js: 3.50.0 - exit-hook: 4.0.0 - resolve-pkg-maps@1.0.0: {} rolldown-plugin-dts@0.27.14(rolldown@1.2.3)(typescript@7.0.2): @@ -3866,13 +3761,10 @@ snapshots: string.prototype.codepointat@0.2.1: {} - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - supports-color@8.1.1: dependencies: has-flag: 4.0.0 + optional: true tiny-inflate@1.0.3: {} @@ -3922,8 +3814,6 @@ snapshots: tslib@2.8.1: {} - type-fest@4.41.0: {} - typescript@5.6.1-rc: {} typescript@7.0.2: @@ -3963,6 +3853,11 @@ snapshots: pako: 0.2.9 tiny-inflate: 1.0.3 + unplugin-utils@0.3.2: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.7 + unplugin@3.3.0(rolldown@1.2.3)(vite@8.2.1(@types/node@26.2.0)(yaml@2.9.1)): dependencies: '@jridgewell/remapping': 2.3.5 From 9a633ddb2e95a694f4ab682a7d737f608c430d6e Mon Sep 17 00:00:00 2001 From: "Alexis H. Munsayac" Date: Wed, 11 Nov 2026 22:09:44 +0800 Subject: [PATCH 2/3] fix(compiler): add an import when the module only has an aliased one import { createMemo as memo } does not bind createMemo, but the compiler treated it as present and the generated code threw a ReferenceError. Generated imports from one source are now one statement, and a fixture without an output fails unless UPDATE=1 is set. Co-Authored-By: Claude Opus 5.5 --- packages/ogp/src/compiler/index.ts | 22 ++++++++++++++----- packages/ogp/tests/compiler.test.ts | 4 ++-- .../fixtures/solid/aliased-import/code.js | 4 ++++ .../fixtures/solid/aliased-import/output.js | 18 +++++++++++++++ .../ogp/tests/fixtures/solid/basic/output.js | 3 +-- .../solid/custom-image-options/output.js | 3 +-- .../fixtures/solid/exclude-static/output.js | 3 +-- .../solid/multiple-children/output.js | 3 +-- .../fixtures/solid/multiple-images/output.js | 3 +-- .../solid/nested-expressions/output.js | 3 +-- .../fixtures/solid/nested-in-jsx/output.js | 3 +-- .../fixtures/solid/object-values/output.js | 3 +-- .../fixtures/solid/optional-chain/output.js | 3 +-- .../solid/partially-dynamic-object/output.js | 3 +-- .../fixtures/solid/realistic-styles/output.js | 3 +-- .../tests/fixtures/solid/typescript/output.js | 3 +-- .../tests/fixtures/solid/variables/output.js | 3 +-- 17 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 packages/ogp/tests/fixtures/solid/aliased-import/code.js create mode 100644 packages/ogp/tests/fixtures/solid/aliased-import/output.js diff --git a/packages/ogp/src/compiler/index.ts b/packages/ogp/src/compiler/index.ts index ff019f2..631ba50 100644 --- a/packages/ogp/src/compiler/index.ts +++ b/packages/ogp/src/compiler/index.ts @@ -172,7 +172,10 @@ const DynamicImage${id} = (props) => { `; } -/** Collects the names each module already imports, by source. */ +/** + * Collects, by source, the names each module imports under their own name. + * An aliased import (`import { a as b }`) does not bind `a`, so it is left out. + */ function readImports(program: Node): Map> { const imports = new Map>(); for (const statement of program.body as Node[]) { @@ -182,8 +185,11 @@ function readImports(program: Node): Map> { const source = statement.source.value as string; const names = imports.get(source) ?? new Set(); for (const specifier of statement.specifiers as Node[]) { - if (specifier.type === 'ImportSpecifier') { - names.add(specifier.imported.name as string); + if ( + specifier.type === 'ImportSpecifier' && + specifier.imported.name === specifier.local.name + ) { + names.add(specifier.local.name as string); } } imports.set(source, names); @@ -268,12 +274,18 @@ export function compile( needed.push(['serverFunctionUrl', '@solidjs/web/server-functions']); } const imports = readImports(program); - let header = ''; + const missing = new Map(); for (const [name, source] of needed) { if (!imports.get(source)?.has(name)) { - header += `import { ${name} } from '${source}';\n`; + const names = missing.get(source) ?? []; + names.push(name); + missing.set(source, names); } } + let header = ''; + for (const [source, names] of missing) { + header += `import { ${names.join(', ')} } from '${source}';\n`; + } s.prepend(header); return { diff --git a/packages/ogp/tests/compiler.test.ts b/packages/ogp/tests/compiler.test.ts index 06f1747..715edbd 100644 --- a/packages/ogp/tests/compiler.test.ts +++ b/packages/ogp/tests/compiler.test.ts @@ -49,8 +49,8 @@ for (const [runtime, folder] of RUNTIMES) { const result = compile(file, code, { runtime }); const actual = await formatCode(result?.code ?? code, isTs ? 'babel-ts' : 'babel'); const outputFile = join(dir, 'output.js'); - // A missing output is written, so a new fixture only needs its code. - if (!existsSync(outputFile)) { + // UPDATE=1 writes the outputs, so a new fixture only needs its code. + if (process.env.UPDATE === '1') { writeFileSync(outputFile, actual); } expect(actual).toBe(readFileSync(outputFile, 'utf8')); diff --git a/packages/ogp/tests/fixtures/solid/aliased-import/code.js b/packages/ogp/tests/fixtures/solid/aliased-import/code.js new file mode 100644 index 0000000..5e9b857 --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/aliased-import/code.js @@ -0,0 +1,4 @@ +import { createMemo as memo } from 'solid-js' + +const value = memo(() => 1) +const coolVar =
{value()}
diff --git a/packages/ogp/tests/fixtures/solid/aliased-import/output.js b/packages/ogp/tests/fixtures/solid/aliased-import/output.js new file mode 100644 index 0000000..950716a --- /dev/null +++ b/packages/ogp/tests/fixtures/solid/aliased-import/output.js @@ -0,0 +1,18 @@ +import { createMemo } from 'solid-js' +import { createOpenGraphImage } from '@solidjs/ogp/server' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' +import { createMemo as memo } from 'solid-js' +const DynamicImage1ServerFunction = GET((...args) => { + 'use server' + const [r0] = args + return createOpenGraphImage(
{r0}
) +}) +const DynamicImage1 = (props) => { + const url = createMemo(() => + serverFunctionUrl(DynamicImage1ServerFunction, ...props.values), + ) + return url +} + +const value = memo(() => 1) +const coolVar = DynamicImage1({ values: [value()] }) diff --git a/packages/ogp/tests/fixtures/solid/basic/output.js b/packages/ogp/tests/fixtures/solid/basic/output.js index 856c296..00e5e05 100644 --- a/packages/ogp/tests/fixtures/solid/basic/output.js +++ b/packages/ogp/tests/fixtures/solid/basic/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = GET((...args) => { 'use server' diff --git a/packages/ogp/tests/fixtures/solid/custom-image-options/output.js b/packages/ogp/tests/fixtures/solid/custom-image-options/output.js index 6aebf79..3f08311 100644 --- a/packages/ogp/tests/fixtures/solid/custom-image-options/output.js +++ b/packages/ogp/tests/fixtures/solid/custom-image-options/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' return createOpenGraphImage(
Hi!
, { emoji: 'openmoji' }) diff --git a/packages/ogp/tests/fixtures/solid/exclude-static/output.js b/packages/ogp/tests/fixtures/solid/exclude-static/output.js index a8cead7..cd3c2b2 100644 --- a/packages/ogp/tests/fixtures/solid/exclude-static/output.js +++ b/packages/ogp/tests/fixtures/solid/exclude-static/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' return createOpenGraphImage(
Hello
) diff --git a/packages/ogp/tests/fixtures/solid/multiple-children/output.js b/packages/ogp/tests/fixtures/solid/multiple-children/output.js index ea3eaec..4ca8603 100644 --- a/packages/ogp/tests/fixtures/solid/multiple-children/output.js +++ b/packages/ogp/tests/fixtures/solid/multiple-children/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' return createOpenGraphImage( diff --git a/packages/ogp/tests/fixtures/solid/multiple-images/output.js b/packages/ogp/tests/fixtures/solid/multiple-images/output.js index d1ea998..8147f3a 100644 --- a/packages/ogp/tests/fixtures/solid/multiple-images/output.js +++ b/packages/ogp/tests/fixtures/solid/multiple-images/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0] = args diff --git a/packages/ogp/tests/fixtures/solid/nested-expressions/output.js b/packages/ogp/tests/fixtures/solid/nested-expressions/output.js index c64550a..9263811 100644 --- a/packages/ogp/tests/fixtures/solid/nested-expressions/output.js +++ b/packages/ogp/tests/fixtures/solid/nested-expressions/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0, r1] = args diff --git a/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js b/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js index 6f1639e..d3f6d6d 100644 --- a/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js +++ b/packages/ogp/tests/fixtures/solid/nested-in-jsx/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' import { Image } from '@solidjs/ogp' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = GET((...args) => { diff --git a/packages/ogp/tests/fixtures/solid/object-values/output.js b/packages/ogp/tests/fixtures/solid/object-values/output.js index 6879a7d..bd0c2ad 100644 --- a/packages/ogp/tests/fixtures/solid/object-values/output.js +++ b/packages/ogp/tests/fixtures/solid/object-values/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0, r1, r2, r3] = args diff --git a/packages/ogp/tests/fixtures/solid/optional-chain/output.js b/packages/ogp/tests/fixtures/solid/optional-chain/output.js index a5373a0..0dfff6a 100644 --- a/packages/ogp/tests/fixtures/solid/optional-chain/output.js +++ b/packages/ogp/tests/fixtures/solid/optional-chain/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0] = args diff --git a/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js b/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js index 87ec217..a7925b2 100644 --- a/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js +++ b/packages/ogp/tests/fixtures/solid/partially-dynamic-object/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' import { createSignal } from 'solid-js' const DynamicImage1ServerFunction = GET((...args) => { 'use server' diff --git a/packages/ogp/tests/fixtures/solid/realistic-styles/output.js b/packages/ogp/tests/fixtures/solid/realistic-styles/output.js index accfc16..13215bb 100644 --- a/packages/ogp/tests/fixtures/solid/realistic-styles/output.js +++ b/packages/ogp/tests/fixtures/solid/realistic-styles/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0] = args diff --git a/packages/ogp/tests/fixtures/solid/typescript/output.js b/packages/ogp/tests/fixtures/solid/typescript/output.js index ef08ee6..4009e24 100644 --- a/packages/ogp/tests/fixtures/solid/typescript/output.js +++ b/packages/ogp/tests/fixtures/solid/typescript/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0, r1] = args diff --git a/packages/ogp/tests/fixtures/solid/variables/output.js b/packages/ogp/tests/fixtures/solid/variables/output.js index d22c5a5..432a3af 100644 --- a/packages/ogp/tests/fixtures/solid/variables/output.js +++ b/packages/ogp/tests/fixtures/solid/variables/output.js @@ -1,7 +1,6 @@ import { createMemo } from 'solid-js' import { createOpenGraphImage } from '@solidjs/ogp/server' -import { GET } from '@solidjs/web/server-functions' -import { serverFunctionUrl } from '@solidjs/web/server-functions' +import { GET, serverFunctionUrl } from '@solidjs/web/server-functions' const DynamicImage1ServerFunction = GET((...args) => { 'use server' const [r0] = args From e73a3879d83d4fb42562cbcb9920928682d40ab4 Mon Sep 17 00:00:00 2001 From: "Alexis H. Munsayac" Date: Wed, 11 Nov 2026 22:13:45 +0800 Subject: [PATCH 3/3] chore: add a changeset for the oxc compiler Co-Authored-By: Claude Opus 5.5 --- .changeset/compiler-on-oxc.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/compiler-on-oxc.md diff --git a/.changeset/compiler-on-oxc.md b/.changeset/compiler-on-oxc.md new file mode 100644 index 0000000..9fd6f6b --- /dev/null +++ b/.changeset/compiler-on-oxc.md @@ -0,0 +1,7 @@ +--- +'@solidjs/ogp': patch +--- + +- The compiler runs on oxc and returns a source map. Babel is no longer a dependency. +- Values inside objects in a `DynamicImage`, such as `style={{ color: color() }}`, are passed to the server function. +- An aliased import, such as `import { createMemo as memo }`, no longer stops the compiler from adding the import it needs.