astro 7.0.0-alpha.0 → 7.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Code.astro +1 -1
- package/dist/actions/handler.d.ts +32 -0
- package/dist/actions/handler.js +45 -0
- package/dist/actions/runtime/server.js +1 -1
- package/dist/assets/build/generate.js +1 -1
- package/dist/assets/build/remote.d.ts +3 -2
- package/dist/assets/build/remote.js +16 -9
- package/dist/assets/endpoint/dev.js +1 -1
- package/dist/assets/endpoint/generic.js +8 -20
- package/dist/assets/endpoint/loadImage.d.ts +11 -0
- package/dist/assets/endpoint/loadImage.js +19 -0
- package/dist/assets/endpoint/shared.js +7 -2
- package/dist/assets/fonts/config.d.ts +4 -4
- package/dist/assets/fonts/core/optimize-fallbacks.js +38 -13
- package/dist/assets/fonts/definitions.d.ts +2 -2
- package/dist/assets/fonts/infra/system-fallbacks-provider.d.ts +2 -2
- package/dist/assets/fonts/infra/system-fallbacks-provider.js +46 -9
- package/dist/assets/fonts/types.d.ts +1 -0
- package/dist/assets/index.d.ts +1 -0
- package/dist/assets/index.js +2 -0
- package/dist/assets/internal.js +22 -3
- package/dist/assets/services/service.d.ts +1 -1
- package/dist/assets/services/service.js +9 -9
- package/dist/assets/services/sharp.js +53 -18
- package/dist/assets/utils/generateImageStylesCSS.js +26 -6
- package/dist/assets/utils/index.d.ts +1 -0
- package/dist/assets/utils/index.js +2 -0
- package/dist/assets/utils/inferSourceFormat.d.ts +8 -3
- package/dist/assets/utils/inferSourceFormat.js +15 -4
- package/dist/assets/utils/metadata.js +1 -1
- package/dist/assets/utils/redirectValidation.d.ts +48 -0
- package/dist/assets/utils/redirectValidation.js +48 -0
- package/dist/assets/utils/remoteProbe.js +25 -2
- package/dist/assets/utils/vendor/image-size/types/svg.js +1 -1
- package/dist/cli/add/index.js +7 -58
- package/dist/cli/dev/background.d.ts +16 -0
- package/dist/cli/dev/background.js +116 -0
- package/dist/cli/dev/index.js +82 -3
- package/dist/cli/dev/logs.d.ts +6 -0
- package/dist/cli/dev/logs.js +72 -0
- package/dist/cli/dev/status.d.ts +15 -0
- package/dist/cli/dev/status.js +27 -0
- package/dist/cli/dev/stop.d.ts +12 -0
- package/dist/cli/dev/stop.js +43 -0
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/container/index.js +18 -14
- package/dist/content/content-layer.js +16 -11
- package/dist/content/data-store.d.ts +1 -1
- package/dist/content/loaders/types.d.ts +1 -1
- package/dist/content/runtime-assets.d.ts +2 -2
- package/dist/content/runtime.d.ts +1 -1
- package/dist/content/runtime.js +9 -4
- package/dist/content/server-listeners.js +0 -4
- package/dist/content/types-generator.js +5 -1
- package/dist/content/utils.d.ts +1 -1
- package/dist/content/utils.js +1 -1
- package/dist/content/vite-plugin-content-assets.js +1 -0
- package/dist/content/vite-plugin-content-virtual-mod.js +9 -1
- package/dist/core/app/base.d.ts +42 -15
- package/dist/core/app/base.js +151 -375
- package/dist/core/app/dev/app.d.ts +3 -2
- package/dist/core/app/dev/app.js +4 -60
- package/dist/core/app/entrypoints/node.d.ts +1 -1
- package/dist/core/app/entrypoints/node.js +2 -0
- package/dist/core/app/entrypoints/virtual/dev.js +2 -0
- package/dist/core/app/entrypoints/virtual/prod.js +4 -1
- package/dist/core/app/node.d.ts +16 -0
- package/dist/core/app/node.js +59 -13
- package/dist/core/app/prepare-response.d.ts +11 -0
- package/dist/core/app/prepare-response.js +18 -0
- package/dist/core/app/render-options.d.ts +11 -0
- package/dist/core/app/render-options.js +11 -0
- package/dist/core/base-pipeline.d.ts +48 -1
- package/dist/core/base-pipeline.js +63 -8
- package/dist/core/build/app.d.ts +3 -4
- package/dist/core/build/app.js +3 -17
- package/dist/core/build/generate.js +8 -1
- package/dist/core/build/index.d.ts +0 -11
- package/dist/core/build/index.js +0 -3
- package/dist/core/build/internal.d.ts +7 -0
- package/dist/core/build/plugins/plugin-chunk-imports.d.ts +6 -0
- package/dist/core/build/plugins/plugin-chunk-imports.js +29 -17
- package/dist/core/build/plugins/plugin-css.js +40 -1
- package/dist/core/build/plugins/plugin-internals.js +1 -1
- package/dist/core/build/plugins/plugin-manifest.js +11 -1
- package/dist/core/build/static-build.js +22 -141
- package/dist/core/build/types.d.ts +0 -1
- package/dist/core/build/util.js +8 -1
- package/dist/core/build/vite-build-config.d.ts +28 -0
- package/dist/core/build/vite-build-config.js +165 -0
- package/dist/core/cache/handler.d.ts +29 -0
- package/dist/core/cache/handler.js +81 -0
- package/dist/core/compile/style.js +18 -1
- package/dist/core/config/index.d.ts +1 -1
- package/dist/core/config/index.js +4 -1
- package/dist/core/config/merge.js +4 -0
- package/dist/core/config/schemas/base.d.ts +25 -13
- package/dist/core/config/schemas/base.js +39 -10
- package/dist/core/config/schemas/relative.d.ts +76 -49
- package/dist/core/config/schemas/relative.js +2 -3
- package/dist/core/config/settings.js +2 -4
- package/dist/core/config/tsconfig.d.ts +24 -9
- package/dist/core/config/tsconfig.js +54 -45
- package/dist/core/config/validate.js +59 -0
- package/dist/core/constants.d.ts +27 -1
- package/dist/core/constants.js +14 -1
- package/dist/core/cookies/cookies.d.ts +7 -2
- package/dist/core/cookies/cookies.js +11 -4
- package/dist/core/cookies/response.d.ts +1 -1
- package/dist/core/cookies/response.js +1 -2
- package/dist/core/create-vite.js +18 -1
- package/dist/core/csp/config.js +17 -5
- package/dist/core/csp/runtime.js +6 -4
- package/dist/core/dev/dev.d.ts +1 -0
- package/dist/core/dev/dev.js +4 -13
- package/dist/core/dev/lockfile.d.ts +54 -0
- package/dist/core/dev/lockfile.js +93 -0
- package/dist/core/errors/build-handler.d.ts +17 -0
- package/dist/core/errors/build-handler.js +22 -0
- package/dist/core/errors/default-handler.d.ts +14 -0
- package/dist/core/errors/default-handler.js +144 -0
- package/dist/core/errors/dev-handler.d.ts +21 -0
- package/dist/core/errors/dev-handler.js +82 -0
- package/dist/core/errors/errors-data.d.ts +43 -38
- package/dist/core/errors/errors-data.js +79 -73
- package/dist/core/errors/handler.d.ts +9 -0
- package/dist/core/errors/handler.js +0 -0
- package/dist/core/errors/zod-error-map.js +30 -1
- package/dist/core/fetch/default-handler.d.ts +17 -0
- package/dist/core/fetch/default-handler.js +45 -0
- package/dist/core/fetch/fetch-state.d.ts +230 -0
- package/dist/core/fetch/fetch-state.js +896 -0
- package/dist/core/fetch/index.d.ts +61 -0
- package/dist/core/fetch/index.js +121 -0
- package/dist/core/fetch/types.d.ts +25 -0
- package/dist/core/fetch/types.js +0 -0
- package/dist/core/fetch/vite-plugin.d.ts +5 -0
- package/dist/core/fetch/vite-plugin.js +76 -0
- package/dist/core/hono/index.d.ts +21 -0
- package/dist/core/hono/index.js +101 -0
- package/dist/core/i18n/domain.d.ts +12 -0
- package/dist/core/i18n/domain.js +66 -0
- package/dist/core/i18n/handler.d.ts +18 -0
- package/dist/core/i18n/handler.js +122 -0
- package/dist/core/logger/core.d.ts +9 -1
- package/dist/core/logger/core.js +17 -1
- package/dist/core/messages/runtime.d.ts +0 -3
- package/dist/core/messages/runtime.js +1 -9
- package/dist/core/middleware/astro-middleware.d.ts +27 -0
- package/dist/core/middleware/astro-middleware.js +51 -0
- package/dist/core/module-loader/vite.js +1 -2
- package/dist/core/pages/handler.d.ts +20 -0
- package/dist/core/pages/handler.js +75 -0
- package/dist/core/preview/index.js +6 -5
- package/dist/core/preview/static-preview-server.js +5 -2
- package/dist/core/redirects/render.d.ts +2 -2
- package/dist/core/redirects/render.js +7 -8
- package/dist/core/render/params-and-props.js +2 -2
- package/dist/core/render/route-cache.d.ts +1 -0
- package/dist/core/render/route-cache.js +4 -4
- package/dist/core/render/slots.js +9 -2
- package/dist/core/rewrites/handler.d.ts +37 -0
- package/dist/core/rewrites/handler.js +67 -0
- package/dist/core/routing/3xx.js +8 -4
- package/dist/core/routing/create-manifest.js +11 -1
- package/dist/core/routing/handler.d.ts +17 -0
- package/dist/core/routing/handler.js +171 -0
- package/dist/core/routing/match.d.ts +0 -7
- package/dist/core/routing/match.js +0 -5
- package/dist/core/routing/parse-route.js +1 -1
- package/dist/core/routing/pattern.js +1 -1
- package/dist/core/routing/rewrite.js +2 -5
- package/dist/core/routing/router.d.ts +8 -0
- package/dist/core/routing/router.js +28 -0
- package/dist/core/routing/trailing-slash-handler.d.ts +18 -0
- package/dist/core/routing/trailing-slash-handler.js +67 -0
- package/dist/core/routing/validation.js +1 -1
- package/dist/core/server-islands/vite-plugin-server-islands.d.ts +6 -1
- package/dist/core/server-islands/vite-plugin-server-islands.js +13 -3
- package/dist/core/session/config.d.ts +1 -1
- package/dist/core/session/drivers.d.ts +1 -1
- package/dist/core/session/handler.d.ts +11 -0
- package/dist/core/session/handler.js +33 -0
- package/dist/core/session/runtime.js +7 -2
- package/dist/core/util/normalized-url.d.ts +10 -0
- package/dist/core/util/normalized-url.js +24 -0
- package/dist/core/util/pathname.d.ts +10 -1
- package/dist/core/util/pathname.js +13 -4
- package/dist/environments.js +1 -1
- package/dist/events/session.d.ts +8 -0
- package/dist/events/session.js +11 -0
- package/dist/i18n/middleware.d.ts +10 -0
- package/dist/i18n/middleware.js +4 -88
- package/dist/i18n/utils.js +2 -2
- package/dist/jsx/rehype.d.ts +1 -1
- package/dist/manifest/virtual-module.js +3 -1
- package/dist/markdown/index.d.ts +4 -0
- package/dist/markdown/index.js +14 -0
- package/dist/prefetch/index.js +12 -7
- package/dist/prerender/utils.js +5 -1
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +9 -0
- package/dist/runtime/server/astro-island.js +57 -20
- package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
- package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt.js +1 -1
- package/dist/runtime/server/jsx.js +1 -1
- package/dist/runtime/server/render/common.js +10 -4
- package/dist/runtime/server/render/component.js +8 -6
- package/dist/runtime/server/render/head.js +1 -5
- package/dist/runtime/server/render/server-islands.js +2 -1
- package/dist/runtime/server/render/util.js +2 -2
- package/dist/runtime/server/scripts.js +6 -0
- package/dist/runtime/server/transition.d.ts +1 -6
- package/dist/runtime/server/transition.js +0 -8
- package/dist/transitions/events.d.ts +0 -14
- package/dist/transitions/events.js +0 -14
- package/dist/transitions/index.d.ts +0 -1
- package/dist/transitions/index.js +0 -2
- package/dist/transitions/vite-plugin-transitions.js +2 -4
- package/dist/types/public/config.d.ts +96 -14
- package/dist/types/public/content.d.ts +5 -5
- package/dist/types/public/index.d.ts +2 -1
- package/dist/types/public/integrations.d.ts +11 -3
- package/dist/types/public/internal.d.ts +1 -1
- package/dist/types/public/manifest.d.ts +1 -1
- package/dist/virtual-modules/i18n.d.ts +2 -2
- package/dist/virtual-modules/i18n.js +1 -1
- package/dist/vite-plugin-app/app.d.ts +13 -6
- package/dist/vite-plugin-app/app.js +51 -89
- package/dist/vite-plugin-app/createAstroServerApp.d.ts +3 -1
- package/dist/vite-plugin-app/createAstroServerApp.js +4 -3
- package/dist/vite-plugin-astro-server/plugin.js +11 -5
- package/dist/vite-plugin-astro-server/route-guard.d.ts +33 -0
- package/dist/vite-plugin-astro-server/route-guard.js +42 -23
- package/dist/vite-plugin-dev-status/index.d.ts +2 -0
- package/dist/vite-plugin-dev-status/index.js +15 -0
- package/dist/vite-plugin-head/index.js +36 -19
- package/dist/vite-plugin-hmr-reload/index.d.ts +1 -1
- package/dist/vite-plugin-hmr-reload/index.js +23 -1
- package/dist/vite-plugin-integrations-container/index.js +15 -6
- package/dist/vite-plugin-markdown/content-entry-type.js +7 -4
- package/dist/vite-plugin-markdown/images.js +9 -11
- package/dist/vite-plugin-markdown/index.js +12 -11
- package/dist/vite-plugin-utils/index.d.ts +1 -0
- package/dist/vite-plugin-utils/index.js +10 -1
- package/package.json +23 -16
- package/templates/content/types.d.ts +1 -0
- package/types/transitions.d.ts +0 -7
- package/dist/core/render-context.d.ts +0 -77
- package/dist/core/render-context.js +0 -826
package/components/Code.astro
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { createShikiHighlighter, type ThemePresets } from '@astrojs/
|
|
2
|
+
import { createShikiHighlighter, type ThemePresets } from '@astrojs/internal-helpers/shiki';
|
|
3
3
|
import type { ShikiTransformer, ThemeRegistration, ThemeRegistrationRaw } from 'shiki';
|
|
4
4
|
import { bundledLanguages } from 'shiki/langs';
|
|
5
5
|
import type { CodeLanguage } from '../dist/types/public/common.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { APIContext } from '../types/public/context.js';
|
|
2
|
+
import type { FetchState } from '../core/fetch/fetch-state.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handles Astro Action requests in both modes:
|
|
5
|
+
*
|
|
6
|
+
* - **RPC**: POST requests to `/_actions/<name>` (originating from the
|
|
7
|
+
* generated JS client). Runs the action and returns the serialized result
|
|
8
|
+
* as the response, so the caller can short-circuit rendering.
|
|
9
|
+
* - **Form**: POST requests with `?_action=<name>` targeting a page route
|
|
10
|
+
* (originating from an HTML `<form action={actions.foo}>`). Runs the
|
|
11
|
+
* action, stashes the result into `locals._actionPayload`, and returns
|
|
12
|
+
* `undefined` so the caller continues to render the page.
|
|
13
|
+
*
|
|
14
|
+
* Non-action requests are a no-op (`undefined`).
|
|
15
|
+
*
|
|
16
|
+
* This handler is invoked at the bottom of the middleware chain, before
|
|
17
|
+
* page dispatch. That placement preserves the existing behavior where
|
|
18
|
+
* user middleware sees action requests and response finalization (cookies,
|
|
19
|
+
* sessions, etc.) runs around the action response.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ActionHandler {
|
|
22
|
+
#private;
|
|
23
|
+
/**
|
|
24
|
+
* Run action handling for the current request. Expects the APIContext
|
|
25
|
+
* that is already being used by the render pipeline.
|
|
26
|
+
*
|
|
27
|
+
* Returns a `Response` when the action fully handles the request (RPC),
|
|
28
|
+
* or `undefined` when the caller should continue processing the
|
|
29
|
+
* request (form actions or non-action requests).
|
|
30
|
+
*/
|
|
31
|
+
handle(apiContext: APIContext, state: FetchState): Promise<Response | undefined> | undefined;
|
|
32
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PipelineFeatures } from "../core/base-pipeline.js";
|
|
2
|
+
import { getActionContext, serializeActionResult } from "./runtime/server.js";
|
|
3
|
+
class ActionHandler {
|
|
4
|
+
/**
|
|
5
|
+
* Run action handling for the current request. Expects the APIContext
|
|
6
|
+
* that is already being used by the render pipeline.
|
|
7
|
+
*
|
|
8
|
+
* Returns a `Response` when the action fully handles the request (RPC),
|
|
9
|
+
* or `undefined` when the caller should continue processing the
|
|
10
|
+
* request (form actions or non-action requests).
|
|
11
|
+
*/
|
|
12
|
+
handle(apiContext, state) {
|
|
13
|
+
state.pipeline.usedFeatures |= PipelineFeatures.actions;
|
|
14
|
+
if (apiContext.isPrerendered) {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
const { action, setActionResult } = getActionContext(apiContext);
|
|
18
|
+
if (!action) {
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
return this.#executeAction(action, setActionResult);
|
|
22
|
+
}
|
|
23
|
+
async #executeAction(action, setActionResult) {
|
|
24
|
+
const actionResult = await action.handler();
|
|
25
|
+
const serialized = serializeActionResult(actionResult);
|
|
26
|
+
if (action.calledFrom === "rpc") {
|
|
27
|
+
if (serialized.type === "empty") {
|
|
28
|
+
return new Response(null, {
|
|
29
|
+
status: serialized.status
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return new Response(serialized.body, {
|
|
33
|
+
status: serialized.status,
|
|
34
|
+
headers: {
|
|
35
|
+
"Content-Type": serialized.contentType
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
setActionResult(action.name, serialized);
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
ActionHandler
|
|
45
|
+
};
|
|
@@ -266,7 +266,7 @@ function handleFormDataGetAll(key, formData, validator) {
|
|
|
266
266
|
if (elementValidator instanceof z.$ZodNumber) {
|
|
267
267
|
return entries.map(Number);
|
|
268
268
|
} else if (elementValidator instanceof z.$ZodBoolean) {
|
|
269
|
-
return entries.map(Boolean);
|
|
269
|
+
return entries.map((v) => v === "true" ? true : v === "false" ? false : Boolean(v));
|
|
270
270
|
}
|
|
271
271
|
return entries;
|
|
272
272
|
}
|
|
@@ -234,7 +234,7 @@ function getStaticImageList() {
|
|
|
234
234
|
}
|
|
235
235
|
async function loadImage(path, env) {
|
|
236
236
|
if (isRemotePath(path)) {
|
|
237
|
-
return await loadRemoteImage(path);
|
|
237
|
+
return await loadRemoteImage(path, void 0, env.imageConfig);
|
|
238
238
|
}
|
|
239
239
|
return {
|
|
240
240
|
data: await fs.promises.readFile(getFullImagePath(path, env)),
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { type RemoteImageConfig } from '../utils/redirectValidation.js';
|
|
1
2
|
export type RemoteCacheEntry = {
|
|
2
3
|
data?: string;
|
|
3
4
|
expires: number;
|
|
4
5
|
etag?: string;
|
|
5
6
|
lastModified?: string;
|
|
6
7
|
};
|
|
7
|
-
export declare function loadRemoteImage(src: string, fetchFn?: typeof fetch): Promise<{
|
|
8
|
+
export declare function loadRemoteImage(src: string, fetchFn?: typeof fetch, imageConfig?: RemoteImageConfig): Promise<{
|
|
8
9
|
data: Buffer<ArrayBuffer>;
|
|
9
10
|
expires: number;
|
|
10
11
|
etag: string | undefined;
|
|
@@ -22,7 +23,7 @@ export declare function loadRemoteImage(src: string, fetchFn?: typeof fetch): Pr
|
|
|
22
23
|
export declare function revalidateRemoteImage(src: string, revalidationData: {
|
|
23
24
|
etag?: string;
|
|
24
25
|
lastModified?: string;
|
|
25
|
-
}, fetchFn?: typeof fetch): Promise<{
|
|
26
|
+
}, fetchFn?: typeof fetch, imageConfig?: RemoteImageConfig): Promise<{
|
|
26
27
|
data: Buffer<ArrayBuffer> | null;
|
|
27
28
|
expires: number;
|
|
28
29
|
etag: string | undefined;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import CachePolicy from "http-cache-semantics";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const res = await
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { fetchWithRedirects } from "../utils/redirectValidation.js";
|
|
3
|
+
async function loadRemoteImage(src, fetchFn = globalThis.fetch, imageConfig = { remotePatterns: [], domains: [] }) {
|
|
4
|
+
const res = await fetchWithRedirects({
|
|
5
|
+
url: src,
|
|
6
|
+
fetchFn,
|
|
7
|
+
imageConfig
|
|
8
|
+
});
|
|
8
9
|
if (!res.ok) {
|
|
9
10
|
throw new Error(
|
|
10
11
|
`Failed to load remote image ${src}. The request did not return a 200 OK response. (received ${res.status}))`
|
|
11
12
|
);
|
|
12
13
|
}
|
|
14
|
+
const req = new Request(src);
|
|
13
15
|
const policy = new CachePolicy(webToCachePolicyRequest(req), webToCachePolicyResponse(res));
|
|
14
16
|
const expires = policy.storable() ? policy.timeToLive() : 0;
|
|
15
17
|
return {
|
|
@@ -19,13 +21,18 @@ async function loadRemoteImage(src, fetchFn = globalThis.fetch) {
|
|
|
19
21
|
lastModified: res.headers.get("Last-Modified") ?? void 0
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
|
-
async function revalidateRemoteImage(src, revalidationData, fetchFn = globalThis.fetch) {
|
|
24
|
+
async function revalidateRemoteImage(src, revalidationData, fetchFn = globalThis.fetch, imageConfig = { remotePatterns: [], domains: [] }) {
|
|
23
25
|
const headers = {
|
|
24
26
|
...revalidationData.etag && { "If-None-Match": revalidationData.etag },
|
|
25
27
|
...revalidationData.lastModified && { "If-Modified-Since": revalidationData.lastModified }
|
|
26
28
|
};
|
|
27
29
|
const req = new Request(src, { headers, cache: "no-cache" });
|
|
28
|
-
const res = await
|
|
30
|
+
const res = await fetchWithRedirects({
|
|
31
|
+
url: src,
|
|
32
|
+
headers: new Headers(headers),
|
|
33
|
+
imageConfig,
|
|
34
|
+
fetchFn
|
|
35
|
+
});
|
|
29
36
|
if (!res.ok && res.status !== 304) {
|
|
30
37
|
if (res.status >= 300 && res.status < 400) {
|
|
31
38
|
throw new Error(
|
|
@@ -38,7 +45,7 @@ async function revalidateRemoteImage(src, revalidationData, fetchFn = globalThis
|
|
|
38
45
|
}
|
|
39
46
|
const data = Buffer.from(await res.arrayBuffer());
|
|
40
47
|
if (res.ok && !data.length) {
|
|
41
|
-
return await loadRemoteImage(src, fetchFn);
|
|
48
|
+
return await loadRemoteImage(src, fetchFn, imageConfig);
|
|
42
49
|
}
|
|
43
50
|
const policy = new CachePolicy(
|
|
44
51
|
webToCachePolicyRequest(req),
|
|
@@ -4,24 +4,7 @@ import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
|
|
|
4
4
|
import * as mime from "mrmime";
|
|
5
5
|
import { getConfiguredImageService } from "../internal.js";
|
|
6
6
|
import { etag } from "../utils/etag.js";
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
const res = await fetch(src, {
|
|
10
|
-
// Forward all headers from the original request
|
|
11
|
-
headers,
|
|
12
|
-
redirect: "manual"
|
|
13
|
-
});
|
|
14
|
-
if (res.status >= 300 && res.status < 400) {
|
|
15
|
-
return void 0;
|
|
16
|
-
}
|
|
17
|
-
if (!res.ok) {
|
|
18
|
-
return void 0;
|
|
19
|
-
}
|
|
20
|
-
return await res.arrayBuffer();
|
|
21
|
-
} catch {
|
|
22
|
-
return void 0;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
7
|
+
import { loadImage } from "./loadImage.js";
|
|
25
8
|
const GET = async ({ request }) => {
|
|
26
9
|
try {
|
|
27
10
|
const imageService = await getConfiguredImageService();
|
|
@@ -42,7 +25,12 @@ const GET = async ({ request }) => {
|
|
|
42
25
|
if (!isRemoteImage && sourceUrl.origin !== url.origin) {
|
|
43
26
|
return new Response("Forbidden", { status: 403 });
|
|
44
27
|
}
|
|
45
|
-
inputBuffer = await
|
|
28
|
+
inputBuffer = await loadImage(
|
|
29
|
+
sourceUrl,
|
|
30
|
+
isRemoteImage ? new Headers() : request.headers,
|
|
31
|
+
imageConfig,
|
|
32
|
+
isRemoteImage
|
|
33
|
+
);
|
|
46
34
|
if (!inputBuffer) {
|
|
47
35
|
return new Response("Not Found", { status: 404 });
|
|
48
36
|
}
|
|
@@ -62,7 +50,7 @@ const GET = async ({ request }) => {
|
|
|
62
50
|
});
|
|
63
51
|
} catch (err) {
|
|
64
52
|
console.error("Could not process image request:", err);
|
|
65
|
-
return new Response(
|
|
53
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
66
54
|
}
|
|
67
55
|
};
|
|
68
56
|
export {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RemoteImageConfig } from '../utils/redirectValidation.js';
|
|
2
|
+
/**
|
|
3
|
+
* Fetches an image by URL. Used by the generic image endpoint for both
|
|
4
|
+
* remote images and local images (self-fetched from the same origin).
|
|
5
|
+
*
|
|
6
|
+
* For remote images, the final URL (after any redirects) is validated
|
|
7
|
+
* against `imageConfig.domains` and `imageConfig.remotePatterns`.
|
|
8
|
+
* Local images skip this check — they are already guarded by the
|
|
9
|
+
* same-origin check in the caller.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadImage(src: URL, headers: Headers, imageConfig: RemoteImageConfig, isRemote: boolean, fetchFn?: typeof globalThis.fetch): Promise<ArrayBuffer | undefined>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
|
|
2
|
+
import { fetchWithRedirects } from "../utils/redirectValidation.js";
|
|
3
|
+
async function loadImage(src, headers, imageConfig, isRemote, fetchFn) {
|
|
4
|
+
try {
|
|
5
|
+
const res = await fetchWithRedirects({ url: src, headers, imageConfig, fetchFn });
|
|
6
|
+
if (isRemote && !isRemoteAllowed(res.url, imageConfig)) {
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
if (!res.ok) {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
return await res.arrayBuffer();
|
|
13
|
+
} catch {
|
|
14
|
+
return void 0;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
loadImage
|
|
19
|
+
};
|
|
@@ -5,10 +5,15 @@ import * as mime from "mrmime";
|
|
|
5
5
|
import { getConfiguredImageService } from "../internal.js";
|
|
6
6
|
import { etag } from "../utils/etag.js";
|
|
7
7
|
import { inferSourceFormat } from "../utils/inferSourceFormat.js";
|
|
8
|
+
import { fetchWithRedirects } from "../utils/redirectValidation.js";
|
|
9
|
+
const isLocal = (url) => {
|
|
10
|
+
const hostname = new URL(url).hostname;
|
|
11
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
12
|
+
};
|
|
8
13
|
async function loadRemoteImage(src) {
|
|
9
14
|
try {
|
|
10
|
-
const res = await
|
|
11
|
-
if (res.
|
|
15
|
+
const res = await fetchWithRedirects({ url: src, imageConfig });
|
|
16
|
+
if (!isRemoteAllowed(res.url, imageConfig) && !isLocal(res.url)) {
|
|
12
17
|
return void 0;
|
|
13
18
|
}
|
|
14
19
|
if (!res.ok) {
|
|
@@ -7,11 +7,11 @@ export declare const StyleSchema: z.ZodEnum<{
|
|
|
7
7
|
oblique: "oblique";
|
|
8
8
|
}>;
|
|
9
9
|
export declare const DisplaySchema: z.ZodEnum<{
|
|
10
|
-
optional: "optional";
|
|
11
10
|
auto: "auto";
|
|
11
|
+
optional: "optional";
|
|
12
|
+
fallback: "fallback";
|
|
12
13
|
block: "block";
|
|
13
14
|
swap: "swap";
|
|
14
|
-
fallback: "fallback";
|
|
15
15
|
}>;
|
|
16
16
|
export declare const FontProviderSchema: z.ZodCustom<FontProvider<never>, FontProvider<never>>;
|
|
17
17
|
export declare const FontFamilySchema: z.ZodObject<{
|
|
@@ -45,11 +45,11 @@ export declare const FontFamilySchema: z.ZodObject<{
|
|
|
45
45
|
fallbacks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
46
|
optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
|
|
47
47
|
display: z.ZodOptional<z.ZodEnum<{
|
|
48
|
-
optional: "optional";
|
|
49
48
|
auto: "auto";
|
|
49
|
+
optional: "optional";
|
|
50
|
+
fallback: "fallback";
|
|
50
51
|
block: "block";
|
|
51
52
|
swap: "swap";
|
|
52
|
-
fallback: "fallback";
|
|
53
53
|
}>>;
|
|
54
54
|
stretch: z.ZodOptional<z.ZodString>;
|
|
55
55
|
featureSettings: z.ZodOptional<z.ZodString>;
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { isGenericFontFamily, unifontFontFaceDataToProperties } from "../utils.js";
|
|
2
|
+
function deriveFallbackVariant(data) {
|
|
3
|
+
const weight = data.weight;
|
|
4
|
+
if (typeof weight === "number" && weight >= 700) {
|
|
5
|
+
return "bold";
|
|
6
|
+
}
|
|
7
|
+
if (typeof weight === "string") {
|
|
8
|
+
if (weight === "bold") return "bold";
|
|
9
|
+
if (weight.includes(" ")) return "normal";
|
|
10
|
+
const n = Number.parseInt(weight, 10);
|
|
11
|
+
if (!Number.isNaN(n) && n >= 700) return "bold";
|
|
12
|
+
}
|
|
13
|
+
return "normal";
|
|
14
|
+
}
|
|
2
15
|
async function optimizeFallbacks({
|
|
3
16
|
family,
|
|
4
17
|
fallbacks: _fallbacks,
|
|
@@ -14,28 +27,40 @@ async function optimizeFallbacks({
|
|
|
14
27
|
if (!isGenericFontFamily(lastFallback)) {
|
|
15
28
|
return null;
|
|
16
29
|
}
|
|
17
|
-
const
|
|
18
|
-
|
|
30
|
+
const collectedWithLocalFonts = collectedFonts.map((collected) => ({
|
|
31
|
+
collected,
|
|
32
|
+
localFonts: systemFallbacksProvider.getLocalFonts(lastFallback, deriveFallbackVariant(collected.data)) ?? []
|
|
33
|
+
}));
|
|
34
|
+
const uniqueLocalFonts = [];
|
|
35
|
+
for (const { localFonts } of collectedWithLocalFonts) {
|
|
36
|
+
for (const font of localFonts) {
|
|
37
|
+
if (!uniqueLocalFonts.includes(font)) {
|
|
38
|
+
uniqueLocalFonts.push(font);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (uniqueLocalFonts.length === 0) {
|
|
19
43
|
return null;
|
|
20
44
|
}
|
|
21
|
-
if (
|
|
45
|
+
if (uniqueLocalFonts.includes(family.name)) {
|
|
22
46
|
return null;
|
|
23
47
|
}
|
|
24
|
-
const
|
|
25
|
-
font,
|
|
48
|
+
const nameForFont = (font) => (
|
|
26
49
|
// We mustn't wrap in quote because that's handled by the CSS renderer
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
fallbacks = [...
|
|
50
|
+
`${family.uniqueName} fallback: ${font}`
|
|
51
|
+
);
|
|
52
|
+
fallbacks = [...uniqueLocalFonts.map(nameForFont), ...fallbacks];
|
|
30
53
|
let css = "";
|
|
31
|
-
for (const {
|
|
32
|
-
|
|
54
|
+
for (const { collected, localFonts } of collectedWithLocalFonts) {
|
|
55
|
+
const properties = unifontFontFaceDataToProperties(collected.data);
|
|
56
|
+
const metrics = await fontMetricsResolver.getMetrics(family.name, collected);
|
|
57
|
+
for (const font of localFonts) {
|
|
33
58
|
css += fontMetricsResolver.generateFontFace({
|
|
34
|
-
metrics
|
|
59
|
+
metrics,
|
|
35
60
|
fallbackMetrics: systemFallbacksProvider.getMetricsForLocalFont(font),
|
|
36
61
|
font,
|
|
37
|
-
name,
|
|
38
|
-
properties
|
|
62
|
+
name: nameForFont(font),
|
|
63
|
+
properties
|
|
39
64
|
});
|
|
40
65
|
}
|
|
41
66
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as unifont from 'unifont';
|
|
2
2
|
import type { CollectedFontForMetrics } from './core/optimize-fallbacks.js';
|
|
3
|
-
import type { CssProperties, FontFaceMetrics, FontFileData, FontProvider, FontType, GenericFallbackName, ResolveFontOptions, Style } from './types.js';
|
|
3
|
+
import type { CssProperties, FallbackVariant, FontFaceMetrics, FontFileData, FontProvider, FontType, GenericFallbackName, ResolveFontOptions, Style } from './types.js';
|
|
4
4
|
export interface Hasher {
|
|
5
5
|
hashString: (input: string) => string;
|
|
6
6
|
hashObject: (input: Record<string, any>) => string;
|
|
@@ -28,7 +28,7 @@ export interface FontMetricsResolver {
|
|
|
28
28
|
}) => string;
|
|
29
29
|
}
|
|
30
30
|
export interface SystemFallbacksProvider {
|
|
31
|
-
getLocalFonts: (fallback: GenericFallbackName) => Array<string> | null;
|
|
31
|
+
getLocalFonts: (fallback: GenericFallbackName, variant: FallbackVariant) => Array<string> | null;
|
|
32
32
|
getMetricsForLocalFont: (family: string) => FontFaceMetrics;
|
|
33
33
|
}
|
|
34
34
|
export interface FontFetcher {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SystemFallbacksProvider } from '../definitions.js';
|
|
2
|
-
import type { FontFaceMetrics, GenericFallbackName } from '../types.js';
|
|
2
|
+
import type { FallbackVariant, FontFaceMetrics, GenericFallbackName } from '../types.js';
|
|
3
3
|
export declare class RealSystemFallbacksProvider implements SystemFallbacksProvider {
|
|
4
|
-
getLocalFonts(fallback: GenericFallbackName): Array<string> | null;
|
|
4
|
+
getLocalFonts(fallback: GenericFallbackName, variant: FallbackVariant): Array<string> | null;
|
|
5
5
|
getMetricsForLocalFont(family: string): FontFaceMetrics;
|
|
6
6
|
}
|
|
@@ -6,6 +6,14 @@ const SYSTEM_METRICS = {
|
|
|
6
6
|
unitsPerEm: 2048,
|
|
7
7
|
xWidthAvg: 832
|
|
8
8
|
},
|
|
9
|
+
"Times New Roman Bold": {
|
|
10
|
+
ascent: 1825,
|
|
11
|
+
descent: -443,
|
|
12
|
+
lineGap: 87,
|
|
13
|
+
unitsPerEm: 2048,
|
|
14
|
+
xWidthAvg: 886
|
|
15
|
+
},
|
|
16
|
+
// Times New Roman Italic almost has the same properties as Times New Roman, we don't include it
|
|
9
17
|
Arial: {
|
|
10
18
|
ascent: 1854,
|
|
11
19
|
descent: -434,
|
|
@@ -13,6 +21,14 @@ const SYSTEM_METRICS = {
|
|
|
13
21
|
unitsPerEm: 2048,
|
|
14
22
|
xWidthAvg: 913
|
|
15
23
|
},
|
|
24
|
+
"Arial Bold": {
|
|
25
|
+
ascent: 1854,
|
|
26
|
+
descent: -434,
|
|
27
|
+
lineGap: 67,
|
|
28
|
+
unitsPerEm: 2048,
|
|
29
|
+
xWidthAvg: 983
|
|
30
|
+
},
|
|
31
|
+
// Arial Italic has the same properties as Arial, we don't include it
|
|
16
32
|
"Courier New": {
|
|
17
33
|
ascent: 1705,
|
|
18
34
|
descent: -615,
|
|
@@ -20,6 +36,8 @@ const SYSTEM_METRICS = {
|
|
|
20
36
|
unitsPerEm: 2048,
|
|
21
37
|
xWidthAvg: 1229
|
|
22
38
|
},
|
|
39
|
+
// Courier New Bold has the same properties as Courier New, we don't include it
|
|
40
|
+
// Courier New Italic has the same properties as Courier New, we don't include it
|
|
23
41
|
BlinkMacSystemFont: {
|
|
24
42
|
ascent: 1980,
|
|
25
43
|
descent: -432,
|
|
@@ -50,17 +68,36 @@ const SYSTEM_METRICS = {
|
|
|
50
68
|
}
|
|
51
69
|
};
|
|
52
70
|
const DEFAULT_FALLBACKS = {
|
|
53
|
-
serif:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
serif: {
|
|
72
|
+
normal: ["Times New Roman"],
|
|
73
|
+
bold: ["Times New Roman Bold"]
|
|
74
|
+
},
|
|
75
|
+
"sans-serif": {
|
|
76
|
+
normal: ["Arial"],
|
|
77
|
+
bold: ["Arial Bold"]
|
|
78
|
+
},
|
|
79
|
+
monospace: { normal: ["Courier New"] },
|
|
80
|
+
"system-ui": {
|
|
81
|
+
normal: ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial"],
|
|
82
|
+
bold: ["BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial Bold"]
|
|
83
|
+
},
|
|
84
|
+
"ui-serif": {
|
|
85
|
+
normal: ["Times New Roman"],
|
|
86
|
+
bold: ["Times New Roman Bold"]
|
|
87
|
+
},
|
|
88
|
+
"ui-sans-serif": {
|
|
89
|
+
normal: ["Arial"],
|
|
90
|
+
bold: ["Arial Bold"]
|
|
91
|
+
},
|
|
92
|
+
"ui-monospace": { normal: ["Courier New"] }
|
|
60
93
|
};
|
|
61
94
|
class RealSystemFallbacksProvider {
|
|
62
|
-
getLocalFonts(fallback) {
|
|
63
|
-
|
|
95
|
+
getLocalFonts(fallback, variant) {
|
|
96
|
+
const entry = DEFAULT_FALLBACKS[fallback];
|
|
97
|
+
if (!entry) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return entry[variant] ?? entry.normal ?? null;
|
|
64
101
|
}
|
|
65
102
|
getMetricsForLocalFont(family) {
|
|
66
103
|
return SYSTEM_METRICS[family];
|
|
@@ -191,6 +191,7 @@ export interface PreloadData {
|
|
|
191
191
|
}
|
|
192
192
|
export type FontFaceMetrics = Pick<Font, 'ascent' | 'descent' | 'lineGap' | 'unitsPerEm' | 'xWidthAvg'>;
|
|
193
193
|
export type GenericFallbackName = (typeof GENERIC_FALLBACK_NAMES)[number];
|
|
194
|
+
export type FallbackVariant = 'normal' | 'bold';
|
|
194
195
|
export type Defaults = Required<Pick<ResolvedFontFamily, 'weights' | 'styles' | 'subsets' | 'fallbacks' | 'optimizedFallbacks' | 'formats'>>;
|
|
195
196
|
export interface FontFileData {
|
|
196
197
|
id: string;
|
package/dist/assets/index.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { getConfiguredImageService, getImage, verifyOptions } from './internal.j
|
|
|
2
2
|
export { baseService, isLocalService } from './services/service.js';
|
|
3
3
|
export { hashTransform, propsToFilename } from './utils/hash.js';
|
|
4
4
|
export type { LocalImageProps, RemoteImageProps } from './types.js';
|
|
5
|
+
export { fetchWithRedirects } from './utils/redirectValidation.js';
|
package/dist/assets/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { getConfiguredImageService, getImage, verifyOptions } from "./internal.js";
|
|
2
2
|
import { baseService, isLocalService } from "./services/service.js";
|
|
3
3
|
import { hashTransform, propsToFilename } from "./utils/hash.js";
|
|
4
|
+
import { fetchWithRedirects } from "./utils/redirectValidation.js";
|
|
4
5
|
export {
|
|
5
6
|
baseService,
|
|
7
|
+
fetchWithRedirects,
|
|
6
8
|
getConfiguredImageService,
|
|
7
9
|
getImage,
|
|
8
10
|
hashTransform,
|
package/dist/assets/internal.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
isImageMetadata
|
|
14
14
|
} from "./types.js";
|
|
15
15
|
import { isESMImportedImage, isRemoteImage, resolveSrc } from "./utils/imageKind.js";
|
|
16
|
+
import { resolveDefaultOutputFormat } from "./utils/inferSourceFormat.js";
|
|
16
17
|
import { inferRemoteSize } from "./utils/remoteProbe.js";
|
|
17
18
|
import { createPlaceholderURL, stringifyPlaceholderURL } from "./utils/url.js";
|
|
18
19
|
import { verifyOptions } from "./services/service.js";
|
|
@@ -73,6 +74,9 @@ async function getImage(options, imageConfig) {
|
|
|
73
74
|
const result = await getRemoteSize(resolvedOptions.src);
|
|
74
75
|
resolvedOptions.width ??= result.width;
|
|
75
76
|
resolvedOptions.height ??= result.height;
|
|
77
|
+
if (result.format) {
|
|
78
|
+
resolvedOptions.format ??= resolveDefaultOutputFormat(result.format);
|
|
79
|
+
}
|
|
76
80
|
originalWidth = result.width;
|
|
77
81
|
originalHeight = result.height;
|
|
78
82
|
}
|
|
@@ -122,11 +126,15 @@ async function getImage(options, imageConfig) {
|
|
|
122
126
|
if (resolvedOptions.fit && cssFitValues.includes(resolvedOptions.fit)) {
|
|
123
127
|
resolvedOptions["data-astro-image-fit"] = resolvedOptions.fit;
|
|
124
128
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
129
|
+
const currentPosition = resolvedOptions.position || "center";
|
|
130
|
+
resolvedOptions["data-astro-image-pos"] = currentPosition.replace(/\s+/g, "-");
|
|
128
131
|
}
|
|
129
132
|
const validatedOptions = service.validateOptions ? await service.validateOptions(resolvedOptions, imageConfig) : resolvedOptions;
|
|
133
|
+
validatedOptions.format ??= await peekRemoteFormatForStaticEmit(
|
|
134
|
+
validatedOptions,
|
|
135
|
+
imageConfig,
|
|
136
|
+
service
|
|
137
|
+
);
|
|
130
138
|
const srcSetTransforms = service.getSrcSet ? await service.getSrcSet(validatedOptions, imageConfig) : [];
|
|
131
139
|
const lazyImageURLFactory = (getValue) => {
|
|
132
140
|
let cached = null;
|
|
@@ -188,6 +196,17 @@ async function getImage(options, imageConfig) {
|
|
|
188
196
|
attributes: service.getHTMLAttributes !== void 0 ? await service.getHTMLAttributes(validatedOptions, imageConfig) : {}
|
|
189
197
|
};
|
|
190
198
|
}
|
|
199
|
+
async function peekRemoteFormatForStaticEmit(options, imageConfig, service) {
|
|
200
|
+
if (!isRemoteImage(options.src) || !isRemoteAllowed(options.src, imageConfig) || !globalThis.astroAsset?.addStaticImage || !isLocalService(service) || !service.getRemoteSize) {
|
|
201
|
+
return void 0;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const probed = await service.getRemoteSize(options.src, imageConfig);
|
|
205
|
+
return resolveDefaultOutputFormat(probed.format);
|
|
206
|
+
} catch {
|
|
207
|
+
return void 0;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
191
210
|
export {
|
|
192
211
|
cssFitValues,
|
|
193
212
|
getConfiguredImageService,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
|
|
2
2
|
import { AstroError, AstroErrorData } from "../../core/errors/index.js";
|
|
3
3
|
import { isRemotePath, joinPaths } from "../../core/path.js";
|
|
4
|
-
import { DEFAULT_HASH_PROPS,
|
|
4
|
+
import { DEFAULT_HASH_PROPS, VALID_SUPPORTED_FORMATS } from "../consts.js";
|
|
5
5
|
import { isESMImportedImage, isRemoteImage } from "../utils/imageKind.js";
|
|
6
|
+
import { inferSourceFormat, resolveDefaultOutputFormat } from "../utils/inferSourceFormat.js";
|
|
6
7
|
import { inferRemoteSize } from "../utils/remoteProbe.js";
|
|
7
8
|
function isLocalService(service) {
|
|
8
9
|
if (!service) {
|
|
@@ -74,10 +75,11 @@ const baseService = {
|
|
|
74
75
|
validateOptions(options) {
|
|
75
76
|
verifyOptions(options);
|
|
76
77
|
if (!options.format) {
|
|
77
|
-
if (isESMImportedImage(options.src)
|
|
78
|
-
options.format =
|
|
78
|
+
if (isESMImportedImage(options.src)) {
|
|
79
|
+
options.format = resolveDefaultOutputFormat(options.src.format);
|
|
79
80
|
} else {
|
|
80
|
-
|
|
81
|
+
const inferred = inferSourceFormat(options.src);
|
|
82
|
+
if (inferred) options.format = resolveDefaultOutputFormat(inferred);
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
if (options.width) options.width = Math.round(options.width);
|
|
@@ -120,7 +122,7 @@ const baseService = {
|
|
|
120
122
|
const { targetWidth, targetHeight } = getTargetDimensions(options);
|
|
121
123
|
const aspectRatio = targetWidth / targetHeight;
|
|
122
124
|
const { widths, densities } = options;
|
|
123
|
-
const targetFormat = options.format
|
|
125
|
+
const targetFormat = options.format;
|
|
124
126
|
let transformedWidths = (widths ?? []).sort(sortNumeric);
|
|
125
127
|
let imageWidth = options.width;
|
|
126
128
|
let maxWidth = Number.POSITIVE_INFINITY;
|
|
@@ -164,9 +166,7 @@ const baseService = {
|
|
|
164
166
|
return {
|
|
165
167
|
transform,
|
|
166
168
|
descriptor,
|
|
167
|
-
attributes: {
|
|
168
|
-
type: `image/${targetFormat}`
|
|
169
|
-
}
|
|
169
|
+
attributes: targetFormat ? { type: `image/${targetFormat}` } : {}
|
|
170
170
|
};
|
|
171
171
|
});
|
|
172
172
|
},
|
|
@@ -210,7 +210,7 @@ const baseService = {
|
|
|
210
210
|
src: params.get("href"),
|
|
211
211
|
width: params.has("w") ? Number.parseInt(params.get("w")) : void 0,
|
|
212
212
|
height: params.has("h") ? Number.parseInt(params.get("h")) : void 0,
|
|
213
|
-
format: params.get("f"),
|
|
213
|
+
format: params.has("f") ? params.get("f") : void 0,
|
|
214
214
|
quality: params.get("q"),
|
|
215
215
|
fit: params.get("fit"),
|
|
216
216
|
position: params.get("position") ?? void 0,
|