full site update

This commit is contained in:
2025-07-24 18:46:24 +02:00
parent bfe2b90d8d
commit 37a6e0ab31
6912 changed files with 540482 additions and 361712 deletions

View File

@@ -0,0 +1,9 @@
import type { CssProperties, CssRenderer } from '../definitions.js';
export declare function renderFontFace(properties: CssProperties, minify: boolean): string;
export declare function renderCssVariable(key: string, values: Array<string>, minify: boolean): string;
export declare function withFamily(family: string, properties: CssProperties): CssProperties;
/** If the value contains spaces (which would be incorrectly interpreted), we wrap it in quotes. */
export declare function handleValueWithSpaces(value: string): string;
export declare function createMinifiableCssRenderer({ minify }: {
minify: boolean;
}): CssRenderer;

View File

@@ -0,0 +1,42 @@
function renderFontFace(properties, minify) {
const lf = minify ? "" : `
`;
const sp = minify ? "" : " ";
return `@font-face${sp}{${lf}${Object.entries(properties).filter(([, value]) => Boolean(value)).map(([key, value]) => `${sp}${sp}${key}:${sp}${value};`).join(lf)}${lf}}${lf}`;
}
function renderCssVariable(key, values, minify) {
const lf = minify ? "" : `
`;
const sp = minify ? "" : " ";
return `:root${sp}{${lf}${sp}${sp}${key}:${sp}${values.map((v) => handleValueWithSpaces(v)).join(`,${sp}`)};${lf}}${lf}`;
}
function withFamily(family, properties) {
return {
"font-family": handleValueWithSpaces(family),
...properties
};
}
const SPACE_RE = /\s/;
function handleValueWithSpaces(value) {
if (SPACE_RE.test(value)) {
return JSON.stringify(value);
}
return value;
}
function createMinifiableCssRenderer({ minify }) {
return {
generateFontFace(family, properties) {
return renderFontFace(withFamily(family, properties), minify);
},
generateCssVariable(key, values) {
return renderCssVariable(key, values, minify);
}
};
}
export {
createMinifiableCssRenderer,
handleValueWithSpaces,
renderCssVariable,
renderFontFace,
withFamily
};

View File

@@ -0,0 +1,3 @@
import type { DataCollector } from '../definitions.js';
import type { CreateUrlProxyParams } from '../types.js';
export declare function createDataCollector({ hasUrl, saveUrl, savePreload, saveFontData, }: Omit<CreateUrlProxyParams, 'local'>): DataCollector;

View File

@@ -0,0 +1,21 @@
function createDataCollector({
hasUrl,
saveUrl,
savePreload,
saveFontData
}) {
return {
collect({ hash, url, init, preload, data }) {
if (!hasUrl(hash)) {
saveUrl({ hash, url, init });
if (preload) {
savePreload(preload);
}
}
saveFontData({ hash, url, data, init });
}
};
}
export {
createDataCollector
};

View File

@@ -0,0 +1,2 @@
import type { ErrorHandler } from '../definitions.js';
export declare function createAstroErrorHandler(): ErrorHandler;

View File

@@ -0,0 +1,41 @@
import { AstroError, AstroErrorData } from "../../../core/errors/index.js";
function getProps(input) {
if (input.type === "cannot-load-font-provider") {
return {
...AstroErrorData.CannotLoadFontProvider,
message: AstroErrorData.CannotLoadFontProvider.message(input.data.entrypoint)
};
} else if (input.type === "unknown-fs-error") {
return AstroErrorData.UnknownFilesystemError;
} else if (input.type === "cannot-fetch-font-file") {
return {
...AstroErrorData.CannotFetchFontFile,
message: AstroErrorData.CannotFetchFontFile.message(input.data.url)
};
} else if (input.type === "cannot-extract-font-type") {
return {
...AstroErrorData.CannotExtractFontType,
message: AstroErrorData.CannotExtractFontType.message(input.data.url)
};
} else if (input.type === "cannot-extract-data") {
return {
...AstroErrorData.CannotDetermineWeightAndStyleFromFontFile,
message: AstroErrorData.CannotDetermineWeightAndStyleFromFontFile.message(
input.data.family,
input.data.url
)
};
}
input;
return AstroErrorData.UnknownError;
}
function createAstroErrorHandler() {
return {
handle(input) {
return new AstroError(getProps(input), { cause: input.cause });
}
};
}
export {
createAstroErrorHandler
};

View File

@@ -0,0 +1,8 @@
import type { Storage } from 'unstorage';
import type { ErrorHandler, FontFetcher } from '../definitions.js';
export declare function createCachedFontFetcher({ storage, errorHandler, fetch, readFile, }: {
storage: Storage;
errorHandler: ErrorHandler;
fetch: (url: string, init?: RequestInit) => Promise<Response>;
readFile: (url: string) => Promise<Buffer>;
}): FontFetcher;

View File

@@ -0,0 +1,34 @@
import { isAbsolute } from "node:path";
import { cache } from "../utils.js";
function createCachedFontFetcher({
storage,
errorHandler,
fetch,
readFile
}) {
return {
async fetch({ hash, url, init }) {
return await cache(storage, hash, async () => {
try {
if (isAbsolute(url)) {
return await readFile(url);
}
const response = await fetch(url, init ?? void 0);
if (!response.ok) {
throw new Error(`Response was not successful, received status code ${response.status}`);
}
return Buffer.from(await response.arrayBuffer());
} catch (cause) {
throw errorHandler.handle({
type: "cannot-fetch-font-file",
data: { url },
cause
});
}
});
}
};
}
export {
createCachedFontFetcher
};

View File

@@ -0,0 +1,4 @@
import type { ErrorHandler, FontFileReader } from '../definitions.js';
export declare function createFontaceFontFileReader({ errorHandler, }: {
errorHandler: ErrorHandler;
}): FontFileReader;

View File

@@ -0,0 +1,26 @@
import { readFileSync } from "node:fs";
import { fontace } from "fontace";
function createFontaceFontFileReader({
errorHandler
}) {
return {
extract({ family, url }) {
try {
const data = fontace(readFileSync(url));
return {
weight: data.weight,
style: data.style
};
} catch (cause) {
throw errorHandler.handle({
type: "cannot-extract-data",
data: { family, url },
cause
});
}
}
};
}
export {
createFontaceFontFileReader
};

View File

@@ -0,0 +1,5 @@
import type { CssRenderer, FontFetcher, FontMetricsResolver } from '../definitions.js';
export declare function createCapsizeFontMetricsResolver({ fontFetcher, cssRenderer, }: {
fontFetcher: FontFetcher;
cssRenderer: CssRenderer;
}): FontMetricsResolver;

View File

@@ -0,0 +1,60 @@
import { fromBuffer } from "@capsizecss/unpack";
import { renderFontSrc } from "../utils.js";
function filterRequiredMetrics({
ascent,
descent,
lineGap,
unitsPerEm,
xWidthAvg
}) {
return {
ascent,
descent,
lineGap,
unitsPerEm,
xWidthAvg
};
}
function toPercentage(value, fractionDigits = 4) {
const percentage = value * 100;
return `${+percentage.toFixed(fractionDigits)}%`;
}
function createCapsizeFontMetricsResolver({
fontFetcher,
cssRenderer
}) {
const cache = {};
return {
async getMetrics(name, input) {
cache[name] ??= filterRequiredMetrics(await fromBuffer(await fontFetcher.fetch(input)));
return cache[name];
},
// Source: https://github.com/unjs/fontaine/blob/f00f84032c5d5da72c8798eae4cd68d3ddfbf340/src/css.ts#L170
generateFontFace({
metrics,
fallbackMetrics,
name: fallbackName,
font: fallbackFontName,
properties
}) {
const preferredFontXAvgRatio = metrics.xWidthAvg / metrics.unitsPerEm;
const fallbackFontXAvgRatio = fallbackMetrics.xWidthAvg / fallbackMetrics.unitsPerEm;
const sizeAdjust = preferredFontXAvgRatio / fallbackFontXAvgRatio;
const adjustedEmSquare = metrics.unitsPerEm * sizeAdjust;
const ascentOverride = metrics.ascent / adjustedEmSquare;
const descentOverride = Math.abs(metrics.descent) / adjustedEmSquare;
const lineGapOverride = metrics.lineGap / adjustedEmSquare;
return cssRenderer.generateFontFace(fallbackName, {
...properties,
src: renderFontSrc([{ name: fallbackFontName }]),
"size-adjust": toPercentage(sizeAdjust),
"ascent-override": toPercentage(ascentOverride),
"descent-override": toPercentage(descentOverride),
"line-gap-override": toPercentage(lineGapOverride)
});
}
};
}
export {
createCapsizeFontMetricsResolver
};

View File

@@ -0,0 +1,4 @@
import type { ErrorHandler, FontTypeExtractor } from '../definitions.js';
export declare function createFontTypeExtractor({ errorHandler, }: {
errorHandler: ErrorHandler;
}): FontTypeExtractor;

View File

@@ -0,0 +1,22 @@
import { extname } from "node:path";
import { isFontType } from "../utils.js";
function createFontTypeExtractor({
errorHandler
}) {
return {
extract(url) {
const extension = extname(url).slice(1);
if (!isFontType(extension)) {
throw errorHandler.handle({
type: "cannot-extract-font-type",
data: { url },
cause: `Unexpected extension, got "${extension}"`
});
}
return extension;
}
};
}
export {
createFontTypeExtractor
};

View File

@@ -0,0 +1,2 @@
import type { Hasher } from '../definitions.js';
export declare function createXxHasher(): Promise<Hasher>;

View File

@@ -0,0 +1,14 @@
import xxhash from "xxhash-wasm";
import { sortObjectByKey } from "../utils.js";
async function createXxHasher() {
const { h64ToString: hashString } = await xxhash();
return {
hashString,
hashObject(input) {
return hashString(JSON.stringify(sortObjectByKey(input)));
}
};
}
export {
createXxHasher
};

View File

@@ -0,0 +1,5 @@
import type { LocalProviderUrlResolver } from '../definitions.js';
export declare function createRequireLocalProviderUrlResolver({ root, intercept, }: {
root: URL;
intercept?: (path: string) => void;
}): LocalProviderUrlResolver;

View File

@@ -0,0 +1,17 @@
import { fileURLToPath } from "node:url";
import { resolveEntrypoint } from "../utils.js";
function createRequireLocalProviderUrlResolver({
root,
intercept
}) {
return {
resolve(input) {
const path = fileURLToPath(resolveEntrypoint(root, input));
intercept?.(path);
return path;
}
};
}
export {
createRequireLocalProviderUrlResolver
};

View File

@@ -0,0 +1,6 @@
import type { ViteDevServer } from 'vite';
import type { RemoteFontProviderModResolver } from '../definitions.js';
export declare function createBuildRemoteFontProviderModResolver(): RemoteFontProviderModResolver;
export declare function createDevServerRemoteFontProviderModResolver({ server, }: {
server: ViteDevServer;
}): RemoteFontProviderModResolver;

View File

@@ -0,0 +1,20 @@
function createBuildRemoteFontProviderModResolver() {
return {
resolve(id) {
return import(id);
}
};
}
function createDevServerRemoteFontProviderModResolver({
server
}) {
return {
resolve(id) {
return server.ssrLoadModule(id);
}
};
}
export {
createBuildRemoteFontProviderModResolver,
createDevServerRemoteFontProviderModResolver
};

View File

@@ -0,0 +1,6 @@
import type { ErrorHandler, RemoteFontProviderModResolver, RemoteFontProviderResolver } from '../definitions.js';
export declare function createRemoteFontProviderResolver({ root, modResolver, errorHandler, }: {
root: URL;
modResolver: RemoteFontProviderModResolver;
errorHandler: ErrorHandler;
}): RemoteFontProviderResolver;

View File

@@ -0,0 +1,47 @@
import { resolveEntrypoint } from "../utils.js";
function validateMod({
mod,
entrypoint,
errorHandler
}) {
try {
if (typeof mod !== "object" || mod === null) {
throw new Error(`Expected an object for the module, but received ${typeof mod}.`);
}
if (typeof mod.provider !== "function") {
throw new Error(`Invalid provider export in module, expected a function.`);
}
return {
provider: mod.provider
};
} catch (cause) {
throw errorHandler.handle({
type: "cannot-load-font-provider",
data: {
entrypoint
},
cause
});
}
}
function createRemoteFontProviderResolver({
root,
modResolver,
errorHandler
}) {
return {
async resolve({ entrypoint, config }) {
const id = resolveEntrypoint(root, entrypoint.toString()).href;
const mod = await modResolver.resolve(id);
const { provider } = validateMod({
mod,
entrypoint: id,
errorHandler
});
return { config, provider };
}
};
}
export {
createRemoteFontProviderResolver
};

View File

@@ -0,0 +1,4 @@
import { type Storage } from 'unstorage';
export declare function createFsStorage({ base }: {
base: URL;
}): Storage;

View File

@@ -0,0 +1,14 @@
import { fileURLToPath } from "node:url";
import { createStorage } from "unstorage";
import fsLiteDriver from "unstorage/drivers/fs-lite";
function createFsStorage({ base }) {
return createStorage({
// Types are weirly exported
driver: fsLiteDriver({
base: fileURLToPath(base)
})
});
}
export {
createFsStorage
};

View File

@@ -0,0 +1,11 @@
import type { SystemFallbacksProvider } from '../definitions.js';
export declare const DEFAULT_FALLBACKS: {
serif: "Times New Roman"[];
'sans-serif': "Arial"[];
monospace: "Courier New"[];
'system-ui': ("Arial" | "BlinkMacSystemFont" | "Segoe UI" | "Roboto" | "Helvetica Neue")[];
'ui-serif': "Times New Roman"[];
'ui-sans-serif': "Arial"[];
'ui-monospace': "Courier New"[];
};
export declare function createSystemFallbacksProvider(): SystemFallbacksProvider;

View File

@@ -0,0 +1,74 @@
const SYSTEM_METRICS = {
"Times New Roman": {
ascent: 1825,
descent: -443,
lineGap: 87,
unitsPerEm: 2048,
xWidthAvg: 832
},
Arial: {
ascent: 1854,
descent: -434,
lineGap: 67,
unitsPerEm: 2048,
xWidthAvg: 913
},
"Courier New": {
ascent: 1705,
descent: -615,
lineGap: 0,
unitsPerEm: 2048,
xWidthAvg: 1229
},
BlinkMacSystemFont: {
ascent: 1980,
descent: -432,
lineGap: 0,
unitsPerEm: 2048,
xWidthAvg: 853
},
"Segoe UI": {
ascent: 2210,
descent: -514,
lineGap: 0,
unitsPerEm: 2048,
xWidthAvg: 908
},
Roboto: {
ascent: 1900,
descent: -500,
lineGap: 0,
unitsPerEm: 2048,
xWidthAvg: 911
},
"Helvetica Neue": {
ascent: 952,
descent: -213,
lineGap: 28,
unitsPerEm: 1e3,
xWidthAvg: 450
}
};
const DEFAULT_FALLBACKS = {
serif: ["Times New Roman"],
"sans-serif": ["Arial"],
monospace: ["Courier New"],
"system-ui": ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial"],
"ui-serif": ["Times New Roman"],
"ui-sans-serif": ["Arial"],
"ui-monospace": ["Courier New"]
};
function createSystemFallbacksProvider() {
return {
getLocalFonts(fallback) {
return DEFAULT_FALLBACKS[fallback] ?? null;
},
getMetricsForLocalFont(family) {
return SYSTEM_METRICS[family];
}
};
}
export {
DEFAULT_FALLBACKS,
createSystemFallbacksProvider
};

View File

@@ -0,0 +1,5 @@
import type { ErrorHandler, UrlProxyContentResolver } from '../definitions.js';
export declare function createLocalUrlProxyContentResolver({ errorHandler, }: {
errorHandler: ErrorHandler;
}): UrlProxyContentResolver;
export declare function createRemoteUrlProxyContentResolver(): UrlProxyContentResolver;

View File

@@ -0,0 +1,28 @@
import { readFileSync } from "node:fs";
function createLocalUrlProxyContentResolver({
errorHandler
}) {
return {
resolve(url) {
try {
return url + readFileSync(url, "utf-8");
} catch (cause) {
throw errorHandler.handle({
type: "unknown-fs-error",
data: {},
cause
});
}
}
};
}
function createRemoteUrlProxyContentResolver() {
return {
// Passthrough, the remote provider URL is enough
resolve: (url) => url
};
}
export {
createLocalUrlProxyContentResolver,
createRemoteUrlProxyContentResolver
};

View File

@@ -0,0 +1,7 @@
import type { DataCollector, Hasher, UrlProxy, UrlProxyContentResolver, UrlResolver } from '../definitions.js';
export declare function createUrlProxy({ contentResolver, hasher, dataCollector, urlResolver, }: {
contentResolver: UrlProxyContentResolver;
hasher: Hasher;
dataCollector: DataCollector;
urlResolver: UrlResolver;
}): UrlProxy;

View File

@@ -0,0 +1,24 @@
function createUrlProxy({
contentResolver,
hasher,
dataCollector,
urlResolver
}) {
return {
proxy({ url: originalUrl, type, data, collectPreload, init }) {
const hash = `${hasher.hashString(contentResolver.resolve(originalUrl))}.${type}`;
const url = urlResolver.resolve(hash);
dataCollector.collect({
url: originalUrl,
hash,
preload: collectPreload ? { url, type } : null,
data,
init
});
return url;
}
};
}
export {
createUrlProxy
};

View File

@@ -0,0 +1,9 @@
import type { AssetsPrefix } from '../../../types/public/index.js';
import type { UrlResolver } from '../definitions.js';
export declare function createDevUrlResolver({ base }: {
base: string;
}): UrlResolver;
export declare function createBuildUrlResolver({ base, assetsPrefix, }: {
base: string;
assetsPrefix: AssetsPrefix;
}): UrlResolver;

View File

@@ -0,0 +1,27 @@
import { fileExtension, joinPaths, prependForwardSlash } from "../../../core/path.js";
import { getAssetsPrefix } from "../../utils/getAssetsPrefix.js";
function createDevUrlResolver({ base }) {
return {
resolve(hash) {
return prependForwardSlash(joinPaths(base, hash));
}
};
}
function createBuildUrlResolver({
base,
assetsPrefix
}) {
return {
resolve(hash) {
const prefix = assetsPrefix ? getAssetsPrefix(fileExtension(hash), assetsPrefix) : void 0;
if (prefix) {
return joinPaths(prefix, base, hash);
}
return prependForwardSlash(joinPaths(base, hash));
}
};
}
export {
createBuildUrlResolver,
createDevUrlResolver
};