astro 6.4.0 → 6.4.1

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.
@@ -1,6 +1,6 @@
1
1
  class BuildTimeAstroVersionProvider {
2
2
  // Injected during the build through esbuild define
3
- version = "6.4.0";
3
+ version = "6.4.1";
4
4
  }
5
5
  export {
6
6
  BuildTimeAstroVersionProvider
@@ -197,7 +197,7 @@ ${contentConfig.error.message}`
197
197
  logger.info("Content config changed");
198
198
  shouldClear = true;
199
199
  }
200
- if (previousAstroVersion && previousAstroVersion !== "6.4.0") {
200
+ if (previousAstroVersion && previousAstroVersion !== "6.4.1") {
201
201
  logger.info("Astro version changed");
202
202
  shouldClear = true;
203
203
  }
@@ -205,8 +205,8 @@ ${contentConfig.error.message}`
205
205
  logger.info("Clearing content store");
206
206
  this.#store.clearAll();
207
207
  }
208
- if ("6.4.0") {
209
- this.#store.metaStore().set("astro-version", "6.4.0");
208
+ if ("6.4.1") {
209
+ this.#store.metaStore().set("astro-version", "6.4.1");
210
210
  }
211
211
  if (currentConfigDigest) {
212
212
  this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "6.4.0";
1
+ const ASTRO_VERSION = "6.4.1";
2
2
  const ASTRO_GENERATOR = `Astro v${ASTRO_VERSION}`;
3
3
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
4
4
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
@@ -37,7 +37,7 @@ async function dev(inlineConfig) {
37
37
  await telemetry.record([]);
38
38
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
39
39
  const logger = restart.container.logger;
40
- const currentVersion = "6.4.0";
40
+ const currentVersion = "6.4.1";
41
41
  const isPrerelease = currentVersion.includes("-");
42
42
  if (!isPrerelease) {
43
43
  try {
@@ -276,7 +276,7 @@ function printHelp({
276
276
  message.push(
277
277
  linebreak(),
278
278
  ` ${bgGreen(black(` ${commandName} `))} ${green(
279
- `v${"6.4.0"}`
279
+ `v${"6.4.1"}`
280
280
  )} ${headline}`
281
281
  );
282
282
  }
@@ -0,0 +1,5 @@
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;
@@ -0,0 +1,241 @@
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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "6.4.0",
3
+ "version": "6.4.1",
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,6 +39,7 @@
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",
42
43
  "./jsx-runtime": {
43
44
  "types": "./jsx-runtime.d.ts",
44
45
  "default": "./dist/jsx-runtime/index.js"
@@ -188,6 +189,8 @@
188
189
  "expect-type": "^1.3.0",
189
190
  "fs-fixture": "^2.13.0",
190
191
  "hono": "^4.12.14",
192
+ "mdast-util-mdx": "^3.0.0",
193
+ "mdast-util-mdx-jsx": "^3.2.0",
191
194
  "node-mocks-http": "^1.17.2",
192
195
  "parse-srcset": "^1.0.2",
193
196
  "rehype-autolink-headings": "^7.1.0",