astro 5.7.6 → 5.7.8

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.
Files changed (64) hide show
  1. package/dist/assets/fonts/config.d.ts +3 -3
  2. package/dist/assets/fonts/config.js +2 -3
  3. package/dist/assets/fonts/constants.d.ts +3 -73
  4. package/dist/assets/fonts/constants.js +16 -68
  5. package/dist/assets/fonts/definitions.d.ts +73 -0
  6. package/dist/assets/fonts/definitions.js +0 -0
  7. package/dist/assets/fonts/implementations/css-renderer.d.ts +9 -0
  8. package/dist/assets/fonts/implementations/css-renderer.js +42 -0
  9. package/dist/assets/fonts/implementations/data-collector.d.ts +3 -0
  10. package/dist/assets/fonts/implementations/data-collector.js +21 -0
  11. package/dist/assets/fonts/implementations/error-handler.d.ts +2 -0
  12. package/dist/assets/fonts/implementations/error-handler.js +33 -0
  13. package/dist/assets/fonts/implementations/font-fetcher.d.ts +8 -0
  14. package/dist/assets/fonts/implementations/font-fetcher.js +34 -0
  15. package/dist/assets/fonts/implementations/font-metrics-resolver.d.ts +5 -0
  16. package/dist/assets/fonts/implementations/font-metrics-resolver.js +60 -0
  17. package/dist/assets/fonts/implementations/font-type-extractor.d.ts +4 -0
  18. package/dist/assets/fonts/implementations/font-type-extractor.js +22 -0
  19. package/dist/assets/fonts/implementations/hasher.d.ts +2 -0
  20. package/dist/assets/fonts/implementations/hasher.js +14 -0
  21. package/dist/assets/fonts/implementations/local-provider-url-resolver.d.ts +5 -0
  22. package/dist/assets/fonts/implementations/local-provider-url-resolver.js +17 -0
  23. package/dist/assets/fonts/implementations/remote-font-provider-mod-resolver.d.ts +6 -0
  24. package/dist/assets/fonts/implementations/remote-font-provider-mod-resolver.js +20 -0
  25. package/dist/assets/fonts/implementations/remote-font-provider-resolver.d.ts +6 -0
  26. package/dist/assets/fonts/implementations/remote-font-provider-resolver.js +47 -0
  27. package/dist/assets/fonts/implementations/storage.d.ts +4 -0
  28. package/dist/assets/fonts/implementations/storage.js +14 -0
  29. package/dist/assets/fonts/implementations/system-fallbacks-provider.d.ts +11 -0
  30. package/dist/assets/fonts/implementations/system-fallbacks-provider.js +74 -0
  31. package/dist/assets/fonts/implementations/url-proxy-content-resolver.d.ts +5 -0
  32. package/dist/assets/fonts/implementations/url-proxy-content-resolver.js +28 -0
  33. package/dist/assets/fonts/implementations/url-proxy.d.ts +8 -0
  34. package/dist/assets/fonts/implementations/url-proxy.js +26 -0
  35. package/dist/assets/fonts/logic/extract-unifont-providers.d.ts +10 -0
  36. package/dist/assets/fonts/logic/extract-unifont-providers.js +28 -0
  37. package/dist/assets/fonts/logic/normalize-remote-font-faces.d.ts +6 -0
  38. package/dist/assets/fonts/logic/normalize-remote-font-faces.js +36 -0
  39. package/dist/assets/fonts/logic/optimize-fallbacks.d.ts +17 -0
  40. package/dist/assets/fonts/logic/optimize-fallbacks.js +47 -0
  41. package/dist/assets/fonts/logic/resolve-families.d.ts +17 -0
  42. package/dist/assets/fonts/logic/resolve-families.js +67 -0
  43. package/dist/assets/fonts/orchestrate.d.ts +37 -0
  44. package/dist/assets/fonts/orchestrate.js +125 -0
  45. package/dist/assets/fonts/providers/local.d.ts +6 -7
  46. package/dist/assets/fonts/providers/local.js +26 -29
  47. package/dist/assets/fonts/types.d.ts +32 -2
  48. package/dist/assets/fonts/utils.d.ts +17 -88
  49. package/dist/assets/fonts/utils.js +20 -186
  50. package/dist/assets/fonts/vite-plugin-fonts.js +96 -94
  51. package/dist/content/content-layer.js +3 -3
  52. package/dist/core/constants.js +1 -1
  53. package/dist/core/dev/dev.js +1 -1
  54. package/dist/core/messages.js +2 -2
  55. package/dist/types/public/config.d.ts +2 -2
  56. package/dist/vite-plugin-markdown/images.js +4 -4
  57. package/package.json +2 -2
  58. package/types/content.d.ts +11 -4
  59. package/dist/assets/fonts/load.d.ts +0 -20
  60. package/dist/assets/fonts/load.js +0 -162
  61. package/dist/assets/fonts/metrics.d.ts +0 -10
  62. package/dist/assets/fonts/metrics.js +0 -55
  63. package/dist/assets/fonts/providers/utils.d.ts +0 -9
  64. package/dist/assets/fonts/providers/utils.js +0 -37
@@ -0,0 +1,47 @@
1
+ import { resolveEntrypoint } from "../utils.js";
2
+ function validateMod({
3
+ mod,
4
+ entrypoint,
5
+ errorHandler
6
+ }) {
7
+ try {
8
+ if (typeof mod !== "object" || mod === null) {
9
+ throw new Error(`Expected an object for the module, but received ${typeof mod}.`);
10
+ }
11
+ if (typeof mod.provider !== "function") {
12
+ throw new Error(`Invalid provider export in module, expected a function.`);
13
+ }
14
+ return {
15
+ provider: mod.provider
16
+ };
17
+ } catch (cause) {
18
+ throw errorHandler.handle({
19
+ type: "cannot-load-font-provider",
20
+ data: {
21
+ entrypoint
22
+ },
23
+ cause
24
+ });
25
+ }
26
+ }
27
+ function createRemoteFontProviderResolver({
28
+ root,
29
+ modResolver,
30
+ errorHandler
31
+ }) {
32
+ return {
33
+ async resolve({ entrypoint, config }) {
34
+ const id = resolveEntrypoint(root, entrypoint.toString()).href;
35
+ const mod = await modResolver.resolve(id);
36
+ const { provider } = validateMod({
37
+ mod,
38
+ entrypoint: id,
39
+ errorHandler
40
+ });
41
+ return { config, provider };
42
+ }
43
+ };
44
+ }
45
+ export {
46
+ createRemoteFontProviderResolver
47
+ };
@@ -0,0 +1,4 @@
1
+ import { type Storage } from 'unstorage';
2
+ export declare function createFsStorage({ base }: {
3
+ base: URL;
4
+ }): Storage;
@@ -0,0 +1,14 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { createStorage } from "unstorage";
3
+ import fsLiteDriver from "unstorage/drivers/fs-lite";
4
+ function createFsStorage({ base }) {
5
+ return createStorage({
6
+ // Types are weirly exported
7
+ driver: fsLiteDriver({
8
+ base: fileURLToPath(base)
9
+ })
10
+ });
11
+ }
12
+ export {
13
+ createFsStorage
14
+ };
@@ -0,0 +1,11 @@
1
+ import type { SystemFallbacksProvider } from '../definitions.js';
2
+ export declare const DEFAULT_FALLBACKS: {
3
+ serif: "Times New Roman"[];
4
+ 'sans-serif': "Arial"[];
5
+ monospace: "Courier New"[];
6
+ 'system-ui': ("Arial" | "BlinkMacSystemFont" | "Segoe UI" | "Roboto" | "Helvetica Neue")[];
7
+ 'ui-serif': "Times New Roman"[];
8
+ 'ui-sans-serif': "Arial"[];
9
+ 'ui-monospace': "Courier New"[];
10
+ };
11
+ export declare function createSystemFallbacksProvider(): SystemFallbacksProvider;
@@ -0,0 +1,74 @@
1
+ const SYSTEM_METRICS = {
2
+ "Times New Roman": {
3
+ ascent: 1825,
4
+ descent: -443,
5
+ lineGap: 87,
6
+ unitsPerEm: 2048,
7
+ xWidthAvg: 832
8
+ },
9
+ Arial: {
10
+ ascent: 1854,
11
+ descent: -434,
12
+ lineGap: 67,
13
+ unitsPerEm: 2048,
14
+ xWidthAvg: 913
15
+ },
16
+ "Courier New": {
17
+ ascent: 1705,
18
+ descent: -615,
19
+ lineGap: 0,
20
+ unitsPerEm: 2048,
21
+ xWidthAvg: 1229
22
+ },
23
+ BlinkMacSystemFont: {
24
+ ascent: 1980,
25
+ descent: -432,
26
+ lineGap: 0,
27
+ unitsPerEm: 2048,
28
+ xWidthAvg: 853
29
+ },
30
+ "Segoe UI": {
31
+ ascent: 2210,
32
+ descent: -514,
33
+ lineGap: 0,
34
+ unitsPerEm: 2048,
35
+ xWidthAvg: 908
36
+ },
37
+ Roboto: {
38
+ ascent: 1900,
39
+ descent: -500,
40
+ lineGap: 0,
41
+ unitsPerEm: 2048,
42
+ xWidthAvg: 911
43
+ },
44
+ "Helvetica Neue": {
45
+ ascent: 952,
46
+ descent: -213,
47
+ lineGap: 28,
48
+ unitsPerEm: 1e3,
49
+ xWidthAvg: 450
50
+ }
51
+ };
52
+ const DEFAULT_FALLBACKS = {
53
+ serif: ["Times New Roman"],
54
+ "sans-serif": ["Arial"],
55
+ monospace: ["Courier New"],
56
+ "system-ui": ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial"],
57
+ "ui-serif": ["Times New Roman"],
58
+ "ui-sans-serif": ["Arial"],
59
+ "ui-monospace": ["Courier New"]
60
+ };
61
+ function createSystemFallbacksProvider() {
62
+ return {
63
+ getLocalFonts(fallback) {
64
+ return DEFAULT_FALLBACKS[fallback] ?? null;
65
+ },
66
+ getMetricsForLocalFont(family) {
67
+ return SYSTEM_METRICS[family];
68
+ }
69
+ };
70
+ }
71
+ export {
72
+ DEFAULT_FALLBACKS,
73
+ createSystemFallbacksProvider
74
+ };
@@ -0,0 +1,5 @@
1
+ import type { ErrorHandler, UrlProxyContentResolver } from '../definitions.js';
2
+ export declare function createLocalUrlProxyContentResolver({ errorHandler, }: {
3
+ errorHandler: ErrorHandler;
4
+ }): UrlProxyContentResolver;
5
+ export declare function createRemoteUrlProxyContentResolver(): UrlProxyContentResolver;
@@ -0,0 +1,28 @@
1
+ import { readFileSync } from "node:fs";
2
+ function createLocalUrlProxyContentResolver({
3
+ errorHandler
4
+ }) {
5
+ return {
6
+ resolve(url) {
7
+ try {
8
+ return url + readFileSync(url, "utf-8");
9
+ } catch (cause) {
10
+ throw errorHandler.handle({
11
+ type: "unknown-fs-error",
12
+ data: {},
13
+ cause
14
+ });
15
+ }
16
+ }
17
+ };
18
+ }
19
+ function createRemoteUrlProxyContentResolver() {
20
+ return {
21
+ // Passthrough, the remote provider URL is enough
22
+ resolve: (url) => url
23
+ };
24
+ }
25
+ export {
26
+ createLocalUrlProxyContentResolver,
27
+ createRemoteUrlProxyContentResolver
28
+ };
@@ -0,0 +1,8 @@
1
+ import type { DataCollector, FontTypeExtractor, Hasher, UrlProxy, UrlProxyContentResolver } from '../definitions.js';
2
+ export declare function createUrlProxy({ base, contentResolver, hasher, dataCollector, fontTypeExtractor, }: {
3
+ base: string;
4
+ contentResolver: UrlProxyContentResolver;
5
+ hasher: Hasher;
6
+ dataCollector: DataCollector;
7
+ fontTypeExtractor: FontTypeExtractor;
8
+ }): UrlProxy;
@@ -0,0 +1,26 @@
1
+ function createUrlProxy({
2
+ base,
3
+ contentResolver,
4
+ hasher,
5
+ dataCollector,
6
+ fontTypeExtractor
7
+ }) {
8
+ return {
9
+ proxy({ url: originalUrl, data, collectPreload, init }) {
10
+ const type = fontTypeExtractor.extract(originalUrl);
11
+ const hash = `${hasher.hashString(contentResolver.resolve(originalUrl))}.${type}`;
12
+ const url = base + hash;
13
+ dataCollector.collect({
14
+ url: originalUrl,
15
+ hash,
16
+ preload: collectPreload ? { url, type } : null,
17
+ data,
18
+ init
19
+ });
20
+ return url;
21
+ }
22
+ };
23
+ }
24
+ export {
25
+ createUrlProxy
26
+ };
@@ -0,0 +1,10 @@
1
+ import type * as unifont from 'unifont';
2
+ import type { Hasher } from '../definitions.js';
3
+ import type { ResolvedFontFamily } from '../types.js';
4
+ export declare function extractUnifontProviders({ families, hasher, }: {
5
+ families: Array<ResolvedFontFamily>;
6
+ hasher: Hasher;
7
+ }): {
8
+ families: Array<ResolvedFontFamily>;
9
+ providers: Array<unifont.Provider>;
10
+ };
@@ -0,0 +1,28 @@
1
+ import { LOCAL_PROVIDER_NAME } from "../constants.js";
2
+ function extractUnifontProviders({
3
+ families,
4
+ hasher
5
+ }) {
6
+ const hashes = /* @__PURE__ */ new Set();
7
+ const providers = [];
8
+ for (const { provider } of families) {
9
+ if (provider === LOCAL_PROVIDER_NAME) {
10
+ continue;
11
+ }
12
+ const unifontProvider = provider.provider(provider.config);
13
+ const hash = hasher.hashObject({
14
+ name: unifontProvider._name,
15
+ ...provider.config
16
+ });
17
+ unifontProvider._name += `-${hash}`;
18
+ provider.name = unifontProvider._name;
19
+ if (!hashes.has(hash)) {
20
+ hashes.add(hash);
21
+ providers.push(unifontProvider);
22
+ }
23
+ }
24
+ return { families, providers };
25
+ }
26
+ export {
27
+ extractUnifontProviders
28
+ };
@@ -0,0 +1,6 @@
1
+ import type * as unifont from 'unifont';
2
+ import type { UrlProxy } from '../definitions.js';
3
+ export declare function normalizeRemoteFontFaces({ fonts, urlProxy, }: {
4
+ fonts: Array<unifont.FontFaceData>;
5
+ urlProxy: UrlProxy;
6
+ }): Array<unifont.FontFaceData>;
@@ -0,0 +1,36 @@
1
+ function normalizeRemoteFontFaces({
2
+ fonts,
3
+ urlProxy
4
+ }) {
5
+ return fonts.filter((font) => typeof font.meta?.priority === "number" ? font.meta.priority === 0 : true).map((font) => {
6
+ let index = 0;
7
+ return {
8
+ ...font,
9
+ src: font.src.map((source) => {
10
+ if ("name" in source) {
11
+ return source;
12
+ }
13
+ const proxied = {
14
+ ...source,
15
+ originalURL: source.url,
16
+ url: urlProxy.proxy({
17
+ url: source.url,
18
+ // We only collect the first URL to avoid preloading fallback sources (eg. we only
19
+ // preload woff2 if woff is available)
20
+ collectPreload: index === 0,
21
+ data: {
22
+ weight: font.weight,
23
+ style: font.style
24
+ },
25
+ init: font.meta?.init ?? null
26
+ })
27
+ };
28
+ index++;
29
+ return proxied;
30
+ })
31
+ };
32
+ });
33
+ }
34
+ export {
35
+ normalizeRemoteFontFaces
36
+ };
@@ -0,0 +1,17 @@
1
+ import type * as unifont from 'unifont';
2
+ import type { FontMetricsResolver, SystemFallbacksProvider } from '../definitions.js';
3
+ import type { FontFileData, ResolvedFontFamily } from '../types.js';
4
+ export interface CollectedFontForMetrics extends FontFileData {
5
+ data: Partial<unifont.FontFaceData>;
6
+ }
7
+ export declare function optimizeFallbacks({ family, fallbacks: _fallbacks, collectedFonts, enabled, systemFallbacksProvider, fontMetricsResolver, }: {
8
+ family: Pick<ResolvedFontFamily, 'name' | 'nameWithHash'>;
9
+ fallbacks: Array<string>;
10
+ collectedFonts: Array<CollectedFontForMetrics>;
11
+ enabled: boolean;
12
+ systemFallbacksProvider: SystemFallbacksProvider;
13
+ fontMetricsResolver: FontMetricsResolver;
14
+ }): Promise<null | {
15
+ css: string;
16
+ fallbacks: Array<string>;
17
+ }>;
@@ -0,0 +1,47 @@
1
+ import { isGenericFontFamily, unifontFontFaceDataToProperties } from "../utils.js";
2
+ async function optimizeFallbacks({
3
+ family,
4
+ fallbacks: _fallbacks,
5
+ collectedFonts,
6
+ enabled,
7
+ systemFallbacksProvider,
8
+ fontMetricsResolver
9
+ }) {
10
+ let fallbacks = [..._fallbacks];
11
+ if (fallbacks.length === 0 || !enabled || collectedFonts.length === 0) {
12
+ return null;
13
+ }
14
+ const lastFallback = fallbacks[fallbacks.length - 1];
15
+ if (!isGenericFontFamily(lastFallback)) {
16
+ return null;
17
+ }
18
+ const localFonts = systemFallbacksProvider.getLocalFonts(lastFallback);
19
+ if (!localFonts || localFonts.length === 0) {
20
+ return null;
21
+ }
22
+ if (localFonts.includes(family.name)) {
23
+ return null;
24
+ }
25
+ const localFontsMappings = localFonts.map((font) => ({
26
+ font,
27
+ // We must't wrap in quote because that's handled by the CSS renderer
28
+ name: `${family.nameWithHash} fallback: ${font}`
29
+ }));
30
+ fallbacks = [...localFontsMappings.map((m) => m.name), ...fallbacks];
31
+ let css = "";
32
+ for (const { font, name } of localFontsMappings) {
33
+ for (const collected of collectedFonts) {
34
+ css += fontMetricsResolver.generateFontFace({
35
+ metrics: await fontMetricsResolver.getMetrics(family.name, collected),
36
+ fallbackMetrics: systemFallbacksProvider.getMetricsForLocalFont(font),
37
+ font,
38
+ name,
39
+ properties: unifontFontFaceDataToProperties(collected.data)
40
+ });
41
+ }
42
+ }
43
+ return { css, fallbacks };
44
+ }
45
+ export {
46
+ optimizeFallbacks
47
+ };
@@ -0,0 +1,17 @@
1
+ import type { Hasher, LocalProviderUrlResolver, RemoteFontProviderResolver } from '../definitions.js';
2
+ import type { FontFamily, ResolvedFontFamily } from '../types.js';
3
+ /**
4
+ * Dedupes properties if applicable and resolves entrypoints.
5
+ */
6
+ export declare function resolveFamily({ family, hasher, remoteFontProviderResolver, localProviderUrlResolver, }: {
7
+ family: FontFamily;
8
+ hasher: Hasher;
9
+ remoteFontProviderResolver: RemoteFontProviderResolver;
10
+ localProviderUrlResolver: LocalProviderUrlResolver;
11
+ }): Promise<ResolvedFontFamily>;
12
+ /**
13
+ * A function for convenience. The actual logic lives in resolveFamily
14
+ */
15
+ export declare function resolveFamilies({ families, ...dependencies }: {
16
+ families: Array<FontFamily>;
17
+ } & Omit<Parameters<typeof resolveFamily>[0], 'family'>): Promise<Array<ResolvedFontFamily>>;
@@ -0,0 +1,67 @@
1
+ import { LOCAL_PROVIDER_NAME } from "../constants.js";
2
+ import { dedupe, withoutQuotes } from "../utils.js";
3
+ function resolveVariants({
4
+ variants,
5
+ localProviderUrlResolver
6
+ }) {
7
+ return variants.map((variant) => ({
8
+ ...variant,
9
+ weight: variant.weight.toString(),
10
+ src: variant.src.map((value) => {
11
+ const isValue = typeof value === "string" || value instanceof URL;
12
+ const url = (isValue ? value : value.url).toString();
13
+ const tech = isValue ? void 0 : value.tech;
14
+ return {
15
+ url: localProviderUrlResolver.resolve(url),
16
+ tech
17
+ };
18
+ })
19
+ }));
20
+ }
21
+ async function resolveFamily({
22
+ family,
23
+ hasher,
24
+ remoteFontProviderResolver,
25
+ localProviderUrlResolver
26
+ }) {
27
+ const name = withoutQuotes(family.name);
28
+ const nameWithHash = `${name}-${hasher.hashObject(family)}`;
29
+ if (family.provider === LOCAL_PROVIDER_NAME) {
30
+ return {
31
+ ...family,
32
+ name,
33
+ nameWithHash,
34
+ variants: resolveVariants({ variants: family.variants, localProviderUrlResolver }),
35
+ fallbacks: family.fallbacks ? dedupe(family.fallbacks) : void 0
36
+ };
37
+ }
38
+ return {
39
+ ...family,
40
+ name,
41
+ nameWithHash,
42
+ weights: family.weights ? dedupe(family.weights.map((weight) => weight.toString())) : void 0,
43
+ styles: family.styles ? dedupe(family.styles) : void 0,
44
+ subsets: family.subsets ? dedupe(family.subsets) : void 0,
45
+ fallbacks: family.fallbacks ? dedupe(family.fallbacks) : void 0,
46
+ unicodeRange: family.unicodeRange ? dedupe(family.unicodeRange) : void 0,
47
+ // This will be Astro specific eventually
48
+ provider: await remoteFontProviderResolver.resolve(family.provider)
49
+ };
50
+ }
51
+ async function resolveFamilies({
52
+ families,
53
+ ...dependencies
54
+ }) {
55
+ return await Promise.all(
56
+ families.map(
57
+ (family) => resolveFamily({
58
+ family,
59
+ ...dependencies
60
+ })
61
+ )
62
+ );
63
+ }
64
+ export {
65
+ resolveFamilies,
66
+ resolveFamily
67
+ };
@@ -0,0 +1,37 @@
1
+ import type { Storage } from 'unstorage';
2
+ import type { CssRenderer, FontMetricsResolver, FontTypeExtractor, Hasher, LocalProviderUrlResolver, RemoteFontProviderResolver, SystemFallbacksProvider, UrlProxy } from './definitions.js';
3
+ import type { ConsumableMap, CreateUrlProxyParams, Defaults, FontFamily, FontFileDataMap } from './types.js';
4
+ /**
5
+ * Manages how fonts are resolved:
6
+ *
7
+ * - families are resolved
8
+ * - unifont providers are extracted from families
9
+ * - unifont is initialized
10
+ *
11
+ * For each family:
12
+ * - We create a URL proxy
13
+ * - We resolve the font and normalize the result
14
+ *
15
+ * For each resolved font:
16
+ * - We generate the CSS font face
17
+ * - We generate optimized fallbacks if applicable
18
+ * - We generate CSS variables
19
+ *
20
+ * Once that's done, the collected data is returned
21
+ */
22
+ export declare function orchestrate({ families, hasher, remoteFontProviderResolver, localProviderUrlResolver, storage, cssRenderer, systemFallbacksProvider, fontMetricsResolver, fontTypeExtractor, createUrlProxy, defaults, }: {
23
+ families: Array<FontFamily>;
24
+ hasher: Hasher;
25
+ remoteFontProviderResolver: RemoteFontProviderResolver;
26
+ localProviderUrlResolver: LocalProviderUrlResolver;
27
+ storage: Storage;
28
+ cssRenderer: CssRenderer;
29
+ systemFallbacksProvider: SystemFallbacksProvider;
30
+ fontMetricsResolver: FontMetricsResolver;
31
+ fontTypeExtractor: FontTypeExtractor;
32
+ createUrlProxy: (params: CreateUrlProxyParams) => UrlProxy;
33
+ defaults: Defaults;
34
+ }): Promise<{
35
+ fontFileDataMap: FontFileDataMap;
36
+ consumableMap: ConsumableMap;
37
+ }>;
@@ -0,0 +1,125 @@
1
+ import * as unifont from "unifont";
2
+ import { LOCAL_PROVIDER_NAME } from "./constants.js";
3
+ import { extractUnifontProviders } from "./logic/extract-unifont-providers.js";
4
+ import { normalizeRemoteFontFaces } from "./logic/normalize-remote-font-faces.js";
5
+ import { optimizeFallbacks } from "./logic/optimize-fallbacks.js";
6
+ import { resolveFamilies } from "./logic/resolve-families.js";
7
+ import { resolveLocalFont } from "./providers/local.js";
8
+ import { pickFontFaceProperty, unifontFontFaceDataToProperties } from "./utils.js";
9
+ async function orchestrate({
10
+ families,
11
+ hasher,
12
+ remoteFontProviderResolver,
13
+ localProviderUrlResolver,
14
+ storage,
15
+ cssRenderer,
16
+ systemFallbacksProvider,
17
+ fontMetricsResolver,
18
+ fontTypeExtractor,
19
+ createUrlProxy,
20
+ defaults
21
+ }) {
22
+ let resolvedFamilies = await resolveFamilies({
23
+ families,
24
+ hasher,
25
+ remoteFontProviderResolver,
26
+ localProviderUrlResolver
27
+ });
28
+ const extractedUnifontProvidersResult = extractUnifontProviders({
29
+ families: resolvedFamilies,
30
+ hasher
31
+ });
32
+ resolvedFamilies = extractedUnifontProvidersResult.families;
33
+ const unifontProviders = extractedUnifontProvidersResult.providers;
34
+ const { resolveFont } = await unifont.createUnifont(unifontProviders, {
35
+ storage
36
+ });
37
+ const fontFileDataMap = /* @__PURE__ */ new Map();
38
+ const consumableMap = /* @__PURE__ */ new Map();
39
+ for (const family of resolvedFamilies) {
40
+ const preloadData = [];
41
+ let css = "";
42
+ const collectedFonts = [];
43
+ const fallbacks = family.fallbacks ?? defaults.fallbacks ?? [];
44
+ const urlProxy = createUrlProxy({
45
+ local: family.provider === LOCAL_PROVIDER_NAME,
46
+ hasUrl: (hash) => fontFileDataMap.has(hash),
47
+ saveUrl: ({ hash, url, init }) => {
48
+ fontFileDataMap.set(hash, { url, init });
49
+ },
50
+ savePreload: (preload) => {
51
+ preloadData.push(preload);
52
+ },
53
+ saveFontData: (collected) => {
54
+ if (fallbacks && fallbacks.length > 0 && // If the same data has already been sent for this family, we don't want to have
55
+ // duplicated fallbacks. Such scenario can occur with unicode ranges.
56
+ !collectedFonts.some((f) => JSON.stringify(f.data) === JSON.stringify(collected.data))) {
57
+ collectedFonts.push(collected);
58
+ }
59
+ }
60
+ });
61
+ let fonts;
62
+ if (family.provider === LOCAL_PROVIDER_NAME) {
63
+ const result = resolveLocalFont({
64
+ family,
65
+ urlProxy,
66
+ fontTypeExtractor
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 where
80
+ // we specify a provider per font. Name has been set while extracting unifont providers
81
+ // from families (inside extractUnifontProviders).
82
+ [family.provider.name]
83
+ );
84
+ fonts = normalizeRemoteFontFaces({ fonts: result.fonts, urlProxy });
85
+ }
86
+ for (const data of fonts) {
87
+ css += cssRenderer.generateFontFace(
88
+ family.nameWithHash,
89
+ unifontFontFaceDataToProperties({
90
+ src: data.src,
91
+ weight: data.weight,
92
+ style: data.style,
93
+ // User settings override the generated font settings. We use a helper function
94
+ // because local and remote providers store this data in different places.
95
+ display: pickFontFaceProperty("display", { data, family }),
96
+ unicodeRange: pickFontFaceProperty("unicodeRange", { data, family }),
97
+ stretch: pickFontFaceProperty("stretch", { data, family }),
98
+ featureSettings: pickFontFaceProperty("featureSettings", { data, family }),
99
+ variationSettings: pickFontFaceProperty("variationSettings", { data, family })
100
+ })
101
+ );
102
+ }
103
+ const cssVarValues = [family.nameWithHash];
104
+ const optimizeFallbacksResult = await optimizeFallbacks({
105
+ family,
106
+ fallbacks,
107
+ collectedFonts,
108
+ enabled: family.optimizedFallbacks ?? defaults.optimizedFallbacks ?? false,
109
+ systemFallbacksProvider,
110
+ fontMetricsResolver
111
+ });
112
+ if (optimizeFallbacksResult) {
113
+ css += optimizeFallbacksResult.css;
114
+ cssVarValues.push(...optimizeFallbacksResult.fallbacks);
115
+ } else {
116
+ cssVarValues.push(...fallbacks);
117
+ }
118
+ css += cssRenderer.generateCssVariable(family.cssVariable, cssVarValues);
119
+ consumableMap.set(family.cssVariable, { preloadData, css });
120
+ }
121
+ return { fontFileDataMap, consumableMap };
122
+ }
123
+ export {
124
+ orchestrate
125
+ };
@@ -1,13 +1,12 @@
1
1
  import type * as unifont from 'unifont';
2
+ import type { FontTypeExtractor, UrlProxy } from '../definitions.js';
2
3
  import type { ResolvedLocalFontFamily } from '../types.js';
3
- type InitializedProvider = NonNullable<Awaited<ReturnType<unifont.Provider>>>;
4
- type ResolveFontResult = NonNullable<Awaited<ReturnType<InitializedProvider['resolveFont']>>>;
5
4
  interface Options {
6
5
  family: ResolvedLocalFontFamily;
7
- proxyURL: (params: {
8
- value: string;
9
- data: Partial<unifont.FontFaceData>;
10
- }) => string;
6
+ urlProxy: UrlProxy;
7
+ fontTypeExtractor: FontTypeExtractor;
11
8
  }
12
- export declare function resolveLocalFont({ family, proxyURL }: Options): ResolveFontResult;
9
+ export declare function resolveLocalFont({ family, urlProxy, fontTypeExtractor }: Options): {
10
+ fonts: Array<unifont.FontFaceData>;
11
+ };
13
12
  export {};