Compare commits
18 commits
main
...
fork/markd
Author | SHA1 | Date | |
---|---|---|---|
|
b9bf041e5b | ||
|
6b94a279dd | ||
|
40f1c7773e | ||
|
de43b14c98 | ||
|
cf6d447a94 | ||
|
7c2b0ed879 | ||
|
1de946d898 | ||
|
dbef6c49c8 | ||
|
e65cfcc6db | ||
|
381a144dd5 | ||
|
cb2898c13b | ||
|
3fd18dc503 | ||
|
f6ed5da396 | ||
|
9382330a87 | ||
|
b7e337a1da | ||
|
59dbaa95a1 | ||
|
713722cb36 | ||
|
9c6db525a1 |
44 changed files with 1602 additions and 61 deletions
21
examples/with-markdoc/.gitignore
vendored
Normal file
21
examples/with-markdoc/.gitignore
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
4
examples/with-markdoc/.vscode/extensions.json
vendored
Normal file
4
examples/with-markdoc/.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
examples/with-markdoc/.vscode/launch.json
vendored
Normal file
11
examples/with-markdoc/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
46
examples/with-markdoc/README.md
Normal file
46
examples/with-markdoc/README.md
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Astro Starter Kit: Minimal
|
||||
|
||||
```
|
||||
npm create astro@latest -- --template minimal
|
||||
```
|
||||
|
||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)
|
||||
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
/
|
||||
├── public/
|
||||
├── src/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :--------------------- | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
8
examples/with-markdoc/astro.config.mjs
Normal file
8
examples/with-markdoc/astro.config.mjs
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import markdoc from '@astrojs/markdoc';
|
||||
import mdx from '@astrojs/mdx';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [markdoc(), mdx()],
|
||||
});
|
21
examples/with-markdoc/package.json
Normal file
21
examples/with-markdoc/package.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "@example/with-markdoc",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/markdoc": "^0.0.1",
|
||||
"@astrojs/mdx": "^0.16.0",
|
||||
"astro": "^2.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@markdoc/markdoc": "^0.2.2"
|
||||
}
|
||||
}
|
13
examples/with-markdoc/public/favicon.svg
Normal file
13
examples/with-markdoc/public/favicon.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 36 36">
|
||||
<path fill="#000" d="M22.25 4h-8.5a1 1 0 0 0-.96.73l-5.54 19.4a.5.5 0 0 0 .62.62l5.05-1.44a2 2 0 0 0 1.38-1.4l3.22-11.66a.5.5 0 0 1 .96 0l3.22 11.67a2 2 0 0 0 1.38 1.39l5.05 1.44a.5.5 0 0 0 .62-.62l-5.54-19.4a1 1 0 0 0-.96-.73Z"/>
|
||||
<path fill="url(#gradient)" d="M18 28a7.63 7.63 0 0 1-5-2c-1.4 2.1-.35 4.35.6 5.55.14.17.41.07.47-.15.44-1.8 2.93-1.22 2.93.6 0 2.28.87 3.4 1.72 3.81.34.16.59-.2.49-.56-.31-1.05-.29-2.46 1.29-3.25 3-1.5 3.17-4.83 2.5-6-.67.67-2.6 2-5 2Z"/>
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="16" x2="16" y1="32" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#000"/>
|
||||
<stop offset="1" stop-color="#000" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<style>
|
||||
@media (prefers-color-scheme:dark){:root{filter:invert(100%)}}
|
||||
</style>
|
||||
</svg>
|
After Width: | Height: | Size: 873 B |
11
examples/with-markdoc/sandbox.config.json
Normal file
11
examples/with-markdoc/sandbox.config.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"infiniteLoopProtection": true,
|
||||
"hardReloadOnChange": false,
|
||||
"view": "browser",
|
||||
"template": "node",
|
||||
"container": {
|
||||
"port": 3000,
|
||||
"startScript": "start",
|
||||
"node": "14"
|
||||
}
|
||||
}
|
7
examples/with-markdoc/src/components/Marquee.astro
Normal file
7
examples/with-markdoc/src/components/Marquee.astro
Normal file
|
@ -0,0 +1,7 @@
|
|||
<marquee {...Astro.props}><slot /></marquee>
|
||||
|
||||
<style>
|
||||
marquee {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
7
examples/with-markdoc/src/components/RedP.astro
Normal file
7
examples/with-markdoc/src/components/RedP.astro
Normal file
|
@ -0,0 +1,7 @@
|
|||
<p><slot /></p>
|
||||
|
||||
<style>
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
29
examples/with-markdoc/src/components/test.mdoc
Normal file
29
examples/with-markdoc/src/components/test.mdoc
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Hey there
|
||||
|
||||
Look at this table! Built-in to Markdoc, neat.
|
||||
|
||||
{% table %}
|
||||
* Heading 1
|
||||
* Heading 2
|
||||
---
|
||||
* Row 1 Cell 1
|
||||
* Row 1 Cell 2
|
||||
---
|
||||
* Row 2 Cell 1
|
||||
* Row 2 cell 2
|
||||
{% /table %}
|
||||
|
||||
{% if $shouldMarquee %}
|
||||
{% mq direction="right" %}
|
||||
Im a marquee!
|
||||
{% /mq %}
|
||||
{% /if %}
|
||||
|
||||
{% link href=$href %}Link{% /link %}
|
||||
|
||||
```js
|
||||
const testing = true;
|
||||
function further() {
|
||||
console.log('still highlighted!')
|
||||
}
|
||||
```
|
34
examples/with-markdoc/src/content/blog/test.mdoc
Normal file
34
examples/with-markdoc/src/content/blog/test.mdoc
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
title: Example!
|
||||
---
|
||||
|
||||
# Hey there
|
||||
|
||||
Look at this table! Built-in to Markdoc, neat.
|
||||
|
||||
{% table %}
|
||||
* Heading 1
|
||||
* Heading 2
|
||||
---
|
||||
* Row 1 Cell 1
|
||||
* Row 1 Cell 2
|
||||
---
|
||||
* Row 2 Cell 1
|
||||
* Row 2 cell 2
|
||||
{% /table %}
|
||||
|
||||
{% if $shouldMarquee %}
|
||||
{% mq direction="right" %}
|
||||
Im a marquee!
|
||||
{% /mq %}
|
||||
{% /if %}
|
||||
|
||||
{% link href=$href %}Link{% /link %}
|
||||
|
||||
```js
|
||||
const testing = true;
|
||||
function further() {
|
||||
console.log('still highlighted!')
|
||||
}
|
||||
```
|
||||
|
5
examples/with-markdoc/src/content/blog/with-mdx.mdx
Normal file
5
examples/with-markdoc/src/content/blog/with-mdx.mdx
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: 'Example!'
|
||||
---
|
||||
|
||||
# With MDX {frontmatter.title}
|
2
examples/with-markdoc/src/env.d.ts
vendored
Normal file
2
examples/with-markdoc/src/env.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
30
examples/with-markdoc/src/markdoc.config.ts
Normal file
30
examples/with-markdoc/src/markdoc.config.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
export default {
|
||||
transform: {
|
||||
variables: {
|
||||
shouldMarquee: true,
|
||||
href: 'https://astro.build',
|
||||
},
|
||||
tags: {
|
||||
mq: {
|
||||
render: 'marquee',
|
||||
attributes: {
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'left',
|
||||
matches: ['left', 'right', 'up', 'down'],
|
||||
errorLevel: 'critical',
|
||||
},
|
||||
},
|
||||
},
|
||||
link: {
|
||||
render: 'a',
|
||||
attributes: {
|
||||
href: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
45
examples/with-markdoc/src/pages/index.astro
Normal file
45
examples/with-markdoc/src/pages/index.astro
Normal file
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
import { Markdoc } from '@astrojs/markdoc';
|
||||
import { Code } from 'astro/components';
|
||||
import Marquee from '../components/Marquee.astro';
|
||||
import { getEntryBySlug } from 'astro:content';
|
||||
import RedP from '../components/RedP.astro';
|
||||
|
||||
const mdocEntry = await getEntryBySlug('blog', 'test');
|
||||
const mdxEntry = await getEntryBySlug('blog', 'with-mdx');
|
||||
console.log(mdocEntry);
|
||||
const { Content } = await mdocEntry.render();
|
||||
const { Content: MDXContent } = await mdxEntry.render();
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Astro</h1>
|
||||
<article>
|
||||
<MDXContent />
|
||||
<Content
|
||||
components={{
|
||||
marquee: Marquee,
|
||||
p: RedP,
|
||||
pre: {
|
||||
component: Code,
|
||||
props({ attributes, getTreeNode }) {
|
||||
return {
|
||||
...attributes,
|
||||
lang: attributes.lang ?? attributes['data-language'],
|
||||
code: attributes.code ?? Markdoc.renderers.html(getTreeNode().children),
|
||||
};
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
3
examples/with-markdoc/tsconfig.json
Normal file
3
examples/with-markdoc/tsconfig.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/base"
|
||||
}
|
|
@ -977,12 +977,31 @@ export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
|
|||
integrations: AstroIntegration[];
|
||||
}
|
||||
|
||||
export interface ContentEntryParser {
|
||||
getEntryInfo(params: { contents: string; fileUrl: URL }): Promise<{
|
||||
data: Record<string, unknown>;
|
||||
body: string;
|
||||
slug: string;
|
||||
/**
|
||||
* Used for error hints to point to correct line and location
|
||||
* Should be the untouched data as read from the file,
|
||||
* including newlines
|
||||
*/
|
||||
rawData: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface ContentEntryType {
|
||||
extensions: string[];
|
||||
parser: string;
|
||||
}
|
||||
|
||||
export interface AstroSettings {
|
||||
config: AstroConfig;
|
||||
|
||||
adapter: AstroAdapter | undefined;
|
||||
injectedRoutes: InjectedRoute[];
|
||||
pageExtensions: string[];
|
||||
contentEntryTypes: ContentEntryType[];
|
||||
renderers: AstroRenderer[];
|
||||
scripts: {
|
||||
stage: InjectedScriptStage;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export const contentFileExts = ['.md', '.mdx'];
|
||||
export const defaultContentEntryExts = ['.md'] as const;
|
||||
export const PROPAGATED_ASSET_FLAG = 'astroPropagatedAssets';
|
||||
export const CONTENT_FLAG = 'astroContent';
|
||||
export const VIRTUAL_MODULE_ID = 'astro:content';
|
||||
|
|
|
@ -184,7 +184,7 @@ async function render({
|
|||
|
||||
return {
|
||||
Content,
|
||||
headings: mod.getHeadings(),
|
||||
remarkPluginFrontmatter: mod.frontmatter,
|
||||
headings: mod.getHeadings?.() ?? [],
|
||||
remarkPluginFrontmatter: mod.frontmatter ?? {},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
ContentObservable,
|
||||
ContentPaths,
|
||||
EntryInfo,
|
||||
getContentEntryExts,
|
||||
getContentPaths,
|
||||
getEntryInfo,
|
||||
getEntrySlug,
|
||||
|
@ -51,6 +52,7 @@ export async function createContentTypesGenerator({
|
|||
}: CreateContentGeneratorParams) {
|
||||
const contentTypes: ContentTypes = {};
|
||||
const contentPaths = getContentPaths(settings.config);
|
||||
const contentEntryExts = getContentEntryExts(settings);
|
||||
|
||||
let events: Promise<{ shouldGenerateTypes: boolean; error?: Error }>[] = [];
|
||||
let debounceTimeout: NodeJS.Timeout | undefined;
|
||||
|
@ -111,7 +113,7 @@ export async function createContentTypesGenerator({
|
|||
}
|
||||
return { shouldGenerateTypes: true };
|
||||
}
|
||||
const fileType = getEntryType(fileURLToPath(event.entry), contentPaths);
|
||||
const fileType = getEntryType(fileURLToPath(event.entry), contentPaths, contentEntryExts);
|
||||
if (fileType === 'ignored') {
|
||||
return { shouldGenerateTypes: false };
|
||||
}
|
||||
|
@ -273,7 +275,7 @@ async function parseSlug({
|
|||
// on dev server startup or production build init.
|
||||
const rawContents = await fs.promises.readFile(event.entry, 'utf-8');
|
||||
const { data: frontmatter } = parseFrontmatter(rawContents, fileURLToPath(event.entry));
|
||||
return getEntrySlug({ ...entryInfo, data: frontmatter });
|
||||
return getEntrySlug({ ...entryInfo, unvalidatedSlug: frontmatter.slug });
|
||||
}
|
||||
|
||||
function setEntry(
|
||||
|
|
|
@ -5,10 +5,10 @@ import path from 'node:path';
|
|||
import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||
import { ErrorPayload as ViteErrorPayload, normalizePath, ViteDevServer } from 'vite';
|
||||
import { z } from 'zod';
|
||||
import { AstroConfig, AstroSettings } from '../@types/astro.js';
|
||||
import { AstroConfig, AstroSettings, ContentEntryParser } from '../@types/astro.js';
|
||||
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||
import { appendForwardSlash } from '../core/path.js';
|
||||
import { contentFileExts, CONTENT_TYPES_FILE } from './consts.js';
|
||||
import { CONTENT_TYPES_FILE, defaultContentEntryExts } from './consts.js';
|
||||
|
||||
export const collectionConfigParser = z.object({
|
||||
schema: z.any().optional(),
|
||||
|
@ -30,14 +30,7 @@ export const contentConfigParser = z.object({
|
|||
export type CollectionConfig = z.infer<typeof collectionConfigParser>;
|
||||
export type ContentConfig = z.infer<typeof contentConfigParser>;
|
||||
|
||||
type Entry = {
|
||||
id: string;
|
||||
collection: string;
|
||||
slug: string;
|
||||
data: any;
|
||||
body: string;
|
||||
_internal: { rawData: string; filePath: string };
|
||||
};
|
||||
type EntryInternal = { rawData: string; filePath: string };
|
||||
|
||||
export type EntryInfo = {
|
||||
id: string;
|
||||
|
@ -54,10 +47,10 @@ export function getEntrySlug({
|
|||
id,
|
||||
collection,
|
||||
slug,
|
||||
data: unparsedData,
|
||||
}: Pick<Entry, 'id' | 'collection' | 'slug' | 'data'>) {
|
||||
unvalidatedSlug,
|
||||
}: EntryInfo & { unvalidatedSlug?: unknown }) {
|
||||
try {
|
||||
return z.string().default(slug).parse(unparsedData.slug);
|
||||
return z.string().default(slug).parse(unvalidatedSlug);
|
||||
} catch {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.InvalidContentEntrySlugError,
|
||||
|
@ -66,9 +59,12 @@ export function getEntrySlug({
|
|||
}
|
||||
}
|
||||
|
||||
export async function getEntryData(entry: Entry, collectionConfig: CollectionConfig) {
|
||||
export async function getEntryData(
|
||||
entry: EntryInfo & { unvalidatedData: Record<string, unknown>; _internal: EntryInternal },
|
||||
collectionConfig: CollectionConfig
|
||||
) {
|
||||
// Remove reserved `slug` field before parsing data
|
||||
let { slug, ...data } = entry.data;
|
||||
let { slug, ...data } = entry.unvalidatedData;
|
||||
if (collectionConfig.schema) {
|
||||
// TODO: remove for 2.0 stable release
|
||||
if (
|
||||
|
@ -95,7 +91,9 @@ export async function getEntryData(entry: Entry, collectionConfig: CollectionCon
|
|||
});
|
||||
}
|
||||
// Use `safeParseAsync` to allow async transforms
|
||||
const parsed = await collectionConfig.schema.safeParseAsync(entry.data, { errorMap });
|
||||
const parsed = await collectionConfig.schema.safeParseAsync(entry.unvalidatedData, {
|
||||
errorMap,
|
||||
});
|
||||
if (parsed.success) {
|
||||
data = parsed.data;
|
||||
} else {
|
||||
|
@ -121,6 +119,14 @@ export async function getEntryData(entry: Entry, collectionConfig: CollectionCon
|
|||
return data;
|
||||
}
|
||||
|
||||
export function getContentEntryExts(settings: Pick<AstroSettings, 'contentEntryTypes'>) {
|
||||
return [
|
||||
// TODO: roll defaults into settings
|
||||
...defaultContentEntryExts,
|
||||
...settings.contentEntryTypes.map((t) => t.extensions).flat(),
|
||||
];
|
||||
}
|
||||
|
||||
export class NoCollectionError extends Error {}
|
||||
|
||||
export function getEntryInfo(
|
||||
|
@ -161,7 +167,8 @@ export function getEntryInfo({
|
|||
|
||||
export function getEntryType(
|
||||
entryPath: string,
|
||||
paths: Pick<ContentPaths, 'config'>
|
||||
paths: Pick<ContentPaths, 'config'>,
|
||||
contentFileExts: string[]
|
||||
): 'content' | 'config' | 'ignored' | 'unsupported' {
|
||||
const { dir: rawDir, ext, base } = path.parse(entryPath);
|
||||
const dir = appendForwardSlash(pathToFileURL(rawDir).href);
|
||||
|
@ -169,7 +176,7 @@ export function getEntryType(
|
|||
|
||||
if (hasUnderscoreInPath(fileUrl) || isOnIgnoreList(fileUrl)) {
|
||||
return 'ignored';
|
||||
} else if ((contentFileExts as readonly string[]).includes(ext)) {
|
||||
} else if (contentFileExts.includes(ext)) {
|
||||
return 'content';
|
||||
} else if (fileUrl.href === paths.config.href) {
|
||||
return 'config';
|
||||
|
@ -237,6 +244,28 @@ export function parseFrontmatter(fileContents: string, filePath: string) {
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: Will require dev server restart to debug parser changes
|
||||
const contentEntryExtToParserCache = new Map<string, ContentEntryParser>();
|
||||
|
||||
export async function loadContentEntryParsers({
|
||||
settings,
|
||||
}: {
|
||||
settings: Pick<AstroSettings, 'contentEntryTypes'>;
|
||||
}): Promise<Map<string, ContentEntryParser>> {
|
||||
if (contentEntryExtToParserCache.size > 0) return contentEntryExtToParserCache;
|
||||
|
||||
for (const contentEntryType of settings.contentEntryTypes) {
|
||||
for (const extension of contentEntryType.extensions) {
|
||||
// TODO: explore SSR loading strategy if Content Collections processing
|
||||
// is moved from build to SSR
|
||||
const parser = await import(contentEntryType.parser);
|
||||
// TODO: Zod check that parser is a valid parser
|
||||
contentEntryExtToParserCache.set(extension, parser as ContentEntryParser);
|
||||
}
|
||||
}
|
||||
return contentEntryExtToParserCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* The content config is loaded separately from other `src/` files.
|
||||
* This global observable lets dependent plugins (like the content flag plugin)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import npath from 'node:path';
|
||||
import { pathToFileURL } from 'url';
|
||||
import type { Plugin } from 'vite';
|
||||
import { AstroSettings } from '../@types/astro.js';
|
||||
import { moduleIsTopLevelPage, walkParentInfos } from '../core/build/graph.js';
|
||||
import { BuildInternals, getPageDataByViteID } from '../core/build/internal.js';
|
||||
import { AstroBuildPlugin } from '../core/build/plugin.js';
|
||||
|
@ -11,23 +12,30 @@ import { prependForwardSlash } from '../core/path.js';
|
|||
import { getStylesForURL } from '../core/render/dev/css.js';
|
||||
import { getScriptsForURL } from '../core/render/dev/scripts.js';
|
||||
import {
|
||||
contentFileExts,
|
||||
LINKS_PLACEHOLDER,
|
||||
PROPAGATED_ASSET_FLAG,
|
||||
SCRIPTS_PLACEHOLDER,
|
||||
STYLES_PLACEHOLDER,
|
||||
} from './consts.js';
|
||||
import { getContentEntryExts } from './utils.js';
|
||||
|
||||
function isPropagatedAsset(viteId: string): boolean {
|
||||
function isPropagatedAsset(viteId: string, contentEntryExts: string[]): boolean {
|
||||
const url = new URL(viteId, 'file://');
|
||||
return (
|
||||
url.searchParams.has(PROPAGATED_ASSET_FLAG) &&
|
||||
contentFileExts.some((ext) => url.pathname.endsWith(ext))
|
||||
contentEntryExts.some((ext) => url.pathname.endsWith(ext))
|
||||
);
|
||||
}
|
||||
|
||||
export function astroContentAssetPropagationPlugin({ mode }: { mode: string }): Plugin {
|
||||
export function astroContentAssetPropagationPlugin({
|
||||
mode,
|
||||
settings,
|
||||
}: {
|
||||
mode: string;
|
||||
settings: AstroSettings;
|
||||
}): Plugin {
|
||||
let devModuleLoader: ModuleLoader;
|
||||
const contentEntryExts = getContentEntryExts(settings);
|
||||
return {
|
||||
name: 'astro:content-asset-propagation',
|
||||
enforce: 'pre',
|
||||
|
@ -37,7 +45,7 @@ export function astroContentAssetPropagationPlugin({ mode }: { mode: string }):
|
|||
}
|
||||
},
|
||||
load(id) {
|
||||
if (isPropagatedAsset(id)) {
|
||||
if (isPropagatedAsset(id, contentEntryExts)) {
|
||||
const basePath = id.split('?')[0];
|
||||
const code = `
|
||||
export async function getMod() {
|
||||
|
@ -52,7 +60,7 @@ export function astroContentAssetPropagationPlugin({ mode }: { mode: string }):
|
|||
},
|
||||
async transform(code, id, options) {
|
||||
if (!options?.ssr) return;
|
||||
if (devModuleLoader && isPropagatedAsset(id)) {
|
||||
if (devModuleLoader && isPropagatedAsset(id, contentEntryExts)) {
|
||||
const basePath = id.split('?')[0];
|
||||
if (!devModuleLoader.getModuleById(basePath)?.ssrModule) {
|
||||
await devModuleLoader.import(basePath);
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
import * as devalue from 'devalue';
|
||||
import type fsMod from 'node:fs';
|
||||
import { extname } from 'node:path';
|
||||
import { pathToFileURL } from 'url';
|
||||
import type { Plugin } from 'vite';
|
||||
import { AstroSettings } from '../@types/astro.js';
|
||||
import { AstroErrorData } from '../core/errors/errors-data.js';
|
||||
import { AstroError } from '../core/errors/errors.js';
|
||||
import { escapeViteEnvReferences, getFileInfo } from '../vite-plugin-utils/index.js';
|
||||
import { contentFileExts, CONTENT_FLAG } from './consts.js';
|
||||
import { CONTENT_FLAG } from './consts.js';
|
||||
import {
|
||||
ContentConfig,
|
||||
getContentEntryExts,
|
||||
getContentPaths,
|
||||
getEntryData,
|
||||
getEntryInfo,
|
||||
getEntrySlug,
|
||||
getEntryType,
|
||||
globalContentConfigObserver,
|
||||
loadContentEntryParsers,
|
||||
parseFrontmatter,
|
||||
} from './utils.js';
|
||||
|
||||
function isContentFlagImport(viteId: string) {
|
||||
const { pathname, searchParams } = new URL(viteId, 'file://');
|
||||
return searchParams.has(CONTENT_FLAG) && contentFileExts.some((ext) => pathname.endsWith(ext));
|
||||
function isContentFlagImport(viteId: string, contentEntryExts: string[]) {
|
||||
const { searchParams, pathname } = new URL(viteId, 'file://');
|
||||
return searchParams.has(CONTENT_FLAG) && contentEntryExts.some((ext) => pathname.endsWith(ext));
|
||||
}
|
||||
|
||||
export function astroContentImportPlugin({
|
||||
|
@ -31,12 +34,13 @@ export function astroContentImportPlugin({
|
|||
settings: AstroSettings;
|
||||
}): Plugin {
|
||||
const contentPaths = getContentPaths(settings.config);
|
||||
const contentEntryExts = getContentEntryExts(settings);
|
||||
|
||||
return {
|
||||
name: 'astro:content-imports',
|
||||
async load(id) {
|
||||
const { fileId } = getFileInfo(id, settings.config);
|
||||
if (isContentFlagImport(id)) {
|
||||
if (isContentFlagImport(id, contentEntryExts)) {
|
||||
const observable = globalContentConfigObserver.get();
|
||||
|
||||
// Content config should be loaded before this plugin is used
|
||||
|
@ -63,12 +67,38 @@ export function astroContentImportPlugin({
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
const contentEntryParsers = await loadContentEntryParsers({ settings });
|
||||
const rawContents = await fs.promises.readFile(fileId, 'utf-8');
|
||||
const {
|
||||
content: body,
|
||||
data: unparsedData,
|
||||
matter: rawData = '',
|
||||
} = parseFrontmatter(rawContents, fileId);
|
||||
const fileExt = extname(fileId);
|
||||
const contentEntryParser = contentEntryParsers.get(fileExt);
|
||||
// if (!contentEntryParser) {
|
||||
// throw new AstroError({
|
||||
// ...AstroErrorData.UnknownContentCollectionError,
|
||||
// message: `No content parser found for file extension "${fileExt}".`,
|
||||
// });
|
||||
// }
|
||||
let body: string,
|
||||
unvalidatedData: Record<string, unknown>,
|
||||
unvalidatedSlug: string,
|
||||
rawData: string;
|
||||
if (contentEntryParser) {
|
||||
const info = await contentEntryParser.getEntryInfo({
|
||||
fileUrl: pathToFileURL(fileId),
|
||||
contents: rawContents,
|
||||
});
|
||||
body = info.body;
|
||||
unvalidatedData = info.data;
|
||||
unvalidatedSlug = info.slug;
|
||||
rawData = info.rawData;
|
||||
} else {
|
||||
const parsed = parseFrontmatter(rawContents, fileId);
|
||||
body = parsed.content;
|
||||
unvalidatedData = parsed.data;
|
||||
unvalidatedSlug = parsed.data.slug;
|
||||
rawData = parsed.matter;
|
||||
}
|
||||
|
||||
const entryInfo = getEntryInfo({
|
||||
entry: pathToFileURL(fileId),
|
||||
contentDir: contentPaths.contentDir,
|
||||
|
@ -76,15 +106,14 @@ export function astroContentImportPlugin({
|
|||
if (entryInfo instanceof Error) return;
|
||||
|
||||
const _internal = { filePath: fileId, rawData };
|
||||
const partialEntry = { data: unparsedData, body, _internal, ...entryInfo };
|
||||
// TODO: move slug calculation to the start of the build
|
||||
// to generate a performant lookup map for `getEntryBySlug`
|
||||
const slug = getEntrySlug(partialEntry);
|
||||
const slug = getEntrySlug({ ...entryInfo, unvalidatedSlug });
|
||||
|
||||
const collectionConfig = contentConfig?.collections[entryInfo.collection];
|
||||
const data = collectionConfig
|
||||
? await getEntryData(partialEntry, collectionConfig)
|
||||
: unparsedData;
|
||||
? await getEntryData({ ...entryInfo, _internal, unvalidatedData }, collectionConfig)
|
||||
: unvalidatedData;
|
||||
|
||||
const code = escapeViteEnvReferences(`
|
||||
export const id = ${JSON.stringify(entryInfo.id)};
|
||||
|
@ -94,7 +123,7 @@ export const body = ${JSON.stringify(body)};
|
|||
export const data = ${devalue.uneval(data) /* TODO: reuse astro props serializer */};
|
||||
export const _internal = {
|
||||
filePath: ${JSON.stringify(fileId)},
|
||||
rawData: ${JSON.stringify(rawData)},
|
||||
rawData: ${JSON.stringify(unvalidatedData)},
|
||||
};
|
||||
`);
|
||||
return { code };
|
||||
|
@ -104,11 +133,11 @@ export const _internal = {
|
|||
viteServer.watcher.on('all', async (event, entry) => {
|
||||
if (
|
||||
['add', 'unlink', 'change'].includes(event) &&
|
||||
getEntryType(entry, contentPaths) === 'config'
|
||||
getEntryType(entry, contentPaths, contentEntryExts) === 'config'
|
||||
) {
|
||||
// Content modules depend on config, so we need to invalidate them.
|
||||
for (const modUrl of viteServer.moduleGraph.urlToModuleMap.keys()) {
|
||||
if (isContentFlagImport(modUrl)) {
|
||||
if (isContentFlagImport(modUrl, contentEntryExts)) {
|
||||
const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl);
|
||||
if (mod) {
|
||||
viteServer.moduleGraph.invalidateModule(mod);
|
||||
|
@ -119,7 +148,7 @@ export const _internal = {
|
|||
});
|
||||
},
|
||||
async transform(code, id) {
|
||||
if (isContentFlagImport(id)) {
|
||||
if (isContentFlagImport(id, contentEntryExts)) {
|
||||
// Escape before Rollup internal transform.
|
||||
// Base on MUCH trial-and-error, inspired by MDX integration 2-step transform.
|
||||
return { code: escapeViteEnvReferences(code) };
|
||||
|
|
|
@ -4,8 +4,8 @@ import type { Plugin } from 'vite';
|
|||
import { normalizePath } from 'vite';
|
||||
import type { AstroSettings } from '../@types/astro.js';
|
||||
import { appendForwardSlash, prependForwardSlash } from '../core/path.js';
|
||||
import { contentFileExts, VIRTUAL_MODULE_ID } from './consts.js';
|
||||
import { getContentPaths } from './utils.js';
|
||||
import { VIRTUAL_MODULE_ID } from './consts.js';
|
||||
import { getContentEntryExts, getContentPaths } from './utils.js';
|
||||
|
||||
interface AstroContentVirtualModPluginParams {
|
||||
settings: AstroSettings;
|
||||
|
@ -22,7 +22,9 @@ export function astroContentVirtualModPlugin({
|
|||
)
|
||||
)
|
||||
);
|
||||
const entryGlob = `${relContentDir}**/*{${contentFileExts.join(',')}}`;
|
||||
const contentEntryExts = getContentEntryExts(settings);
|
||||
|
||||
const entryGlob = `${relContentDir}**/*{${contentEntryExts.join(',')}}`;
|
||||
const virtualModContents = fsMod
|
||||
.readFileSync(contentPaths.virtualModTemplate, 'utf-8')
|
||||
.replace('@@CONTENT_DIR@@', relContentDir)
|
||||
|
|
44
packages/astro/src/content/~dream.ts
Normal file
44
packages/astro/src/content/~dream.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { parseFrontmatter } from './utils.js';
|
||||
|
||||
// Register things for typesafety
|
||||
declare module 'astro:content' {
|
||||
interface FancyRender {
|
||||
'.mdoc': {
|
||||
getParsed(): string;
|
||||
getTransformed(): Promise<string>;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
type ContentEntryType = {
|
||||
extensions: string[];
|
||||
getEntryInfo(params: { fileUrl: URL }): Promise<{
|
||||
data: Record<string, unknown>;
|
||||
/**
|
||||
* Used for error hints to point to correct line and location
|
||||
* Should be the untouched data as read from the file,
|
||||
* including newlines
|
||||
*/
|
||||
rawData: string;
|
||||
body: string;
|
||||
slug: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
export const contentEntryTypes: ContentEntryType[] = [
|
||||
{
|
||||
extensions: ['.mdoc'],
|
||||
async getEntryInfo({ fileUrl }) {
|
||||
const rawContents = await fs.promises.readFile(fileUrl, 'utf-8');
|
||||
const parsed = parseFrontmatter(rawContents, fileURLToPath(fileUrl));
|
||||
return {
|
||||
data: parsed.data,
|
||||
body: parsed.content,
|
||||
slug: parsed.data.slug,
|
||||
rawData: parsed.matter,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
|
@ -15,6 +15,8 @@ export function createBaseSettings(config: AstroConfig): AstroSettings {
|
|||
adapter: undefined,
|
||||
injectedRoutes: [],
|
||||
pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS],
|
||||
/** TODO: default Markdown entry type */
|
||||
contentEntryTypes: [],
|
||||
renderers: [jsxRenderer],
|
||||
scripts: [],
|
||||
watchFiles: [],
|
||||
|
|
|
@ -112,7 +112,7 @@ export async function createVite(
|
|||
astroInjectEnvTsPlugin({ settings, logging, fs }),
|
||||
astroContentVirtualModPlugin({ settings }),
|
||||
astroContentImportPlugin({ fs, settings }),
|
||||
astroContentAssetPropagationPlugin({ mode }),
|
||||
astroContentAssetPropagationPlugin({ mode, settings }),
|
||||
],
|
||||
publicDir: fileURLToPath(settings.config.publicDir),
|
||||
root: fileURLToPath(settings.config.root),
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
AstroRenderer,
|
||||
AstroSettings,
|
||||
BuildConfig,
|
||||
ContentEntryType,
|
||||
HookParameters,
|
||||
RouteData,
|
||||
} from '../@types/astro.js';
|
||||
|
@ -100,11 +101,22 @@ export async function runHookConfigSetup({
|
|||
const exts = (input.flat(Infinity) as string[]).map((ext) => `.${ext.replace(/^\./, '')}`);
|
||||
updatedSettings.pageExtensions.push(...exts);
|
||||
}
|
||||
|
||||
// Semi-private `addContentEntryType` hook
|
||||
function addContentEntryType(contentEntryType: ContentEntryType) {
|
||||
updatedSettings.contentEntryTypes.push(contentEntryType);
|
||||
}
|
||||
|
||||
Object.defineProperty(hooks, 'addPageExtension', {
|
||||
value: addPageExtension,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
});
|
||||
Object.defineProperty(hooks, 'addContentEntryType', {
|
||||
value: addContentEntryType,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
});
|
||||
await withTakingALongTimeMsg({
|
||||
name: integration.name,
|
||||
hookResult: integration.hooks['astro:config:setup'](hooks),
|
||||
|
|
|
@ -2,6 +2,8 @@ import { getEntryType } from '../../../dist/content/utils.js';
|
|||
import { expect } from 'chai';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const contentFileExts = ['.md', '.mdx'];
|
||||
|
||||
describe('Content Collections - getEntryType', () => {
|
||||
const contentDir = new URL('src/content/', import.meta.url);
|
||||
const contentPaths = {
|
||||
|
@ -11,7 +13,7 @@ describe('Content Collections - getEntryType', () => {
|
|||
it('Returns "content" for Markdown files', () => {
|
||||
for (const entryPath of ['blog/first-post.md', 'blog/first-post.mdx']) {
|
||||
const entry = fileURLToPath(new URL(entryPath, contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('content');
|
||||
}
|
||||
});
|
||||
|
@ -19,44 +21,44 @@ describe('Content Collections - getEntryType', () => {
|
|||
it('Returns "content" for Markdown files in nested directories', () => {
|
||||
for (const entryPath of ['blog/2021/01/01/index.md', 'blog/2021/01/01/index.mdx']) {
|
||||
const entry = fileURLToPath(new URL(entryPath, contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('content');
|
||||
}
|
||||
});
|
||||
|
||||
it('Returns "config" for config files', () => {
|
||||
const entry = fileURLToPath(contentPaths.config);
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('config');
|
||||
});
|
||||
|
||||
it('Returns "unsupported" for non-Markdown files', () => {
|
||||
const entry = fileURLToPath(new URL('blog/robots.txt', contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('unsupported');
|
||||
});
|
||||
|
||||
it('Returns "ignored" for .DS_Store', () => {
|
||||
const entry = fileURLToPath(new URL('blog/.DS_Store', contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('ignored');
|
||||
});
|
||||
|
||||
it('Returns "ignored" for unsupported files using an underscore', () => {
|
||||
const entry = fileURLToPath(new URL('blog/_draft-robots.txt', contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('ignored');
|
||||
});
|
||||
|
||||
it('Returns "ignored" when using underscore on file name', () => {
|
||||
const entry = fileURLToPath(new URL('blog/_first-post.md', contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('ignored');
|
||||
});
|
||||
|
||||
it('Returns "ignored" when using underscore on directory name', () => {
|
||||
const entry = fileURLToPath(new URL('blog/_draft/first-post.md', contentDir));
|
||||
const type = getEntryType(entry, contentPaths);
|
||||
const type = getEntryType(entry, contentPaths, contentFileExts);
|
||||
expect(type).to.equal('ignored');
|
||||
});
|
||||
});
|
||||
|
|
614
packages/integrations/markdoc/CHANGELOG.md
Normal file
614
packages/integrations/markdoc/CHANGELOG.md
Normal file
|
@ -0,0 +1,614 @@
|
|||
# @astrojs/mdx
|
||||
|
||||
## 0.16.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6050](https://github.com/withastro/astro/pull/6050) [`2ab32b59e`](https://github.com/withastro/astro/commit/2ab32b59ef0a28d34757f2c2adb9cf2baa86855e) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: load syntax highlighters after MDX remark plugins. This keeps MDX consistent with Astro's markdown behavior.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6062](https://github.com/withastro/astro/pull/6062) [`c6cf847bd`](https://github.com/withastro/astro/commit/c6cf847bd0b6bef3c51a5710fba5ca43b11e46f9) Thanks [@delucis](https://github.com/delucis)! - Update MDX README
|
||||
|
||||
## 0.15.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5478](https://github.com/withastro/astro/pull/5478) [`1c7eef308`](https://github.com/withastro/astro/commit/1c7eef308e808aa5ed4662b53e67ec8d1b814d1f) Thanks [@nemo0](https://github.com/nemo0)! - Update READMEs for consistency
|
||||
|
||||
## 0.15.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5978](https://github.com/withastro/astro/pull/5978) [`7abb1e905`](https://github.com/withastro/astro/commit/7abb1e9056c4b4fd0abfced347df32a41cdfbf28) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Fix MDX heading IDs generation when using a frontmatter reference
|
||||
|
||||
- Updated dependencies [[`7abb1e905`](https://github.com/withastro/astro/commit/7abb1e9056c4b4fd0abfced347df32a41cdfbf28)]:
|
||||
- @astrojs/markdown-remark@2.0.1
|
||||
|
||||
## 0.15.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5684](https://github.com/withastro/astro/pull/5684) [`a9c292026`](https://github.com/withastro/astro/commit/a9c2920264e36cc5dc05f4adc1912187979edb0d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Refine Markdown and MDX configuration options for ease-of-use. & [#5769](https://github.com/withastro/astro/pull/5769) [`93e633922`](https://github.com/withastro/astro/commit/93e633922c2e449df3bb2357b3683af1d3c0e07b) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Introduce a `smartypants` flag to opt-out of Astro's default SmartyPants plugin.
|
||||
|
||||
- **Markdown**
|
||||
|
||||
- **Replace the `extendDefaultPlugins` option** with a `gfm` boolean and a `smartypants` boolean. These are enabled by default, and can be disabled to remove GitHub-Flavored Markdown and SmartyPants.
|
||||
|
||||
- Ensure GitHub-Flavored Markdown and SmartyPants are applied whether or not custom `remarkPlugins` or `rehypePlugins` are configured. If you want to apply custom plugins _and_ remove Astro's default plugins, manually set `gfm: false` and `smartypants: false` in your config.
|
||||
|
||||
- **Migrate `extendDefaultPlugins` to `gfm` and `smartypants`**
|
||||
|
||||
You may have disabled Astro's built-in plugins (GitHub-Flavored Markdown and Smartypants) with the `extendDefaultPlugins` option. This has now been split into 2 flags to disable each plugin individually:
|
||||
|
||||
- `markdown.gfm` to disable GitHub-Flavored Markdown
|
||||
- `markdown.smartypants` to disable SmartyPants
|
||||
|
||||
```diff
|
||||
// astro.config.mjs
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
markdown: {
|
||||
- extendDefaultPlugins: false,
|
||||
+ smartypants: false,
|
||||
+ gfm: false,
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Additionally, applying remark and rehype plugins **no longer disables** `gfm` and `smartypants`. You will need to opt-out manually by setting `gfm` and `smartypants` to `false`.
|
||||
|
||||
- **MDX**
|
||||
|
||||
- Support _all_ Markdown configuration options (except `drafts`) from your MDX integration config. This includes `syntaxHighlighting` and `shikiConfig` options to further customize the MDX renderer.
|
||||
|
||||
- Simplify `extendPlugins` to an `extendMarkdownConfig` option. MDX options will default to their equivalent in your Markdown config. By setting `extendMarkdownConfig` to false, you can "eject" to set your own syntax highlighting, plugins, and more.
|
||||
|
||||
- **Migrate MDX's `extendPlugins` to `extendMarkdownConfig`**
|
||||
|
||||
You may have used the `extendPlugins` option to manage plugin defaults in MDX. This has been replaced by 3 flags:
|
||||
|
||||
- `extendMarkdownConfig` (`true` by default) to toggle Markdown config inheritance. This replaces the `extendPlugins: 'markdown'` option.
|
||||
- `gfm` (`true` by default) and `smartypants` (`true` by default) to toggle GitHub-Flavored Markdown and SmartyPants in MDX. This replaces the `extendPlugins: 'defaults'` option.
|
||||
|
||||
- [#5687](https://github.com/withastro/astro/pull/5687) [`e2019be6f`](https://github.com/withastro/astro/commit/e2019be6ffa46fa33d92cfd346f9ecbe51bb7144) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Give remark and rehype plugins access to user frontmatter via frontmatter injection. This means `data.astro.frontmatter` is now the _complete_ Markdown or MDX document's frontmatter, rather than an empty object.
|
||||
|
||||
This allows plugin authors to modify existing frontmatter, or compute new properties based on other properties. For example, say you want to compute a full image URL based on an `imageSrc` slug in your document frontmatter:
|
||||
|
||||
```ts
|
||||
export function remarkInjectSocialImagePlugin() {
|
||||
return function (tree, file) {
|
||||
const { frontmatter } = file.data.astro;
|
||||
frontmatter.socialImageSrc = new URL(frontmatter.imageSrc, 'https://my-blog.com/').pathname;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
When using Content Collections, you can access this modified frontmatter using the `remarkPluginFrontmatter` property returned when rendering an entry.
|
||||
|
||||
**Migration instructions**
|
||||
|
||||
Plugin authors should now **check for user frontmatter when applying defaults.**
|
||||
|
||||
For example, say a remark plugin wants to apply a default `title` if none is present. Add a conditional to check if the property is present, and update if none exists:
|
||||
|
||||
```diff
|
||||
export function remarkInjectTitlePlugin() {
|
||||
return function (tree, file) {
|
||||
const { frontmatter } = file.data.astro;
|
||||
+ if (!frontmatter.title) {
|
||||
frontmatter.title = 'Default title';
|
||||
+ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This differs from previous behavior, where a Markdown file's frontmatter would _always_ override frontmatter injected via remark or reype.
|
||||
|
||||
- [#5891](https://github.com/withastro/astro/pull/5891) [`05caf445d`](https://github.com/withastro/astro/commit/05caf445d4d2728f1010aeb2179a9e756c2fd17d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove deprecated Markdown APIs from Astro v0.X. This includes `getHeaders()`, the `.astro` property for layouts, and the `rawContent()` and `compiledContent()` error messages for MDX.
|
||||
|
||||
- [#5782](https://github.com/withastro/astro/pull/5782) [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Remove support for Node 14. Minimum supported Node version is now >=16.12.0
|
||||
|
||||
- [#5825](https://github.com/withastro/astro/pull/5825) [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Baseline the experimental `contentCollections` flag. You're free to remove this from your astro config!
|
||||
|
||||
```diff
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
- experimental: { contentCollections: true }
|
||||
})
|
||||
```
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5837](https://github.com/withastro/astro/pull/5837) [`12f65a4d5`](https://github.com/withastro/astro/commit/12f65a4d55e3fd2993c2f67b18794dd536280c69) Thanks [@giuseppelt](https://github.com/giuseppelt)! - fix shiki css class replace logic
|
||||
|
||||
- [#5741](https://github.com/withastro/astro/pull/5741) [`000d3e694`](https://github.com/withastro/astro/commit/000d3e6940839c2aebba1984e6fb3b133cec6749) Thanks [@delucis](https://github.com/delucis)! - Fix broken links in README
|
||||
|
||||
- Updated dependencies [[`93e633922`](https://github.com/withastro/astro/commit/93e633922c2e449df3bb2357b3683af1d3c0e07b), [`e2019be6f`](https://github.com/withastro/astro/commit/e2019be6ffa46fa33d92cfd346f9ecbe51bb7144), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`12f65a4d5`](https://github.com/withastro/astro/commit/12f65a4d55e3fd2993c2f67b18794dd536280c69), [`16107b6a1`](https://github.com/withastro/astro/commit/16107b6a10514ef1b563e585ec9add4b14f42b94), [`a9c292026`](https://github.com/withastro/astro/commit/a9c2920264e36cc5dc05f4adc1912187979edb0d), [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f), [`7572f7402`](https://github.com/withastro/astro/commit/7572f7402238da37de748be58d678fedaf863b53)]:
|
||||
- @astrojs/markdown-remark@2.0.0
|
||||
- @astrojs/prism@2.0.0
|
||||
|
||||
## 1.0.0-beta.2
|
||||
|
||||
<details>
|
||||
<summary>See changes in 1.0.0-beta.2</summary>
|
||||
|
||||
### Major Changes
|
||||
|
||||
- [#5825](https://github.com/withastro/astro/pull/5825) [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Baseline the experimental `contentCollections` flag. You're free to remove this from your astro config!
|
||||
|
||||
```diff
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
- experimental: { contentCollections: true }
|
||||
})
|
||||
```
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5782](https://github.com/withastro/astro/pull/5782) [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Remove support for Node 14. Minimum supported Node version is now >=16.12.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5837](https://github.com/withastro/astro/pull/5837) [`12f65a4d5`](https://github.com/withastro/astro/commit/12f65a4d55e3fd2993c2f67b18794dd536280c69) Thanks [@giuseppelt](https://github.com/giuseppelt)! - fix shiki css class replace logic
|
||||
|
||||
- Updated dependencies [[`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`12f65a4d5`](https://github.com/withastro/astro/commit/12f65a4d55e3fd2993c2f67b18794dd536280c69), [`16107b6a1`](https://github.com/withastro/astro/commit/16107b6a10514ef1b563e585ec9add4b14f42b94), [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f), [`7572f7402`](https://github.com/withastro/astro/commit/7572f7402238da37de748be58d678fedaf863b53)]:
|
||||
- @astrojs/prism@2.0.0-beta.0
|
||||
- @astrojs/markdown-remark@2.0.0-beta.2
|
||||
|
||||
</details>
|
||||
|
||||
## 0.15.0-beta.1
|
||||
|
||||
<details>
|
||||
<summary>See changes in 0.15.0-beta.1</summary>
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5769](https://github.com/withastro/astro/pull/5769) [`93e633922`](https://github.com/withastro/astro/commit/93e633922c2e449df3bb2357b3683af1d3c0e07b) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Introduce a `smartypants` flag to opt-out of Astro's default SmartyPants plugin.
|
||||
|
||||
```js
|
||||
{
|
||||
markdown: {
|
||||
smartypants: false,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Migration
|
||||
|
||||
You may have disabled Astro's built-in plugins (GitHub-Flavored Markdown and Smartypants) with the `extendDefaultPlugins` option. This has now been split into 2 flags to disable each plugin individually:
|
||||
|
||||
- `markdown.gfm` to disable GitHub-Flavored Markdown
|
||||
- `markdown.smartypants` to disable SmartyPants
|
||||
|
||||
```diff
|
||||
// astro.config.mjs
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
markdown: {
|
||||
- extendDefaultPlugins: false,
|
||||
+ smartypants: false,
|
||||
+ gfm: false,
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5741](https://github.com/withastro/astro/pull/5741) [`000d3e694`](https://github.com/withastro/astro/commit/000d3e6940839c2aebba1984e6fb3b133cec6749) Thanks [@delucis](https://github.com/delucis)! - Fix broken links in README
|
||||
|
||||
- Updated dependencies [[`93e633922`](https://github.com/withastro/astro/commit/93e633922c2e449df3bb2357b3683af1d3c0e07b)]:
|
||||
- @astrojs/markdown-remark@2.0.0-beta.1
|
||||
|
||||
</details>
|
||||
|
||||
## 0.15.0-beta.0
|
||||
|
||||
<details>
|
||||
<summary>See changes in 0.15.0-beta.0</summary>
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5687](https://github.com/withastro/astro/pull/5687) [`e2019be6f`](https://github.com/withastro/astro/commit/e2019be6ffa46fa33d92cfd346f9ecbe51bb7144) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Give remark and rehype plugins access to user frontmatter via frontmatter injection. This means `data.astro.frontmatter` is now the _complete_ Markdown or MDX document's frontmatter, rather than an empty object.
|
||||
|
||||
This allows plugin authors to modify existing frontmatter, or compute new properties based on other properties. For example, say you want to compute a full image URL based on an `imageSrc` slug in your document frontmatter:
|
||||
|
||||
```ts
|
||||
export function remarkInjectSocialImagePlugin() {
|
||||
return function (tree, file) {
|
||||
const { frontmatter } = file.data.astro;
|
||||
frontmatter.socialImageSrc = new URL(frontmatter.imageSrc, 'https://my-blog.com/').pathname;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Content Collections - new `remarkPluginFrontmatter` property
|
||||
|
||||
We have changed _inject_ frontmatter to _modify_ frontmatter in our docs to improve discoverability. This is based on support forum feedback, where "injection" is rarely the term used.
|
||||
|
||||
To reflect this, the `injectedFrontmatter` property has been renamed to `remarkPluginFrontmatter`. This should clarify this plugin is still separate from the `data` export Content Collections expose today.
|
||||
|
||||
#### Migration instructions
|
||||
|
||||
Plugin authors should now **check for user frontmatter when applying defaults.**
|
||||
|
||||
For example, say a remark plugin wants to apply a default `title` if none is present. Add a conditional to check if the property is present, and update if none exists:
|
||||
|
||||
```diff
|
||||
export function remarkInjectTitlePlugin() {
|
||||
return function (tree, file) {
|
||||
const { frontmatter } = file.data.astro;
|
||||
+ if (!frontmatter.title) {
|
||||
frontmatter.title = 'Default title';
|
||||
+ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This differs from previous behavior, where a Markdown file's frontmatter would _always_ override frontmatter injected via remark or reype.
|
||||
|
||||
- [#5684](https://github.com/withastro/astro/pull/5684) [`a9c292026`](https://github.com/withastro/astro/commit/a9c2920264e36cc5dc05f4adc1912187979edb0d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Refine Markdown and MDX configuration options for ease-of-use.
|
||||
|
||||
#### Markdown
|
||||
|
||||
- **Remove `remark-smartypants`** from Astro's default Markdown plugins.
|
||||
- **Replace the `extendDefaultPlugins` option** with a simplified `gfm` boolean. This is enabled by default, and can be disabled to remove GitHub-Flavored Markdown.
|
||||
- Ensure GitHub-Flavored Markdown is applied whether or not custom `remarkPlugins` or `rehypePlugins` are configured. If you want to apply custom plugins _and_ remove GFM, manually set `gfm: false` in your config.
|
||||
|
||||
#### MDX
|
||||
|
||||
- Support _all_ Markdown configuration options (except `drafts`) from your MDX integration config. This includes `syntaxHighlighting` and `shikiConfig` options to further customize the MDX renderer.
|
||||
- Simplify `extendDefaults` to an `extendMarkdownConfig` option. MDX options will default to their equivalent in your Markdown config. By setting `extendMarkdownConfig` to false, you can "eject" to set your own syntax highlighting, plugins, and more.
|
||||
|
||||
#### Migration
|
||||
|
||||
To preserve your existing Markdown and MDX setup, you may need some configuration changes:
|
||||
|
||||
##### Smartypants manual installation
|
||||
|
||||
[Smartypants](https://github.com/silvenon/remark-smartypants) has been removed from Astro's default setup. If you rely on this plugin, [install `remark-smartypants`](https://github.com/silvenon/remark-smartypants#installing) and apply to your `astro.config.*`:
|
||||
|
||||
```diff
|
||||
// astro.config.mjs
|
||||
import { defineConfig } from 'astro/config';
|
||||
+ import smartypants from 'remark-smartypants';
|
||||
|
||||
export default defineConfig({
|
||||
markdown: {
|
||||
+ remarkPlugins: [smartypants],
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
##### Migrate `extendDefaultPlugins` to `gfm`
|
||||
|
||||
You may have disabled Astro's built-in plugins (GitHub-Flavored Markdown and Smartypants) with the `extendDefaultPlugins` option. Since Smartypants has been removed, this has been renamed to `gfm`.
|
||||
|
||||
```diff
|
||||
// astro.config.mjs
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
markdown: {
|
||||
- extendDefaultPlugins: false,
|
||||
+ gfm: false,
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Additionally, applying remark and rehype plugins **no longer disables** `gfm`. You will need to opt-out manually by setting `gfm` to `false`.
|
||||
|
||||
##### Migrate MDX's `extendPlugins` to `extendMarkdownConfig`
|
||||
|
||||
You may have used the `extendPlugins` option to manage plugin defaults in MDX. This has been replaced by 2 flags:
|
||||
|
||||
- `extendMarkdownConfig` (`true` by default) to toggle Markdown config inheritance. This replaces the `extendPlugins: 'markdown'` option.
|
||||
- `gfm` (`true` by default) to toggle GitHub-Flavored Markdown in MDX. This replaces the `extendPlugins: 'defaults'` option.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e2019be6f`](https://github.com/withastro/astro/commit/e2019be6ffa46fa33d92cfd346f9ecbe51bb7144), [`a9c292026`](https://github.com/withastro/astro/commit/a9c2920264e36cc5dc05f4adc1912187979edb0d)]:
|
||||
- @astrojs/markdown-remark@2.0.0-beta.0
|
||||
|
||||
</details>
|
||||
|
||||
## 0.14.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5654](https://github.com/withastro/astro/pull/5654) [`2c65b433b`](https://github.com/withastro/astro/commit/2c65b433bf840a1bb93b0a1947df5949e33512ff) Thanks [@delucis](https://github.com/delucis)! - Run heading ID injection after user plugins
|
||||
|
||||
⚠️ BREAKING CHANGE ⚠️
|
||||
|
||||
If you are using a rehype plugin that depends on heading IDs injected by Astro, the IDs will no longer be available when your plugin runs by default.
|
||||
|
||||
To inject IDs before your plugins run, import and add the `rehypeHeadingIds` plugin to your `rehypePlugins` config:
|
||||
|
||||
```diff
|
||||
// astro.config.mjs
|
||||
+ import { rehypeHeadingIds } from '@astrojs/markdown-remark';
|
||||
import mdx from '@astrojs/mdx';
|
||||
|
||||
export default {
|
||||
integrations: [mdx()],
|
||||
markdown: {
|
||||
rehypePlugins: [
|
||||
+ rehypeHeadingIds,
|
||||
otherPluginThatReliesOnHeadingIDs,
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5667](https://github.com/withastro/astro/pull/5667) [`a5ba4af79`](https://github.com/withastro/astro/commit/a5ba4af79930145f4edf66d45cd40ddad045cc86) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Chore: remove verbose "Now interiting Markdown plugins..." logs
|
||||
|
||||
- [#5648](https://github.com/withastro/astro/pull/5648) [`853081d1c`](https://github.com/withastro/astro/commit/853081d1c857d8ad8a9634c37ed8fd123d32d241) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Prevent relative image paths in `src/content/`
|
||||
|
||||
- Updated dependencies [[`853081d1c`](https://github.com/withastro/astro/commit/853081d1c857d8ad8a9634c37ed8fd123d32d241), [`2c65b433b`](https://github.com/withastro/astro/commit/2c65b433bf840a1bb93b0a1947df5949e33512ff)]:
|
||||
- @astrojs/markdown-remark@1.2.0
|
||||
|
||||
## 0.13.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5291](https://github.com/withastro/astro/pull/5291) [`5ec0f6ed5`](https://github.com/withastro/astro/commit/5ec0f6ed55b0a14a9663a90a03428345baf126bd) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Introduce Content Collections experimental API
|
||||
- Organize your Markdown and MDX content into easy-to-manage collections.
|
||||
- Add type safety to your frontmatter with schemas.
|
||||
- Generate landing pages, static routes, and SSR endpoints from your content using the collection query APIs.
|
||||
|
||||
## 0.12.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5586](https://github.com/withastro/astro/pull/5586) [`f4ff69a3c`](https://github.com/withastro/astro/commit/f4ff69a3cd874c8804c6d01c7cbbaed8a8e90be7) Thanks [@delucis](https://github.com/delucis)! - Fix link in MDX integration README
|
||||
|
||||
- [#5570](https://github.com/withastro/astro/pull/5570) [`3f811eb68`](https://github.com/withastro/astro/commit/3f811eb682d55bd1f908f9b4bc3b795d2859d713) Thanks [@sarah11918](https://github.com/sarah11918)! - Revise README
|
||||
|
||||
## 0.12.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5522](https://github.com/withastro/astro/pull/5522) [`efc4363e0`](https://github.com/withastro/astro/commit/efc4363e0baf7f92900e20af339811bb3df42b0e) Thanks [@delucis](https://github.com/delucis)! - Support use of `<Fragment>` in MDX files rendered with `<Content />` component
|
||||
|
||||
## 0.12.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#5427](https://github.com/withastro/astro/pull/5427) [`2a1c085b1`](https://github.com/withastro/astro/commit/2a1c085b199f24e34424ec8c19041c03602c53c5) Thanks [@backflip](https://github.com/backflip)! - Uses remark-rehype options from astro.config.mjs
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5448](https://github.com/withastro/astro/pull/5448) [`ef2ffc7ae`](https://github.com/withastro/astro/commit/ef2ffc7ae9ff554860238ecd2fb3bf6d82b5801b) Thanks [@delucis](https://github.com/delucis)! - Fix broken link in README
|
||||
|
||||
## 0.11.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5335](https://github.com/withastro/astro/pull/5335) [`dca762cf7`](https://github.com/withastro/astro/commit/dca762cf734a657d8f126fd6958892b6163a4f67) Thanks [@bluwy](https://github.com/bluwy)! - Preserve code element node `data.meta` in `properties.metastring` for rehype syntax highlighters, like `rehype-pretty-code``
|
||||
|
||||
## 0.11.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5146](https://github.com/withastro/astro/pull/5146) [`308e565ad`](https://github.com/withastro/astro/commit/308e565ad39957e3353d72ca5d3bbce1a1b45008) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Support recmaPlugins config option
|
||||
|
||||
## 0.11.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4953](https://github.com/withastro/astro/pull/4953) [`a59731995`](https://github.com/withastro/astro/commit/a59731995b93ae69c21dc3adc5c8b482b466d12e) Thanks [@bluwy](https://github.com/bluwy)! - Log markdown hints with console.info
|
||||
|
||||
## 0.11.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4842](https://github.com/withastro/astro/pull/4842) [`812658ad2`](https://github.com/withastro/astro/commit/812658ad2ab3732a99e35c4fd903e302e723db46) Thanks [@bluwy](https://github.com/bluwy)! - Add missing dependencies, support strict dependency installation (e.g. pnpm)
|
||||
|
||||
## 0.11.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4700](https://github.com/withastro/astro/pull/4700) [`e5f71142e`](https://github.com/withastro/astro/commit/e5f71142eb62bd72456e889dad5774347c3753f2) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Document MDXLayoutProps utility type
|
||||
|
||||
- [#4858](https://github.com/withastro/astro/pull/4858) [`58a2dca22`](https://github.com/withastro/astro/commit/58a2dca2286cb14f6211cf51267c02447e78433a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Correctly parse import.meta.env in MDX files
|
||||
|
||||
## 0.11.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4588](https://github.com/withastro/astro/pull/4588) [`db38f61b2`](https://github.com/withastro/astro/commit/db38f61b2b2dc55f03b28797d19b163b1940f1c8) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: Add GFM and Smartypants to MDX by default
|
||||
|
||||
## 0.11.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4504](https://github.com/withastro/astro/pull/4504) [`8f8dff4d3`](https://github.com/withastro/astro/commit/8f8dff4d339a3a12ee155d81a97132032ef3b622) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Introduce new `extendPlugins` configuration option. This defaults to inheriting all remark and rehype plugins from your `markdown` config, with options to use either Astro's defaults or no inheritance at all.
|
||||
|
||||
## 0.10.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4519](https://github.com/withastro/astro/pull/4519) [`a2e8e76c3`](https://github.com/withastro/astro/commit/a2e8e76c303e8d6f39c24c122905a10f06907997) Thanks [@JuanM04](https://github.com/JuanM04)! - Upgraded Shiki to v0.11.1
|
||||
|
||||
- [#4530](https://github.com/withastro/astro/pull/4530) [`8504cd79b`](https://github.com/withastro/astro/commit/8504cd79b708e0d3bf1a2bb4ff9b86936bdd692b) Thanks [@kylebutts](https://github.com/kylebutts)! - Add custom components to README
|
||||
|
||||
## 0.10.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4423](https://github.com/withastro/astro/pull/4423) [`d4cd7a59f`](https://github.com/withastro/astro/commit/d4cd7a59fd38d411c442a818cfaab40f74106628) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Update Markdown type signature to match new markdown plugin,and update top-level layout props for better alignment
|
||||
|
||||
## 0.10.2-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4423](https://github.com/withastro/astro/pull/4423) [`d4cd7a59f`](https://github.com/withastro/astro/commit/d4cd7a59fd38d411c442a818cfaab40f74106628) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Update Markdown type signature to match new markdown plugin,and update top-level layout props for better alignment
|
||||
|
||||
## 0.10.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4443](https://github.com/withastro/astro/pull/4443) [`adb207979`](https://github.com/withastro/astro/commit/adb20797962c280d4d38f335f577fd52a1b48d4b) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix MDX style imports when layout is not applied
|
||||
|
||||
* [#4428](https://github.com/withastro/astro/pull/4428) [`a2414bf59`](https://github.com/withastro/astro/commit/a2414bf59e2e2cd633aece68e724401c4ad281b9) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix dev server reload performance when globbing from an MDX layout
|
||||
|
||||
## 0.10.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4292](https://github.com/withastro/astro/pull/4292) [`f1a52c18a`](https://github.com/withastro/astro/commit/f1a52c18afe66e6d310743ae6884be76f69be265) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Switch from Shiki Twoslash to Astro's Shiki Markdown highlighter
|
||||
|
||||
## 0.9.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4268](https://github.com/withastro/astro/pull/4268) [`f7afdb889`](https://github.com/withastro/astro/commit/f7afdb889fe4e97177958c8ec92f80c5f6e5cb51) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Align MD with MDX on layout props and "glob" import results:
|
||||
- Add `Content` to MDX
|
||||
- Add `file` and `url` to MDX frontmatter (layout import only)
|
||||
- Update glob types to reflect differences (lack of `rawContent` and `compiledContent`)
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4272](https://github.com/withastro/astro/pull/4272) [`24d2f7a6e`](https://github.com/withastro/astro/commit/24d2f7a6e6700c10c863f826f37bb653d70e3a83) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Properly handle hydration for namespaced components
|
||||
|
||||
## 0.8.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4248](https://github.com/withastro/astro/pull/4248) [`869d00935`](https://github.com/withastro/astro/commit/869d0093596b709cfcc1a1a95ee631b48d6d1c26) Thanks [@svemat01](https://github.com/svemat01)! - Load builtin rehype plugins before user plugins instead of after
|
||||
|
||||
* [#4255](https://github.com/withastro/astro/pull/4255) [`411612808`](https://github.com/withastro/astro/commit/4116128082121ee276d51cb245bf8095be4728a1) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Pass injected frontmatter from remark and rehype plugins to layouts
|
||||
|
||||
* Updated dependencies [[`1f0dd31d9`](https://github.com/withastro/astro/commit/1f0dd31d9239b5e3dca99c88d021e7a9a3e2054d)]:
|
||||
- @astrojs/prism@1.0.1
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4237](https://github.com/withastro/astro/pull/4237) [`9d5ab5508`](https://github.com/withastro/astro/commit/9d5ab55086964fbede17da3d78c209c6d8d13711) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Update "Astro.props.content" -> "Astro.props.frontmatter" in README
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308)]:
|
||||
- @astrojs/prism@1.0.0
|
||||
|
||||
## 0.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4204](https://github.com/withastro/astro/pull/4204) [`4c2ca5352`](https://github.com/withastro/astro/commit/4c2ca5352d0c4119ed2a9e5e0b78ce71eb1b414a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove `frontmatterOptions` from MDX config
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4205](https://github.com/withastro/astro/pull/4205) [`6c9736cbc`](https://github.com/withastro/astro/commit/6c9736cbc90162f1de3ebccd7cfe98332749b639) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add frontmatter injection instructions to README
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4176](https://github.com/withastro/astro/pull/4176) [`2675b8633`](https://github.com/withastro/astro/commit/2675b8633c5d5c45b237ec87940d5eaf1bfb1b4b) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Support frontmatter injection for MD and MDX using remark and rehype plugins
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4181](https://github.com/withastro/astro/pull/4181) [`77cede720`](https://github.com/withastro/astro/commit/77cede720b09bce34f29c3d2d8b505311ce876b1) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Make collect-headings rehype plugin non-overridable
|
||||
|
||||
* [#4174](https://github.com/withastro/astro/pull/4174) [`8eb3a8c6d`](https://github.com/withastro/astro/commit/8eb3a8c6d9554707963c3a3bc36ed8b68d3cf0fb) Thanks [@matthewp](https://github.com/matthewp)! - Allows using React with automatic imports alongside MDX
|
||||
|
||||
- [#4145](https://github.com/withastro/astro/pull/4145) [`c7efcf57e`](https://github.com/withastro/astro/commit/c7efcf57e00a0fcde3bc9f813e3cc59902bd484c) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Fix a missing newline bug when `layout` was set.
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4134](https://github.com/withastro/astro/pull/4134) [`2968ba2b6`](https://github.com/withastro/astro/commit/2968ba2b6f00775b6e9872681b390cb466fdbfa2) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add `headings` and `frontmatter` properties to layout props
|
||||
|
||||
## 0.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4095](https://github.com/withastro/astro/pull/4095) [`40ef43a59`](https://github.com/withastro/astro/commit/40ef43a59b08a1a8fbcd9f4a53745a9636a4fbb9) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add IDs to MDX headings and expose via getHeadings() export
|
||||
|
||||
* [#4114](https://github.com/withastro/astro/pull/4114) [`64432bcb8`](https://github.com/withastro/astro/commit/64432bcb873efd0e4297c00fc9583a1fe516dfe7) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Refactor `@astrojs/mdx` and `@astrojs/markdown-remark` to use `@astrojs/prism` instead of duplicating the code
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4112](https://github.com/withastro/astro/pull/4112) [`e33fc9bc4`](https://github.com/withastro/astro/commit/e33fc9bc46ff0a30013deb6dc76e545e70cc3a3e) Thanks [@matthewp](https://github.com/matthewp)! - Fix MDX working with a ts config file
|
||||
|
||||
* [#4049](https://github.com/withastro/astro/pull/4049) [`b60cc0538`](https://github.com/withastro/astro/commit/b60cc0538bc5c68dd411117780d20d892530789d) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improve `injectScript` handling for non-Astro pages
|
||||
|
||||
* Updated dependencies [[`64432bcb8`](https://github.com/withastro/astro/commit/64432bcb873efd0e4297c00fc9583a1fe516dfe7)]:
|
||||
- @astrojs/prism@0.7.0
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#4088](https://github.com/withastro/astro/pull/4088) [`1743fe140`](https://github.com/withastro/astro/commit/1743fe140eb58d60e26cbd11a066bb60de046e0c) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Support "layout" frontmatter property
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4076](https://github.com/withastro/astro/pull/4076) [`6120a71e5`](https://github.com/withastro/astro/commit/6120a71e5425ad55a17ddac800d64a3f50273bce) Thanks [@matthewp](https://github.com/matthewp)! - Ensure file and url are always present in MDX for Astro.glob
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#3977](https://github.com/withastro/astro/pull/3977) [`19433eb4a`](https://github.com/withastro/astro/commit/19433eb4a4441522f68492ca914ad2ab4f061343) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add remarkPlugins and rehypePlugins to config, with the same default plugins as our standard Markdown parser
|
||||
|
||||
* [#4002](https://github.com/withastro/astro/pull/4002) [`3b8a74452`](https://github.com/withastro/astro/commit/3b8a7445247221100462ba035f6778b43ea180e7) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Support Prism and Shiki syntax highlighting based on project config
|
||||
|
||||
- [#3995](https://github.com/withastro/astro/pull/3995) [`b2b367c96`](https://github.com/withastro/astro/commit/b2b367c969493aaf21c974064beb241d05228066) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Support YAML frontmatter in MDX files
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4050](https://github.com/withastro/astro/pull/4050) [`9ab66c4ba`](https://github.com/withastro/astro/commit/9ab66c4ba9bf2250990114c76b792f26d0694365) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Add support for injected "page-ssr" scripts
|
||||
|
||||
* [#3981](https://github.com/withastro/astro/pull/3981) [`61fec6304`](https://github.com/withastro/astro/commit/61fec63044e1585348e8405bee6fdf4dec635efa) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Include page url in MDX glob result
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#3937](https://github.com/withastro/astro/pull/3937) [`31f9c0bf0`](https://github.com/withastro/astro/commit/31f9c0bf029ffa4b470e620f2c32e1370643e81e) Thanks [@delucis](https://github.com/delucis)! - Roll back supported Node engines
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#3914](https://github.com/withastro/astro/pull/3914) [`b48767985`](https://github.com/withastro/astro/commit/b48767985359bd359df8071324952ea5f2bc0d86) Thanks [@ran-dall](https://github.com/ran-dall)! - Rollback supported `node@16` version. Minimum versions are now `node@14.20.0` or `node@16.14.0`.
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#3885](https://github.com/withastro/astro/pull/3885) [`bf5d1cc1e`](https://github.com/withastro/astro/commit/bf5d1cc1e71da38a14658c615e9481f2145cc6e7) Thanks [@delucis](https://github.com/delucis)! - Integration README fixes
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#3871](https://github.com/withastro/astro/pull/3871) [`1cc5b7890`](https://github.com/withastro/astro/commit/1cc5b78905633608e5b07ad291f916f54e67feb1) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Update supported `node` versions. Minimum versions are now `node@14.20.0` or `node@16.16.0`.
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#3854](https://github.com/withastro/astro/pull/3854) [`b012ee55`](https://github.com/withastro/astro/commit/b012ee55b107dea0730286263b27d83e530fad5d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - [astro add] Support adapters and third party packages
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#3706](https://github.com/withastro/astro/pull/3706) [`032ad1c0`](https://github.com/withastro/astro/commit/032ad1c047a62dd663067cc562537d16f2872aa7) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Initial release! 🎉
|
85
packages/integrations/markdoc/README.md
Normal file
85
packages/integrations/markdoc/README.md
Normal file
|
@ -0,0 +1,85 @@
|
|||
# @astrojs/markdoc 📝
|
||||
|
||||
This **[Astro integration][astro-integration]** enables the usage of [Markdoc](https://markdoc.dev/) to create components, pages, and content collection entries.
|
||||
|
||||
- <strong>[Why Markdoc?](#why-markdoc)</strong>
|
||||
- <strong>[Installation](#installation)</strong>
|
||||
- <strong>[Usage](#usage)</strong>
|
||||
- <strong>[Configuration](#configuration)</strong>
|
||||
- <strong>[Examples](#examples)</strong>
|
||||
- <strong>[Troubleshooting](#troubleshooting)</strong>
|
||||
- <strong>[Contributing](#contributing)</strong>
|
||||
- <strong>[Changelog](#changelog)</strong>
|
||||
|
||||
## Why Markdoc?
|
||||
|
||||
Markdoc allows you to enhance your Markdown with [UI components][astro-ui-frameworks]. If you have existing content authored in Markdoc, this integration allows you to bring those files to your Astro project.
|
||||
|
||||
## Installation
|
||||
|
||||
### Quick Install
|
||||
|
||||
The `astro add` command-line tool automates the installation for you. Run one of the following commands in a new terminal window. (If you aren't sure which package manager you're using, run the first command.) Then, follow the prompts, and type "y" in the terminal (meaning "yes") for each one.
|
||||
|
||||
```sh
|
||||
# Using NPM
|
||||
npx astro add markdoc
|
||||
# Using Yarn
|
||||
yarn astro add markdoc
|
||||
# Using PNPM
|
||||
pnpm astro add markdoc
|
||||
```
|
||||
|
||||
If you run into any issues, [feel free to report them to us on GitHub](https://github.com/withastro/astro/issues) and try the manual installation steps below.
|
||||
|
||||
### Manual Install
|
||||
|
||||
First, install the `@astrojs/markdoc` package using your package manager. If you're using npm or aren't sure, run this in the terminal:
|
||||
|
||||
```sh
|
||||
npm install @astrojs/markdoc
|
||||
```
|
||||
|
||||
Then, apply this integration to your `astro.config.*` file using the `integrations` property:
|
||||
|
||||
__`astro.config.mjs`__
|
||||
|
||||
```js ins={2} "markdoc()"
|
||||
import { defineConfig } from 'astro/config';
|
||||
import markdoc from '@astrojs/markdoc';
|
||||
|
||||
export default defineConfig({
|
||||
// ...
|
||||
integrations: [markdoc()],
|
||||
});
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
TODO
|
||||
|
||||
## Configuration
|
||||
|
||||
TODO
|
||||
|
||||
## Examples
|
||||
|
||||
TODO
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help!
|
||||
|
||||
You can also check our [Astro Integration Documentation][astro-integration] for more on integrations.
|
||||
|
||||
## Contributing
|
||||
|
||||
This package is maintained by Astro's Core team. You're welcome to submit an issue or PR!
|
||||
|
||||
## Changelog
|
||||
|
||||
See [CHANGELOG.md](https://github.com/withastro/astro/tree/main/packages/integrations/markdoc/CHANGELOG.md) for a history of changes to this integration.
|
||||
|
||||
[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/
|
||||
|
||||
[astro-ui-frameworks]: https://docs.astro.build/en/core-concepts/framework-components/#using-framework-components
|
30
packages/integrations/markdoc/components/RenderNode.astro
Normal file
30
packages/integrations/markdoc/components/RenderNode.astro
Normal file
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
import stringifyAttributes from 'stringify-attributes';
|
||||
import type { AstroNode } from './astroNode';
|
||||
|
||||
type Props = {
|
||||
node: AstroNode;
|
||||
};
|
||||
|
||||
const Node = (Astro.props as Props).node;
|
||||
---
|
||||
|
||||
{
|
||||
typeof Node === 'string' ? (
|
||||
<Fragment set:text={Node} />
|
||||
) : 'component' in Node ? (
|
||||
<Node.component {...Node.props}>
|
||||
{Node.children.map((child) => (
|
||||
<Astro.self node={child} />
|
||||
))}
|
||||
</Node.component>
|
||||
) : (
|
||||
<Fragment>
|
||||
<Fragment set:html={`<${Node.tag} ${stringifyAttributes(Node.attributes)}>`} />
|
||||
{Node.children.map((child) => (
|
||||
<Astro.self node={child} />
|
||||
))}
|
||||
<Fragment set:html={`</${Node.tag}>`} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
14
packages/integrations/markdoc/components/Renderer.astro
Normal file
14
packages/integrations/markdoc/components/Renderer.astro
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
||||
import { ComponentRenderer, createAstroNode } from './astroNode';
|
||||
import RenderNode from './RenderNode.astro';
|
||||
|
||||
type Props = {
|
||||
content: RenderableTreeNode;
|
||||
components: Record<string, ComponentRenderer>;
|
||||
};
|
||||
|
||||
const { content, components } = Astro.props as Props;
|
||||
---
|
||||
|
||||
<RenderNode node={createAstroNode(content, components)} />
|
67
packages/integrations/markdoc/components/astroNode.ts
Normal file
67
packages/integrations/markdoc/components/astroNode.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { RenderableTreeNode, Tag, renderers, NodeType } from '@markdoc/markdoc';
|
||||
import { escape } from 'html-escaper';
|
||||
|
||||
// TODO: expose `AstroComponentFactory` type from core
|
||||
type AstroComponentFactory = (props: Record<string, any>) => any & {
|
||||
isAstroComponentFactory: true;
|
||||
};
|
||||
|
||||
export type ComponentRenderer =
|
||||
| AstroComponentFactory
|
||||
| {
|
||||
component: AstroComponentFactory;
|
||||
props?(params: { attributes: Record<string, any>; getTreeNode(): Tag }): Record<string, any>;
|
||||
};
|
||||
|
||||
export type AstroNode =
|
||||
| string
|
||||
| {
|
||||
component: AstroComponentFactory;
|
||||
props: Record<string, any>;
|
||||
children: AstroNode[];
|
||||
}
|
||||
| {
|
||||
tag: string;
|
||||
attributes: Record<string, any>;
|
||||
children: AstroNode[];
|
||||
};
|
||||
|
||||
export function createAstroNode(
|
||||
node: RenderableTreeNode,
|
||||
components: Record<string, ComponentRenderer> = {}
|
||||
): AstroNode {
|
||||
if (typeof node === 'string' || typeof node === 'number') {
|
||||
return escape(String(node));
|
||||
} else if (node === null || typeof node !== 'object' || !Tag.isTag(node)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (node.name in components) {
|
||||
const componentRenderer = components[node.name];
|
||||
const component =
|
||||
'component' in componentRenderer ? componentRenderer.component : componentRenderer;
|
||||
const props =
|
||||
'props' in componentRenderer && typeof componentRenderer.props === 'function'
|
||||
? componentRenderer.props({
|
||||
attributes: node.attributes,
|
||||
getTreeNode() {
|
||||
return node;
|
||||
},
|
||||
})
|
||||
: node.attributes;
|
||||
|
||||
const children = node.children.map((child) => createAstroNode(child, components));
|
||||
|
||||
return {
|
||||
component,
|
||||
props,
|
||||
children,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
tag: node.name,
|
||||
attributes: node.attributes,
|
||||
children: node.children.map((child) => createAstroNode(child, components)),
|
||||
};
|
||||
}
|
||||
}
|
2
packages/integrations/markdoc/components/index.ts
Normal file
2
packages/integrations/markdoc/components/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
// @ts-ignore
|
||||
export { default as Renderer } from './Renderer.astro';
|
19
packages/integrations/markdoc/content-types.d.ts
vendored
Normal file
19
packages/integrations/markdoc/content-types.d.ts
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
declare module 'astro:content' {
|
||||
type ComponentRenderer =
|
||||
| JSX.Element
|
||||
| {
|
||||
component: JSX.Element;
|
||||
props?(params: {
|
||||
attributes: Record<string, any>;
|
||||
getTreeNode(): import('@markdoc/markdoc').Tag;
|
||||
}): Record<string, any>;
|
||||
};
|
||||
interface Render {
|
||||
'.mdoc': {
|
||||
Content(props: {
|
||||
components: Record<string, ComponentRenderer>;
|
||||
config: import('@markdoc/markdoc').Config;
|
||||
}): Promise<JSX.Element>;
|
||||
};
|
||||
}
|
||||
}
|
55
packages/integrations/markdoc/package.json
Normal file
55
packages/integrations/markdoc/package.json
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "@astrojs/markdoc",
|
||||
"description": "Use Markdoc within Astro",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"types": "./dist/index.d.ts",
|
||||
"author": "withastro",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/withastro/astro.git",
|
||||
"directory": "packages/integrations/markdoc"
|
||||
},
|
||||
"keywords": [
|
||||
"astro-integration",
|
||||
"astro-component",
|
||||
"markdoc"
|
||||
],
|
||||
"bugs": "https://github.com/withastro/astro/issues",
|
||||
"homepage": "https://docs.astro.build/en/guides/integrations-guide/markdoc/",
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./content-type-parser": "./dist/content-type-parser.js",
|
||||
"./components": "./components/index.ts",
|
||||
"./content-types": "./content-types.d.ts",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
|
||||
"build:ci": "astro-scripts build \"src/**/*.ts\"",
|
||||
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
||||
"test": "mocha --exit --timeout 20000",
|
||||
"test:match": "mocha --timeout 20000 -g"
|
||||
},
|
||||
"dependencies": {
|
||||
"@markdoc/markdoc": "^0.2.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"html-escaper": "^3.0.3",
|
||||
"stringify-attributes": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.1",
|
||||
"@types/html-escaper": "^3.0.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"astro": "workspace:*",
|
||||
"astro-scripts": "workspace:*",
|
||||
"chai": "^4.3.6",
|
||||
"linkedom": "^0.14.12",
|
||||
"mocha": "^9.2.2",
|
||||
"vite": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.12.0"
|
||||
}
|
||||
}
|
38
packages/integrations/markdoc/src/content-type-parser.ts
Normal file
38
packages/integrations/markdoc/src/content-type-parser.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
import matter from 'gray-matter';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import type { ErrorPayload as ViteErrorPayload } from 'vite';
|
||||
|
||||
export default {
|
||||
async getEntryInfo({ contents, fileUrl }: { contents: string; fileUrl: URL }) {
|
||||
const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
|
||||
return {
|
||||
data: parsed.data,
|
||||
body: parsed.content,
|
||||
slug: parsed.data.slug,
|
||||
rawData: parsed.matter,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Match YAML exception handling from Astro core errors
|
||||
* @see 'astro/src/core/errors.ts'
|
||||
*/
|
||||
function parseFrontmatter(fileContents: string, filePath: string) {
|
||||
try {
|
||||
// `matter` is empty string on cache results
|
||||
// clear cache to prevent this
|
||||
(matter as any).clearCache();
|
||||
return matter(fileContents);
|
||||
} catch (e: any) {
|
||||
if (e.name === 'YAMLException') {
|
||||
const err: Error & ViteErrorPayload['err'] = e;
|
||||
err.id = filePath;
|
||||
err.loc = { file: e.id, line: e.mark.line + 1, column: e.mark.column };
|
||||
err.message = e.reason;
|
||||
throw err;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
48
packages/integrations/markdoc/src/index.ts
Normal file
48
packages/integrations/markdoc/src/index.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import type { AstroIntegration } from 'astro';
|
||||
import type { InlineConfig } from 'vite';
|
||||
import _Markdoc from '@markdoc/markdoc';
|
||||
|
||||
const contentEntryType = {
|
||||
extensions: ['.mdoc'],
|
||||
parser: '@astrojs/markdoc/content-type-parser',
|
||||
};
|
||||
|
||||
export default function markdoc(partialOptions: {} = {}): AstroIntegration {
|
||||
return {
|
||||
name: '@astrojs/markdoc',
|
||||
hooks: {
|
||||
'astro:config:setup': async ({ updateConfig, config, addContentEntryType, command }: any) => {
|
||||
addContentEntryType(contentEntryType);
|
||||
|
||||
console.log('Markdoc working!');
|
||||
const markdocConfigUrl = new URL('./markdoc.config.ts', config.srcDir);
|
||||
|
||||
const viteConfig: InlineConfig = {
|
||||
plugins: [
|
||||
{
|
||||
name: '@astrojs/markdoc',
|
||||
async transform(code, id) {
|
||||
if (!id.endsWith('.mdoc')) return;
|
||||
return `import { jsx as h } from 'astro/jsx-runtime';\nimport { Markdoc } from '@astrojs/markdoc';\nimport { Renderer } from '@astrojs/markdoc/components';\nexport const body = ${JSON.stringify(
|
||||
code
|
||||
)};\nexport function getParsed() { return Markdoc.parse(body); }\nexport async function getTransformed(inlineConfig) {
|
||||
let config = inlineConfig ?? {};
|
||||
if (!config) {
|
||||
try {
|
||||
const importedConfig = await import(${JSON.stringify(markdocConfigUrl.pathname)});
|
||||
console.log({ importedConfig })
|
||||
config = importedConfig.default.transform;
|
||||
} catch {}
|
||||
}
|
||||
return Markdoc.transform(getParsed(), config) }\nexport async function Content ({ transformConfig, components }) { return h(Renderer, { content: await getTransformed(transformConfig), components }); }\nContent[Symbol.for('astro.needsHeadRendering')] = true;`;
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
updateConfig({ vite: viteConfig });
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const Markdoc = _Markdoc;
|
10
packages/integrations/markdoc/tsconfig.json
Normal file
10
packages/integrations/markdoc/tsconfig.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"include": ["src", "components", "content-types.d.ts"],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"module": "ES2020",
|
||||
"outDir": "./dist",
|
||||
"target": "ES2020"
|
||||
}
|
||||
}
|
14
packages/integrations/mdx/src/content-type-parser.ts
Normal file
14
packages/integrations/mdx/src/content-type-parser.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { fileURLToPath } from 'node:url';
|
||||
import { parseFrontmatter } from './utils.js';
|
||||
|
||||
export default {
|
||||
async getEntryInfo({ contents, fileUrl }: { contents: string; fileUrl: URL }) {
|
||||
const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
|
||||
return {
|
||||
data: parsed.data,
|
||||
body: parsed.content,
|
||||
slug: parsed.data.slug,
|
||||
rawData: parsed.matter,
|
||||
};
|
||||
},
|
||||
};
|
|
@ -6,6 +6,7 @@ import mdxPlugin, { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
|
|||
import type { AstroIntegration } from 'astro';
|
||||
import { parse as parseESM } from 'es-module-lexer';
|
||||
import fs from 'node:fs/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import type { Options as RemarkRehypeOptions } from 'remark-rehype';
|
||||
import { VFile } from 'vfile';
|
||||
import type { Plugin as VitePlugin } from 'vite';
|
||||
|
@ -22,12 +23,24 @@ export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | '
|
|||
remarkRehype: RemarkRehypeOptions;
|
||||
};
|
||||
|
||||
const contentEntryType = {
|
||||
extensions: ['.mdx'],
|
||||
parser: '@astrojs/mdx/content-type-parser',
|
||||
};
|
||||
|
||||
export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroIntegration {
|
||||
return {
|
||||
name: '@astrojs/mdx',
|
||||
hooks: {
|
||||
'astro:config:setup': async ({ updateConfig, config, addPageExtension, command }: any) => {
|
||||
'astro:config:setup': async ({
|
||||
updateConfig,
|
||||
config,
|
||||
addPageExtension,
|
||||
addContentEntryType,
|
||||
command,
|
||||
}: any) => {
|
||||
addPageExtension('.mdx');
|
||||
addContentEntryType(contentEntryType);
|
||||
|
||||
const extendMarkdownConfig =
|
||||
partialMdxOptions.extendMarkdownConfig ?? defaultOptions.extendMarkdownConfig;
|
||||
|
|
|
@ -285,6 +285,19 @@ importers:
|
|||
unocss: 0.15.6
|
||||
vite-imagetools: 4.0.18
|
||||
|
||||
examples/with-markdoc:
|
||||
specifiers:
|
||||
'@astrojs/markdoc': ^0.0.1
|
||||
'@astrojs/mdx': ^0.16.0
|
||||
'@markdoc/markdoc': ^0.2.2
|
||||
astro: ^2.0.6
|
||||
dependencies:
|
||||
'@astrojs/markdoc': link:../../packages/integrations/markdoc
|
||||
'@astrojs/mdx': link:../../packages/integrations/mdx
|
||||
astro: link:../../packages/astro
|
||||
devDependencies:
|
||||
'@markdoc/markdoc': 0.2.2
|
||||
|
||||
examples/with-markdown-plugins:
|
||||
specifiers:
|
||||
'@astrojs/markdown-remark': ^2.0.1
|
||||
|
@ -2845,6 +2858,37 @@ importers:
|
|||
mocha: 9.2.2
|
||||
sass: 1.58.0
|
||||
|
||||
packages/integrations/markdoc:
|
||||
specifiers:
|
||||
'@markdoc/markdoc': ^0.2.2
|
||||
'@types/chai': ^4.3.1
|
||||
'@types/html-escaper': ^3.0.0
|
||||
'@types/mocha': ^9.1.1
|
||||
astro: workspace:*
|
||||
astro-scripts: workspace:*
|
||||
chai: ^4.3.6
|
||||
gray-matter: ^4.0.3
|
||||
html-escaper: ^3.0.3
|
||||
linkedom: ^0.14.12
|
||||
mocha: ^9.2.2
|
||||
stringify-attributes: ^3.0.0
|
||||
vite: ^4.0.3
|
||||
dependencies:
|
||||
'@markdoc/markdoc': 0.2.2
|
||||
gray-matter: 4.0.3
|
||||
html-escaper: 3.0.3
|
||||
stringify-attributes: 3.0.0
|
||||
devDependencies:
|
||||
'@types/chai': 4.3.4
|
||||
'@types/html-escaper': 3.0.0
|
||||
'@types/mocha': 9.1.1
|
||||
astro: link:../../astro
|
||||
astro-scripts: link:../../../scripts
|
||||
chai: 4.3.7
|
||||
linkedom: 0.14.21
|
||||
mocha: 9.2.2
|
||||
vite: 4.1.1
|
||||
|
||||
packages/integrations/mdx:
|
||||
specifiers:
|
||||
'@astrojs/markdown-remark': ^2.0.1
|
||||
|
@ -6365,6 +6409,20 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@markdoc/markdoc/0.2.2:
|
||||
resolution: {integrity: sha512-0TiD9jmA5h5znN4lxo7HECAu3WieU5g5vUsfByeucrdR/x88hEilpt16EydFyJwJddQ/3w5HQgW7Ovy62r4cyw==}
|
||||
engines: {node: '>=14.7.0'}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: '*'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
optionalDependencies:
|
||||
'@types/markdown-it': 12.2.3
|
||||
|
||||
/@mdx-js/mdx/2.2.1:
|
||||
resolution: {integrity: sha512-hZ3ex7exYLJn6FfReq8yTvA6TE53uW9UHJQM9IlSauOuS55J9y8RtA7W+dzp6Yrzr00/U1sd7q+Wf61q6SfiTQ==}
|
||||
dependencies:
|
||||
|
@ -7169,11 +7227,27 @@ packages:
|
|||
/@types/json5/0.0.30:
|
||||
resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==}
|
||||
|
||||
/@types/linkify-it/3.0.2:
|
||||
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
|
||||
optional: true
|
||||
|
||||
/@types/markdown-it/12.2.3:
|
||||
resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@types/linkify-it': 3.0.2
|
||||
'@types/mdurl': 1.0.2
|
||||
optional: true
|
||||
|
||||
/@types/mdast/3.0.10:
|
||||
resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==}
|
||||
dependencies:
|
||||
'@types/unist': 2.0.6
|
||||
|
||||
/@types/mdurl/1.0.2:
|
||||
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
||||
optional: true
|
||||
|
||||
/@types/mdx/2.0.3:
|
||||
resolution: {integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==}
|
||||
dev: false
|
||||
|
@ -9510,6 +9584,11 @@ packages:
|
|||
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
/escape-goat/3.0.0:
|
||||
resolution: {integrity: sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/escape-html/1.0.3:
|
||||
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||
dev: false
|
||||
|
@ -14185,6 +14264,13 @@ packages:
|
|||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
/stringify-attributes/3.0.0:
|
||||
resolution: {integrity: sha512-tJKiThlLfog6ljT7ZTihlMh0iAtjKlu/ss9DMmBE5oOosbMqOMcuxc7zDfxP2lGzSb2Bwvbd3gQTqTSCmXyySw==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
escape-goat: 3.0.0
|
||||
dev: false
|
||||
|
||||
/stringify-entities/4.0.3:
|
||||
resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==}
|
||||
dependencies:
|
||||
|
|
Loading…
Reference in a new issue