@storybook-astro/framework 1.3.0 → 1.4.0-canary.1
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-2EABPTOY.js → chunk-AIEYHH2G.js} +2 -2
- package/dist/{chunk-AYYMNFI6.js → chunk-EU6E5SJE.js} +216 -33
- package/dist/chunk-EU6E5SJE.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/preset.d.ts +1 -1
- package/dist/preset.js +16 -8
- package/dist/preset.js.map +1 -1
- package/dist/testing.js +3 -3
- package/dist/{types-BCpJLSTo.d.ts → types--SvYP5Ri.d.ts} +55 -0
- package/dist/{viteStorybookAstroMiddlewarePlugin-UB6ZLJ4B.js → viteStorybookAstroMiddlewarePlugin-RPIBVJAV.js} +2 -2
- package/dist/vitest/global-setup.js +2 -2
- package/package.json +2 -2
- package/src/loadUserAstroConfig.ts +59 -0
- package/src/productionRenderRuntime.ts +4 -1
- package/src/storySsrVite.ts +4 -2
- package/src/types.ts +9 -1
- package/src/vitePluginAstro.ts +10 -3
- package/src/vitePluginAstroBuildPrerender.ts +4 -1
- package/src/vitePluginAstroFonts.test.ts +153 -0
- package/src/vitePluginAstroFonts.ts +302 -0
- package/src/viteStorybookAstroMiddlewarePlugin.ts +18 -7
- package/dist/chunk-AYYMNFI6.js.map +0 -1
- package/src/vitePluginAstroFontsFallback.ts +0 -69
- /package/dist/{chunk-2EABPTOY.js.map → chunk-AIEYHH2G.js.map} +0 -0
- /package/dist/{viteStorybookAstroMiddlewarePlugin-UB6ZLJ4B.js.map → viteStorybookAstroMiddlewarePlugin-RPIBVJAV.js.map} +0 -0
|
@@ -14,6 +14,54 @@ type StoryRulesOptions = string | {
|
|
|
14
14
|
configFile: string;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
interface StorybookFontProvider {
|
|
18
|
+
name: string;
|
|
19
|
+
init?: (context: {
|
|
20
|
+
storage: FontStorage;
|
|
21
|
+
root: URL;
|
|
22
|
+
}) => Promise<void> | void;
|
|
23
|
+
resolveFont: (options: {
|
|
24
|
+
familyName: string;
|
|
25
|
+
weights: string[];
|
|
26
|
+
styles: string[];
|
|
27
|
+
subsets: string[];
|
|
28
|
+
formats: string[];
|
|
29
|
+
}) => Promise<{
|
|
30
|
+
fonts: FontFaceData[];
|
|
31
|
+
} | undefined> | {
|
|
32
|
+
fonts: FontFaceData[];
|
|
33
|
+
} | undefined;
|
|
34
|
+
}
|
|
35
|
+
interface FontFaceData {
|
|
36
|
+
src: Array<{
|
|
37
|
+
url?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
format?: string;
|
|
40
|
+
tech?: string;
|
|
41
|
+
}>;
|
|
42
|
+
weight?: string | number | [number, number];
|
|
43
|
+
style?: string;
|
|
44
|
+
display?: string;
|
|
45
|
+
unicodeRange?: string[];
|
|
46
|
+
featureSettings?: string;
|
|
47
|
+
variationSettings?: string;
|
|
48
|
+
}
|
|
49
|
+
interface StorybookFontFamily {
|
|
50
|
+
name: string;
|
|
51
|
+
cssVariable: string;
|
|
52
|
+
provider: StorybookFontProvider;
|
|
53
|
+
weights?: Array<string | number>;
|
|
54
|
+
styles?: string[];
|
|
55
|
+
subsets?: string[];
|
|
56
|
+
formats?: string[];
|
|
57
|
+
fallbacks?: string[];
|
|
58
|
+
display?: string;
|
|
59
|
+
}
|
|
60
|
+
interface FontStorage {
|
|
61
|
+
getItem: <T = unknown>(key: string, init?: () => Promise<T> | T) => Promise<T | null>;
|
|
62
|
+
setItem: (key: string, value: unknown) => Promise<void> | void;
|
|
63
|
+
}
|
|
64
|
+
|
|
17
65
|
type FrameworkName = CompatibleString<'@storybook-astro/framework'>;
|
|
18
66
|
|
|
19
67
|
type RenderMode = 'server' | 'static';
|
|
@@ -31,6 +79,13 @@ type BaseFrameworkOptions = {
|
|
|
31
79
|
integrations?: Integration[];
|
|
32
80
|
sanitization?: SanitizationOptions;
|
|
33
81
|
resolveFrom?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Astro font families to resolve and inject as @font-face CSS during story
|
|
84
|
+
* rendering. Pass the same array you have in your `astro.config.ts` under
|
|
85
|
+
* `fonts:`. Currently honored in development; static/server builds fall
|
|
86
|
+
* back to no-op stubs.
|
|
87
|
+
*/
|
|
88
|
+
fonts?: StorybookFontFamily[];
|
|
34
89
|
};
|
|
35
90
|
type ServerFrameworkOptions = BaseFrameworkOptions & {
|
|
36
91
|
renderMode?: 'server';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createViteServer,
|
|
3
3
|
vitePluginStorybookAstroMiddleware
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EU6E5SJE.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-RPIBVJAV.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-AIEYHH2G.js";
|
|
5
5
|
import "../chunk-WUTCMEF5.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-EU6E5SJE.js";
|
|
7
7
|
import "../chunk-PUTCAN6X.js";
|
|
8
8
|
import "../chunk-7YBE4TTI.js";
|
|
9
9
|
import "../chunk-B5HHF6FC.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook-astro/framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0-canary.1",
|
|
4
4
|
"description": "Community-supported Storybook framework for Astro 5 & 6 components",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
}
|
|
143
143
|
},
|
|
144
144
|
"dependencies": {
|
|
145
|
-
"@storybook-astro/renderer": "1.
|
|
145
|
+
"@storybook-astro/renderer": "1.4.0-canary.1",
|
|
146
146
|
"hono": "^4.11.12",
|
|
147
147
|
"sanitize-html": "^2.17.0",
|
|
148
148
|
"vite": "^6.4.1 || ^7.0.0 || ^8.0.0"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { loadConfigFromFile } from 'vite';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import type { AstroIntegration } from 'astro';
|
|
5
|
+
|
|
6
|
+
const CONFIG_FILENAMES = [
|
|
7
|
+
'astro.config.ts',
|
|
8
|
+
'astro.config.mjs',
|
|
9
|
+
'astro.config.js',
|
|
10
|
+
'astro.config.cjs',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Loads integrations declared in the user's astro.config.* so that any Vite
|
|
15
|
+
* plugins they register (e.g. astro-icon's virtual:astro-icon resolver) are
|
|
16
|
+
* present in both the main Storybook Vite server and the internal Astro SSR
|
|
17
|
+
* server. Returns an empty array on any failure so the calling code can
|
|
18
|
+
* continue with only the framework-level integrations.
|
|
19
|
+
*/
|
|
20
|
+
export async function loadUserAstroIntegrations(resolveFrom: string): Promise<AstroIntegration[]> {
|
|
21
|
+
const configFile = CONFIG_FILENAMES.find(name => existsSync(resolve(resolveFrom, name)));
|
|
22
|
+
|
|
23
|
+
if (!configFile) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const result = await loadConfigFromFile(
|
|
29
|
+
{ command: 'serve', mode: 'development' },
|
|
30
|
+
configFile,
|
|
31
|
+
resolveFrom
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
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 [];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Astro allows nested arrays from conditional spreads (e.g. ...whenX(() => mdx()))
|
|
46
|
+
const flat = (Array.isArray(raw) ? raw : [raw]).flat(Infinity);
|
|
47
|
+
|
|
48
|
+
return flat.filter(
|
|
49
|
+
(i): i is AstroIntegration => Boolean(i) && typeof i === 'object' && 'name' in i && 'hooks' in i
|
|
50
|
+
);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.warn(
|
|
53
|
+
'[storybook-astro] Could not load astro.config to discover integrations:',
|
|
54
|
+
err instanceof Error ? err.message : String(err)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -2,6 +2,7 @@ import { resolve } from 'node:path';
|
|
|
2
2
|
import { createAstroRenderHandler, type HandlerProps } from './astroRenderHandler.ts';
|
|
3
3
|
import type { Integration } from './integrations/index.ts';
|
|
4
4
|
import type { SanitizationOptions } from './lib/sanitization.ts';
|
|
5
|
+
import type { FrameworkOptions } from './types.ts';
|
|
5
6
|
import {
|
|
6
7
|
createClientModuleResolver,
|
|
7
8
|
createProductionAstroContainer,
|
|
@@ -34,6 +35,7 @@ type ProductionRenderRuntimeOptions = {
|
|
|
34
35
|
trackedSpecifiers: Set<string>;
|
|
35
36
|
resolveFrom: string;
|
|
36
37
|
resolveComponentId?: (id: string) => string;
|
|
38
|
+
fonts?: FrameworkOptions['fonts'];
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
/** Creates the shared SSR runtime used by both build-time prerendering and the standalone render server. */
|
|
@@ -43,7 +45,8 @@ export async function createProductionRenderRuntime(
|
|
|
43
45
|
const viteServer = await createStorySsrViteServer({
|
|
44
46
|
integrations: options.integrations,
|
|
45
47
|
trackedSpecifiers: options.trackedSpecifiers,
|
|
46
|
-
resolveFrom: options.resolveFrom
|
|
48
|
+
resolveFrom: options.resolveFrom,
|
|
49
|
+
fonts: options.fonts
|
|
47
50
|
});
|
|
48
51
|
|
|
49
52
|
try {
|
package/src/storySsrVite.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { importAstroConfig } from './importAstroConfig.ts';
|
|
|
6
6
|
import type { Integration } from './integrations/index.ts';
|
|
7
7
|
import { ssrLoadModuleWithFsFallback } from './lib/ssr-load-module-with-fs-fallback.ts';
|
|
8
8
|
import { resolveStoryModuleMock } from './module-mocks.ts';
|
|
9
|
-
import {
|
|
9
|
+
import type { FrameworkOptions } from './types.ts';
|
|
10
|
+
import { vitePluginAstroFonts } from './vitePluginAstroFonts.ts';
|
|
10
11
|
import { vitePluginAstroIntegrationOptsFallback } from './vitePluginAstroIntegrationOptsFallback.ts';
|
|
11
12
|
import { vitePluginAstroRoutesFallback } from './vitePluginAstroRoutesFallback.ts';
|
|
12
13
|
import { vitePluginAstroVueFallback } from './vitePluginAstroVueFallback.ts';
|
|
@@ -16,6 +17,7 @@ export async function createStorySsrViteServer(options: {
|
|
|
16
17
|
integrations: Integration[];
|
|
17
18
|
trackedSpecifiers: Set<string>;
|
|
18
19
|
resolveFrom: string;
|
|
20
|
+
fonts?: FrameworkOptions['fonts'];
|
|
19
21
|
}) {
|
|
20
22
|
const { getViteConfig, passthroughImageService } = await importAstroConfig(options.resolveFrom);
|
|
21
23
|
const astroConfig = await getViteConfig(
|
|
@@ -44,7 +46,7 @@ export async function createStorySsrViteServer(options: {
|
|
|
44
46
|
},
|
|
45
47
|
plugins: [
|
|
46
48
|
createProjectAstroResolutionPlugin(options.resolveFrom),
|
|
47
|
-
|
|
49
|
+
vitePluginAstroFonts({ fonts: options.fonts, root: options.resolveFrom }),
|
|
48
50
|
vitePluginAstroIntegrationOptsFallback(),
|
|
49
51
|
vitePluginAstroVueFallback(),
|
|
50
52
|
vitePluginAstroRoutesFallback(),
|
package/src/types.ts
CHANGED
|
@@ -3,10 +3,11 @@ import type { InlineConfig } from 'vite';
|
|
|
3
3
|
import type { Integration } from './integrations/index.ts';
|
|
4
4
|
import type { SanitizationOptions } from './lib/sanitization.ts';
|
|
5
5
|
import type { StoryRulesOptions } from './rules-options.ts';
|
|
6
|
+
import type { StorybookFontFamily } from './vitePluginAstroFonts.ts';
|
|
6
7
|
|
|
7
8
|
type FrameworkName = CompatibleString<'@storybook-astro/framework'>;
|
|
8
9
|
|
|
9
|
-
export type { Integration, SanitizationOptions, StoryRulesOptions };
|
|
10
|
+
export type { Integration, SanitizationOptions, StoryRulesOptions, StorybookFontFamily };
|
|
10
11
|
export type RenderMode = 'server' | 'static';
|
|
11
12
|
|
|
12
13
|
export type ServerBuildOptions = {
|
|
@@ -25,6 +26,13 @@ type BaseFrameworkOptions = {
|
|
|
25
26
|
integrations?: Integration[];
|
|
26
27
|
sanitization?: SanitizationOptions;
|
|
27
28
|
resolveFrom?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Astro font families to resolve and inject as @font-face CSS during story
|
|
31
|
+
* rendering. Pass the same array you have in your `astro.config.ts` under
|
|
32
|
+
* `fonts:`. Currently honored in development; static/server builds fall
|
|
33
|
+
* back to no-op stubs.
|
|
34
|
+
*/
|
|
35
|
+
fonts?: StorybookFontFamily[];
|
|
28
36
|
};
|
|
29
37
|
|
|
30
38
|
type ServerFrameworkOptions = BaseFrameworkOptions & {
|
package/src/vitePluginAstro.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mergeConfig, type InlineConfig } from 'vite';
|
|
2
2
|
import type { Integration } from './integrations/index.ts';
|
|
3
3
|
import { importAstroConfig } from './importAstroConfig.ts';
|
|
4
|
+
import { loadUserAstroIntegrations } from './loadUserAstroConfig.ts';
|
|
4
5
|
|
|
5
6
|
const ASTRO_PLUGINS_THAT_ARE_SUPPOSEDLY_NOT_NEEDED_IN_STORYBOOK = [
|
|
6
7
|
'@astro/plugin-actions',
|
|
@@ -38,13 +39,19 @@ export async function mergeWithAstroConfig(
|
|
|
38
39
|
const { getViteConfig } = await importAstroConfig(resolveFrom);
|
|
39
40
|
const safeIntegrations = integrations ?? [];
|
|
40
41
|
|
|
42
|
+
const frameworkIntegrations = await Promise.all(
|
|
43
|
+
safeIntegrations.map((integration) => integration.loadIntegration(resolveFrom))
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const userIntegrations = await loadUserAstroIntegrations(resolveFrom);
|
|
47
|
+
const frameworkNames = new Set(frameworkIntegrations.map(i => i.name));
|
|
48
|
+
const extraIntegrations = userIntegrations.filter(i => !frameworkNames.has(i.name));
|
|
49
|
+
|
|
41
50
|
const astroConfig = await getViteConfig(
|
|
42
51
|
{},
|
|
43
52
|
{
|
|
44
53
|
configFile: false,
|
|
45
|
-
integrations:
|
|
46
|
-
safeIntegrations.map((integration) => integration.loadIntegration(resolveFrom))
|
|
47
|
-
)
|
|
54
|
+
integrations: [...frameworkIntegrations, ...extraIntegrations]
|
|
48
55
|
}
|
|
49
56
|
)({
|
|
50
57
|
mode,
|
|
@@ -138,6 +138,7 @@ export function vitePluginAstroBuildPrerender(options: FrameworkOptions): Plugin
|
|
|
138
138
|
staticCssMap,
|
|
139
139
|
trackedSpecifiers,
|
|
140
140
|
resolveFrom,
|
|
141
|
+
fonts: options.fonts,
|
|
141
142
|
bundle
|
|
142
143
|
});
|
|
143
144
|
|
|
@@ -162,6 +163,7 @@ async function prerenderAstroStories(options: {
|
|
|
162
163
|
staticCssMap: StaticCssMap;
|
|
163
164
|
trackedSpecifiers: Set<string>;
|
|
164
165
|
resolveFrom: string;
|
|
166
|
+
fonts?: FrameworkOptions['fonts'];
|
|
165
167
|
bundle: Rollup.OutputBundle;
|
|
166
168
|
}) {
|
|
167
169
|
const runtime = await createProductionRenderRuntime({
|
|
@@ -170,7 +172,8 @@ async function prerenderAstroStories(options: {
|
|
|
170
172
|
storyRulesConfigFilePath: options.storyRulesConfigFilePath,
|
|
171
173
|
staticModuleMap: options.staticModuleMap,
|
|
172
174
|
trackedSpecifiers: options.trackedSpecifiers,
|
|
173
|
-
resolveFrom: options.resolveFrom
|
|
175
|
+
resolveFrom: options.resolveFrom,
|
|
176
|
+
fonts: options.fonts
|
|
174
177
|
});
|
|
175
178
|
const assetPathMap = buildAssetPathMap(options.bundle);
|
|
176
179
|
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
buildFamilyCss,
|
|
4
|
+
vitePluginAstroFonts,
|
|
5
|
+
type FontFaceData,
|
|
6
|
+
type StorybookFontFamily,
|
|
7
|
+
type StorybookFontProvider
|
|
8
|
+
} from './vitePluginAstroFonts.ts';
|
|
9
|
+
|
|
10
|
+
function makeProvider(faces: FontFaceData[]): StorybookFontProvider {
|
|
11
|
+
return {
|
|
12
|
+
name: 'test',
|
|
13
|
+
resolveFont: () => ({ fonts: faces })
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('buildFamilyCss', () => {
|
|
18
|
+
test('emits @font-face block with src url and font-display: swap by default', () => {
|
|
19
|
+
const family: StorybookFontFamily = {
|
|
20
|
+
name: 'Inter',
|
|
21
|
+
cssVariable: '--font-inter',
|
|
22
|
+
provider: makeProvider([])
|
|
23
|
+
};
|
|
24
|
+
const css = buildFamilyCss(family, [
|
|
25
|
+
{ src: [{ url: 'https://example.com/inter-400.woff2', format: 'woff2' }], weight: 400, style: 'normal' }
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
expect(css).toContain('@font-face');
|
|
29
|
+
expect(css).toContain('font-family: "Inter"');
|
|
30
|
+
expect(css).toContain('src: url("https://example.com/inter-400.woff2") format("woff2");');
|
|
31
|
+
expect(css).toContain('font-display: swap');
|
|
32
|
+
expect(css).toContain('font-weight: 400');
|
|
33
|
+
expect(css).toContain('font-style: normal');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('emits CSS variable rule binding cssVariable to family name and fallbacks', () => {
|
|
37
|
+
const family: StorybookFontFamily = {
|
|
38
|
+
name: 'Inter',
|
|
39
|
+
cssVariable: '--font-inter',
|
|
40
|
+
provider: makeProvider([]),
|
|
41
|
+
fallbacks: ['system-ui', 'sans-serif']
|
|
42
|
+
};
|
|
43
|
+
const css = buildFamilyCss(family, []);
|
|
44
|
+
|
|
45
|
+
expect(css).toContain(':root { --font-inter: "Inter", system-ui, sans-serif; }');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('handles local() source entries from local font providers', () => {
|
|
49
|
+
const family: StorybookFontFamily = {
|
|
50
|
+
name: 'CustomFont',
|
|
51
|
+
cssVariable: '--font-custom',
|
|
52
|
+
provider: makeProvider([])
|
|
53
|
+
};
|
|
54
|
+
const css = buildFamilyCss(family, [
|
|
55
|
+
{ src: [{ name: 'CustomFont Regular' }, { url: '/fonts/custom.woff2', format: 'woff2' }] }
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
expect(css).toContain('local("CustomFont Regular")');
|
|
59
|
+
expect(css).toContain('url("/fonts/custom.woff2") format("woff2")');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('emits variable-font weight range when provider returns a tuple', () => {
|
|
63
|
+
const family: StorybookFontFamily = {
|
|
64
|
+
name: 'Inter',
|
|
65
|
+
cssVariable: '--font-inter',
|
|
66
|
+
provider: makeProvider([])
|
|
67
|
+
};
|
|
68
|
+
const css = buildFamilyCss(family, [{ src: [{ url: '/x.woff2' }], weight: [100, 900] }]);
|
|
69
|
+
|
|
70
|
+
expect(css).toContain('font-weight: 100 900');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('vitePluginAstroFonts virtual modules', () => {
|
|
75
|
+
test('resolveId maps both virtual ids and the bare astro/assets/fonts/runtime import', async () => {
|
|
76
|
+
const plugin = vitePluginAstroFonts();
|
|
77
|
+
const resolveId = plugin.resolveId as (this: unknown, id: string) => string | undefined;
|
|
78
|
+
|
|
79
|
+
expect(resolveId.call({}, 'virtual:astro:assets/fonts/internal')).toBe(
|
|
80
|
+
'\0virtual:astro:assets/fonts/internal'
|
|
81
|
+
);
|
|
82
|
+
expect(resolveId.call({}, 'virtual:astro:assets/fonts/runtime')).toBe(
|
|
83
|
+
'\0virtual:astro:assets/fonts/runtime'
|
|
84
|
+
);
|
|
85
|
+
expect(resolveId.call({}, 'astro/assets/fonts/runtime')).toBe('\0storybook:astro-fonts-runtime');
|
|
86
|
+
expect(resolveId.call({}, 'astro/assets/fonts/runtime.js')).toBe('\0storybook:astro-fonts-runtime');
|
|
87
|
+
expect(resolveId.call({}, 'some-other-id')).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('internal virtual module exports a Map populated from the resolved families', async () => {
|
|
91
|
+
const family: StorybookFontFamily = {
|
|
92
|
+
name: 'Inter',
|
|
93
|
+
cssVariable: '--font-inter',
|
|
94
|
+
provider: makeProvider([
|
|
95
|
+
{ src: [{ url: 'https://example.com/inter.woff2', format: 'woff2' }], weight: 400 }
|
|
96
|
+
])
|
|
97
|
+
};
|
|
98
|
+
const plugin = vitePluginAstroFonts({ fonts: [family] });
|
|
99
|
+
|
|
100
|
+
const buildStart = plugin.buildStart as (this: unknown) => Promise<void>;
|
|
101
|
+
const load = plugin.load as (this: unknown, id: string) => Promise<{ code: string } | undefined>;
|
|
102
|
+
|
|
103
|
+
await buildStart.call({});
|
|
104
|
+
const result = await load.call({ load: async () => null }, '\0virtual:astro:assets/fonts/internal');
|
|
105
|
+
|
|
106
|
+
expect(result?.code).toContain('componentDataByCssVariable = new Map(');
|
|
107
|
+
expect(result?.code).toContain('--font-inter');
|
|
108
|
+
expect(result?.code).toContain('@font-face');
|
|
109
|
+
expect(result?.code).toContain('fontDataByCssVariable = ');
|
|
110
|
+
expect(result?.code).toContain('https://example.com/inter.woff2');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('emits empty maps when no families are configured (no-op behavior preserved)', async () => {
|
|
114
|
+
const plugin = vitePluginAstroFonts();
|
|
115
|
+
|
|
116
|
+
const buildStart = plugin.buildStart as (this: unknown) => Promise<void>;
|
|
117
|
+
const load = plugin.load as (this: unknown, id: string) => Promise<{ code: string } | undefined>;
|
|
118
|
+
|
|
119
|
+
await buildStart.call({});
|
|
120
|
+
const result = await load.call({ load: async () => null }, '\0virtual:astro:assets/fonts/internal');
|
|
121
|
+
|
|
122
|
+
expect(result?.code).toContain('componentDataByCssVariable = new Map([])');
|
|
123
|
+
expect(result?.code).toContain('fontDataByCssVariable = {}');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('continues processing remaining families if one provider throws', async () => {
|
|
127
|
+
const failing: StorybookFontFamily = {
|
|
128
|
+
name: 'Broken',
|
|
129
|
+
cssVariable: '--font-broken',
|
|
130
|
+
provider: {
|
|
131
|
+
name: 'broken',
|
|
132
|
+
resolveFont: () => {
|
|
133
|
+
throw new Error('boom');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const working: StorybookFontFamily = {
|
|
138
|
+
name: 'Inter',
|
|
139
|
+
cssVariable: '--font-inter',
|
|
140
|
+
provider: makeProvider([{ src: [{ url: '/inter.woff2' }], weight: 400 }])
|
|
141
|
+
};
|
|
142
|
+
const plugin = vitePluginAstroFonts({ fonts: [failing, working] });
|
|
143
|
+
|
|
144
|
+
const buildStart = plugin.buildStart as (this: unknown) => Promise<void>;
|
|
145
|
+
const load = plugin.load as (this: unknown, id: string) => Promise<{ code: string } | undefined>;
|
|
146
|
+
|
|
147
|
+
await buildStart.call({});
|
|
148
|
+
const result = await load.call({ load: async () => null }, '\0virtual:astro:assets/fonts/internal');
|
|
149
|
+
|
|
150
|
+
expect(result?.code).toContain('--font-inter');
|
|
151
|
+
expect(result?.code).not.toContain('--font-broken');
|
|
152
|
+
});
|
|
153
|
+
});
|