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.
- package/dist/assets/fonts/config.d.ts +3 -3
- package/dist/assets/fonts/config.js +2 -3
- package/dist/assets/fonts/constants.d.ts +3 -73
- package/dist/assets/fonts/constants.js +16 -68
- package/dist/assets/fonts/definitions.d.ts +73 -0
- package/dist/assets/fonts/definitions.js +0 -0
- package/dist/assets/fonts/implementations/css-renderer.d.ts +9 -0
- package/dist/assets/fonts/implementations/css-renderer.js +42 -0
- package/dist/assets/fonts/implementations/data-collector.d.ts +3 -0
- package/dist/assets/fonts/implementations/data-collector.js +21 -0
- package/dist/assets/fonts/implementations/error-handler.d.ts +2 -0
- package/dist/assets/fonts/implementations/error-handler.js +33 -0
- package/dist/assets/fonts/implementations/font-fetcher.d.ts +8 -0
- package/dist/assets/fonts/implementations/font-fetcher.js +34 -0
- package/dist/assets/fonts/implementations/font-metrics-resolver.d.ts +5 -0
- package/dist/assets/fonts/implementations/font-metrics-resolver.js +60 -0
- package/dist/assets/fonts/implementations/font-type-extractor.d.ts +4 -0
- package/dist/assets/fonts/implementations/font-type-extractor.js +22 -0
- package/dist/assets/fonts/implementations/hasher.d.ts +2 -0
- package/dist/assets/fonts/implementations/hasher.js +14 -0
- package/dist/assets/fonts/implementations/local-provider-url-resolver.d.ts +5 -0
- package/dist/assets/fonts/implementations/local-provider-url-resolver.js +17 -0
- package/dist/assets/fonts/implementations/remote-font-provider-mod-resolver.d.ts +6 -0
- package/dist/assets/fonts/implementations/remote-font-provider-mod-resolver.js +20 -0
- package/dist/assets/fonts/implementations/remote-font-provider-resolver.d.ts +6 -0
- package/dist/assets/fonts/implementations/remote-font-provider-resolver.js +47 -0
- package/dist/assets/fonts/implementations/storage.d.ts +4 -0
- package/dist/assets/fonts/implementations/storage.js +14 -0
- package/dist/assets/fonts/implementations/system-fallbacks-provider.d.ts +11 -0
- package/dist/assets/fonts/implementations/system-fallbacks-provider.js +74 -0
- package/dist/assets/fonts/implementations/url-proxy-content-resolver.d.ts +5 -0
- package/dist/assets/fonts/implementations/url-proxy-content-resolver.js +28 -0
- package/dist/assets/fonts/implementations/url-proxy.d.ts +8 -0
- package/dist/assets/fonts/implementations/url-proxy.js +26 -0
- package/dist/assets/fonts/logic/extract-unifont-providers.d.ts +10 -0
- package/dist/assets/fonts/logic/extract-unifont-providers.js +28 -0
- package/dist/assets/fonts/logic/normalize-remote-font-faces.d.ts +6 -0
- package/dist/assets/fonts/logic/normalize-remote-font-faces.js +36 -0
- package/dist/assets/fonts/logic/optimize-fallbacks.d.ts +17 -0
- package/dist/assets/fonts/logic/optimize-fallbacks.js +47 -0
- package/dist/assets/fonts/logic/resolve-families.d.ts +17 -0
- package/dist/assets/fonts/logic/resolve-families.js +67 -0
- package/dist/assets/fonts/orchestrate.d.ts +37 -0
- package/dist/assets/fonts/orchestrate.js +125 -0
- package/dist/assets/fonts/providers/local.d.ts +6 -7
- package/dist/assets/fonts/providers/local.js +26 -29
- package/dist/assets/fonts/types.d.ts +32 -2
- package/dist/assets/fonts/utils.d.ts +17 -88
- package/dist/assets/fonts/utils.js +20 -186
- package/dist/assets/fonts/vite-plugin-fonts.js +96 -94
- package/dist/content/content-layer.js +3 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/types/public/config.d.ts +2 -2
- package/dist/vite-plugin-markdown/images.js +4 -4
- package/package.json +2 -2
- package/types/content.d.ts +11 -4
- package/dist/assets/fonts/load.d.ts +0 -20
- package/dist/assets/fonts/load.js +0 -162
- package/dist/assets/fonts/metrics.d.ts +0 -10
- package/dist/assets/fonts/metrics.js +0 -55
- package/dist/assets/fonts/providers/utils.d.ts +0 -9
- package/dist/assets/fonts/providers/utils.js +0 -37
|
@@ -3,49 +3,38 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import { isAbsolute } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { removeTrailingForwardSlash } from "@astrojs/internal-helpers/path";
|
|
6
|
-
import { createStorage } from "unstorage";
|
|
7
|
-
import fsLiteDriver from "unstorage/drivers/fs-lite";
|
|
8
|
-
import xxhash from "xxhash-wasm";
|
|
9
6
|
import { collectErrorMetadata } from "../../core/errors/dev/utils.js";
|
|
10
7
|
import { AstroError, AstroErrorData, isAstroError } from "../../core/errors/index.js";
|
|
11
8
|
import { formatErrorMessage } from "../../core/messages.js";
|
|
12
9
|
import { getClientOutputDirectory } from "../../prerender/utils.js";
|
|
13
10
|
import {
|
|
14
11
|
CACHE_DIR,
|
|
12
|
+
DEFAULTS,
|
|
15
13
|
RESOLVED_VIRTUAL_MODULE_ID,
|
|
16
14
|
URL_PREFIX,
|
|
17
15
|
VIRTUAL_MODULE_ID
|
|
18
16
|
} from "./constants.js";
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
17
|
+
import { createMinifiableCssRenderer } from "./implementations/css-renderer.js";
|
|
18
|
+
import { createDataCollector } from "./implementations/data-collector.js";
|
|
19
|
+
import { createAstroErrorHandler } from "./implementations/error-handler.js";
|
|
20
|
+
import { createCachedFontFetcher } from "./implementations/font-fetcher.js";
|
|
21
|
+
import { createCapsizeFontMetricsResolver } from "./implementations/font-metrics-resolver.js";
|
|
22
|
+
import { createFontTypeExtractor } from "./implementations/font-type-extractor.js";
|
|
23
|
+
import { createXxHasher } from "./implementations/hasher.js";
|
|
24
|
+
import { createRequireLocalProviderUrlResolver } from "./implementations/local-provider-url-resolver.js";
|
|
21
25
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const response = await fetch(url);
|
|
35
|
-
if (!response.ok) {
|
|
36
|
-
throw new Error(`Response was not successful, received status code ${response.status}`);
|
|
37
|
-
}
|
|
38
|
-
return Buffer.from(await response.arrayBuffer());
|
|
39
|
-
} catch (cause) {
|
|
40
|
-
throw new AstroError(
|
|
41
|
-
{
|
|
42
|
-
...AstroErrorData.CannotFetchFontFile,
|
|
43
|
-
message: AstroErrorData.CannotFetchFontFile.message(url)
|
|
44
|
-
},
|
|
45
|
-
{ cause }
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
26
|
+
createBuildRemoteFontProviderModResolver,
|
|
27
|
+
createDevServerRemoteFontProviderModResolver
|
|
28
|
+
} from "./implementations/remote-font-provider-mod-resolver.js";
|
|
29
|
+
import { createRemoteFontProviderResolver } from "./implementations/remote-font-provider-resolver.js";
|
|
30
|
+
import { createFsStorage } from "./implementations/storage.js";
|
|
31
|
+
import { createSystemFallbacksProvider } from "./implementations/system-fallbacks-provider.js";
|
|
32
|
+
import {
|
|
33
|
+
createLocalUrlProxyContentResolver,
|
|
34
|
+
createRemoteUrlProxyContentResolver
|
|
35
|
+
} from "./implementations/url-proxy-content-resolver.js";
|
|
36
|
+
import { createUrlProxy } from "./implementations/url-proxy.js";
|
|
37
|
+
import { orchestrate } from "./orchestrate.js";
|
|
49
38
|
function fontsPlugin({ settings, sync, logger }) {
|
|
50
39
|
if (!settings.config.experimental.fonts) {
|
|
51
40
|
return {
|
|
@@ -65,64 +54,75 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
65
54
|
};
|
|
66
55
|
}
|
|
67
56
|
const baseUrl = removeTrailingForwardSlash(settings.config.base) + URL_PREFIX;
|
|
68
|
-
let
|
|
69
|
-
let
|
|
57
|
+
let fontFileDataMap = null;
|
|
58
|
+
let consumableMap = null;
|
|
70
59
|
let isBuild;
|
|
71
|
-
let
|
|
60
|
+
let fontFetcher = null;
|
|
61
|
+
let fontTypeExtractor = null;
|
|
72
62
|
const cleanup = () => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
consumableMap = null;
|
|
64
|
+
fontFileDataMap = null;
|
|
65
|
+
fontFetcher = null;
|
|
76
66
|
};
|
|
77
|
-
async function initialize({
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
67
|
+
async function initialize({
|
|
68
|
+
cacheDir,
|
|
69
|
+
modResolver,
|
|
70
|
+
cssRenderer
|
|
71
|
+
}) {
|
|
72
|
+
const { root } = settings.config;
|
|
73
|
+
const hasher = await createXxHasher();
|
|
74
|
+
const errorHandler = createAstroErrorHandler();
|
|
75
|
+
const remoteFontProviderResolver = createRemoteFontProviderResolver({
|
|
76
|
+
root,
|
|
77
|
+
modResolver,
|
|
78
|
+
errorHandler
|
|
84
79
|
});
|
|
85
|
-
hashToUrlMap = /* @__PURE__ */ new Map();
|
|
86
|
-
resolvedMap = /* @__PURE__ */ new Map();
|
|
87
|
-
const families = [];
|
|
88
|
-
const root = settings.config.root;
|
|
89
80
|
const pathsToWarn = /* @__PURE__ */ new Set();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
generateNameWithHash: (_family) => `${withoutQuotes(_family.name)}-${h64ToString(JSON.stringify(sortObjectByKey(_family)))}`,
|
|
97
|
-
resolveLocalEntrypoint: (url) => {
|
|
98
|
-
const resolvedPath = fileURLToPath(resolveEntrypoint(root, url));
|
|
99
|
-
if (resolvedPath.startsWith(fileURLToPath(settings.config.publicDir))) {
|
|
100
|
-
pathsToWarn.add(resolvedPath);
|
|
101
|
-
}
|
|
102
|
-
return resolvedPath;
|
|
81
|
+
const localProviderUrlResolver = createRequireLocalProviderUrlResolver({
|
|
82
|
+
root,
|
|
83
|
+
intercept: (path) => {
|
|
84
|
+
if (path.startsWith(fileURLToPath(settings.config.publicDir))) {
|
|
85
|
+
if (pathsToWarn.has(path)) {
|
|
86
|
+
return;
|
|
103
87
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
88
|
+
pathsToWarn.add(path);
|
|
89
|
+
logger.warn(
|
|
90
|
+
"assets",
|
|
91
|
+
`Found a local font file ${JSON.stringify(path)} in the \`public/\` folder. To avoid duplicated files in the build output, move this file into \`src/\``
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
const storage = createFsStorage({ base: cacheDir });
|
|
97
|
+
const systemFallbacksProvider = createSystemFallbacksProvider();
|
|
98
|
+
fontFetcher = createCachedFontFetcher({ storage, errorHandler, fetch, readFile });
|
|
99
|
+
const fontMetricsResolver = createCapsizeFontMetricsResolver({ fontFetcher, cssRenderer });
|
|
100
|
+
fontTypeExtractor = createFontTypeExtractor({ errorHandler });
|
|
101
|
+
const res = await orchestrate({
|
|
102
|
+
families: settings.config.experimental.fonts,
|
|
103
|
+
hasher,
|
|
104
|
+
remoteFontProviderResolver,
|
|
105
|
+
localProviderUrlResolver,
|
|
116
106
|
storage,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
107
|
+
cssRenderer,
|
|
108
|
+
systemFallbacksProvider,
|
|
109
|
+
fontMetricsResolver,
|
|
110
|
+
fontTypeExtractor,
|
|
111
|
+
createUrlProxy: ({ local, ...params }) => {
|
|
112
|
+
const dataCollector = createDataCollector(params);
|
|
113
|
+
const contentResolver = local ? createLocalUrlProxyContentResolver({ errorHandler }) : createRemoteUrlProxyContentResolver();
|
|
114
|
+
return createUrlProxy({
|
|
115
|
+
base: baseUrl,
|
|
116
|
+
contentResolver,
|
|
117
|
+
hasher,
|
|
118
|
+
dataCollector,
|
|
119
|
+
fontTypeExtractor
|
|
120
|
+
});
|
|
123
121
|
},
|
|
124
|
-
|
|
122
|
+
defaults: DEFAULTS
|
|
125
123
|
});
|
|
124
|
+
fontFileDataMap = res.fontFileDataMap;
|
|
125
|
+
consumableMap = res.consumableMap;
|
|
126
126
|
}
|
|
127
127
|
return {
|
|
128
128
|
name: "astro:fonts",
|
|
@@ -132,18 +132,20 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
132
132
|
async buildStart() {
|
|
133
133
|
if (isBuild) {
|
|
134
134
|
await initialize({
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
cacheDir: new URL(CACHE_DIR, settings.config.cacheDir),
|
|
136
|
+
modResolver: createBuildRemoteFontProviderModResolver(),
|
|
137
|
+
cssRenderer: createMinifiableCssRenderer({ minify: true })
|
|
137
138
|
});
|
|
138
139
|
}
|
|
139
140
|
},
|
|
140
141
|
async configureServer(server) {
|
|
141
142
|
await initialize({
|
|
142
|
-
resolveMod: (id) => server.ssrLoadModule(id),
|
|
143
143
|
// In dev, we cache fonts data in .astro so it can be easily inspected and cleared
|
|
144
|
-
|
|
144
|
+
cacheDir: new URL(CACHE_DIR, settings.dotAstroDir),
|
|
145
|
+
modResolver: createDevServerRemoteFontProviderModResolver({ server }),
|
|
146
|
+
cssRenderer: createMinifiableCssRenderer({ minify: false })
|
|
145
147
|
});
|
|
146
|
-
const localPaths = [...
|
|
148
|
+
const localPaths = [...fontFileDataMap.values()].filter(({ url }) => isAbsolute(url)).map((v) => v.url);
|
|
147
149
|
server.watcher.on("change", (path) => {
|
|
148
150
|
if (localPaths.includes(path)) {
|
|
149
151
|
logger.info("assets", "Font file updated");
|
|
@@ -163,17 +165,17 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
163
165
|
return next();
|
|
164
166
|
}
|
|
165
167
|
const hash = req.url.slice(1);
|
|
166
|
-
const
|
|
167
|
-
if (!
|
|
168
|
+
const associatedData = fontFileDataMap?.get(hash);
|
|
169
|
+
if (!associatedData) {
|
|
168
170
|
return next();
|
|
169
171
|
}
|
|
170
172
|
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
|
|
171
173
|
res.setHeader("Pragma", "no-cache");
|
|
172
174
|
res.setHeader("Expires", 0);
|
|
173
175
|
try {
|
|
174
|
-
const data = await
|
|
176
|
+
const data = await fontFetcher.fetch({ hash, ...associatedData });
|
|
175
177
|
res.setHeader("Content-Length", data.length);
|
|
176
|
-
res.setHeader("Content-Type", `font/${
|
|
178
|
+
res.setHeader("Content-Type", `font/${fontTypeExtractor.extract(hash)}`);
|
|
177
179
|
res.end(data);
|
|
178
180
|
} catch (err) {
|
|
179
181
|
logger.error("assets", "Cannot download font file");
|
|
@@ -196,7 +198,7 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
196
198
|
load(id) {
|
|
197
199
|
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
198
200
|
return {
|
|
199
|
-
code: `export const fontsData = new Map(${JSON.stringify(Array.from(
|
|
201
|
+
code: `export const fontsData = new Map(${JSON.stringify(Array.from(consumableMap?.entries() ?? []))})`
|
|
200
202
|
};
|
|
201
203
|
}
|
|
202
204
|
},
|
|
@@ -213,11 +215,11 @@ function fontsPlugin({ settings, sync, logger }) {
|
|
|
213
215
|
} catch (cause) {
|
|
214
216
|
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause });
|
|
215
217
|
}
|
|
216
|
-
if (
|
|
218
|
+
if (fontFileDataMap) {
|
|
217
219
|
logger.info("assets", "Copying fonts...");
|
|
218
220
|
await Promise.all(
|
|
219
|
-
Array.from(
|
|
220
|
-
const data = await
|
|
221
|
+
Array.from(fontFileDataMap.entries()).map(async ([hash, associatedData]) => {
|
|
222
|
+
const data = await fontFetcher.fetch({ hash, ...associatedData });
|
|
221
223
|
try {
|
|
222
224
|
writeFileSync(new URL(hash, fontsDir), data);
|
|
223
225
|
} catch (cause) {
|
|
@@ -153,7 +153,7 @@ ${contentConfig.error.message}`);
|
|
|
153
153
|
logger.info("Content config changed");
|
|
154
154
|
shouldClear = true;
|
|
155
155
|
}
|
|
156
|
-
if (previousAstroVersion && previousAstroVersion !== "5.7.
|
|
156
|
+
if (previousAstroVersion && previousAstroVersion !== "5.7.8") {
|
|
157
157
|
logger.info("Astro version changed");
|
|
158
158
|
shouldClear = true;
|
|
159
159
|
}
|
|
@@ -161,8 +161,8 @@ ${contentConfig.error.message}`);
|
|
|
161
161
|
logger.info("Clearing content store");
|
|
162
162
|
this.#store.clearAll();
|
|
163
163
|
}
|
|
164
|
-
if ("5.7.
|
|
165
|
-
await this.#store.metaStore().set("astro-version", "5.7.
|
|
164
|
+
if ("5.7.8") {
|
|
165
|
+
await this.#store.metaStore().set("astro-version", "5.7.8");
|
|
166
166
|
}
|
|
167
167
|
if (currentConfigDigest) {
|
|
168
168
|
await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
|
|
|
22
22
|
await telemetry.record([]);
|
|
23
23
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
24
24
|
const logger = restart.container.logger;
|
|
25
|
-
const currentVersion = "5.7.
|
|
25
|
+
const currentVersion = "5.7.8";
|
|
26
26
|
const isPrerelease = currentVersion.includes("-");
|
|
27
27
|
if (!isPrerelease) {
|
|
28
28
|
try {
|
package/dist/core/messages.js
CHANGED
|
@@ -37,7 +37,7 @@ function serverStart({
|
|
|
37
37
|
host,
|
|
38
38
|
base
|
|
39
39
|
}) {
|
|
40
|
-
const version = "5.7.
|
|
40
|
+
const version = "5.7.8";
|
|
41
41
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
42
42
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
43
43
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -274,7 +274,7 @@ function printHelp({
|
|
|
274
274
|
message.push(
|
|
275
275
|
linebreak(),
|
|
276
276
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
277
|
-
`v${"5.7.
|
|
277
|
+
`v${"5.7.8"}`
|
|
278
278
|
)} ${headline}`
|
|
279
279
|
);
|
|
280
280
|
}
|
|
@@ -312,9 +312,9 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
|
|
|
312
312
|
* @see output
|
|
313
313
|
* @description
|
|
314
314
|
*
|
|
315
|
-
* Deploy to your favorite server, serverless, or edge host with build adapters. Import one of our first-party adapters
|
|
315
|
+
* Deploy to your favorite server, serverless, or edge host with build adapters. Import one of our first-party adapters ([Cloudflare](/en/guides/integrations-guide/cloudflare/), [Netlify](/en/guides/integrations-guide/netlify/), [Node.js](/en/guides/integrations-guide/node/), [Vercel](/en/guides/integrations-guide/vercel/)) or explore [community adapters](https://astro.build/integrations/2/?search=&categories%5B%5D=adapters) to enable on-demand rendering in your Astro project.
|
|
316
316
|
*
|
|
317
|
-
*
|
|
317
|
+
* See our [on-demand rendering guide](/en/guides/on-demand-rendering/) for more on Astro's server rendering options.
|
|
318
318
|
*
|
|
319
319
|
* ```js
|
|
320
320
|
* import netlify from '@astrojs/netlify';
|
|
@@ -6,7 +6,7 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
6
6
|
const images = async function(html) {
|
|
7
7
|
const imageSources = {};
|
|
8
8
|
${localImagePaths.map((entry) => {
|
|
9
|
-
const rawUrl = JSON.stringify(entry.raw);
|
|
9
|
+
const rawUrl = JSON.stringify(entry.raw).replace(/'/g, "'");
|
|
10
10
|
return `{
|
|
11
11
|
const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
|
|
12
12
|
/[.*+?^${}()|[\]\\]/g,
|
|
@@ -16,7 +16,7 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
16
16
|
let occurrenceCounter = 0;
|
|
17
17
|
while ((match = regex.exec(html)) !== null) {
|
|
18
18
|
const matchKey = ${rawUrl} + '_' + occurrenceCounter;
|
|
19
|
-
const imageProps = JSON.parse(match[1].replace(/"/g, '"'));
|
|
19
|
+
const imageProps = JSON.parse(match[1].replace(/"/g, '"').replace(/'/g, "'"));
|
|
20
20
|
const { src, ...props } = imageProps;
|
|
21
21
|
imageSources[matchKey] = await getImage({src: Astro__${entry.safeName}, ...props});
|
|
22
22
|
occurrenceCounter++;
|
|
@@ -24,7 +24,7 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
24
24
|
}`;
|
|
25
25
|
}).join("\n")}
|
|
26
26
|
${remoteImagePaths.map((raw) => {
|
|
27
|
-
const rawUrl = JSON.stringify(raw);
|
|
27
|
+
const rawUrl = JSON.stringify(raw).replace(/'/g, "'");
|
|
28
28
|
return `{
|
|
29
29
|
const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
|
|
30
30
|
/[.*+?^${}()|[\]\\]/g,
|
|
@@ -34,7 +34,7 @@ function getMarkdownCodeForImages(localImagePaths, remoteImagePaths, html) {
|
|
|
34
34
|
let occurrenceCounter = 0;
|
|
35
35
|
while ((match = regex.exec(html)) !== null) {
|
|
36
36
|
const matchKey = ${rawUrl} + '_' + occurrenceCounter;
|
|
37
|
-
const props = JSON.parse(match[1].replace(/"/g, '"'));
|
|
37
|
+
const props = JSON.parse(match[1].replace(/"/g, '"').replace(/'/g, "'"));
|
|
38
38
|
imageSources[matchKey] = await getImage(props);
|
|
39
39
|
occurrenceCounter++;
|
|
40
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "5.7.
|
|
3
|
+
"version": "5.7.8",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"tinyglobby": "^0.2.12",
|
|
143
143
|
"tsconfck": "^3.1.5",
|
|
144
144
|
"ultrahtml": "^1.6.0",
|
|
145
|
-
"unifont": "~0.
|
|
145
|
+
"unifont": "~0.4.1",
|
|
146
146
|
"unist-util-visit": "^5.0.0",
|
|
147
147
|
"unstorage": "^1.15.0",
|
|
148
148
|
"vfile": "^6.0.3",
|
package/types/content.d.ts
CHANGED
|
@@ -45,11 +45,18 @@ declare module 'astro:content' {
|
|
|
45
45
|
has: (key: string) => boolean;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
type BaseAtomicSchema = import('astro/zod').AnyZodObject;
|
|
49
|
+
|
|
50
|
+
type BaseCompositeSchema =
|
|
51
|
+
| import('astro/zod').ZodUnion<[BaseAtomicSchema, ...BaseAtomicSchema[]]>
|
|
52
|
+
| import('astro/zod').ZodDiscriminatedUnion<string, BaseAtomicSchema[]>
|
|
53
|
+
// If we have a union of unions, give up on trying to type-check it all. You're on your own.
|
|
54
|
+
| import('astro/zod').ZodUnion<[import('astro/zod').ZodUnion<z.any>, ...z.any[]]>;
|
|
55
|
+
|
|
48
56
|
type BaseSchemaWithoutEffects =
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
| import('astro/zod').
|
|
52
|
-
| import('astro/zod').ZodIntersection<BaseSchemaWithoutEffects, BaseSchemaWithoutEffects>;
|
|
57
|
+
| BaseAtomicSchema
|
|
58
|
+
| BaseCompositeSchema
|
|
59
|
+
| import('astro/zod').ZodIntersection<BaseAtomicSchema, BaseAtomicSchema | BaseCompositeSchema>;
|
|
53
60
|
|
|
54
61
|
export type BaseSchema =
|
|
55
62
|
| BaseSchemaWithoutEffects
|
|
@@ -1,20 +0,0 @@
|
|
|
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 {};
|
|
@@ -1,162 +0,0 @@
|
|
|
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
|
-
const fallbacks = family.fallbacks ?? DEFAULTS.fallbacks;
|
|
32
|
-
const fallbackFontData = [];
|
|
33
|
-
const collect = ({ hash, type, value, data }, collectPreload) => {
|
|
34
|
-
const url = base + hash;
|
|
35
|
-
if (!hashToUrlMap.has(hash)) {
|
|
36
|
-
hashToUrlMap.set(hash, value);
|
|
37
|
-
if (collectPreload) {
|
|
38
|
-
preloadData.push({ url, type });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (fallbacks && fallbacks.length > 0 && // If the same data has already been sent for this family, we don't want to have duplicate fallbacks
|
|
42
|
-
// Such scenario can occur with unicode ranges
|
|
43
|
-
!fallbackFontData.some((f) => JSON.stringify(f.data) === JSON.stringify(data))) {
|
|
44
|
-
fallbackFontData.push({
|
|
45
|
-
hash,
|
|
46
|
-
url: value,
|
|
47
|
-
data
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
return url;
|
|
51
|
-
};
|
|
52
|
-
let fonts;
|
|
53
|
-
if (family.provider === LOCAL_PROVIDER_NAME) {
|
|
54
|
-
const result = resolveLocalFont({
|
|
55
|
-
family,
|
|
56
|
-
proxyURL: ({ value, data }) => {
|
|
57
|
-
return proxyURL({
|
|
58
|
-
value,
|
|
59
|
-
// We hash based on the filepath and the contents, since the user could replace
|
|
60
|
-
// a given font file with completely different contents.
|
|
61
|
-
hashString: (v) => {
|
|
62
|
-
let content;
|
|
63
|
-
try {
|
|
64
|
-
content = readFileSync(value, "utf-8");
|
|
65
|
-
} catch (e) {
|
|
66
|
-
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: e });
|
|
67
|
-
}
|
|
68
|
-
return hashString(v + content);
|
|
69
|
-
},
|
|
70
|
-
collect: (input) => collect({ ...input, data }, true)
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
fonts = result.fonts;
|
|
75
|
-
} else {
|
|
76
|
-
const result = await resolveFont(
|
|
77
|
-
family.name,
|
|
78
|
-
// We do not merge the defaults, we only provide defaults as a fallback
|
|
79
|
-
{
|
|
80
|
-
weights: family.weights ?? DEFAULTS.weights,
|
|
81
|
-
styles: family.styles ?? DEFAULTS.styles,
|
|
82
|
-
subsets: family.subsets ?? DEFAULTS.subsets,
|
|
83
|
-
fallbacks: family.fallbacks ?? DEFAULTS.fallbacks
|
|
84
|
-
},
|
|
85
|
-
// By default, unifont goes through all providers. We use a different approach
|
|
86
|
-
// where we specify a provider per font.
|
|
87
|
-
// Name has been set while extracting unifont providers from families (inside familiesToUnifontProviders)
|
|
88
|
-
[family.provider.name]
|
|
89
|
-
);
|
|
90
|
-
fonts = result.fonts.filter(
|
|
91
|
-
(font) => typeof font.meta?.priority === "number" ? font.meta.priority === 0 : true
|
|
92
|
-
).map((font) => {
|
|
93
|
-
let index = 0;
|
|
94
|
-
return {
|
|
95
|
-
...font,
|
|
96
|
-
src: font.src.map((source) => {
|
|
97
|
-
if ("name" in source) {
|
|
98
|
-
return source;
|
|
99
|
-
}
|
|
100
|
-
const proxied = {
|
|
101
|
-
...source,
|
|
102
|
-
originalURL: source.url,
|
|
103
|
-
url: proxyURL({
|
|
104
|
-
value: source.url,
|
|
105
|
-
// We only use the url for hashing since the service returns urls with a hash already
|
|
106
|
-
hashString,
|
|
107
|
-
// We only collect the first URL to avoid preloading fallback sources (eg. we only
|
|
108
|
-
// preload woff2 if woff is available)
|
|
109
|
-
collect: (data) => collect(
|
|
110
|
-
{
|
|
111
|
-
...data,
|
|
112
|
-
data: {
|
|
113
|
-
weight: font.weight,
|
|
114
|
-
style: font.style
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
index === 0
|
|
118
|
-
)
|
|
119
|
-
})
|
|
120
|
-
};
|
|
121
|
-
index++;
|
|
122
|
-
return proxied;
|
|
123
|
-
})
|
|
124
|
-
};
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
for (const data of fonts) {
|
|
128
|
-
css += generateFontFace(family.nameWithHash, {
|
|
129
|
-
src: data.src,
|
|
130
|
-
display: data.display ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.display,
|
|
131
|
-
unicodeRange: data.unicodeRange ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.unicodeRange,
|
|
132
|
-
weight: data.weight,
|
|
133
|
-
style: data.style,
|
|
134
|
-
stretch: data.stretch ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.stretch,
|
|
135
|
-
featureSettings: data.featureSettings ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.featureSettings,
|
|
136
|
-
variationSettings: data.variationSettings ?? family.provider === LOCAL_PROVIDER_NAME ? void 0 : family.variationSettings
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
const fallbackData = await generateFallbacksCSS({
|
|
140
|
-
family,
|
|
141
|
-
font: fallbackFontData,
|
|
142
|
-
fallbacks,
|
|
143
|
-
metrics: family.optimizedFallbacks ?? DEFAULTS.optimizedFallbacks ? {
|
|
144
|
-
getMetricsForFamily,
|
|
145
|
-
generateFontFace: generateFallbackFontFace
|
|
146
|
-
} : null
|
|
147
|
-
});
|
|
148
|
-
const cssVarValues = [family.nameWithHash];
|
|
149
|
-
if (fallbackData) {
|
|
150
|
-
if (fallbackData.css) {
|
|
151
|
-
css += fallbackData.css;
|
|
152
|
-
}
|
|
153
|
-
cssVarValues.push(...fallbackData.fallbacks);
|
|
154
|
-
}
|
|
155
|
-
css += `:root { ${family.cssVariable}: ${cssVarValues.join(", ")}; }`;
|
|
156
|
-
resolvedMap.set(family.cssVariable, { preloadData, css });
|
|
157
|
-
}
|
|
158
|
-
log("Fonts initialized");
|
|
159
|
-
}
|
|
160
|
-
export {
|
|
161
|
-
loadFonts
|
|
162
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type Font } from '@capsizecss/unpack';
|
|
2
|
-
export type FontFaceMetrics = Pick<Font, 'ascent' | 'descent' | 'lineGap' | 'unitsPerEm' | 'xWidthAvg'>;
|
|
3
|
-
export declare function readMetrics(family: string, buffer: Buffer): Promise<FontFaceMetrics>;
|
|
4
|
-
export declare function generateFallbackFontFace({ metrics, fallbackMetrics, name: fallbackName, font: fallbackFontName, properties, }: {
|
|
5
|
-
metrics: FontFaceMetrics;
|
|
6
|
-
fallbackMetrics: FontFaceMetrics;
|
|
7
|
-
name: string;
|
|
8
|
-
font: string;
|
|
9
|
-
properties: Record<string, string | undefined>;
|
|
10
|
-
}): string;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { fromBuffer } from "@capsizecss/unpack";
|
|
2
|
-
import { renderFontFace, renderFontSrc } from "./utils.js";
|
|
3
|
-
const metricCache = {};
|
|
4
|
-
function filterRequiredMetrics({
|
|
5
|
-
ascent,
|
|
6
|
-
descent,
|
|
7
|
-
lineGap,
|
|
8
|
-
unitsPerEm,
|
|
9
|
-
xWidthAvg
|
|
10
|
-
}) {
|
|
11
|
-
return {
|
|
12
|
-
ascent,
|
|
13
|
-
descent,
|
|
14
|
-
lineGap,
|
|
15
|
-
unitsPerEm,
|
|
16
|
-
xWidthAvg
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
async function readMetrics(family, buffer) {
|
|
20
|
-
const metrics = await fromBuffer(buffer);
|
|
21
|
-
metricCache[family] = filterRequiredMetrics(metrics);
|
|
22
|
-
return metricCache[family];
|
|
23
|
-
}
|
|
24
|
-
function toPercentage(value, fractionDigits = 4) {
|
|
25
|
-
const percentage = value * 100;
|
|
26
|
-
return `${+percentage.toFixed(fractionDigits)}%`;
|
|
27
|
-
}
|
|
28
|
-
function generateFallbackFontFace({
|
|
29
|
-
metrics,
|
|
30
|
-
fallbackMetrics,
|
|
31
|
-
name: fallbackName,
|
|
32
|
-
font: fallbackFontName,
|
|
33
|
-
properties
|
|
34
|
-
}) {
|
|
35
|
-
const preferredFontXAvgRatio = metrics.xWidthAvg / metrics.unitsPerEm;
|
|
36
|
-
const fallbackFontXAvgRatio = fallbackMetrics.xWidthAvg / fallbackMetrics.unitsPerEm;
|
|
37
|
-
const sizeAdjust = preferredFontXAvgRatio / fallbackFontXAvgRatio;
|
|
38
|
-
const adjustedEmSquare = metrics.unitsPerEm * sizeAdjust;
|
|
39
|
-
const ascentOverride = metrics.ascent / adjustedEmSquare;
|
|
40
|
-
const descentOverride = Math.abs(metrics.descent) / adjustedEmSquare;
|
|
41
|
-
const lineGapOverride = metrics.lineGap / adjustedEmSquare;
|
|
42
|
-
return renderFontFace({
|
|
43
|
-
"font-family": fallbackName,
|
|
44
|
-
src: renderFontSrc([{ name: fallbackFontName }]),
|
|
45
|
-
"size-adjust": toPercentage(sizeAdjust),
|
|
46
|
-
"ascent-override": toPercentage(ascentOverride),
|
|
47
|
-
"descent-override": toPercentage(descentOverride),
|
|
48
|
-
"line-gap-override": toPercentage(lineGapOverride),
|
|
49
|
-
...properties
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
export {
|
|
53
|
-
generateFallbackFontFace,
|
|
54
|
-
readMetrics
|
|
55
|
-
};
|