Merge branch 'main' into redirects-ssg
This commit is contained in:
commit
11a517b1f1
42 changed files with 404 additions and 157 deletions
5
.changeset/hungry-lobsters-happen.md
Normal file
5
.changeset/hungry-lobsters-happen.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add types for `import.meta.env.ASSETS_PREFIX` and `import.meta.env.SITE`
|
5
.changeset/odd-geese-shop.md
Normal file
5
.changeset/odd-geese-shop.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
value of var can be undefined when using `define:vars`
|
|
@ -1,9 +0,0 @@
|
||||||
import { defineCollection, z } from 'astro:content';
|
|
||||||
|
|
||||||
const docs = defineCollection({
|
|
||||||
schema: z.object({
|
|
||||||
title: z.string(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const collections = { docs };
|
|
|
@ -1,5 +1,13 @@
|
||||||
# astro
|
# astro
|
||||||
|
|
||||||
|
## 2.5.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#6758](https://github.com/withastro/astro/pull/6758) [`f558a9e20`](https://github.com/withastro/astro/commit/f558a9e2056fc8f2e2d5814e74f199e398159fc4) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Improve style and script handling across content collection files. This addresses style bleed present in `@astrojs/markdoc` v0.1.0
|
||||||
|
|
||||||
|
- [#7143](https://github.com/withastro/astro/pull/7143) [`b41963b77`](https://github.com/withastro/astro/commit/b41963b775149b802eea9e12c5fe266bb9a02944) Thanks [@johannesspohr](https://github.com/johannesspohr)! - Render 404 page content when a `Response` with status 404 is returned from a page
|
||||||
|
|
||||||
## 2.5.2
|
## 2.5.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
33
packages/astro/client-base.d.ts
vendored
33
packages/astro/client-base.d.ts
vendored
|
@ -1,5 +1,32 @@
|
||||||
/// <reference path="./import-meta.d.ts" />
|
/// <reference path="./import-meta.d.ts" />
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
declare namespace App {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface Locals {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
/**
|
||||||
|
* The prefix for Astro-generated asset links if the build.assetsPrefix config option is set. This can be used to create asset links not handled by Astro.
|
||||||
|
*/
|
||||||
|
readonly ASSETS_PREFIX: string;
|
||||||
|
/**
|
||||||
|
* This is set to the site option specified in your project’s Astro config file.
|
||||||
|
*/
|
||||||
|
readonly SITE: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
/**
|
||||||
|
* Astro and Vite expose environment variables through `import.meta.env`. For a complete list of the environment variables available, see the two references below.
|
||||||
|
*
|
||||||
|
* - [Astro reference](https://docs.astro.build/en/guides/environment-variables/#default-environment-variables)
|
||||||
|
* - [Vite reference](https://vitejs.dev/guide/env-and-mode.html#env-variables)
|
||||||
|
*/
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
||||||
|
|
||||||
declare module 'astro:assets' {
|
declare module 'astro:assets' {
|
||||||
// Exporting things one by one is a bit cumbersome, not sure if there's a better way - erika, 2023-02-03
|
// Exporting things one by one is a bit cumbersome, not sure if there's a better way - erika, 2023-02-03
|
||||||
type AstroAssets = {
|
type AstroAssets = {
|
||||||
|
@ -387,9 +414,3 @@ declare module '*?inline' {
|
||||||
const src: string;
|
const src: string;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
||||||
declare namespace App {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface Locals {}
|
|
||||||
}
|
|
||||||
|
|
2
packages/astro/client-image.d.ts
vendored
2
packages/astro/client-image.d.ts
vendored
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// TODO: Merge this file with `client-base.d.ts` in 3.0, when the `astro:assets` feature isn't under a flag anymore.
|
// TODO: Merge this file with `client-base.d.ts` in 3.0, when the `astro:assets` feature isn't under a flag anymore.
|
||||||
|
|
||||||
type InputFormat = import('./dist/assets/types.js').InputFormat;
|
type InputFormat = import('./dist/assets/types.js').ImageInputFormat;
|
||||||
|
|
||||||
interface ImageMetadata {
|
interface ImageMetadata {
|
||||||
src: string;
|
src: string;
|
||||||
|
|
4
packages/astro/client.d.ts
vendored
4
packages/astro/client.d.ts
vendored
|
@ -21,10 +21,6 @@ declare module '*.svg' {
|
||||||
const src: string;
|
const src: string;
|
||||||
export default src;
|
export default src;
|
||||||
}
|
}
|
||||||
declare module '*.ico' {
|
|
||||||
const src: string;
|
|
||||||
export default src;
|
|
||||||
}
|
|
||||||
declare module '*.webp' {
|
declare module '*.webp' {
|
||||||
const src: string;
|
const src: string;
|
||||||
export default src;
|
export default src;
|
||||||
|
|
9
packages/astro/import-meta.d.ts
vendored
9
packages/astro/import-meta.d.ts
vendored
|
@ -1,4 +1,4 @@
|
||||||
// File vendored from Vite itself, as a workaround to https://github.com/vitejs/vite/pull/9827 until Vite 4 comes out
|
// File vendored from Vite itself, as a workaround to https://github.com/vitejs/vite/issues/13309 until Vite 5 comes out
|
||||||
|
|
||||||
// This file is an augmentation to the built-in ImportMeta interface
|
// This file is an augmentation to the built-in ImportMeta interface
|
||||||
// Thus cannot contain any top-level imports
|
// Thus cannot contain any top-level imports
|
||||||
|
@ -6,13 +6,6 @@
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
||||||
|
|
||||||
// Duplicate of import('../src/node/importGlob').GlobOptions in order to
|
|
||||||
// avoid breaking the production client type. Because this file is referenced
|
|
||||||
// in vite/client.d.ts and in production src/node/importGlob.ts doesn't exist.
|
|
||||||
interface GlobOptions {
|
|
||||||
as?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
url: string;
|
url: string;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "astro",
|
"name": "astro",
|
||||||
"version": "2.5.2",
|
"version": "2.5.3",
|
||||||
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "withastro",
|
"author": "withastro",
|
||||||
|
|
|
@ -1280,6 +1280,12 @@ export interface ContentEntryType {
|
||||||
}
|
}
|
||||||
): rollup.LoadResult | Promise<rollup.LoadResult>;
|
): rollup.LoadResult | Promise<rollup.LoadResult>;
|
||||||
contentModuleTypes?: string;
|
contentModuleTypes?: string;
|
||||||
|
/**
|
||||||
|
* Handle asset propagation for rendered content to avoid bleed.
|
||||||
|
* Ex. MDX content can import styles and scripts, so `handlePropagation` should be true.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
handlePropagation?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetContentEntryInfoReturnType = {
|
type GetContentEntryInfoReturnType = {
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
export const PROPAGATED_ASSET_FLAG = 'astroPropagatedAssets';
|
export const PROPAGATED_ASSET_FLAG = 'astroPropagatedAssets';
|
||||||
|
export const CONTENT_RENDER_FLAG = 'astroRenderContent';
|
||||||
export const CONTENT_FLAG = 'astroContentCollectionEntry';
|
export const CONTENT_FLAG = 'astroContentCollectionEntry';
|
||||||
export const DATA_FLAG = 'astroDataCollectionEntry';
|
export const DATA_FLAG = 'astroDataCollectionEntry';
|
||||||
export const CONTENT_FLAGS = [CONTENT_FLAG, DATA_FLAG, PROPAGATED_ASSET_FLAG] as const;
|
|
||||||
|
|
||||||
export const VIRTUAL_MODULE_ID = 'astro:content';
|
export const VIRTUAL_MODULE_ID = 'astro:content';
|
||||||
export const LINKS_PLACEHOLDER = '@@ASTRO-LINKS@@';
|
export const LINKS_PLACEHOLDER = '@@ASTRO-LINKS@@';
|
||||||
export const STYLES_PLACEHOLDER = '@@ASTRO-STYLES@@';
|
export const STYLES_PLACEHOLDER = '@@ASTRO-STYLES@@';
|
||||||
export const SCRIPTS_PLACEHOLDER = '@@ASTRO-SCRIPTS@@';
|
export const SCRIPTS_PLACEHOLDER = '@@ASTRO-SCRIPTS@@';
|
||||||
|
|
||||||
|
export const CONTENT_FLAGS = [
|
||||||
|
CONTENT_FLAG,
|
||||||
|
CONTENT_RENDER_FLAG,
|
||||||
|
DATA_FLAG,
|
||||||
|
PROPAGATED_ASSET_FLAG,
|
||||||
|
] as const;
|
||||||
|
|
||||||
export const CONTENT_TYPES_FILE = 'types.d.ts';
|
export const CONTENT_TYPES_FILE = 'types.d.ts';
|
||||||
|
|
|
@ -270,62 +270,82 @@ async function render({
|
||||||
const baseMod = await renderEntryImport();
|
const baseMod = await renderEntryImport();
|
||||||
if (baseMod == null || typeof baseMod !== 'object') throw UnexpectedRenderError;
|
if (baseMod == null || typeof baseMod !== 'object') throw UnexpectedRenderError;
|
||||||
|
|
||||||
const { collectedStyles, collectedLinks, collectedScripts, getMod } = baseMod;
|
if (
|
||||||
if (typeof getMod !== 'function') throw UnexpectedRenderError;
|
baseMod.default != null &&
|
||||||
const mod = await getMod();
|
typeof baseMod.default === 'object' &&
|
||||||
if (mod == null || typeof mod !== 'object') throw UnexpectedRenderError;
|
baseMod.default.__astroPropagation === true
|
||||||
|
) {
|
||||||
|
const { collectedStyles, collectedLinks, collectedScripts, getMod } = baseMod.default;
|
||||||
|
if (typeof getMod !== 'function') throw UnexpectedRenderError;
|
||||||
|
const propagationMod = await getMod();
|
||||||
|
if (propagationMod == null || typeof propagationMod !== 'object') throw UnexpectedRenderError;
|
||||||
|
|
||||||
const Content = createComponent({
|
const Content = createComponent({
|
||||||
factory(result, baseProps, slots) {
|
factory(result, baseProps, slots) {
|
||||||
let styles = '',
|
let styles = '',
|
||||||
links = '',
|
links = '',
|
||||||
scripts = '';
|
scripts = '';
|
||||||
if (Array.isArray(collectedStyles)) {
|
if (Array.isArray(collectedStyles)) {
|
||||||
styles = collectedStyles
|
styles = collectedStyles
|
||||||
.map((style: any) => {
|
.map((style: any) => {
|
||||||
return renderUniqueStylesheet(result, {
|
return renderUniqueStylesheet(result, {
|
||||||
type: 'inline',
|
type: 'inline',
|
||||||
content: style,
|
content: style,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.join('');
|
.join('');
|
||||||
}
|
}
|
||||||
if (Array.isArray(collectedLinks)) {
|
if (Array.isArray(collectedLinks)) {
|
||||||
links = collectedLinks
|
links = collectedLinks
|
||||||
.map((link: any) => {
|
.map((link: any) => {
|
||||||
return renderUniqueStylesheet(result, {
|
return renderUniqueStylesheet(result, {
|
||||||
type: 'external',
|
type: 'external',
|
||||||
src: prependForwardSlash(link),
|
src: prependForwardSlash(link),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.join('');
|
.join('');
|
||||||
}
|
}
|
||||||
if (Array.isArray(collectedScripts)) {
|
if (Array.isArray(collectedScripts)) {
|
||||||
scripts = collectedScripts.map((script: any) => renderScriptElement(script)).join('');
|
scripts = collectedScripts.map((script: any) => renderScriptElement(script)).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
let props = baseProps;
|
let props = baseProps;
|
||||||
// Auto-apply MDX components export
|
// Auto-apply MDX components export
|
||||||
if (id.endsWith('mdx')) {
|
if (id.endsWith('mdx')) {
|
||||||
props = {
|
props = {
|
||||||
components: mod.components ?? {},
|
components: propagationMod.components ?? {},
|
||||||
...baseProps,
|
...baseProps,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return createHeadAndContent(
|
return createHeadAndContent(
|
||||||
unescapeHTML(styles + links + scripts) as any,
|
unescapeHTML(styles + links + scripts) as any,
|
||||||
renderTemplate`${renderComponent(result, 'Content', mod.Content, props, slots)}`
|
renderTemplate`${renderComponent(
|
||||||
);
|
result,
|
||||||
},
|
'Content',
|
||||||
propagation: 'self',
|
propagationMod.Content,
|
||||||
});
|
props,
|
||||||
|
slots
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
propagation: 'self',
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Content,
|
Content,
|
||||||
headings: mod.getHeadings?.() ?? [],
|
headings: propagationMod.getHeadings?.() ?? [],
|
||||||
remarkPluginFrontmatter: mod.frontmatter ?? {},
|
remarkPluginFrontmatter: propagationMod.frontmatter ?? {},
|
||||||
};
|
};
|
||||||
|
} else if (baseMod.Content && typeof baseMod.Content === 'function') {
|
||||||
|
return {
|
||||||
|
Content: baseMod.Content,
|
||||||
|
headings: baseMod.getHeadings?.() ?? [],
|
||||||
|
remarkPluginFrontmatter: baseMod.frontmatter ?? {},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw UnexpectedRenderError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createReference({ lookupMap }: { lookupMap: ContentLookupMap }) {
|
export function createReference({ lookupMap }: { lookupMap: ContentLookupMap }) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ function createGlobLookup(glob) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderEntryGlob = import.meta.glob('@@RENDER_ENTRY_GLOB_PATH@@', {
|
const renderEntryGlob = import.meta.glob('@@RENDER_ENTRY_GLOB_PATH@@', {
|
||||||
query: { astroPropagatedAssets: true },
|
query: { astroRenderContent: true },
|
||||||
});
|
});
|
||||||
const collectionToRenderEntryMap = createCollectionToGlobResultMap({
|
const collectionToRenderEntryMap = createCollectionToGlobResultMap({
|
||||||
globResult: renderEntryGlob,
|
globResult: renderEntryGlob,
|
||||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
||||||
} from '../@types/astro.js';
|
} from '../@types/astro.js';
|
||||||
import { VALID_INPUT_FORMATS } from '../assets/consts.js';
|
import { VALID_INPUT_FORMATS } from '../assets/consts.js';
|
||||||
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||||
|
|
||||||
import { formatYAMLException, isYAMLException } from '../core/errors/utils.js';
|
import { formatYAMLException, isYAMLException } from '../core/errors/utils.js';
|
||||||
import { CONTENT_FLAGS, CONTENT_TYPES_FILE } from './consts.js';
|
import { CONTENT_FLAGS, CONTENT_TYPES_FILE } from './consts.js';
|
||||||
import { errorMap } from './error-map.js';
|
import { errorMap } from './error-map.js';
|
||||||
|
@ -328,7 +329,7 @@ export function parseFrontmatter(fileContents: string, filePath: string) {
|
||||||
*/
|
*/
|
||||||
export const globalContentConfigObserver = contentObservable({ status: 'init' });
|
export const globalContentConfigObserver = contentObservable({ status: 'init' });
|
||||||
|
|
||||||
export function hasContentFlag(viteId: string, flag: (typeof CONTENT_FLAGS)[number]) {
|
export function hasContentFlag(viteId: string, flag: (typeof CONTENT_FLAGS)[number]): boolean {
|
||||||
const flags = new URLSearchParams(viteId.split('?')[1] ?? '');
|
const flags = new URLSearchParams(viteId.split('?')[1] ?? '');
|
||||||
return flags.has(flag);
|
return flags.has(flag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { pathToFileURL } from 'url';
|
import { extname } from 'node:path';
|
||||||
|
import { pathToFileURL } from 'node:url';
|
||||||
import type { Plugin } from 'vite';
|
import type { Plugin } from 'vite';
|
||||||
import type { AstroSettings } from '../@types/astro.js';
|
import type { AstroSettings } from '../@types/astro.js';
|
||||||
import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js';
|
import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js';
|
||||||
|
@ -11,16 +12,13 @@ import { joinPaths, prependForwardSlash } from '../core/path.js';
|
||||||
import { getStylesForURL } from '../core/render/dev/css.js';
|
import { getStylesForURL } from '../core/render/dev/css.js';
|
||||||
import { getScriptsForURL } from '../core/render/dev/scripts.js';
|
import { getScriptsForURL } from '../core/render/dev/scripts.js';
|
||||||
import {
|
import {
|
||||||
|
CONTENT_RENDER_FLAG,
|
||||||
LINKS_PLACEHOLDER,
|
LINKS_PLACEHOLDER,
|
||||||
PROPAGATED_ASSET_FLAG,
|
PROPAGATED_ASSET_FLAG,
|
||||||
SCRIPTS_PLACEHOLDER,
|
SCRIPTS_PLACEHOLDER,
|
||||||
STYLES_PLACEHOLDER,
|
STYLES_PLACEHOLDER,
|
||||||
} from './consts.js';
|
} from './consts.js';
|
||||||
|
import { hasContentFlag } from './utils.js';
|
||||||
function isPropagatedAsset(viteId: string) {
|
|
||||||
const flags = new URLSearchParams(viteId.split('?')[1]);
|
|
||||||
return flags.has(PROPAGATED_ASSET_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function astroContentAssetPropagationPlugin({
|
export function astroContentAssetPropagationPlugin({
|
||||||
mode,
|
mode,
|
||||||
|
@ -32,13 +30,31 @@ export function astroContentAssetPropagationPlugin({
|
||||||
let devModuleLoader: ModuleLoader;
|
let devModuleLoader: ModuleLoader;
|
||||||
return {
|
return {
|
||||||
name: 'astro:content-asset-propagation',
|
name: 'astro:content-asset-propagation',
|
||||||
|
enforce: 'pre',
|
||||||
|
async resolveId(id, importer, opts) {
|
||||||
|
if (hasContentFlag(id, CONTENT_RENDER_FLAG)) {
|
||||||
|
const base = id.split('?')[0];
|
||||||
|
|
||||||
|
for (const { extensions, handlePropagation = true } of settings.contentEntryTypes) {
|
||||||
|
if (handlePropagation && extensions.includes(extname(base))) {
|
||||||
|
return this.resolve(`${base}?${PROPAGATED_ASSET_FLAG}`, importer, {
|
||||||
|
skipSelf: true,
|
||||||
|
...opts,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Resolve to the base id (no content flags)
|
||||||
|
// if Astro doesn't need to handle propagation.
|
||||||
|
return this.resolve(base, importer, { skipSelf: true, ...opts });
|
||||||
|
}
|
||||||
|
},
|
||||||
configureServer(server) {
|
configureServer(server) {
|
||||||
if (mode === 'dev') {
|
if (mode === 'dev') {
|
||||||
devModuleLoader = createViteLoader(server);
|
devModuleLoader = createViteLoader(server);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async transform(_, id, options) {
|
async transform(_, id, options) {
|
||||||
if (isPropagatedAsset(id)) {
|
if (hasContentFlag(id, PROPAGATED_ASSET_FLAG)) {
|
||||||
const basePath = id.split('?')[0];
|
const basePath = id.split('?')[0];
|
||||||
let stringifiedLinks: string, stringifiedStyles: string, stringifiedScripts: string;
|
let stringifiedLinks: string, stringifiedStyles: string, stringifiedScripts: string;
|
||||||
|
|
||||||
|
@ -73,14 +89,17 @@ export function astroContentAssetPropagationPlugin({
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = `
|
const code = `
|
||||||
export async function getMod() {
|
async function getMod() {
|
||||||
return import(${JSON.stringify(basePath)});
|
return import(${JSON.stringify(basePath)});
|
||||||
}
|
}
|
||||||
export const collectedLinks = ${stringifiedLinks};
|
const collectedLinks = ${stringifiedLinks};
|
||||||
export const collectedStyles = ${stringifiedStyles};
|
const collectedStyles = ${stringifiedStyles};
|
||||||
export const collectedScripts = ${stringifiedScripts};
|
const collectedScripts = ${stringifiedScripts};
|
||||||
|
const defaultMod = { __astroPropagation: true, getMod, collectedLinks, collectedStyles, collectedScripts };
|
||||||
|
export default defaultMod;
|
||||||
`;
|
`;
|
||||||
|
// ^ Use a default export for tools like Markdoc
|
||||||
|
// to catch the `__astroPropagation` identifier
|
||||||
return { code, map: { mappings: '' } };
|
return { code, map: { mappings: '' } };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -144,19 +144,19 @@ export class App {
|
||||||
if (routeData.type === 'page') {
|
if (routeData.type === 'page') {
|
||||||
let response = await this.#renderPage(request, routeData, mod, defaultStatus);
|
let response = await this.#renderPage(request, routeData, mod, defaultStatus);
|
||||||
|
|
||||||
// If there was a 500 error, try sending the 500 page.
|
// If there was a known error code, try sending the according page (e.g. 404.astro / 500.astro).
|
||||||
if (response.status === 500) {
|
if (response.status === 500 || response.status === 404) {
|
||||||
const fiveHundredRouteData = matchRoute('/500', this.#manifestData);
|
const errorPageData = matchRoute('/' + response.status, this.#manifestData);
|
||||||
if (fiveHundredRouteData) {
|
if (errorPageData && errorPageData.route !== routeData.route) {
|
||||||
mod = await this.#manifest.pageMap.get(fiveHundredRouteData.component)!();
|
mod = await this.#manifest.pageMap.get(errorPageData.component)!();
|
||||||
try {
|
try {
|
||||||
let fiveHundredResponse = await this.#renderPage(
|
let errorResponse = await this.#renderPage(
|
||||||
request,
|
request,
|
||||||
fiveHundredRouteData,
|
errorPageData,
|
||||||
mod,
|
mod,
|
||||||
500
|
response.status
|
||||||
);
|
);
|
||||||
return fiveHundredResponse;
|
return errorResponse;
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import type { ModuleLoader, ModuleNode } from '../../module-loader/index';
|
import type { ModuleLoader, ModuleNode } from '../../module-loader/index';
|
||||||
|
|
||||||
import npath from 'path';
|
import npath from 'path';
|
||||||
import { PROPAGATED_ASSET_FLAG } from '../../../content/consts.js';
|
|
||||||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js';
|
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js';
|
||||||
import { unwrapId } from '../../util.js';
|
import { unwrapId } from '../../util.js';
|
||||||
import { isCSSRequest } from './util.js';
|
import { isCSSRequest } from './util.js';
|
||||||
|
@ -10,9 +9,10 @@ import { isCSSRequest } from './util.js';
|
||||||
* List of file extensions signalling we can (and should) SSR ahead-of-time
|
* List of file extensions signalling we can (and should) SSR ahead-of-time
|
||||||
* See usage below
|
* See usage below
|
||||||
*/
|
*/
|
||||||
const fileExtensionsToSSR = new Set(['.astro', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS]);
|
const fileExtensionsToSSR = new Set(['.astro', '.mdoc', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS]);
|
||||||
|
|
||||||
const STRIP_QUERY_PARAMS_REGEX = /\?.*$/;
|
const STRIP_QUERY_PARAMS_REGEX = /\?.*$/;
|
||||||
|
const ASTRO_PROPAGATED_ASSET_REGEX = /\?astroPropagatedAssets/;
|
||||||
|
|
||||||
/** recursively crawl the module graph to get all style files imported by parent id */
|
/** recursively crawl the module graph to get all style files imported by parent id */
|
||||||
export async function* crawlGraph(
|
export async function* crawlGraph(
|
||||||
|
@ -23,7 +23,6 @@ export async function* crawlGraph(
|
||||||
): AsyncGenerator<ModuleNode, void, unknown> {
|
): AsyncGenerator<ModuleNode, void, unknown> {
|
||||||
const id = unwrapId(_id);
|
const id = unwrapId(_id);
|
||||||
const importedModules = new Set<ModuleNode>();
|
const importedModules = new Set<ModuleNode>();
|
||||||
if (new URL(id, 'file://').searchParams.has(PROPAGATED_ASSET_FLAG)) return;
|
|
||||||
|
|
||||||
const moduleEntriesForId = isRootFile
|
const moduleEntriesForId = isRootFile
|
||||||
? // "getModulesByFile" pulls from a delayed module cache (fun implementation detail),
|
? // "getModulesByFile" pulls from a delayed module cache (fun implementation detail),
|
||||||
|
@ -44,6 +43,7 @@ export async function* crawlGraph(
|
||||||
if (id === entry.id) {
|
if (id === entry.id) {
|
||||||
scanned.add(id);
|
scanned.add(id);
|
||||||
const entryIsStyle = isCSSRequest(id);
|
const entryIsStyle = isCSSRequest(id);
|
||||||
|
|
||||||
for (const importedModule of entry.importedModules) {
|
for (const importedModule of entry.importedModules) {
|
||||||
// some dynamically imported modules are *not* server rendered in time
|
// some dynamically imported modules are *not* server rendered in time
|
||||||
// to only SSR modules that we can safely transform, we check against
|
// to only SSR modules that we can safely transform, we check against
|
||||||
|
@ -60,15 +60,13 @@ export async function* crawlGraph(
|
||||||
if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
|
if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const isFileTypeNeedingSSR = fileExtensionsToSSR.has(
|
||||||
|
npath.extname(importedModulePathname)
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
fileExtensionsToSSR.has(
|
isFileTypeNeedingSSR &&
|
||||||
npath.extname(
|
// Should not SSR a module with ?astroPropagatedAssets
|
||||||
// Use `id` instead of `pathname` to preserve query params.
|
!ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id)
|
||||||
// Should not SSR a module with an unexpected query param,
|
|
||||||
// like "?astroPropagatedAssets"
|
|
||||||
importedModule.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
const mod = loader.getModuleById(importedModule.id);
|
const mod = loader.getModuleById(importedModule.id);
|
||||||
if (!mod?.ssrModule) {
|
if (!mod?.ssrModule) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function defineScriptVars(vars: Record<any, any>) {
|
||||||
for (const [key, value] of Object.entries(vars)) {
|
for (const [key, value] of Object.entries(vars)) {
|
||||||
// Use const instead of let as let global unsupported with Safari
|
// Use const instead of let as let global unsupported with Safari
|
||||||
// https://stackoverflow.com/questions/29194024/cant-use-let-keyword-in-safari-javascript
|
// https://stackoverflow.com/questions/29194024/cant-use-let-keyword-in-safari-javascript
|
||||||
output += `const ${toIdent(key)} = ${JSON.stringify(value).replace(
|
output += `const ${toIdent(key)} = ${JSON.stringify(value)?.replace(
|
||||||
/<\/script>/g,
|
/<\/script>/g,
|
||||||
'\\x3C/script>'
|
'\\x3C/script>'
|
||||||
)};\n`;
|
)};\n`;
|
||||||
|
|
|
@ -9,7 +9,8 @@ import { getTopLevelPages, walkParentInfos } from '../core/build/graph.js';
|
||||||
import type { BuildInternals } from '../core/build/internal.js';
|
import type { BuildInternals } from '../core/build/internal.js';
|
||||||
import { getAstroMetadata } from '../vite-plugin-astro/index.js';
|
import { getAstroMetadata } from '../vite-plugin-astro/index.js';
|
||||||
|
|
||||||
const injectExp = /^\/\/\s*astro-head-inject/;
|
// Detect this in comments, both in .astro components and in js/ts files.
|
||||||
|
const injectExp = /(^\/\/|\/\/!)\s*astro-head-inject/;
|
||||||
|
|
||||||
export default function configHeadVitePlugin({
|
export default function configHeadVitePlugin({
|
||||||
settings,
|
settings,
|
||||||
|
@ -32,6 +33,7 @@ export default function configHeadVitePlugin({
|
||||||
seen.add(id);
|
seen.add(id);
|
||||||
const mod = server.moduleGraph.getModuleById(id);
|
const mod = server.moduleGraph.getModuleById(id);
|
||||||
const info = this.getModuleInfo(id);
|
const info = this.getModuleInfo(id);
|
||||||
|
|
||||||
if (info?.meta.astro) {
|
if (info?.meta.astro) {
|
||||||
const astroMetadata = getAstroMetadata(info);
|
const astroMetadata = getAstroMetadata(info);
|
||||||
if (astroMetadata) {
|
if (astroMetadata) {
|
||||||
|
|
|
@ -13,6 +13,8 @@ export const markdownContentEntryType: ContentEntryType = {
|
||||||
rawData: parsed.matter,
|
rawData: parsed.matter,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
// We need to handle propagation for Markdown because they support layouts which will bring in styles.
|
||||||
|
handlePropagation: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +32,9 @@ export const mdxContentEntryType: ContentEntryType = {
|
||||||
rawData: parsed.matter,
|
rawData: parsed.matter,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
// MDX can import scripts and styles,
|
||||||
|
// so wrap all MDX files with script / style propagation checks
|
||||||
|
handlePropagation: true,
|
||||||
contentModuleTypes: `declare module 'astro:content' {
|
contentModuleTypes: `declare module 'astro:content' {
|
||||||
interface Render {
|
interface Render {
|
||||||
'.mdx': Promise<{
|
'.mdx': Promise<{
|
||||||
|
|
|
@ -14,7 +14,7 @@ describe('Directives', async () => {
|
||||||
const html = await fixture.readFile('/define-vars/index.html');
|
const html = await fixture.readFile('/define-vars/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
||||||
expect($('script')).to.have.lengthOf(4);
|
expect($('script')).to.have.lengthOf(5);
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (const script of $('script').toArray()) {
|
for (const script of $('script').toArray()) {
|
||||||
|
@ -27,9 +27,12 @@ describe('Directives', async () => {
|
||||||
} else if (i < 3) {
|
} else if (i < 3) {
|
||||||
// Convert invalid keys to valid identifiers
|
// Convert invalid keys to valid identifiers
|
||||||
expect($(script).toString()).to.include('const dashCase = "bar"');
|
expect($(script).toString()).to.include('const dashCase = "bar"');
|
||||||
} else {
|
} else if (i < 4) {
|
||||||
// Closing script tags in strings are escaped
|
// Closing script tags in strings are escaped
|
||||||
expect($(script).toString()).to.include('const bar = "<script>bar\\x3C/script>"');
|
expect($(script).toString()).to.include('const bar = "<script>bar\\x3C/script>"');
|
||||||
|
} else {
|
||||||
|
// Vars with undefined values are handled
|
||||||
|
expect($(script).toString()).to.include('const undef = undefined');
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ let foo = 'bar'
|
||||||
let bg = 'white'
|
let bg = 'white'
|
||||||
let fg = 'black'
|
let fg = 'black'
|
||||||
let bar = '<script>bar</script>'
|
let bar = '<script>bar</script>'
|
||||||
|
let undef: undefined;
|
||||||
---
|
---
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
@ -32,6 +33,9 @@ let bar = '<script>bar</script>'
|
||||||
<script id="inline-4" define:vars={{ bar }}>
|
<script id="inline-4" define:vars={{ bar }}>
|
||||||
console.log(bar);
|
console.log(bar);
|
||||||
</script>
|
</script>
|
||||||
|
<script id="inline-5" define:vars={{ undef }}>
|
||||||
|
console.log(undef);
|
||||||
|
</script>
|
||||||
|
|
||||||
<Title />
|
<Title />
|
||||||
</body>
|
</body>
|
||||||
|
|
6
packages/astro/test/fixtures/ssr-api-route-custom-404/src/pages/causes-404.astro
vendored
Normal file
6
packages/astro/test/fixtures/ssr-api-route-custom-404/src/pages/causes-404.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
return new Response(null, {
|
||||||
|
status: 404,
|
||||||
|
statusText: 'Not found',
|
||||||
|
});
|
||||||
|
---
|
|
@ -62,6 +62,16 @@ describe('404 and 500 pages', () => {
|
||||||
expect($('h1').text()).to.equal('Something went horribly wrong!');
|
expect($('h1').text()).to.equal('Something went horribly wrong!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('404 page returned when there is an 404 response returned from route', async () => {
|
||||||
|
const app = await fixture.loadTestAdapterApp();
|
||||||
|
const request = new Request('http://example.com/causes-404');
|
||||||
|
const response = await app.render(request);
|
||||||
|
expect(response.status).to.equal(404);
|
||||||
|
const html = await response.text();
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
expect($('h1').text()).to.equal('Something went horribly wrong!');
|
||||||
|
});
|
||||||
|
|
||||||
it('500 page returned when there is an error', async () => {
|
it('500 page returned when there is an error', async () => {
|
||||||
const app = await fixture.loadTestAdapterApp();
|
const app = await fixture.loadTestAdapterApp();
|
||||||
const request = new Request('http://example.com/causes-error');
|
const request = new Request('http://example.com/causes-error');
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
"tiny-glob": "^0.2.9"
|
"tiny-glob": "^0.2.9"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2"
|
"astro": "workspace:^2.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "workspace:*",
|
"astro": "workspace:*",
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
"esbuild": "^0.15.18"
|
"esbuild": "^0.15.18"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2"
|
"astro": "workspace:^2.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "workspace:*",
|
"astro": "workspace:*",
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
"vite": "^4.3.1"
|
"vite": "^4.3.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2",
|
"astro": "workspace:^2.5.3",
|
||||||
"sharp": ">=0.31.0"
|
"sharp": ">=0.31.0"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
# @astrojs/markdoc
|
# @astrojs/markdoc
|
||||||
|
|
||||||
|
## 0.2.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#6758](https://github.com/withastro/astro/pull/6758) [`f558a9e20`](https://github.com/withastro/astro/commit/f558a9e2056fc8f2e2d5814e74f199e398159fc4) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Improve style and script handling across content collection files. This addresses style bleed present in `@astrojs/markdoc` v0.1.0
|
||||||
|
|
||||||
|
- Updated dependencies [[`f558a9e20`](https://github.com/withastro/astro/commit/f558a9e2056fc8f2e2d5814e74f199e398159fc4), [`b41963b77`](https://github.com/withastro/astro/commit/b41963b775149b802eea9e12c5fe266bb9a02944)]:
|
||||||
|
- astro@2.5.3
|
||||||
|
|
||||||
## 0.2.1
|
## 0.2.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
//! astro-head-inject
|
||||||
import type { Config } from '@markdoc/markdoc';
|
import type { Config } from '@markdoc/markdoc';
|
||||||
import Markdoc from '@markdoc/markdoc';
|
import Markdoc from '@markdoc/markdoc';
|
||||||
import { ComponentNode, createTreeNode } from './TreeNode.js';
|
import { ComponentNode, createTreeNode } from './TreeNode.js';
|
||||||
|
@ -14,4 +15,4 @@ const ast = Markdoc.Ast.fromJSON(stringifiedAst);
|
||||||
const content = Markdoc.transform(ast, config);
|
const content = Markdoc.transform(ast, config);
|
||||||
---
|
---
|
||||||
|
|
||||||
<ComponentNode treeNode={createTreeNode(content)} />
|
<ComponentNode treeNode={await createTreeNode(content)} />
|
||||||
|
|
|
@ -2,7 +2,16 @@ import type { AstroInstance } from 'astro';
|
||||||
import { Fragment } from 'astro/jsx-runtime';
|
import { Fragment } from 'astro/jsx-runtime';
|
||||||
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
||||||
import Markdoc from '@markdoc/markdoc';
|
import Markdoc from '@markdoc/markdoc';
|
||||||
import { createComponent, renderComponent, render } from 'astro/runtime/server/index.js';
|
import {
|
||||||
|
createComponent,
|
||||||
|
renderComponent,
|
||||||
|
render,
|
||||||
|
renderScriptElement,
|
||||||
|
renderUniqueStylesheet,
|
||||||
|
createHeadAndContent,
|
||||||
|
unescapeHTML,
|
||||||
|
renderTemplate,
|
||||||
|
} from 'astro/runtime/server/index.js';
|
||||||
|
|
||||||
export type TreeNode =
|
export type TreeNode =
|
||||||
| {
|
| {
|
||||||
|
@ -12,6 +21,9 @@ export type TreeNode =
|
||||||
| {
|
| {
|
||||||
type: 'component';
|
type: 'component';
|
||||||
component: AstroInstance['default'];
|
component: AstroInstance['default'];
|
||||||
|
collectedLinks?: string[];
|
||||||
|
collectedStyles?: string[];
|
||||||
|
collectedScripts?: string[];
|
||||||
props: Record<string, any>;
|
props: Record<string, any>;
|
||||||
children: TreeNode[];
|
children: TreeNode[];
|
||||||
}
|
}
|
||||||
|
@ -32,20 +44,67 @@ export const ComponentNode = createComponent({
|
||||||
)}`,
|
)}`,
|
||||||
};
|
};
|
||||||
if (treeNode.type === 'component') {
|
if (treeNode.type === 'component') {
|
||||||
return renderComponent(
|
let styles = '',
|
||||||
result,
|
links = '',
|
||||||
treeNode.component.name,
|
scripts = '';
|
||||||
treeNode.component,
|
if (Array.isArray(treeNode.collectedStyles)) {
|
||||||
treeNode.props,
|
styles = treeNode.collectedStyles
|
||||||
slots
|
.map((style: any) =>
|
||||||
|
renderUniqueStylesheet({
|
||||||
|
type: 'inline',
|
||||||
|
content: style,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
if (Array.isArray(treeNode.collectedLinks)) {
|
||||||
|
links = treeNode.collectedLinks
|
||||||
|
.map((link: any) => {
|
||||||
|
return renderUniqueStylesheet(result, {
|
||||||
|
href: link[0] === '/' ? link : '/' + link,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
if (Array.isArray(treeNode.collectedScripts)) {
|
||||||
|
scripts = treeNode.collectedScripts
|
||||||
|
.map((script: any) => renderScriptElement(script))
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
const head = unescapeHTML(styles + links + scripts);
|
||||||
|
|
||||||
|
let headAndContent = createHeadAndContent(
|
||||||
|
head,
|
||||||
|
renderTemplate`${renderComponent(
|
||||||
|
result,
|
||||||
|
treeNode.component.name,
|
||||||
|
treeNode.component,
|
||||||
|
treeNode.props,
|
||||||
|
slots
|
||||||
|
)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Let the runtime know that this component is being used.
|
||||||
|
result.propagators.set(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
init() {
|
||||||
|
return headAndContent;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return headAndContent;
|
||||||
}
|
}
|
||||||
return renderComponent(result, treeNode.tag, treeNode.tag, treeNode.attributes, slots);
|
return renderComponent(result, treeNode.tag, treeNode.tag, treeNode.attributes, slots);
|
||||||
},
|
},
|
||||||
propagation: 'none',
|
propagation: 'self',
|
||||||
});
|
});
|
||||||
|
|
||||||
export function createTreeNode(node: RenderableTreeNode | RenderableTreeNode[]): TreeNode {
|
export async function createTreeNode(
|
||||||
|
node: RenderableTreeNode | RenderableTreeNode[]
|
||||||
|
): Promise<TreeNode> {
|
||||||
if (typeof node === 'string' || typeof node === 'number') {
|
if (typeof node === 'string' || typeof node === 'number') {
|
||||||
return { type: 'text', content: String(node) };
|
return { type: 'text', content: String(node) };
|
||||||
} else if (Array.isArray(node)) {
|
} else if (Array.isArray(node)) {
|
||||||
|
@ -53,16 +112,17 @@ export function createTreeNode(node: RenderableTreeNode | RenderableTreeNode[]):
|
||||||
type: 'component',
|
type: 'component',
|
||||||
component: Fragment,
|
component: Fragment,
|
||||||
props: {},
|
props: {},
|
||||||
children: node.map((child) => createTreeNode(child)),
|
children: await Promise.all(node.map((child) => createTreeNode(child))),
|
||||||
};
|
};
|
||||||
} else if (node === null || typeof node !== 'object' || !Markdoc.Tag.isTag(node)) {
|
} else if (node === null || typeof node !== 'object' || !Markdoc.Tag.isTag(node)) {
|
||||||
return { type: 'text', content: '' };
|
return { type: 'text', content: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const children = await Promise.all(node.children.map((child) => createTreeNode(child)));
|
||||||
|
|
||||||
if (typeof node.name === 'function') {
|
if (typeof node.name === 'function') {
|
||||||
const component = node.name;
|
const component = node.name;
|
||||||
const props = node.attributes;
|
const props = node.attributes;
|
||||||
const children = node.children.map((child) => createTreeNode(child));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'component',
|
type: 'component',
|
||||||
|
@ -70,12 +130,38 @@ export function createTreeNode(node: RenderableTreeNode | RenderableTreeNode[]):
|
||||||
props,
|
props,
|
||||||
children,
|
children,
|
||||||
};
|
};
|
||||||
|
} else if (isPropagatedAssetsModule(node.name)) {
|
||||||
|
const { collectedStyles, collectedLinks, collectedScripts } = node.name;
|
||||||
|
const component = (await node.name.getMod())?.default ?? Fragment;
|
||||||
|
const props = node.attributes;
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'component',
|
||||||
|
component,
|
||||||
|
collectedStyles,
|
||||||
|
collectedLinks,
|
||||||
|
collectedScripts,
|
||||||
|
props,
|
||||||
|
children,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
type: 'element',
|
type: 'element',
|
||||||
tag: node.name,
|
tag: node.name,
|
||||||
attributes: node.attributes,
|
attributes: node.attributes,
|
||||||
children: node.children.map((child) => createTreeNode(child)),
|
children,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PropagatedAssetsModule = {
|
||||||
|
__astroPropagation: true;
|
||||||
|
getMod: () => Promise<AstroInstance['default']>;
|
||||||
|
collectedStyles: string[];
|
||||||
|
collectedLinks: string[];
|
||||||
|
collectedScripts: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function isPropagatedAssetsModule(module: any): module is PropagatedAssetsModule {
|
||||||
|
return typeof module === 'object' && module != null && '__astroPropagation' in module;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@astrojs/markdoc",
|
"name": "@astrojs/markdoc",
|
||||||
"description": "Add support for Markdoc pages in your Astro site",
|
"description": "Add support for Markdoc pages in your Astro site",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"author": "withastro",
|
"author": "withastro",
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
"zod": "^3.17.3"
|
"zod": "^3.17.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2"
|
"astro": "workspace:^2.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/markdown-remark": "^2.2.1",
|
"@astrojs/markdown-remark": "^2.2.1",
|
||||||
|
|
|
@ -32,7 +32,11 @@ export default function markdocIntegration(legacyConfig?: any): AstroIntegration
|
||||||
name: '@astrojs/markdoc',
|
name: '@astrojs/markdoc',
|
||||||
hooks: {
|
hooks: {
|
||||||
'astro:config:setup': async (params) => {
|
'astro:config:setup': async (params) => {
|
||||||
const { config: astroConfig, addContentEntryType } = params as SetupHookParams;
|
const {
|
||||||
|
config: astroConfig,
|
||||||
|
updateConfig,
|
||||||
|
addContentEntryType,
|
||||||
|
} = params as SetupHookParams;
|
||||||
|
|
||||||
markdocConfigResult = await loadMarkdocConfig(astroConfig);
|
markdocConfigResult = await loadMarkdocConfig(astroConfig);
|
||||||
const userMarkdocConfig = markdocConfigResult?.config ?? {};
|
const userMarkdocConfig = markdocConfigResult?.config ?? {};
|
||||||
|
@ -49,6 +53,9 @@ export default function markdocIntegration(legacyConfig?: any): AstroIntegration
|
||||||
addContentEntryType({
|
addContentEntryType({
|
||||||
extensions: ['.mdoc'],
|
extensions: ['.mdoc'],
|
||||||
getEntryInfo,
|
getEntryInfo,
|
||||||
|
// Markdoc handles script / style propagation
|
||||||
|
// for Astro components internally
|
||||||
|
handlePropagation: false,
|
||||||
async getRenderModule({ entry, viteId }) {
|
async getRenderModule({ entry, viteId }) {
|
||||||
const ast = Markdoc.parse(entry.body);
|
const ast = Markdoc.parse(entry.body);
|
||||||
const pluginContext = this;
|
const pluginContext = this;
|
||||||
|
@ -88,7 +95,10 @@ export default function markdocIntegration(legacyConfig?: any): AstroIntegration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = `import { jsx as h } from 'astro/jsx-runtime';
|
const res = `import {
|
||||||
|
createComponent,
|
||||||
|
renderComponent,
|
||||||
|
} from 'astro/runtime/server/index.js';
|
||||||
import { Renderer } from '@astrojs/markdoc/components';
|
import { Renderer } from '@astrojs/markdoc/components';
|
||||||
import { collectHeadings, setupConfig, Markdoc } from '@astrojs/markdoc/runtime';
|
import { collectHeadings, setupConfig, Markdoc } from '@astrojs/markdoc/runtime';
|
||||||
import * as entry from ${JSON.stringify(viteId + '?astroContentCollectionEntry')};
|
import * as entry from ${JSON.stringify(viteId + '?astroContentCollectionEntry')};
|
||||||
|
@ -119,14 +129,24 @@ export function getHeadings() {
|
||||||
const content = Markdoc.transform(ast, config);
|
const content = Markdoc.transform(ast, config);
|
||||||
return collectHeadings(Array.isArray(content) ? content : content.children);
|
return collectHeadings(Array.isArray(content) ? content : content.children);
|
||||||
}
|
}
|
||||||
export async function Content (props) {
|
|
||||||
const config = setupConfig({
|
|
||||||
...userConfig,
|
|
||||||
variables: { ...userConfig.variables, ...props },
|
|
||||||
}, entry);
|
|
||||||
|
|
||||||
return h(Renderer, { config, stringifiedAst });
|
export const Content = createComponent({
|
||||||
}`;
|
factory(result, props) {
|
||||||
|
const config = setupConfig({
|
||||||
|
...userConfig,
|
||||||
|
variables: { ...userConfig.variables, ...props },
|
||||||
|
}, entry);
|
||||||
|
|
||||||
|
return renderComponent(
|
||||||
|
result,
|
||||||
|
Renderer.name,
|
||||||
|
Renderer,
|
||||||
|
{ stringifiedAst, config },
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
propagation: 'self',
|
||||||
|
});`;
|
||||||
return { code: res };
|
return { code: res };
|
||||||
},
|
},
|
||||||
contentModuleTypes: await fs.promises.readFile(
|
contentModuleTypes: await fs.promises.readFile(
|
||||||
|
@ -134,6 +154,27 @@ export async function Content (props) {
|
||||||
'utf-8'
|
'utf-8'
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateConfig({
|
||||||
|
vite: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: '@astrojs/markdoc:astro-propagated-assets',
|
||||||
|
enforce: 'pre',
|
||||||
|
// Astro component styles and scripts should only be injected
|
||||||
|
// When a given Markdoc file actually uses that component.
|
||||||
|
// Add the `astroPropagatedAssets` flag to inject only when rendered.
|
||||||
|
resolveId(this: rollup.TransformPluginContext, id: string, importer: string) {
|
||||||
|
if (importer === markdocConfigResult?.fileUrl.pathname && id.endsWith('.astro')) {
|
||||||
|
return this.resolve(id + '?astroPropagatedAssets', importer, {
|
||||||
|
skipSelf: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
'astro:server:setup': async ({ server }) => {
|
'astro:server:setup': async ({ server }) => {
|
||||||
server.watcher.on('all', (event, entry) => {
|
server.watcher.on('all', (event, entry) => {
|
||||||
|
|
|
@ -37,13 +37,14 @@ export const heading: Schema = {
|
||||||
const slug = getSlug(attributes, children, config.ctx.headingSlugger);
|
const slug = getSlug(attributes, children, config.ctx.headingSlugger);
|
||||||
|
|
||||||
const render = config.nodes?.heading?.render ?? `h${level}`;
|
const render = config.nodes?.heading?.render ?? `h${level}`;
|
||||||
|
|
||||||
const tagProps =
|
const tagProps =
|
||||||
// For components, pass down `level` as a prop,
|
// For components, pass down `level` as a prop,
|
||||||
// alongside `__collectHeading` for our `headings` collector.
|
// alongside `__collectHeading` for our `headings` collector.
|
||||||
// Avoid accidentally rendering `level` as an HTML attribute otherwise!
|
// Avoid accidentally rendering `level` as an HTML attribute otherwise!
|
||||||
typeof render === 'function'
|
typeof render === 'string'
|
||||||
? { ...attributes, id: slug, __collectHeading: true, level }
|
? { ...attributes, id: slug }
|
||||||
: { ...attributes, id: slug };
|
: { ...attributes, id: slug, __collectHeading: true, level };
|
||||||
|
|
||||||
return new Markdoc.Tag(render, tagProps, children);
|
return new Markdoc.Tag(render, tagProps, children);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
# @astrojs/mdx
|
# @astrojs/mdx
|
||||||
|
|
||||||
|
## 0.19.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#6758](https://github.com/withastro/astro/pull/6758) [`f558a9e20`](https://github.com/withastro/astro/commit/f558a9e2056fc8f2e2d5814e74f199e398159fc4) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Improve style and script handling across content collection files. This addresses style bleed present in `@astrojs/markdoc` v0.1.0
|
||||||
|
|
||||||
## 0.19.2
|
## 0.19.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@astrojs/mdx",
|
"name": "@astrojs/mdx",
|
||||||
"description": "Add support for MDX pages in your Astro site",
|
"description": "Add support for MDX pages in your Astro site",
|
||||||
"version": "0.19.2",
|
"version": "0.19.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"author": "withastro",
|
"author": "withastro",
|
||||||
|
|
|
@ -55,6 +55,9 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
|
||||||
new URL('../template/content-module-types.d.ts', import.meta.url),
|
new URL('../template/content-module-types.d.ts', import.meta.url),
|
||||||
'utf-8'
|
'utf-8'
|
||||||
),
|
),
|
||||||
|
// MDX can import scripts and styles,
|
||||||
|
// so wrap all MDX files with script / style propagation checks
|
||||||
|
handlePropagation: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const extendMarkdownConfig =
|
const extendMarkdownConfig =
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
"esbuild": "^0.15.18"
|
"esbuild": "^0.15.18"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2"
|
"astro": "workspace:^2.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@netlify/edge-functions": "^2.0.0",
|
"@netlify/edge-functions": "^2.0.0",
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
"server-destroy": "^1.0.1"
|
"server-destroy": "^1.0.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2"
|
"astro": "workspace:^2.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/send": "^0.17.1",
|
"@types/send": "^0.17.1",
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
"vite": "^4.3.1"
|
"vite": "^4.3.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2",
|
"astro": "workspace:^2.5.3",
|
||||||
"svelte": "^3.54.0"
|
"svelte": "^3.54.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
"vite": "^4.3.1"
|
"vite": "^4.3.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2",
|
"astro": "workspace:^2.5.3",
|
||||||
"tailwindcss": "^3.0.24"
|
"tailwindcss": "^3.0.24"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
"web-vitals": "^3.1.1"
|
"web-vitals": "^3.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2"
|
"astro": "workspace:^2.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/set-cookie-parser": "^2.4.2",
|
"@types/set-cookie-parser": "^2.4.2",
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"vue": "^3.2.37"
|
"vue": "^3.2.37"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^2.5.2",
|
"astro": "workspace:^2.5.3",
|
||||||
"vue": "^3.2.30"
|
"vue": "^3.2.30"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
Loading…
Reference in a new issue