astro 7.0.0-beta.3 → 7.0.0-beta.5

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.
Files changed (57) hide show
  1. package/dist/assets/build/generate.js +4 -3
  2. package/dist/cli/add/index.js +1 -0
  3. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  4. package/dist/container/index.d.ts +3 -3
  5. package/dist/content/content-layer.js +3 -3
  6. package/dist/content/runtime.d.ts +1 -1
  7. package/dist/content/runtime.js +1 -0
  8. package/dist/content/vite-plugin-content-virtual-mod.js +27 -0
  9. package/dist/core/app/base.js +7 -15
  10. package/dist/core/app/prepare-response.d.ts +2 -3
  11. package/dist/core/app/prepare-response.js +1 -6
  12. package/dist/core/build/generate.js +1 -1
  13. package/dist/core/build/plugins/plugin-css.js +1 -0
  14. package/dist/core/config/schemas/base.d.ts +4 -4
  15. package/dist/core/config/schemas/base.js +4 -4
  16. package/dist/core/config/validate.js +10 -2
  17. package/dist/core/constants.d.ts +0 -41
  18. package/dist/core/constants.js +1 -18
  19. package/dist/core/dev/dev.js +1 -1
  20. package/dist/core/errors/default-handler.js +22 -8
  21. package/dist/core/fetch/fetch-state.d.ts +11 -0
  22. package/dist/core/fetch/fetch-state.js +21 -2
  23. package/dist/core/fetch/index.d.ts +8 -3
  24. package/dist/core/fetch/index.js +2 -2
  25. package/dist/core/i18n/handler.js +7 -13
  26. package/dist/core/messages/runtime.js +1 -1
  27. package/dist/core/middleware/astro-middleware.d.ts +19 -0
  28. package/dist/core/middleware/astro-middleware.js +43 -0
  29. package/dist/core/middleware/noop-middleware.js +0 -2
  30. package/dist/core/middleware/vite-plugin.d.ts +1 -0
  31. package/dist/core/middleware/vite-plugin.js +5 -1
  32. package/dist/core/pages/handler.d.ts +13 -0
  33. package/dist/core/pages/handler.js +35 -14
  34. package/dist/core/routing/handler.js +6 -8
  35. package/dist/core/routing/rewrite.js +2 -1
  36. package/dist/core/util/normalized-url.js +2 -5
  37. package/dist/core/util/pathname.d.ts +17 -10
  38. package/dist/core/util/pathname.js +14 -7
  39. package/dist/i18n/index.js +11 -9
  40. package/dist/runtime/server/endpoint.d.ts +2 -1
  41. package/dist/runtime/server/endpoint.js +4 -13
  42. package/dist/runtime/server/jsx.js +2 -1
  43. package/dist/runtime/server/render/head.js +2 -1
  44. package/dist/runtime/server/render/util.js +4 -0
  45. package/dist/types/public/config.d.ts +68 -13
  46. package/dist/virtual-modules/container.d.ts +1 -1
  47. package/dist/vite-plugin-head/index.js +5 -11
  48. package/dist/vite-plugin-hmr-reload/index.js +19 -6
  49. package/dist/vite-plugin-html/transform/slots.js +4 -1
  50. package/dist/vite-plugin-pages/pages.d.ts +11 -0
  51. package/dist/vite-plugin-pages/pages.js +1 -3
  52. package/package.json +12 -6
  53. package/templates/content/module.mjs +0 -1
  54. package/dist/core/head-propagation/hint.d.ts +0 -4
  55. package/dist/core/head-propagation/hint.js +0 -7
  56. package/dist/jsx/rehype.d.ts +0 -5
  57. package/dist/jsx/rehype.js +0 -241
@@ -420,22 +420,22 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
420
420
  * @docs
421
421
  * @name compressHTML
422
422
  * @type {boolean | "jsx"}
423
- * @default `true`
423
+ * @default `'jsx'`
424
424
  * @description
425
425
  *
426
426
  * Controls how Astro handles whitespace in your HTML. This affects both development mode and the final build output.
427
427
  *
428
- * By default, Astro removes whitespace from your HTML, including line breaks, in a lossless manner from `.astro` components. Some whitespace may be preserved as needed to maintain the visual rendering of your HTML.
428
+ * Since v7.0, Astro applies by default the JSX whitespace rules used by frameworks like React. This removes whitespace and line breaks around elements, collapses multi-line text onto a single line, and preserves whitespace within a single line (e.g. a space between two inline elements). To keep a space that would otherwise be removed, include it explicitly in the source through constructs such as `{" "}`.
429
429
  *
430
- * Since 6.2.0, this option can also be set to `"jsx"`, Astro will apply the JSX whitespace stripping rules used by frameworks like React. Leading and trailing whitespace is only preserved when explicitly included in the source code through constructs such as `{" "}`, and is otherwise removed entirely.
430
+ * Setting this option to `true` instead removes whitespace, including line breaks, in a lossless manner from `.astro` components. Some whitespace may be preserved as needed to maintain the visual rendering of your HTML.
431
431
  *
432
- * Setting this option to false disables HTML compression and preserves all whitespace.
432
+ * Setting this option to `false` disables HTML compression and preserves all whitespace.
433
433
  *
434
434
  * ```js
435
435
  * {
436
- * compressHTML: false
436
+ * compressHTML: true
437
437
  * // or:
438
- * // compressHTML: 'jsx'
438
+ * // compressHTML: false
439
439
  * }
440
440
  * ```
441
441
  */
@@ -1348,7 +1348,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
1348
1348
  * });
1349
1349
  * ```
1350
1350
  *
1351
- * Learn more about customizing the request pipeline in the [advanced routing guide](https://docs.astro.build/en/guides/routing/#advanced-routing).
1351
+ * Learn more about customizing the request pipeline in the [advanced routing guide](https://v7.docs.astro.build/en/guides/routing/#advanced-routing).
1352
1352
  */
1353
1353
  fetchFile?: string | null;
1354
1354
  /**
@@ -1360,10 +1360,52 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
1360
1360
  * @version 7.0.0
1361
1361
  * @description
1362
1362
  *
1363
- * Configures a custom logger by defining its entrypoint and, optionally, providing a serializable configuration:
1363
+ * Configures how Astro logs messages during development and production.
1364
+ *
1365
+ * By default, Astro uses a built-in logger that outputs human-friendly logs to the console. You can customize this behavior by providing [your own logger handler](https://v7.docs.astro.build/en/reference/logger-reference/#custom-loggers) or by using one of the [built-in log handlers](https://v7.docs.astro.build/en/reference/logger-reference/#built-in-loggers):
1364
1366
  *
1365
1367
  * ```js
1366
1368
  * // astro.config.mjs
1369
+ * import { defineConfig, logHandlers } from 'astro/config';
1370
+ *
1371
+ * export default defineConfig({
1372
+ * logger: logHandlers.json({ level: 'info' })
1373
+ * });
1374
+ * ```
1375
+ *
1376
+ * See [the logger API reference](https://v7.docs.astro.build/en/reference/logger-reference/) for more information.
1377
+ */
1378
+ logger?: LoggerHandlerConfig;
1379
+ /**
1380
+ * @docs
1381
+ * @name logger.entrypoint
1382
+ * @type {string}
1383
+ * @version 7.0.0
1384
+ * @description
1385
+ *
1386
+ * The entrypoint of the log handler. This can be a path to a file in your project or an npm package:
1387
+ *
1388
+ * ```js title="astro.config.mjs"
1389
+ * import { defineConfig } from 'astro/config';
1390
+ *
1391
+ * export default defineConfig({
1392
+ * logger: {
1393
+ * entrypoint: "@org/astro-logger",
1394
+ * }
1395
+ * });
1396
+ * ```
1397
+ */
1398
+ /**
1399
+ * @docs
1400
+ * @name logger.config
1401
+ * @type {Record<string, unknown> | undefined}
1402
+ * @version 7.0.0
1403
+ * @default `{}`
1404
+ * @description
1405
+ *
1406
+ * The configuration object for the log handler. The options depend on the configured logger.
1407
+ *
1408
+ * ```js title="astro.config.mjs"
1367
1409
  * import { defineConfig } from 'astro/config';
1368
1410
  *
1369
1411
  * export default defineConfig({
@@ -1375,10 +1417,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
1375
1417
  * }
1376
1418
  * });
1377
1419
  * ```
1378
- *
1379
- * See [the logger API reference](https://docs.astro.build/en/reference/logger-reference/) for more information.
1380
1420
  */
1381
- logger?: LoggerHandlerConfig;
1382
1421
  /**
1383
1422
  * @docs
1384
1423
  * @kind heading
@@ -2129,8 +2168,24 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
2129
2168
  * @type {MarkdownProcessor}
2130
2169
  * @version 6.4.0
2131
2170
  * @description
2132
- * Configures the Markdown processor used to render `.md` files. Defaults to `unified()` from
2133
- * `@astrojs/markdown-remark` (the remark/rehype pipeline).
2171
+ * Configures the Markdown processor used to render `.md` files. Defaults to `satteri()` from
2172
+ * `@astrojs/markdown-satteri`, Astro's native Markdown pipeline.
2173
+ *
2174
+ * ```js
2175
+ * // astro.config.mjs
2176
+ * import { defineConfig } from 'astro/config';
2177
+ * import { satteri } from '@astrojs/markdown-satteri';
2178
+ *
2179
+ * export default defineConfig({
2180
+ * markdown: {
2181
+ * processor: satteri({
2182
+ * features: { gfm: false },
2183
+ * }),
2184
+ * },
2185
+ * });
2186
+ * ```
2187
+ *
2188
+ * To keep the remark/rehype pipeline, install `@astrojs/markdown-remark` and pass `unified()`:
2134
2189
  *
2135
2190
  * ```js
2136
2191
  * // astro.config.mjs
@@ -4,7 +4,7 @@ import type { SSRLoadedRenderer } from '../types/public/internal.js';
4
4
  * Use this function to provide renderers to the `AstroContainer`:
5
5
  *
6
6
  * ```js
7
- * import { getContainerRenderer } from "@astrojs/react";
7
+ * import { getContainerRenderer } from "@astrojs/react/container-renderer";
8
8
  * import { experimental_AstroContainer as AstroContainer } from "astro/container";
9
9
  * import { loadRenderers } from "astro:container"; // use this only when using vite/vitest
10
10
  *
@@ -1,9 +1,9 @@
1
- import { hasHeadPropagationCall } from "../core/head-propagation/hint.js";
2
1
  import {
3
2
  buildImporterGraphFromModuleInfo,
4
3
  computeInTreeAncestors
5
4
  } from "../core/head-propagation/graph.js";
6
5
  import { getTopLevelPageModuleInfos } from "../core/build/graph.js";
6
+ import { PROPAGATED_ASSET_FLAG } from "../content/consts.js";
7
7
  import { getAstroMetadata } from "../vite-plugin-astro/index.js";
8
8
  import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
9
9
  const VIRTUAL_COMPONENT_METADATA = "virtual:astro:component-metadata";
@@ -127,12 +127,12 @@ function configHeadVitePlugin() {
127
127
  });
128
128
  }
129
129
  },
130
- transform(source, id) {
130
+ transform(_source, id) {
131
131
  let info = this.getModuleInfo(id);
132
132
  if (info && getAstroMetadata(info)?.containsHead) {
133
133
  propagateMetadata.call(this, id, "containsHead", true);
134
134
  }
135
- if (hasHeadPropagationCall(source)) {
135
+ if (id.includes(PROPAGATED_ASSET_FLAG)) {
136
136
  propagateMetadata.call(this, id, "propagation", "in-tree");
137
137
  }
138
138
  invalidateComponentMetadataModule();
@@ -140,17 +140,11 @@ function configHeadVitePlugin() {
140
140
  };
141
141
  }
142
142
  function astroHeadBuildPlugin(internals) {
143
- const headPropagationModuleIds = /* @__PURE__ */ new Set();
144
143
  return {
145
144
  name: "astro:head-metadata-build",
146
145
  applyToEnvironment(environment) {
147
146
  return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender;
148
147
  },
149
- transform(source, id) {
150
- if (hasHeadPropagationCall(source)) {
151
- headPropagationModuleIds.add(id);
152
- }
153
- },
154
148
  generateBundle(_opts, bundle) {
155
149
  const map = internals.componentMetadata;
156
150
  const moduleIds = /* @__PURE__ */ new Set();
@@ -167,7 +161,7 @@ function astroHeadBuildPlugin(internals) {
167
161
  }
168
162
  for (const [, output] of Object.entries(bundle)) {
169
163
  if (output.type !== "chunk") continue;
170
- for (const [id, mod] of Object.entries(output.modules)) {
164
+ for (const [id] of Object.entries(output.modules)) {
171
165
  moduleIds.add(id);
172
166
  const modinfo = this.getModuleInfo(id);
173
167
  if (modinfo) {
@@ -182,7 +176,7 @@ function astroHeadBuildPlugin(internals) {
182
176
  selfPropagationSeeds.add(id);
183
177
  }
184
178
  }
185
- if (mod.code && hasHeadPropagationCall(mod.code) || headPropagationModuleIds.has(id)) {
179
+ if (id.includes(PROPAGATED_ASSET_FLAG)) {
186
180
  commentPropagationSeeds.add(id);
187
181
  }
188
182
  }
@@ -1,15 +1,17 @@
1
1
  import { isRunnableDevEnvironment } from "vite";
2
2
  import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../vite-plugin-pages/const.js";
3
+ import { RESOLVED_MODULE_DEV_CSS_PREFIX } from "../vite-plugin-css/const.js";
3
4
  import { getDevCssModuleNameFromPageVirtualModuleName } from "../vite-plugin-css/util.js";
4
5
  import { isAstroServerEnvironment } from "../environments.js";
5
6
  const STYLE_EXT_REGEX = /\.(?:css|scss|sass|less|styl|pcss)$/i;
7
+ const RAW_QUERY_REGEX = /(?:\?|&)raw(?:&|$)/;
8
+ function hasStyleExtension(id) {
9
+ return STYLE_EXT_REGEX.test(id.split("?")[0]);
10
+ }
6
11
  function isStyleModule(mod) {
7
- if (mod.file && STYLE_EXT_REGEX.test(mod.file)) return true;
8
- if (mod.id) {
9
- const idPath = mod.id.split("?")[0];
10
- if (STYLE_EXT_REGEX.test(idPath)) return true;
11
- }
12
- return false;
12
+ if (mod.id && RAW_QUERY_REGEX.test(mod.id) && hasStyleExtension(mod.id)) return false;
13
+ if (mod.file && hasStyleExtension(mod.file)) return true;
14
+ return mod.id ? hasStyleExtension(mod.id) : false;
13
15
  }
14
16
  function hmrReload() {
15
17
  return {
@@ -65,6 +67,17 @@ function hmrReload() {
65
67
  return [];
66
68
  }
67
69
  if (hasSkippedStyleModules) {
70
+ for (const [id, mod] of this.environment.moduleGraph.idToModuleMap) {
71
+ if (id.startsWith(RESOLVED_MODULE_DEV_CSS_PREFIX)) {
72
+ this.environment.moduleGraph.invalidateModule(mod, void 0, timestamp, true);
73
+ if (isRunnableDevEnvironment(this.environment)) {
74
+ const runnerMod = this.environment.runner.evaluatedModules.getModuleById(id);
75
+ if (runnerMod) {
76
+ this.environment.runner.evaluatedModules.invalidateModule(runnerMod);
77
+ }
78
+ }
79
+ }
80
+ }
68
81
  return [];
69
82
  }
70
83
  if (modules.length > 0) {
@@ -10,7 +10,10 @@ const rehypeSlots = ({ s }) => {
10
10
  const end = node.position?.end.offset ?? 0;
11
11
  const first = node.children.at(0) ?? node;
12
12
  const last = node.children.at(-1) ?? node;
13
- const text = file.value.slice(first.position?.start.offset ?? 0, last.position?.end.offset ?? 0).toString();
13
+ const text = file.value.slice(
14
+ first.position?.start.offset ?? 0,
15
+ last.position?.end.offset ?? 0
16
+ ).toString();
14
17
  s.overwrite(
15
18
  start,
16
19
  end,
@@ -1,8 +1,19 @@
1
1
  import type { Plugin as VitePlugin } from 'vite';
2
2
  import type { RoutesList } from '../types/astro.js';
3
+ import type { RouteData } from '../types/public/internal.js';
3
4
  export declare const VIRTUAL_PAGES_MODULE_ID = "virtual:astro:pages";
4
5
  interface PagesPluginOptions {
5
6
  routesList: RoutesList;
6
7
  }
8
+ /**
9
+ * Filters routes for a specific build environment.
10
+ *
11
+ * Redirect target routes do not need special handling here: they already
12
+ * appear in the routes list with their own `prerender` flag and are
13
+ * included when it matches `isPrerender`. At SSR runtime, redirect
14
+ * responses are generated from route metadata alone (no component is
15
+ * loaded), so the target's component is never needed in the SSR page map.
16
+ */
17
+ export declare function getRoutesForEnvironment(routes: RouteData[], isPrerender: boolean): Set<RouteData>;
7
18
  export declare function pluginPages({ routesList }: PagesPluginOptions): VitePlugin;
8
19
  export {};
@@ -11,9 +11,6 @@ function getRoutesForEnvironment(routes, isPrerender) {
11
11
  if (route.prerender === isPrerender) {
12
12
  result.add(route);
13
13
  }
14
- if (route.redirectRoute) {
15
- result.add(route.redirectRoute);
16
- }
17
14
  }
18
15
  return result;
19
16
  }
@@ -75,5 +72,6 @@ export { pageMap };`;
75
72
  }
76
73
  export {
77
74
  VIRTUAL_PAGES_MODULE_ID,
75
+ getRoutesForEnvironment,
78
76
  pluginPages
79
77
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "7.0.0-beta.3",
3
+ "version": "7.0.0-beta.5",
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",
@@ -39,7 +39,6 @@
39
39
  "./astro-jsx": "./astro-jsx.d.ts",
40
40
  "./tsconfigs/*.json": "./tsconfigs/*",
41
41
  "./tsconfigs/*": "./tsconfigs/*.json",
42
- "./jsx/rehype.js": "./dist/jsx/rehype.js",
43
42
  "./jsx-runtime": {
44
43
  "types": "./jsx-runtime.d.ts",
45
44
  "default": "./dist/jsx-runtime/index.js"
@@ -113,7 +112,7 @@
113
112
  "README.md"
114
113
  ],
115
114
  "dependencies": {
116
- "@astrojs/compiler-rs": "^0.1.10",
115
+ "@astrojs/compiler-rs": "^0.2.2",
117
116
  "@capsizecss/unpack": "^4.0.0",
118
117
  "@clack/prompts": "^1.1.0",
119
118
  "@oslojs/encoding": "^1.1.0",
@@ -167,12 +166,20 @@
167
166
  "yargs-parser": "^22.0.0",
168
167
  "zod": "^4.3.6",
169
168
  "@astrojs/internal-helpers": "0.10.0",
170
- "@astrojs/markdown-remark": "7.2.0",
169
+ "@astrojs/markdown-satteri": "0.3.1-beta.1",
171
170
  "@astrojs/telemetry": "3.3.2"
172
171
  },
173
172
  "optionalDependencies": {
174
173
  "sharp": "^0.34.0"
175
174
  },
175
+ "peerDependencies": {
176
+ "@astrojs/markdown-remark": "7.2.0"
177
+ },
178
+ "peerDependenciesMeta": {
179
+ "@astrojs/markdown-remark": {
180
+ "optional": true
181
+ }
182
+ },
176
183
  "devDependencies": {
177
184
  "@playwright/test": "1.58.2",
178
185
  "@types/aria-query": "^5.0.4",
@@ -189,8 +196,6 @@
189
196
  "expect-type": "^1.3.0",
190
197
  "fs-fixture": "^2.13.0",
191
198
  "hono": "^4.12.14",
192
- "mdast-util-mdx": "^3.0.0",
193
- "mdast-util-mdx-jsx": "^3.2.0",
194
199
  "node-mocks-http": "^1.17.2",
195
200
  "parse-srcset": "^1.0.2",
196
201
  "rehype-autolink-headings": "^7.1.0",
@@ -203,6 +208,7 @@
203
208
  "unified": "^11.0.5",
204
209
  "vitest": "^4.1.0",
205
210
  "@astrojs/check": "0.9.9",
211
+ "@astrojs/markdown-remark": "7.2.0",
206
212
  "astro-scripts": "0.0.14"
207
213
  },
208
214
  "engines": {
@@ -1,4 +1,3 @@
1
- 'use astro:head-inject';
2
1
  import {
3
2
  createDeprecatedFunction,
4
3
  createGetCollection,
@@ -1,4 +0,0 @@
1
- /**
2
- * Returns true when source contains the `"use astro:head-inject"` directive.
3
- */
4
- export declare function hasHeadPropagationCall(source: string): boolean;
@@ -1,7 +0,0 @@
1
- const HEAD_PROPAGATION_HINT = '"use astro:head-inject"';
2
- function hasHeadPropagationCall(source) {
3
- return source.includes(HEAD_PROPAGATION_HINT);
4
- }
5
- export {
6
- hasHeadPropagationCall
7
- };
@@ -1,5 +0,0 @@
1
- import type { RehypePlugin } from '@astrojs/internal-helpers/markdown';
2
- import type { VFile } from 'vfile';
3
- import type { PluginMetadata } from '../vite-plugin-astro/types.js';
4
- export declare const rehypeAnalyzeAstroMetadata: RehypePlugin;
5
- export declare function getAstroMetadata(file: VFile): PluginMetadata["astro"] | undefined;
@@ -1,241 +0,0 @@
1
- import { visit } from "unist-util-visit";
2
- import { AstroError } from "../core/errors/errors.js";
3
- import { AstroErrorData } from "../core/errors/index.js";
4
- import { resolvePath } from "../core/viteUtils.js";
5
- import { createDefaultAstroMetadata } from "../vite-plugin-astro/metadata.js";
6
- const ClientOnlyPlaceholder = "astro-client-only";
7
- const rehypeAnalyzeAstroMetadata = () => {
8
- return (tree, file) => {
9
- const metadata = createDefaultAstroMetadata();
10
- const imports = parseImports(tree.children);
11
- visit(tree, (node) => {
12
- if (node.type !== "mdxJsxFlowElement" && node.type !== "mdxJsxTextElement") return;
13
- const tagName = node.name;
14
- if (!tagName || !isComponent(tagName) || !(hasClientDirective(node) || hasServerDeferDirective(node)))
15
- return;
16
- const matchedImport = findMatchingImport(tagName, imports);
17
- if (!matchedImport) {
18
- throw new AstroError({
19
- ...AstroErrorData.NoMatchingImport,
20
- message: AstroErrorData.NoMatchingImport.message(node.name)
21
- });
22
- }
23
- if (matchedImport.path.endsWith(".astro")) {
24
- const clientAttribute = node.attributes.find(
25
- (attr) => attr.type === "mdxJsxAttribute" && attr.name.startsWith("client:")
26
- );
27
- if (clientAttribute) {
28
- console.warn(
29
- `You are attempting to render <${node.name} ${clientAttribute.name} />, but ${node.name} is an Astro component. Astro components do not render in the client and should not have a hydration directive. Please use a framework component for client rendering.`
30
- );
31
- }
32
- }
33
- const resolvedPath = resolvePath(matchedImport.path, file.path);
34
- if (hasClientOnlyDirective(node)) {
35
- metadata.clientOnlyComponents.push({
36
- exportName: matchedImport.name,
37
- localName: "",
38
- specifier: tagName,
39
- resolvedPath
40
- });
41
- addClientOnlyMetadata(node, matchedImport, resolvedPath);
42
- } else if (hasClientDirective(node)) {
43
- metadata.hydratedComponents.push({
44
- exportName: "*",
45
- localName: "",
46
- specifier: tagName,
47
- resolvedPath
48
- });
49
- addClientMetadata(node, matchedImport, resolvedPath);
50
- } else if (hasServerDeferDirective(node)) {
51
- metadata.serverComponents.push({
52
- exportName: matchedImport.name,
53
- localName: tagName,
54
- specifier: matchedImport.path,
55
- resolvedPath
56
- });
57
- addServerDeferMetadata(node, matchedImport, resolvedPath);
58
- }
59
- });
60
- file.data.__astroMetadata = metadata;
61
- };
62
- };
63
- function getAstroMetadata(file) {
64
- return file.data.__astroMetadata;
65
- }
66
- function parseImports(children) {
67
- const imports = /* @__PURE__ */ new Map();
68
- for (const child of children) {
69
- if (child.type !== "mdxjsEsm") continue;
70
- const body = child.data?.estree?.body;
71
- if (!body) continue;
72
- for (const ast of body) {
73
- if (ast.type !== "ImportDeclaration") continue;
74
- const source = ast.source.value;
75
- const specs = ast.specifiers.map((spec) => {
76
- switch (spec.type) {
77
- case "ImportDefaultSpecifier":
78
- return { local: spec.local.name, imported: "default" };
79
- case "ImportNamespaceSpecifier":
80
- return { local: spec.local.name, imported: "*" };
81
- case "ImportSpecifier": {
82
- return {
83
- local: spec.local.name,
84
- imported: spec.imported.type === "Identifier" ? spec.imported.name : String(spec.imported.value)
85
- };
86
- }
87
- default:
88
- throw new Error("Unknown import declaration specifier: " + spec);
89
- }
90
- });
91
- let specSet = imports.get(source);
92
- if (!specSet) {
93
- specSet = /* @__PURE__ */ new Set();
94
- imports.set(source, specSet);
95
- }
96
- for (const spec of specs) {
97
- specSet.add(spec);
98
- }
99
- }
100
- }
101
- return imports;
102
- }
103
- function isComponent(tagName) {
104
- return tagName[0] && tagName[0].toLowerCase() !== tagName[0] || tagName.includes(".") || /[^a-zA-Z]/.test(tagName[0]);
105
- }
106
- function hasClientDirective(node) {
107
- return node.attributes.some(
108
- (attr) => attr.type === "mdxJsxAttribute" && attr.name.startsWith("client:")
109
- );
110
- }
111
- function hasServerDeferDirective(node) {
112
- return node.attributes.some(
113
- (attr) => attr.type === "mdxJsxAttribute" && attr.name === "server:defer"
114
- );
115
- }
116
- function hasClientOnlyDirective(node) {
117
- return node.attributes.some(
118
- (attr) => attr.type === "mdxJsxAttribute" && attr.name === "client:only"
119
- );
120
- }
121
- function findMatchingImport(tagName, imports) {
122
- const tagSpecifier = tagName.split(".")[0];
123
- for (const [source, specs] of imports) {
124
- for (const { imported, local } of specs) {
125
- if (local === tagSpecifier) {
126
- if (tagSpecifier !== tagName) {
127
- switch (imported) {
128
- // Namespace import: "<buttons.Foo.Bar />" => name: "Foo.Bar"
129
- case "*": {
130
- const accessPath = tagName.slice(tagSpecifier.length + 1);
131
- return { name: accessPath, path: source };
132
- }
133
- // Default import: "<buttons.Foo.Bar />" => name: "default.Foo.Bar"
134
- case "default": {
135
- const accessPath = tagName.slice(tagSpecifier.length + 1);
136
- return { name: `default.${accessPath}`, path: source };
137
- }
138
- // Named import: "<buttons.Foo.Bar />" => name: "buttons.Foo.Bar"
139
- default: {
140
- return { name: tagName, path: source };
141
- }
142
- }
143
- }
144
- return { name: imported, path: source };
145
- }
146
- }
147
- }
148
- }
149
- function addClientMetadata(node, meta, resolvedPath) {
150
- const attributeNames = node.attributes.map((attr) => attr.type === "mdxJsxAttribute" ? attr.name : null).filter(Boolean);
151
- if (!attributeNames.includes("client:component-path")) {
152
- node.attributes.push({
153
- type: "mdxJsxAttribute",
154
- name: "client:component-path",
155
- value: resolvedPath
156
- });
157
- }
158
- if (!attributeNames.includes("client:component-export")) {
159
- if (meta.name === "*") {
160
- meta.name = node.name.split(".").slice(1).join(".");
161
- }
162
- node.attributes.push({
163
- type: "mdxJsxAttribute",
164
- name: "client:component-export",
165
- value: meta.name
166
- });
167
- }
168
- if (!attributeNames.includes("client:component-hydration")) {
169
- node.attributes.push({
170
- type: "mdxJsxAttribute",
171
- name: "client:component-hydration",
172
- value: null
173
- });
174
- }
175
- }
176
- function addClientOnlyMetadata(node, meta, resolvedPath) {
177
- const attributeNames = node.attributes.map((attr) => attr.type === "mdxJsxAttribute" ? attr.name : null).filter(Boolean);
178
- if (!attributeNames.includes("client:display-name")) {
179
- node.attributes.push({
180
- type: "mdxJsxAttribute",
181
- name: "client:display-name",
182
- value: node.name
183
- });
184
- }
185
- if (!attributeNames.includes("client:component-path")) {
186
- node.attributes.push({
187
- type: "mdxJsxAttribute",
188
- name: "client:component-path",
189
- value: resolvedPath
190
- });
191
- }
192
- if (!attributeNames.includes("client:component-export")) {
193
- if (meta.name === "*") {
194
- meta.name = node.name.split(".").slice(1).join(".");
195
- }
196
- node.attributes.push({
197
- type: "mdxJsxAttribute",
198
- name: "client:component-export",
199
- value: meta.name
200
- });
201
- }
202
- if (!attributeNames.includes("client:component-hydration")) {
203
- node.attributes.push({
204
- type: "mdxJsxAttribute",
205
- name: "client:component-hydration",
206
- value: null
207
- });
208
- }
209
- node.name = ClientOnlyPlaceholder;
210
- }
211
- function addServerDeferMetadata(node, meta, resolvedPath) {
212
- const attributeNames = node.attributes.map((attr) => attr.type === "mdxJsxAttribute" ? attr.name : null).filter(Boolean);
213
- if (!attributeNames.includes("server:component-directive")) {
214
- node.attributes.push({
215
- type: "mdxJsxAttribute",
216
- name: "server:component-directive",
217
- value: "server:defer"
218
- });
219
- }
220
- if (!attributeNames.includes("server:component-path")) {
221
- node.attributes.push({
222
- type: "mdxJsxAttribute",
223
- name: "server:component-path",
224
- value: resolvedPath
225
- });
226
- }
227
- if (!attributeNames.includes("server:component-export")) {
228
- if (meta.name === "*") {
229
- meta.name = node.name.split(".").slice(1).join(".");
230
- }
231
- node.attributes.push({
232
- type: "mdxJsxAttribute",
233
- name: "server:component-export",
234
- value: meta.name
235
- });
236
- }
237
- }
238
- export {
239
- getAstroMetadata,
240
- rehypeAnalyzeAstroMetadata
241
- };