astro 5.6.2 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.d.ts +3 -0
- package/components/Font.astro +32 -0
- package/dist/actions/plugins.js +2 -2
- package/dist/assets/fonts/config.d.ts +378 -0
- package/dist/assets/fonts/config.js +157 -0
- package/dist/assets/fonts/constants.d.ts +15 -0
- package/dist/assets/fonts/constants.js +41 -0
- package/dist/assets/fonts/load.d.ts +20 -0
- package/dist/assets/fonts/load.js +133 -0
- package/dist/assets/fonts/metrics.d.ts +10 -0
- package/dist/assets/fonts/metrics.js +84 -0
- package/dist/assets/fonts/providers/entrypoints/adobe.d.ts +2 -0
- package/dist/assets/fonts/providers/entrypoints/adobe.js +5 -0
- package/dist/assets/fonts/providers/entrypoints/bunny.d.ts +1 -0
- package/dist/assets/fonts/providers/entrypoints/bunny.js +5 -0
- package/dist/assets/fonts/providers/entrypoints/fontshare.d.ts +1 -0
- package/dist/assets/fonts/providers/entrypoints/fontshare.js +5 -0
- package/dist/assets/fonts/providers/entrypoints/fontsource.d.ts +1 -0
- package/dist/assets/fonts/providers/entrypoints/fontsource.js +5 -0
- package/dist/assets/fonts/providers/entrypoints/google.d.ts +2 -0
- package/dist/assets/fonts/providers/entrypoints/google.js +5 -0
- package/dist/assets/fonts/providers/index.d.ts +48 -0
- package/dist/assets/fonts/providers/index.js +40 -0
- package/dist/assets/fonts/providers/local.d.ts +10 -0
- package/dist/assets/fonts/providers/local.js +30 -0
- package/dist/assets/fonts/providers/utils.d.ts +9 -0
- package/dist/assets/fonts/providers/utils.js +37 -0
- package/dist/assets/fonts/sync.d.ts +2 -0
- package/dist/assets/fonts/sync.js +17 -0
- package/dist/assets/fonts/types.d.ts +45 -0
- package/dist/assets/fonts/types.js +0 -0
- package/dist/assets/fonts/utils.d.ts +95 -0
- package/dist/assets/fonts/utils.js +215 -0
- package/dist/assets/fonts/vite-plugin-fonts.d.ts +10 -0
- package/dist/assets/fonts/vite-plugin-fonts.js +217 -0
- package/dist/assets/utils/node/emitAsset.d.ts +4 -2
- package/dist/assets/utils/node/emitAsset.js +1 -1
- package/dist/assets/utils/vendor/image-size/types/index.d.ts +2 -2
- package/dist/assets/vite-plugin-assets.d.ts +8 -3
- package/dist/assets/vite-plugin-assets.js +7 -7
- package/dist/config/entrypoint.d.ts +2 -0
- package/dist/config/entrypoint.js +3 -0
- package/dist/config/index.d.ts +2 -1
- package/dist/content/content-layer.js +5 -4
- package/dist/content/runtime-assets.js +1 -0
- package/dist/content/vite-plugin-content-imports.js +4 -2
- package/dist/core/build/generate.js +2 -2
- package/dist/core/build/pipeline.js +2 -2
- package/dist/core/build/static-build.js +2 -2
- package/dist/core/config/schemas/base.d.ts +436 -39
- package/dist/core/config/schemas/base.js +3 -7
- package/dist/core/config/schemas/refined.js +12 -0
- package/dist/core/config/schemas/relative.d.ts +567 -63
- package/dist/core/config/schemas/relative.js +1 -2
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +2 -2
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/errors-data.d.ts +82 -26
- package/dist/core/errors/errors-data.js +45 -16
- package/dist/core/logger/core.d.ts +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/middleware/vite-plugin.js +2 -2
- package/dist/core/render-context.js +38 -5
- package/dist/core/routing/rewrite.js +14 -5
- package/dist/core/session.d.ts +2 -4
- package/dist/core/session.js +4 -29
- package/dist/core/sync/index.js +2 -0
- package/dist/integrations/hooks.js +2 -3
- package/dist/manifest/virtual-module.d.ts +1 -5
- package/dist/manifest/virtual-module.js +1 -18
- package/dist/prerender/utils.d.ts +5 -1
- package/dist/prerender/utils.js +8 -8
- package/dist/runtime/client/dev-toolbar/apps/audit/annotations.d.ts +6 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/annotations.js +27 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/index.js +10 -4
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-ui.js +2 -2
- package/dist/types/public/config.d.ts +155 -98
- package/dist/vite-plugin-astro-server/plugin.js +1 -1
- package/package.json +6 -2
- package/types/fonts.d.ts +4 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Storage } from 'unstorage';
|
|
2
|
+
import type { generateFallbackFontFace } from './metrics.js';
|
|
3
|
+
import type { PreloadData, ResolvedFontFamily } from './types.js';
|
|
4
|
+
import { type GetMetricsForFamily } from './utils.js';
|
|
5
|
+
interface Options {
|
|
6
|
+
base: string;
|
|
7
|
+
families: Array<ResolvedFontFamily>;
|
|
8
|
+
storage: Storage;
|
|
9
|
+
hashToUrlMap: Map<string, string>;
|
|
10
|
+
resolvedMap: Map<string, {
|
|
11
|
+
preloadData: PreloadData;
|
|
12
|
+
css: string;
|
|
13
|
+
}>;
|
|
14
|
+
hashString: (value: string) => string;
|
|
15
|
+
log: (message: string) => void;
|
|
16
|
+
generateFallbackFontFace: typeof generateFallbackFontFace;
|
|
17
|
+
getMetricsForFamily: GetMetricsForFamily;
|
|
18
|
+
}
|
|
19
|
+
export declare function loadFonts({ base, families, storage, hashToUrlMap, resolvedMap, hashString, generateFallbackFontFace, getMetricsForFamily, log, }: Options): Promise<void>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import * as unifont from "unifont";
|
|
3
|
+
import { AstroError, AstroErrorData } from "../../core/errors/index.js";
|
|
4
|
+
import { DEFAULTS, LOCAL_PROVIDER_NAME } from "./constants.js";
|
|
5
|
+
import { resolveLocalFont } from "./providers/local.js";
|
|
6
|
+
import {
|
|
7
|
+
familiesToUnifontProviders,
|
|
8
|
+
generateFallbacksCSS,
|
|
9
|
+
generateFontFace,
|
|
10
|
+
proxyURL
|
|
11
|
+
} from "./utils.js";
|
|
12
|
+
async function loadFonts({
|
|
13
|
+
base,
|
|
14
|
+
families,
|
|
15
|
+
storage,
|
|
16
|
+
hashToUrlMap,
|
|
17
|
+
resolvedMap,
|
|
18
|
+
hashString,
|
|
19
|
+
generateFallbackFontFace,
|
|
20
|
+
getMetricsForFamily,
|
|
21
|
+
log
|
|
22
|
+
}) {
|
|
23
|
+
const extractedProvidersResult = familiesToUnifontProviders({ families, hashString });
|
|
24
|
+
families = extractedProvidersResult.families;
|
|
25
|
+
const { resolveFont } = await unifont.createUnifont(extractedProvidersResult.providers, {
|
|
26
|
+
storage
|
|
27
|
+
});
|
|
28
|
+
for (const family of families) {
|
|
29
|
+
const preloadData = [];
|
|
30
|
+
let css = "";
|
|
31
|
+
let fallbackFontData = null;
|
|
32
|
+
const collect = ({ hash, type, value }) => {
|
|
33
|
+
const url = base + hash;
|
|
34
|
+
if (!hashToUrlMap.has(hash)) {
|
|
35
|
+
hashToUrlMap.set(hash, value);
|
|
36
|
+
preloadData.push({ url, type });
|
|
37
|
+
}
|
|
38
|
+
if (family.fallbacks && family.fallbacks.length > 0) {
|
|
39
|
+
fallbackFontData ??= {
|
|
40
|
+
hash,
|
|
41
|
+
url: value
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return url;
|
|
45
|
+
};
|
|
46
|
+
let fonts;
|
|
47
|
+
if (family.provider === LOCAL_PROVIDER_NAME) {
|
|
48
|
+
const result = resolveLocalFont({
|
|
49
|
+
family,
|
|
50
|
+
proxyURL: (value) => {
|
|
51
|
+
return proxyURL({
|
|
52
|
+
value,
|
|
53
|
+
// We hash based on the filepath and the contents, since the user could replace
|
|
54
|
+
// a given font file with completely different contents.
|
|
55
|
+
hashString: (v) => {
|
|
56
|
+
let content;
|
|
57
|
+
try {
|
|
58
|
+
content = readFileSync(value, "utf-8");
|
|
59
|
+
} catch (e) {
|
|
60
|
+
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: e });
|
|
61
|
+
}
|
|
62
|
+
return hashString(v + content);
|
|
63
|
+
},
|
|
64
|
+
collect
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
fonts = result.fonts;
|
|
69
|
+
} else {
|
|
70
|
+
const result = await resolveFont(
|
|
71
|
+
family.name,
|
|
72
|
+
// We do not merge the defaults, we only provide defaults as a fallback
|
|
73
|
+
{
|
|
74
|
+
weights: family.weights ?? DEFAULTS.weights,
|
|
75
|
+
styles: family.styles ?? DEFAULTS.styles,
|
|
76
|
+
subsets: family.subsets ?? DEFAULTS.subsets,
|
|
77
|
+
fallbacks: family.fallbacks ?? DEFAULTS.fallbacks
|
|
78
|
+
},
|
|
79
|
+
// By default, unifont goes through all providers. We use a different approach
|
|
80
|
+
// where we specify a provider per font.
|
|
81
|
+
// Name has been set while extracting unifont providers from families (inside familiesToUnifontProviders)
|
|
82
|
+
[family.provider.name]
|
|
83
|
+
);
|
|
84
|
+
fonts = result.fonts.map((font) => ({
|
|
85
|
+
...font,
|
|
86
|
+
src: font.src.map(
|
|
87
|
+
(source) => "name" in source ? source : {
|
|
88
|
+
...source,
|
|
89
|
+
originalURL: source.url,
|
|
90
|
+
url: proxyURL({
|
|
91
|
+
value: source.url,
|
|
92
|
+
// We only use the url for hashing since the service returns urls with a hash already
|
|
93
|
+
hashString,
|
|
94
|
+
collect
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
for (const data of fonts) {
|
|
101
|
+
css += generateFontFace(family.nameWithHash, {
|
|
102
|
+
src: data.src,
|
|
103
|
+
display: data.display ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.display,
|
|
104
|
+
unicodeRange: data.unicodeRange ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.unicodeRange,
|
|
105
|
+
weight: data.weight,
|
|
106
|
+
style: data.style,
|
|
107
|
+
stretch: data.stretch ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.stretch,
|
|
108
|
+
featureSettings: data.featureSettings ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.featureSettings,
|
|
109
|
+
variationSettings: data.variationSettings ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.variationSettings
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const fallbackData = await generateFallbacksCSS({
|
|
113
|
+
family,
|
|
114
|
+
font: fallbackFontData,
|
|
115
|
+
fallbacks: family.fallbacks ?? DEFAULTS.fallbacks,
|
|
116
|
+
metrics: family.optimizedFallbacks ?? DEFAULTS.optimizedFallbacks ? {
|
|
117
|
+
getMetricsForFamily,
|
|
118
|
+
generateFontFace: generateFallbackFontFace
|
|
119
|
+
} : null
|
|
120
|
+
});
|
|
121
|
+
const cssVarValues = [family.nameWithHash];
|
|
122
|
+
if (fallbackData) {
|
|
123
|
+
css += fallbackData.css;
|
|
124
|
+
cssVarValues.push(...fallbackData.fallbacks);
|
|
125
|
+
}
|
|
126
|
+
css += `:root { ${family.cssVariable}: ${cssVarValues.join(", ")}; }`;
|
|
127
|
+
resolvedMap.set(family.cssVariable, { preloadData, css });
|
|
128
|
+
}
|
|
129
|
+
log("Fonts initialized");
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
loadFonts
|
|
133
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Font } from '@capsizecss/unpack';
|
|
2
|
+
export type FontFaceMetrics = Pick<Font, 'ascent' | 'descent' | 'lineGap' | 'unitsPerEm' | 'xWidthAvg'>;
|
|
3
|
+
export declare function getMetricsForFamily(family: string): Promise<FontFaceMetrics | null>;
|
|
4
|
+
export declare function readMetrics(family: string, buffer: Buffer): Promise<FontFaceMetrics>;
|
|
5
|
+
export declare function generateFallbackFontFace(metrics: FontFaceMetrics, fallback: {
|
|
6
|
+
name: string;
|
|
7
|
+
font: string;
|
|
8
|
+
metrics?: FontFaceMetrics;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { fontFamilyToCamelCase } from "@capsizecss/metrics";
|
|
2
|
+
import { fromBuffer } from "@capsizecss/unpack";
|
|
3
|
+
const QUOTES_RE = /^["']|["']$/g;
|
|
4
|
+
const withoutQuotes = (str) => str.trim().replace(QUOTES_RE, "");
|
|
5
|
+
const metricCache = {};
|
|
6
|
+
function filterRequiredMetrics({
|
|
7
|
+
ascent,
|
|
8
|
+
descent,
|
|
9
|
+
lineGap,
|
|
10
|
+
unitsPerEm,
|
|
11
|
+
xWidthAvg
|
|
12
|
+
}) {
|
|
13
|
+
return {
|
|
14
|
+
ascent,
|
|
15
|
+
descent,
|
|
16
|
+
lineGap,
|
|
17
|
+
unitsPerEm,
|
|
18
|
+
xWidthAvg
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async function getMetricsForFamily(family) {
|
|
22
|
+
family = withoutQuotes(family);
|
|
23
|
+
if (family in metricCache) return metricCache[family];
|
|
24
|
+
try {
|
|
25
|
+
const name = fontFamilyToCamelCase(family);
|
|
26
|
+
const { entireMetricsCollection } = await import("@capsizecss/metrics/entireMetricsCollection");
|
|
27
|
+
const metrics = entireMetricsCollection[name];
|
|
28
|
+
if (!("descent" in metrics)) {
|
|
29
|
+
metricCache[family] = null;
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const filteredMetrics = filterRequiredMetrics(metrics);
|
|
33
|
+
metricCache[family] = filteredMetrics;
|
|
34
|
+
return filteredMetrics;
|
|
35
|
+
} catch {
|
|
36
|
+
metricCache[family] = null;
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function readMetrics(family, buffer) {
|
|
41
|
+
const metrics = await fromBuffer(buffer);
|
|
42
|
+
metricCache[family] = filterRequiredMetrics(metrics);
|
|
43
|
+
return metricCache[family];
|
|
44
|
+
}
|
|
45
|
+
function toPercentage(value, fractionDigits = 4) {
|
|
46
|
+
const percentage = value * 100;
|
|
47
|
+
return `${+percentage.toFixed(fractionDigits)}%`;
|
|
48
|
+
}
|
|
49
|
+
function toCSS(properties, indent = 2) {
|
|
50
|
+
return Object.entries(properties).map(([key, value]) => `${" ".repeat(indent)}${key}: ${value};`).join("\n");
|
|
51
|
+
}
|
|
52
|
+
function generateFallbackFontFace(metrics, fallback) {
|
|
53
|
+
const {
|
|
54
|
+
name: fallbackName,
|
|
55
|
+
font: fallbackFontName,
|
|
56
|
+
metrics: fallbackMetrics,
|
|
57
|
+
...properties
|
|
58
|
+
} = fallback;
|
|
59
|
+
const preferredFontXAvgRatio = metrics.xWidthAvg / metrics.unitsPerEm;
|
|
60
|
+
const fallbackFontXAvgRatio = fallbackMetrics ? fallbackMetrics.xWidthAvg / fallbackMetrics.unitsPerEm : 1;
|
|
61
|
+
const sizeAdjust = fallbackMetrics && preferredFontXAvgRatio && fallbackFontXAvgRatio ? preferredFontXAvgRatio / fallbackFontXAvgRatio : 1;
|
|
62
|
+
const adjustedEmSquare = metrics.unitsPerEm * sizeAdjust;
|
|
63
|
+
const ascentOverride = metrics.ascent / adjustedEmSquare;
|
|
64
|
+
const descentOverride = Math.abs(metrics.descent) / adjustedEmSquare;
|
|
65
|
+
const lineGapOverride = metrics.lineGap / adjustedEmSquare;
|
|
66
|
+
const declaration = {
|
|
67
|
+
"font-family": JSON.stringify(fallbackName),
|
|
68
|
+
src: `local(${JSON.stringify(fallbackFontName)})`,
|
|
69
|
+
"size-adjust": toPercentage(sizeAdjust),
|
|
70
|
+
"ascent-override": toPercentage(ascentOverride),
|
|
71
|
+
"descent-override": toPercentage(descentOverride),
|
|
72
|
+
"line-gap-override": toPercentage(lineGapOverride),
|
|
73
|
+
...properties
|
|
74
|
+
};
|
|
75
|
+
return `@font-face {
|
|
76
|
+
${toCSS(declaration)}
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
generateFallbackFontFace,
|
|
82
|
+
getMetricsForFamily,
|
|
83
|
+
readMetrics
|
|
84
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const provider: () => import("unifont").Provider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const provider: () => import("unifont").Provider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const provider: () => import("unifont").Provider;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { providers } from 'unifont';
|
|
2
|
+
import type { AstroFontProvider } from '../types.js';
|
|
3
|
+
/** [Adobe](https://fonts.adobe.com/) */
|
|
4
|
+
declare function adobe(config: Parameters<typeof providers.adobe>[0]): {
|
|
5
|
+
entrypoint: string | URL;
|
|
6
|
+
config?: Record<string, any> | undefined;
|
|
7
|
+
};
|
|
8
|
+
/** [Bunny](https://fonts.bunny.net/) */
|
|
9
|
+
declare function bunny(): {
|
|
10
|
+
entrypoint: string | URL;
|
|
11
|
+
config?: Record<string, any> | undefined;
|
|
12
|
+
};
|
|
13
|
+
/** [Fontshare](https://www.fontshare.com/) */
|
|
14
|
+
declare function fontshare(): {
|
|
15
|
+
entrypoint: string | URL;
|
|
16
|
+
config?: Record<string, any> | undefined;
|
|
17
|
+
};
|
|
18
|
+
/** [Fontsource](https://fontsource.org/) */
|
|
19
|
+
declare function fontsource(): {
|
|
20
|
+
entrypoint: string | URL;
|
|
21
|
+
config?: Record<string, any> | undefined;
|
|
22
|
+
};
|
|
23
|
+
/** [Google](https://fonts.google.com/) */
|
|
24
|
+
declare function google(): {
|
|
25
|
+
entrypoint: string | URL;
|
|
26
|
+
config?: Record<string, any> | undefined;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Astro re-exports most [unifont](https://github.com/unjs/unifont/) providers:
|
|
30
|
+
* - [Adobe](https://fonts.adobe.com/)
|
|
31
|
+
* - [Bunny](https://fonts.bunny.net/)
|
|
32
|
+
* - [Fontshare](https://www.fontshare.com/)
|
|
33
|
+
* - [Fontsource](https://fontsource.org/)
|
|
34
|
+
* - [Google](https://fonts.google.com/)
|
|
35
|
+
*/
|
|
36
|
+
export declare const fontProviders: {
|
|
37
|
+
adobe: typeof adobe;
|
|
38
|
+
bunny: typeof bunny;
|
|
39
|
+
fontshare: typeof fontshare;
|
|
40
|
+
fontsource: typeof fontsource;
|
|
41
|
+
google: typeof google;
|
|
42
|
+
};
|
|
43
|
+
/** A type helper for defining Astro font providers config objects */
|
|
44
|
+
export declare function defineAstroFontProvider(provider: AstroFontProvider): {
|
|
45
|
+
entrypoint: string | URL;
|
|
46
|
+
config?: Record<string, any> | undefined;
|
|
47
|
+
};
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function adobe(config) {
|
|
2
|
+
return defineAstroFontProvider({
|
|
3
|
+
entrypoint: "astro/assets/fonts/providers/adobe",
|
|
4
|
+
config
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
function bunny() {
|
|
8
|
+
return defineAstroFontProvider({
|
|
9
|
+
entrypoint: "astro/assets/fonts/providers/bunny"
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function fontshare() {
|
|
13
|
+
return defineAstroFontProvider({
|
|
14
|
+
entrypoint: "astro/assets/fonts/providers/fontshare"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function fontsource() {
|
|
18
|
+
return defineAstroFontProvider({
|
|
19
|
+
entrypoint: "astro/assets/fonts/providers/fontsource"
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function google() {
|
|
23
|
+
return defineAstroFontProvider({
|
|
24
|
+
entrypoint: "astro/assets/fonts/providers/google"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const fontProviders = {
|
|
28
|
+
adobe,
|
|
29
|
+
bunny,
|
|
30
|
+
fontshare,
|
|
31
|
+
fontsource,
|
|
32
|
+
google
|
|
33
|
+
};
|
|
34
|
+
function defineAstroFontProvider(provider) {
|
|
35
|
+
return provider;
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
defineAstroFontProvider,
|
|
39
|
+
fontProviders
|
|
40
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as unifont from 'unifont';
|
|
2
|
+
import type { ResolvedLocalFontFamily } from '../types.js';
|
|
3
|
+
type InitializedProvider = NonNullable<Awaited<ReturnType<unifont.Provider>>>;
|
|
4
|
+
type ResolveFontResult = NonNullable<Awaited<ReturnType<InitializedProvider['resolveFont']>>>;
|
|
5
|
+
interface Options {
|
|
6
|
+
family: ResolvedLocalFontFamily;
|
|
7
|
+
proxyURL: (value: string) => string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveLocalFont({ family, proxyURL }: Options): ResolveFontResult;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { extractFontType } from "../utils.js";
|
|
2
|
+
function resolveLocalFont({ family, proxyURL }) {
|
|
3
|
+
const fonts = [];
|
|
4
|
+
for (const variant of family.variants) {
|
|
5
|
+
const data = {
|
|
6
|
+
weight: variant.weight,
|
|
7
|
+
style: variant.style,
|
|
8
|
+
src: variant.src.map(({ url: originalURL, tech }) => {
|
|
9
|
+
return {
|
|
10
|
+
originalURL,
|
|
11
|
+
url: proxyURL(originalURL),
|
|
12
|
+
format: extractFontType(originalURL),
|
|
13
|
+
tech
|
|
14
|
+
};
|
|
15
|
+
})
|
|
16
|
+
};
|
|
17
|
+
if (variant.display) data.display = variant.display;
|
|
18
|
+
if (variant.unicodeRange) data.unicodeRange = variant.unicodeRange;
|
|
19
|
+
if (variant.stretch) data.stretch = variant.stretch;
|
|
20
|
+
if (variant.featureSettings) data.featureSettings = variant.featureSettings;
|
|
21
|
+
if (variant.variationSettings) data.variationSettings = variant.variationSettings;
|
|
22
|
+
fonts.push(data);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
fonts
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
resolveLocalFont
|
|
30
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AstroFontProvider, ResolvedFontProvider } from '../types.js';
|
|
2
|
+
export declare function validateMod(mod: any, entrypoint: string): Pick<ResolvedFontProvider, 'provider'>;
|
|
3
|
+
export type ResolveMod = (id: string) => Promise<any>;
|
|
4
|
+
export interface ResolveProviderOptions {
|
|
5
|
+
root: URL;
|
|
6
|
+
provider: AstroFontProvider;
|
|
7
|
+
resolveMod: ResolveMod;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveProvider({ root, provider: { entrypoint, config }, resolveMod, }: ResolveProviderOptions): Promise<ResolvedFontProvider>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AstroError, AstroErrorData } from "../../../core/errors/index.js";
|
|
2
|
+
import { resolveEntrypoint } from "../utils.js";
|
|
3
|
+
function validateMod(mod, entrypoint) {
|
|
4
|
+
try {
|
|
5
|
+
if (typeof mod !== "object" || mod === null) {
|
|
6
|
+
throw new Error(`Expected an object for the module, but received ${typeof mod}.`);
|
|
7
|
+
}
|
|
8
|
+
if (typeof mod.provider !== "function") {
|
|
9
|
+
throw new Error(`Invalid provider export in module, expected a function.`);
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
provider: mod.provider
|
|
13
|
+
};
|
|
14
|
+
} catch (cause) {
|
|
15
|
+
throw new AstroError(
|
|
16
|
+
{
|
|
17
|
+
...AstroErrorData.CannotLoadFontProvider,
|
|
18
|
+
message: AstroErrorData.CannotLoadFontProvider.message(entrypoint)
|
|
19
|
+
},
|
|
20
|
+
{ cause }
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function resolveProvider({
|
|
25
|
+
root,
|
|
26
|
+
provider: { entrypoint, config },
|
|
27
|
+
resolveMod
|
|
28
|
+
}) {
|
|
29
|
+
const id = resolveEntrypoint(root, entrypoint.toString()).href;
|
|
30
|
+
const mod = await resolveMod(id);
|
|
31
|
+
const { provider } = validateMod(mod, id);
|
|
32
|
+
return { config, provider };
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
resolveProvider,
|
|
36
|
+
validateMod
|
|
37
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FONTS_TYPES_FILE } from "./constants.js";
|
|
2
|
+
function syncFonts(settings) {
|
|
3
|
+
if (!settings.config.experimental.fonts) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
settings.injectedTypes.push({
|
|
7
|
+
filename: FONTS_TYPES_FILE,
|
|
8
|
+
content: `declare module 'astro:assets' {
|
|
9
|
+
/** @internal */
|
|
10
|
+
export type FontFamily = (${JSON.stringify(settings.config.experimental.fonts.map((family) => family.cssVariable))})[number];
|
|
11
|
+
}
|
|
12
|
+
`
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
syncFonts
|
|
17
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type * as unifont from 'unifont';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { fontProviderSchema, localFontFamilySchema, remoteFontFamilySchema } from './config.js';
|
|
4
|
+
import type { FONT_TYPES } from './constants.js';
|
|
5
|
+
export type AstroFontProvider = z.infer<typeof fontProviderSchema>;
|
|
6
|
+
export interface ResolvedFontProvider {
|
|
7
|
+
name?: string;
|
|
8
|
+
provider: (config?: Record<string, any>) => unifont.Provider;
|
|
9
|
+
config?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
export type LocalFontFamily = z.infer<typeof localFontFamilySchema>;
|
|
12
|
+
interface ResolvedFontFamilyAttributes {
|
|
13
|
+
nameWithHash: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ResolvedLocalFontFamily extends ResolvedFontFamilyAttributes, Omit<LocalFontFamily, 'variants'> {
|
|
16
|
+
variants: Array<Omit<LocalFontFamily['variants'][number], 'weight' | 'src'> & {
|
|
17
|
+
weight: string;
|
|
18
|
+
src: Array<{
|
|
19
|
+
url: string;
|
|
20
|
+
tech?: string;
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
type RemoteFontFamily = z.infer<typeof remoteFontFamilySchema>;
|
|
25
|
+
export interface ResolvedRemoteFontFamily extends ResolvedFontFamilyAttributes, Omit<z.output<typeof remoteFontFamilySchema>, 'provider' | 'weights'> {
|
|
26
|
+
provider: ResolvedFontProvider;
|
|
27
|
+
weights?: Array<string>;
|
|
28
|
+
}
|
|
29
|
+
export type FontFamily = LocalFontFamily | RemoteFontFamily;
|
|
30
|
+
export type ResolvedFontFamily = ResolvedLocalFontFamily | ResolvedRemoteFontFamily;
|
|
31
|
+
export type FontType = (typeof FONT_TYPES)[number];
|
|
32
|
+
/**
|
|
33
|
+
* Preload data is used for links generation inside the <Font /> component
|
|
34
|
+
*/
|
|
35
|
+
export type PreloadData = Array<{
|
|
36
|
+
/**
|
|
37
|
+
* Absolute link to a font file, eg. /_astro/fonts/abc.woff
|
|
38
|
+
*/
|
|
39
|
+
url: string;
|
|
40
|
+
/**
|
|
41
|
+
* A font type, eg. woff2, woff, ttf...
|
|
42
|
+
*/
|
|
43
|
+
type: FontType;
|
|
44
|
+
}>;
|
|
45
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type * as unifont from 'unifont';
|
|
2
|
+
import type { Storage } from 'unstorage';
|
|
3
|
+
import { DEFAULT_FALLBACKS } from './constants.js';
|
|
4
|
+
import type { FontFaceMetrics, generateFallbackFontFace } from './metrics.js';
|
|
5
|
+
import { type ResolveProviderOptions } from './providers/utils.js';
|
|
6
|
+
import type { FontFamily, FontType, ResolvedFontFamily } from './types.js';
|
|
7
|
+
export declare function generateFontFace(family: string, font: unifont.FontFaceData): string;
|
|
8
|
+
export declare function extractFontType(str: string): FontType;
|
|
9
|
+
export declare function isFontType(str: string): str is FontType;
|
|
10
|
+
export declare function cache(storage: Storage, key: string, cb: () => Promise<Buffer>): Promise<{
|
|
11
|
+
cached: boolean;
|
|
12
|
+
data: Buffer;
|
|
13
|
+
}>;
|
|
14
|
+
export interface ProxyURLOptions {
|
|
15
|
+
/**
|
|
16
|
+
* The original URL
|
|
17
|
+
*/
|
|
18
|
+
value: string;
|
|
19
|
+
/**
|
|
20
|
+
* Specifies how the hash is computed. Can be based on the value,
|
|
21
|
+
* a specific string for testing etc
|
|
22
|
+
*/
|
|
23
|
+
hashString: (value: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Use the hook to save the associated value and hash, and possibly
|
|
26
|
+
* transform it (eg. apply a base)
|
|
27
|
+
*/
|
|
28
|
+
collect: (data: {
|
|
29
|
+
hash: string;
|
|
30
|
+
type: FontType;
|
|
31
|
+
value: string;
|
|
32
|
+
}) => string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The fonts data we receive contains urls or file paths we do no control.
|
|
36
|
+
* However, we will emit font files ourselves so we store the original value
|
|
37
|
+
* and replace it with a url we control. For example with the value "https://foo.bar/file.woff2":
|
|
38
|
+
* - font type is woff2
|
|
39
|
+
* - hash will be "<hash>.woff2"
|
|
40
|
+
* - `collect` will save the association of the original url and the new hash for later use
|
|
41
|
+
* - the returned url will be `/_astro/fonts/<hash>.woff2`
|
|
42
|
+
*/
|
|
43
|
+
export declare function proxyURL({ value, hashString, collect }: ProxyURLOptions): string;
|
|
44
|
+
export declare function isGenericFontFamily(str: string): str is keyof typeof DEFAULT_FALLBACKS;
|
|
45
|
+
export type GetMetricsForFamilyFont = {
|
|
46
|
+
hash: string;
|
|
47
|
+
url: string;
|
|
48
|
+
} | null;
|
|
49
|
+
export type GetMetricsForFamily = (name: string,
|
|
50
|
+
/** A remote url or local filepath to a font file. Used if metrics can't be resolved purely from the family name */
|
|
51
|
+
font: GetMetricsForFamilyFont) => Promise<FontFaceMetrics | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Generates CSS for a given family fallbacks if possible.
|
|
54
|
+
*
|
|
55
|
+
* It works by trying to get metrics (using capsize) of the provided font family.
|
|
56
|
+
* If some can be computed, they will be applied to the eligible fallbacks to match
|
|
57
|
+
* the original font shape as close as possible.
|
|
58
|
+
*/
|
|
59
|
+
export declare function generateFallbacksCSS({ family, fallbacks: _fallbacks, font: fontData, metrics, }: {
|
|
60
|
+
family: Pick<ResolvedFontFamily, 'name' | 'nameWithHash'>;
|
|
61
|
+
/** The family fallbacks */
|
|
62
|
+
fallbacks: Array<string>;
|
|
63
|
+
font: GetMetricsForFamilyFont;
|
|
64
|
+
metrics: {
|
|
65
|
+
getMetricsForFamily: GetMetricsForFamily;
|
|
66
|
+
generateFontFace: typeof generateFallbackFontFace;
|
|
67
|
+
} | null;
|
|
68
|
+
}): Promise<null | {
|
|
69
|
+
css: string;
|
|
70
|
+
fallbacks: Array<string>;
|
|
71
|
+
}>;
|
|
72
|
+
/**
|
|
73
|
+
* Resolves the font family provider. If none is provided, it will infer the provider as
|
|
74
|
+
* one of the built-in providers and resolve it. The most important part is that if a
|
|
75
|
+
* provider is not provided but `src` is, then it's inferred as the local provider.
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveFontFamily({ family, generateNameWithHash, root, resolveMod, }: Omit<ResolveProviderOptions, 'provider'> & {
|
|
78
|
+
family: FontFamily;
|
|
79
|
+
generateNameWithHash: (family: FontFamily) => string;
|
|
80
|
+
}): Promise<ResolvedFontFamily>;
|
|
81
|
+
export declare function sortObjectByKey<T extends Record<string, any>>(unordered: T): T;
|
|
82
|
+
/**
|
|
83
|
+
* Extracts providers from families so they can be consumed by unifont.
|
|
84
|
+
* It deduplicates them based on their config and provider name:
|
|
85
|
+
* - If several families use the same provider (by value, not by reference), we only use one provider
|
|
86
|
+
* - If one provider is used with different settings for 2 families, we make sure there are kept as 2 providers
|
|
87
|
+
*/
|
|
88
|
+
export declare function familiesToUnifontProviders({ families, hashString, }: {
|
|
89
|
+
families: Array<ResolvedFontFamily>;
|
|
90
|
+
hashString: (value: string) => string;
|
|
91
|
+
}): {
|
|
92
|
+
families: Array<ResolvedFontFamily>;
|
|
93
|
+
providers: Array<unifont.Provider>;
|
|
94
|
+
};
|
|
95
|
+
export declare function resolveEntrypoint(root: URL, entrypoint: string): URL;
|