@storybook-astro/framework 1.4.0 → 1.5.0-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-6RIGYMZP.js +144 -0
- package/dist/chunk-6RIGYMZP.js.map +1 -0
- package/dist/{chunk-VZXGPM6P.js → chunk-7UF6LK4Z.js} +62 -14
- package/dist/{chunk-VZXGPM6P.js.map → chunk-7UF6LK4Z.js.map} +1 -1
- package/dist/{chunk-BV6V2Z4X.js → chunk-XVVIGJV6.js} +2 -2
- package/dist/preset.js +32 -5
- package/dist/preset.js.map +1 -1
- package/dist/renderer/renderer-dev.js +2 -0
- package/dist/renderer/renderer-dev.js.map +1 -1
- package/dist/renderer/renderer-server.js +3 -1
- package/dist/renderer/renderer-server.js.map +1 -1
- package/dist/renderer/renderer-static.js +2 -0
- package/dist/renderer/renderer-static.js.map +1 -1
- package/dist/testing.js +3 -3
- package/dist/{viteStorybookAstroMiddlewarePlugin-246I5D3Y.js → viteStorybookAstroMiddlewarePlugin-LUMKF7NG.js} +2 -2
- package/dist/vitest/global-setup.js +2 -2
- package/dist/vitest/index.js +1 -1
- package/package.json +5 -2
- package/src/loadUserAstroConfig.test.ts +149 -0
- package/src/loadUserAstroConfig.ts +126 -25
- package/src/preset.ts +45 -2
- package/src/renderer/renderer-dev.ts +2 -0
- package/src/renderer/renderer-server.ts +2 -0
- package/src/renderer/renderer-static.ts +2 -0
- package/src/shim.d.ts +21 -0
- package/src/virtual.d.ts +1 -0
- package/src/vitePluginAstroComponentMarker.test.ts +231 -0
- package/src/vitePluginAstroComponentMarker.ts +173 -51
- package/src/viteStorybookAstroRendererPlugin.ts +2 -1
- package/dist/chunk-E4LB75JN.js +0 -89
- package/dist/chunk-E4LB75JN.js.map +0 -1
- /package/dist/{chunk-BV6V2Z4X.js.map → chunk-XVVIGJV6.js.map} +0 -0
- /package/dist/{viteStorybookAstroMiddlewarePlugin-246I5D3Y.js.map → viteStorybookAstroMiddlewarePlugin-LUMKF7NG.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/renderer/renderer-dev.ts"],"sourcesContent":["import type {\n RenderComponentInput,\n RenderPromise,\n RenderResponseMessage\n} from '@storybook-astro/renderer/types';\n\nconst pendingMessages = new Map<string, RenderPromise>();\nconst ASTRO_SERVER_UNAVAILABLE_ERROR_NAME = 'AstroRenderServerUnavailableError';\n\nexport async function render(data: RenderComponentInput, timeoutMs = 5000) {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const id = crypto.randomUUID();\n\n const promise = new Promise<RenderResponseMessage['data']>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n pendingMessages.delete(id);\n\n const error = new Error(\n `Unable to reach Astro rendering server. No render response was received within ${timeoutMs}ms.`\n );\n\n error.name = ASTRO_SERVER_UNAVAILABLE_ERROR_NAME;\n\n reject(error);\n }, timeoutMs);\n\n pendingMessages.set(id, { resolve, reject, timeoutId });\n });\n\n import.meta.hot?.send('astro:render:request', {\n ...data,\n id\n });\n\n return promise;\n}\n\nexport function init() {\n import.meta.hot?.on('vite:afterUpdate', (payload) => {\n if (payload.updates.some((update) => isAstroStyleUpdate(update.path))) {\n applyStyles();\n }\n });\n\n import.meta.hot?.on('astro:render:response', (data: RenderResponseMessage['data']) => {\n if (!data.id || !pendingMessages.has(data.id)) {\n return;\n }\n\n const pendingMessage = pendingMessages.get(data.id);\n\n if (!pendingMessage) {\n return;\n }\n\n clearTimeout(pendingMessage.timeoutId);\n pendingMessages.delete(data.id);\n pendingMessage.resolve(data);\n });\n}\n\nexport function applyStyles() {\n Array.from(document.querySelectorAll('style[data-vite-dev-id]'))\n .filter((element) => /__vite__updateStyle/.test(element.innerHTML))\n .forEach((element) => {\n const script = document.createElement('script');\n\n script.type = 'module';\n\n const safeScriptContent = element.innerHTML\n .replaceAll('import.meta.hot.accept(', 'import.meta.hot?.accept(')\n .replaceAll('import.meta.hot.prune(', 'import.meta.hot?.prune(');\n\n script.appendChild(document.createTextNode(safeScriptContent));\n document.head.appendChild(script);\n document.head.removeChild(script);\n });\n}\n\nfunction isAstroStyleUpdate(path: string): boolean {\n return /\\.astro\\?astro&type=style&index=\\d+&lang\\.(css|scss|sass|less|stylus)$/.test(path);\n}\n"],"mappings":";;;AAMA,IAAM,kBAAkB,oBAAI,IAA2B;AACvD,IAAM,sCAAsC;
|
|
1
|
+
{"version":3,"sources":["../../src/renderer/renderer-dev.ts"],"sourcesContent":["import type {\n RenderComponentInput,\n RenderPromise,\n RenderResponseMessage\n} from '@storybook-astro/renderer/types';\n\nconst pendingMessages = new Map<string, RenderPromise>();\nconst ASTRO_SERVER_UNAVAILABLE_ERROR_NAME = 'AstroRenderServerUnavailableError';\n\nexport const isStaticMode = false;\n\nexport async function render(data: RenderComponentInput, timeoutMs = 5000) {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const id = crypto.randomUUID();\n\n const promise = new Promise<RenderResponseMessage['data']>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n pendingMessages.delete(id);\n\n const error = new Error(\n `Unable to reach Astro rendering server. No render response was received within ${timeoutMs}ms.`\n );\n\n error.name = ASTRO_SERVER_UNAVAILABLE_ERROR_NAME;\n\n reject(error);\n }, timeoutMs);\n\n pendingMessages.set(id, { resolve, reject, timeoutId });\n });\n\n import.meta.hot?.send('astro:render:request', {\n ...data,\n id\n });\n\n return promise;\n}\n\nexport function init() {\n import.meta.hot?.on('vite:afterUpdate', (payload) => {\n if (payload.updates.some((update) => isAstroStyleUpdate(update.path))) {\n applyStyles();\n }\n });\n\n import.meta.hot?.on('astro:render:response', (data: RenderResponseMessage['data']) => {\n if (!data.id || !pendingMessages.has(data.id)) {\n return;\n }\n\n const pendingMessage = pendingMessages.get(data.id);\n\n if (!pendingMessage) {\n return;\n }\n\n clearTimeout(pendingMessage.timeoutId);\n pendingMessages.delete(data.id);\n pendingMessage.resolve(data);\n });\n}\n\nexport function applyStyles() {\n Array.from(document.querySelectorAll('style[data-vite-dev-id]'))\n .filter((element) => /__vite__updateStyle/.test(element.innerHTML))\n .forEach((element) => {\n const script = document.createElement('script');\n\n script.type = 'module';\n\n const safeScriptContent = element.innerHTML\n .replaceAll('import.meta.hot.accept(', 'import.meta.hot?.accept(')\n .replaceAll('import.meta.hot.prune(', 'import.meta.hot?.prune(');\n\n script.appendChild(document.createTextNode(safeScriptContent));\n document.head.appendChild(script);\n document.head.removeChild(script);\n });\n}\n\nfunction isAstroStyleUpdate(path: string): boolean {\n return /\\.astro\\?astro&type=style&index=\\d+&lang\\.(css|scss|sass|less|stylus)$/.test(path);\n}\n"],"mappings":";;;AAMA,IAAM,kBAAkB,oBAAI,IAA2B;AACvD,IAAM,sCAAsC;AAErC,IAAM,eAAe;AAE5B,eAAsB,OAAO,MAA4B,YAAY,KAAM;AAEzE,QAAM,KAAK,OAAO,WAAW;AAE7B,QAAM,UAAU,IAAI,QAAuC,CAAC,SAAS,WAAW;AAC9E,UAAM,YAAY,WAAW,MAAM;AACjC,sBAAgB,OAAO,EAAE;AAEzB,YAAM,QAAQ,IAAI;AAAA,QAChB,kFAAkF,SAAS;AAAA,MAC7F;AAEA,YAAM,OAAO;AAEb,aAAO,KAAK;AAAA,IACd,GAAG,SAAS;AAEZ,oBAAgB,IAAI,IAAI,EAAE,SAAS,QAAQ,UAAU,CAAC;AAAA,EACxD,CAAC;AAED,cAAY,KAAK,KAAK,wBAAwB;AAAA,IAC5C,GAAG;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEO,SAAS,OAAO;AACrB,cAAY,KAAK,GAAG,oBAAoB,CAAC,YAAY;AACnD,QAAI,QAAQ,QAAQ,KAAK,CAAC,WAAW,mBAAmB,OAAO,IAAI,CAAC,GAAG;AACrE,kBAAY;AAAA,IACd;AAAA,EACF,CAAC;AAED,cAAY,KAAK,GAAG,yBAAyB,CAAC,SAAwC;AACpF,QAAI,CAAC,KAAK,MAAM,CAAC,gBAAgB,IAAI,KAAK,EAAE,GAAG;AAC7C;AAAA,IACF;AAEA,UAAM,iBAAiB,gBAAgB,IAAI,KAAK,EAAE;AAElD,QAAI,CAAC,gBAAgB;AACnB;AAAA,IACF;AAEA,iBAAa,eAAe,SAAS;AACrC,oBAAgB,OAAO,KAAK,EAAE;AAC9B,mBAAe,QAAQ,IAAI;AAAA,EAC7B,CAAC;AACH;AAEO,SAAS,cAAc;AAC5B,QAAM,KAAK,SAAS,iBAAiB,yBAAyB,CAAC,EAC5D,OAAO,CAAC,YAAY,sBAAsB,KAAK,QAAQ,SAAS,CAAC,EACjE,QAAQ,CAAC,YAAY;AACpB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAE9C,WAAO,OAAO;AAEd,UAAM,oBAAoB,QAAQ,UAC/B,WAAW,2BAA2B,0BAA0B,EAChE,WAAW,0BAA0B,yBAAyB;AAEjE,WAAO,YAAY,SAAS,eAAe,iBAAiB,CAAC;AAC7D,aAAS,KAAK,YAAY,MAAM;AAChC,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AACL;AAEA,SAAS,mBAAmB,MAAuB;AACjD,SAAO,yEAAyE,KAAK,IAAI;AAC3F;","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "../chunk-G3PMV62Z.js";
|
|
2
2
|
|
|
3
3
|
// src/renderer/renderer-server.ts
|
|
4
|
+
var isStaticMode = false;
|
|
4
5
|
var ASTRO_SERVER_UNAVAILABLE_ERROR_NAME = "AstroRenderServerUnavailableError";
|
|
5
6
|
function createServerRenderer(defaults = {}) {
|
|
6
7
|
return {
|
|
@@ -87,6 +88,7 @@ function createServerUnavailableError(serverUrl, reason) {
|
|
|
87
88
|
return error;
|
|
88
89
|
}
|
|
89
90
|
export {
|
|
90
|
-
createServerRenderer
|
|
91
|
+
createServerRenderer,
|
|
92
|
+
isStaticMode
|
|
91
93
|
};
|
|
92
94
|
//# sourceMappingURL=renderer-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/renderer/renderer-server.ts"],"sourcesContent":["import type { RenderComponentInput, RenderResponseMessage } from '@storybook-astro/renderer/types';\n\ntype StorybookImportMetaEnv = ImportMeta & {\n env?: Record<string, string | undefined>;\n};\n\ntype StorybookGlobalEnv = typeof globalThis & {\n STORYBOOK_ASTRO_SERVER_URL?: string;\n STORYBOOK_ASTRO_SERVER_TOKEN?: string;\n STORYBOOK_ASTRO_SERVER_AUTH_HEADER?: string;\n};\n\ntype ServerRendererDefaults = {\n serverUrl?: string;\n authToken?: string;\n authHeader?: string;\n};\n\nconst ASTRO_SERVER_UNAVAILABLE_ERROR_NAME = 'AstroRenderServerUnavailableError';\n\nexport function createServerRenderer(defaults: ServerRendererDefaults = {}) {\n return {\n render(data: RenderComponentInput, timeoutMs = 5000) {\n return renderWithHttp(data, timeoutMs, defaults);\n },\n init() {\n return;\n },\n applyStyles() {\n return;\n }\n };\n}\n\nasync function renderWithHttp(\n data: RenderComponentInput,\n timeoutMs: number,\n defaults: ServerRendererDefaults\n) {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const id = crypto.randomUUID();\n const serverUrl = resolveServerUrl(defaults);\n const authToken = resolveAuthToken(defaults);\n const authHeader = resolveAuthHeader(defaults);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const headers: Record<string, string> = {\n 'content-type': 'application/json'\n };\n\n if (authToken) {\n headers[authHeader] =\n authHeader.toLowerCase() === 'authorization' && !authToken.startsWith('Bearer ')\n ? `Bearer ${authToken}`\n : authToken;\n }\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const response = await fetch(`${serverUrl}/render`, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n if (response.status === 401 || response.status === 403) {\n throw new Error(\n `Astro rendering server rejected the request with ${response.status}. ` +\n `Check STORYBOOK_ASTRO_SERVER_TOKEN and auth header configuration.`\n );\n }\n\n if (!response.ok) {\n throw new Error(`Server responded with ${response.status}: ${response.statusText}`);\n }\n\n const html = await response.text();\n\n return {\n id,\n html\n } satisfies RenderResponseMessage['data'];\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw createServerUnavailableError(\n serverUrl,\n `Request timed out after ${timeoutMs}ms while waiting for a render response.`\n );\n }\n\n if (error instanceof TypeError) {\n throw createServerUnavailableError(\n serverUrl,\n 'The Astro rendering server is not reachable over HTTP.'\n );\n }\n\n throw error;\n }\n}\n\nfunction resolveServerUrl(defaults: ServerRendererDefaults) {\n const envServerUrl = (import.meta as StorybookImportMetaEnv).env?.STORYBOOK_ASTRO_SERVER_URL;\n const globalServerUrl = (globalThis as StorybookGlobalEnv).STORYBOOK_ASTRO_SERVER_URL;\n\n return defaults.serverUrl || envServerUrl || globalServerUrl || 'http://localhost:3000';\n}\n\nfunction resolveAuthToken(defaults: ServerRendererDefaults) {\n const envAuthToken = (import.meta as StorybookImportMetaEnv).env?.STORYBOOK_ASTRO_SERVER_TOKEN;\n const globalAuthToken = (globalThis as StorybookGlobalEnv).STORYBOOK_ASTRO_SERVER_TOKEN;\n\n return defaults.authToken || envAuthToken || globalAuthToken;\n}\n\nfunction resolveAuthHeader(defaults: ServerRendererDefaults) {\n const envAuthHeader = (import.meta as StorybookImportMetaEnv).env?.STORYBOOK_ASTRO_SERVER_AUTH_HEADER;\n const globalAuthHeader = (globalThis as StorybookGlobalEnv).STORYBOOK_ASTRO_SERVER_AUTH_HEADER;\n\n return (defaults.authHeader || envAuthHeader || globalAuthHeader || 'authorization').toLowerCase();\n}\n\nfunction createServerUnavailableError(serverUrl: string, reason: string) {\n const error = new Error(`Unable to reach Astro rendering server at ${serverUrl}. ${reason}`);\n\n error.name = ASTRO_SERVER_UNAVAILABLE_ERROR_NAME;\n\n return error;\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../../src/renderer/renderer-server.ts"],"sourcesContent":["import type { RenderComponentInput, RenderResponseMessage } from '@storybook-astro/renderer/types';\n\nexport const isStaticMode = false;\n\ntype StorybookImportMetaEnv = ImportMeta & {\n env?: Record<string, string | undefined>;\n};\n\ntype StorybookGlobalEnv = typeof globalThis & {\n STORYBOOK_ASTRO_SERVER_URL?: string;\n STORYBOOK_ASTRO_SERVER_TOKEN?: string;\n STORYBOOK_ASTRO_SERVER_AUTH_HEADER?: string;\n};\n\ntype ServerRendererDefaults = {\n serverUrl?: string;\n authToken?: string;\n authHeader?: string;\n};\n\nconst ASTRO_SERVER_UNAVAILABLE_ERROR_NAME = 'AstroRenderServerUnavailableError';\n\nexport function createServerRenderer(defaults: ServerRendererDefaults = {}) {\n return {\n render(data: RenderComponentInput, timeoutMs = 5000) {\n return renderWithHttp(data, timeoutMs, defaults);\n },\n init() {\n return;\n },\n applyStyles() {\n return;\n }\n };\n}\n\nasync function renderWithHttp(\n data: RenderComponentInput,\n timeoutMs: number,\n defaults: ServerRendererDefaults\n) {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const id = crypto.randomUUID();\n const serverUrl = resolveServerUrl(defaults);\n const authToken = resolveAuthToken(defaults);\n const authHeader = resolveAuthHeader(defaults);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const headers: Record<string, string> = {\n 'content-type': 'application/json'\n };\n\n if (authToken) {\n headers[authHeader] =\n authHeader.toLowerCase() === 'authorization' && !authToken.startsWith('Bearer ')\n ? `Bearer ${authToken}`\n : authToken;\n }\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const response = await fetch(`${serverUrl}/render`, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal\n });\n\n clearTimeout(timeoutId);\n\n if (response.status === 401 || response.status === 403) {\n throw new Error(\n `Astro rendering server rejected the request with ${response.status}. ` +\n `Check STORYBOOK_ASTRO_SERVER_TOKEN and auth header configuration.`\n );\n }\n\n if (!response.ok) {\n throw new Error(`Server responded with ${response.status}: ${response.statusText}`);\n }\n\n const html = await response.text();\n\n return {\n id,\n html\n } satisfies RenderResponseMessage['data'];\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw createServerUnavailableError(\n serverUrl,\n `Request timed out after ${timeoutMs}ms while waiting for a render response.`\n );\n }\n\n if (error instanceof TypeError) {\n throw createServerUnavailableError(\n serverUrl,\n 'The Astro rendering server is not reachable over HTTP.'\n );\n }\n\n throw error;\n }\n}\n\nfunction resolveServerUrl(defaults: ServerRendererDefaults) {\n const envServerUrl = (import.meta as StorybookImportMetaEnv).env?.STORYBOOK_ASTRO_SERVER_URL;\n const globalServerUrl = (globalThis as StorybookGlobalEnv).STORYBOOK_ASTRO_SERVER_URL;\n\n return defaults.serverUrl || envServerUrl || globalServerUrl || 'http://localhost:3000';\n}\n\nfunction resolveAuthToken(defaults: ServerRendererDefaults) {\n const envAuthToken = (import.meta as StorybookImportMetaEnv).env?.STORYBOOK_ASTRO_SERVER_TOKEN;\n const globalAuthToken = (globalThis as StorybookGlobalEnv).STORYBOOK_ASTRO_SERVER_TOKEN;\n\n return defaults.authToken || envAuthToken || globalAuthToken;\n}\n\nfunction resolveAuthHeader(defaults: ServerRendererDefaults) {\n const envAuthHeader = (import.meta as StorybookImportMetaEnv).env?.STORYBOOK_ASTRO_SERVER_AUTH_HEADER;\n const globalAuthHeader = (globalThis as StorybookGlobalEnv).STORYBOOK_ASTRO_SERVER_AUTH_HEADER;\n\n return (defaults.authHeader || envAuthHeader || globalAuthHeader || 'authorization').toLowerCase();\n}\n\nfunction createServerUnavailableError(serverUrl: string, reason: string) {\n const error = new Error(`Unable to reach Astro rendering server at ${serverUrl}. ${reason}`);\n\n error.name = ASTRO_SERVER_UNAVAILABLE_ERROR_NAME;\n\n return error;\n}\n"],"mappings":";;;AAEO,IAAM,eAAe;AAkB5B,IAAM,sCAAsC;AAErC,SAAS,qBAAqB,WAAmC,CAAC,GAAG;AAC1E,SAAO;AAAA,IACL,OAAO,MAA4B,YAAY,KAAM;AACnD,aAAO,eAAe,MAAM,WAAW,QAAQ;AAAA,IACjD;AAAA,IACA,OAAO;AACL;AAAA,IACF;AAAA,IACA,cAAc;AACZ;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,eACb,MACA,WACA,UACA;AAEA,QAAM,KAAK,OAAO,WAAW;AAC7B,QAAM,YAAY,iBAAiB,QAAQ;AAC3C,QAAM,YAAY,iBAAiB,QAAQ;AAC3C,QAAM,aAAa,kBAAkB,QAAQ;AAC7C,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAEhE,MAAI;AACF,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,IAClB;AAEA,QAAI,WAAW;AACb,cAAQ,UAAU,IAChB,WAAW,YAAY,MAAM,mBAAmB,CAAC,UAAU,WAAW,SAAS,IAC3E,UAAU,SAAS,KACnB;AAAA,IACR;AAGA,UAAM,WAAW,MAAM,MAAM,GAAG,SAAS,WAAW;AAAA,MAClD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,iBAAa,SAAS;AAEtB,QAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,YAAM,IAAI;AAAA,QACR,oDAAoD,SAAS,MAAM;AAAA,MAErE;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,yBAAyB,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,IACpF;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,iBAAa,SAAS;AAEtB,QAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD,YAAM;AAAA,QACJ;AAAA,QACA,2BAA2B,SAAS;AAAA,MACtC;AAAA,IACF;AAEA,QAAI,iBAAiB,WAAW;AAC9B,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM;AAAA,EACR;AACF;AAEA,SAAS,iBAAiB,UAAkC;AAC1D,QAAM,eAAgB,YAAuC,KAAK;AAClE,QAAM,kBAAmB,WAAkC;AAE3D,SAAO,SAAS,aAAa,gBAAgB,mBAAmB;AAClE;AAEA,SAAS,iBAAiB,UAAkC;AAC1D,QAAM,eAAgB,YAAuC,KAAK;AAClE,QAAM,kBAAmB,WAAkC;AAE3D,SAAO,SAAS,aAAa,gBAAgB;AAC/C;AAEA,SAAS,kBAAkB,UAAkC;AAC3D,QAAM,gBAAiB,YAAuC,KAAK;AACnE,QAAM,mBAAoB,WAAkC;AAE5D,UAAQ,SAAS,cAAc,iBAAiB,oBAAoB,iBAAiB,YAAY;AACnG;AAEA,SAAS,6BAA6B,WAAmB,QAAgB;AACvE,QAAM,QAAQ,IAAI,MAAM,6CAA6C,SAAS,KAAK,MAAM,EAAE;AAE3F,QAAM,OAAO;AAEb,SAAO;AACT;","names":[]}
|
|
@@ -2,6 +2,7 @@ import "../chunk-G3PMV62Z.js";
|
|
|
2
2
|
|
|
3
3
|
// src/renderer/renderer-static.ts
|
|
4
4
|
var PRERENDERED_STORIES_FILE = "astro-prerendered-stories.json";
|
|
5
|
+
var isStaticMode = true;
|
|
5
6
|
var prerenderedStoriesPromise;
|
|
6
7
|
async function render(data) {
|
|
7
8
|
const id = crypto.randomUUID();
|
|
@@ -49,6 +50,7 @@ function resolvePrerenderedStoriesUrl() {
|
|
|
49
50
|
export {
|
|
50
51
|
applyStyles,
|
|
51
52
|
init,
|
|
53
|
+
isStaticMode,
|
|
52
54
|
render
|
|
53
55
|
};
|
|
54
56
|
//# sourceMappingURL=renderer-static.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/renderer/renderer-static.ts"],"sourcesContent":["import type { RenderComponentInput, RenderResponseMessage } from '@storybook-astro/renderer/types';\n\nconst PRERENDERED_STORIES_FILE = 'astro-prerendered-stories.json';\n\nlet prerenderedStoriesPromise: Promise<Record<string, string>> | undefined;\n\nexport async function render(data: RenderComponentInput) {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const id = crypto.randomUUID();\n const storyId = data.story?.id;\n\n if (!storyId) {\n throw new Error(\n 'Astro static renderer expected a story id, but none was provided in the render payload.'\n );\n }\n\n const prerenderedStories = await loadPrerenderedStories();\n const html = prerenderedStories[storyId];\n\n if (html === undefined) {\n throw new Error(\n `No prerendered HTML was found for story \"${storyId}\". Rebuild Storybook static output.`\n );\n }\n\n return {\n id,\n html\n } satisfies RenderResponseMessage['data'];\n}\n\nexport function init() {\n return;\n}\n\nexport function applyStyles() {\n return;\n}\n\nasync function loadPrerenderedStories() {\n if (!prerenderedStoriesPromise) {\n const jsonPath = resolvePrerenderedStoriesUrl();\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n prerenderedStoriesPromise = fetch(jsonPath).then(async (response) => {\n if (!response.ok) {\n throw new Error(\n `Failed to load ${PRERENDERED_STORIES_FILE}. Received ${response.status} ${response.statusText}.`\n );\n }\n\n return (await response.json()) as Record<string, string>;\n });\n }\n\n return prerenderedStoriesPromise;\n}\n\nfunction resolvePrerenderedStoriesUrl() {\n return new URL(PRERENDERED_STORIES_FILE, window.location.href).toString();\n}\n"],"mappings":";;;AAEA,IAAM,2BAA2B;
|
|
1
|
+
{"version":3,"sources":["../../src/renderer/renderer-static.ts"],"sourcesContent":["import type { RenderComponentInput, RenderResponseMessage } from '@storybook-astro/renderer/types';\n\nconst PRERENDERED_STORIES_FILE = 'astro-prerendered-stories.json';\n\nexport const isStaticMode = true;\n\nlet prerenderedStoriesPromise: Promise<Record<string, string>> | undefined;\n\nexport async function render(data: RenderComponentInput) {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const id = crypto.randomUUID();\n const storyId = data.story?.id;\n\n if (!storyId) {\n throw new Error(\n 'Astro static renderer expected a story id, but none was provided in the render payload.'\n );\n }\n\n const prerenderedStories = await loadPrerenderedStories();\n const html = prerenderedStories[storyId];\n\n if (html === undefined) {\n throw new Error(\n `No prerendered HTML was found for story \"${storyId}\". Rebuild Storybook static output.`\n );\n }\n\n return {\n id,\n html\n } satisfies RenderResponseMessage['data'];\n}\n\nexport function init() {\n return;\n}\n\nexport function applyStyles() {\n return;\n}\n\nasync function loadPrerenderedStories() {\n if (!prerenderedStoriesPromise) {\n const jsonPath = resolvePrerenderedStoriesUrl();\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n prerenderedStoriesPromise = fetch(jsonPath).then(async (response) => {\n if (!response.ok) {\n throw new Error(\n `Failed to load ${PRERENDERED_STORIES_FILE}. Received ${response.status} ${response.statusText}.`\n );\n }\n\n return (await response.json()) as Record<string, string>;\n });\n }\n\n return prerenderedStoriesPromise;\n}\n\nfunction resolvePrerenderedStoriesUrl() {\n return new URL(PRERENDERED_STORIES_FILE, window.location.href).toString();\n}\n"],"mappings":";;;AAEA,IAAM,2BAA2B;AAE1B,IAAM,eAAe;AAE5B,IAAI;AAEJ,eAAsB,OAAO,MAA4B;AAEvD,QAAM,KAAK,OAAO,WAAW;AAC7B,QAAM,UAAU,KAAK,OAAO;AAE5B,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,qBAAqB,MAAM,uBAAuB;AACxD,QAAM,OAAO,mBAAmB,OAAO;AAEvC,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI;AAAA,MACR,4CAA4C,OAAO;AAAA,IACrD;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,OAAO;AACrB;AACF;AAEO,SAAS,cAAc;AAC5B;AACF;AAEA,eAAe,yBAAyB;AACtC,MAAI,CAAC,2BAA2B;AAC9B,UAAM,WAAW,6BAA6B;AAG9C,gCAA4B,MAAM,QAAQ,EAAE,KAAK,OAAO,aAAa;AACnE,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI;AAAA,UACR,kBAAkB,wBAAwB,cAAc,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QAChG;AAAA,MACF;AAEA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,+BAA+B;AACtC,SAAO,IAAI,IAAI,0BAA0B,OAAO,SAAS,IAAI,EAAE,SAAS;AAC1E;","names":[]}
|
package/dist/testing.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
renderViaTestingRendererDaemon,
|
|
3
3
|
runWithWorkingDirectory
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XVVIGJV6.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveTestingIntegrationsForRoot
|
|
7
7
|
} from "./chunk-WUTCMEF5.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-KXAAX3GN.js";
|
|
13
13
|
import {
|
|
14
14
|
ssrLoadModuleWithFsFallback
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7UF6LK4Z.js";
|
|
16
16
|
import "./chunk-PUTCAN6X.js";
|
|
17
17
|
import "./chunk-7YBE4TTI.js";
|
|
18
18
|
import "./chunk-B5HHF6FC.js";
|
|
@@ -213,7 +213,7 @@ async function getAstroContainer() {
|
|
|
213
213
|
}
|
|
214
214
|
async function getAstroSsrViteServer(resolveFrom) {
|
|
215
215
|
if (!astroSsrViteServerPromises.has(resolveFrom)) {
|
|
216
|
-
const { createViteServer } = await import("./viteStorybookAstroMiddlewarePlugin-
|
|
216
|
+
const { createViteServer } = await import("./viteStorybookAstroMiddlewarePlugin-LUMKF7NG.js");
|
|
217
217
|
const integrations = getTestingIntegrations(resolveFrom);
|
|
218
218
|
astroSsrViteServerPromises.set(
|
|
219
219
|
resolveFrom,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createViteServer,
|
|
3
3
|
vitePluginStorybookAstroMiddleware
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7UF6LK4Z.js";
|
|
5
5
|
import "./chunk-PUTCAN6X.js";
|
|
6
6
|
import "./chunk-B5HHF6FC.js";
|
|
7
7
|
import "./chunk-G3PMV62Z.js";
|
|
@@ -9,4 +9,4 @@ export {
|
|
|
9
9
|
createViteServer,
|
|
10
10
|
vitePluginStorybookAstroMiddleware
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=viteStorybookAstroMiddlewarePlugin-
|
|
12
|
+
//# sourceMappingURL=viteStorybookAstroMiddlewarePlugin-LUMKF7NG.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TESTING_RENDERER_DAEMON_URL_ENV,
|
|
3
3
|
startTestingRendererDaemon
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-XVVIGJV6.js";
|
|
5
5
|
import "../chunk-WUTCMEF5.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-7UF6LK4Z.js";
|
|
7
7
|
import "../chunk-PUTCAN6X.js";
|
|
8
8
|
import "../chunk-7YBE4TTI.js";
|
|
9
9
|
import "../chunk-B5HHF6FC.js";
|
package/dist/vitest/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook-astro/framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0-canary.2",
|
|
4
4
|
"description": "Community-supported Storybook framework for Astro 5 & 6 components",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -51,6 +51,9 @@
|
|
|
51
51
|
"types": "./dist/preset.d.ts",
|
|
52
52
|
"import": "./dist/preset.js"
|
|
53
53
|
},
|
|
54
|
+
"./shim": {
|
|
55
|
+
"types": "./src/shim.d.ts"
|
|
56
|
+
},
|
|
54
57
|
"./package.json": "./package.json"
|
|
55
58
|
},
|
|
56
59
|
"scripts": {
|
|
@@ -142,7 +145,7 @@
|
|
|
142
145
|
}
|
|
143
146
|
},
|
|
144
147
|
"dependencies": {
|
|
145
|
-
"@storybook-astro/renderer": "1.
|
|
148
|
+
"@storybook-astro/renderer": "1.5.0-canary.2",
|
|
146
149
|
"hono": "^4.11.12",
|
|
147
150
|
"sanitize-html": "^2.17.0",
|
|
148
151
|
"tsconfck": "^3.1.6",
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
loadUserAstroFonts,
|
|
7
|
+
loadUserAstroIntegrations,
|
|
8
|
+
loadUserAstroVitePlugins
|
|
9
|
+
} from './loadUserAstroConfig.ts';
|
|
10
|
+
|
|
11
|
+
let tmpDir: string;
|
|
12
|
+
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
tmpDir = await mkdtemp(join(tmpdir(), 'storybook-astro-user-config-'));
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(async () => {
|
|
18
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
async function writeConfig(body: string) {
|
|
22
|
+
await writeFile(join(tmpDir, 'astro.config.mjs'), body);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('loadUserAstroFonts', () => {
|
|
26
|
+
test('returns the fonts array from astro.config.*', async () => {
|
|
27
|
+
await writeConfig(`
|
|
28
|
+
export default {
|
|
29
|
+
fonts: [
|
|
30
|
+
{
|
|
31
|
+
provider: { name: 'fake', resolveFont: () => undefined },
|
|
32
|
+
name: 'Inter',
|
|
33
|
+
cssVariable: '--font-inter'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
provider: { name: 'fake', resolveFont: () => undefined },
|
|
37
|
+
name: 'Roboto',
|
|
38
|
+
cssVariable: '--font-roboto'
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
`);
|
|
43
|
+
|
|
44
|
+
const fonts = await loadUserAstroFonts(tmpDir);
|
|
45
|
+
|
|
46
|
+
expect(fonts).toHaveLength(2);
|
|
47
|
+
expect(fonts.map((f) => f.cssVariable)).toEqual(['--font-inter', '--font-roboto']);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('returns [] when astro.config.* has no fonts', async () => {
|
|
51
|
+
await writeConfig(`export default { integrations: [] };`);
|
|
52
|
+
|
|
53
|
+
expect(await loadUserAstroFonts(tmpDir)).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('returns [] when no astro.config.* is present', async () => {
|
|
57
|
+
expect(await loadUserAstroFonts(tmpDir)).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('drops entries missing required font-family fields', async () => {
|
|
61
|
+
await writeConfig(`
|
|
62
|
+
export default {
|
|
63
|
+
fonts: [
|
|
64
|
+
{ provider: { name: 'fake', resolveFont: () => undefined }, name: 'Inter', cssVariable: '--font-inter' },
|
|
65
|
+
{ name: 'NoProvider', cssVariable: '--font-x' },
|
|
66
|
+
'not-an-object'
|
|
67
|
+
]
|
|
68
|
+
};
|
|
69
|
+
`);
|
|
70
|
+
|
|
71
|
+
const fonts = await loadUserAstroFonts(tmpDir);
|
|
72
|
+
|
|
73
|
+
expect(fonts).toHaveLength(1);
|
|
74
|
+
expect(fonts[0].cssVariable).toBe('--font-inter');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('loadUserAstroVitePlugins', () => {
|
|
79
|
+
test('returns plugins from vite.plugins', async () => {
|
|
80
|
+
await writeConfig(`
|
|
81
|
+
export default {
|
|
82
|
+
vite: {
|
|
83
|
+
plugins: [
|
|
84
|
+
{ name: 'tailwindcss', enforce: 'pre' },
|
|
85
|
+
{ name: 'unocss/vite' }
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
`);
|
|
90
|
+
|
|
91
|
+
const plugins = await loadUserAstroVitePlugins(tmpDir);
|
|
92
|
+
|
|
93
|
+
expect(plugins.map((p) => p.name)).toEqual(['tailwindcss', 'unocss/vite']);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('flattens nested plugin arrays', async () => {
|
|
97
|
+
await writeConfig(`
|
|
98
|
+
export default {
|
|
99
|
+
vite: {
|
|
100
|
+
plugins: [
|
|
101
|
+
[{ name: 'a' }, { name: 'b' }],
|
|
102
|
+
{ name: 'c' }
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
`);
|
|
107
|
+
|
|
108
|
+
const plugins = await loadUserAstroVitePlugins(tmpDir);
|
|
109
|
+
|
|
110
|
+
expect(plugins.map((p) => p.name)).toEqual(['a', 'b', 'c']);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('returns [] when vite.plugins is missing', async () => {
|
|
114
|
+
await writeConfig(`export default { vite: {} };`);
|
|
115
|
+
|
|
116
|
+
expect(await loadUserAstroVitePlugins(tmpDir)).toEqual([]);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('drops entries without a name', async () => {
|
|
120
|
+
await writeConfig(`
|
|
121
|
+
export default {
|
|
122
|
+
vite: {
|
|
123
|
+
plugins: [{ name: 'real' }, false, null, undefined, { foo: 'bar' }]
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
`);
|
|
127
|
+
|
|
128
|
+
const plugins = await loadUserAstroVitePlugins(tmpDir);
|
|
129
|
+
|
|
130
|
+
expect(plugins.map((p) => p.name)).toEqual(['real']);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe('loadUserAstroIntegrations (regression)', () => {
|
|
135
|
+
test('still picks up integrations after the refactor', async () => {
|
|
136
|
+
await writeConfig(`
|
|
137
|
+
export default {
|
|
138
|
+
integrations: [
|
|
139
|
+
{ name: 'astro-icon', hooks: {} },
|
|
140
|
+
{ name: 'unocss/astro', hooks: {} }
|
|
141
|
+
]
|
|
142
|
+
};
|
|
143
|
+
`);
|
|
144
|
+
|
|
145
|
+
const integrations = await loadUserAstroIntegrations(tmpDir);
|
|
146
|
+
|
|
147
|
+
expect(integrations.map((i) => i.name)).toEqual(['astro-icon', 'unocss/astro']);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { loadConfigFromFile } from 'vite';
|
|
1
|
+
import { loadConfigFromFile, type Plugin } from 'vite';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import type { AstroIntegration } from 'astro';
|
|
5
|
+
import type { StorybookFontFamily } from './vitePluginAstroFonts.ts';
|
|
5
6
|
|
|
6
7
|
const CONFIG_FILENAMES = [
|
|
7
8
|
'astro.config.ts',
|
|
@@ -10,18 +11,45 @@ const CONFIG_FILENAMES = [
|
|
|
10
11
|
'astro.config.cjs',
|
|
11
12
|
];
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
interface UserAstroConfigData {
|
|
15
|
+
integrations: AstroIntegration[];
|
|
16
|
+
fonts: StorybookFontFamily[];
|
|
17
|
+
vitePlugins: Plugin[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const EMPTY: UserAstroConfigData = {
|
|
21
|
+
integrations: [],
|
|
22
|
+
fonts: [],
|
|
23
|
+
vitePlugins: []
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Cache by resolveFrom — config rarely changes during a Storybook session and
|
|
27
|
+
// several call sites read the same data. Each entry stores the in-flight
|
|
28
|
+
// promise so concurrent callers share the same load.
|
|
29
|
+
const configCache = new Map<string, Promise<UserAstroConfigData>>();
|
|
30
|
+
|
|
31
|
+
async function loadUserAstroConfigData(resolveFrom: string): Promise<UserAstroConfigData> {
|
|
32
|
+
let cached = configCache.get(resolveFrom);
|
|
33
|
+
|
|
34
|
+
if (!cached) {
|
|
35
|
+
cached = readUserAstroConfig(resolveFrom);
|
|
36
|
+
configCache.set(resolveFrom, cached);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return cached;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function readUserAstroConfig(resolveFrom: string): Promise<UserAstroConfigData> {
|
|
43
|
+
// Vite's loadConfigFromFile resolves a relative configFile against
|
|
44
|
+
// process.cwd(), not the configRoot argument, so we always hand it an
|
|
45
|
+
// absolute path to make the lookup deterministic regardless of where
|
|
46
|
+
// Storybook is invoked from.
|
|
47
|
+
const configFile = CONFIG_FILENAMES
|
|
48
|
+
.map((name) => resolve(resolveFrom, name))
|
|
49
|
+
.find((path) => existsSync(path));
|
|
22
50
|
|
|
23
51
|
if (!configFile) {
|
|
24
|
-
return
|
|
52
|
+
return EMPTY;
|
|
25
53
|
}
|
|
26
54
|
|
|
27
55
|
try {
|
|
@@ -32,28 +60,101 @@ export async function loadUserAstroIntegrations(resolveFrom: string): Promise<As
|
|
|
32
60
|
);
|
|
33
61
|
|
|
34
62
|
if (!result?.config) {
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const config = result.config as { integrations?: unknown };
|
|
39
|
-
const raw = config.integrations;
|
|
40
|
-
|
|
41
|
-
if (!raw) {
|
|
42
|
-
return [];
|
|
63
|
+
return EMPTY;
|
|
43
64
|
}
|
|
44
65
|
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
const config = result.config as {
|
|
67
|
+
integrations?: unknown;
|
|
68
|
+
fonts?: unknown;
|
|
69
|
+
vite?: { plugins?: unknown };
|
|
70
|
+
};
|
|
47
71
|
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
|
|
72
|
+
return {
|
|
73
|
+
integrations: extractIntegrations(config.integrations),
|
|
74
|
+
fonts: extractFonts(config.fonts),
|
|
75
|
+
vitePlugins: extractVitePlugins(config.vite?.plugins)
|
|
76
|
+
};
|
|
51
77
|
} catch (err) {
|
|
52
78
|
console.warn(
|
|
53
|
-
'[storybook-astro] Could not load astro.config to discover integrations:',
|
|
79
|
+
'[storybook-astro] Could not load astro.config to discover integrations / fonts / vite plugins:',
|
|
54
80
|
err instanceof Error ? err.message : String(err)
|
|
55
81
|
);
|
|
56
82
|
|
|
83
|
+
return EMPTY;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function extractIntegrations(raw: unknown): AstroIntegration[] {
|
|
88
|
+
if (!raw) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Astro allows nested arrays from conditional spreads (e.g. ...whenX(() => mdx()))
|
|
93
|
+
const flat = (Array.isArray(raw) ? raw : [raw]).flat(Infinity);
|
|
94
|
+
|
|
95
|
+
return flat.filter(
|
|
96
|
+
(i): i is AstroIntegration =>
|
|
97
|
+
Boolean(i) && typeof i === 'object' && 'name' in i && 'hooks' in i
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function extractFonts(raw: unknown): StorybookFontFamily[] {
|
|
102
|
+
if (!Array.isArray(raw)) {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return raw.filter(
|
|
107
|
+
(f): f is StorybookFontFamily =>
|
|
108
|
+
Boolean(f) &&
|
|
109
|
+
typeof f === 'object' &&
|
|
110
|
+
typeof (f as { name?: unknown }).name === 'string' &&
|
|
111
|
+
typeof (f as { cssVariable?: unknown }).cssVariable === 'string' &&
|
|
112
|
+
typeof (f as { provider?: unknown }).provider === 'object'
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function extractVitePlugins(raw: unknown): Plugin[] {
|
|
117
|
+
if (!raw) {
|
|
57
118
|
return [];
|
|
58
119
|
}
|
|
120
|
+
|
|
121
|
+
// vite.plugins accepts Plugin | Plugin[] | (Plugin | false | null | undefined)[][] etc.
|
|
122
|
+
const flat = (Array.isArray(raw) ? raw : [raw]).flat(Infinity);
|
|
123
|
+
|
|
124
|
+
return flat.filter(
|
|
125
|
+
(p): p is Plugin =>
|
|
126
|
+
Boolean(p) && typeof p === 'object' && 'name' in p && typeof (p as Plugin).name === 'string'
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Loads integrations declared in the user's astro.config.* so that any Vite
|
|
132
|
+
* plugins they register (e.g. astro-icon's virtual:astro-icon resolver) are
|
|
133
|
+
* present in both the main Storybook Vite server and the internal Astro SSR
|
|
134
|
+
* server. Returns an empty array on any failure so the calling code can
|
|
135
|
+
* continue with only the framework-level integrations.
|
|
136
|
+
*/
|
|
137
|
+
export async function loadUserAstroIntegrations(resolveFrom: string): Promise<AstroIntegration[]> {
|
|
138
|
+
return (await loadUserAstroConfigData(resolveFrom)).integrations;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Loads the `fonts:` array from the user's astro.config.* so the Astro 6
|
|
143
|
+
* Font Provider API works in Storybook without duplicating the array into
|
|
144
|
+
* `framework.options.fonts`. Returns [] if the project has no fonts
|
|
145
|
+
* configured or the config can't be read.
|
|
146
|
+
*/
|
|
147
|
+
export async function loadUserAstroFonts(resolveFrom: string): Promise<StorybookFontFamily[]> {
|
|
148
|
+
return (await loadUserAstroConfigData(resolveFrom)).fonts;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Loads raw Vite plugins declared at `vite.plugins` in the user's
|
|
153
|
+
* astro.config.* (e.g. `@tailwindcss/vite`, `unocss/vite`). These are not
|
|
154
|
+
* registered through Astro's integration API so `loadUserAstroIntegrations`
|
|
155
|
+
* does not pick them up; this loader fills the gap so CSS frameworks added
|
|
156
|
+
* as raw Vite plugins work in Storybook without `viteFinal`.
|
|
157
|
+
*/
|
|
158
|
+
export async function loadUserAstroVitePlugins(resolveFrom: string): Promise<Plugin[]> {
|
|
159
|
+
return (await loadUserAstroConfigData(resolveFrom)).vitePlugins;
|
|
59
160
|
}
|
package/src/preset.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { vitePluginAstroVueFallback } from './vitePluginAstroVueFallback.ts';
|
|
|
11
11
|
import { vitePluginAstroToolbarFallback } from './vitePluginAstroToolbarFallback.ts';
|
|
12
12
|
import { resolveSanitizationOptions } from './lib/sanitization.ts';
|
|
13
13
|
import { mergeWithAstroConfig } from './vitePluginAstro.ts';
|
|
14
|
+
import { loadUserAstroFonts, loadUserAstroVitePlugins } from './loadUserAstroConfig.ts';
|
|
14
15
|
|
|
15
16
|
export const core = {
|
|
16
17
|
builder: '@storybook/builder-vite',
|
|
@@ -27,9 +28,26 @@ export const core = {
|
|
|
27
28
|
export const viteFinal: StorybookConfigVite['viteFinal'] = async (config, storybookOptions) => {
|
|
28
29
|
const { configType, presets, configDir } = storybookOptions;
|
|
29
30
|
const frameworkOptions = await presets.apply<FrameworkOptions>('frameworkOptions');
|
|
31
|
+
const resolveFrom = frameworkOptions.resolveFrom ?? dirname(configDir);
|
|
32
|
+
|
|
33
|
+
// Auto-load fonts from the user's astro.config.* when the framework option
|
|
34
|
+
// is omitted entirely. An explicit empty array means "I want no fonts" and
|
|
35
|
+
// is honored as-is.
|
|
36
|
+
const fonts =
|
|
37
|
+
frameworkOptions.fonts === undefined
|
|
38
|
+
? await loadUserAstroFonts(resolveFrom)
|
|
39
|
+
: frameworkOptions.fonts;
|
|
40
|
+
|
|
41
|
+
if (frameworkOptions.fonts === undefined && fonts.length > 0) {
|
|
42
|
+
console.warn(
|
|
43
|
+
`[storybook-astro] Auto-loaded ${fonts.length} font famil${fonts.length === 1 ? 'y' : 'ies'} from astro.config: ${fonts.map((f) => f.cssVariable).join(', ')}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
const options = {
|
|
31
48
|
...frameworkOptions,
|
|
32
|
-
resolveFrom
|
|
49
|
+
resolveFrom,
|
|
50
|
+
fonts
|
|
33
51
|
} satisfies FrameworkOptions;
|
|
34
52
|
|
|
35
53
|
if (!config.plugins) {
|
|
@@ -37,7 +55,7 @@ export const viteFinal: StorybookConfigVite['viteFinal'] = async (config, storyb
|
|
|
37
55
|
}
|
|
38
56
|
|
|
39
57
|
const integrations = options.integrations ?? [];
|
|
40
|
-
const renderMode = options.renderMode ?? '
|
|
58
|
+
const renderMode = options.renderMode ?? 'static';
|
|
41
59
|
const mode = configType === 'DEVELOPMENT' ? 'development' : 'production';
|
|
42
60
|
const command = configType === 'DEVELOPMENT' ? 'serve' : 'build';
|
|
43
61
|
|
|
@@ -110,6 +128,31 @@ export const viteFinal: StorybookConfigVite['viteFinal'] = async (config, storyb
|
|
|
110
128
|
command
|
|
111
129
|
);
|
|
112
130
|
|
|
131
|
+
// Auto-merge raw Vite plugins declared at `vite.plugins` in the user's
|
|
132
|
+
// astro.config.*. This covers CSS frameworks added as Vite plugins rather
|
|
133
|
+
// than Astro integrations (e.g. `@tailwindcss/vite`, `unocss/vite`) which
|
|
134
|
+
// the integration auto-loader does not pick up.
|
|
135
|
+
const userVitePlugins = await loadUserAstroVitePlugins(options.resolveFrom);
|
|
136
|
+
|
|
137
|
+
if (userVitePlugins.length > 0) {
|
|
138
|
+
const existingNames = new Set<string>();
|
|
139
|
+
|
|
140
|
+
for (const plugin of (finalConfig.plugins ?? []).flat(Infinity) as Array<{ name?: string }>) {
|
|
141
|
+
if (plugin && typeof plugin === 'object' && typeof plugin.name === 'string') {
|
|
142
|
+
existingNames.add(plugin.name);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const newPlugins = userVitePlugins.filter((plugin) => !existingNames.has(plugin.name));
|
|
147
|
+
|
|
148
|
+
if (newPlugins.length > 0) {
|
|
149
|
+
console.warn(
|
|
150
|
+
`[storybook-astro] Auto-loaded ${newPlugins.length} vite plugin${newPlugins.length === 1 ? '' : 's'} from astro.config: ${newPlugins.map((p) => p.name).join(', ')}`
|
|
151
|
+
);
|
|
152
|
+
finalConfig.plugins = [...(finalConfig.plugins ?? []), ...newPlugins];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
113
156
|
// Exclude Astro integration packages from dependency optimization because
|
|
114
157
|
// they import virtual modules that esbuild cannot resolve.
|
|
115
158
|
if (!finalConfig.optimizeDeps) {
|
|
@@ -7,6 +7,8 @@ import type {
|
|
|
7
7
|
const pendingMessages = new Map<string, RenderPromise>();
|
|
8
8
|
const ASTRO_SERVER_UNAVAILABLE_ERROR_NAME = 'AstroRenderServerUnavailableError';
|
|
9
9
|
|
|
10
|
+
export const isStaticMode = false;
|
|
11
|
+
|
|
10
12
|
export async function render(data: RenderComponentInput, timeoutMs = 5000) {
|
|
11
13
|
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
12
14
|
const id = crypto.randomUUID();
|
|
@@ -2,6 +2,8 @@ import type { RenderComponentInput, RenderResponseMessage } from '@storybook-ast
|
|
|
2
2
|
|
|
3
3
|
const PRERENDERED_STORIES_FILE = 'astro-prerendered-stories.json';
|
|
4
4
|
|
|
5
|
+
export const isStaticMode = true;
|
|
6
|
+
|
|
5
7
|
let prerenderedStoriesPromise: Promise<Record<string, string>> | undefined;
|
|
6
8
|
|
|
7
9
|
export async function render(data: RenderComponentInput) {
|
package/src/shim.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Ambient type declarations for *.astro file imports.
|
|
2
|
+
//
|
|
3
|
+
// Without the Astro language server, TypeScript (and ESLint's type-checker)
|
|
4
|
+
// cannot resolve `.astro` modules, so `import Foo from './Foo.astro'` is
|
|
5
|
+
// treated as an error-typed value and fires
|
|
6
|
+
// @typescript-eslint/no-unsafe-assignment on `component: Foo`.
|
|
7
|
+
//
|
|
8
|
+
// To opt in, add this to your project's src/env.d.ts:
|
|
9
|
+
//
|
|
10
|
+
// /// <reference types="@storybook-astro/framework/shim" />
|
|
11
|
+
|
|
12
|
+
declare module '*.astro' {
|
|
13
|
+
type AstroComponentFactory = {
|
|
14
|
+
(result: unknown, props: unknown, slots: unknown): unknown | Promise<unknown>;
|
|
15
|
+
isAstroComponentFactory?: boolean;
|
|
16
|
+
moduleId?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
const Component: AstroComponentFactory;
|
|
19
|
+
|
|
20
|
+
export default Component;
|
|
21
|
+
}
|
package/src/virtual.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ declare module 'virtual:storybook-astro-renderer' {
|
|
|
20
20
|
): Promise<RenderResponseMessage['data']>;
|
|
21
21
|
export function init(): void;
|
|
22
22
|
export function applyStyles(): void;
|
|
23
|
+
export const isStaticMode: boolean;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
declare module 'virtual:storybook-astro/sanitize-config' {
|