mirror of
https://github.com/withastro/astro.git
synced 2025-03-10 23:01:26 -05:00
feat(fonts): fallbacks (#13331)
* feat(fonts): fallbacks * feat: local * fix: test * feat: isGenericFontFamily test * feat: generateFallbackCSS test * feat: docs * feat: simplify * fix * feat: improve schema * Discard changes to examples/basics/astro.config.mjs * feat: address reviews
This commit is contained in:
parent
08eff8cd9e
commit
4eef143486
10 changed files with 532 additions and 42 deletions
|
@ -145,6 +145,7 @@
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"flattie": "^1.1.1",
|
"flattie": "^1.1.1",
|
||||||
|
"fontaine": "^0.5.0",
|
||||||
"github-slugger": "^2.0.0",
|
"github-slugger": "^2.0.0",
|
||||||
"html-escaper": "3.0.3",
|
"html-escaper": "3.0.3",
|
||||||
"http-cache-semantics": "^4.1.1",
|
"http-cache-semantics": "^4.1.1",
|
||||||
|
|
|
@ -8,7 +8,6 @@ export const DEFAULTS: ResolveFontOptions = {
|
||||||
weights: ['400'],
|
weights: ['400'],
|
||||||
styles: ['normal', 'italic'],
|
styles: ['normal', 'italic'],
|
||||||
subsets: ['cyrillic-ext', 'cyrillic', 'greek-ext', 'greek', 'vietnamese', 'latin-ext', 'latin'],
|
subsets: ['cyrillic-ext', 'cyrillic', 'greek-ext', 'greek', 'vietnamese', 'latin-ext', 'latin'],
|
||||||
fallbacks: undefined,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VIRTUAL_MODULE_ID = 'virtual:astro:assets/fonts/internal';
|
export const VIRTUAL_MODULE_ID = 'virtual:astro:assets/fonts/internal';
|
||||||
|
@ -19,3 +18,20 @@ export const URL_PREFIX = '/_astro/fonts/';
|
||||||
export const CACHE_DIR = './fonts/';
|
export const CACHE_DIR = './fonts/';
|
||||||
|
|
||||||
export const FONT_TYPES = ['woff2', 'woff', 'otf', 'ttf', 'eot'] as const;
|
export const FONT_TYPES = ['woff2', 'woff', 'otf', 'ttf', 'eot'] as const;
|
||||||
|
|
||||||
|
// Source: https://github.com/nuxt/fonts/blob/3a3eb6dfecc472242b3011b25f3fcbae237d0acc/src/module.ts#L55-L75
|
||||||
|
export const DEFAULT_FALLBACKS: Record<string, Array<string>> = {
|
||||||
|
serif: ['Times New Roman'],
|
||||||
|
'sans-serif': ['Arial'],
|
||||||
|
monospace: ['Courier New'],
|
||||||
|
cursive: [],
|
||||||
|
fantasy: [],
|
||||||
|
'system-ui': ['BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial'],
|
||||||
|
'ui-serif': ['Times New Roman'],
|
||||||
|
'ui-sans-serif': ['Arial'],
|
||||||
|
'ui-monospace': ['Courier New'],
|
||||||
|
'ui-rounded': [],
|
||||||
|
emoji: [],
|
||||||
|
math: [],
|
||||||
|
fangsong: [],
|
||||||
|
};
|
||||||
|
|
|
@ -28,15 +28,18 @@ export function resolveLocalFont(
|
||||||
for (const src of family.src) {
|
for (const src of family.src) {
|
||||||
for (const weight of src.weights ?? DEFAULTS.weights) {
|
for (const weight of src.weights ?? DEFAULTS.weights) {
|
||||||
for (const style of src.styles ?? DEFAULTS.styles) {
|
for (const style of src.styles ?? DEFAULTS.styles) {
|
||||||
// TODO: handle fallbacks?
|
|
||||||
// TODO: handle subset
|
// TODO: handle subset
|
||||||
fonts.push({
|
fonts.push({
|
||||||
weight,
|
weight,
|
||||||
style,
|
style,
|
||||||
src: src.paths.map((path) => ({
|
src: src.paths.map((path) => {
|
||||||
url: proxyURL(fileURLToPath(new URL(path, root))),
|
const originalURL = fileURLToPath(new URL(path, root));
|
||||||
format: extractFontType(path),
|
return {
|
||||||
})),
|
originalURL,
|
||||||
|
url: proxyURL(originalURL),
|
||||||
|
format: extractFontType(path),
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ interface FontFamilyAttributes extends Partial<ResolveFontOptions> {
|
||||||
provider: string;
|
provider: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocalFontFamily extends Pick<FontFamilyAttributes, 'name'> {
|
export interface LocalFontFamily extends Pick<FontFamilyAttributes, 'name' | 'fallbacks'> {
|
||||||
provider: LocalProviderName;
|
provider: LocalProviderName;
|
||||||
src: Array<Partial<ResolveFontOptions> & { paths: Array<string> }>;
|
src: Array<Partial<Omit<ResolveFontOptions, 'fallbacks'>> & { paths: Array<string> }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CommonFontFamily<TProvider extends string>
|
interface CommonFontFamily<TProvider extends string>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import type * as unifont from 'unifont';
|
import type * as unifont from 'unifont';
|
||||||
import type { FontType } from './types.js';
|
import type { FontType } from './types.js';
|
||||||
import { extname } from 'node:path';
|
import { extname } from 'node:path';
|
||||||
import { FONT_TYPES } from './constants.js';
|
import { DEFAULT_FALLBACKS, FONT_TYPES } from './constants.js';
|
||||||
import type { Storage } from 'unstorage';
|
import type { Storage } from 'unstorage';
|
||||||
|
import type * as fontaine from 'fontaine';
|
||||||
|
|
||||||
// TODO: expose all relevant options in config
|
// TODO: expose all relevant options in config
|
||||||
// Source: https://github.com/nuxt/fonts/blob/main/src/css/render.ts#L7-L21
|
// Source: https://github.com/nuxt/fonts/blob/main/src/css/render.ts#L7-L21
|
||||||
|
@ -81,7 +82,7 @@ export interface ProxyURLOptions {
|
||||||
value: string;
|
value: string;
|
||||||
/**
|
/**
|
||||||
* Specifies how the hash is computed. Can be based on the value,
|
* Specifies how the hash is computed. Can be based on the value,
|
||||||
* a specific string for testing etc
|
* a specific string for testing etc
|
||||||
*/
|
*/
|
||||||
hashString: (value: string) => string;
|
hashString: (value: string) => string;
|
||||||
/**
|
/**
|
||||||
|
@ -111,3 +112,76 @@ export function proxyURL({ value, hashString, collect }: ProxyURLOptions): strin
|
||||||
// Now that we collected the original url, we return our proxy so the consumer can override it
|
// Now that we collected the original url, we return our proxy so the consumer can override it
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isGenericFontFamily(str: string): str is keyof typeof DEFAULT_FALLBACKS {
|
||||||
|
return Object.keys(DEFAULT_FALLBACKS).includes(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
type FontFaceMetrics = Parameters<typeof fontaine.generateFontFace>[0];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates CSS for a given family fallbacks if possible.
|
||||||
|
*
|
||||||
|
* It works by trying to get metrics (using fontaine) of the provided font family.
|
||||||
|
* If some can be computed, they will be applied to the eligible fallbacks to match
|
||||||
|
* the original font shape as close as possible.
|
||||||
|
*/
|
||||||
|
export async function generateFallbacksCSS({
|
||||||
|
family,
|
||||||
|
fallbacks: _fallbacks,
|
||||||
|
fontURL,
|
||||||
|
getMetricsForFamily,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
|
generateFontFace,
|
||||||
|
}: {
|
||||||
|
/** The family name */
|
||||||
|
family: string;
|
||||||
|
/** The family fallbacks */
|
||||||
|
fallbacks: Array<string>;
|
||||||
|
/** A remote url or local filepath to a font file. Used if metrics can't be resolved purely from the family name */
|
||||||
|
fontURL: string | null;
|
||||||
|
getMetricsForFamily: (family: string, fontURL: string | null) => Promise<null | FontFaceMetrics>;
|
||||||
|
generateFontFace: typeof fontaine.generateFontFace;
|
||||||
|
}): Promise<null | { css: string; fallbacks: Array<string> }> {
|
||||||
|
// We avoid mutating the original array
|
||||||
|
let fallbacks = [..._fallbacks];
|
||||||
|
if (fallbacks.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let css = '';
|
||||||
|
|
||||||
|
// The last element of the fallbacks is usually a generic family name (eg. serif)
|
||||||
|
const lastFallback = fallbacks[fallbacks.length - 1];
|
||||||
|
// If it's not a generic family name, we can't infer local fonts to be used as fallbacks
|
||||||
|
if (!isGenericFontFamily(lastFallback)) {
|
||||||
|
return { css, fallbacks };
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a generic family name, we get the associated local fonts (eg. Arial)
|
||||||
|
const localFonts = DEFAULT_FALLBACKS[lastFallback];
|
||||||
|
// Some generic families do not have associated local fonts so we abort early
|
||||||
|
if (localFonts.length === 0) {
|
||||||
|
return { css, fallbacks };
|
||||||
|
}
|
||||||
|
|
||||||
|
const metrics = await getMetricsForFamily(family, fontURL);
|
||||||
|
if (!metrics) {
|
||||||
|
// If there are no metrics, we can't generate useful fallbacks
|
||||||
|
return { css, fallbacks };
|
||||||
|
}
|
||||||
|
|
||||||
|
// We prepend the fallbacks with the local fonts and we dedupe in case a local font is already provided
|
||||||
|
fallbacks = [...new Set([...localFonts, ...fallbacks])];
|
||||||
|
|
||||||
|
for (const fallback of localFonts) {
|
||||||
|
css += generateFontFace(metrics, {
|
||||||
|
font: fallback,
|
||||||
|
// TODO: support family.as
|
||||||
|
name: `${family} fallback: ${fallback}`,
|
||||||
|
metrics: (await getMetricsForFamily(fallback, null)) ?? undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { css, fallbacks };
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
proxyURL,
|
proxyURL,
|
||||||
extractFontType,
|
extractFontType,
|
||||||
type ProxyURLOptions,
|
type ProxyURLOptions,
|
||||||
|
generateFallbacksCSS,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
import {
|
import {
|
||||||
DEFAULTS,
|
DEFAULTS,
|
||||||
|
@ -31,6 +32,7 @@ import { readFile } from 'node:fs/promises';
|
||||||
import { createStorage } from 'unstorage';
|
import { createStorage } from 'unstorage';
|
||||||
import fsLiteDriver from 'unstorage/drivers/fs-lite';
|
import fsLiteDriver from 'unstorage/drivers/fs-lite';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import * as fontaine from 'fontaine';
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
settings: AstroSettings;
|
settings: AstroSettings;
|
||||||
|
@ -153,6 +155,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
let isBuild: boolean;
|
let isBuild: boolean;
|
||||||
let cache: CacheHandler | null = null;
|
let cache: CacheHandler | null = null;
|
||||||
|
|
||||||
|
// TODO: refactor to allow testing
|
||||||
async function initialize({ resolveMod, base }: { resolveMod: ResolveMod; base: URL }) {
|
async function initialize({ resolveMod, base }: { resolveMod: ResolveMod; base: URL }) {
|
||||||
const { h64ToString } = await xxhash();
|
const { h64ToString } = await xxhash();
|
||||||
|
|
||||||
|
@ -194,19 +197,19 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: investigate using fontaine for fallbacks
|
// TODO: refactor to avoid repetition
|
||||||
for (const family of families) {
|
for (const family of families) {
|
||||||
// Reset
|
// Reset
|
||||||
preloadData.length = 0;
|
preloadData.length = 0;
|
||||||
css = '';
|
css = '';
|
||||||
|
|
||||||
if (family.provider === LOCAL_PROVIDER_NAME) {
|
if (family.provider === LOCAL_PROVIDER_NAME) {
|
||||||
const { fonts, fallbacks } = resolveLocalFont(family, {
|
const { fonts } = resolveLocalFont(family, {
|
||||||
proxyURL: (value) => {
|
proxyURL: (value) => {
|
||||||
return proxyURL({
|
return proxyURL({
|
||||||
value,
|
value,
|
||||||
// We hash based on the filepath and the contents, since the user could replace
|
// We hash based on the filepath and the contents, since the user could replace
|
||||||
// a given font file with completely different contents.
|
// a given font file with completely different contents.
|
||||||
hashString: (v) => {
|
hashString: (v) => {
|
||||||
let content: string;
|
let content: string;
|
||||||
try {
|
try {
|
||||||
|
@ -224,15 +227,39 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
for (const data of fonts) {
|
for (const data of fonts) {
|
||||||
css += generateFontFace(family.name, data);
|
css += generateFontFace(family.name, data);
|
||||||
}
|
}
|
||||||
|
const urls = fonts
|
||||||
|
.flatMap((font) => font.src.map((src) => ('originalURL' in src ? src.originalURL : null)))
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
const fallbackData = await generateFallbacksCSS({
|
||||||
|
family: family.name,
|
||||||
|
fallbacks: family.fallbacks ?? [],
|
||||||
|
fontURL: urls.at(0) ?? null,
|
||||||
|
getMetricsForFamily: async (name, fontURL) => {
|
||||||
|
let metrics = await fontaine.getMetricsForFamily(name);
|
||||||
|
if (fontURL && !metrics) {
|
||||||
|
// TODO: investigate in using capsize directly (fromBlob) to be able to cache
|
||||||
|
metrics = await fontaine.readMetrics(fontURL);
|
||||||
|
}
|
||||||
|
return metrics;
|
||||||
|
},
|
||||||
|
generateFontFace: fontaine.generateFontFace,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fallbackData) {
|
||||||
|
css += fallbackData.css;
|
||||||
|
// TODO: generate css var
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const { fonts, fallbacks } = await resolveFont(
|
const { fonts } = await resolveFont(
|
||||||
family.name,
|
family.name,
|
||||||
// We do not merge the defaults, we only provide defaults as a fallback
|
// We do not merge the defaults, we only provide defaults as a fallback
|
||||||
{
|
{
|
||||||
weights: family.weights ?? DEFAULTS.weights,
|
weights: family.weights ?? DEFAULTS.weights,
|
||||||
styles: family.styles ?? DEFAULTS.styles,
|
styles: family.styles ?? DEFAULTS.styles,
|
||||||
subsets: family.subsets ?? DEFAULTS.subsets,
|
subsets: family.subsets ?? DEFAULTS.subsets,
|
||||||
fallbacks: family.fallbacks ?? DEFAULTS.fallbacks,
|
// No default fallback to be used here
|
||||||
|
fallbacks: family.fallbacks,
|
||||||
},
|
},
|
||||||
// By default, fontaine goes through all providers. We use a different approach
|
// By default, fontaine goes through all providers. We use a different approach
|
||||||
// where we specify a provider per font (default to google)
|
// where we specify a provider per font (default to google)
|
||||||
|
@ -244,6 +271,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
if ('name' in source) {
|
if ('name' in source) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
source.originalURL = source.url;
|
||||||
source.url = proxyURL({
|
source.url = proxyURL({
|
||||||
value: source.url,
|
value: source.url,
|
||||||
// We only use the url for hashing since the service returns urls with a hash already
|
// We only use the url for hashing since the service returns urls with a hash already
|
||||||
|
@ -254,6 +282,30 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
// TODO: support optional as prop
|
// TODO: support optional as prop
|
||||||
css += generateFontFace(family.name, data);
|
css += generateFontFace(family.name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const urls = fonts
|
||||||
|
.map((font) => font.src.map((src) => ('originalURL' in src ? src.originalURL : null)))
|
||||||
|
.flat()
|
||||||
|
.filter((url) => typeof url === 'string');
|
||||||
|
|
||||||
|
const fallbackData = await generateFallbacksCSS({
|
||||||
|
family: family.name,
|
||||||
|
fallbacks: family.fallbacks ?? [],
|
||||||
|
fontURL: urls.at(0) ?? null,
|
||||||
|
getMetricsForFamily: async (name, fontURL) => {
|
||||||
|
let metrics = await fontaine.getMetricsForFamily(name);
|
||||||
|
if (fontURL && !metrics) {
|
||||||
|
metrics = await fontaine.readMetrics(fontURL);
|
||||||
|
}
|
||||||
|
return metrics;
|
||||||
|
},
|
||||||
|
generateFontFace: fontaine.generateFontFace,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fallbackData) {
|
||||||
|
css += fallbackData.css;
|
||||||
|
// TODO: generate css var
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resolvedMap.set(family.name, { preloadData: [...preloadData], css });
|
resolvedMap.set(family.name, { preloadData: [...preloadData], css });
|
||||||
}
|
}
|
||||||
|
@ -285,7 +337,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
// as well as local paths for the local provider. We filter them to only keep the filepaths
|
// as well as local paths for the local provider. We filter them to only keep the filepaths
|
||||||
paths: [...hashToUrlMap!.values()].filter((url) => isAbsolute(url)),
|
paths: [...hashToUrlMap!.values()].filter((url) => isAbsolute(url)),
|
||||||
// Whenever a local font file is updated, we restart the server so the user always has an up to date
|
// Whenever a local font file is updated, we restart the server so the user always has an up to date
|
||||||
// version of the font file
|
// version of the font file
|
||||||
update: () => {
|
update: () => {
|
||||||
logger.info('assets', 'Font file updated');
|
logger.info('assets', 'Font file updated');
|
||||||
server.restart();
|
server.restart();
|
||||||
|
@ -356,18 +408,20 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: e });
|
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: e });
|
||||||
}
|
}
|
||||||
await Promise.all(
|
if (hashToUrlMap) {
|
||||||
Array.from(hashToUrlMap!.entries()).map(async ([hash, url]) => {
|
await Promise.all(
|
||||||
logManager.add(hash);
|
Array.from(hashToUrlMap.entries()).map(async ([hash, url]) => {
|
||||||
const { cached, data } = await cache!(hash, () => fetchFont(url));
|
logManager.add(hash);
|
||||||
logManager.remove(hash, cached);
|
const { cached, data } = await cache!(hash, () => fetchFont(url));
|
||||||
try {
|
logManager.remove(hash, cached);
|
||||||
writeFileSync(new URL(hash, fontsDir), data);
|
try {
|
||||||
} catch (e) {
|
writeFileSync(new URL(hash, fontsDir), data);
|
||||||
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: e });
|
} catch (e) {
|
||||||
}
|
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: e });
|
||||||
}),
|
}
|
||||||
);
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
hashToUrlMap = null;
|
hashToUrlMap = null;
|
||||||
cache = null;
|
cache = null;
|
||||||
|
|
|
@ -600,6 +600,8 @@ export const AstroConfigSchema = z.object({
|
||||||
}
|
}
|
||||||
return svgConfig;
|
return svgConfig;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// TODO: properly test everything
|
||||||
fonts: z
|
fonts: z
|
||||||
.object({
|
.object({
|
||||||
providers: z
|
providers: z
|
||||||
|
@ -635,10 +637,11 @@ export const AstroConfigSchema = z.object({
|
||||||
.object({
|
.object({
|
||||||
paths: z.array(z.string()).nonempty(),
|
paths: z.array(z.string()).nonempty(),
|
||||||
})
|
})
|
||||||
.merge(resolveFontOptionsSchema.partial())
|
.merge(resolveFontOptionsSchema.omit({ fallbacks: true }).partial())
|
||||||
.strict(),
|
.strict(),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
.merge(resolveFontOptionsSchema.pick({ fallbacks: true }).partial())
|
||||||
.strict(),
|
.strict(),
|
||||||
z
|
z
|
||||||
.object({
|
.object({
|
||||||
|
|
|
@ -106,16 +106,32 @@ describe('fonts providers', () => {
|
||||||
weight: '400',
|
weight: '400',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
src: [
|
src: [
|
||||||
{ url: '/_astro/fonts/foo.woff2', format: 'woff2' },
|
{
|
||||||
{ url: '/_astro/fonts/foo.ttf', format: 'ttf' },
|
originalURL: fileURLToPath(new URL('./src/fonts/foo.woff2', import.meta.url)),
|
||||||
|
url: '/_astro/fonts/foo.woff2',
|
||||||
|
format: 'woff2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
originalURL: fileURLToPath(new URL('./src/fonts/foo.ttf', import.meta.url)),
|
||||||
|
url: '/_astro/fonts/foo.ttf',
|
||||||
|
format: 'ttf',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
weight: '400',
|
weight: '400',
|
||||||
style: 'italic',
|
style: 'italic',
|
||||||
src: [
|
src: [
|
||||||
{ url: '/_astro/fonts/foo.woff2', format: 'woff2' },
|
{
|
||||||
{ url: '/_astro/fonts/foo.ttf', format: 'ttf' },
|
originalURL: fileURLToPath(new URL('./src/fonts/foo.woff2', import.meta.url)),
|
||||||
|
url: '/_astro/fonts/foo.woff2',
|
||||||
|
format: 'woff2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
originalURL: fileURLToPath(new URL('./src/fonts/foo.ttf', import.meta.url)),
|
||||||
|
url: '/_astro/fonts/foo.ttf',
|
||||||
|
format: 'ttf',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -143,12 +159,24 @@ describe('fonts providers', () => {
|
||||||
{
|
{
|
||||||
weight: '600',
|
weight: '600',
|
||||||
style: 'oblique',
|
style: 'oblique',
|
||||||
src: [{ url: '/_astro/fonts/bar.eot', format: 'eot' }],
|
src: [
|
||||||
|
{
|
||||||
|
originalURL: fileURLToPath(new URL('./src/fonts/bar.eot', import.meta.url)),
|
||||||
|
url: '/_astro/fonts/bar.eot',
|
||||||
|
format: 'eot',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
weight: '700',
|
weight: '700',
|
||||||
style: 'oblique',
|
style: 'oblique',
|
||||||
src: [{ url: '/_astro/fonts/bar.eot', format: 'eot' }],
|
src: [
|
||||||
|
{
|
||||||
|
originalURL: fileURLToPath(new URL('./src/fonts/bar.eot', import.meta.url)),
|
||||||
|
url: '/_astro/fonts/bar.eot',
|
||||||
|
format: 'eot',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
assert.deepStrictEqual(values, [fileURLToPath(new URL('./src/fonts/bar.eot', root))]);
|
assert.deepStrictEqual(values, [fileURLToPath(new URL('./src/fonts/bar.eot', root))]);
|
||||||
|
|
|
@ -6,6 +6,8 @@ import {
|
||||||
extractFontType,
|
extractFontType,
|
||||||
createCache,
|
createCache,
|
||||||
proxyURL,
|
proxyURL,
|
||||||
|
isGenericFontFamily,
|
||||||
|
generateFallbacksCSS,
|
||||||
} from '../../../../dist/assets/fonts/utils.js';
|
} from '../../../../dist/assets/fonts/utils.js';
|
||||||
|
|
||||||
function createSpyCache() {
|
function createSpyCache() {
|
||||||
|
@ -143,4 +145,156 @@ describe('fonts utils', () => {
|
||||||
value: '/home/documents/project/font.ttf',
|
value: '/home/documents/project/font.ttf',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('isGenericFontFamily()', () => {
|
||||||
|
assert.equal(isGenericFontFamily('serif'), true);
|
||||||
|
assert.equal(isGenericFontFamily('sans-serif'), true);
|
||||||
|
assert.equal(isGenericFontFamily('monospace'), true);
|
||||||
|
assert.equal(isGenericFontFamily('cursive'), true);
|
||||||
|
assert.equal(isGenericFontFamily('fantasy'), true);
|
||||||
|
assert.equal(isGenericFontFamily('system-ui'), true);
|
||||||
|
assert.equal(isGenericFontFamily('ui-serif'), true);
|
||||||
|
assert.equal(isGenericFontFamily('ui-sans-serif'), true);
|
||||||
|
assert.equal(isGenericFontFamily('ui-monospace'), true);
|
||||||
|
assert.equal(isGenericFontFamily('ui-rounded'), true);
|
||||||
|
assert.equal(isGenericFontFamily('emoji'), true);
|
||||||
|
assert.equal(isGenericFontFamily('math'), true);
|
||||||
|
assert.equal(isGenericFontFamily('fangsong'), true);
|
||||||
|
assert.equal(isGenericFontFamily(''), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('generateFallbacksCSS()', () => {
|
||||||
|
it('should return null if there are no fallbacks', async () => {
|
||||||
|
assert.equal(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: [],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => null,
|
||||||
|
generateFontFace: () => '',
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return fallbacks if there are no metrics', async () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: ['foo'],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => null,
|
||||||
|
generateFontFace: () => '',
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
css: '',
|
||||||
|
fallbacks: ['foo'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return fallbacks if there are metrics but no generic font family', async () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: ['foo'],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => ({
|
||||||
|
ascent: 0,
|
||||||
|
descent: 0,
|
||||||
|
lineGap: 0,
|
||||||
|
unitsPerEm: 0,
|
||||||
|
xWidthAvg: 0,
|
||||||
|
}),
|
||||||
|
generateFontFace: () => '',
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
css: '',
|
||||||
|
fallbacks: ['foo'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shold return fallbacks if the generic font family does not have fonts associated', async () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: ['emoji'],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => ({
|
||||||
|
ascent: 0,
|
||||||
|
descent: 0,
|
||||||
|
lineGap: 0,
|
||||||
|
unitsPerEm: 0,
|
||||||
|
xWidthAvg: 0,
|
||||||
|
}),
|
||||||
|
generateFontFace: () => '',
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
css: '',
|
||||||
|
fallbacks: ['emoji'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resolves fallbacks correctly', async () => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: ['foo', 'bar'],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => ({
|
||||||
|
ascent: 0,
|
||||||
|
descent: 0,
|
||||||
|
lineGap: 0,
|
||||||
|
unitsPerEm: 0,
|
||||||
|
xWidthAvg: 0,
|
||||||
|
}),
|
||||||
|
generateFontFace: (_metrics, fallback) => `[${fallback.font},${fallback.name}]`,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
css: '',
|
||||||
|
fallbacks: ['foo', 'bar'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: ['sans-serif', 'foo'],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => ({
|
||||||
|
ascent: 0,
|
||||||
|
descent: 0,
|
||||||
|
lineGap: 0,
|
||||||
|
unitsPerEm: 0,
|
||||||
|
xWidthAvg: 0,
|
||||||
|
}),
|
||||||
|
generateFontFace: (_metrics, fallback) => `[${fallback.font},${fallback.name}]`,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
css: '',
|
||||||
|
fallbacks: ['sans-serif', 'foo'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await generateFallbacksCSS({
|
||||||
|
family: 'Roboto',
|
||||||
|
fallbacks: ['foo', 'sans-serif'],
|
||||||
|
fontURL: null,
|
||||||
|
getMetricsForFamily: async () => ({
|
||||||
|
ascent: 0,
|
||||||
|
descent: 0,
|
||||||
|
lineGap: 0,
|
||||||
|
unitsPerEm: 0,
|
||||||
|
xWidthAvg: 0,
|
||||||
|
}),
|
||||||
|
generateFontFace: (_metrics, fallback) => `[${fallback.font},${fallback.name}]`,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
css: `[Arial,Roboto fallback: Arial]`,
|
||||||
|
fallbacks: ['Arial', 'foo', 'sans-serif'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
171
pnpm-lock.yaml
generated
171
pnpm-lock.yaml
generated
|
@ -538,6 +538,9 @@ importers:
|
||||||
flattie:
|
flattie:
|
||||||
specifier: ^1.1.1
|
specifier: ^1.1.1
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
|
fontaine:
|
||||||
|
specifier: ^0.5.0
|
||||||
|
version: 0.5.0
|
||||||
github-slugger:
|
github-slugger:
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
@ -6588,6 +6591,12 @@ packages:
|
||||||
resolution: {integrity: sha512-v9f+ueUOKkZCDKiCm0yxKtYgYNLD9zlKarNux0NSXOvNm94QEYL3RlMpGKgD2hq44pbF2qWqEmHnCvmk56kPJw==}
|
resolution: {integrity: sha512-v9f+ueUOKkZCDKiCm0yxKtYgYNLD9zlKarNux0NSXOvNm94QEYL3RlMpGKgD2hq44pbF2qWqEmHnCvmk56kPJw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@capsizecss/metrics@2.2.0':
|
||||||
|
resolution: {integrity: sha512-DkFIser1KbGxWyG2hhQQeCit72TnOQDx5pr9bkA7+XlIy7qv+4lYtslH3bidVxm2qkY2guAgypSIPYuQQuk70A==}
|
||||||
|
|
||||||
|
'@capsizecss/unpack@2.3.0':
|
||||||
|
resolution: {integrity: sha512-qkf9IoFIVTOkkpr8oZtCNSmubyWFCuPU4EOWO6J/rFPP5Ks2b1k1EHDSQRLwfokh6nCd7mJgBT2lhcuDCE6w4w==}
|
||||||
|
|
||||||
'@changesets/apply-release-plan@7.0.8':
|
'@changesets/apply-release-plan@7.0.8':
|
||||||
resolution: {integrity: sha512-qjMUj4DYQ1Z6qHawsn7S71SujrExJ+nceyKKyI9iB+M5p9lCL55afuEd6uLBPRpLGWQwkwvWegDHtwHJb1UjpA==}
|
resolution: {integrity: sha512-qjMUj4DYQ1Z6qHawsn7S71SujrExJ+nceyKKyI9iB+M5p9lCL55afuEd6uLBPRpLGWQwkwvWegDHtwHJb1UjpA==}
|
||||||
|
|
||||||
|
@ -8049,6 +8058,9 @@ packages:
|
||||||
svelte: ^5.0.0
|
svelte: ^5.0.0
|
||||||
vite: ^6.0.0
|
vite: ^6.0.0
|
||||||
|
|
||||||
|
'@swc/helpers@0.5.15':
|
||||||
|
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
|
||||||
|
|
||||||
'@tailwindcss/node@4.0.6':
|
'@tailwindcss/node@4.0.6':
|
||||||
resolution: {integrity: sha512-jb6E0WeSq7OQbVYcIJ6LxnZTeC4HjMvbzFBMCrQff4R50HBlo/obmYNk6V2GCUXDeqiXtvtrQgcIbT+/boB03Q==}
|
resolution: {integrity: sha512-jb6E0WeSq7OQbVYcIJ6LxnZTeC4HjMvbzFBMCrQff4R50HBlo/obmYNk6V2GCUXDeqiXtvtrQgcIbT+/boB03Q==}
|
||||||
|
|
||||||
|
@ -8744,6 +8756,9 @@ packages:
|
||||||
blake3-wasm@2.1.5:
|
blake3-wasm@2.1.5:
|
||||||
resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
|
resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
|
||||||
|
|
||||||
|
blob-to-buffer@1.2.9:
|
||||||
|
resolution: {integrity: sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==}
|
||||||
|
|
||||||
body-parser@1.20.3:
|
body-parser@1.20.3:
|
||||||
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
|
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
|
@ -8765,6 +8780,9 @@ packages:
|
||||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
brotli@1.3.3:
|
||||||
|
resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==}
|
||||||
|
|
||||||
browserslist@4.24.0:
|
browserslist@4.24.0:
|
||||||
resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==}
|
resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==}
|
||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
|
@ -8902,6 +8920,10 @@ packages:
|
||||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
clone@2.1.2:
|
||||||
|
resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
|
||||||
|
engines: {node: '>=0.8'}
|
||||||
|
|
||||||
clsx@2.1.1:
|
clsx@2.1.1:
|
||||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -9004,6 +9026,9 @@ packages:
|
||||||
cross-argv@2.0.0:
|
cross-argv@2.0.0:
|
||||||
resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==}
|
resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==}
|
||||||
|
|
||||||
|
cross-fetch@3.2.0:
|
||||||
|
resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==}
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
@ -9199,6 +9224,9 @@ packages:
|
||||||
devlop@1.1.0:
|
devlop@1.1.0:
|
||||||
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
|
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
|
||||||
|
|
||||||
|
dfa@1.2.0:
|
||||||
|
resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==}
|
||||||
|
|
||||||
didyoumean@1.2.2:
|
didyoumean@1.2.2:
|
||||||
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
||||||
|
|
||||||
|
@ -9667,6 +9695,12 @@ packages:
|
||||||
debug:
|
debug:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
fontaine@0.5.0:
|
||||||
|
resolution: {integrity: sha512-vPDSWKhVAfTx4hRKT777+N6Szh2pAosAuzLpbppZ6O3UdD/1m6OlHjNcC3vIbgkRTIcLjzySLHXzPeLO2rE8cA==}
|
||||||
|
|
||||||
|
fontkit@2.0.4:
|
||||||
|
resolution: {integrity: sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==}
|
||||||
|
|
||||||
foreground-child@3.3.0:
|
foreground-child@3.3.0:
|
||||||
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
@ -10348,6 +10382,9 @@ packages:
|
||||||
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
|
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
magic-regexp@0.8.0:
|
||||||
|
resolution: {integrity: sha512-lOSLWdE156csDYwCTIGiAymOLN7Epu/TU5e/oAnISZfU6qP+pgjkE+xbVjVn3yLPKN8n1G2yIAYTAM5KRk6/ow==}
|
||||||
|
|
||||||
magic-string@0.25.9:
|
magic-string@0.25.9:
|
||||||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||||
|
|
||||||
|
@ -10912,6 +10949,9 @@ packages:
|
||||||
package-manager-detector@0.2.8:
|
package-manager-detector@0.2.8:
|
||||||
resolution: {integrity: sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA==}
|
resolution: {integrity: sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA==}
|
||||||
|
|
||||||
|
pako@0.2.9:
|
||||||
|
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
||||||
|
|
||||||
pako@1.0.11:
|
pako@1.0.11:
|
||||||
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
||||||
|
|
||||||
|
@ -11431,6 +11471,10 @@ packages:
|
||||||
resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==}
|
resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==}
|
||||||
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
||||||
|
|
||||||
|
regexp-tree@0.1.27:
|
||||||
|
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
rehype-autolink-headings@7.1.0:
|
rehype-autolink-headings@7.1.0:
|
||||||
resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}
|
resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}
|
||||||
|
|
||||||
|
@ -11537,6 +11581,9 @@ packages:
|
||||||
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
|
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
|
||||||
|
restructure@3.0.2:
|
||||||
|
resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
|
||||||
|
|
||||||
retext-latin@4.0.0:
|
retext-latin@4.0.0:
|
||||||
resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==}
|
resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==}
|
||||||
|
|
||||||
|
@ -11972,6 +12019,9 @@ packages:
|
||||||
resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==}
|
resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
tiny-inflate@1.0.3:
|
||||||
|
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
||||||
|
|
||||||
tinybench@2.9.0:
|
tinybench@2.9.0:
|
||||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||||
|
|
||||||
|
@ -12052,8 +12102,8 @@ packages:
|
||||||
tslib@2.1.0:
|
tslib@2.1.0:
|
||||||
resolution: {integrity: sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==}
|
resolution: {integrity: sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==}
|
||||||
|
|
||||||
tslib@2.6.2:
|
tslib@2.8.1:
|
||||||
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
turbo-darwin-64@2.4.1:
|
turbo-darwin-64@2.4.1:
|
||||||
resolution: {integrity: sha512-oos3Gz5N6ol2/7+ys0wPENhl7ZzeVKIumn2BR7X2oE5dEPxNPDMOpKBwreU9ToCxM94e+uFTzKgjcUJpBqpTHA==}
|
resolution: {integrity: sha512-oos3Gz5N6ol2/7+ys0wPENhl7ZzeVKIumn2BR7X2oE5dEPxNPDMOpKBwreU9ToCxM94e+uFTzKgjcUJpBqpTHA==}
|
||||||
|
@ -12105,6 +12155,9 @@ packages:
|
||||||
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
type-level-regexp@0.1.17:
|
||||||
|
resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==}
|
||||||
|
|
||||||
types-react-dom@19.0.0-alpha.3:
|
types-react-dom@19.0.0-alpha.3:
|
||||||
resolution: {integrity: sha512-foCg3VSAoTLKBpU6FKgtHjOzqZVo7UVXfG/JnKM8imXq/+TvSGebj+KJlAVG6H1n+hiQtqpjHc+hk5FmZOJCqw==}
|
resolution: {integrity: sha512-foCg3VSAoTLKBpU6FKgtHjOzqZVo7UVXfG/JnKM8imXq/+TvSGebj+KJlAVG6H1n+hiQtqpjHc+hk5FmZOJCqw==}
|
||||||
|
|
||||||
|
@ -12165,6 +12218,12 @@ packages:
|
||||||
unenv@2.0.0-rc.1:
|
unenv@2.0.0-rc.1:
|
||||||
resolution: {integrity: sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg==}
|
resolution: {integrity: sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg==}
|
||||||
|
|
||||||
|
unicode-properties@1.4.1:
|
||||||
|
resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==}
|
||||||
|
|
||||||
|
unicode-trie@2.0.0:
|
||||||
|
resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
|
||||||
|
|
||||||
unicorn-magic@0.3.0:
|
unicorn-magic@0.3.0:
|
||||||
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
|
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
@ -12242,6 +12301,10 @@ packages:
|
||||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
unplugin@1.16.1:
|
||||||
|
resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
unstorage@1.14.4:
|
unstorage@1.14.4:
|
||||||
resolution: {integrity: sha512-1SYeamwuYeQJtJ/USE1x4l17LkmQBzg7deBJ+U9qOBoHo15d1cDxG4jM31zKRgF7pG0kirZy4wVMX6WL6Zoscg==}
|
resolution: {integrity: sha512-1SYeamwuYeQJtJ/USE1x4l17LkmQBzg7deBJ+U9qOBoHo15d1cDxG4jM31zKRgF7pG0kirZy4wVMX6WL6Zoscg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -12615,6 +12678,9 @@ packages:
|
||||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
webpack-virtual-modules@0.6.2:
|
||||||
|
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
||||||
|
|
||||||
whatwg-encoding@3.1.1:
|
whatwg-encoding@3.1.1:
|
||||||
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
|
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
@ -13186,6 +13252,16 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
tar: 6.2.1
|
tar: 6.2.1
|
||||||
|
|
||||||
|
'@capsizecss/metrics@2.2.0': {}
|
||||||
|
|
||||||
|
'@capsizecss/unpack@2.3.0':
|
||||||
|
dependencies:
|
||||||
|
blob-to-buffer: 1.2.9
|
||||||
|
cross-fetch: 3.2.0
|
||||||
|
fontkit: 2.0.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
|
||||||
'@changesets/apply-release-plan@7.0.8':
|
'@changesets/apply-release-plan@7.0.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@changesets/config': 3.0.5
|
'@changesets/config': 3.0.5
|
||||||
|
@ -13676,7 +13752,7 @@ snapshots:
|
||||||
|
|
||||||
'@emnapi/runtime@1.3.1':
|
'@emnapi/runtime@1.3.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.6.2
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)':
|
'@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)':
|
||||||
|
@ -14499,6 +14575,10 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@swc/helpers@0.5.15':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@tailwindcss/node@4.0.6':
|
'@tailwindcss/node@4.0.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
enhanced-resolve: 5.18.1
|
enhanced-resolve: 5.18.1
|
||||||
|
@ -15314,6 +15394,8 @@ snapshots:
|
||||||
|
|
||||||
blake3-wasm@2.1.5: {}
|
blake3-wasm@2.1.5: {}
|
||||||
|
|
||||||
|
blob-to-buffer@1.2.9: {}
|
||||||
|
|
||||||
body-parser@1.20.3:
|
body-parser@1.20.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes: 3.1.2
|
bytes: 3.1.2
|
||||||
|
@ -15357,6 +15439,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
fill-range: 7.1.1
|
fill-range: 7.1.1
|
||||||
|
|
||||||
|
brotli@1.3.3:
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
|
||||||
browserslist@4.24.0:
|
browserslist@4.24.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001667
|
caniuse-lite: 1.0.30001667
|
||||||
|
@ -15501,6 +15587,8 @@ snapshots:
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
wrap-ansi: 7.0.0
|
wrap-ansi: 7.0.0
|
||||||
|
|
||||||
|
clone@2.1.2: {}
|
||||||
|
|
||||||
clsx@2.1.1: {}
|
clsx@2.1.1: {}
|
||||||
|
|
||||||
collapse-white-space@2.1.0: {}
|
collapse-white-space@2.1.0: {}
|
||||||
|
@ -15576,6 +15664,12 @@ snapshots:
|
||||||
|
|
||||||
cross-argv@2.0.0: {}
|
cross-argv@2.0.0: {}
|
||||||
|
|
||||||
|
cross-fetch@3.2.0:
|
||||||
|
dependencies:
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key: 3.1.1
|
path-key: 3.1.1
|
||||||
|
@ -15725,6 +15819,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
dequal: 2.0.3
|
dequal: 2.0.3
|
||||||
|
|
||||||
|
dfa@1.2.0: {}
|
||||||
|
|
||||||
didyoumean@1.2.2: {}
|
didyoumean@1.2.2: {}
|
||||||
|
|
||||||
diff@5.2.0: {}
|
diff@5.2.0: {}
|
||||||
|
@ -16234,6 +16330,30 @@ snapshots:
|
||||||
|
|
||||||
follow-redirects@1.15.9: {}
|
follow-redirects@1.15.9: {}
|
||||||
|
|
||||||
|
fontaine@0.5.0:
|
||||||
|
dependencies:
|
||||||
|
'@capsizecss/metrics': 2.2.0
|
||||||
|
'@capsizecss/unpack': 2.3.0
|
||||||
|
magic-regexp: 0.8.0
|
||||||
|
magic-string: 0.30.17
|
||||||
|
pathe: 1.1.2
|
||||||
|
ufo: 1.5.4
|
||||||
|
unplugin: 1.16.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
|
||||||
|
fontkit@2.0.4:
|
||||||
|
dependencies:
|
||||||
|
'@swc/helpers': 0.5.15
|
||||||
|
brotli: 1.3.3
|
||||||
|
clone: 2.1.2
|
||||||
|
dfa: 1.2.0
|
||||||
|
fast-deep-equal: 3.1.3
|
||||||
|
restructure: 3.0.2
|
||||||
|
tiny-inflate: 1.0.3
|
||||||
|
unicode-properties: 1.4.1
|
||||||
|
unicode-trie: 2.0.0
|
||||||
|
|
||||||
foreground-child@3.3.0:
|
foreground-child@3.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
|
@ -17000,7 +17120,7 @@ snapshots:
|
||||||
|
|
||||||
lower-case@2.0.2:
|
lower-case@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.6.2
|
tslib: 2.8.1
|
||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
|
@ -17010,6 +17130,16 @@ snapshots:
|
||||||
|
|
||||||
lz-string@1.5.0: {}
|
lz-string@1.5.0: {}
|
||||||
|
|
||||||
|
magic-regexp@0.8.0:
|
||||||
|
dependencies:
|
||||||
|
estree-walker: 3.0.3
|
||||||
|
magic-string: 0.30.17
|
||||||
|
mlly: 1.7.4
|
||||||
|
regexp-tree: 0.1.27
|
||||||
|
type-level-regexp: 0.1.17
|
||||||
|
ufo: 1.5.4
|
||||||
|
unplugin: 1.16.1
|
||||||
|
|
||||||
magic-string@0.25.9:
|
magic-string@0.25.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
sourcemap-codec: 1.4.8
|
sourcemap-codec: 1.4.8
|
||||||
|
@ -17654,7 +17784,7 @@ snapshots:
|
||||||
no-case@3.0.4:
|
no-case@3.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
lower-case: 2.0.2
|
lower-case: 2.0.2
|
||||||
tslib: 2.6.2
|
tslib: 2.8.1
|
||||||
|
|
||||||
node-addon-api@7.1.1:
|
node-addon-api@7.1.1:
|
||||||
optional: true
|
optional: true
|
||||||
|
@ -17829,6 +17959,8 @@ snapshots:
|
||||||
|
|
||||||
package-manager-detector@0.2.8: {}
|
package-manager-detector@0.2.8: {}
|
||||||
|
|
||||||
|
pako@0.2.9: {}
|
||||||
|
|
||||||
pako@1.0.11: {}
|
pako@1.0.11: {}
|
||||||
|
|
||||||
parent-module@1.0.1:
|
parent-module@1.0.1:
|
||||||
|
@ -17879,7 +18011,7 @@ snapshots:
|
||||||
pascal-case@3.1.2:
|
pascal-case@3.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
no-case: 3.0.4
|
no-case: 3.0.4
|
||||||
tslib: 2.6.2
|
tslib: 2.8.1
|
||||||
|
|
||||||
path-browserify@1.0.1: {}
|
path-browserify@1.0.1: {}
|
||||||
|
|
||||||
|
@ -18381,6 +18513,8 @@ snapshots:
|
||||||
'@eslint-community/regexpp': 4.12.1
|
'@eslint-community/regexpp': 4.12.1
|
||||||
refa: 0.12.1
|
refa: 0.12.1
|
||||||
|
|
||||||
|
regexp-tree@0.1.27: {}
|
||||||
|
|
||||||
rehype-autolink-headings@7.1.0:
|
rehype-autolink-headings@7.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
|
@ -18571,6 +18705,8 @@ snapshots:
|
||||||
onetime: 5.1.2
|
onetime: 5.1.2
|
||||||
signal-exit: 3.0.7
|
signal-exit: 3.0.7
|
||||||
|
|
||||||
|
restructure@3.0.2: {}
|
||||||
|
|
||||||
retext-latin@4.0.0:
|
retext-latin@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/nlcst': 2.0.3
|
'@types/nlcst': 2.0.3
|
||||||
|
@ -19145,6 +19281,8 @@ snapshots:
|
||||||
|
|
||||||
timestring@6.0.0: {}
|
timestring@6.0.0: {}
|
||||||
|
|
||||||
|
tiny-inflate@1.0.3: {}
|
||||||
|
|
||||||
tinybench@2.9.0: {}
|
tinybench@2.9.0: {}
|
||||||
|
|
||||||
tinyexec@0.3.2: {}
|
tinyexec@0.3.2: {}
|
||||||
|
@ -19203,7 +19341,7 @@ snapshots:
|
||||||
|
|
||||||
tslib@2.1.0: {}
|
tslib@2.1.0: {}
|
||||||
|
|
||||||
tslib@2.6.2: {}
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
turbo-darwin-64@2.4.1:
|
turbo-darwin-64@2.4.1:
|
||||||
optional: true
|
optional: true
|
||||||
|
@ -19245,6 +19383,8 @@ snapshots:
|
||||||
media-typer: 0.3.0
|
media-typer: 0.3.0
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
|
type-level-regexp@0.1.17: {}
|
||||||
|
|
||||||
types-react-dom@19.0.0-alpha.3:
|
types-react-dom@19.0.0-alpha.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.18
|
'@types/react': 18.3.18
|
||||||
|
@ -19307,6 +19447,16 @@ snapshots:
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
ufo: 1.5.4
|
ufo: 1.5.4
|
||||||
|
|
||||||
|
unicode-properties@1.4.1:
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
unicode-trie: 2.0.0
|
||||||
|
|
||||||
|
unicode-trie@2.0.0:
|
||||||
|
dependencies:
|
||||||
|
pako: 0.2.9
|
||||||
|
tiny-inflate: 1.0.3
|
||||||
|
|
||||||
unicorn-magic@0.3.0: {}
|
unicorn-magic@0.3.0: {}
|
||||||
|
|
||||||
unified@11.0.5:
|
unified@11.0.5:
|
||||||
|
@ -19408,6 +19558,11 @@ snapshots:
|
||||||
|
|
||||||
unpipe@1.0.0: {}
|
unpipe@1.0.0: {}
|
||||||
|
|
||||||
|
unplugin@1.16.1:
|
||||||
|
dependencies:
|
||||||
|
acorn: 8.14.0
|
||||||
|
webpack-virtual-modules: 0.6.2
|
||||||
|
|
||||||
unstorage@1.14.4(@netlify/blobs@8.1.0):
|
unstorage@1.14.4(@netlify/blobs@8.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
anymatch: 3.1.3
|
anymatch: 3.1.3
|
||||||
|
@ -19760,6 +19915,8 @@ snapshots:
|
||||||
|
|
||||||
webidl-conversions@7.0.0: {}
|
webidl-conversions@7.0.0: {}
|
||||||
|
|
||||||
|
webpack-virtual-modules@0.6.2: {}
|
||||||
|
|
||||||
whatwg-encoding@3.1.1:
|
whatwg-encoding@3.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
iconv-lite: 0.6.3
|
iconv-lite: 0.6.3
|
||||||
|
|
Loading…
Add table
Reference in a new issue