astro 2.5.2 → 2.5.3

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.
@@ -1170,6 +1170,12 @@ export interface ContentEntryType {
1170
1170
  entry: ContentEntryModule;
1171
1171
  }): rollup.LoadResult | Promise<rollup.LoadResult>;
1172
1172
  contentModuleTypes?: string;
1173
+ /**
1174
+ * Handle asset propagation for rendered content to avoid bleed.
1175
+ * Ex. MDX content can import styles and scripts, so `handlePropagation` should be true.
1176
+ * @default true
1177
+ */
1178
+ handlePropagation?: boolean;
1173
1179
  }
1174
1180
  type GetContentEntryInfoReturnType = {
1175
1181
  data: Record<string, unknown>;
@@ -1,9 +1,10 @@
1
1
  export declare const PROPAGATED_ASSET_FLAG = "astroPropagatedAssets";
2
+ export declare const CONTENT_RENDER_FLAG = "astroRenderContent";
2
3
  export declare const CONTENT_FLAG = "astroContentCollectionEntry";
3
4
  export declare const DATA_FLAG = "astroDataCollectionEntry";
4
- export declare const CONTENT_FLAGS: readonly ["astroContentCollectionEntry", "astroDataCollectionEntry", "astroPropagatedAssets"];
5
5
  export declare const VIRTUAL_MODULE_ID = "astro:content";
6
6
  export declare const LINKS_PLACEHOLDER = "@@ASTRO-LINKS@@";
7
7
  export declare const STYLES_PLACEHOLDER = "@@ASTRO-STYLES@@";
8
8
  export declare const SCRIPTS_PLACEHOLDER = "@@ASTRO-SCRIPTS@@";
9
+ export declare const CONTENT_FLAGS: readonly ["astroContentCollectionEntry", "astroRenderContent", "astroDataCollectionEntry", "astroPropagatedAssets"];
9
10
  export declare const CONTENT_TYPES_FILE = "types.d.ts";
@@ -1,15 +1,22 @@
1
1
  const PROPAGATED_ASSET_FLAG = "astroPropagatedAssets";
2
+ const CONTENT_RENDER_FLAG = "astroRenderContent";
2
3
  const CONTENT_FLAG = "astroContentCollectionEntry";
3
4
  const DATA_FLAG = "astroDataCollectionEntry";
4
- const CONTENT_FLAGS = [CONTENT_FLAG, DATA_FLAG, PROPAGATED_ASSET_FLAG];
5
5
  const VIRTUAL_MODULE_ID = "astro:content";
6
6
  const LINKS_PLACEHOLDER = "@@ASTRO-LINKS@@";
7
7
  const STYLES_PLACEHOLDER = "@@ASTRO-STYLES@@";
8
8
  const SCRIPTS_PLACEHOLDER = "@@ASTRO-SCRIPTS@@";
9
+ const CONTENT_FLAGS = [
10
+ CONTENT_FLAG,
11
+ CONTENT_RENDER_FLAG,
12
+ DATA_FLAG,
13
+ PROPAGATED_ASSET_FLAG
14
+ ];
9
15
  const CONTENT_TYPES_FILE = "types.d.ts";
10
16
  export {
11
17
  CONTENT_FLAG,
12
18
  CONTENT_FLAGS,
19
+ CONTENT_RENDER_FLAG,
13
20
  CONTENT_TYPES_FILE,
14
21
  DATA_FLAG,
15
22
  LINKS_PLACEHOLDER,
@@ -184,7 +184,7 @@ async function render({
184
184
  id,
185
185
  renderEntryImport
186
186
  }) {
187
- var _a;
187
+ var _a, _b;
188
188
  const UnexpectedRenderError = new AstroError({
189
189
  ...AstroErrorData.UnknownContentCollectionError,
190
190
  message: `Unexpected error while rendering ${String(collection)} \u2192 ${String(id)}.`
@@ -194,53 +194,69 @@ async function render({
194
194
  const baseMod = await renderEntryImport();
195
195
  if (baseMod == null || typeof baseMod !== "object")
196
196
  throw UnexpectedRenderError;
197
- const { collectedStyles, collectedLinks, collectedScripts, getMod } = baseMod;
198
- if (typeof getMod !== "function")
199
- throw UnexpectedRenderError;
200
- const mod = await getMod();
201
- if (mod == null || typeof mod !== "object")
197
+ if (baseMod.default != null && typeof baseMod.default === "object" && baseMod.default.__astroPropagation === true) {
198
+ const { collectedStyles, collectedLinks, collectedScripts, getMod } = baseMod.default;
199
+ if (typeof getMod !== "function")
200
+ throw UnexpectedRenderError;
201
+ const propagationMod = await getMod();
202
+ if (propagationMod == null || typeof propagationMod !== "object")
203
+ throw UnexpectedRenderError;
204
+ const Content = createComponent({
205
+ factory(result, baseProps, slots) {
206
+ let styles = "", links = "", scripts = "";
207
+ if (Array.isArray(collectedStyles)) {
208
+ styles = collectedStyles.map((style) => {
209
+ return renderUniqueStylesheet(result, {
210
+ type: "inline",
211
+ content: style
212
+ });
213
+ }).join("");
214
+ }
215
+ if (Array.isArray(collectedLinks)) {
216
+ links = collectedLinks.map((link) => {
217
+ return renderUniqueStylesheet(result, {
218
+ type: "external",
219
+ src: prependForwardSlash(link)
220
+ });
221
+ }).join("");
222
+ }
223
+ if (Array.isArray(collectedScripts)) {
224
+ scripts = collectedScripts.map((script) => renderScriptElement(script)).join("");
225
+ }
226
+ let props = baseProps;
227
+ if (id.endsWith("mdx")) {
228
+ props = {
229
+ components: propagationMod.components ?? {},
230
+ ...baseProps
231
+ };
232
+ }
233
+ return createHeadAndContent(
234
+ unescapeHTML(styles + links + scripts),
235
+ renderTemplate`${renderComponent(
236
+ result,
237
+ "Content",
238
+ propagationMod.Content,
239
+ props,
240
+ slots
241
+ )}`
242
+ );
243
+ },
244
+ propagation: "self"
245
+ });
246
+ return {
247
+ Content,
248
+ headings: ((_a = propagationMod.getHeadings) == null ? void 0 : _a.call(propagationMod)) ?? [],
249
+ remarkPluginFrontmatter: propagationMod.frontmatter ?? {}
250
+ };
251
+ } else if (baseMod.Content && typeof baseMod.Content === "function") {
252
+ return {
253
+ Content: baseMod.Content,
254
+ headings: ((_b = baseMod.getHeadings) == null ? void 0 : _b.call(baseMod)) ?? [],
255
+ remarkPluginFrontmatter: baseMod.frontmatter ?? {}
256
+ };
257
+ } else {
202
258
  throw UnexpectedRenderError;
203
- const Content = createComponent({
204
- factory(result, baseProps, slots) {
205
- let styles = "", links = "", scripts = "";
206
- if (Array.isArray(collectedStyles)) {
207
- styles = collectedStyles.map((style) => {
208
- return renderUniqueStylesheet(result, {
209
- type: "inline",
210
- content: style
211
- });
212
- }).join("");
213
- }
214
- if (Array.isArray(collectedLinks)) {
215
- links = collectedLinks.map((link) => {
216
- return renderUniqueStylesheet(result, {
217
- type: "external",
218
- src: prependForwardSlash(link)
219
- });
220
- }).join("");
221
- }
222
- if (Array.isArray(collectedScripts)) {
223
- scripts = collectedScripts.map((script) => renderScriptElement(script)).join("");
224
- }
225
- let props = baseProps;
226
- if (id.endsWith("mdx")) {
227
- props = {
228
- components: mod.components ?? {},
229
- ...baseProps
230
- };
231
- }
232
- return createHeadAndContent(
233
- unescapeHTML(styles + links + scripts),
234
- renderTemplate`${renderComponent(result, "Content", mod.Content, props, slots)}`
235
- );
236
- },
237
- propagation: "self"
238
- });
239
- return {
240
- Content,
241
- headings: ((_a = mod.getHeadings) == null ? void 0 : _a.call(mod)) ?? [],
242
- remarkPluginFrontmatter: mod.frontmatter ?? {}
243
- };
259
+ }
244
260
  }
245
261
  function createReference({ lookupMap }) {
246
262
  return function reference(collection) {
@@ -1,4 +1,5 @@
1
- import { pathToFileURL } from "url";
1
+ import { extname } from "node:path";
2
+ import { pathToFileURL } from "node:url";
2
3
  import { moduleIsTopLevelPage, walkParentInfos } from "../core/build/graph.js";
3
4
  import { getPageDataByViteID } from "../core/build/internal.js";
4
5
  import { createViteLoader } from "../core/module-loader/vite.js";
@@ -6,15 +7,13 @@ import { joinPaths, prependForwardSlash } from "../core/path.js";
6
7
  import { getStylesForURL } from "../core/render/dev/css.js";
7
8
  import { getScriptsForURL } from "../core/render/dev/scripts.js";
8
9
  import {
10
+ CONTENT_RENDER_FLAG,
9
11
  LINKS_PLACEHOLDER,
10
12
  PROPAGATED_ASSET_FLAG,
11
13
  SCRIPTS_PLACEHOLDER,
12
14
  STYLES_PLACEHOLDER
13
15
  } from "./consts.js";
14
- function isPropagatedAsset(viteId) {
15
- const flags = new URLSearchParams(viteId.split("?")[1]);
16
- return flags.has(PROPAGATED_ASSET_FLAG);
17
- }
16
+ import { hasContentFlag } from "./utils.js";
18
17
  function astroContentAssetPropagationPlugin({
19
18
  mode,
20
19
  settings
@@ -22,6 +21,21 @@ function astroContentAssetPropagationPlugin({
22
21
  let devModuleLoader;
23
22
  return {
24
23
  name: "astro:content-asset-propagation",
24
+ enforce: "pre",
25
+ async resolveId(id, importer, opts) {
26
+ if (hasContentFlag(id, CONTENT_RENDER_FLAG)) {
27
+ const base = id.split("?")[0];
28
+ for (const { extensions, handlePropagation = true } of settings.contentEntryTypes) {
29
+ if (handlePropagation && extensions.includes(extname(base))) {
30
+ return this.resolve(`${base}?${PROPAGATED_ASSET_FLAG}`, importer, {
31
+ skipSelf: true,
32
+ ...opts
33
+ });
34
+ }
35
+ }
36
+ return this.resolve(base, importer, { skipSelf: true, ...opts });
37
+ }
38
+ },
25
39
  configureServer(server) {
26
40
  if (mode === "dev") {
27
41
  devModuleLoader = createViteLoader(server);
@@ -29,7 +43,7 @@ function astroContentAssetPropagationPlugin({
29
43
  },
30
44
  async transform(_, id, options) {
31
45
  var _a;
32
- if (isPropagatedAsset(id)) {
46
+ if (hasContentFlag(id, PROPAGATED_ASSET_FLAG)) {
33
47
  const basePath = id.split("?")[0];
34
48
  let stringifiedLinks, stringifiedStyles, stringifiedScripts;
35
49
  if ((options == null ? void 0 : options.ssr) && devModuleLoader) {
@@ -55,12 +69,14 @@ function astroContentAssetPropagationPlugin({
55
69
  stringifiedScripts = JSON.stringify(SCRIPTS_PLACEHOLDER);
56
70
  }
57
71
  const code = `
58
- export async function getMod() {
72
+ async function getMod() {
59
73
  return import(${JSON.stringify(basePath)});
60
74
  }
61
- export const collectedLinks = ${stringifiedLinks};
62
- export const collectedStyles = ${stringifiedStyles};
63
- export const collectedScripts = ${stringifiedScripts};
75
+ const collectedLinks = ${stringifiedLinks};
76
+ const collectedStyles = ${stringifiedStyles};
77
+ const collectedScripts = ${stringifiedScripts};
78
+ const defaultMod = { __astroPropagation: true, getMod, collectedLinks, collectedStyles, collectedScripts };
79
+ export default defaultMod;
64
80
  `;
65
81
  return { code, map: { mappings: "" } };
66
82
  }
@@ -118,18 +118,18 @@ class App {
118
118
  let mod = await this.#manifest.pageMap.get(routeData.component)();
119
119
  if (routeData.type === "page") {
120
120
  let response = await this.#renderPage(request, routeData, mod, defaultStatus);
121
- if (response.status === 500) {
122
- const fiveHundredRouteData = matchRoute("/500", this.#manifestData);
123
- if (fiveHundredRouteData) {
124
- mod = await this.#manifest.pageMap.get(fiveHundredRouteData.component)();
121
+ if (response.status === 500 || response.status === 404) {
122
+ const errorPageData = matchRoute("/" + response.status, this.#manifestData);
123
+ if (errorPageData && errorPageData.route !== routeData.route) {
124
+ mod = await this.#manifest.pageMap.get(errorPageData.component)();
125
125
  try {
126
- let fiveHundredResponse = await this.#renderPage(
126
+ let errorResponse = await this.#renderPage(
127
127
  request,
128
- fiveHundredRouteData,
128
+ errorPageData,
129
129
  mod,
130
- 500
130
+ response.status
131
131
  );
132
- return fiveHundredResponse;
132
+ return errorResponse;
133
133
  } catch {
134
134
  }
135
135
  }
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "2.5.2";
1
+ const ASTRO_VERSION = "2.5.3";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -53,7 +53,7 @@ async function dev(settings, options) {
53
53
  isRestart: options.isRestart
54
54
  })
55
55
  );
56
- const currentVersion = "2.5.2";
56
+ const currentVersion = "2.5.3";
57
57
  if (currentVersion.includes("-")) {
58
58
  warn(options.logging, null, msg.prerelease({ currentVersion }));
59
59
  }
@@ -47,7 +47,7 @@ function serverStart({
47
47
  base,
48
48
  isRestart = false
49
49
  }) {
50
- const version = "2.5.2";
50
+ const version = "2.5.3";
51
51
  const localPrefix = `${dim("\u2503")} Local `;
52
52
  const networkPrefix = `${dim("\u2503")} Network `;
53
53
  const emptyPrefix = " ".repeat(11);
@@ -233,7 +233,7 @@ function printHelp({
233
233
  message.push(
234
234
  linebreak(),
235
235
  ` ${bgGreen(black(` ${commandName} `))} ${green(
236
- `v${"2.5.2"}`
236
+ `v${"2.5.3"}`
237
237
  )} ${headline}`
238
238
  );
239
239
  }
@@ -1,15 +1,13 @@
1
1
  import npath from "path";
2
- import { PROPAGATED_ASSET_FLAG } from "../../../content/consts.js";
3
2
  import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from "../../constants.js";
4
3
  import { unwrapId } from "../../util.js";
5
4
  import { isCSSRequest } from "./util.js";
6
- const fileExtensionsToSSR = /* @__PURE__ */ new Set([".astro", ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS]);
5
+ const fileExtensionsToSSR = /* @__PURE__ */ new Set([".astro", ".mdoc", ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS]);
7
6
  const STRIP_QUERY_PARAMS_REGEX = /\?.*$/;
7
+ const ASTRO_PROPAGATED_ASSET_REGEX = /\?astroPropagatedAssets/;
8
8
  async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ new Set()) {
9
9
  const id = unwrapId(_id);
10
10
  const importedModules = /* @__PURE__ */ new Set();
11
- if (new URL(id, "file://").searchParams.has(PROPAGATED_ASSET_FLAG))
12
- return;
13
11
  const moduleEntriesForId = isRootFile ? (
14
12
  // "getModulesByFile" pulls from a delayed module cache (fun implementation detail),
15
13
  // So we can get up-to-date info on initial server load.
@@ -33,14 +31,11 @@ async function* crawlGraph(loader, _id, isRootFile, scanned = /* @__PURE__ */ ne
33
31
  if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
34
32
  continue;
35
33
  }
36
- if (fileExtensionsToSSR.has(
37
- npath.extname(
38
- // Use `id` instead of `pathname` to preserve query params.
39
- // Should not SSR a module with an unexpected query param,
40
- // like "?astroPropagatedAssets"
41
- importedModule.id
42
- )
43
- )) {
34
+ const isFileTypeNeedingSSR = fileExtensionsToSSR.has(
35
+ npath.extname(importedModulePathname)
36
+ );
37
+ if (isFileTypeNeedingSSR && // Should not SSR a module with ?astroPropagatedAssets
38
+ !ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id)) {
44
39
  const mod = loader.getModuleById(importedModule.id);
45
40
  if (!(mod == null ? void 0 : mod.ssrModule)) {
46
41
  try {
@@ -1,6 +1,6 @@
1
1
  import { getTopLevelPages, walkParentInfos } from "../core/build/graph.js";
2
2
  import { getAstroMetadata } from "../vite-plugin-astro/index.js";
3
- const injectExp = /^\/\/\s*astro-head-inject/;
3
+ const injectExp = /(^\/\/|\/\/!)\s*astro-head-inject/;
4
4
  function configHeadVitePlugin({
5
5
  settings
6
6
  }) {
@@ -10,7 +10,9 @@ const markdownContentEntryType = {
10
10
  slug: parsed.data.slug,
11
11
  rawData: parsed.matter
12
12
  };
13
- }
13
+ },
14
+ // We need to handle propagation for Markdown because they support layouts which will bring in styles.
15
+ handlePropagation: true
14
16
  };
15
17
  const mdxContentEntryType = {
16
18
  extensions: [".mdx"],
@@ -23,6 +25,9 @@ const mdxContentEntryType = {
23
25
  rawData: parsed.matter
24
26
  };
25
27
  },
28
+ // MDX can import scripts and styles,
29
+ // so wrap all MDX files with script / style propagation checks
30
+ handlePropagation: true,
26
31
  contentModuleTypes: `declare module 'astro:content' {
27
32
  interface Render {
28
33
  '.mdx': Promise<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "2.5.2",
3
+ "version": "2.5.3",
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",
@@ -46,7 +46,7 @@ function createGlobLookup(glob) {
46
46
  }
47
47
 
48
48
  const renderEntryGlob = import.meta.glob('@@RENDER_ENTRY_GLOB_PATH@@', {
49
- query: { astroPropagatedAssets: true },
49
+ query: { astroRenderContent: true },
50
50
  });
51
51
  const collectionToRenderEntryMap = createCollectionToGlobResultMap({
52
52
  globResult: renderEntryGlob,