@astrojs/markdoc 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -4
- package/dist/content-entry-type.js +19 -22
- package/dist/extensions/prism.js +1 -1
- package/dist/extensions/shiki.js +1 -18
- package/dist/heading-ids.js +4 -4
- package/dist/html/transform/html-token-transform.d.ts +1 -1
- package/dist/{experimental-assets-config.d.ts → runtime-assets-config.d.ts} +1 -1
- package/dist/{experimental-assets-config.js → runtime-assets-config.js} +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +5 -3
- package/dist/tokenizer.js +1 -1
- package/dist/utils.js +5 -1
- package/package.json +17 -17
package/README.md
CHANGED
|
@@ -278,7 +278,7 @@ export default defineMarkdocConfig({
|
|
|
278
278
|
|
|
279
279
|
### Use client-side UI components
|
|
280
280
|
|
|
281
|
-
Tags and nodes are restricted to `.astro` files. To embed client-side UI components in Markdoc, [use a wrapper `.astro` component that renders a framework component](/en/core-concepts/framework-components/#nesting-framework-components) with your desired `client:` directive.
|
|
281
|
+
Tags and nodes are restricted to `.astro` files. To embed client-side UI components in Markdoc, [use a wrapper `.astro` component that renders a framework component](https://docs.astro.build/en/core-concepts/framework-components/#nesting-framework-components) with your desired `client:` directive.
|
|
282
282
|
|
|
283
283
|
This example wraps a React `Aside.tsx` component with a `ClientAside.astro` component:
|
|
284
284
|
|
|
@@ -344,6 +344,36 @@ Now, you can call this function from any Markdoc content entry:
|
|
|
344
344
|
|
|
345
345
|
📚 [See the Markdoc documentation](https://markdoc.dev/docs/functions#creating-a-custom-function) for more on using variables or functions in your content.
|
|
346
346
|
|
|
347
|
+
### Markdoc Language Server
|
|
348
|
+
|
|
349
|
+
If you are using VS Code, there is an official [Markdoc language extension](https://marketplace.visualstudio.com/items?itemName=Stripe.markdoc-language-support) that includes syntax highlighting and autocomplete for configured tags. [See the language server on GitHub](https://github.com/markdoc/language-server.git) for more information.
|
|
350
|
+
|
|
351
|
+
To set up the extension, create a `markdoc.config.json` file into the project root with following content:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
[
|
|
355
|
+
{
|
|
356
|
+
"id": "my-site",
|
|
357
|
+
"path": "src/content",
|
|
358
|
+
"schema": {
|
|
359
|
+
"path": "markdoc.config.mjs",
|
|
360
|
+
"type": "esm",
|
|
361
|
+
"property": "default",
|
|
362
|
+
"watch": true
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
The `schema` property contains all information to configure the language server for Astro content collections. It accepts following properties:
|
|
369
|
+
|
|
370
|
+
- `path`: The path to the configuration file.
|
|
371
|
+
- `type`: The type of module your configuration file uses (`esm` allows `import` syntax).
|
|
372
|
+
- `property`: The exported property name that contains the configuration object.
|
|
373
|
+
- `watch`: Tell the server to watch for changes in the configuration.
|
|
374
|
+
|
|
375
|
+
The top-level `path` property tells the server where content is located. Since Markdoc is specific to content collections, you can use `src/content`.
|
|
376
|
+
|
|
347
377
|
### Pass Markdoc variables
|
|
348
378
|
|
|
349
379
|
You may need to pass [variables][markdoc-variables] to your content. This is useful when passing SSR parameters like A/B tests.
|
|
@@ -425,9 +455,7 @@ export default defineConfig({
|
|
|
425
455
|
```
|
|
426
456
|
|
|
427
457
|
> **Warning**
|
|
428
|
-
> When `allowHTML` is enabled, HTML markup inside Markdoc documents will be rendered as actual HTML elements (including `<script>`), making attack vectors like XSS possible.
|
|
429
|
-
>
|
|
430
|
-
> Ensure that any HTML markup comes from trusted sources.
|
|
458
|
+
> When `allowHTML` is enabled, HTML markup inside Markdoc documents will be rendered as actual HTML elements (including `<script>`), making attack vectors like XSS possible. Ensure that any HTML markup comes from trusted sources.
|
|
431
459
|
|
|
432
460
|
## Examples
|
|
433
461
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import Markdoc from "@markdoc/markdoc";
|
|
2
|
+
import { emitESMImage } from "astro/assets/utils";
|
|
2
3
|
import matter from "gray-matter";
|
|
3
4
|
import fs from "node:fs";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { MarkdocError, isComponentConfig, isValidUrl, prependForwardSlash } from "./utils.js";
|
|
6
|
-
import { emitESMImage } from "astro/assets/utils";
|
|
7
5
|
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
8
7
|
import { htmlTokenTransform } from "./html/transform/html-token-transform.js";
|
|
9
8
|
import { setupConfig } from "./runtime.js";
|
|
10
9
|
import { getMarkdocTokenizer } from "./tokenizer.js";
|
|
10
|
+
import { MarkdocError, isComponentConfig, isValidUrl, prependForwardSlash } from "./utils.js";
|
|
11
11
|
async function getContentEntryType({
|
|
12
12
|
markdocConfigResult,
|
|
13
13
|
astroConfig,
|
|
@@ -18,27 +18,26 @@ async function getContentEntryType({
|
|
|
18
18
|
getEntryInfo,
|
|
19
19
|
handlePropagation: true,
|
|
20
20
|
async getRenderModule({ contents, fileUrl, viteId }) {
|
|
21
|
-
var _a, _b;
|
|
22
21
|
const entry = getEntryInfo({ contents, fileUrl });
|
|
23
22
|
const tokenizer = getMarkdocTokenizer(options);
|
|
24
23
|
let tokens = tokenizer.tokenize(entry.body);
|
|
25
|
-
if (options
|
|
24
|
+
if (options?.allowHTML) {
|
|
26
25
|
tokens = htmlTokenTransform(tokenizer, tokens);
|
|
27
26
|
}
|
|
28
27
|
const ast = Markdoc.parse(tokens);
|
|
29
28
|
const usedTags = getUsedTags(ast);
|
|
30
|
-
const userMarkdocConfig =
|
|
31
|
-
const markdocConfigUrl = markdocConfigResult
|
|
29
|
+
const userMarkdocConfig = markdocConfigResult?.config ?? {};
|
|
30
|
+
const markdocConfigUrl = markdocConfigResult?.fileUrl;
|
|
32
31
|
let componentConfigByTagMap = {};
|
|
33
32
|
for (const tag of usedTags) {
|
|
34
|
-
const render =
|
|
33
|
+
const render = userMarkdocConfig.tags?.[tag]?.render;
|
|
35
34
|
if (isComponentConfig(render)) {
|
|
36
35
|
componentConfigByTagMap[tag] = render;
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
let componentConfigByNodeMap = {};
|
|
40
39
|
for (const [nodeType, schema] of Object.entries(userMarkdocConfig.nodes ?? {})) {
|
|
41
|
-
const render = schema
|
|
40
|
+
const render = schema?.render;
|
|
42
41
|
if (isComponentConfig(render)) {
|
|
43
42
|
componentConfigByNodeMap[nodeType] = render;
|
|
44
43
|
}
|
|
@@ -74,18 +73,17 @@ async function getContentEntryType({
|
|
|
74
73
|
}
|
|
75
74
|
});
|
|
76
75
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
}
|
|
76
|
+
await emitOptimizedImages(ast.children, {
|
|
77
|
+
astroConfig,
|
|
78
|
+
pluginContext,
|
|
79
|
+
filePath
|
|
80
|
+
});
|
|
84
81
|
const res = `import { Renderer } from '@astrojs/markdoc/components';
|
|
85
82
|
import { createGetHeadings, createContentComponent } from '@astrojs/markdoc/runtime';
|
|
86
|
-
${markdocConfigUrl ? `import markdocConfig from ${JSON.stringify(markdocConfigUrl.pathname)};` : "const markdocConfig = {};"}
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
${markdocConfigUrl ? `import markdocConfig from ${JSON.stringify(markdocConfigUrl.pathname)};` : "const markdocConfig = {};"}
|
|
84
|
+
|
|
85
|
+
import { assetsConfig } from '@astrojs/markdoc/runtime-assets-config';
|
|
86
|
+
markdocConfig.nodes = { ...assetsConfig.nodes, ...markdocConfig.nodes };
|
|
89
87
|
|
|
90
88
|
${getStringifiedImports(componentConfigByTagMap, "Tag", astroConfig.root)}
|
|
91
89
|
${getStringifiedImports(componentConfigByNodeMap, "Node", astroConfig.root)}
|
|
@@ -141,12 +139,11 @@ async function emitOptimizedImages(nodeChildren, ctx) {
|
|
|
141
139
|
for (const node of nodeChildren) {
|
|
142
140
|
if (node.type === "image" && typeof node.attributes.src === "string" && shouldOptimizeImage(node.attributes.src)) {
|
|
143
141
|
const resolved = await ctx.pluginContext.resolve(node.attributes.src, ctx.filePath);
|
|
144
|
-
if (
|
|
142
|
+
if (resolved?.id && fs.existsSync(new URL(prependForwardSlash(resolved.id), "file://"))) {
|
|
145
143
|
const src = await emitESMImage(
|
|
146
144
|
resolved.id,
|
|
147
145
|
ctx.pluginContext.meta.watchMode,
|
|
148
|
-
ctx.pluginContext.emitFile
|
|
149
|
-
{ config: ctx.astroConfig }
|
|
146
|
+
ctx.pluginContext.emitFile
|
|
150
147
|
);
|
|
151
148
|
node.attributes.__optimizedSrc = src;
|
|
152
149
|
} else {
|
package/dist/extensions/prism.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { unescapeHTML } from "astro/runtime/server/index.js";
|
|
2
1
|
import { runHighlighterWithAstro } from "@astrojs/prism/dist/highlighter";
|
|
2
|
+
import { unescapeHTML } from "astro/runtime/server/index.js";
|
|
3
3
|
import { Markdoc } from "../config.js";
|
|
4
4
|
function prism() {
|
|
5
5
|
return {
|
package/dist/extensions/shiki.js
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
import { unescapeHTML } from "astro/runtime/server/index.js";
|
|
2
1
|
import Markdoc from "@markdoc/markdoc";
|
|
2
|
+
import { unescapeHTML } from "astro/runtime/server/index.js";
|
|
3
3
|
import { getHighlighter } from "shiki";
|
|
4
|
-
const compatThemes = {
|
|
5
|
-
"material-darker": "material-theme-darker",
|
|
6
|
-
"material-default": "material-theme",
|
|
7
|
-
"material-lighter": "material-theme-lighter",
|
|
8
|
-
"material-ocean": "material-theme-ocean",
|
|
9
|
-
"material-palenight": "material-theme-palenight"
|
|
10
|
-
};
|
|
11
|
-
const normalizeTheme = (theme) => {
|
|
12
|
-
if (typeof theme === "string") {
|
|
13
|
-
return compatThemes[theme] || theme;
|
|
14
|
-
} else if (compatThemes[theme.name]) {
|
|
15
|
-
return { ...theme, name: compatThemes[theme.name] };
|
|
16
|
-
} else {
|
|
17
|
-
return theme;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
4
|
const ASTRO_COLOR_REPLACEMENTS = {
|
|
21
5
|
"#000001": "var(--astro-code-color-text)",
|
|
22
6
|
"#000002": "var(--astro-code-color-background)",
|
|
@@ -39,7 +23,6 @@ async function shiki({
|
|
|
39
23
|
theme = "github-dark",
|
|
40
24
|
wrap = false
|
|
41
25
|
} = {}) {
|
|
42
|
-
theme = normalizeTheme(theme);
|
|
43
26
|
const cacheID = typeof theme === "string" ? theme : theme.name;
|
|
44
27
|
if (!highlighterCache.has(cacheID)) {
|
|
45
28
|
highlighterCache.set(
|
package/dist/heading-ids.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import Markdoc
|
|
1
|
+
import Markdoc, {
|
|
2
|
+
} from "@markdoc/markdoc";
|
|
2
3
|
import Slugger from "github-slugger";
|
|
3
4
|
import { getTextContent } from "./runtime.js";
|
|
4
5
|
import { MarkdocError } from "./utils.js";
|
|
@@ -19,16 +20,15 @@ const heading = {
|
|
|
19
20
|
level: { type: Number, required: true, default: 1 }
|
|
20
21
|
},
|
|
21
22
|
transform(node, config) {
|
|
22
|
-
var _a, _b, _c;
|
|
23
23
|
const { level, ...attributes } = node.transformAttributes(config);
|
|
24
24
|
const children = node.transformChildren(config);
|
|
25
|
-
if (!
|
|
25
|
+
if (!config.ctx?.headingSlugger) {
|
|
26
26
|
throw new MarkdocError({
|
|
27
27
|
message: "Unexpected problem adding heading IDs to Markdoc file. Did you modify the `ctx.headingSlugger` property in your Markdoc config?"
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
const slug = getSlug(attributes, children, config.ctx.headingSlugger);
|
|
31
|
-
const render =
|
|
31
|
+
const render = config.nodes?.heading?.render ?? `h${level}`;
|
|
32
32
|
const tagProps = (
|
|
33
33
|
// For components, pass down `level` as a prop,
|
|
34
34
|
// alongside `__collectHeading` for our `headings` collector.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Config as MarkdocConfig } from '@markdoc/markdoc';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const assetsConfig: MarkdocConfig;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Markdoc from "@markdoc/markdoc";
|
|
2
2
|
import { Image } from "astro:assets";
|
|
3
|
-
const
|
|
3
|
+
const assetsConfig = {
|
|
4
4
|
nodes: {
|
|
5
5
|
image: {
|
|
6
6
|
attributes: {
|
|
@@ -21,5 +21,5 @@ const experimentalAssetsConfig = {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
export {
|
|
24
|
-
|
|
24
|
+
assetsConfig
|
|
25
25
|
};
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MarkdownHeading } from '@astrojs/markdown-remark';
|
|
2
2
|
import { type NodeType, type RenderableTreeNode } from '@markdoc/markdoc';
|
|
3
3
|
import type { AstroInstance } from 'astro';
|
|
4
|
-
import type
|
|
4
|
+
import { type AstroMarkdocConfig } from './config.js';
|
|
5
5
|
import type { MarkdocIntegrationOptions } from './options.js';
|
|
6
6
|
/**
|
|
7
7
|
* Merge user config with default config and set up context (ex. heading ID slugger)
|
|
@@ -25,5 +25,5 @@ export declare function getTextContent(childNodes: RenderableTreeNode[]): string
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function collectHeadings(children: RenderableTreeNode[], collectedHeadings: MarkdownHeading[]): void;
|
|
27
27
|
export declare function createGetHeadings(stringifiedAst: string, userConfig: AstroMarkdocConfig, options: MarkdocIntegrationOptions | undefined): () => MarkdownHeading[];
|
|
28
|
-
export declare function createContentComponent(Renderer: AstroInstance['default'], stringifiedAst: string, userConfig: AstroMarkdocConfig, options: MarkdocIntegrationOptions | undefined, tagComponentMap: Record<string, AstroInstance['default']>, nodeComponentMap: Record<NodeType, AstroInstance['default']>):
|
|
28
|
+
export declare function createContentComponent(Renderer: AstroInstance['default'], stringifiedAst: string, userConfig: AstroMarkdocConfig, options: MarkdocIntegrationOptions | undefined, tagComponentMap: Record<string, AstroInstance['default']>, nodeComponentMap: Record<NodeType, AstroInstance['default']>): import("astro/runtime/server/index.js").AstroComponentFactory;
|
|
29
29
|
export {};
|
package/dist/runtime.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import Markdoc
|
|
1
|
+
import Markdoc, {
|
|
2
|
+
} from "@markdoc/markdoc";
|
|
2
3
|
import { createComponent, renderComponent } from "astro/runtime/server/index.js";
|
|
4
|
+
import {} from "./config.js";
|
|
3
5
|
import { setupHeadingConfig } from "./heading-ids.js";
|
|
4
6
|
import { htmlTag } from "./html/tagdefs/html.tag.js";
|
|
5
7
|
async function setupConfig(userConfig = {}, options) {
|
|
@@ -13,7 +15,7 @@ async function setupConfig(userConfig = {}, options) {
|
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
17
|
let merged = mergeConfig(defaultConfig, userConfig);
|
|
16
|
-
if (options
|
|
18
|
+
if (options?.allowHTML) {
|
|
17
19
|
merged = mergeConfig(merged, HTML_CONFIG);
|
|
18
20
|
}
|
|
19
21
|
return merged;
|
|
@@ -21,7 +23,7 @@ async function setupConfig(userConfig = {}, options) {
|
|
|
21
23
|
function setupConfigSync(userConfig = {}, options) {
|
|
22
24
|
const defaultConfig = setupHeadingConfig();
|
|
23
25
|
let merged = mergeConfig(defaultConfig, userConfig);
|
|
24
|
-
if (options
|
|
26
|
+
if (options?.allowHTML) {
|
|
25
27
|
merged = mergeConfig(merged, HTML_CONFIG);
|
|
26
28
|
}
|
|
27
29
|
return merged;
|
package/dist/tokenizer.js
CHANGED
|
@@ -7,7 +7,7 @@ function getMarkdocTokenizer(options) {
|
|
|
7
7
|
// Without this, they're rendered as strings!
|
|
8
8
|
allowComments: true
|
|
9
9
|
};
|
|
10
|
-
if (options
|
|
10
|
+
if (options?.allowHTML) {
|
|
11
11
|
tokenizerOptions.allowIndentation = true;
|
|
12
12
|
tokenizerOptions.html = true;
|
|
13
13
|
}
|
package/dist/utils.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
class MarkdocError extends Error {
|
|
2
|
+
loc;
|
|
3
|
+
title;
|
|
4
|
+
hint;
|
|
5
|
+
frame;
|
|
6
|
+
type = "MarkdocError";
|
|
2
7
|
constructor(props, ...params) {
|
|
3
8
|
super(...params);
|
|
4
|
-
this.type = "MarkdocError";
|
|
5
9
|
const { title = "MarkdocError", message, stack, location, hint, frame } = props;
|
|
6
10
|
this.title = title;
|
|
7
11
|
if (message)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/markdoc",
|
|
3
3
|
"description": "Add support for Markdoc in your Astro site",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "withastro",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
".": "./dist/index.js",
|
|
35
35
|
"./components": "./components/index.ts",
|
|
36
36
|
"./runtime": "./dist/runtime.js",
|
|
37
|
-
"./
|
|
37
|
+
"./runtime-assets-config": "./dist/runtime-assets-config.js",
|
|
38
38
|
"./package.json": "./package.json"
|
|
39
39
|
},
|
|
40
40
|
"typesVersions": {
|
|
@@ -56,37 +56,37 @@
|
|
|
56
56
|
"template"
|
|
57
57
|
],
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@astrojs/internal-helpers": "^0.1.0",
|
|
60
|
-
"@astrojs/prism": "^2.1.2",
|
|
61
59
|
"@markdoc/markdoc": "^0.3.0",
|
|
62
|
-
"esbuild": "^0.
|
|
60
|
+
"esbuild": "^0.19.2",
|
|
63
61
|
"github-slugger": "^2.0.0",
|
|
64
62
|
"gray-matter": "^4.0.3",
|
|
65
63
|
"htmlparser2": "^9.0.0",
|
|
66
64
|
"kleur": "^4.1.5",
|
|
67
|
-
"shiki": "^0.14.
|
|
68
|
-
"zod": "
|
|
65
|
+
"shiki": "^0.14.3",
|
|
66
|
+
"zod": "3.21.1",
|
|
67
|
+
"@astrojs/internal-helpers": "0.2.0",
|
|
68
|
+
"@astrojs/prism": "3.0.0"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"astro": "^
|
|
71
|
+
"astro": "^3.0.0"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@astrojs/markdown-remark": "^2.2.1",
|
|
75
74
|
"@types/chai": "^4.3.5",
|
|
76
75
|
"@types/html-escaper": "^3.0.0",
|
|
77
|
-
"@types/markdown-it": "^
|
|
78
|
-
"@types/mocha": "^
|
|
76
|
+
"@types/markdown-it": "^13.0.0",
|
|
77
|
+
"@types/mocha": "^10.0.1",
|
|
79
78
|
"chai": "^4.3.7",
|
|
80
79
|
"devalue": "^4.3.2",
|
|
81
|
-
"linkedom": "^0.
|
|
82
|
-
"mocha": "^
|
|
83
|
-
"rollup": "^3.
|
|
84
|
-
"vite": "^4.4.
|
|
85
|
-
"
|
|
80
|
+
"linkedom": "^0.15.1",
|
|
81
|
+
"mocha": "^10.2.0",
|
|
82
|
+
"rollup": "^3.28.1",
|
|
83
|
+
"vite": "^4.4.9",
|
|
84
|
+
"@astrojs/markdown-remark": "3.0.0",
|
|
85
|
+
"astro": "3.0.0",
|
|
86
86
|
"astro-scripts": "0.0.14"
|
|
87
87
|
},
|
|
88
88
|
"engines": {
|
|
89
|
-
"node": ">=
|
|
89
|
+
"node": ">=18.14.1"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
92
|
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
|