astro 4.0.8 → 4.1.0
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/astro-jsx.d.ts +10 -1
- package/config.d.ts +2 -1
- package/config.mjs +2 -2
- package/dist/@types/astro.d.ts +58 -15
- package/dist/assets/services/sharp.d.ts +7 -1
- package/dist/assets/services/sharp.js +6 -2
- package/dist/assets/utils/transformToPath.js +1 -1
- package/dist/assets/vite-plugin-assets.js +2 -2
- package/dist/cli/add/index.js +4 -2
- package/dist/cli/check/index.js +2 -0
- package/dist/cli/flags.js +1 -1
- package/dist/cli/index.js +0 -3
- package/dist/cli/preview/index.js +3 -0
- package/dist/core/build/index.js +2 -0
- package/dist/core/config/config.js +2 -2
- package/dist/core/config/schema.d.ts +26 -26
- package/dist/core/config/schema.js +3 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/cookies/cookies.d.ts +7 -3
- package/dist/core/cookies/cookies.js +8 -8
- package/dist/core/cookies/index.d.ts +1 -0
- package/dist/core/dev/container.js +2 -2
- package/dist/core/dev/dev.js +3 -1
- package/dist/core/errors/dev/utils.js +5 -2
- package/dist/core/errors/dev/vite.d.ts +1 -1
- package/dist/core/errors/overlay.js +2 -2
- package/dist/core/messages.js +2 -2
- package/dist/core/preview/index.js +9 -0
- package/dist/core/render/result.js +1 -0
- package/dist/core/routing/manifest/create.js +1 -1
- package/dist/core/sync/index.js +2 -0
- package/dist/core/util.d.ts +4 -0
- package/dist/core/util.js +6 -0
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +6 -3
- package/dist/i18n/vite-plugin-i18n.js +1 -1
- package/dist/prefetch/index.js +11 -1
- package/dist/runtime/client/dev-overlay/overlay.js +8 -2
- package/dist/runtime/client/dev-overlay/plugins/audit/a11y.js +126 -0
- package/dist/runtime/client/visible.js +6 -2
- package/dist/runtime/client/visible.prebuilt.d.ts +1 -1
- package/dist/runtime/client/visible.prebuilt.js +1 -1
- package/dist/runtime/server/render/common.js +9 -0
- package/dist/runtime/server/render/component.js +9 -0
- package/dist/runtime/server/render/instruction.d.ts +11 -1
- package/dist/transitions/router.js +9 -3
- package/dist/vite-plugin-astro-server/base.js +6 -1
- package/dist/vite-plugin-astro-server/error.js +4 -2
- package/dist/vite-plugin-dev-overlay/vite-plugin-dev-overlay.js +8 -0
- package/package.json +4 -1
|
@@ -62,7 +62,7 @@ class AstroCookies {
|
|
|
62
62
|
* @param key The cookie to get.
|
|
63
63
|
* @returns An object containing the cookie value as well as convenience methods for converting its value.
|
|
64
64
|
*/
|
|
65
|
-
get(key) {
|
|
65
|
+
get(key, options = void 0) {
|
|
66
66
|
if (this.#outgoing?.has(key)) {
|
|
67
67
|
let [serializedValue, , isSetValue] = this.#outgoing.get(key);
|
|
68
68
|
if (isSetValue) {
|
|
@@ -71,7 +71,7 @@ class AstroCookies {
|
|
|
71
71
|
return void 0;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
const values = this.#ensureParsed();
|
|
74
|
+
const values = this.#ensureParsed(options);
|
|
75
75
|
if (key in values) {
|
|
76
76
|
const value = values[key];
|
|
77
77
|
return new AstroCookie(value);
|
|
@@ -83,12 +83,12 @@ class AstroCookies {
|
|
|
83
83
|
* @param key The cookie to check for.
|
|
84
84
|
* @returns
|
|
85
85
|
*/
|
|
86
|
-
has(key) {
|
|
86
|
+
has(key, options = void 0) {
|
|
87
87
|
if (this.#outgoing?.has(key)) {
|
|
88
88
|
let [, , isSetValue] = this.#outgoing.get(key);
|
|
89
89
|
return isSetValue;
|
|
90
90
|
}
|
|
91
|
-
const values = this.#ensureParsed();
|
|
91
|
+
const values = this.#ensureParsed(options);
|
|
92
92
|
return !!values[key];
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
@@ -140,9 +140,9 @@ class AstroCookies {
|
|
|
140
140
|
yield value[1];
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
-
#ensureParsed() {
|
|
143
|
+
#ensureParsed(options = void 0) {
|
|
144
144
|
if (!this.#requestValues) {
|
|
145
|
-
this.#parse();
|
|
145
|
+
this.#parse(options);
|
|
146
146
|
}
|
|
147
147
|
if (!this.#requestValues) {
|
|
148
148
|
this.#requestValues = {};
|
|
@@ -155,12 +155,12 @@ class AstroCookies {
|
|
|
155
155
|
}
|
|
156
156
|
return this.#outgoing;
|
|
157
157
|
}
|
|
158
|
-
#parse() {
|
|
158
|
+
#parse(options = void 0) {
|
|
159
159
|
const raw = this.#request.headers.get("cookie");
|
|
160
160
|
if (!raw) {
|
|
161
161
|
return;
|
|
162
162
|
}
|
|
163
|
-
this.#requestValues = parse(raw);
|
|
163
|
+
this.#requestValues = parse(raw, options);
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
export {
|
|
@@ -26,9 +26,9 @@ async function createContainer({
|
|
|
26
26
|
settings = injectImageEndpoint(settings, "dev");
|
|
27
27
|
const {
|
|
28
28
|
base,
|
|
29
|
-
server: { host, headers, open:
|
|
29
|
+
server: { host, headers, open: serverOpen }
|
|
30
30
|
} = settings.config;
|
|
31
|
-
const open =
|
|
31
|
+
const open = typeof serverOpen == "string" ? serverOpen : serverOpen ? base : false;
|
|
32
32
|
const rendererClientEntries = settings.renderers.map((r) => r.clientEntrypoint).filter(Boolean);
|
|
33
33
|
const viteConfig = await createVite(
|
|
34
34
|
{
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -6,7 +6,9 @@ import { telemetry } from "../../events/index.js";
|
|
|
6
6
|
import * as msg from "../messages.js";
|
|
7
7
|
import { startContainer } from "./container.js";
|
|
8
8
|
import { createContainerWithAutomaticRestart } from "./restart.js";
|
|
9
|
+
import { ensureProcessNodeEnv } from "../util.js";
|
|
9
10
|
async function dev(inlineConfig) {
|
|
11
|
+
ensureProcessNodeEnv("development");
|
|
10
12
|
const devStart = performance.now();
|
|
11
13
|
await telemetry.record([]);
|
|
12
14
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
@@ -21,7 +23,7 @@ async function dev(inlineConfig) {
|
|
|
21
23
|
base: restart.container.settings.config.base
|
|
22
24
|
})
|
|
23
25
|
);
|
|
24
|
-
const currentVersion = "4.0
|
|
26
|
+
const currentVersion = "4.1.0";
|
|
25
27
|
if (currentVersion.includes("-")) {
|
|
26
28
|
logger.warn("SKIP_FORMAT", msg.prerelease({ currentVersion }));
|
|
27
29
|
}
|
|
@@ -15,7 +15,7 @@ function collectErrorMetadata(e, rootFolder) {
|
|
|
15
15
|
err.forEach((error) => {
|
|
16
16
|
if (e.stack) {
|
|
17
17
|
const stackInfo = collectInfoFromStacktrace(e);
|
|
18
|
-
error.stack = stackInfo.stack;
|
|
18
|
+
error.stack = stripAnsi(stackInfo.stack);
|
|
19
19
|
error.loc = stackInfo.loc;
|
|
20
20
|
error.plugin = stackInfo.plugin;
|
|
21
21
|
error.pluginCode = stackInfo.pluginCode;
|
|
@@ -30,7 +30,7 @@ function collectErrorMetadata(e, rootFolder) {
|
|
|
30
30
|
const fileContents = fs.readFileSync(error.loc.file, "utf8");
|
|
31
31
|
if (!error.frame) {
|
|
32
32
|
const frame = codeFrame(fileContents, error.loc);
|
|
33
|
-
error.frame = frame;
|
|
33
|
+
error.frame = stripAnsi(frame);
|
|
34
34
|
}
|
|
35
35
|
if (!error.fullCode) {
|
|
36
36
|
error.fullCode = fileContents;
|
|
@@ -39,6 +39,9 @@ function collectErrorMetadata(e, rootFolder) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
error.hint = generateHint(e);
|
|
42
|
+
if (error.message) {
|
|
43
|
+
error.message = stripAnsi(error.message);
|
|
44
|
+
}
|
|
42
45
|
});
|
|
43
46
|
if (!AggregateError.is(e) && Array.isArray(e.errors)) {
|
|
44
47
|
e.errors.forEach((buildError, i) => {
|
|
@@ -621,7 +621,7 @@ class ErrorOverlay extends HTMLElement {
|
|
|
621
621
|
docslink.appendChild(this.createLink(`See Docs Reference${openNewWindowIcon}`, err.docslink));
|
|
622
622
|
}
|
|
623
623
|
const code = this.root.querySelector("#code");
|
|
624
|
-
if (code && err.loc
|
|
624
|
+
if (code && err.loc?.file) {
|
|
625
625
|
code.style.display = "block";
|
|
626
626
|
const codeHeader = code.querySelector("#code header");
|
|
627
627
|
const codeContent = code.querySelector("#code-content");
|
|
@@ -647,7 +647,7 @@ class ErrorOverlay extends HTMLElement {
|
|
|
647
647
|
if (errorLine.parentElement?.parentElement) {
|
|
648
648
|
errorLine.parentElement.parentElement.scrollTop = errorLine.offsetTop - errorLine.parentElement.parentElement.offsetTop - 8;
|
|
649
649
|
}
|
|
650
|
-
if (err.loc
|
|
650
|
+
if (err.loc?.column) {
|
|
651
651
|
errorLine.insertAdjacentHTML(
|
|
652
652
|
"afterend",
|
|
653
653
|
`
|
package/dist/core/messages.js
CHANGED
|
@@ -36,7 +36,7 @@ function serverStart({
|
|
|
36
36
|
host,
|
|
37
37
|
base
|
|
38
38
|
}) {
|
|
39
|
-
const version = "4.0
|
|
39
|
+
const version = "4.1.0";
|
|
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.0
|
|
261
|
+
`v${"4.1.0"}`
|
|
262
262
|
)} ${headline}`
|
|
263
263
|
);
|
|
264
264
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
1
2
|
import { createRequire } from "node:module";
|
|
2
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
4
|
import { AstroIntegrationLogger } from "../../core/logger/core.js";
|
|
@@ -9,7 +10,9 @@ import { createNodeLogger } from "../config/logging.js";
|
|
|
9
10
|
import { createSettings } from "../config/settings.js";
|
|
10
11
|
import createStaticPreviewServer from "./static-preview-server.js";
|
|
11
12
|
import { getResolvedHostForHttpServer } from "./util.js";
|
|
13
|
+
import { ensureProcessNodeEnv } from "../util.js";
|
|
12
14
|
async function preview(inlineConfig) {
|
|
15
|
+
ensureProcessNodeEnv("production");
|
|
13
16
|
const logger = createNodeLogger(inlineConfig);
|
|
14
17
|
const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, "preview");
|
|
15
18
|
telemetry.record(eventCliSession("preview", userConfig));
|
|
@@ -21,6 +24,12 @@ async function preview(inlineConfig) {
|
|
|
21
24
|
});
|
|
22
25
|
await runHookConfigDone({ settings, logger });
|
|
23
26
|
if (settings.config.output === "static") {
|
|
27
|
+
if (!fs.existsSync(settings.config.outDir)) {
|
|
28
|
+
const outDirPath = fileURLToPath(settings.config.outDir);
|
|
29
|
+
throw new Error(
|
|
30
|
+
`[preview] The output directory ${outDirPath} does not exist. Did you run \`astro build\`?`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
24
33
|
const server2 = await createStaticPreviewServer(settings, logger);
|
|
25
34
|
return server2;
|
|
26
35
|
}
|
|
@@ -224,7 +224,7 @@ function createRouteManifest({ settings, cwd, fsMod }, logger) {
|
|
|
224
224
|
} else {
|
|
225
225
|
components.push(item.file);
|
|
226
226
|
const component = item.file;
|
|
227
|
-
const trailingSlash =
|
|
227
|
+
const { trailingSlash } = settings.config;
|
|
228
228
|
const pattern = getPattern(segments, settings.config, trailingSlash);
|
|
229
229
|
const generate = getRouteGenerator(segments, trailingSlash);
|
|
230
230
|
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
package/dist/core/sync/index.js
CHANGED
|
@@ -15,7 +15,9 @@ import { createNodeLogger } from "../config/logging.js";
|
|
|
15
15
|
import { createSettings } from "../config/settings.js";
|
|
16
16
|
import { createVite } from "../create-vite.js";
|
|
17
17
|
import { AstroError, AstroErrorData, createSafeError, isAstroError } from "../errors/index.js";
|
|
18
|
+
import { ensureProcessNodeEnv } from "../util.js";
|
|
18
19
|
async function sync(inlineConfig, options) {
|
|
20
|
+
ensureProcessNodeEnv("production");
|
|
19
21
|
const logger = createNodeLogger(inlineConfig);
|
|
20
22
|
const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, "sync");
|
|
21
23
|
telemetry.record(eventCliSession("sync", userConfig));
|
package/dist/core/util.d.ts
CHANGED
|
@@ -50,3 +50,7 @@ export declare function resolveJsToTs(filePath: string): string;
|
|
|
50
50
|
* Resolve the hydration paths so that it can be imported in the client
|
|
51
51
|
*/
|
|
52
52
|
export declare function resolvePath(specifier: string, importer: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Set a default NODE_ENV so Vite doesn't set an incorrect default when loading the Astro config
|
|
55
|
+
*/
|
|
56
|
+
export declare function ensureProcessNodeEnv(defaultNodeEnv: string): void;
|
package/dist/core/util.js
CHANGED
|
@@ -174,11 +174,17 @@ function resolvePath(specifier, importer) {
|
|
|
174
174
|
return specifier;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
+
function ensureProcessNodeEnv(defaultNodeEnv) {
|
|
178
|
+
if (!process.env.NODE_ENV) {
|
|
179
|
+
process.env.NODE_ENV = defaultNodeEnv;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
177
182
|
export {
|
|
178
183
|
NULL_BYTE_PLACEHOLDER,
|
|
179
184
|
VALID_ID_PREFIX,
|
|
180
185
|
arraify,
|
|
181
186
|
emoji,
|
|
187
|
+
ensureProcessNodeEnv,
|
|
182
188
|
getOutputFilename,
|
|
183
189
|
isEndpoint,
|
|
184
190
|
isMarkdownFile,
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export declare function getPathByLocale(locale: string, locales: Locales): strin
|
|
|
53
53
|
/**
|
|
54
54
|
* An utility function that retrieves the preferred locale that correspond to a path.
|
|
55
55
|
*
|
|
56
|
-
* @param
|
|
56
|
+
* @param path
|
|
57
57
|
* @param locales
|
|
58
58
|
*/
|
|
59
59
|
export declare function getLocaleByPath(path: string, locales: Locales): string | undefined;
|
package/dist/i18n/index.js
CHANGED
|
@@ -99,10 +99,13 @@ function getPathByLocale(locale, locales) {
|
|
|
99
99
|
function getLocaleByPath(path, locales) {
|
|
100
100
|
for (const locale of locales) {
|
|
101
101
|
if (typeof locale !== "string") {
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
if (locale.path === path) {
|
|
103
|
+
const code = locale.codes.at(0);
|
|
104
|
+
return code;
|
|
105
|
+
}
|
|
106
|
+
} else if (locale === path) {
|
|
107
|
+
return locale;
|
|
104
108
|
}
|
|
105
|
-
1;
|
|
106
109
|
}
|
|
107
110
|
return void 0;
|
|
108
111
|
}
|
|
@@ -54,7 +54,7 @@ function astroInternationalization({
|
|
|
54
54
|
export const getAbsoluteLocaleUrlList = (path = "", opts) => _getLocaleAbsoluteUrlList({ base, path, trailingSlash, format, site, ...i18n, ...opts });
|
|
55
55
|
|
|
56
56
|
export const getPathByLocale = (locale) => _getPathByLocale(locale, i18n.locales);
|
|
57
|
-
export const getLocaleByPath = (
|
|
57
|
+
export const getLocaleByPath = (path) => _getLocaleByPath(path, i18n.locales);
|
|
58
58
|
`;
|
|
59
59
|
}
|
|
60
60
|
}
|
package/dist/prefetch/index.js
CHANGED
|
@@ -17,6 +17,7 @@ function init(defaultOpts) {
|
|
|
17
17
|
initTapStrategy();
|
|
18
18
|
initHoverStrategy();
|
|
19
19
|
initViewportStrategy();
|
|
20
|
+
initLoadStrategy();
|
|
20
21
|
}
|
|
21
22
|
function initTapStrategy() {
|
|
22
23
|
for (const event of ["touchstart", "mousedown"]) {
|
|
@@ -111,6 +112,15 @@ function createViewportIntersectionObserver() {
|
|
|
111
112
|
}
|
|
112
113
|
});
|
|
113
114
|
}
|
|
115
|
+
function initLoadStrategy() {
|
|
116
|
+
onPageLoad(() => {
|
|
117
|
+
for (const anchor of document.getElementsByTagName("a")) {
|
|
118
|
+
if (elMatchesStrategy(anchor, "load")) {
|
|
119
|
+
prefetch(anchor.href, { with: "link" });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
114
124
|
function prefetch(url, opts) {
|
|
115
125
|
const ignoreSlowConnection = opts?.ignoreSlowConnection ?? false;
|
|
116
126
|
if (!canPrefetchUrl(url, ignoreSlowConnection))
|
|
@@ -163,7 +173,7 @@ function elMatchesStrategy(el, strategy) {
|
|
|
163
173
|
function isSlowConnection() {
|
|
164
174
|
if ("connection" in navigator) {
|
|
165
175
|
const conn = navigator.connection;
|
|
166
|
-
return conn.saveData || /
|
|
176
|
+
return conn.saveData || /2g/.test(conn.effectiveType);
|
|
167
177
|
}
|
|
168
178
|
return false;
|
|
169
179
|
}
|
|
@@ -3,6 +3,7 @@ import { getIconElement, isDefinedIcon } from "./ui-library/icons.js";
|
|
|
3
3
|
const WS_EVENT_NAME = "astro-dev-toolbar";
|
|
4
4
|
const WS_EVENT_NAME_DEPRECATED = "astro-dev-overlay";
|
|
5
5
|
const HOVER_DELAY = 2 * 1e3;
|
|
6
|
+
const DEVBAR_HITBOX_ABOVE = 42;
|
|
6
7
|
class AstroDevOverlay extends HTMLElement {
|
|
7
8
|
shadowRoot;
|
|
8
9
|
delayedHideTimeout;
|
|
@@ -62,7 +63,7 @@ class AstroDevOverlay extends HTMLElement {
|
|
|
62
63
|
pointer-events: auto;
|
|
63
64
|
}
|
|
64
65
|
#dev-bar-hitbox-above {
|
|
65
|
-
height:
|
|
66
|
+
height: ${DEVBAR_HITBOX_ABOVE}px;
|
|
66
67
|
}
|
|
67
68
|
#dev-bar-hitbox-below {
|
|
68
69
|
height: 16px;
|
|
@@ -131,7 +132,7 @@ class AstroDevOverlay extends HTMLElement {
|
|
|
131
132
|
border-radius: 4px;
|
|
132
133
|
padding: 4px 8px;
|
|
133
134
|
position: absolute;
|
|
134
|
-
top:
|
|
135
|
+
top: ${4 - DEVBAR_HITBOX_ABOVE}px;
|
|
135
136
|
font-size: 14px;
|
|
136
137
|
opacity: 0;
|
|
137
138
|
transition: opacity 0.2s ease-in-out 0s;
|
|
@@ -423,16 +424,21 @@ class AstroDevOverlay extends HTMLElement {
|
|
|
423
424
|
setOverlayVisible(newStatus) {
|
|
424
425
|
const barContainer = this.shadowRoot.querySelector("#bar-container");
|
|
425
426
|
const devBar = this.shadowRoot.querySelector("#dev-bar");
|
|
427
|
+
const devBarHitboxAbove = this.shadowRoot.querySelector("#dev-bar-hitbox-above");
|
|
426
428
|
if (newStatus === true) {
|
|
427
429
|
this.devOverlay?.removeAttribute("data-hidden");
|
|
428
430
|
barContainer?.removeAttribute("inert");
|
|
429
431
|
devBar?.removeAttribute("tabindex");
|
|
432
|
+
if (devBarHitboxAbove)
|
|
433
|
+
devBarHitboxAbove.style.height = "0";
|
|
430
434
|
return;
|
|
431
435
|
}
|
|
432
436
|
if (newStatus === false) {
|
|
433
437
|
this.devOverlay?.setAttribute("data-hidden", "");
|
|
434
438
|
barContainer?.setAttribute("inert", "");
|
|
435
439
|
devBar?.setAttribute("tabindex", "0");
|
|
440
|
+
if (devBarHitboxAbove)
|
|
441
|
+
devBarHitboxAbove.style.height = `${DEVBAR_HITBOX_ABOVE}px`;
|
|
436
442
|
return;
|
|
437
443
|
}
|
|
438
444
|
}
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
23
|
* SOFTWARE.
|
|
24
24
|
*/
|
|
25
|
+
import { aria, roles } from "aria-query";
|
|
26
|
+
import { AXObjectRoles, elementAXObjects } from "axobject-query";
|
|
25
27
|
const a11y_required_attributes = {
|
|
26
28
|
a: ["href"],
|
|
27
29
|
area: ["alt", "aria-label", "aria-labelledby"],
|
|
@@ -413,6 +415,58 @@ const a11y = [
|
|
|
413
415
|
message: "This will move elements out of the expected tab order, creating a confusing experience for keyboard users.",
|
|
414
416
|
selector: '[tabindex]:not([tabindex="-1"]):not([tabindex="0"])'
|
|
415
417
|
},
|
|
418
|
+
{
|
|
419
|
+
code: "a11y-role-has-required-aria-props",
|
|
420
|
+
title: "Missing attributes required for ARIA role",
|
|
421
|
+
message: (element) => {
|
|
422
|
+
const { __astro_role: role, __astro_missing_attributes: required } = element;
|
|
423
|
+
return `${element.localName} element is missing required attributes for its role (${role}): ${required.join(", ")}`;
|
|
424
|
+
},
|
|
425
|
+
selector: "*",
|
|
426
|
+
match(element) {
|
|
427
|
+
const role = getRole(element);
|
|
428
|
+
if (!role)
|
|
429
|
+
return false;
|
|
430
|
+
if (is_semantic_role_element(role, element.localName, getAttributeObject(element))) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const { requiredProps } = roles.get(role);
|
|
434
|
+
const required_role_props = Object.keys(requiredProps);
|
|
435
|
+
const missingProps = required_role_props.filter((prop) => !element.hasAttribute(prop));
|
|
436
|
+
if (missingProps.length > 0) {
|
|
437
|
+
element.__astro_role = role;
|
|
438
|
+
element.__astro_missing_attributes = missingProps;
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
code: "a11y-role-supports-aria-props",
|
|
445
|
+
title: "Unsupported ARIA attribute",
|
|
446
|
+
message: (element) => {
|
|
447
|
+
const { __astro_role: role, __astro_unsupported_attributes: unsupported } = element;
|
|
448
|
+
return `${element.localName} element has ARIA attributes that are not supported by its role (${role}): ${unsupported.join(
|
|
449
|
+
", "
|
|
450
|
+
)}`;
|
|
451
|
+
},
|
|
452
|
+
selector: "*",
|
|
453
|
+
match(element) {
|
|
454
|
+
const role = getRole(element);
|
|
455
|
+
if (!role)
|
|
456
|
+
return false;
|
|
457
|
+
const { props } = roles.get(role);
|
|
458
|
+
const attributes = getAttributeObject(element);
|
|
459
|
+
const unsupportedAttributes = aria.keys().filter((attribute) => !(attribute in props));
|
|
460
|
+
const invalidAttributes = Object.keys(attributes).filter(
|
|
461
|
+
(key) => key.startsWith("aria-") && unsupportedAttributes.includes(key)
|
|
462
|
+
);
|
|
463
|
+
if (invalidAttributes.length > 0) {
|
|
464
|
+
element.__astro_role = role;
|
|
465
|
+
element.__astro_unsupported_attributes = invalidAttributes;
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
},
|
|
416
470
|
{
|
|
417
471
|
code: "a11y-structure",
|
|
418
472
|
title: "Invalid DOM structure",
|
|
@@ -447,6 +501,16 @@ const a11y = [
|
|
|
447
501
|
}
|
|
448
502
|
}
|
|
449
503
|
];
|
|
504
|
+
const a11y_labelable = [
|
|
505
|
+
"button",
|
|
506
|
+
"input",
|
|
507
|
+
"keygen",
|
|
508
|
+
"meter",
|
|
509
|
+
"output",
|
|
510
|
+
"progress",
|
|
511
|
+
"select",
|
|
512
|
+
"textarea"
|
|
513
|
+
];
|
|
450
514
|
const a11y_non_interactive_element_to_interactive_role_exceptions = {
|
|
451
515
|
ul: ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"],
|
|
452
516
|
ol: ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"],
|
|
@@ -455,6 +519,68 @@ const a11y_non_interactive_element_to_interactive_role_exceptions = {
|
|
|
455
519
|
td: ["gridcell"],
|
|
456
520
|
fieldset: ["radiogroup", "presentation"]
|
|
457
521
|
};
|
|
522
|
+
const combobox_if_list = ["email", "search", "tel", "text", "url"];
|
|
523
|
+
function input_implicit_role(attributes) {
|
|
524
|
+
if (!("type" in attributes))
|
|
525
|
+
return;
|
|
526
|
+
const { type, list } = attributes;
|
|
527
|
+
if (!type)
|
|
528
|
+
return;
|
|
529
|
+
if (list && combobox_if_list.includes(type)) {
|
|
530
|
+
return "combobox";
|
|
531
|
+
}
|
|
532
|
+
return input_type_to_implicit_role.get(type);
|
|
533
|
+
}
|
|
534
|
+
function menuitem_implicit_role(attributes) {
|
|
535
|
+
if (!("type" in attributes))
|
|
536
|
+
return;
|
|
537
|
+
const { type } = attributes;
|
|
538
|
+
if (!type)
|
|
539
|
+
return;
|
|
540
|
+
return menuitem_type_to_implicit_role.get(type);
|
|
541
|
+
}
|
|
542
|
+
function getRole(element) {
|
|
543
|
+
if (element.hasAttribute("role")) {
|
|
544
|
+
return element.getAttribute("role");
|
|
545
|
+
}
|
|
546
|
+
return getImplicitRole(element);
|
|
547
|
+
}
|
|
548
|
+
function getImplicitRole(element) {
|
|
549
|
+
const name = element.localName;
|
|
550
|
+
const attrs = getAttributeObject(element);
|
|
551
|
+
if (name === "menuitem") {
|
|
552
|
+
return menuitem_implicit_role(attrs);
|
|
553
|
+
} else if (name === "input") {
|
|
554
|
+
return input_implicit_role(attrs);
|
|
555
|
+
} else {
|
|
556
|
+
return a11y_implicit_semantics.get(name);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
function getAttributeObject(element) {
|
|
560
|
+
let obj = {};
|
|
561
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
562
|
+
const attribute = element.attributes.item(i);
|
|
563
|
+
obj[attribute.name] = attribute.value;
|
|
564
|
+
}
|
|
565
|
+
return obj;
|
|
566
|
+
}
|
|
567
|
+
function is_semantic_role_element(role, tag_name, attributes) {
|
|
568
|
+
for (const [schema, ax_object] of elementAXObjects.entries()) {
|
|
569
|
+
if (schema.name === tag_name && (!schema.attributes || schema.attributes.every((attr) => attributes[attr.name] === attr.value))) {
|
|
570
|
+
for (const name of ax_object) {
|
|
571
|
+
const axRoles = AXObjectRoles.get(name);
|
|
572
|
+
if (axRoles) {
|
|
573
|
+
for (const { name: _name } of axRoles) {
|
|
574
|
+
if (_name === role) {
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return false;
|
|
583
|
+
}
|
|
458
584
|
export {
|
|
459
585
|
a11y
|
|
460
586
|
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
const visibleDirective = (load,
|
|
1
|
+
const visibleDirective = (load, options, el) => {
|
|
2
2
|
const cb = async () => {
|
|
3
3
|
const hydrate = await load();
|
|
4
4
|
await hydrate();
|
|
5
5
|
};
|
|
6
|
+
const rawOptions = typeof options.value === "object" ? options.value : void 0;
|
|
7
|
+
const ioOptions = {
|
|
8
|
+
rootMargin: rawOptions?.rootMargin
|
|
9
|
+
};
|
|
6
10
|
const io = new IntersectionObserver((entries) => {
|
|
7
11
|
for (const entry of entries) {
|
|
8
12
|
if (!entry.isIntersecting)
|
|
@@ -11,7 +15,7 @@ const visibleDirective = (load, _options, el) => {
|
|
|
11
15
|
cb();
|
|
12
16
|
break;
|
|
13
17
|
}
|
|
14
|
-
});
|
|
18
|
+
}, ioOptions);
|
|
15
19
|
for (const child of el.children) {
|
|
16
20
|
io.observe(child);
|
|
17
21
|
}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Do not edit this directly, but instead edit that file and rerun the prebuild
|
|
4
4
|
* to generate this file.
|
|
5
5
|
*/
|
|
6
|
-
declare const _default: "(()=>{var
|
|
6
|
+
declare const _default: "(()=>{var l=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value==\"object\"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let a of e)if(a.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=l;window.dispatchEvent(new Event(\"astro:visible\"));})();";
|
|
7
7
|
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var visible_prebuilt_default = `(()=>{var
|
|
1
|
+
var visible_prebuilt_default = `(()=>{var l=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value=="object"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let a of e)if(a.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=l;window.dispatchEvent(new Event("astro:visible"));})();`;
|
|
2
2
|
export {
|
|
3
3
|
visible_prebuilt_default as default
|
|
4
4
|
};
|
|
@@ -39,6 +39,15 @@ function stringifyChunk(result, chunk) {
|
|
|
39
39
|
}
|
|
40
40
|
return renderAllHeadContent(result);
|
|
41
41
|
}
|
|
42
|
+
case "renderer-hydration-script": {
|
|
43
|
+
const { rendererSpecificHydrationScripts } = result._metadata;
|
|
44
|
+
const { rendererName } = instruction;
|
|
45
|
+
if (!rendererSpecificHydrationScripts.has(rendererName)) {
|
|
46
|
+
rendererSpecificHydrationScripts.add(rendererName);
|
|
47
|
+
return instruction.render();
|
|
48
|
+
}
|
|
49
|
+
return "";
|
|
50
|
+
}
|
|
42
51
|
default: {
|
|
43
52
|
throw new Error(`Unknown chunk type: ${chunk.type}`);
|
|
44
53
|
}
|
|
@@ -291,6 +291,15 @@ ${serializeProps(
|
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
destination.write(createRenderInstruction({ type: "directive", hydration }));
|
|
294
|
+
if (hydration.directive !== "only" && renderer?.ssr.renderHydrationScript) {
|
|
295
|
+
destination.write(
|
|
296
|
+
createRenderInstruction({
|
|
297
|
+
type: "renderer-hydration-script",
|
|
298
|
+
rendererName: renderer.name,
|
|
299
|
+
render: renderer.ssr.renderHydrationScript
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
}
|
|
294
303
|
destination.write(markHTMLString(renderElement("astro-island", island, false)));
|
|
295
304
|
}
|
|
296
305
|
};
|
|
@@ -6,11 +6,21 @@ export type RenderDirectiveInstruction = {
|
|
|
6
6
|
export type RenderHeadInstruction = {
|
|
7
7
|
type: 'head';
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Render a renderer-specific hydration script before the first component of that
|
|
11
|
+
* framework
|
|
12
|
+
*/
|
|
13
|
+
export type RendererHydrationScriptInstruction = {
|
|
14
|
+
type: 'renderer-hydration-script';
|
|
15
|
+
rendererName: string;
|
|
16
|
+
render: () => string;
|
|
17
|
+
};
|
|
9
18
|
export type MaybeRenderHeadInstruction = {
|
|
10
19
|
type: 'maybe-head';
|
|
11
20
|
};
|
|
12
|
-
export type RenderInstruction = RenderDirectiveInstruction | RenderHeadInstruction | MaybeRenderHeadInstruction;
|
|
21
|
+
export type RenderInstruction = RenderDirectiveInstruction | RenderHeadInstruction | MaybeRenderHeadInstruction | RendererHydrationScriptInstruction;
|
|
13
22
|
export declare function createRenderInstruction(instruction: RenderDirectiveInstruction): RenderDirectiveInstruction;
|
|
23
|
+
export declare function createRenderInstruction(instruction: RendererHydrationScriptInstruction): RendererHydrationScriptInstruction;
|
|
14
24
|
export declare function createRenderInstruction(instruction: RenderHeadInstruction): RenderHeadInstruction;
|
|
15
25
|
export declare function createRenderInstruction(instruction: MaybeRenderHeadInstruction): MaybeRenderHeadInstruction;
|
|
16
26
|
export declare function isRenderInstruction(chunk: any): chunk is RenderInstruction;
|