@astrojs/markdoc 0.0.3 → 0.0.4
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/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +18 -0
- package/README.md +17 -3
- package/components/Renderer.astro +2 -3
- package/components/TreeNode.ts +82 -0
- package/dist/index.js +21 -33
- package/package.json +2 -3
- package/src/index.ts +17 -32
- package/test/entry-prop.test.js +58 -0
- package/test/fixtures/entry-prop/astro.config.mjs +7 -0
- package/test/fixtures/entry-prop/node_modules/.bin/astro +17 -0
- package/test/fixtures/entry-prop/package.json +9 -0
- package/test/fixtures/entry-prop/src/content/blog/entry.mdoc +9 -0
- package/test/fixtures/entry-prop/src/content/config.ts +9 -0
- package/test/fixtures/entry-prop/src/pages/index.astro +19 -0
- package/components/RenderNode.astro +0 -30
- package/components/astroNode.ts +0 -51
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
[
|
|
2
|
-
[
|
|
3
|
-
[
|
|
4
|
-
[
|
|
5
|
-
[
|
|
1
|
+
[33m@astrojs/markdoc:build: [0mcache hit, replaying output [2ma6e7d1873a50f12c[0m
|
|
2
|
+
[33m@astrojs/markdoc:build: [0m
|
|
3
|
+
[33m@astrojs/markdoc:build: [0m> @astrojs/markdoc@0.0.4 build /home/runner/work/astro/astro/packages/integrations/markdoc
|
|
4
|
+
[33m@astrojs/markdoc:build: [0m> astro-scripts build "src/**/*.ts" && tsc
|
|
5
|
+
[33m@astrojs/markdoc:build: [0m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @astrojs/markdoc
|
|
2
2
|
|
|
3
|
+
## 0.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#6588](https://github.com/withastro/astro/pull/6588) [`f42f47dc6`](https://github.com/withastro/astro/commit/f42f47dc6a91cdb6534dab0ecbf9e8e85f00ba40) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Allow access to content collection entry information (including parsed frontmatter and the entry slug) from your Markdoc using the `$entry` variable:
|
|
8
|
+
|
|
9
|
+
```mdx
|
|
10
|
+
---
|
|
11
|
+
title: Hello Markdoc!
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# {% $entry.data.title %}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- [#6607](https://github.com/withastro/astro/pull/6607) [`86273b588`](https://github.com/withastro/astro/commit/86273b5881cc61ebee11d40280b4c0aba8f4bb2e) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: Update Markdoc renderer internals to remove unneeded dependencies
|
|
18
|
+
|
|
19
|
+
- [#6622](https://github.com/withastro/astro/pull/6622) [`b37b86540`](https://github.com/withastro/astro/commit/b37b865400e77e92878d7e150244acce47e933c6) Thanks [@paulrudy](https://github.com/paulrudy)! - Fix README instructions for installing Markdoc manually.
|
|
20
|
+
|
|
3
21
|
## 0.0.3
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -237,6 +237,20 @@ const { Content } = await entry.render();
|
|
|
237
237
|
/>
|
|
238
238
|
```
|
|
239
239
|
|
|
240
|
+
### Access frontmatter and content collection information from your templates
|
|
241
|
+
|
|
242
|
+
You can access content collection information from your Markdoc templates using the `$entry` variable. This includes the entry `slug`, `collection` name, and frontmatter `data` parsed by your content collection schema (if any). This example renders the `title` frontmatter property as a heading:
|
|
243
|
+
|
|
244
|
+
```md
|
|
245
|
+
---
|
|
246
|
+
title: Welcome to Markdoc 👋
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
# {% $entry.data.title %}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The `$entry` object matches [the `CollectionEntry` type](https://docs.astro.build/en/reference/api-reference/#collection-entry-type), excluding the `.render()` property.
|
|
253
|
+
|
|
240
254
|
### Markdoc config
|
|
241
255
|
|
|
242
256
|
The Markdoc integration accepts [all Markdoc configuration options](https://markdoc.dev/docs/config), including [tags](https://markdoc.dev/docs/tags) and [functions](https://markdoc.dev/docs/functions).
|
|
@@ -292,11 +306,11 @@ You will need to install the `@markdoc/markdoc` package into your project first:
|
|
|
292
306
|
|
|
293
307
|
```sh
|
|
294
308
|
# Using NPM
|
|
295
|
-
|
|
309
|
+
npm install @markdoc/markdoc
|
|
296
310
|
# Using Yarn
|
|
297
|
-
yarn
|
|
311
|
+
yarn add @markdoc/markdoc
|
|
298
312
|
# Using PNPM
|
|
299
|
-
pnpm
|
|
313
|
+
pnpm add @markdoc/markdoc
|
|
300
314
|
```
|
|
301
315
|
|
|
302
316
|
Now, you can define Markdoc configuration options using `Markdock.transform()`.
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
|
3
3
|
import type { AstroInstance } from 'astro';
|
|
4
4
|
import { validateComponentsProp } from '../dist/utils.js';
|
|
5
|
-
import {
|
|
6
|
-
import RenderNode from './RenderNode.astro';
|
|
5
|
+
import { ComponentNode, createTreeNode } from './TreeNode.js';
|
|
7
6
|
|
|
8
7
|
type Props = {
|
|
9
8
|
content: RenderableTreeNode;
|
|
@@ -18,4 +17,4 @@ if (components) {
|
|
|
18
17
|
}
|
|
19
18
|
---
|
|
20
19
|
|
|
21
|
-
<
|
|
20
|
+
<ComponentNode treeNode={createTreeNode(content, components)} />
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { AstroInstance } from 'astro';
|
|
2
|
+
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
|
3
|
+
import { createComponent, renderComponent, render } from 'astro/runtime/server/index.js';
|
|
4
|
+
import Markdoc from '@markdoc/markdoc';
|
|
5
|
+
import { MarkdocError, isCapitalized } from '../dist/utils.js';
|
|
6
|
+
|
|
7
|
+
export type TreeNode =
|
|
8
|
+
| {
|
|
9
|
+
type: 'text';
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
| {
|
|
13
|
+
type: 'component';
|
|
14
|
+
component: AstroInstance['default'];
|
|
15
|
+
props: Record<string, any>;
|
|
16
|
+
children: TreeNode[];
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
type: 'element';
|
|
20
|
+
tag: string;
|
|
21
|
+
attributes: Record<string, any>;
|
|
22
|
+
children: TreeNode[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const ComponentNode = createComponent({
|
|
26
|
+
factory(result: any, { treeNode }: { treeNode: TreeNode }) {
|
|
27
|
+
if (treeNode.type === 'text') return render`${treeNode.content}`;
|
|
28
|
+
const slots = {
|
|
29
|
+
default: () =>
|
|
30
|
+
render`${treeNode.children.map((child) =>
|
|
31
|
+
renderComponent(result, 'ComponentNode', ComponentNode, { treeNode: child })
|
|
32
|
+
)}`,
|
|
33
|
+
};
|
|
34
|
+
if (treeNode.type === 'component') {
|
|
35
|
+
return renderComponent(
|
|
36
|
+
result,
|
|
37
|
+
treeNode.component.name,
|
|
38
|
+
treeNode.component,
|
|
39
|
+
treeNode.props,
|
|
40
|
+
slots
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return renderComponent(result, treeNode.tag, treeNode.tag, treeNode.attributes, slots);
|
|
44
|
+
},
|
|
45
|
+
propagation: 'none',
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export function createTreeNode(
|
|
49
|
+
node: RenderableTreeNode,
|
|
50
|
+
components: Record<string, AstroInstance['default']> = {}
|
|
51
|
+
): TreeNode {
|
|
52
|
+
if (typeof node === 'string' || typeof node === 'number') {
|
|
53
|
+
return { type: 'text', content: String(node) };
|
|
54
|
+
} else if (node === null || typeof node !== 'object' || !Markdoc.Tag.isTag(node)) {
|
|
55
|
+
return { type: 'text', content: '' };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (node.name in components) {
|
|
59
|
+
const component = components[node.name];
|
|
60
|
+
const props = node.attributes;
|
|
61
|
+
const children = node.children.map((child) => createTreeNode(child, components));
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
type: 'component',
|
|
65
|
+
component,
|
|
66
|
+
props,
|
|
67
|
+
children,
|
|
68
|
+
};
|
|
69
|
+
} else if (isCapitalized(node.name)) {
|
|
70
|
+
throw new MarkdocError({
|
|
71
|
+
message: `Unable to render ${JSON.stringify(node.name)}.`,
|
|
72
|
+
hint: 'Did you add this to the "components" prop on your <Content /> component?',
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
return {
|
|
76
|
+
type: 'element',
|
|
77
|
+
tag: node.name,
|
|
78
|
+
attributes: node.attributes,
|
|
79
|
+
children: node.children.map((child) => createTreeNode(child, components)),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import Markdoc from "@markdoc/markdoc";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import {
|
|
5
|
-
getAstroConfigPath,
|
|
6
|
-
MarkdocError,
|
|
7
|
-
parseFrontmatter,
|
|
8
|
-
prependForwardSlash
|
|
9
|
-
} from "./utils.js";
|
|
4
|
+
import { getAstroConfigPath, MarkdocError, parseFrontmatter } from "./utils.js";
|
|
10
5
|
function markdoc(markdocConfig = {}) {
|
|
11
6
|
return {
|
|
12
7
|
name: "@astrojs/markdoc",
|
|
@@ -25,38 +20,31 @@ function markdoc(markdocConfig = {}) {
|
|
|
25
20
|
addContentEntryType({
|
|
26
21
|
extensions: [".mdoc"],
|
|
27
22
|
getEntryInfo,
|
|
23
|
+
getRenderModule({ entry }) {
|
|
24
|
+
validateRenderProperties(markdocConfig, config);
|
|
25
|
+
const ast = Markdoc.parse(entry.body);
|
|
26
|
+
const content = Markdoc.transform(ast, {
|
|
27
|
+
...markdocConfig,
|
|
28
|
+
variables: {
|
|
29
|
+
...markdocConfig.variables,
|
|
30
|
+
entry
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
code: `import { jsx as h } from 'astro/jsx-runtime';
|
|
35
|
+
import { Renderer } from '@astrojs/markdoc/components';
|
|
36
|
+
const transformedContent = ${JSON.stringify(
|
|
37
|
+
content
|
|
38
|
+
)};
|
|
39
|
+
export async function Content ({ components }) { return h(Renderer, { content: transformedContent, components }); }
|
|
40
|
+
Content[Symbol.for('astro.needsHeadRendering')] = true;`
|
|
41
|
+
};
|
|
42
|
+
},
|
|
28
43
|
contentModuleTypes: await fs.promises.readFile(
|
|
29
44
|
new URL("../template/content-module-types.d.ts", import.meta.url),
|
|
30
45
|
"utf-8"
|
|
31
46
|
)
|
|
32
47
|
});
|
|
33
|
-
const viteConfig = {
|
|
34
|
-
plugins: [
|
|
35
|
-
{
|
|
36
|
-
name: "@astrojs/markdoc",
|
|
37
|
-
async transform(code, id) {
|
|
38
|
-
if (!id.endsWith(".mdoc"))
|
|
39
|
-
return;
|
|
40
|
-
validateRenderProperties(markdocConfig, config);
|
|
41
|
-
const body = getEntryInfo({
|
|
42
|
-
// Can't use `pathToFileUrl` - Vite IDs are not plain file paths
|
|
43
|
-
fileUrl: new URL(prependForwardSlash(id), "file://"),
|
|
44
|
-
contents: code
|
|
45
|
-
}).body;
|
|
46
|
-
const ast = Markdoc.parse(body);
|
|
47
|
-
const content = Markdoc.transform(ast, markdocConfig);
|
|
48
|
-
return `import { jsx as h } from 'astro/jsx-runtime';
|
|
49
|
-
import { Renderer } from '@astrojs/markdoc/components';
|
|
50
|
-
const transformedContent = ${JSON.stringify(
|
|
51
|
-
content
|
|
52
|
-
)};
|
|
53
|
-
export async function Content ({ components }) { return h(Renderer, { content: transformedContent, components }); }
|
|
54
|
-
Content[Symbol.for('astro.needsHeadRendering')] = true;`;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
};
|
|
59
|
-
updateConfig({ vite: viteConfig });
|
|
60
48
|
}
|
|
61
49
|
}
|
|
62
50
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/markdoc",
|
|
3
3
|
"description": "Add support for Markdoc pages in your Astro site",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "withastro",
|
|
@@ -26,14 +26,13 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@markdoc/markdoc": "^0.2.2",
|
|
28
28
|
"gray-matter": "^4.0.3",
|
|
29
|
-
"stringify-attributes": "^3.0.0",
|
|
30
29
|
"zod": "^3.17.3"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"@types/chai": "^4.3.1",
|
|
34
33
|
"@types/html-escaper": "^3.0.0",
|
|
35
34
|
"@types/mocha": "^9.1.1",
|
|
36
|
-
"astro": "2.1.
|
|
35
|
+
"astro": "2.1.5",
|
|
37
36
|
"astro-scripts": "0.0.14",
|
|
38
37
|
"chai": "^4.3.6",
|
|
39
38
|
"devalue": "^4.2.0",
|
package/src/index.ts
CHANGED
|
@@ -3,13 +3,7 @@ import Markdoc from '@markdoc/markdoc';
|
|
|
3
3
|
import type { AstroConfig, AstroIntegration, ContentEntryType, HookParameters } from 'astro';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
getAstroConfigPath,
|
|
9
|
-
MarkdocError,
|
|
10
|
-
parseFrontmatter,
|
|
11
|
-
prependForwardSlash,
|
|
12
|
-
} from './utils.js';
|
|
6
|
+
import { getAstroConfigPath, MarkdocError, parseFrontmatter } from './utils.js';
|
|
13
7
|
|
|
14
8
|
type SetupHookParams = HookParameters<'astro:config:setup'> & {
|
|
15
9
|
// `contentEntryType` is not a public API
|
|
@@ -36,36 +30,27 @@ export default function markdoc(markdocConfig: Config = {}): AstroIntegration {
|
|
|
36
30
|
addContentEntryType({
|
|
37
31
|
extensions: ['.mdoc'],
|
|
38
32
|
getEntryInfo,
|
|
33
|
+
getRenderModule({ entry }) {
|
|
34
|
+
validateRenderProperties(markdocConfig, config);
|
|
35
|
+
const ast = Markdoc.parse(entry.body);
|
|
36
|
+
const content = Markdoc.transform(ast, {
|
|
37
|
+
...markdocConfig,
|
|
38
|
+
variables: {
|
|
39
|
+
...markdocConfig.variables,
|
|
40
|
+
entry,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
code: `import { jsx as h } from 'astro/jsx-runtime';\nimport { Renderer } from '@astrojs/markdoc/components';\nconst transformedContent = ${JSON.stringify(
|
|
45
|
+
content
|
|
46
|
+
)};\nexport async function Content ({ components }) { return h(Renderer, { content: transformedContent, components }); }\nContent[Symbol.for('astro.needsHeadRendering')] = true;`,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
39
49
|
contentModuleTypes: await fs.promises.readFile(
|
|
40
50
|
new URL('../template/content-module-types.d.ts', import.meta.url),
|
|
41
51
|
'utf-8'
|
|
42
52
|
),
|
|
43
53
|
});
|
|
44
|
-
|
|
45
|
-
const viteConfig: InlineConfig = {
|
|
46
|
-
plugins: [
|
|
47
|
-
{
|
|
48
|
-
name: '@astrojs/markdoc',
|
|
49
|
-
async transform(code, id) {
|
|
50
|
-
if (!id.endsWith('.mdoc')) return;
|
|
51
|
-
|
|
52
|
-
validateRenderProperties(markdocConfig, config);
|
|
53
|
-
const body = getEntryInfo({
|
|
54
|
-
// Can't use `pathToFileUrl` - Vite IDs are not plain file paths
|
|
55
|
-
fileUrl: new URL(prependForwardSlash(id), 'file://'),
|
|
56
|
-
contents: code,
|
|
57
|
-
}).body;
|
|
58
|
-
const ast = Markdoc.parse(body);
|
|
59
|
-
const content = Markdoc.transform(ast, markdocConfig);
|
|
60
|
-
|
|
61
|
-
return `import { jsx as h } from 'astro/jsx-runtime';\nimport { Renderer } from '@astrojs/markdoc/components';\nconst transformedContent = ${JSON.stringify(
|
|
62
|
-
content
|
|
63
|
-
)};\nexport async function Content ({ components }) { return h(Renderer, { content: transformedContent, components }); }\nContent[Symbol.for('astro.needsHeadRendering')] = true;`;
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
};
|
|
68
|
-
updateConfig({ vite: viteConfig });
|
|
69
54
|
},
|
|
70
55
|
},
|
|
71
56
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { parseHTML } from 'linkedom';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
4
|
+
import markdoc from '../dist/index.js';
|
|
5
|
+
|
|
6
|
+
const root = new URL('./fixtures/entry-prop/', import.meta.url);
|
|
7
|
+
|
|
8
|
+
describe('Markdoc - Entry prop', () => {
|
|
9
|
+
let baseFixture;
|
|
10
|
+
|
|
11
|
+
before(async () => {
|
|
12
|
+
baseFixture = await loadFixture({
|
|
13
|
+
root,
|
|
14
|
+
integrations: [markdoc()],
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('dev', () => {
|
|
19
|
+
let devServer;
|
|
20
|
+
|
|
21
|
+
before(async () => {
|
|
22
|
+
devServer = await baseFixture.startDevServer();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
after(async () => {
|
|
26
|
+
await devServer.stop();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('has expected entry properties', async () => {
|
|
30
|
+
const res = await baseFixture.fetch('/');
|
|
31
|
+
const html = await res.text();
|
|
32
|
+
const { document } = parseHTML(html);
|
|
33
|
+
expect(document.querySelector('h1')?.textContent).to.equal('Processed by schema: Test entry');
|
|
34
|
+
expect(document.getElementById('id')?.textContent?.trim()).to.equal('id: entry.mdoc');
|
|
35
|
+
expect(document.getElementById('slug')?.textContent?.trim()).to.equal('slug: entry');
|
|
36
|
+
expect(document.getElementById('collection')?.textContent?.trim()).to.equal(
|
|
37
|
+
'collection: blog'
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('build', () => {
|
|
43
|
+
before(async () => {
|
|
44
|
+
await baseFixture.build();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('has expected entry properties', async () => {
|
|
48
|
+
const html = await baseFixture.readFile('/index.html');
|
|
49
|
+
const { document } = parseHTML(html);
|
|
50
|
+
expect(document.querySelector('h1')?.textContent).to.equal('Processed by schema: Test entry');
|
|
51
|
+
expect(document.getElementById('id')?.textContent?.trim()).to.equal('id: entry.mdoc');
|
|
52
|
+
expect(document.getElementById('slug')?.textContent?.trim()).to.equal('slug: entry');
|
|
53
|
+
expect(document.getElementById('collection')?.textContent?.trim()).to.equal(
|
|
54
|
+
'collection: blog'
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
+
|
|
4
|
+
case `uname` in
|
|
5
|
+
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
|
6
|
+
esac
|
|
7
|
+
|
|
8
|
+
if [ -z "$NODE_PATH" ]; then
|
|
9
|
+
export NODE_PATH="/home/runner/work/astro/astro/node_modules/.pnpm/node_modules"
|
|
10
|
+
else
|
|
11
|
+
export NODE_PATH="$NODE_PATH:/home/runner/work/astro/astro/node_modules/.pnpm/node_modules"
|
|
12
|
+
fi
|
|
13
|
+
if [ -x "$basedir/node" ]; then
|
|
14
|
+
exec "$basedir/node" "$basedir/../../../../../../../astro/astro.js" "$@"
|
|
15
|
+
else
|
|
16
|
+
exec node "$basedir/../../../../../../../astro/astro.js" "$@"
|
|
17
|
+
fi
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getEntryBySlug } from 'astro:content';
|
|
3
|
+
|
|
4
|
+
const entry = await getEntryBySlug('blog', 'entry');
|
|
5
|
+
const { Content } = await entry.render();
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<html lang="en">
|
|
9
|
+
<head>
|
|
10
|
+
<meta charset="utf-8" />
|
|
11
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
12
|
+
<meta name="viewport" content="width=device-width" />
|
|
13
|
+
<meta name="generator" content={Astro.generator} />
|
|
14
|
+
<title>Astro</title>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<Content />
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
import stringifyAttributes from 'stringify-attributes';
|
|
3
|
-
import type { AstroNode } from './astroNode';
|
|
4
|
-
|
|
5
|
-
type Props = {
|
|
6
|
-
node: AstroNode;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const Node = (Astro.props as Props).node;
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
typeof Node === 'string' ? (
|
|
14
|
-
<Fragment set:text={Node} />
|
|
15
|
-
) : 'component' in Node ? (
|
|
16
|
-
<Node.component {...Node.props}>
|
|
17
|
-
{Node.children.map((child) => (
|
|
18
|
-
<Astro.self node={child} />
|
|
19
|
-
))}
|
|
20
|
-
</Node.component>
|
|
21
|
-
) : (
|
|
22
|
-
<Fragment>
|
|
23
|
-
<Fragment set:html={`<${Node.tag} ${stringifyAttributes(Node.attributes)}>`} />
|
|
24
|
-
{Node.children.map((child) => (
|
|
25
|
-
<Astro.self node={child} />
|
|
26
|
-
))}
|
|
27
|
-
<Fragment set:html={`</${Node.tag}>`} />
|
|
28
|
-
</Fragment>
|
|
29
|
-
)
|
|
30
|
-
}
|
package/components/astroNode.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { AstroInstance } from 'astro';
|
|
2
|
-
import type { RenderableTreeNode } from '@markdoc/markdoc';
|
|
3
|
-
import Markdoc from '@markdoc/markdoc';
|
|
4
|
-
import { MarkdocError, isCapitalized } from '../dist/utils.js';
|
|
5
|
-
|
|
6
|
-
export type AstroNode =
|
|
7
|
-
| string
|
|
8
|
-
| {
|
|
9
|
-
component: AstroInstance['default'];
|
|
10
|
-
props: Record<string, any>;
|
|
11
|
-
children: AstroNode[];
|
|
12
|
-
}
|
|
13
|
-
| {
|
|
14
|
-
tag: string;
|
|
15
|
-
attributes: Record<string, any>;
|
|
16
|
-
children: AstroNode[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export function createAstroNode(
|
|
20
|
-
node: RenderableTreeNode,
|
|
21
|
-
components: Record<string, AstroInstance['default']> = {}
|
|
22
|
-
): AstroNode {
|
|
23
|
-
if (typeof node === 'string' || typeof node === 'number') {
|
|
24
|
-
return String(node);
|
|
25
|
-
} else if (node === null || typeof node !== 'object' || !Markdoc.Tag.isTag(node)) {
|
|
26
|
-
return '';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (node.name in components) {
|
|
30
|
-
const component = components[node.name];
|
|
31
|
-
const props = node.attributes;
|
|
32
|
-
const children = node.children.map((child) => createAstroNode(child, components));
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
component,
|
|
36
|
-
props,
|
|
37
|
-
children,
|
|
38
|
-
};
|
|
39
|
-
} else if (isCapitalized(node.name)) {
|
|
40
|
-
throw new MarkdocError({
|
|
41
|
-
message: `Unable to render ${JSON.stringify(node.name)}.`,
|
|
42
|
-
hint: 'Did you add this to the "components" prop on your <Content /> component?',
|
|
43
|
-
});
|
|
44
|
-
} else {
|
|
45
|
-
return {
|
|
46
|
-
tag: node.name,
|
|
47
|
-
attributes: node.attributes,
|
|
48
|
-
children: node.children.map((child) => createAstroNode(child, components)),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
}
|