blank project

This commit is contained in:
root
2025-10-17 20:17:33 +00:00
commit 14b2d53e8e
9366 changed files with 1515019 additions and 0 deletions

16
node_modules/astro/dist/actions/consts.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
export declare const ACTIONS_TYPES_FILE = "actions.d.ts";
export declare const VIRTUAL_MODULE_ID = "astro:actions";
/** Used to expose shared utilities, with server or client specific implementations */
export declare const RUNTIME_VIRTUAL_MODULE_ID = "virtual:astro:actions/runtime";
export declare const RESOLVED_RUNTIME_VIRTUAL_MODULE_ID: string;
export declare const ENTRYPOINT_VIRTUAL_MODULE_ID = "virtual:astro:actions/entrypoint";
export declare const RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID: string;
/** Used to pass data from the config to the main virtual module */
export declare const OPTIONS_VIRTUAL_MODULE_ID = "virtual:astro:actions/options";
export declare const RESOLVED_OPTIONS_VIRTUAL_MODULE_ID: string;
export declare const RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID = "\0virtual:astro:actions/noop-entrypoint";
export declare const ACTION_QUERY_PARAMS: {
actionName: string;
actionPayload: string;
};
export declare const ACTION_RPC_ROUTE_PATTERN = "/_actions/[...path]";

27
node_modules/astro/dist/actions/consts.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
const ACTIONS_TYPES_FILE = "actions.d.ts";
const VIRTUAL_MODULE_ID = "astro:actions";
const RUNTIME_VIRTUAL_MODULE_ID = "virtual:astro:actions/runtime";
const RESOLVED_RUNTIME_VIRTUAL_MODULE_ID = "\0" + RUNTIME_VIRTUAL_MODULE_ID;
const ENTRYPOINT_VIRTUAL_MODULE_ID = "virtual:astro:actions/entrypoint";
const RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID = "\0" + ENTRYPOINT_VIRTUAL_MODULE_ID;
const OPTIONS_VIRTUAL_MODULE_ID = "virtual:astro:actions/options";
const RESOLVED_OPTIONS_VIRTUAL_MODULE_ID = "\0" + OPTIONS_VIRTUAL_MODULE_ID;
const RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID = "\0virtual:astro:actions/noop-entrypoint";
const ACTION_QUERY_PARAMS = {
actionName: "_action",
actionPayload: "_astroActionPayload"
};
const ACTION_RPC_ROUTE_PATTERN = "/_actions/[...path]";
export {
ACTIONS_TYPES_FILE,
ACTION_QUERY_PARAMS,
ACTION_RPC_ROUTE_PATTERN,
ENTRYPOINT_VIRTUAL_MODULE_ID,
OPTIONS_VIRTUAL_MODULE_ID,
RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID,
RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID,
RESOLVED_OPTIONS_VIRTUAL_MODULE_ID,
RESOLVED_RUNTIME_VIRTUAL_MODULE_ID,
RUNTIME_VIRTUAL_MODULE_ID,
VIRTUAL_MODULE_ID
};

10
node_modules/astro/dist/actions/integration.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import type { AstroSettings } from '../types/astro.js';
import type { AstroIntegration } from '../types/public/integrations.js';
/**
* This integration is applied when the user is using Actions in their project.
* It will inject the necessary routes and middlewares to handle actions.
*/
export default function astroIntegrationActionsRouteHandler({ settings, filename, }: {
settings: AstroSettings;
filename: string;
}): AstroIntegration;

43
node_modules/astro/dist/actions/integration.js generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import { AstroError } from "../core/errors/errors.js";
import { ActionsWithoutServerOutputError } from "../core/errors/errors-data.js";
import { viteID } from "../core/util.js";
import { ACTION_RPC_ROUTE_PATTERN, ACTIONS_TYPES_FILE, VIRTUAL_MODULE_ID } from "./consts.js";
function astroIntegrationActionsRouteHandler({
settings,
filename
}) {
return {
name: VIRTUAL_MODULE_ID,
hooks: {
async "astro:config:setup"() {
settings.injectedRoutes.push({
pattern: ACTION_RPC_ROUTE_PATTERN,
entrypoint: "astro/actions/runtime/route.js",
prerender: false,
origin: "internal"
});
},
"astro:config:done": async (params) => {
if (params.buildOutput === "static") {
const error = new AstroError(ActionsWithoutServerOutputError);
error.stack = void 0;
throw error;
}
const stringifiedActionsImport = JSON.stringify(
viteID(new URL(`./${filename}`, params.config.srcDir))
);
settings.injectedTypes.push({
filename: ACTIONS_TYPES_FILE,
content: `declare module "astro:actions" {
type Actions = typeof import(${stringifiedActionsImport})["server"];
export const actions: Actions;
}`
});
}
}
};
}
export {
astroIntegrationActionsRouteHandler as default
};

8
node_modules/astro/dist/actions/loadActions.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import type { SSRActions } from '../core/app/types.js';
import type { ModuleLoader } from '../core/module-loader/index.js';
/**
* It accepts a module loader and the astro settings, and it attempts to load the middlewares defined in the configuration.
*
* If not middlewares were not set, the function returns an empty array.
*/
export declare function loadActions(moduleLoader: ModuleLoader): Promise<SSRActions>;

13
node_modules/astro/dist/actions/loadActions.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import { ActionsCantBeLoaded } from "../core/errors/errors-data.js";
import { AstroError } from "../core/errors/index.js";
import { ENTRYPOINT_VIRTUAL_MODULE_ID } from "./consts.js";
async function loadActions(moduleLoader) {
try {
return await moduleLoader.import(ENTRYPOINT_VIRTUAL_MODULE_ID);
} catch (error) {
throw new AstroError(ActionsCantBeLoaded, { cause: error });
}
}
export {
loadActions
};

2
node_modules/astro/dist/actions/noop-actions.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import type { SSRActions } from '../core/app/types.js';
export declare const NOOP_ACTIONS_MOD: SSRActions;

6
node_modules/astro/dist/actions/noop-actions.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
const NOOP_ACTIONS_MOD = {
server: {}
};
export {
NOOP_ACTIONS_MOD
};

3
node_modules/astro/dist/actions/runtime/client.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export * from './shared.js';
export declare function defineAction(): void;
export declare function getActionContext(): void;

11
node_modules/astro/dist/actions/runtime/client.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
export * from "./shared.js";
function defineAction() {
throw new Error("[astro:action] `defineAction()` unexpectedly used on the client.");
}
function getActionContext() {
throw new Error("[astro:action] `getActionContext()` unexpectedly used on the client.");
}
export {
defineAction,
getActionContext
};

2
node_modules/astro/dist/actions/runtime/route.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import type { APIRoute } from '../../types/public/common.js';
export declare const POST: APIRoute;

23
node_modules/astro/dist/actions/runtime/route.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import { getActionContext } from "./server.js";
const POST = async (context) => {
const { action, serializeActionResult } = getActionContext(context);
if (action?.calledFrom !== "rpc") {
return new Response("Not found", { status: 404 });
}
const result = await action.handler();
const serialized = serializeActionResult(result);
if (serialized.type === "empty") {
return new Response(null, {
status: serialized.status
});
}
return new Response(serialized.body, {
status: serialized.status,
headers: {
"Content-Type": serialized.contentType
}
});
};
export {
POST
};

50
node_modules/astro/dist/actions/runtime/server.d.ts generated vendored Normal file
View File

@@ -0,0 +1,50 @@
import { z } from 'zod';
import type { APIContext } from '../../types/public/index.js';
import { deserializeActionResult, type SafeResult, type SerializedActionResult, serializeActionResult } from './shared.js';
import { type ActionAPIContext, type ErrorInferenceObject, type MaybePromise } from './utils.js';
export * from './shared.js';
export type ActionAccept = 'form' | 'json';
export type ActionHandler<TInputSchema, TOutput> = TInputSchema extends z.ZodType ? (input: z.infer<TInputSchema>, context: ActionAPIContext) => MaybePromise<TOutput> : (input: any, context: ActionAPIContext) => MaybePromise<TOutput>;
export type ActionReturnType<T extends ActionHandler<any, any>> = Awaited<ReturnType<T>>;
export type ActionClient<TOutput, TAccept extends ActionAccept | undefined, TInputSchema extends z.ZodType | undefined> = TInputSchema extends z.ZodType ? ((input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<SafeResult<z.input<TInputSchema> extends ErrorInferenceObject ? z.input<TInputSchema> : ErrorInferenceObject, Awaited<TOutput>>>) & {
queryString: string;
orThrow: (input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<Awaited<TOutput>>;
} : ((input?: any) => Promise<SafeResult<never, Awaited<TOutput>>>) & {
orThrow: (input?: any) => Promise<Awaited<TOutput>>;
};
export declare function defineAction<TOutput, TAccept extends ActionAccept | undefined = undefined, TInputSchema extends z.ZodType | undefined = TAccept extends 'form' ? z.ZodType<FormData> : undefined>({ accept, input: inputSchema, handler, }: {
input?: TInputSchema;
accept?: TAccept;
handler: ActionHandler<TInputSchema, TOutput>;
}): ActionClient<TOutput, TAccept, TInputSchema> & string;
/** Transform form data to an object based on a Zod schema. */
export declare function formDataToObject<T extends z.AnyZodObject>(formData: FormData, schema: T): Record<string, unknown>;
export type AstroActionContext = {
/** Information about an incoming action request. */
action?: {
/** Whether an action was called using an RPC function or by using an HTML form action. */
calledFrom: 'rpc' | 'form';
/** The name of the action. Useful to track the source of an action result during a redirect. */
name: string;
/** Programmatically call the action to get the result. */
handler: () => Promise<SafeResult<any, any>>;
};
/**
* Manually set the action result accessed via `getActionResult()`.
* Calling this function from middleware will disable Astro's own action result handling.
*/
setActionResult(actionName: string, actionResult: SerializedActionResult): void;
/**
* Serialize an action result to stored in a cookie or session.
* Also used to pass a result to Astro templates via `setActionResult()`.
*/
serializeActionResult: typeof serializeActionResult;
/**
* Deserialize an action result to access data and error objects.
*/
deserializeActionResult: typeof deserializeActionResult;
};
/**
* Access information about Action requests from middleware.
*/
export declare function getActionContext(context: APIContext): AstroActionContext;

217
node_modules/astro/dist/actions/runtime/server.js generated vendored Normal file
View File

@@ -0,0 +1,217 @@
import { z } from "zod";
import { shouldAppendForwardSlash } from "../../core/build/util.js";
import { AstroError } from "../../core/errors/errors.js";
import { ActionCalledFromServerError } from "../../core/errors/errors-data.js";
import { removeTrailingForwardSlash } from "../../core/path.js";
import { apiContextRoutesSymbol } from "../../core/render-context.js";
import { ACTION_RPC_ROUTE_PATTERN } from "../consts.js";
import {
ACTION_QUERY_PARAMS,
ActionError,
ActionInputError,
callSafely,
deserializeActionResult,
serializeActionResult
} from "./shared.js";
import {
ACTION_API_CONTEXT_SYMBOL,
formContentTypes,
hasContentType,
isActionAPIContext
} from "./utils.js";
export * from "./shared.js";
function defineAction({
accept,
input: inputSchema,
handler
}) {
const serverHandler = accept === "form" ? getFormServerHandler(handler, inputSchema) : getJsonServerHandler(handler, inputSchema);
async function safeServerHandler(unparsedInput) {
if (typeof this === "function" || !isActionAPIContext(this)) {
throw new AstroError(ActionCalledFromServerError);
}
return callSafely(() => serverHandler(unparsedInput, this));
}
Object.assign(safeServerHandler, {
orThrow(unparsedInput) {
if (typeof this === "function") {
throw new AstroError(ActionCalledFromServerError);
}
return serverHandler(unparsedInput, this);
}
});
return safeServerHandler;
}
function getFormServerHandler(handler, inputSchema) {
return async (unparsedInput, context) => {
if (!(unparsedInput instanceof FormData)) {
throw new ActionError({
code: "UNSUPPORTED_MEDIA_TYPE",
message: "This action only accepts FormData."
});
}
if (!inputSchema) return await handler(unparsedInput, context);
const baseSchema = unwrapBaseObjectSchema(inputSchema, unparsedInput);
const parsed = await inputSchema.safeParseAsync(
baseSchema instanceof z.ZodObject ? formDataToObject(unparsedInput, baseSchema) : unparsedInput
);
if (!parsed.success) {
throw new ActionInputError(parsed.error.issues);
}
return await handler(parsed.data, context);
};
}
function getJsonServerHandler(handler, inputSchema) {
return async (unparsedInput, context) => {
if (unparsedInput instanceof FormData) {
throw new ActionError({
code: "UNSUPPORTED_MEDIA_TYPE",
message: "This action only accepts JSON."
});
}
if (!inputSchema) return await handler(unparsedInput, context);
const parsed = await inputSchema.safeParseAsync(unparsedInput);
if (!parsed.success) {
throw new ActionInputError(parsed.error.issues);
}
return await handler(parsed.data, context);
};
}
function formDataToObject(formData, schema) {
const obj = schema._def.unknownKeys === "passthrough" ? Object.fromEntries(formData.entries()) : {};
for (const [key, baseValidator] of Object.entries(schema.shape)) {
let validator = baseValidator;
while (validator instanceof z.ZodOptional || validator instanceof z.ZodNullable || validator instanceof z.ZodDefault) {
if (validator instanceof z.ZodDefault && !formData.has(key)) {
obj[key] = validator._def.defaultValue();
}
validator = validator._def.innerType;
}
if (!formData.has(key) && key in obj) {
continue;
} else if (validator instanceof z.ZodBoolean) {
const val = formData.get(key);
obj[key] = val === "true" ? true : val === "false" ? false : formData.has(key);
} else if (validator instanceof z.ZodArray) {
obj[key] = handleFormDataGetAll(key, formData, validator);
} else {
obj[key] = handleFormDataGet(key, formData, validator, baseValidator);
}
}
return obj;
}
function handleFormDataGetAll(key, formData, validator) {
const entries = Array.from(formData.getAll(key));
const elementValidator = validator._def.type;
if (elementValidator instanceof z.ZodNumber) {
return entries.map(Number);
} else if (elementValidator instanceof z.ZodBoolean) {
return entries.map(Boolean);
}
return entries;
}
function handleFormDataGet(key, formData, validator, baseValidator) {
const value = formData.get(key);
if (!value) {
return baseValidator instanceof z.ZodOptional ? void 0 : null;
}
return validator instanceof z.ZodNumber ? Number(value) : value;
}
function unwrapBaseObjectSchema(schema, unparsedInput) {
while (schema instanceof z.ZodEffects || schema instanceof z.ZodPipeline) {
if (schema instanceof z.ZodEffects) {
schema = schema._def.schema;
}
if (schema instanceof z.ZodPipeline) {
schema = schema._def.in;
}
}
if (schema instanceof z.ZodDiscriminatedUnion) {
const typeKey = schema._def.discriminator;
const typeValue = unparsedInput.get(typeKey);
if (typeof typeValue !== "string") return schema;
const objSchema = schema._def.optionsMap.get(typeValue);
if (!objSchema) return schema;
return objSchema;
}
return schema;
}
function getActionContext(context) {
const callerInfo = getCallerInfo(context);
const actionResultAlreadySet = Boolean(context.locals._actionPayload);
let action = void 0;
if (callerInfo && context.request.method === "POST" && !actionResultAlreadySet) {
action = {
calledFrom: callerInfo.from,
name: callerInfo.name,
handler: async () => {
const pipeline = Reflect.get(context, apiContextRoutesSymbol);
const callerInfoName = shouldAppendForwardSlash(
pipeline.manifest.trailingSlash,
pipeline.manifest.buildFormat
) ? removeTrailingForwardSlash(callerInfo.name) : callerInfo.name;
const baseAction = await pipeline.getAction(callerInfoName);
let input;
try {
input = await parseRequestBody(context.request);
} catch (e) {
if (e instanceof TypeError) {
return { data: void 0, error: new ActionError({ code: "UNSUPPORTED_MEDIA_TYPE" }) };
}
throw e;
}
const omitKeys = ["props", "getActionResult", "callAction", "redirect"];
const actionAPIContext = Object.create(
Object.getPrototypeOf(context),
Object.fromEntries(
Object.entries(Object.getOwnPropertyDescriptors(context)).filter(
([key]) => !omitKeys.includes(key)
)
)
);
Reflect.set(actionAPIContext, ACTION_API_CONTEXT_SYMBOL, true);
const handler = baseAction.bind(actionAPIContext);
return handler(input);
}
};
}
function setActionResult(actionName, actionResult) {
context.locals._actionPayload = {
actionResult,
actionName
};
}
return {
action,
setActionResult,
serializeActionResult,
deserializeActionResult
};
}
function getCallerInfo(ctx) {
if (ctx.routePattern === ACTION_RPC_ROUTE_PATTERN) {
return { from: "rpc", name: ctx.url.pathname.replace(/^.*\/_actions\//, "") };
}
const queryParam = ctx.url.searchParams.get(ACTION_QUERY_PARAMS.actionName);
if (queryParam) {
return { from: "form", name: queryParam };
}
return void 0;
}
async function parseRequestBody(request) {
const contentType = request.headers.get("content-type");
const contentLength = request.headers.get("Content-Length");
if (!contentType) return void 0;
if (hasContentType(contentType, formContentTypes)) {
return await request.clone().formData();
}
if (hasContentType(contentType, ["application/json"])) {
return contentLength === "0" ? void 0 : await request.clone().json();
}
throw new TypeError("Unsupported content type");
}
export {
defineAction,
formDataToObject,
getActionContext
};

60
node_modules/astro/dist/actions/runtime/shared.d.ts generated vendored Normal file
View File

@@ -0,0 +1,60 @@
import type { z } from 'zod';
import { AstroError } from '../../core/errors/errors.js';
import { appendForwardSlash as _appendForwardSlash } from '../../core/path.js';
import type { ActionAPIContext as _ActionAPIContext, ErrorInferenceObject, MaybePromise } from './utils.js';
export type ActionAPIContext = _ActionAPIContext;
export declare const ACTION_QUERY_PARAMS: {
actionName: string;
actionPayload: string;
};
export declare const appendForwardSlash: typeof _appendForwardSlash;
export declare const ACTION_ERROR_CODES: readonly ["BAD_REQUEST", "UNAUTHORIZED", "PAYMENT_REQUIRED", "FORBIDDEN", "NOT_FOUND", "METHOD_NOT_ALLOWED", "NOT_ACCEPTABLE", "PROXY_AUTHENTICATION_REQUIRED", "REQUEST_TIMEOUT", "CONFLICT", "GONE", "LENGTH_REQUIRED", "PRECONDITION_FAILED", "CONTENT_TOO_LARGE", "URI_TOO_LONG", "UNSUPPORTED_MEDIA_TYPE", "RANGE_NOT_SATISFIABLE", "EXPECTATION_FAILED", "MISDIRECTED_REQUEST", "UNPROCESSABLE_CONTENT", "LOCKED", "FAILED_DEPENDENCY", "TOO_EARLY", "UPGRADE_REQUIRED", "PRECONDITION_REQUIRED", "TOO_MANY_REQUESTS", "REQUEST_HEADER_FIELDS_TOO_LARGE", "UNAVAILABLE_FOR_LEGAL_REASONS", "INTERNAL_SERVER_ERROR", "NOT_IMPLEMENTED", "BAD_GATEWAY", "SERVICE_UNAVAILABLE", "GATEWAY_TIMEOUT", "HTTP_VERSION_NOT_SUPPORTED", "VARIANT_ALSO_NEGOTIATES", "INSUFFICIENT_STORAGE", "LOOP_DETECTED", "NETWORK_AUTHENTICATION_REQUIRED"];
export type ActionErrorCode = (typeof ACTION_ERROR_CODES)[number];
export declare class ActionError<_T extends ErrorInferenceObject = ErrorInferenceObject> extends Error {
type: string;
code: ActionErrorCode;
status: number;
constructor(params: {
message?: string;
code: ActionErrorCode;
stack?: string;
});
static codeToStatus(code: ActionErrorCode): number;
static statusToCode(status: number): ActionErrorCode;
static fromJson(body: any): ActionError<ErrorInferenceObject>;
}
export declare function isActionError(error?: unknown): error is ActionError;
export declare function isInputError<T extends ErrorInferenceObject>(error?: ActionError<T>): error is ActionInputError<T>;
export declare function isInputError(error?: unknown): error is ActionInputError<ErrorInferenceObject>;
export type SafeResult<TInput extends ErrorInferenceObject, TOutput> = {
data: TOutput;
error: undefined;
} | {
data: undefined;
error: ActionError<TInput>;
};
export declare class ActionInputError<T extends ErrorInferenceObject> extends ActionError {
type: string;
issues: z.ZodIssue[];
fields: z.ZodError<T>['formErrors']['fieldErrors'];
constructor(issues: z.ZodIssue[]);
}
export declare function callSafely<TOutput>(handler: () => MaybePromise<TOutput>): Promise<SafeResult<z.ZodType, TOutput>>;
export declare function getActionQueryString(name: string): string;
export type SerializedActionResult = {
type: 'data';
contentType: 'application/json+devalue';
status: 200;
body: string;
} | {
type: 'error';
contentType: 'application/json';
status: number;
body: string;
} | {
type: 'empty';
status: 204;
};
export declare function serializeActionResult(res: SafeResult<any, any>): SerializedActionResult;
export declare function deserializeActionResult(res: SerializedActionResult): SafeResult<any, any>;
export declare function astroCalledServerError(): AstroError;

296
node_modules/astro/dist/actions/runtime/shared.js generated vendored Normal file
View File

@@ -0,0 +1,296 @@
import { parse as devalueParse, stringify as devalueStringify } from "devalue";
import { REDIRECT_STATUS_CODES } from "../../core/constants.js";
import { AstroError } from "../../core/errors/errors.js";
import {
ActionCalledFromServerError,
ActionsReturnedInvalidDataError
} from "../../core/errors/errors-data.js";
import { appendForwardSlash as _appendForwardSlash } from "../../core/path.js";
import { ACTION_QUERY_PARAMS as _ACTION_QUERY_PARAMS } from "../consts.js";
const ACTION_QUERY_PARAMS = _ACTION_QUERY_PARAMS;
const appendForwardSlash = _appendForwardSlash;
const ACTION_ERROR_CODES = [
"BAD_REQUEST",
"UNAUTHORIZED",
"PAYMENT_REQUIRED",
"FORBIDDEN",
"NOT_FOUND",
"METHOD_NOT_ALLOWED",
"NOT_ACCEPTABLE",
"PROXY_AUTHENTICATION_REQUIRED",
"REQUEST_TIMEOUT",
"CONFLICT",
"GONE",
"LENGTH_REQUIRED",
"PRECONDITION_FAILED",
"CONTENT_TOO_LARGE",
"URI_TOO_LONG",
"UNSUPPORTED_MEDIA_TYPE",
"RANGE_NOT_SATISFIABLE",
"EXPECTATION_FAILED",
"MISDIRECTED_REQUEST",
"UNPROCESSABLE_CONTENT",
"LOCKED",
"FAILED_DEPENDENCY",
"TOO_EARLY",
"UPGRADE_REQUIRED",
"PRECONDITION_REQUIRED",
"TOO_MANY_REQUESTS",
"REQUEST_HEADER_FIELDS_TOO_LARGE",
"UNAVAILABLE_FOR_LEGAL_REASONS",
"INTERNAL_SERVER_ERROR",
"NOT_IMPLEMENTED",
"BAD_GATEWAY",
"SERVICE_UNAVAILABLE",
"GATEWAY_TIMEOUT",
"HTTP_VERSION_NOT_SUPPORTED",
"VARIANT_ALSO_NEGOTIATES",
"INSUFFICIENT_STORAGE",
"LOOP_DETECTED",
"NETWORK_AUTHENTICATION_REQUIRED"
];
const codeToStatusMap = {
// Implemented from IANA HTTP Status Code Registry
// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
PAYMENT_REQUIRED: 402,
FORBIDDEN: 403,
NOT_FOUND: 404,
METHOD_NOT_ALLOWED: 405,
NOT_ACCEPTABLE: 406,
PROXY_AUTHENTICATION_REQUIRED: 407,
REQUEST_TIMEOUT: 408,
CONFLICT: 409,
GONE: 410,
LENGTH_REQUIRED: 411,
PRECONDITION_FAILED: 412,
CONTENT_TOO_LARGE: 413,
URI_TOO_LONG: 414,
UNSUPPORTED_MEDIA_TYPE: 415,
RANGE_NOT_SATISFIABLE: 416,
EXPECTATION_FAILED: 417,
MISDIRECTED_REQUEST: 421,
UNPROCESSABLE_CONTENT: 422,
LOCKED: 423,
FAILED_DEPENDENCY: 424,
TOO_EARLY: 425,
UPGRADE_REQUIRED: 426,
PRECONDITION_REQUIRED: 428,
TOO_MANY_REQUESTS: 429,
REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
UNAVAILABLE_FOR_LEGAL_REASONS: 451,
INTERNAL_SERVER_ERROR: 500,
NOT_IMPLEMENTED: 501,
BAD_GATEWAY: 502,
SERVICE_UNAVAILABLE: 503,
GATEWAY_TIMEOUT: 504,
HTTP_VERSION_NOT_SUPPORTED: 505,
VARIANT_ALSO_NEGOTIATES: 506,
INSUFFICIENT_STORAGE: 507,
LOOP_DETECTED: 508,
NETWORK_AUTHENTICATION_REQUIRED: 511
};
const statusToCodeMap = Object.entries(codeToStatusMap).reduce(
// reverse the key-value pairs
(acc, [key, value]) => ({ ...acc, [value]: key }),
{}
);
class ActionError extends Error {
type = "AstroActionError";
code = "INTERNAL_SERVER_ERROR";
status = 500;
constructor(params) {
super(params.message);
this.code = params.code;
this.status = ActionError.codeToStatus(params.code);
if (params.stack) {
this.stack = params.stack;
}
}
static codeToStatus(code) {
return codeToStatusMap[code];
}
static statusToCode(status) {
return statusToCodeMap[status] ?? "INTERNAL_SERVER_ERROR";
}
static fromJson(body) {
if (isInputError(body)) {
return new ActionInputError(body.issues);
}
if (isActionError(body)) {
return new ActionError(body);
}
return new ActionError({
code: "INTERNAL_SERVER_ERROR"
});
}
}
function isActionError(error) {
return typeof error === "object" && error != null && "type" in error && error.type === "AstroActionError";
}
function isInputError(error) {
return typeof error === "object" && error != null && "type" in error && error.type === "AstroActionInputError" && "issues" in error && Array.isArray(error.issues);
}
class ActionInputError extends ActionError {
type = "AstroActionInputError";
// We don't expose all ZodError properties.
// Not all properties will serialize from server to client,
// and we don't want to import the full ZodError object into the client.
issues;
fields;
constructor(issues) {
super({
message: `Failed to validate: ${JSON.stringify(issues, null, 2)}`,
code: "BAD_REQUEST"
});
this.issues = issues;
this.fields = {};
for (const issue of issues) {
if (issue.path.length > 0) {
const key = issue.path[0].toString();
this.fields[key] ??= [];
this.fields[key]?.push(issue.message);
}
}
}
}
async function callSafely(handler) {
try {
const data = await handler();
return { data, error: void 0 };
} catch (e) {
if (e instanceof ActionError) {
return { data: void 0, error: e };
}
return {
data: void 0,
error: new ActionError({
message: e instanceof Error ? e.message : "Unknown error",
code: "INTERNAL_SERVER_ERROR"
})
};
}
}
function getActionQueryString(name) {
const searchParams = new URLSearchParams({ [_ACTION_QUERY_PARAMS.actionName]: name });
return `?${searchParams.toString()}`;
}
function serializeActionResult(res) {
if (res.error) {
if (import.meta.env?.DEV) {
actionResultErrorStack.set(res.error.stack);
}
let body2;
if (res.error instanceof ActionInputError) {
body2 = {
type: res.error.type,
issues: res.error.issues,
fields: res.error.fields
};
} else {
body2 = {
...res.error,
message: res.error.message
};
}
return {
type: "error",
status: res.error.status,
contentType: "application/json",
body: JSON.stringify(body2)
};
}
if (res.data === void 0) {
return {
type: "empty",
status: 204
};
}
let body;
try {
body = devalueStringify(res.data, {
// Add support for URL objects
URL: (value) => value instanceof URL && value.href
});
} catch (e) {
let hint = ActionsReturnedInvalidDataError.hint;
if (res.data instanceof Response) {
hint = REDIRECT_STATUS_CODES.includes(res.data.status) ? "If you need to redirect when the action succeeds, trigger a redirect where the action is called. See the Actions guide for server and client redirect examples: https://docs.astro.build/en/guides/actions." : "If you need to return a Response object, try using a server endpoint instead. See https://docs.astro.build/en/guides/endpoints/#server-endpoints-api-routes";
}
throw new AstroError({
...ActionsReturnedInvalidDataError,
message: ActionsReturnedInvalidDataError.message(String(e)),
hint
});
}
return {
type: "data",
status: 200,
contentType: "application/json+devalue",
body
};
}
function deserializeActionResult(res) {
if (res.type === "error") {
let json;
try {
json = JSON.parse(res.body);
} catch {
return {
data: void 0,
error: new ActionError({
message: res.body,
code: "INTERNAL_SERVER_ERROR"
})
};
}
if (import.meta.env?.PROD) {
return { error: ActionError.fromJson(json), data: void 0 };
} else {
const error = ActionError.fromJson(json);
error.stack = actionResultErrorStack.get();
return {
error,
data: void 0
};
}
}
if (res.type === "empty") {
return { data: void 0, error: void 0 };
}
return {
data: devalueParse(res.body, {
URL: (href) => new URL(href)
}),
error: void 0
};
}
const actionResultErrorStack = /* @__PURE__ */ function actionResultErrorStackFn() {
let errorStack;
return {
set(stack) {
errorStack = stack;
},
get() {
return errorStack;
}
};
}();
function astroCalledServerError() {
return new AstroError(ActionCalledFromServerError);
}
export {
ACTION_ERROR_CODES,
ACTION_QUERY_PARAMS,
ActionError,
ActionInputError,
appendForwardSlash,
astroCalledServerError,
callSafely,
deserializeActionResult,
getActionQueryString,
isActionError,
isInputError,
serializeActionResult
};

31
node_modules/astro/dist/actions/runtime/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import type { APIContext, AstroSharedContext } from '../../types/public/context.js';
import type { SerializedActionResult } from './shared.js';
export type ActionPayload = {
actionResult: SerializedActionResult;
actionName: string;
};
export type Locals = {
_actionPayload: ActionPayload;
};
export declare const ACTION_API_CONTEXT_SYMBOL: unique symbol;
export declare const formContentTypes: string[];
export declare function hasContentType(contentType: string, expected: string[]): boolean;
export type ActionAPIContext = Pick<APIContext, 'rewrite' | 'request' | 'url' | 'isPrerendered' | 'locals' | 'clientAddress' | 'cookies' | 'currentLocale' | 'generator' | 'routePattern' | 'site' | 'params' | 'preferredLocale' | 'preferredLocaleList' | 'originPathname' | 'session' | 'csp'> & {
/**
* @deprecated
* The use of `rewrite` in Actions is deprecated
*/
rewrite: AstroSharedContext['rewrite'];
};
export type MaybePromise<T> = T | Promise<T>;
/**
* Used to preserve the input schema type in the error object.
* This allows for type inference on the `fields` property
* when type narrowed to an `ActionInputError`.
*
* Example: Action has an input schema of `{ name: z.string() }`.
* When calling the action and checking `isInputError(result.error)`,
* `result.error.fields` will be typed with the `name` field.
*/
export type ErrorInferenceObject = Record<string, any>;
export declare function isActionAPIContext(ctx: ActionAPIContext): boolean;

16
node_modules/astro/dist/actions/runtime/utils.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
const ACTION_API_CONTEXT_SYMBOL = Symbol.for("astro.actionAPIContext");
const formContentTypes = ["application/x-www-form-urlencoded", "multipart/form-data"];
function hasContentType(contentType, expected) {
const type = contentType.split(";")[0].toLowerCase();
return expected.some((t) => type === t);
}
function isActionAPIContext(ctx) {
const symbol = Reflect.get(ctx, ACTION_API_CONTEXT_SYMBOL);
return symbol === true;
}
export {
ACTION_API_CONTEXT_SYMBOL,
formContentTypes,
hasContentType,
isActionAPIContext
};

10
node_modules/astro/dist/actions/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import type fsMod from 'node:fs';
import type { APIContext } from '../types/public/context.js';
import { type ActionAPIContext, type Locals } from './runtime/utils.js';
export declare function hasActionPayload(locals: APIContext['locals']): locals is Locals;
export declare function createGetActionResult(locals: APIContext['locals']): APIContext['getActionResult'];
export declare function createCallAction(context: ActionAPIContext): APIContext['callAction'];
/**
* Check whether the Actions config file is present.
*/
export declare function isActionsFilePresent(fs: typeof fsMod, srcDir: URL): Promise<string | false>;

65
node_modules/astro/dist/actions/utils.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
import * as eslexer from "es-module-lexer";
import { deserializeActionResult, getActionQueryString } from "./runtime/shared.js";
import { ACTION_API_CONTEXT_SYMBOL } from "./runtime/utils.js";
function hasActionPayload(locals) {
return "_actionPayload" in locals;
}
function createGetActionResult(locals) {
return (actionFn) => {
if (!hasActionPayload(locals) || actionFn.toString() !== getActionQueryString(locals._actionPayload.actionName)) {
return void 0;
}
return deserializeActionResult(locals._actionPayload.actionResult);
};
}
function createCallAction(context) {
return (baseAction, input) => {
Reflect.set(context, ACTION_API_CONTEXT_SYMBOL, true);
const action = baseAction.bind(context);
return action(input);
};
}
let didInitLexer = false;
async function isActionsFilePresent(fs, srcDir) {
if (!didInitLexer) await eslexer.init;
const actionsFile = search(fs, srcDir);
if (!actionsFile) return false;
let contents;
try {
contents = fs.readFileSync(actionsFile.url, "utf-8");
} catch {
return false;
}
const [, exports] = eslexer.parse(contents, actionsFile.url.pathname);
for (const exp of exports) {
if (exp.n === "server") {
return actionsFile.filename;
}
}
return false;
}
function search(fs, srcDir) {
const filenames = [
"actions.mjs",
"actions.js",
"actions.mts",
"actions.ts",
"actions/index.mjs",
"actions/index.js",
"actions/index.mts",
"actions/index.ts"
];
for (const filename of filenames) {
const url = new URL(filename, srcDir);
if (fs.existsSync(url)) {
return { filename, url };
}
}
return void 0;
}
export {
createCallAction,
createGetActionResult,
hasActionPayload,
isActionsFilePresent
};

View File

@@ -0,0 +1,15 @@
import type fsMod from 'node:fs';
import type { Plugin as VitePlugin } from 'vite';
import type { BuildInternals } from '../core/build/internal.js';
import type { StaticBuildOptions } from '../core/build/types.js';
import type { AstroSettings } from '../types/astro.js';
/**
* This plugin is used to retrieve the final entry point of the bundled actions.ts file
* @param opts
* @param internals
*/
export declare function vitePluginActionsBuild(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin;
export declare function vitePluginActions({ fs, settings, }: {
fs: typeof fsMod;
settings: AstroSettings;
}): VitePlugin;

98
node_modules/astro/dist/actions/vite-plugin-actions.js generated vendored Normal file
View File

@@ -0,0 +1,98 @@
import { addRollupInput } from "../core/build/add-rollup-input.js";
import { shouldAppendForwardSlash } from "../core/build/util.js";
import { getServerOutputDirectory } from "../prerender/utils.js";
import {
ENTRYPOINT_VIRTUAL_MODULE_ID,
OPTIONS_VIRTUAL_MODULE_ID,
RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID,
RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID,
RESOLVED_OPTIONS_VIRTUAL_MODULE_ID,
RESOLVED_RUNTIME_VIRTUAL_MODULE_ID,
RUNTIME_VIRTUAL_MODULE_ID,
VIRTUAL_MODULE_ID
} from "./consts.js";
import { isActionsFilePresent } from "./utils.js";
function vitePluginActionsBuild(opts, internals) {
return {
name: "@astro/plugin-actions-build",
options(options) {
return addRollupInput(options, [ENTRYPOINT_VIRTUAL_MODULE_ID]);
},
writeBundle(_, bundle) {
for (const [chunkName, chunk] of Object.entries(bundle)) {
if (chunk.type !== "asset" && chunk.facadeModuleId === RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID) {
const outputDirectory = getServerOutputDirectory(opts.settings);
internals.astroActionsEntryPoint = new URL(chunkName, outputDirectory);
}
}
}
};
}
function vitePluginActions({
fs,
settings
}) {
let resolvedActionsId;
return {
name: VIRTUAL_MODULE_ID,
enforce: "pre",
async resolveId(id) {
if (id === VIRTUAL_MODULE_ID) {
return this.resolve("astro/virtual-modules/actions.js");
}
if (id === RUNTIME_VIRTUAL_MODULE_ID) {
return RESOLVED_RUNTIME_VIRTUAL_MODULE_ID;
}
if (id === OPTIONS_VIRTUAL_MODULE_ID) {
return RESOLVED_OPTIONS_VIRTUAL_MODULE_ID;
}
if (id === ENTRYPOINT_VIRTUAL_MODULE_ID) {
const resolvedModule = await this.resolve(
`${decodeURI(new URL("actions", settings.config.srcDir).pathname)}`
);
if (!resolvedModule) {
return RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID;
}
resolvedActionsId = resolvedModule.id;
return RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID;
}
},
async configureServer(server) {
const filePresentOnStartup = await isActionsFilePresent(fs, settings.config.srcDir);
async function watcherCallback() {
const filePresent = await isActionsFilePresent(fs, settings.config.srcDir);
if (filePresentOnStartup !== filePresent) {
server.restart();
}
}
server.watcher.on("add", watcherCallback);
server.watcher.on("change", watcherCallback);
},
async load(id, opts) {
if (id === RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID) {
return { code: "export const server = {}" };
}
if (id === RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID) {
return { code: `export { server } from ${JSON.stringify(resolvedActionsId)};` };
}
if (id === RESOLVED_RUNTIME_VIRTUAL_MODULE_ID) {
return {
code: `export * from 'astro/actions/runtime/${opts?.ssr ? "server" : "client"}.js';`
};
}
if (id === RESOLVED_OPTIONS_VIRTUAL_MODULE_ID) {
return {
code: `
export const shouldAppendTrailingSlash = ${JSON.stringify(
shouldAppendForwardSlash(settings.config.trailingSlash, settings.config.build.format)
)};
`
};
}
}
};
}
export {
vitePluginActions,
vitePluginActionsBuild
};

23
node_modules/astro/dist/assets/build/generate.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import type { BuildPipeline } from '../../core/build/pipeline.js';
import type { Logger } from '../../core/logger/core.js';
import type { MapValue } from '../../type-utils.js';
import type { AstroConfig } from '../../types/public/config.js';
import type { AssetsGlobalStaticImagesList } from '../types.js';
type AssetEnv = {
logger: Logger;
isSSR: boolean;
count: {
total: number;
current: number;
};
useCache: boolean;
assetsCacheDir: URL;
serverRoot: URL;
clientRoot: URL;
imageConfig: AstroConfig['image'];
assetsFolder: AstroConfig['build']['assets'];
};
export declare function prepareAssetsGenerationEnv(pipeline: BuildPipeline, totalCount: number): Promise<AssetEnv>;
export declare function generateImagesForPath(originalFilePath: string, transformsAndPath: MapValue<AssetsGlobalStaticImagesList>, env: AssetEnv): Promise<void>;
export declare function getStaticImageList(): AssetsGlobalStaticImagesList;
export {};

250
node_modules/astro/dist/assets/build/generate.js generated vendored Normal file
View File

@@ -0,0 +1,250 @@
import fs, { readFileSync } from "node:fs";
import { basename } from "node:path/posix";
import { dim, green } from "kleur/colors";
import { getOutDirWithinCwd } from "../../core/build/common.js";
import { getTimeStat } from "../../core/build/util.js";
import { AstroError } from "../../core/errors/errors.js";
import { AstroErrorData } from "../../core/errors/index.js";
import { isRemotePath, removeLeadingForwardSlash } from "../../core/path.js";
import { getConfiguredImageService } from "../internal.js";
import { isESMImportedImage } from "../utils/imageKind.js";
import { loadRemoteImage, revalidateRemoteImage } from "./remote.js";
async function prepareAssetsGenerationEnv(pipeline, totalCount) {
const { config, logger, settings } = pipeline;
let useCache = true;
const assetsCacheDir = new URL("assets/", config.cacheDir);
const count = { total: totalCount, current: 1 };
try {
await fs.promises.mkdir(assetsCacheDir, { recursive: true });
} catch (err) {
logger.warn(
null,
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${err}`
);
useCache = false;
}
const isServerOutput = settings.buildOutput === "server";
let serverRoot, clientRoot;
if (isServerOutput) {
serverRoot = config.build.server;
clientRoot = config.build.client;
} else {
serverRoot = getOutDirWithinCwd(config.outDir);
clientRoot = config.outDir;
}
return {
logger,
isSSR: isServerOutput,
count,
useCache,
assetsCacheDir,
serverRoot,
clientRoot,
imageConfig: config.image,
assetsFolder: config.build.assets
};
}
function getFullImagePath(originalFilePath, env) {
return new URL(removeLeadingForwardSlash(originalFilePath), env.serverRoot);
}
async function generateImagesForPath(originalFilePath, transformsAndPath, env) {
let originalImage;
for (const [_, transform] of transformsAndPath.transforms) {
await generateImage(transform.finalPath, transform.transform);
}
if (!env.isSSR && transformsAndPath.originalSrcPath && !globalThis.astroAsset.referencedImages?.has(transformsAndPath.originalSrcPath)) {
try {
if (transformsAndPath.originalSrcPath) {
env.logger.debug(
"assets",
`Deleting ${originalFilePath} as it's not referenced outside of image processing.`
);
await fs.promises.unlink(getFullImagePath(originalFilePath, env));
}
} catch {
}
}
async function generateImage(filepath, options) {
const timeStart = performance.now();
const generationData = await generateImageInternal(filepath, options);
const timeEnd = performance.now();
const timeChange = getTimeStat(timeStart, timeEnd);
const timeIncrease = `(+${timeChange})`;
const statsText = generationData.cached !== "miss" ? generationData.cached === "hit" ? `(reused cache entry)` : `(revalidated cache entry)` : `(before: ${generationData.weight.before}kB, after: ${generationData.weight.after}kB)`;
const count = `(${env.count.current}/${env.count.total})`;
env.logger.info(
null,
` ${green("\u25B6")} ${filepath} ${dim(statsText)} ${dim(timeIncrease)} ${dim(count)}`
);
env.count.current++;
}
async function generateImageInternal(filepath, options) {
const isLocalImage = isESMImportedImage(options.src);
const finalFileURL = new URL("." + filepath, env.clientRoot);
const finalFolderURL = new URL("./", finalFileURL);
await fs.promises.mkdir(finalFolderURL, { recursive: true });
const cacheFile = basename(filepath);
const cachedFileURL = new URL(cacheFile, env.assetsCacheDir);
const cacheMetaFile = cacheFile + ".json";
const cachedMetaFileURL = new URL(cacheMetaFile, env.assetsCacheDir);
try {
if (isLocalImage) {
await fs.promises.copyFile(cachedFileURL, finalFileURL, fs.constants.COPYFILE_FICLONE);
return {
cached: "hit"
};
} else {
const JSONData = JSON.parse(readFileSync(cachedMetaFileURL, "utf-8"));
if (!JSONData.expires) {
try {
await fs.promises.unlink(cachedFileURL);
} catch {
}
await fs.promises.unlink(cachedMetaFileURL);
throw new Error(
`Malformed cache entry for ${filepath}, cache will be regenerated for this file.`
);
}
if (JSONData.data) {
const { data, ...meta } = JSONData;
await Promise.all([
fs.promises.writeFile(cachedFileURL, Buffer.from(data, "base64")),
writeCacheMetaFile(cachedMetaFileURL, meta, env)
]);
}
if (JSONData.expires > Date.now()) {
await fs.promises.copyFile(cachedFileURL, finalFileURL, fs.constants.COPYFILE_FICLONE);
return {
cached: "hit"
};
}
if (JSONData.etag || JSONData.lastModified) {
try {
const revalidatedData = await revalidateRemoteImage(options.src, {
etag: JSONData.etag,
lastModified: JSONData.lastModified
});
if (revalidatedData.data.length) {
originalImage = revalidatedData;
} else {
await writeCacheMetaFile(cachedMetaFileURL, revalidatedData, env);
await fs.promises.copyFile(
cachedFileURL,
finalFileURL,
fs.constants.COPYFILE_FICLONE
);
return { cached: "revalidated" };
}
} catch (e) {
env.logger.warn(
null,
`An error was encountered while revalidating a cached remote asset. Proceeding with stale cache. ${e}`
);
await fs.promises.copyFile(cachedFileURL, finalFileURL, fs.constants.COPYFILE_FICLONE);
return { cached: "hit" };
}
}
await fs.promises.unlink(cachedFileURL);
await fs.promises.unlink(cachedMetaFileURL);
}
} catch (e) {
if (e.code !== "ENOENT") {
throw new Error(`An error was encountered while reading the cache file. Error: ${e}`);
}
}
const originalImagePath = isLocalImage ? options.src.src : options.src;
if (!originalImage) {
originalImage = await loadImage(originalFilePath, env);
}
let resultData = {
data: void 0,
expires: originalImage.expires,
etag: originalImage.etag,
lastModified: originalImage.lastModified
};
const imageService = await getConfiguredImageService();
try {
resultData.data = (await imageService.transform(
originalImage.data,
{ ...options, src: originalImagePath },
env.imageConfig
)).data;
} catch (e) {
if (AstroError.is(e)) {
throw e;
}
const error = new AstroError(
{
...AstroErrorData.CouldNotTransformImage,
message: AstroErrorData.CouldNotTransformImage.message(originalFilePath)
},
{ cause: e }
);
throw error;
}
try {
if (env.useCache) {
if (isLocalImage) {
await fs.promises.writeFile(cachedFileURL, resultData.data);
} else {
await Promise.all([
fs.promises.writeFile(cachedFileURL, resultData.data),
writeCacheMetaFile(cachedMetaFileURL, resultData, env)
]);
}
}
} catch (e) {
env.logger.warn(
null,
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${e}`
);
} finally {
await fs.promises.writeFile(finalFileURL, resultData.data);
}
return {
cached: "miss",
weight: {
// Divide by 1024 to get size in kilobytes
before: Math.trunc(originalImage.data.byteLength / 1024),
after: Math.trunc(Buffer.from(resultData.data).byteLength / 1024)
}
};
}
}
async function writeCacheMetaFile(cachedMetaFileURL, resultData, env) {
try {
return await fs.promises.writeFile(
cachedMetaFileURL,
JSON.stringify({
expires: resultData.expires,
etag: resultData.etag,
lastModified: resultData.lastModified
})
);
} catch (e) {
env.logger.warn(
null,
`An error was encountered while writing the cache file for a remote asset. Proceeding without caching this asset. Error: ${e}`
);
}
}
function getStaticImageList() {
if (!globalThis?.astroAsset?.staticImages) {
return /* @__PURE__ */ new Map();
}
return globalThis.astroAsset.staticImages;
}
async function loadImage(path, env) {
if (isRemotePath(path)) {
return await loadRemoteImage(path);
}
return {
data: await fs.promises.readFile(getFullImagePath(path, env)),
expires: 0
};
}
export {
generateImagesForPath,
getStaticImageList,
prepareAssetsGenerationEnv
};

30
node_modules/astro/dist/assets/build/remote.d.ts generated vendored Normal file
View File

@@ -0,0 +1,30 @@
export type RemoteCacheEntry = {
data?: string;
expires: number;
etag?: string;
lastModified?: string;
};
export declare function loadRemoteImage(src: string): Promise<{
data: Buffer<ArrayBuffer>;
expires: number;
etag: string | undefined;
lastModified: string | undefined;
}>;
/**
* Revalidate a cached remote asset using its entity-tag or modified date.
* Uses the [If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) and [If-Modified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)
* headers to check with the remote server if the cached version of a remote asset is still up to date.
* The remote server may respond that the cached asset is still up-to-date if the entity-tag or modification time matches (304 Not Modified), or respond with an updated asset (200 OK)
* @param src - url to remote asset
* @param revalidationData - an object containing the stored Entity-Tag of the cached asset and/or the Last Modified time
* @returns An ImageData object containing the asset data, a new expiry time, and the asset's etag. The data buffer will be empty if the asset was not modified.
*/
export declare function revalidateRemoteImage(src: string, revalidationData: {
etag?: string;
lastModified?: string;
}): Promise<{
data: Buffer<ArrayBuffer>;
expires: number;
etag: string | undefined;
lastModified: string | undefined;
}>;

77
node_modules/astro/dist/assets/build/remote.js generated vendored Normal file
View File

@@ -0,0 +1,77 @@
import CachePolicy from "http-cache-semantics";
async function loadRemoteImage(src) {
const req = new Request(src);
const res = await fetch(req);
if (!res.ok) {
throw new Error(
`Failed to load remote image ${src}. The request did not return a 200 OK response. (received ${res.status}))`
);
}
const policy = new CachePolicy(webToCachePolicyRequest(req), webToCachePolicyResponse(res));
const expires = policy.storable() ? policy.timeToLive() : 0;
return {
data: Buffer.from(await res.arrayBuffer()),
expires: Date.now() + expires,
etag: res.headers.get("Etag") ?? void 0,
lastModified: res.headers.get("Last-Modified") ?? void 0
};
}
async function revalidateRemoteImage(src, revalidationData) {
const headers = {
...revalidationData.etag && { "If-None-Match": revalidationData.etag },
...revalidationData.lastModified && { "If-Modified-Since": revalidationData.lastModified }
};
const req = new Request(src, { headers });
const res = await fetch(req);
if (!res.ok && res.status !== 304) {
throw new Error(
`Failed to revalidate cached remote image ${src}. The request did not return a 200 OK / 304 NOT MODIFIED response. (received ${res.status} ${res.statusText})`
);
}
const data = Buffer.from(await res.arrayBuffer());
if (res.ok && !data.length) {
return await loadRemoteImage(src);
}
const policy = new CachePolicy(
webToCachePolicyRequest(req),
webToCachePolicyResponse(
res.ok ? res : new Response(null, { status: 200, headers: res.headers })
)
// 304 responses themselves are not cacheable, so just pretend to get the refreshed TTL
);
const expires = policy.storable() ? policy.timeToLive() : 0;
return {
data,
expires: Date.now() + expires,
// While servers should respond with the same headers as a 200 response, if they don't we should reuse the stored value
etag: res.headers.get("Etag") ?? (res.ok ? void 0 : revalidationData.etag),
lastModified: res.headers.get("Last-Modified") ?? (res.ok ? void 0 : revalidationData.lastModified)
};
}
function webToCachePolicyRequest({ url, method, headers: _headers }) {
let headers = {};
try {
headers = Object.fromEntries(_headers.entries());
} catch {
}
return {
method,
url,
headers
};
}
function webToCachePolicyResponse({ status, headers: _headers }) {
let headers = {};
try {
headers = Object.fromEntries(_headers.entries());
} catch {
}
return {
status,
headers
};
}
export {
loadRemoteImage,
revalidateRemoteImage
};

11
node_modules/astro/dist/assets/consts.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
export declare const VIRTUAL_MODULE_ID = "astro:assets";
export declare const VIRTUAL_SERVICE_ID = "virtual:image-service";
export declare const VALID_INPUT_FORMATS: readonly ["jpeg", "jpg", "png", "tiff", "webp", "gif", "svg", "avif"];
/**
* Valid formats that our base services support.
* Certain formats can be imported (namely SVGs) but will not be processed.
*/
export declare const VALID_SUPPORTED_FORMATS: readonly ["jpeg", "jpg", "png", "tiff", "webp", "gif", "svg", "avif"];
export declare const DEFAULT_OUTPUT_FORMAT: "webp";
export declare const VALID_OUTPUT_FORMATS: readonly ["avif", "png", "webp", "jpeg", "jpg", "svg"];
export declare const DEFAULT_HASH_PROPS: string[];

42
node_modules/astro/dist/assets/consts.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
const VIRTUAL_MODULE_ID = "astro:assets";
const VIRTUAL_SERVICE_ID = "virtual:image-service";
const VALID_INPUT_FORMATS = [
"jpeg",
"jpg",
"png",
"tiff",
"webp",
"gif",
"svg",
"avif"
];
const VALID_SUPPORTED_FORMATS = [
"jpeg",
"jpg",
"png",
"tiff",
"webp",
"gif",
"svg",
"avif"
];
const DEFAULT_OUTPUT_FORMAT = "webp";
const VALID_OUTPUT_FORMATS = ["avif", "png", "webp", "jpeg", "jpg", "svg"];
const DEFAULT_HASH_PROPS = [
"src",
"width",
"height",
"format",
"quality",
"fit",
"position"
];
export {
DEFAULT_HASH_PROPS,
DEFAULT_OUTPUT_FORMAT,
VALID_INPUT_FORMATS,
VALID_OUTPUT_FORMATS,
VALID_SUPPORTED_FORMATS,
VIRTUAL_MODULE_ID,
VIRTUAL_SERVICE_ID
};

2
node_modules/astro/dist/assets/endpoint/config.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import type { AstroSettings, RoutesList } from '../../types/astro.js';
export declare function injectImageEndpoint(settings: AstroSettings, manifest: RoutesList, mode: 'dev' | 'build', cwd?: string): void;

40
node_modules/astro/dist/assets/endpoint/config.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
import {
removeLeadingForwardSlash,
removeTrailingForwardSlash
} from "@astrojs/internal-helpers/path";
import { resolveInjectedRoute } from "../../core/routing/manifest/create.js";
import { getPattern } from "../../core/routing/manifest/pattern.js";
function injectImageEndpoint(settings, manifest, mode, cwd) {
manifest.routes.unshift(getImageEndpointData(settings, mode, cwd));
}
function getImageEndpointData(settings, mode, cwd) {
const endpointEntrypoint = settings.config.image.endpoint.entrypoint === void 0 ? mode === "dev" ? "astro/assets/endpoint/dev" : "astro/assets/endpoint/generic" : settings.config.image.endpoint.entrypoint;
const segments = [
[
{
content: removeTrailingForwardSlash(
removeLeadingForwardSlash(settings.config.image.endpoint.route)
),
dynamic: false,
spread: false
}
]
];
return {
type: "endpoint",
isIndex: false,
route: settings.config.image.endpoint.route,
pattern: getPattern(segments, settings.config.base, settings.config.trailingSlash),
segments,
params: [],
component: resolveInjectedRoute(endpointEntrypoint, settings.config.root, cwd).component,
generate: () => "",
pathname: settings.config.image.endpoint.route,
prerender: false,
fallbackRoutes: [],
origin: "internal"
};
}
export {
injectImageEndpoint
};

5
node_modules/astro/dist/assets/endpoint/dev.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import type { APIRoute } from '../../types/public/common.js';
/**
* Endpoint used in dev and SSR to serve optimized images by the base image services
*/
export declare const GET: APIRoute;

47
node_modules/astro/dist/assets/endpoint/dev.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import { root } from "astro:config/server";
import { readFile } from "node:fs/promises";
import os from "node:os";
import { fileURLToPath } from "node:url";
import { isParentDirectory } from "@astrojs/internal-helpers/path";
import { handleImageRequest, loadRemoteImage } from "./shared.js";
function replaceFileSystemReferences(src) {
return os.platform().includes("win32") ? src.replace(/^\/@fs\//, "") : src.replace(/^\/@fs/, "");
}
async function loadLocalImage(src, url) {
if (src.startsWith("/@fs/")) {
src = replaceFileSystemReferences(src);
if (!isParentDirectory(fileURLToPath(root), src)) {
return void 0;
}
}
if (isParentDirectory(fileURLToPath(root), src)) {
try {
return await readFile(src);
} catch {
return void 0;
}
} else {
const sourceUrl = new URL(src, url.origin);
if (sourceUrl.origin !== url.origin) {
return void 0;
}
return loadRemoteImage(sourceUrl);
}
}
const GET = async ({ request }) => {
if (!import.meta.env.DEV) {
console.error("The dev image endpoint can only be used in dev mode.");
return new Response("Invalid endpoint", { status: 500 });
}
try {
return await handleImageRequest({ request, loadLocalImage });
} catch (err) {
console.error("Could not process image request:", err);
return new Response(`Could not process image request: ${err}`, {
status: 500
});
}
};
export {
GET
};

5
node_modules/astro/dist/assets/endpoint/generic.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import type { APIRoute } from '../../types/public/common.js';
/**
* Endpoint used in dev and SSR to serve optimized images by the base image services
*/
export declare const GET: APIRoute;

66
node_modules/astro/dist/assets/endpoint/generic.js generated vendored Normal file
View File

@@ -0,0 +1,66 @@
import { imageConfig } from "astro:assets";
import { isRemotePath } from "@astrojs/internal-helpers/path";
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
import * as mime from "mrmime";
import { getConfiguredImageService } from "../internal.js";
import { etag } from "../utils/etag.js";
async function loadRemoteImage(src, headers) {
try {
const res = await fetch(src, {
// Forward all headers from the original request
headers
});
if (!res.ok) {
return void 0;
}
return await res.arrayBuffer();
} catch {
return void 0;
}
}
const GET = async ({ request }) => {
try {
const imageService = await getConfiguredImageService();
if (!("transform" in imageService)) {
throw new Error("Configured image service is not a local service");
}
const url = new URL(request.url);
const transform = await imageService.parseURL(url, imageConfig);
if (!transform?.src) {
throw new Error("Incorrect transform returned by `parseURL`");
}
let inputBuffer = void 0;
const isRemoteImage = isRemotePath(transform.src);
if (isRemoteImage && isRemoteAllowed(transform.src, imageConfig) === false) {
return new Response("Forbidden", { status: 403 });
}
const sourceUrl = new URL(transform.src, url.origin);
if (!isRemoteImage && sourceUrl.origin !== url.origin) {
return new Response("Forbidden", { status: 403 });
}
inputBuffer = await loadRemoteImage(sourceUrl, isRemoteImage ? new Headers() : request.headers);
if (!inputBuffer) {
return new Response("Not Found", { status: 404 });
}
const { data, format } = await imageService.transform(
new Uint8Array(inputBuffer),
transform,
imageConfig
);
return new Response(data, {
status: 200,
headers: {
"Content-Type": mime.lookup(format) ?? `image/${format}`,
"Cache-Control": "public, max-age=31536000",
ETag: etag(data.toString()),
Date: (/* @__PURE__ */ new Date()).toUTCString()
}
});
} catch (err) {
console.error("Could not process image request:", err);
return new Response(`Server Error: ${err}`, { status: 500 });
}
};
export {
GET
};

5
node_modules/astro/dist/assets/endpoint/node.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import type { APIRoute } from '../../types/public/common.js';
/**
* Endpoint used in dev and SSR to serve optimized images by the base image services
*/
export declare const GET: APIRoute;

39
node_modules/astro/dist/assets/endpoint/node.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
import { outDir } from "astro:assets";
import { readFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { isParentDirectory } from "@astrojs/internal-helpers/path";
import { handleImageRequest } from "./shared.js";
async function loadLocalImage(src, url) {
const idx = url.pathname.indexOf("/_image");
if (idx > 0) {
src = src.slice(idx);
}
if (!URL.canParse("." + src, outDir)) {
return void 0;
}
const fileUrl = new URL("." + src, outDir);
if (fileUrl.protocol !== "file:") {
return void 0;
}
if (!isParentDirectory(fileURLToPath(outDir), fileURLToPath(fileUrl))) {
return void 0;
}
try {
return await readFile(fileUrl);
} catch {
return void 0;
}
}
const GET = async ({ request }) => {
try {
return await handleImageRequest({ request, loadLocalImage });
} catch (err) {
console.error("Could not process image request:", err);
return new Response("Internal Server Error", {
status: 500
});
}
};
export {
GET
};

5
node_modules/astro/dist/assets/endpoint/shared.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
export declare function loadRemoteImage(src: URL): Promise<Buffer | undefined>;
export declare const handleImageRequest: ({ request, loadLocalImage, }: {
request: Request;
loadLocalImage: (src: string, baseUrl: URL) => Promise<Buffer | undefined>;
}) => Promise<Response>;

57
node_modules/astro/dist/assets/endpoint/shared.js generated vendored Normal file
View File

@@ -0,0 +1,57 @@
import { imageConfig } from "astro:assets";
import { isRemotePath, removeQueryString } from "@astrojs/internal-helpers/path";
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
import * as mime from "mrmime";
import { getConfiguredImageService } from "../internal.js";
import { etag } from "../utils/etag.js";
async function loadRemoteImage(src) {
try {
const res = await fetch(src);
if (!res.ok) {
return void 0;
}
return Buffer.from(await res.arrayBuffer());
} catch {
return void 0;
}
}
const handleImageRequest = async ({
request,
loadLocalImage
}) => {
const imageService = await getConfiguredImageService();
if (!("transform" in imageService)) {
throw new Error("Configured image service is not a local service");
}
const url = new URL(request.url);
const transform = await imageService.parseURL(url, imageConfig);
if (!transform?.src) {
return new Response("Invalid request", { status: 400 });
}
let inputBuffer = void 0;
if (isRemotePath(transform.src)) {
if (!isRemoteAllowed(transform.src, imageConfig)) {
return new Response("Forbidden", { status: 403 });
}
inputBuffer = await loadRemoteImage(new URL(transform.src));
} else {
inputBuffer = await loadLocalImage(removeQueryString(transform.src), url);
}
if (!inputBuffer) {
return new Response("Internal Server Error", { status: 500 });
}
const { data, format } = await imageService.transform(inputBuffer, transform, imageConfig);
return new Response(data, {
status: 200,
headers: {
"Content-Type": mime.lookup(format) ?? `image/${format}`,
"Cache-Control": "public, max-age=31536000",
ETag: etag(data.toString()),
Date: (/* @__PURE__ */ new Date()).toUTCString()
}
});
};
export {
handleImageRequest,
loadRemoteImage
};

363
node_modules/astro/dist/assets/fonts/config.d.ts generated vendored Normal file
View File

@@ -0,0 +1,363 @@
import { z } from 'zod';
export declare const styleSchema: z.ZodEnum<["normal", "italic", "oblique"]>;
export declare const fontProviderSchema: z.ZodObject<{
/**
* URL, path relative to the root or package import.
*/
entrypoint: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
/**
* Optional serializable object passed to the unifont provider.
*/
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
}, "strict", z.ZodTypeAny, {
entrypoint: string | URL;
config?: Record<string, any> | undefined;
}, {
entrypoint: string | URL;
config?: Record<string, any> | undefined;
}>;
export declare const localFontFamilySchema: z.ZodObject<{
/**
* The font family name, as identified by your font provider.
*/
name: z.ZodString;
/**
* A valid [ident](https://developer.mozilla.org/en-US/docs/Web/CSS/ident) in the form of a CSS variable (i.e. starting with `--`).
*/
cssVariable: z.ZodString;
} & {
/**
* @default `["sans-serif"]`
*
* An array of fonts to use when your chosen font is unavailable, or loading. Fallback fonts will be chosen in the order listed. The first available font will be used:
*
* ```js
* fallbacks: ["CustomFont", "serif"]
* ```
*
* To disable fallback fonts completely, configure an empty array:
*
* ```js
* fallbacks: []
* ```
*
* If the last font in the `fallbacks` array is a [generic family name](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#generic-name), Astro will attempt to generate [optimized fallbacks](https://developer.chrome.com/blog/font-fallbacks) using font metrics will be generated. To disable this optimization, set `optimizedFallbacks` to false.
*/
fallbacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/**
* @default `true`
*
* Whether or not to enable optimized fallback generation. You may disable this default optimization to have full control over `fallbacks`.
*/
optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
} & {
/**
* The source of your font files. Set to `"local"` to use local font files.
*/
provider: z.ZodLiteral<"local">;
/**
* Each variant represents a [`@font-face` declaration](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/).
*/
variants: z.ZodArray<z.ZodObject<{
/**
* A [font weight](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
*
* ```js
* weight: "100 900"
* ```
*/
weight: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
/**
* A [font style](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style).
*/
style: z.ZodOptional<z.ZodEnum<["normal", "italic", "oblique"]>>;
/**
* @default `"swap"`
*
* A [font display](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display).
*/
display: z.ZodOptional<z.ZodEnum<["auto", "block", "swap", "fallback", "optional"]>>;
/**
* A [font stretch](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch).
*/
stretch: z.ZodOptional<z.ZodString>;
/**
* Font [feature settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings).
*/
featureSettings: z.ZodOptional<z.ZodString>;
/**
* Font [variation settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variation-settings).
*/
variationSettings: z.ZodOptional<z.ZodString>;
} & {
/**
* Font [sources](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src). It can be a path relative to the root, a package import or a URL. URLs are particularly useful if you inject local fonts through an integration.
*/
src: z.ZodArray<z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>, z.ZodObject<{
url: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
tech: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
url: string | URL;
tech?: string | undefined;
}, {
url: string | URL;
tech?: string | undefined;
}>]>, "atleastone">;
/**
* A [unicode range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range).
*/
unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
}, "strict", z.ZodTypeAny, {
src: [string | URL | {
url: string | URL;
tech?: string | undefined;
}, ...(string | URL | {
url: string | URL;
tech?: string | undefined;
})[]];
weight?: string | number | undefined;
style?: "normal" | "italic" | "oblique" | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}, {
src: [string | URL | {
url: string | URL;
tech?: string | undefined;
}, ...(string | URL | {
url: string | URL;
tech?: string | undefined;
})[]];
weight?: string | number | undefined;
style?: "normal" | "italic" | "oblique" | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}>, "atleastone">;
}, "strict", z.ZodTypeAny, {
name: string;
cssVariable: string;
provider: "local";
variants: [{
src: [string | URL | {
url: string | URL;
tech?: string | undefined;
}, ...(string | URL | {
url: string | URL;
tech?: string | undefined;
})[]];
weight?: string | number | undefined;
style?: "normal" | "italic" | "oblique" | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}, ...{
src: [string | URL | {
url: string | URL;
tech?: string | undefined;
}, ...(string | URL | {
url: string | URL;
tech?: string | undefined;
})[]];
weight?: string | number | undefined;
style?: "normal" | "italic" | "oblique" | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}[]];
fallbacks?: string[] | undefined;
optimizedFallbacks?: boolean | undefined;
}, {
name: string;
cssVariable: string;
provider: "local";
variants: [{
src: [string | URL | {
url: string | URL;
tech?: string | undefined;
}, ...(string | URL | {
url: string | URL;
tech?: string | undefined;
})[]];
weight?: string | number | undefined;
style?: "normal" | "italic" | "oblique" | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}, ...{
src: [string | URL | {
url: string | URL;
tech?: string | undefined;
}, ...(string | URL | {
url: string | URL;
tech?: string | undefined;
})[]];
weight?: string | number | undefined;
style?: "normal" | "italic" | "oblique" | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}[]];
fallbacks?: string[] | undefined;
optimizedFallbacks?: boolean | undefined;
}>;
export declare const remoteFontFamilySchema: z.ZodObject<{
/**
* The font family name, as identified by your font provider.
*/
name: z.ZodString;
/**
* A valid [ident](https://developer.mozilla.org/en-US/docs/Web/CSS/ident) in the form of a CSS variable (i.e. starting with `--`).
*/
cssVariable: z.ZodString;
} & Omit<{
/**
* A [font weight](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
*
* ```js
* weight: "100 900"
* ```
*/
weight: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
/**
* A [font style](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style).
*/
style: z.ZodOptional<z.ZodEnum<["normal", "italic", "oblique"]>>;
/**
* @default `"swap"`
*
* A [font display](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display).
*/
display: z.ZodOptional<z.ZodEnum<["auto", "block", "swap", "fallback", "optional"]>>;
/**
* A [font stretch](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch).
*/
stretch: z.ZodOptional<z.ZodString>;
/**
* Font [feature settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings).
*/
featureSettings: z.ZodOptional<z.ZodString>;
/**
* Font [variation settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variation-settings).
*/
variationSettings: z.ZodOptional<z.ZodString>;
}, "weight" | "style"> & {
/**
* @default `["sans-serif"]`
*
* An array of fonts to use when your chosen font is unavailable, or loading. Fallback fonts will be chosen in the order listed. The first available font will be used:
*
* ```js
* fallbacks: ["CustomFont", "serif"]
* ```
*
* To disable fallback fonts completely, configure an empty array:
*
* ```js
* fallbacks: []
* ```
*
* If the last font in the `fallbacks` array is a [generic family name](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#generic-name), Astro will attempt to generate [optimized fallbacks](https://developer.chrome.com/blog/font-fallbacks) using font metrics will be generated. To disable this optimization, set `optimizedFallbacks` to false.
*/
fallbacks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/**
* @default `true`
*
* Whether or not to enable optimized fallback generation. You may disable this default optimization to have full control over `fallbacks`.
*/
optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
} & {
/**
* The source of your font files. You can use a built-in provider or write your own custom provider.
*/
provider: z.ZodObject<{
/**
* URL, path relative to the root or package import.
*/
entrypoint: z.ZodUnion<[z.ZodString, z.ZodType<URL, z.ZodTypeDef, URL>]>;
/**
* Optional serializable object passed to the unifont provider.
*/
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
}, "strict", z.ZodTypeAny, {
entrypoint: string | URL;
config?: Record<string, any> | undefined;
}, {
entrypoint: string | URL;
config?: Record<string, any> | undefined;
}>;
/**
* @default `[400]`
*
* An array of [font weights](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
*
* ```js
* weight: "100 900"
* ```
*/
weights: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber]>, "atleastone">>;
/**
* @default `["normal", "italic"]`
*
* An array of [font styles](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style).
*/
styles: z.ZodOptional<z.ZodArray<z.ZodEnum<["normal", "italic", "oblique"]>, "atleastone">>;
/**
* @default `["cyrillic-ext", "cyrillic", "greek-ext", "greek", "vietnamese", "latin-ext", "latin"]`
*
* An array of [font subsets](https://knaap.dev/posts/font-subsetting/):
*/
subsets: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
/**
* A [unicode range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range).
*/
unicodeRange: z.ZodOptional<z.ZodArray<z.ZodString, "atleastone">>;
}, "strict", z.ZodTypeAny, {
name: string;
cssVariable: string;
provider: {
entrypoint: string | URL;
config?: Record<string, any> | undefined;
};
weights?: [string | number, ...(string | number)[]] | undefined;
styles?: ["normal" | "italic" | "oblique", ...("normal" | "italic" | "oblique")[]] | undefined;
subsets?: [string, ...string[]] | undefined;
fallbacks?: string[] | undefined;
optimizedFallbacks?: boolean | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}, {
name: string;
cssVariable: string;
provider: {
entrypoint: string | URL;
config?: Record<string, any> | undefined;
};
weights?: [string | number, ...(string | number)[]] | undefined;
styles?: ["normal" | "italic" | "oblique", ...("normal" | "italic" | "oblique")[]] | undefined;
subsets?: [string, ...string[]] | undefined;
fallbacks?: string[] | undefined;
optimizedFallbacks?: boolean | undefined;
display?: "auto" | "block" | "swap" | "fallback" | "optional" | undefined;
stretch?: string | undefined;
featureSettings?: string | undefined;
variationSettings?: string | undefined;
unicodeRange?: [string, ...string[]] | undefined;
}>;

161
node_modules/astro/dist/assets/fonts/config.js generated vendored Normal file
View File

@@ -0,0 +1,161 @@
import { z } from "zod";
import { LOCAL_PROVIDER_NAME } from "./constants.js";
const weightSchema = z.union([z.string(), z.number()]);
const styleSchema = z.enum(["normal", "italic", "oblique"]);
const unicodeRangeSchema = z.array(z.string()).nonempty();
const familyPropertiesSchema = z.object({
/**
* A [font weight](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
*
* ```js
* weight: "100 900"
* ```
*/
weight: weightSchema.optional(),
/**
* A [font style](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style).
*/
style: styleSchema.optional(),
/**
* @default `"swap"`
*
* A [font display](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display).
*/
display: z.enum(["auto", "block", "swap", "fallback", "optional"]).optional(),
/**
* A [font stretch](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch).
*/
stretch: z.string().optional(),
/**
* Font [feature settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings).
*/
featureSettings: z.string().optional(),
/**
* Font [variation settings](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-variation-settings).
*/
variationSettings: z.string().optional()
});
const fallbacksSchema = z.object({
/**
* @default `["sans-serif"]`
*
* An array of fonts to use when your chosen font is unavailable, or loading. Fallback fonts will be chosen in the order listed. The first available font will be used:
*
* ```js
* fallbacks: ["CustomFont", "serif"]
* ```
*
* To disable fallback fonts completely, configure an empty array:
*
* ```js
* fallbacks: []
* ```
*
* If the last font in the `fallbacks` array is a [generic family name](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#generic-name), Astro will attempt to generate [optimized fallbacks](https://developer.chrome.com/blog/font-fallbacks) using font metrics will be generated. To disable this optimization, set `optimizedFallbacks` to false.
*/
fallbacks: z.array(z.string()).optional(),
/**
* @default `true`
*
* Whether or not to enable optimized fallback generation. You may disable this default optimization to have full control over `fallbacks`.
*/
optimizedFallbacks: z.boolean().optional()
});
const requiredFamilyAttributesSchema = z.object({
/**
* The font family name, as identified by your font provider.
*/
name: z.string(),
/**
* A valid [ident](https://developer.mozilla.org/en-US/docs/Web/CSS/ident) in the form of a CSS variable (i.e. starting with `--`).
*/
cssVariable: z.string()
});
const entrypointSchema = z.union([z.string(), z.instanceof(URL)]);
const fontProviderSchema = z.object({
/**
* URL, path relative to the root or package import.
*/
entrypoint: entrypointSchema,
/**
* Optional serializable object passed to the unifont provider.
*/
config: z.record(z.string(), z.any()).optional()
}).strict();
const localFontFamilySchema = requiredFamilyAttributesSchema.merge(fallbacksSchema).merge(
z.object({
/**
* The source of your font files. Set to `"local"` to use local font files.
*/
provider: z.literal(LOCAL_PROVIDER_NAME),
/**
* Each variant represents a [`@font-face` declaration](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/).
*/
variants: z.array(
familyPropertiesSchema.merge(
z.object({
/**
* Font [sources](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src). It can be a path relative to the root, a package import or a URL. URLs are particularly useful if you inject local fonts through an integration.
*/
src: z.array(
z.union([
entrypointSchema,
z.object({ url: entrypointSchema, tech: z.string().optional() }).strict()
])
).nonempty(),
/**
* A [unicode range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range).
*/
unicodeRange: unicodeRangeSchema.optional()
// TODO: find a way to support subsets (through fontkit?)
}).strict()
)
).nonempty()
})
).strict();
const remoteFontFamilySchema = requiredFamilyAttributesSchema.merge(
familyPropertiesSchema.omit({
weight: true,
style: true
})
).merge(fallbacksSchema).merge(
z.object({
/**
* The source of your font files. You can use a built-in provider or write your own custom provider.
*/
provider: fontProviderSchema,
/**
* @default `[400]`
*
* An array of [font weights](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight). If the associated font is a [variable font](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide), you can specify a range of weights:
*
* ```js
* weight: "100 900"
* ```
*/
weights: z.array(weightSchema).nonempty().optional(),
/**
* @default `["normal", "italic"]`
*
* An array of [font styles](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style).
*/
styles: z.array(styleSchema).nonempty().optional(),
/**
* @default `["cyrillic-ext", "cyrillic", "greek-ext", "greek", "vietnamese", "latin-ext", "latin"]`
*
* An array of [font subsets](https://knaap.dev/posts/font-subsetting/):
*/
subsets: z.array(z.string()).nonempty().optional(),
/**
* A [unicode range](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range).
*/
unicodeRange: unicodeRangeSchema.optional()
})
).strict();
export {
fontProviderSchema,
localFontFamilySchema,
remoteFontFamilySchema,
styleSchema
};

15
node_modules/astro/dist/assets/fonts/constants.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import type { Defaults, FontType } from './types.js';
export declare const LOCAL_PROVIDER_NAME = "local";
export declare const DEFAULTS: Defaults;
/** Used to serialize data, to be used by public APIs */
export declare const VIRTUAL_MODULE_ID = "virtual:astro:assets/fonts/internal";
export declare const RESOLVED_VIRTUAL_MODULE_ID: string;
export declare const ASSETS_DIR = "fonts";
export declare const CACHE_DIR = "./fonts/";
export declare const FONT_TYPES: readonly ["woff2", "woff", "otf", "ttf", "eot"];
export declare const FONT_FORMATS: Array<{
type: FontType;
format: string;
}>;
export declare const GENERIC_FALLBACK_NAMES: readonly ["serif", "sans-serif", "monospace", "cursive", "fantasy", "system-ui", "ui-serif", "ui-sans-serif", "ui-monospace", "ui-rounded", "emoji", "math", "fangsong"];
export declare const FONTS_TYPES_FILE = "fonts.d.ts";

49
node_modules/astro/dist/assets/fonts/constants.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
const LOCAL_PROVIDER_NAME = "local";
const DEFAULTS = {
weights: ["400"],
styles: ["normal", "italic"],
subsets: ["cyrillic-ext", "cyrillic", "greek-ext", "greek", "vietnamese", "latin-ext", "latin"],
// Technically serif is the browser default but most websites these days use sans-serif
fallbacks: ["sans-serif"],
optimizedFallbacks: true
};
const VIRTUAL_MODULE_ID = "virtual:astro:assets/fonts/internal";
const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
const ASSETS_DIR = "fonts";
const CACHE_DIR = "./fonts/";
const FONT_TYPES = ["woff2", "woff", "otf", "ttf", "eot"];
const FONT_FORMATS = [
{ type: "woff2", format: "woff2" },
{ type: "woff", format: "woff" },
{ type: "otf", format: "opentype" },
{ type: "ttf", format: "truetype" },
{ type: "eot", format: "embedded-opentype" }
];
const GENERIC_FALLBACK_NAMES = [
"serif",
"sans-serif",
"monospace",
"cursive",
"fantasy",
"system-ui",
"ui-serif",
"ui-sans-serif",
"ui-monospace",
"ui-rounded",
"emoji",
"math",
"fangsong"
];
const FONTS_TYPES_FILE = "fonts.d.ts";
export {
ASSETS_DIR,
CACHE_DIR,
DEFAULTS,
FONTS_TYPES_FILE,
FONT_FORMATS,
FONT_TYPES,
GENERIC_FALLBACK_NAMES,
LOCAL_PROVIDER_NAME,
RESOLVED_VIRTUAL_MODULE_ID,
VIRTUAL_MODULE_ID
};

105
node_modules/astro/dist/assets/fonts/definitions.d.ts generated vendored Normal file
View File

@@ -0,0 +1,105 @@
import type * as unifont from 'unifont';
import type { CollectedFontForMetrics } from './logic/optimize-fallbacks.js';
import type { AstroFontProvider, FontFaceMetrics, FontFileData, FontType, GenericFallbackName, PreloadData, ResolvedFontProvider, Style } from './types.js';
export interface Hasher {
hashString: (input: string) => string;
hashObject: (input: Record<string, any>) => string;
}
export interface RemoteFontProviderModResolver {
resolve: (id: string) => Promise<any>;
}
export interface RemoteFontProviderResolver {
resolve: (provider: AstroFontProvider) => Promise<ResolvedFontProvider>;
}
export interface LocalProviderUrlResolver {
resolve: (input: string) => string;
}
type SingleErrorInput<TType extends string, TData extends Record<string, any>> = {
type: TType;
data: TData;
cause: unknown;
};
export type ErrorHandlerInput = SingleErrorInput<'cannot-load-font-provider', {
entrypoint: string;
}> | SingleErrorInput<'unknown-fs-error', {}> | SingleErrorInput<'cannot-fetch-font-file', {
url: string;
}> | SingleErrorInput<'cannot-extract-font-type', {
url: string;
}> | SingleErrorInput<'cannot-extract-data', {
family: string;
url: string;
}>;
export interface ErrorHandler {
handle: (input: ErrorHandlerInput) => Error;
}
interface ProxyData {
weight: unifont.FontFaceData['weight'];
style: unifont.FontFaceData['style'];
subset: NonNullable<unifont.FontFaceData['meta']>['subset'];
}
export interface UrlProxy {
proxy: (input: Pick<FontFileData, 'url' | 'init'> & {
type: FontType;
collectPreload: boolean;
data: ProxyData;
}) => string;
}
export interface UrlResolver {
resolve: (hash: string) => string;
getCspResources: () => Array<string>;
}
export interface UrlProxyContentResolver {
resolve: (url: string) => string;
}
export interface DataCollector {
collect: (input: FontFileData & {
data: ProxyData;
preload: PreloadData | null;
}) => void;
}
export type CssProperties = Record<string, string | undefined>;
export interface CssRenderer {
generateFontFace: (family: string, properties: CssProperties) => string;
generateCssVariable: (key: string, values: Array<string>) => string;
}
export interface FontMetricsResolver {
getMetrics: (name: string, font: CollectedFontForMetrics) => Promise<FontFaceMetrics>;
generateFontFace: (input: {
metrics: FontFaceMetrics;
fallbackMetrics: FontFaceMetrics;
name: string;
font: string;
properties: CssProperties;
}) => string;
}
export interface SystemFallbacksProvider {
getLocalFonts: (fallback: GenericFallbackName) => Array<string> | null;
getMetricsForLocalFont: (family: string) => FontFaceMetrics;
}
export interface FontFetcher {
fetch: (input: FontFileData) => Promise<Buffer>;
}
export interface FontTypeExtractor {
extract: (url: string) => FontType;
}
export interface FontFileReader {
extract: (input: {
family: string;
url: string;
}) => {
weight: string;
style: Style;
};
}
export interface UrlProxyHashResolver {
resolve: (input: {
originalUrl: string;
type: FontType;
cssVariable: string;
data: ProxyData;
}) => string;
}
export interface StringMatcher {
getClosestMatch: (target: string, candidates: Array<string>) => string;
}
export {};

0
node_modules/astro/dist/assets/fonts/definitions.js generated vendored Normal file
View File

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, }: Pick<CreateUrlProxyParams, 'hasUrl' | 'saveUrl' | 'savePreload' | 'saveFontData'>): 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,2 @@
import type { StringMatcher } from '../definitions.js';
export declare function createLevenshteinStringMatcher(): StringMatcher;

View File

@@ -0,0 +1,147 @@
const peq = new Uint32Array(65536);
const myers_32 = (a, b) => {
const n = a.length;
const m = b.length;
const lst = 1 << n - 1;
let pv = -1;
let mv = 0;
let sc = n;
let i = n;
while (i--) {
peq[a.charCodeAt(i)] |= 1 << i;
}
for (i = 0; i < m; i++) {
let eq = peq[b.charCodeAt(i)];
const xv = eq | mv;
eq |= (eq & pv) + pv ^ pv;
mv |= ~(eq | pv);
pv &= eq;
if (mv & lst) {
sc++;
}
if (pv & lst) {
sc--;
}
mv = mv << 1 | 1;
pv = pv << 1 | ~(xv | mv);
mv &= xv;
}
i = n;
while (i--) {
peq[a.charCodeAt(i)] = 0;
}
return sc;
};
const myers_x = (b, a) => {
const n = a.length;
const m = b.length;
const mhc = [];
const phc = [];
const hsize = Math.ceil(n / 32);
const vsize = Math.ceil(m / 32);
for (let i = 0; i < hsize; i++) {
phc[i] = -1;
mhc[i] = 0;
}
let j = 0;
for (; j < vsize - 1; j++) {
let mv2 = 0;
let pv2 = -1;
const start2 = j * 32;
const vlen2 = Math.min(32, m) + start2;
for (let k = start2; k < vlen2; k++) {
peq[b.charCodeAt(k)] |= 1 << k;
}
for (let i = 0; i < n; i++) {
const eq = peq[a.charCodeAt(i)];
const pb = phc[i / 32 | 0] >>> i & 1;
const mb = mhc[i / 32 | 0] >>> i & 1;
const xv = eq | mv2;
const xh = ((eq | mb) & pv2) + pv2 ^ pv2 | eq | mb;
let ph = mv2 | ~(xh | pv2);
let mh = pv2 & xh;
if (ph >>> 31 ^ pb) {
phc[i / 32 | 0] ^= 1 << i;
}
if (mh >>> 31 ^ mb) {
mhc[i / 32 | 0] ^= 1 << i;
}
ph = ph << 1 | pb;
mh = mh << 1 | mb;
pv2 = mh | ~(xv | ph);
mv2 = ph & xv;
}
for (let k = start2; k < vlen2; k++) {
peq[b.charCodeAt(k)] = 0;
}
}
let mv = 0;
let pv = -1;
const start = j * 32;
const vlen = Math.min(32, m - start) + start;
for (let k = start; k < vlen; k++) {
peq[b.charCodeAt(k)] |= 1 << k;
}
let score = m;
for (let i = 0; i < n; i++) {
const eq = peq[a.charCodeAt(i)];
const pb = phc[i / 32 | 0] >>> i & 1;
const mb = mhc[i / 32 | 0] >>> i & 1;
const xv = eq | mv;
const xh = ((eq | mb) & pv) + pv ^ pv | eq | mb;
let ph = mv | ~(xh | pv);
let mh = pv & xh;
score += ph >>> m - 1 & 1;
score -= mh >>> m - 1 & 1;
if (ph >>> 31 ^ pb) {
phc[i / 32 | 0] ^= 1 << i;
}
if (mh >>> 31 ^ mb) {
mhc[i / 32 | 0] ^= 1 << i;
}
ph = ph << 1 | pb;
mh = mh << 1 | mb;
pv = mh | ~(xv | ph);
mv = ph & xv;
}
for (let k = start; k < vlen; k++) {
peq[b.charCodeAt(k)] = 0;
}
return score;
};
const distance = (a, b) => {
if (a.length < b.length) {
const tmp = b;
b = a;
a = tmp;
}
if (b.length === 0) {
return a.length;
}
if (a.length <= 32) {
return myers_32(a, b);
}
return myers_x(a, b);
};
const closest = (str, arr) => {
let min_distance = Infinity;
let min_index = 0;
for (let i = 0; i < arr.length; i++) {
const dist = distance(str, arr[i]);
if (dist < min_distance) {
min_distance = dist;
min_index = i;
}
}
return arr[min_index];
};
function createLevenshteinStringMatcher() {
return {
getClosestMatch(target, candidates) {
return closest(target, candidates);
}
};
}
export {
createLevenshteinStringMatcher
};

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,8 @@
import type { Hasher, UrlProxyContentResolver, UrlProxyHashResolver } from '../definitions.js';
export declare function createBuildUrlProxyHashResolver({ hasher, contentResolver, }: {
hasher: Hasher;
contentResolver: UrlProxyContentResolver;
}): UrlProxyHashResolver;
export declare function createDevUrlProxyHashResolver({ baseHashResolver, }: {
baseHashResolver: UrlProxyHashResolver;
}): UrlProxyHashResolver;

View File

@@ -0,0 +1,39 @@
function createBuildUrlProxyHashResolver({
hasher,
contentResolver
}) {
return {
resolve({ originalUrl, type }) {
return `${hasher.hashString(contentResolver.resolve(originalUrl))}.${type}`;
}
};
}
function createDevUrlProxyHashResolver({
baseHashResolver
}) {
return {
resolve(input) {
const { cssVariable, data } = input;
return [
cssVariable.slice(2),
formatWeight(data.weight),
data.style,
data.subset,
baseHashResolver.resolve(input)
].filter(Boolean).join("-");
}
};
}
function formatWeight(weight) {
if (Array.isArray(weight)) {
return weight.join("-");
}
if (typeof weight === "number") {
return weight.toString();
}
return weight?.replace(/\s+/g, "-");
}
export {
createBuildUrlProxyHashResolver,
createDevUrlProxyHashResolver
};

View File

@@ -0,0 +1,7 @@
import type { DataCollector, UrlProxy, UrlProxyHashResolver, UrlResolver } from '../definitions.js';
export declare function createUrlProxy({ hashResolver, dataCollector, urlResolver, cssVariable, }: {
hashResolver: UrlProxyHashResolver;
dataCollector: DataCollector;
urlResolver: UrlResolver;
cssVariable: string;
}): UrlProxy;

View File

@@ -0,0 +1,24 @@
function createUrlProxy({
hashResolver,
dataCollector,
urlResolver,
cssVariable
}) {
return {
proxy({ url: originalUrl, type, data, collectPreload, init }) {
const hash = hashResolver.resolve({ cssVariable, data, 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,38 @@
import { fileExtension, joinPaths, prependForwardSlash } from "../../../core/path.js";
import { getAssetsPrefix } from "../../utils/getAssetsPrefix.js";
function createDevUrlResolver({ base }) {
let resolved = false;
return {
resolve(hash) {
resolved ||= true;
return prependForwardSlash(joinPaths(base, hash));
},
getCspResources() {
return resolved ? ["'self'"] : [];
}
};
}
function createBuildUrlResolver({
base,
assetsPrefix
}) {
const resources = /* @__PURE__ */ new Set();
return {
resolve(hash) {
const prefix = assetsPrefix ? getAssetsPrefix(fileExtension(hash), assetsPrefix) : void 0;
if (prefix) {
resources.add(prefix);
return joinPaths(prefix, base, hash);
}
resources.add("'self'");
return prependForwardSlash(joinPaths(base, hash));
},
getCspResources() {
return Array.from(resources);
}
};
}
export {
createBuildUrlResolver,
createDevUrlResolver
};

View File

@@ -0,0 +1,10 @@
import type * as unifont from 'unifont';
import type { Hasher } from '../definitions.js';
import type { ResolvedFontFamily } from '../types.js';
export declare function extractUnifontProviders({ families, hasher, }: {
families: Array<ResolvedFontFamily>;
hasher: Hasher;
}): {
families: Array<ResolvedFontFamily>;
providers: Array<unifont.Provider>;
};

View File

@@ -0,0 +1,28 @@
import { LOCAL_PROVIDER_NAME } from "../constants.js";
function extractUnifontProviders({
families,
hasher
}) {
const hashes = /* @__PURE__ */ new Set();
const providers = [];
for (const { provider } of families) {
if (provider === LOCAL_PROVIDER_NAME) {
continue;
}
const unifontProvider = provider.provider(provider.config);
const hash = hasher.hashObject({
name: unifontProvider._name,
...provider.config
});
unifontProvider._name += `-${hash}`;
provider.name = unifontProvider._name;
if (!hashes.has(hash)) {
hashes.add(hash);
providers.push(unifontProvider);
}
}
return { families, providers };
}
export {
extractUnifontProviders
};

View File

@@ -0,0 +1,7 @@
import type * as unifont from 'unifont';
import type { FontTypeExtractor, UrlProxy } from '../definitions.js';
export declare function normalizeRemoteFontFaces({ fonts, urlProxy, fontTypeExtractor, }: {
fonts: Array<unifont.FontFaceData>;
urlProxy: UrlProxy;
fontTypeExtractor: FontTypeExtractor;
}): Array<unifont.FontFaceData>;

View File

@@ -0,0 +1,41 @@
import { FONT_FORMATS } from "../constants.js";
function normalizeRemoteFontFaces({
fonts,
urlProxy,
fontTypeExtractor
}) {
return fonts.filter((font) => typeof font.meta?.priority === "number" ? font.meta.priority === 0 : true).map((font) => {
let index = 0;
return {
...font,
src: font.src.map((source) => {
if ("name" in source) {
return source;
}
const url = source.url.startsWith("//") ? `https:${source.url}` : source.url;
const proxied = {
...source,
originalURL: url,
url: urlProxy.proxy({
url,
type: FONT_FORMATS.find((e) => e.format === source.format)?.type ?? fontTypeExtractor.extract(source.url),
// We only collect the first URL to avoid preloading fallback sources (eg. we only
// preload woff2 if woff is available)
collectPreload: index === 0,
data: {
weight: font.weight,
style: font.style,
subset: font.meta?.subset
},
init: font.meta?.init ?? null
})
};
index++;
return proxied;
})
};
});
}
export {
normalizeRemoteFontFaces
};

View File

@@ -0,0 +1,17 @@
import type * as unifont from 'unifont';
import type { FontMetricsResolver, SystemFallbacksProvider } from '../definitions.js';
import type { FontFileData, ResolvedFontFamily } from '../types.js';
export interface CollectedFontForMetrics extends FontFileData {
data: Partial<unifont.FontFaceData>;
}
export declare function optimizeFallbacks({ family, fallbacks: _fallbacks, collectedFonts, enabled, systemFallbacksProvider, fontMetricsResolver, }: {
family: Pick<ResolvedFontFamily, 'name' | 'nameWithHash'>;
fallbacks: Array<string>;
collectedFonts: Array<CollectedFontForMetrics>;
enabled: boolean;
systemFallbacksProvider: SystemFallbacksProvider;
fontMetricsResolver: FontMetricsResolver;
}): Promise<null | {
css: string;
fallbacks: Array<string>;
}>;

View File

@@ -0,0 +1,47 @@
import { isGenericFontFamily, unifontFontFaceDataToProperties } from "../utils.js";
async function optimizeFallbacks({
family,
fallbacks: _fallbacks,
collectedFonts,
enabled,
systemFallbacksProvider,
fontMetricsResolver
}) {
let fallbacks = [..._fallbacks];
if (fallbacks.length === 0 || !enabled || collectedFonts.length === 0) {
return null;
}
const lastFallback = fallbacks[fallbacks.length - 1];
if (!isGenericFontFamily(lastFallback)) {
return null;
}
const localFonts = systemFallbacksProvider.getLocalFonts(lastFallback);
if (!localFonts || localFonts.length === 0) {
return null;
}
if (localFonts.includes(family.name)) {
return null;
}
const localFontsMappings = localFonts.map((font) => ({
font,
// We must't wrap in quote because that's handled by the CSS renderer
name: `${family.nameWithHash} fallback: ${font}`
}));
fallbacks = [...localFontsMappings.map((m) => m.name), ...fallbacks];
let css = "";
for (const { font, name } of localFontsMappings) {
for (const collected of collectedFonts) {
css += fontMetricsResolver.generateFontFace({
metrics: await fontMetricsResolver.getMetrics(family.name, collected),
fallbackMetrics: systemFallbacksProvider.getMetricsForLocalFont(font),
font,
name,
properties: unifontFontFaceDataToProperties(collected.data)
});
}
}
return { css, fallbacks };
}
export {
optimizeFallbacks
};

View File

@@ -0,0 +1,17 @@
import type { Hasher, LocalProviderUrlResolver, RemoteFontProviderResolver } from '../definitions.js';
import type { FontFamily, ResolvedFontFamily } from '../types.js';
/**
* Dedupes properties if applicable and resolves entrypoints.
*/
export declare function resolveFamily({ family, hasher, remoteFontProviderResolver, localProviderUrlResolver, }: {
family: FontFamily;
hasher: Hasher;
remoteFontProviderResolver: RemoteFontProviderResolver;
localProviderUrlResolver: LocalProviderUrlResolver;
}): Promise<ResolvedFontFamily>;
/**
* A function for convenience. The actual logic lives in resolveFamily
*/
export declare function resolveFamilies({ families, ...dependencies }: {
families: Array<FontFamily>;
} & Omit<Parameters<typeof resolveFamily>[0], 'family'>): Promise<Array<ResolvedFontFamily>>;

View File

@@ -0,0 +1,67 @@
import { LOCAL_PROVIDER_NAME } from "../constants.js";
import { dedupe, withoutQuotes } from "../utils.js";
function resolveVariants({
variants,
localProviderUrlResolver
}) {
return variants.map((variant) => ({
...variant,
weight: variant.weight?.toString(),
src: variant.src.map((value) => {
const isValue = typeof value === "string" || value instanceof URL;
const url = (isValue ? value : value.url).toString();
const tech = isValue ? void 0 : value.tech;
return {
url: localProviderUrlResolver.resolve(url),
tech
};
})
}));
}
async function resolveFamily({
family,
hasher,
remoteFontProviderResolver,
localProviderUrlResolver
}) {
const name = withoutQuotes(family.name);
const nameWithHash = `${name}-${hasher.hashObject(family)}`;
if (family.provider === LOCAL_PROVIDER_NAME) {
return {
...family,
name,
nameWithHash,
variants: resolveVariants({ variants: family.variants, localProviderUrlResolver }),
fallbacks: family.fallbacks ? dedupe(family.fallbacks) : void 0
};
}
return {
...family,
name,
nameWithHash,
weights: family.weights ? dedupe(family.weights.map((weight) => weight.toString())) : void 0,
styles: family.styles ? dedupe(family.styles) : void 0,
subsets: family.subsets ? dedupe(family.subsets) : void 0,
fallbacks: family.fallbacks ? dedupe(family.fallbacks) : void 0,
unicodeRange: family.unicodeRange ? dedupe(family.unicodeRange) : void 0,
// This will be Astro specific eventually
provider: await remoteFontProviderResolver.resolve(family.provider)
};
}
async function resolveFamilies({
families,
...dependencies
}) {
return await Promise.all(
families.map(
(family) => resolveFamily({
family,
...dependencies
})
)
);
}
export {
resolveFamilies,
resolveFamily
};

43
node_modules/astro/dist/assets/fonts/orchestrate.d.ts generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import type { Storage } from 'unstorage';
import type { Logger } from '../../core/logger/core.js';
import type { CssRenderer, FontFileReader, FontMetricsResolver, FontTypeExtractor, Hasher, LocalProviderUrlResolver, RemoteFontProviderResolver, StringMatcher, SystemFallbacksProvider, UrlProxy } from './definitions.js';
import type { ConsumableMap, CreateUrlProxyParams, Defaults, FontFamily, FontFileDataMap, InternalConsumableMap } from './types.js';
/**
* Manages how fonts are resolved:
*
* - families are resolved
* - unifont providers are extracted from families
* - unifont is initialized
*
* For each family:
* - We create a URL proxy
* - We resolve the font and normalize the result
*
* For each resolved font:
* - We generate the CSS font face
* - We generate optimized fallbacks if applicable
* - We generate CSS variables
*
* Once that's done, the collected data is returned
*/
export declare function orchestrate({ families, hasher, remoteFontProviderResolver, localProviderUrlResolver, storage, cssRenderer, systemFallbacksProvider, fontMetricsResolver, fontTypeExtractor, fontFileReader, logger, createUrlProxy, defaults, bold, stringMatcher, }: {
families: Array<FontFamily>;
hasher: Hasher;
remoteFontProviderResolver: RemoteFontProviderResolver;
localProviderUrlResolver: LocalProviderUrlResolver;
storage: Storage;
cssRenderer: CssRenderer;
systemFallbacksProvider: SystemFallbacksProvider;
fontMetricsResolver: FontMetricsResolver;
fontTypeExtractor: FontTypeExtractor;
fontFileReader: FontFileReader;
logger: Logger;
createUrlProxy: (params: CreateUrlProxyParams) => UrlProxy;
defaults: Defaults;
bold: (input: string) => string;
stringMatcher: StringMatcher;
}): Promise<{
fontFileDataMap: FontFileDataMap;
internalConsumableMap: InternalConsumableMap;
consumableMap: ConsumableMap;
}>;

160
node_modules/astro/dist/assets/fonts/orchestrate.js generated vendored Normal file
View File

@@ -0,0 +1,160 @@
import * as unifont from "unifont";
import { LOCAL_PROVIDER_NAME } from "./constants.js";
import { extractUnifontProviders } from "./logic/extract-unifont-providers.js";
import { normalizeRemoteFontFaces } from "./logic/normalize-remote-font-faces.js";
import { optimizeFallbacks } from "./logic/optimize-fallbacks.js";
import { resolveFamilies } from "./logic/resolve-families.js";
import { resolveLocalFont } from "./providers/local.js";
import {
pickFontFaceProperty,
renderFontWeight,
unifontFontFaceDataToProperties
} from "./utils.js";
async function orchestrate({
families,
hasher,
remoteFontProviderResolver,
localProviderUrlResolver,
storage,
cssRenderer,
systemFallbacksProvider,
fontMetricsResolver,
fontTypeExtractor,
fontFileReader,
logger,
createUrlProxy,
defaults,
bold,
stringMatcher
}) {
let resolvedFamilies = await resolveFamilies({
families,
hasher,
remoteFontProviderResolver,
localProviderUrlResolver
});
const extractedUnifontProvidersResult = extractUnifontProviders({
families: resolvedFamilies,
hasher
});
resolvedFamilies = extractedUnifontProvidersResult.families;
const unifontProviders = extractedUnifontProvidersResult.providers;
const { resolveFont, listFonts } = await unifont.createUnifont(unifontProviders, {
storage
});
const fontFileDataMap = /* @__PURE__ */ new Map();
const internalConsumableMap = /* @__PURE__ */ new Map();
const consumableMap = /* @__PURE__ */ new Map();
for (const family of resolvedFamilies) {
const preloadData = [];
const consumableMapValue = [];
let css = "";
const collectedFonts = [];
const fallbacks = family.fallbacks ?? defaults.fallbacks ?? [];
const urlProxy = createUrlProxy({
local: family.provider === LOCAL_PROVIDER_NAME,
hasUrl: (hash) => fontFileDataMap.has(hash),
saveUrl: ({ hash, url, init }) => {
fontFileDataMap.set(hash, { url, init });
},
savePreload: (preload) => {
preloadData.push(preload);
},
saveFontData: (collected) => {
if (fallbacks && fallbacks.length > 0 && // If the same data has already been sent for this family, we don't want to have
// duplicated fallbacks. Such scenario can occur with unicode ranges.
!collectedFonts.some((f) => JSON.stringify(f.data) === JSON.stringify(collected.data))) {
collectedFonts.push(collected);
}
},
cssVariable: family.cssVariable
});
let fonts;
if (family.provider === LOCAL_PROVIDER_NAME) {
const result = resolveLocalFont({
family,
urlProxy,
fontTypeExtractor,
fontFileReader
});
fonts = result.fonts;
} else {
const result = await resolveFont(
family.name,
// We do not merge the defaults, we only provide defaults as a fallback
{
weights: family.weights ?? defaults.weights,
styles: family.styles ?? defaults.styles,
subsets: family.subsets ?? defaults.subsets,
fallbacks: family.fallbacks ?? defaults.fallbacks
},
// By default, unifont goes through all providers. We use a different approach where
// we specify a provider per font. Name has been set while extracting unifont providers
// from families (inside extractUnifontProviders).
[family.provider.name]
);
if (result.fonts.length === 0) {
logger.warn(
"assets",
`No data found for font family ${bold(family.name)}. Review your configuration`
);
const availableFamilies = await listFonts([family.provider.name]);
if (availableFamilies && !availableFamilies.includes(family.name)) {
logger.warn(
"assets",
`${bold(family.name)} font family cannot be retrieved by the provider. Did you mean ${bold(stringMatcher.getClosestMatch(family.name, availableFamilies))}?`
);
}
}
fonts = normalizeRemoteFontFaces({ fonts: result.fonts, urlProxy, fontTypeExtractor });
}
for (const data of fonts) {
css += cssRenderer.generateFontFace(
family.nameWithHash,
unifontFontFaceDataToProperties({
src: data.src,
weight: data.weight,
style: data.style,
// User settings override the generated font settings. We use a helper function
// because local and remote providers store this data in different places.
display: pickFontFaceProperty("display", { data, family }),
unicodeRange: pickFontFaceProperty("unicodeRange", { data, family }),
stretch: pickFontFaceProperty("stretch", { data, family }),
featureSettings: pickFontFaceProperty("featureSettings", { data, family }),
variationSettings: pickFontFaceProperty("variationSettings", { data, family })
})
);
consumableMapValue.push({
weight: renderFontWeight(data.weight),
style: data.style,
src: data.src.filter((src) => "url" in src).map((src) => ({
url: src.url,
format: src.format,
tech: src.tech
}))
});
}
const cssVarValues = [family.nameWithHash];
const optimizeFallbacksResult = await optimizeFallbacks({
family,
fallbacks,
collectedFonts,
enabled: family.optimizedFallbacks ?? defaults.optimizedFallbacks ?? false,
systemFallbacksProvider,
fontMetricsResolver
});
if (optimizeFallbacksResult) {
css += optimizeFallbacksResult.css;
cssVarValues.push(...optimizeFallbacksResult.fallbacks);
} else {
cssVarValues.push(...fallbacks);
}
css += cssRenderer.generateCssVariable(family.cssVariable, cssVarValues);
internalConsumableMap.set(family.cssVariable, { preloadData, css });
consumableMap.set(family.cssVariable, consumableMapValue);
}
return { fontFileDataMap, internalConsumableMap, consumableMap };
}
export {
orchestrate
};

View File

@@ -0,0 +1,2 @@
import { providers } from 'unifont';
export declare const provider: typeof providers.adobe;

View File

@@ -0,0 +1,5 @@
import { providers } from "unifont";
const provider = providers.adobe;
export {
provider
};

View File

@@ -0,0 +1 @@
export declare const provider: () => import("unifont").Provider;

View File

@@ -0,0 +1,5 @@
import { providers } from "unifont";
const provider = providers.bunny;
export {
provider
};

View File

@@ -0,0 +1 @@
export declare const provider: () => import("unifont").Provider;

View File

@@ -0,0 +1,5 @@
import { providers } from "unifont";
const provider = providers.fontshare;
export {
provider
};

View File

@@ -0,0 +1 @@
export declare const provider: () => import("unifont").Provider;

View File

@@ -0,0 +1,5 @@
import { providers } from "unifont";
const provider = providers.fontsource;
export {
provider
};

View File

@@ -0,0 +1,2 @@
import { providers } from 'unifont';
export declare const provider: typeof providers.google;

View File

@@ -0,0 +1,5 @@
import { providers } from "unifont";
const provider = providers.google;
export {
provider
};

Some files were not shown because too many files have changed in this diff Show More