astro 4.2.2 → 4.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/astro.d.ts +1 -1
- package/dist/cli/db/index.js +5 -3
- package/dist/core/app/index.js +11 -14
- package/dist/core/app/ssrPipeline.d.ts +0 -10
- package/dist/core/app/ssrPipeline.js +0 -19
- package/dist/core/build/buildPipeline.js +0 -4
- package/dist/core/build/generate.js +2 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/logger/core.d.ts +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/pipeline.d.ts +0 -8
- package/dist/core/pipeline.js +1 -29
- package/dist/core/routing/manifest/create.js +46 -17
- package/dist/prerender/utils.js +1 -1
- package/dist/runtime/client/dev-toolbar/apps/audit/a11y.js +1 -1
- package/dist/runtime/client/dev-toolbar/apps/settings.js +2 -2
- package/dist/runtime/client/dev-toolbar/entrypoint.js +1 -1
- package/dist/runtime/client/dev-toolbar/settings.d.ts +4 -1
- package/dist/runtime/client/dev-toolbar/settings.js +8 -1
- package/dist/runtime/client/dev-toolbar/toolbar.d.ts +1 -0
- package/dist/runtime/client/dev-toolbar/toolbar.js +28 -6
- package/dist/runtime/server/endpoint.js +4 -7
- package/dist/vite-plugin-astro-server/devPipeline.js +0 -4
- package/dist/vite-plugin-dev-toolbar/vite-plugin-dev-toolbar.d.ts +1 -1
- package/dist/vite-plugin-dev-toolbar/vite-plugin-dev-toolbar.js +39 -2
- package/dist/vite-plugin-html/transform/escape.js +12 -5
- package/dist/vite-plugin-html/transform/slots.js +6 -2
- package/dist/vite-plugin-html/transform/utils.d.ts +2 -2
- package/dist/vite-plugin-html/transform/utils.js +26 -7
- package/dist/vite-plugin-markdown/images.js +4 -1
- package/package.json +2 -2
package/dist/@types/astro.d.ts
CHANGED
|
@@ -2401,7 +2401,7 @@ export interface ClientDirectiveConfig {
|
|
|
2401
2401
|
export interface DevToolbarApp {
|
|
2402
2402
|
id: string;
|
|
2403
2403
|
name: string;
|
|
2404
|
-
icon
|
|
2404
|
+
icon?: Icon;
|
|
2405
2405
|
init?(canvas: ShadowRoot, eventTarget: EventTarget): void | Promise<void>;
|
|
2406
2406
|
beforeTogglingOff?(canvas: ShadowRoot): boolean | Promise<boolean>;
|
|
2407
2407
|
}
|
package/dist/cli/db/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { createLoggerFromFlags } from "../flags.js";
|
|
1
|
+
import { createLoggerFromFlags, flagsToAstroInlineConfig } from "../flags.js";
|
|
2
2
|
import { getPackage } from "../install-package.js";
|
|
3
|
+
import { resolveConfig } from "../../core/config/config.js";
|
|
3
4
|
async function db({ flags }) {
|
|
4
5
|
const logger = createLoggerFromFlags(flags);
|
|
5
6
|
const getPackageOpts = { skipAsk: flags.yes || flags.y, cwd: flags.root };
|
|
@@ -12,8 +13,9 @@ async function db({ flags }) {
|
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
const { cli } = dbPackage;
|
|
15
|
-
const
|
|
16
|
-
await
|
|
16
|
+
const inlineConfig = flagsToAstroInlineConfig(flags);
|
|
17
|
+
const { astroConfig } = await resolveConfig(inlineConfig, "build");
|
|
18
|
+
await cli({ flags, config: astroConfig });
|
|
17
19
|
}
|
|
18
20
|
export {
|
|
19
21
|
db
|
package/dist/core/app/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
createStylesheetElementSet
|
|
18
18
|
} from "../render/ssr-element.js";
|
|
19
19
|
import { matchRoute } from "../routing/match.js";
|
|
20
|
-
import {
|
|
20
|
+
import { SSRRoutePipeline } from "./ssrPipeline.js";
|
|
21
21
|
import { deserializeManifest } from "./common.js";
|
|
22
22
|
const localsSymbol = Symbol.for("astro.locals");
|
|
23
23
|
const clientAddressSymbol = Symbol.for("astro.clientAddress");
|
|
@@ -187,20 +187,17 @@ class App {
|
|
|
187
187
|
}
|
|
188
188
|
response = await this.#pipeline.renderRoute(renderContext, pageModule);
|
|
189
189
|
} catch (err) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
} else {
|
|
193
|
-
this.#logger.error(null, err.stack || err.message || String(err));
|
|
194
|
-
return this.#renderError(request, { status: 500 });
|
|
195
|
-
}
|
|
190
|
+
this.#logger.error(null, err.stack || err.message || String(err));
|
|
191
|
+
return this.#renderError(request, { status: 500 });
|
|
196
192
|
}
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
193
|
+
if (REROUTABLE_STATUS_CODES.has(response.status) && response.headers.get("X-Astro-Reroute") !== "no") {
|
|
194
|
+
return this.#renderError(request, {
|
|
195
|
+
response,
|
|
196
|
+
status: response.status
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (response.headers.has("X-Astro-Reroute")) {
|
|
200
|
+
response.headers.delete("X-Astro-Reroute");
|
|
204
201
|
}
|
|
205
202
|
if (addCookieHeader) {
|
|
206
203
|
for (const setCookieHeaderValue of App.getSetCookieFromResponse(response)) {
|
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
import { Pipeline } from '../pipeline.js';
|
|
2
|
-
import type { Environment } from '../render/index.js';
|
|
3
|
-
/**
|
|
4
|
-
* Thrown when an endpoint contains a response with the header "X-Astro-Response" === 'Not-Found'
|
|
5
|
-
*/
|
|
6
|
-
export declare class EndpointNotFoundError extends Error {
|
|
7
|
-
originalResponse: Response;
|
|
8
|
-
constructor(originalResponse: Response);
|
|
9
|
-
}
|
|
10
2
|
export declare class SSRRoutePipeline extends Pipeline {
|
|
11
|
-
#private;
|
|
12
|
-
constructor(env: Environment);
|
|
13
3
|
}
|
|
@@ -1,25 +1,6 @@
|
|
|
1
1
|
import { Pipeline } from "../pipeline.js";
|
|
2
|
-
class EndpointNotFoundError extends Error {
|
|
3
|
-
originalResponse;
|
|
4
|
-
constructor(originalResponse) {
|
|
5
|
-
super();
|
|
6
|
-
this.originalResponse = originalResponse;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
2
|
class SSRRoutePipeline extends Pipeline {
|
|
10
|
-
constructor(env) {
|
|
11
|
-
super(env);
|
|
12
|
-
this.setEndpointHandler(this.#ssrEndpointHandler);
|
|
13
|
-
}
|
|
14
|
-
// This function is responsible for handling the result coming from an endpoint.
|
|
15
|
-
async #ssrEndpointHandler(request, response) {
|
|
16
|
-
if (response.headers.get("X-Astro-Response") === "Not-Found") {
|
|
17
|
-
throw new EndpointNotFoundError(response);
|
|
18
|
-
}
|
|
19
|
-
return response;
|
|
20
|
-
}
|
|
21
3
|
}
|
|
22
4
|
export {
|
|
23
|
-
EndpointNotFoundError,
|
|
24
5
|
SSRRoutePipeline
|
|
25
6
|
};
|
|
@@ -51,7 +51,6 @@ class BuildPipeline extends Pipeline {
|
|
|
51
51
|
this.#internals = internals;
|
|
52
52
|
this.#staticBuildOptions = staticBuildOptions;
|
|
53
53
|
this.#manifest = manifest;
|
|
54
|
-
this.setEndpointHandler(this.#handleEndpointResult);
|
|
55
54
|
}
|
|
56
55
|
getInternals() {
|
|
57
56
|
return this.#internals;
|
|
@@ -143,9 +142,6 @@ class BuildPipeline extends Pipeline {
|
|
|
143
142
|
}
|
|
144
143
|
return pages;
|
|
145
144
|
}
|
|
146
|
-
async #handleEndpointResult(_, response) {
|
|
147
|
-
return response;
|
|
148
|
-
}
|
|
149
145
|
}
|
|
150
146
|
export {
|
|
151
147
|
BuildPipeline
|
|
@@ -347,7 +347,8 @@ function getUrlForPath(pathname, base, origin, format, routeType) {
|
|
|
347
347
|
async function generatePath(pathname, pipeline, gopts, route) {
|
|
348
348
|
const { mod, scripts: hoistedScripts, styles: _styles } = gopts;
|
|
349
349
|
const manifest = pipeline.getManifest();
|
|
350
|
-
pipeline.
|
|
350
|
+
const logger = pipeline.getLogger();
|
|
351
|
+
logger.debug("build", `Generating: ${pathname}`);
|
|
351
352
|
const links = /* @__PURE__ */ new Set();
|
|
352
353
|
const scripts = createModuleScriptsSet(
|
|
353
354
|
hoistedScripts ? [hoistedScripts] : [],
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -23,7 +23,7 @@ async function dev(inlineConfig) {
|
|
|
23
23
|
base: restart.container.settings.config.base
|
|
24
24
|
})
|
|
25
25
|
);
|
|
26
|
-
const currentVersion = "4.2.
|
|
26
|
+
const currentVersion = "4.2.4";
|
|
27
27
|
if (currentVersion.includes("-")) {
|
|
28
28
|
logger.warn("SKIP_FORMAT", msg.prerelease({ currentVersion }));
|
|
29
29
|
}
|
|
@@ -7,7 +7,7 @@ export type LoggerLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
|
7
7
|
* rather than specific to a single command, function, use, etc. The label will be
|
|
8
8
|
* shown in the log message to the user, so it should be relevant.
|
|
9
9
|
*/
|
|
10
|
-
export type LoggerLabel = 'add' | 'build' | 'check' | 'config' | 'content' | 'deprecated' | 'markdown' | 'router' | 'types' | 'vite' | 'watch' | 'middleware' | 'preferences' | 'redirects' | 'SKIP_FORMAT';
|
|
10
|
+
export type LoggerLabel = 'add' | 'build' | 'check' | 'config' | 'content' | 'deprecated' | 'markdown' | 'router' | 'types' | 'vite' | 'watch' | 'middleware' | 'preferences' | 'redirects' | 'toolbar' | 'SKIP_FORMAT';
|
|
11
11
|
export interface LogOptions {
|
|
12
12
|
dest: LogWritable<LogMessage>;
|
|
13
13
|
level: LoggerLevel;
|
package/dist/core/messages.js
CHANGED
|
@@ -36,7 +36,7 @@ function serverStart({
|
|
|
36
36
|
host,
|
|
37
37
|
base
|
|
38
38
|
}) {
|
|
39
|
-
const version = "4.2.
|
|
39
|
+
const version = "4.2.4";
|
|
40
40
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
41
41
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
42
42
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -258,7 +258,7 @@ function printHelp({
|
|
|
258
258
|
message.push(
|
|
259
259
|
linebreak(),
|
|
260
260
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
261
|
-
`v${"4.2.
|
|
261
|
+
`v${"4.2.4"}`
|
|
262
262
|
)} ${headline}`
|
|
263
263
|
);
|
|
264
264
|
}
|
package/dist/core/pipeline.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ComponentInstance, MiddlewareHandler } from '../@types/astro.js';
|
|
2
2
|
import { type Environment, type RenderContext } from './render/index.js';
|
|
3
|
-
type EndpointResultHandler = (originalRequest: Request, result: Response) => Promise<Response> | Response;
|
|
4
3
|
export type PipelineHookFunction = (ctx: RenderContext, mod: ComponentInstance | undefined) => void;
|
|
5
4
|
/**
|
|
6
5
|
* This is the basic class of a pipeline.
|
|
@@ -16,12 +15,6 @@ export declare class Pipeline {
|
|
|
16
15
|
*/
|
|
17
16
|
constructor(env: Environment);
|
|
18
17
|
setEnvironment(): void;
|
|
19
|
-
/**
|
|
20
|
-
* When rendering a route, an "endpoint" will a type that needs to be handled and transformed into a `Response`.
|
|
21
|
-
*
|
|
22
|
-
* Each consumer might have different needs; use this function to set up the handler.
|
|
23
|
-
*/
|
|
24
|
-
setEndpointHandler(handler: EndpointResultHandler): void;
|
|
25
18
|
/**
|
|
26
19
|
* A middleware function that will be called before each request.
|
|
27
20
|
*/
|
|
@@ -44,4 +37,3 @@ export declare class Pipeline {
|
|
|
44
37
|
*/
|
|
45
38
|
onBeforeRenderRoute(fn: PipelineHookFunction): void;
|
|
46
39
|
}
|
|
47
|
-
export {};
|
package/dist/core/pipeline.js
CHANGED
|
@@ -8,11 +8,6 @@ class Pipeline {
|
|
|
8
8
|
#hooks = {
|
|
9
9
|
before: []
|
|
10
10
|
};
|
|
11
|
-
/**
|
|
12
|
-
* The handler accepts the *original* `Request` and result returned by the endpoint.
|
|
13
|
-
* It must return a `Response`.
|
|
14
|
-
*/
|
|
15
|
-
#endpointHandler;
|
|
16
11
|
/**
|
|
17
12
|
* When creating a pipeline, an environment is mandatory.
|
|
18
13
|
* The environment won't change for the whole lifetime of the pipeline.
|
|
@@ -22,14 +17,6 @@ class Pipeline {
|
|
|
22
17
|
}
|
|
23
18
|
setEnvironment() {
|
|
24
19
|
}
|
|
25
|
-
/**
|
|
26
|
-
* When rendering a route, an "endpoint" will a type that needs to be handled and transformed into a `Response`.
|
|
27
|
-
*
|
|
28
|
-
* Each consumer might have different needs; use this function to set up the handler.
|
|
29
|
-
*/
|
|
30
|
-
setEndpointHandler(handler) {
|
|
31
|
-
this.#endpointHandler = handler;
|
|
32
|
-
}
|
|
33
20
|
/**
|
|
34
21
|
* A middleware function that will be called before each request.
|
|
35
22
|
*/
|
|
@@ -55,22 +42,7 @@ class Pipeline {
|
|
|
55
42
|
for (const hook of this.#hooks.before) {
|
|
56
43
|
hook(renderContext, componentInstance);
|
|
57
44
|
}
|
|
58
|
-
|
|
59
|
-
renderContext,
|
|
60
|
-
this.env,
|
|
61
|
-
componentInstance,
|
|
62
|
-
this.#onRequest
|
|
63
|
-
);
|
|
64
|
-
if (renderContext.route.type === "endpoint") {
|
|
65
|
-
if (!this.#endpointHandler) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
"You created a pipeline that does not know how to handle the result coming from an endpoint."
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
return this.#endpointHandler(renderContext.request, result);
|
|
71
|
-
} else {
|
|
72
|
-
return result;
|
|
73
|
-
}
|
|
45
|
+
return await this.#tryRenderRoute(renderContext, this.env, componentInstance, this.#onRequest);
|
|
74
46
|
}
|
|
75
47
|
/**
|
|
76
48
|
* It attempts to render a route. A route can be a:
|
|
@@ -99,28 +99,57 @@ function isSemanticallyEqualSegment(segmentA, segmentB) {
|
|
|
99
99
|
return true;
|
|
100
100
|
}
|
|
101
101
|
function routeComparator(a, b) {
|
|
102
|
+
const commonLength = Math.min(a.segments.length, b.segments.length);
|
|
103
|
+
for (let index = 0; index < commonLength; index++) {
|
|
104
|
+
const aSegment = a.segments[index];
|
|
105
|
+
const bSegment = b.segments[index];
|
|
106
|
+
const aIsStatic = aSegment.every((part) => !part.dynamic && !part.spread);
|
|
107
|
+
const bIsStatic = bSegment.every((part) => !part.dynamic && !part.spread);
|
|
108
|
+
if (aIsStatic && bIsStatic) {
|
|
109
|
+
const aContent = aSegment.map((part) => part.content).join("");
|
|
110
|
+
const bContent = bSegment.map((part) => part.content).join("");
|
|
111
|
+
if (aContent !== bContent) {
|
|
112
|
+
return aContent.localeCompare(bContent);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (aIsStatic !== bIsStatic) {
|
|
116
|
+
return aIsStatic ? -1 : 1;
|
|
117
|
+
}
|
|
118
|
+
const aHasSpread = aSegment.some((part) => part.spread);
|
|
119
|
+
const bHasSpread = bSegment.some((part) => part.spread);
|
|
120
|
+
if (aHasSpread !== bHasSpread) {
|
|
121
|
+
return aHasSpread ? 1 : -1;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (Math.abs(a.segments.length - b.segments.length) === 1) {
|
|
125
|
+
const aEndsInRest = a.segments.at(-1)?.some((part) => part.spread);
|
|
126
|
+
const bEndsInRest = b.segments.at(-1)?.some((part) => part.spread);
|
|
127
|
+
if (a.segments.length > b.segments.length && !bEndsInRest) {
|
|
128
|
+
return 1;
|
|
129
|
+
}
|
|
130
|
+
if (b.segments.length > a.segments.length && !aEndsInRest) {
|
|
131
|
+
return -1;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (a.isIndex !== b.isIndex) {
|
|
135
|
+
if (a.isIndex) {
|
|
136
|
+
const followingBSegment = b.segments.at(a.segments.length);
|
|
137
|
+
const followingBSegmentIsStatic = followingBSegment?.every(
|
|
138
|
+
(part) => !part.dynamic && !part.spread
|
|
139
|
+
);
|
|
140
|
+
return followingBSegmentIsStatic ? 1 : -1;
|
|
141
|
+
}
|
|
142
|
+
const followingASegment = a.segments.at(b.segments.length);
|
|
143
|
+
const followingASegmentIsStatic = followingASegment?.every(
|
|
144
|
+
(part) => !part.dynamic && !part.spread
|
|
145
|
+
);
|
|
146
|
+
return followingASegmentIsStatic ? -1 : 1;
|
|
147
|
+
}
|
|
102
148
|
const aLength = a.isIndex ? a.segments.length + 1 : a.segments.length;
|
|
103
149
|
const bLength = b.isIndex ? b.segments.length + 1 : b.segments.length;
|
|
104
150
|
if (aLength !== bLength) {
|
|
105
151
|
return aLength > bLength ? -1 : 1;
|
|
106
152
|
}
|
|
107
|
-
const aIsStatic = a.segments.every(
|
|
108
|
-
(segment) => segment.every((part) => !part.dynamic && !part.spread)
|
|
109
|
-
);
|
|
110
|
-
const bIsStatic = b.segments.every(
|
|
111
|
-
(segment) => segment.every((part) => !part.dynamic && !part.spread)
|
|
112
|
-
);
|
|
113
|
-
if (aIsStatic !== bIsStatic) {
|
|
114
|
-
return aIsStatic ? -1 : 1;
|
|
115
|
-
}
|
|
116
|
-
const aHasSpread = a.segments.some((segment) => segment.some((part) => part.spread));
|
|
117
|
-
const bHasSpread = b.segments.some((segment) => segment.some((part) => part.spread));
|
|
118
|
-
if (aHasSpread !== bHasSpread) {
|
|
119
|
-
return aHasSpread ? 1 : -1;
|
|
120
|
-
}
|
|
121
|
-
if (a.prerender !== b.prerender) {
|
|
122
|
-
return a.prerender ? -1 : 1;
|
|
123
|
-
}
|
|
124
153
|
if (a.type === "endpoint" !== (b.type === "endpoint")) {
|
|
125
154
|
return a.type === "endpoint" ? -1 : 1;
|
|
126
155
|
}
|
package/dist/prerender/utils.js
CHANGED
|
@@ -3,7 +3,7 @@ function isServerLikeOutput(config) {
|
|
|
3
3
|
return config.output === "server" || config.output === "hybrid";
|
|
4
4
|
}
|
|
5
5
|
function getPrerenderDefault(config) {
|
|
6
|
-
return config.output
|
|
6
|
+
return config.output !== "server";
|
|
7
7
|
}
|
|
8
8
|
function getOutputDirectory(config) {
|
|
9
9
|
const ssr = isServerLikeOutput(config);
|
|
@@ -193,7 +193,7 @@ const ariaAttributes = new Set(
|
|
|
193
193
|
)
|
|
194
194
|
);
|
|
195
195
|
const ariaRoles = new Set(
|
|
196
|
-
"alert alertdialog application article banner button cell checkbox columnheader combobox complementary contentinfo definition dialog directory document feed figure form grid gridcell group heading img link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search searchbox separator slider spinbutton status tab tablist tabpanel textbox timer toolbar tooltip tree treegrid treeitem".split(
|
|
196
|
+
"alert alertdialog application article banner button cell checkbox columnheader combobox complementary contentinfo definition dialog directory document feed figure form grid gridcell group heading img link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search searchbox separator slider spinbutton status switch tab tablist tabpanel textbox timer toolbar tooltip tree treegrid treeitem".split(
|
|
197
197
|
" "
|
|
198
198
|
)
|
|
199
199
|
);
|
|
@@ -14,7 +14,7 @@ const settingsRows = [
|
|
|
14
14
|
}
|
|
15
15
|
settings.updateSetting("disableAppNotification", evt.currentTarget.checked);
|
|
16
16
|
const action = evt.currentTarget.checked ? "disabled" : "enabled";
|
|
17
|
-
settings.
|
|
17
|
+
settings.logger.verboseLog(`App notification badges ${action}`);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
},
|
|
@@ -27,7 +27,7 @@ const settingsRows = [
|
|
|
27
27
|
if (evt.currentTarget instanceof HTMLInputElement) {
|
|
28
28
|
settings.updateSetting("verbose", evt.currentTarget.checked);
|
|
29
29
|
const action = evt.currentTarget.checked ? "enabled" : "disabled";
|
|
30
|
-
settings.
|
|
30
|
+
settings.logger.verboseLog(`Verbose logging ${action}`);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -173,7 +173,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
173
173
|
button.setAttribute("data-app-id", app.id);
|
|
174
174
|
const iconContainer = document.createElement("div");
|
|
175
175
|
const iconElement = document.createElement("template");
|
|
176
|
-
iconElement.innerHTML = getAppIcon(app.icon);
|
|
176
|
+
iconElement.innerHTML = app.icon ? getAppIcon(app.icon) : "?";
|
|
177
177
|
iconContainer.append(iconElement.content.cloneNode(true));
|
|
178
178
|
const notification = document.createElement("div");
|
|
179
179
|
notification.classList.add("notification");
|
|
@@ -9,5 +9,8 @@ export declare const defaultSettings: {
|
|
|
9
9
|
export declare const settings: {
|
|
10
10
|
readonly config: Settings;
|
|
11
11
|
updateSetting: (key: keyof Settings, value: boolean) => void;
|
|
12
|
-
|
|
12
|
+
logger: {
|
|
13
|
+
log: (message: string) => void;
|
|
14
|
+
verboseLog: (message: string) => void;
|
|
15
|
+
};
|
|
13
16
|
};
|
|
@@ -28,6 +28,7 @@ export declare class AstroDevToolbar extends HTMLElement {
|
|
|
28
28
|
getAppTemplate(app: DevToolbarApp): string;
|
|
29
29
|
getAppById(id: string): DevToolbarApp | undefined;
|
|
30
30
|
getAppCanvasById(id: string): HTMLElement | null;
|
|
31
|
+
getAppButtonById(id: string): HTMLElement | null;
|
|
31
32
|
toggleAppStatus(app: DevToolbarApp): Promise<void>;
|
|
32
33
|
setAppStatus(app: DevToolbarApp, newStatus: boolean): Promise<boolean>;
|
|
33
34
|
isHidden(): boolean;
|
|
@@ -109,6 +109,11 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
109
109
|
outline-offset: -3px;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
#dev-bar #bar-container .item[data-app-error]:hover, #dev-bar #bar-container .item[data-app-error]:focus-visible {
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
background: #ff252520;
|
|
115
|
+
}
|
|
116
|
+
|
|
112
117
|
#dev-bar .item:first-of-type {
|
|
113
118
|
border-top-left-radius: 9999px;
|
|
114
119
|
border-bottom-left-radius: 9999px;
|
|
@@ -149,6 +154,10 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
149
154
|
border-top: 5px solid #343841;
|
|
150
155
|
}
|
|
151
156
|
|
|
157
|
+
#dev-bar .item[data-app-error] .icon {
|
|
158
|
+
opacity: 0.35;
|
|
159
|
+
}
|
|
160
|
+
|
|
152
161
|
#dev-bar .item:hover .item-tooltip, #dev-bar .item:not(.active):focus-visible .item-tooltip {
|
|
153
162
|
transition: opacity 0.2s ease-in-out 200ms;
|
|
154
163
|
opacity: 1;
|
|
@@ -229,8 +238,7 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
229
238
|
this.devToolbarContainer = this.shadowRoot.querySelector("#dev-toolbar-root");
|
|
230
239
|
this.attachEvents();
|
|
231
240
|
this.apps.forEach(async (app) => {
|
|
232
|
-
|
|
233
|
-
console.log(`Creating app canvas for ${app.id}`);
|
|
241
|
+
settings.logger.verboseLog(`Creating app canvas for ${app.id}`);
|
|
234
242
|
const appCanvas = document.createElement("astro-dev-toolbar-app-canvas");
|
|
235
243
|
appCanvas.dataset.appId = app.id;
|
|
236
244
|
this.shadowRoot?.append(appCanvas);
|
|
@@ -311,8 +319,7 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
311
319
|
const shadowRoot = this.getAppCanvasById(app.id).shadowRoot;
|
|
312
320
|
app.status = "loading";
|
|
313
321
|
try {
|
|
314
|
-
|
|
315
|
-
console.info(`Initializing app ${app.id}`);
|
|
322
|
+
settings.logger.verboseLog(`Initializing app ${app.id}`);
|
|
316
323
|
await app.init?.(shadowRoot, app.eventTarget);
|
|
317
324
|
app.status = "ready";
|
|
318
325
|
if (import.meta.hot) {
|
|
@@ -322,11 +329,23 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
322
329
|
} catch (e) {
|
|
323
330
|
console.error(`Failed to init app ${app.id}, error: ${e}`);
|
|
324
331
|
app.status = "error";
|
|
332
|
+
if (import.meta.hot) {
|
|
333
|
+
import.meta.hot.send("astro:devtoolbar:error:init", {
|
|
334
|
+
app,
|
|
335
|
+
error: e instanceof Error ? e.stack : e
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
const appButton = this.getAppButtonById(app.id);
|
|
339
|
+
const appTooltip = appButton?.querySelector(".item-tooltip");
|
|
340
|
+
if (appButton && appTooltip) {
|
|
341
|
+
appButton.toggleAttribute("data-app-error", true);
|
|
342
|
+
appTooltip.innerText = `Error initializing ${app.name}`;
|
|
343
|
+
}
|
|
325
344
|
}
|
|
326
345
|
}
|
|
327
346
|
getAppTemplate(app) {
|
|
328
347
|
return `<button class="item" data-app-id="${app.id}">
|
|
329
|
-
<div class="icon">${getAppIcon(app.icon)}<div class="notification"></div></div>
|
|
348
|
+
<div class="icon">${app.icon ? getAppIcon(app.icon) : "?"}<div class="notification"></div></div>
|
|
330
349
|
<span class="item-tooltip">${app.name}</span>
|
|
331
350
|
</button>`;
|
|
332
351
|
}
|
|
@@ -338,6 +357,9 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
338
357
|
`astro-dev-toolbar-app-canvas[data-app-id="${id}"]`
|
|
339
358
|
);
|
|
340
359
|
}
|
|
360
|
+
getAppButtonById(id) {
|
|
361
|
+
return this.shadowRoot.querySelector(`[data-app-id="${id}"]`);
|
|
362
|
+
}
|
|
341
363
|
async toggleAppStatus(app) {
|
|
342
364
|
const activeApp = this.getActiveApp();
|
|
343
365
|
if (activeApp) {
|
|
@@ -361,7 +383,7 @@ class AstroDevToolbar extends HTMLElement {
|
|
|
361
383
|
return false;
|
|
362
384
|
}
|
|
363
385
|
app.active = newStatus ?? !app.active;
|
|
364
|
-
const mainBarButton = this.
|
|
386
|
+
const mainBarButton = this.getAppButtonById(app.id);
|
|
365
387
|
const moreBarButton = this.getAppCanvasById("astro:more")?.shadowRoot?.querySelector(
|
|
366
388
|
`[data-app-id="${app.id}"]`
|
|
367
389
|
);
|
|
@@ -19,14 +19,11 @@ Found handlers: ${Object.keys(mod).map((exp) => JSON.stringify(exp)).join(", ")}
|
|
|
19
19
|
` + ("all" in mod ? `One of the exported handlers is "all" (lowercase), did you mean to export 'ALL'?
|
|
20
20
|
` : "")
|
|
21
21
|
);
|
|
22
|
-
return new Response(null, {
|
|
23
|
-
status: 404,
|
|
24
|
-
headers: {
|
|
25
|
-
"X-Astro-Response": "Not-Found"
|
|
26
|
-
}
|
|
27
|
-
});
|
|
22
|
+
return new Response(null, { status: 404 });
|
|
28
23
|
}
|
|
29
|
-
|
|
24
|
+
const response = await handler.call(mod, context);
|
|
25
|
+
response.headers.set("X-Astro-Reroute", "no");
|
|
26
|
+
return response;
|
|
30
27
|
}
|
|
31
28
|
export {
|
|
32
29
|
renderEndpoint
|
|
@@ -18,7 +18,6 @@ class DevPipeline extends Pipeline {
|
|
|
18
18
|
this.#devLogger = logger;
|
|
19
19
|
this.#settings = settings;
|
|
20
20
|
this.#loader = loader;
|
|
21
|
-
this.setEndpointHandler(this.#handleEndpointResult);
|
|
22
21
|
}
|
|
23
22
|
clearRouteCache() {
|
|
24
23
|
this.env.routeCache.clearAll();
|
|
@@ -58,9 +57,6 @@ class DevPipeline extends Pipeline {
|
|
|
58
57
|
streaming: true
|
|
59
58
|
});
|
|
60
59
|
}
|
|
61
|
-
async #handleEndpointResult(_, response) {
|
|
62
|
-
return response;
|
|
63
|
-
}
|
|
64
60
|
async handleFallback() {
|
|
65
61
|
}
|
|
66
62
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type * as vite from 'vite';
|
|
2
2
|
import type { AstroPluginOptions } from '../@types/astro.js';
|
|
3
|
-
export default function astroDevToolbar({ settings }: AstroPluginOptions): vite.Plugin;
|
|
3
|
+
export default function astroDevToolbar({ settings, logger }: AstroPluginOptions): vite.Plugin;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const VIRTUAL_MODULE_ID = "astro:dev-toolbar";
|
|
2
2
|
const resolvedVirtualModuleId = "\0" + VIRTUAL_MODULE_ID;
|
|
3
|
-
function astroDevToolbar({ settings }) {
|
|
3
|
+
function astroDevToolbar({ settings, logger }) {
|
|
4
4
|
return {
|
|
5
5
|
name: "astro:dev-toolbar",
|
|
6
6
|
config() {
|
|
@@ -16,12 +16,49 @@ function astroDevToolbar({ settings }) {
|
|
|
16
16
|
return resolvedVirtualModuleId;
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
+
configureServer(server) {
|
|
20
|
+
server.ws.on("astro:devtoolbar:error:load", (args) => {
|
|
21
|
+
logger.error(
|
|
22
|
+
"toolbar",
|
|
23
|
+
`Failed to load dev toolbar app from ${args.entrypoint}: ${args.error}`
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
server.ws.on("astro:devtoolbar:error:init", (args) => {
|
|
27
|
+
logger.error(
|
|
28
|
+
"toolbar",
|
|
29
|
+
`Failed to initialize dev toolbar app ${args.app.name} (${args.app.id}):
|
|
30
|
+
${args.error}`
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
},
|
|
19
34
|
async load(id) {
|
|
20
35
|
if (id === resolvedVirtualModuleId) {
|
|
21
36
|
return `
|
|
22
37
|
export const loadDevToolbarApps = async () => {
|
|
23
|
-
return [${settings.devToolbarApps.map((plugin) => `(
|
|
38
|
+
return (await Promise.all([${settings.devToolbarApps.map((plugin) => `safeLoadPlugin(${JSON.stringify(plugin)})`).join(",")}])).filter(app => app);
|
|
24
39
|
};
|
|
40
|
+
|
|
41
|
+
async function safeLoadPlugin(entrypoint) {
|
|
42
|
+
try {
|
|
43
|
+
const app = (await import(/* @vite-ignore */ entrypoint)).default;
|
|
44
|
+
|
|
45
|
+
if (typeof app !== 'object' || !app.id || !app.name) {
|
|
46
|
+
throw new Error("Apps must default export an object with an id, and a name.");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return app;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error(\`Failed to load dev toolbar app from \${entrypoint}: \${err.message}\`);
|
|
52
|
+
|
|
53
|
+
if (import.meta.hot) {
|
|
54
|
+
import.meta.hot.send('astro:devtoolbar:error:load', { entrypoint: entrypoint, error: err.message })
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
25
62
|
`;
|
|
26
63
|
}
|
|
27
64
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { visit } from "unist-util-visit";
|
|
2
|
-
import {
|
|
2
|
+
import { escapeTemplateLiteralCharacters, needsEscape, replaceAttribute } from "./utils.js";
|
|
3
3
|
const rehypeEscape = ({ s }) => {
|
|
4
4
|
return (tree) => {
|
|
5
5
|
visit(tree, (node) => {
|
|
6
6
|
if (node.type === "text" || node.type === "comment") {
|
|
7
7
|
if (needsEscape(node.value)) {
|
|
8
|
-
s.overwrite(
|
|
8
|
+
s.overwrite(
|
|
9
|
+
node.position.start.offset,
|
|
10
|
+
node.position.end.offset,
|
|
11
|
+
escapeTemplateLiteralCharacters(node.value)
|
|
12
|
+
);
|
|
9
13
|
}
|
|
10
14
|
} else if (node.type === "element") {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
if (!node.properties)
|
|
16
|
+
return;
|
|
17
|
+
for (let [key, value] of Object.entries(node.properties)) {
|
|
18
|
+
key = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
19
|
+
const newKey = needsEscape(key) ? escapeTemplateLiteralCharacters(key) : key;
|
|
20
|
+
const newValue = needsEscape(value) ? escapeTemplateLiteralCharacters(value) : value;
|
|
14
21
|
if (newKey === key && newValue === value)
|
|
15
22
|
continue;
|
|
16
23
|
replaceAttribute(s, node, key, value === "" ? newKey : `${newKey}="${newValue}"`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { visit } from "unist-util-visit";
|
|
2
|
-
import {
|
|
2
|
+
import { escapeTemplateLiteralCharacters } from "./utils.js";
|
|
3
3
|
const rehypeSlots = ({ s }) => {
|
|
4
4
|
return (tree, file) => {
|
|
5
5
|
visit(tree, (node) => {
|
|
@@ -12,7 +12,11 @@ const rehypeSlots = ({ s }) => {
|
|
|
12
12
|
const first = node.children.at(0) ?? node;
|
|
13
13
|
const last = node.children.at(-1) ?? node;
|
|
14
14
|
const text = file.value.slice(first.position?.start.offset ?? 0, last.position?.end.offset ?? 0).toString();
|
|
15
|
-
s.overwrite(
|
|
15
|
+
s.overwrite(
|
|
16
|
+
start,
|
|
17
|
+
end,
|
|
18
|
+
`\${${SLOT_PREFIX}["${name}"] ?? \`${escapeTemplateLiteralCharacters(text).trim()}\`}`
|
|
19
|
+
);
|
|
16
20
|
}
|
|
17
21
|
});
|
|
18
22
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Element } from 'hast';
|
|
2
2
|
import type MagicString from 'magic-string';
|
|
3
|
-
export declare function replaceAttribute(s: MagicString, node: Element, key: string, newValue: string):
|
|
3
|
+
export declare function replaceAttribute(s: MagicString, node: Element, key: string, newValue: string): MagicString | undefined;
|
|
4
4
|
export declare function needsEscape(value: any): value is string;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function escapeTemplateLiteralCharacters(value: string): string;
|
|
@@ -10,20 +10,39 @@ function replaceAttribute(s, node, key, newValue) {
|
|
|
10
10
|
const token = tokens[0].replace(/([^>])(\>[\s\S]*$)/gim, "$1");
|
|
11
11
|
if (token.trim() === key) {
|
|
12
12
|
const end = start + key.length;
|
|
13
|
-
s.overwrite(start, end, newValue);
|
|
13
|
+
return s.overwrite(start, end, newValue, { contentOnly: true });
|
|
14
14
|
} else {
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
const length = token.length;
|
|
16
|
+
const end = start + length;
|
|
17
|
+
return s.overwrite(start, end, newValue, { contentOnly: true });
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
const NEEDS_ESCAPE_RE = /[`\\]|\$\{/g;
|
|
19
21
|
function needsEscape(value) {
|
|
20
|
-
|
|
22
|
+
NEEDS_ESCAPE_RE.lastIndex = 0;
|
|
23
|
+
return typeof value === "string" && NEEDS_ESCAPE_RE.test(value);
|
|
21
24
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
25
|
+
function escapeTemplateLiteralCharacters(value) {
|
|
26
|
+
NEEDS_ESCAPE_RE.lastIndex = 0;
|
|
27
|
+
let char;
|
|
28
|
+
let startIndex = 0;
|
|
29
|
+
let segment = "";
|
|
30
|
+
let text = "";
|
|
31
|
+
while ([char] = NEEDS_ESCAPE_RE.exec(value) ?? []) {
|
|
32
|
+
if (!char) {
|
|
33
|
+
text += value.slice(startIndex);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
const endIndex = NEEDS_ESCAPE_RE.lastIndex - char.length;
|
|
37
|
+
const prefix = segment === "\\" ? "" : "\\";
|
|
38
|
+
segment = prefix + char;
|
|
39
|
+
text += value.slice(startIndex, endIndex) + segment;
|
|
40
|
+
startIndex = NEEDS_ESCAPE_RE.lastIndex;
|
|
41
|
+
}
|
|
42
|
+
return text;
|
|
24
43
|
}
|
|
25
44
|
export {
|
|
26
|
-
|
|
45
|
+
escapeTemplateLiteralCharacters,
|
|
27
46
|
needsEscape,
|
|
28
47
|
replaceAttribute
|
|
29
48
|
};
|
|
@@ -8,7 +8,10 @@ function getMarkdownCodeForImages(imagePaths, html) {
|
|
|
8
8
|
${imagePaths.map((entry) => {
|
|
9
9
|
const rawUrl = JSON.stringify(entry.raw);
|
|
10
10
|
return `{
|
|
11
|
-
const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl
|
|
11
|
+
const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
|
|
12
|
+
/[.*+?^${}()|[\]\\]/g,
|
|
13
|
+
"\\\\$&"
|
|
14
|
+
)} + '[^"]*)"', 'g');
|
|
12
15
|
let match;
|
|
13
16
|
let occurrenceCounter = 0;
|
|
14
17
|
while ((match = regex.exec(html)) !== null) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.4",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"tsconfck": "^3.0.0",
|
|
157
157
|
"unist-util-visit": "^5.0.0",
|
|
158
158
|
"vfile": "^6.0.1",
|
|
159
|
-
"vite": "^5.0.
|
|
159
|
+
"vite": "^5.0.12",
|
|
160
160
|
"vitefu": "^0.2.5",
|
|
161
161
|
"which-pm": "^2.1.1",
|
|
162
162
|
"yargs-parser": "^21.1.1",
|