@astrojs/markdoc 0.0.4 → 0.1.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.
Files changed (60) hide show
  1. package/.turbo/turbo-build.log +5 -5
  2. package/CHANGELOG.md +66 -0
  3. package/README.md +110 -146
  4. package/components/Renderer.astro +8 -11
  5. package/components/TreeNode.ts +6 -15
  6. package/dist/config.d.ts +2 -0
  7. package/dist/config.js +6 -0
  8. package/dist/default-config.d.ts +5 -0
  9. package/dist/default-config.js +13 -0
  10. package/dist/experimental-assets-config.d.ts +2 -0
  11. package/dist/experimental-assets-config.js +25 -0
  12. package/dist/index.d.ts +1 -2
  13. package/dist/index.js +74 -53
  14. package/dist/load-config.d.ts +14 -0
  15. package/dist/load-config.js +82 -0
  16. package/dist/utils.d.ts +1 -11
  17. package/dist/utils.js +7 -41
  18. package/package.json +11 -2
  19. package/src/config.ts +5 -0
  20. package/src/default-config.ts +18 -0
  21. package/src/experimental-assets-config.ts +29 -0
  22. package/src/index.ts +116 -59
  23. package/src/load-config.ts +102 -0
  24. package/src/utils.ts +5 -54
  25. package/template/content-module-types.d.ts +1 -3
  26. package/test/content-collections.test.js +24 -172
  27. package/test/fixtures/content-collections/package.json +0 -4
  28. package/test/fixtures/content-collections/src/content/blog/post-1.mdoc +7 -0
  29. package/test/fixtures/content-collections/src/content/blog/post-2.mdoc +7 -0
  30. package/test/fixtures/content-collections/src/content/blog/post-3.mdoc +7 -0
  31. package/test/fixtures/content-collections/src/pages/entry.json.js +1 -1
  32. package/test/fixtures/image-assets/astro.config.mjs +10 -0
  33. package/test/fixtures/image-assets/node_modules/.bin/astro +17 -0
  34. package/test/fixtures/image-assets/package.json +9 -0
  35. package/test/fixtures/image-assets/src/assets/alias/cityscape.jpg +0 -0
  36. package/test/fixtures/image-assets/src/assets/relative/oar.jpg +0 -0
  37. package/test/fixtures/image-assets/src/content/docs/intro.mdoc +7 -0
  38. package/test/fixtures/image-assets/src/pages/index.astro +19 -0
  39. package/test/fixtures/image-assets/src/public/favicon.svg +9 -0
  40. package/test/fixtures/render-simple/astro.config.mjs +7 -0
  41. package/test/fixtures/render-simple/node_modules/.bin/astro +17 -0
  42. package/test/fixtures/render-simple/package.json +9 -0
  43. package/test/fixtures/{content-collections/src/pages/content-simple.astro → render-simple/src/pages/index.astro} +2 -1
  44. package/test/fixtures/render-with-components/astro.config.mjs +7 -0
  45. package/test/fixtures/render-with-components/markdoc.config.mjs +28 -0
  46. package/test/fixtures/render-with-components/node_modules/.bin/astro +17 -0
  47. package/test/fixtures/render-with-components/package.json +12 -0
  48. package/test/fixtures/{content-collections/src/pages/content-with-components.astro → render-with-components/src/pages/index.astro} +2 -6
  49. package/test/fixtures/render-with-config/astro.config.mjs +7 -0
  50. package/test/fixtures/render-with-config/markdoc.config.mjs +15 -0
  51. package/test/fixtures/render-with-config/node_modules/.bin/astro +17 -0
  52. package/test/fixtures/render-with-config/package.json +9 -0
  53. package/test/fixtures/{content-collections → render-with-config}/src/content/blog/with-config.mdoc +4 -0
  54. package/test/fixtures/{content-collections/src/pages/content-with-config.astro → render-with-config/src/pages/index.astro} +2 -2
  55. package/test/image-assets.test.js +76 -0
  56. package/test/render.test.js +124 -0
  57. /package/test/fixtures/{content-collections → render-simple}/src/content/blog/simple.mdoc +0 -0
  58. /package/test/fixtures/{content-collections → render-with-components}/src/components/Code.astro +0 -0
  59. /package/test/fixtures/{content-collections → render-with-components}/src/components/CustomMarquee.astro +0 -0
  60. /package/test/fixtures/{content-collections → render-with-components}/src/content/blog/with-components.mdoc +0 -0
@@ -0,0 +1,102 @@
1
+ import type { Config as MarkdocConfig } from '@markdoc/markdoc';
2
+ import type { AstroConfig } from 'astro';
3
+ import { build as esbuild } from 'esbuild';
4
+ import * as fs from 'node:fs';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const SUPPORTED_MARKDOC_CONFIG_FILES = [
8
+ 'markdoc.config.js',
9
+ 'markdoc.config.mjs',
10
+ 'markdoc.config.mts',
11
+ 'markdoc.config.ts',
12
+ ];
13
+
14
+ export async function loadMarkdocConfig(astroConfig: Pick<AstroConfig, 'root'>) {
15
+ let markdocConfigUrl: URL | undefined;
16
+ for (const filename of SUPPORTED_MARKDOC_CONFIG_FILES) {
17
+ const filePath = new URL(filename, astroConfig.root);
18
+ if (!fs.existsSync(filePath)) continue;
19
+
20
+ markdocConfigUrl = filePath;
21
+ break;
22
+ }
23
+ if (!markdocConfigUrl) return;
24
+
25
+ const { code, dependencies } = await bundleConfigFile({
26
+ markdocConfigUrl,
27
+ astroConfig,
28
+ });
29
+ const config: MarkdocConfig = await loadConfigFromBundledFile(astroConfig.root, code);
30
+
31
+ return {
32
+ config,
33
+ fileUrl: markdocConfigUrl,
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Forked from Vite's `bundleConfigFile` function
39
+ * with added handling for `.astro` imports,
40
+ * and removed unused Deno patches.
41
+ * @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L961
42
+ */
43
+ async function bundleConfigFile({
44
+ markdocConfigUrl,
45
+ astroConfig,
46
+ }: {
47
+ markdocConfigUrl: URL;
48
+ astroConfig: Pick<AstroConfig, 'root'>;
49
+ }): Promise<{ code: string; dependencies: string[] }> {
50
+ const result = await esbuild({
51
+ absWorkingDir: fileURLToPath(astroConfig.root),
52
+ entryPoints: [fileURLToPath(markdocConfigUrl)],
53
+ outfile: 'out.js',
54
+ write: false,
55
+ target: ['node16'],
56
+ platform: 'node',
57
+ packages: 'external',
58
+ bundle: true,
59
+ format: 'esm',
60
+ sourcemap: 'inline',
61
+ metafile: true,
62
+ plugins: [
63
+ {
64
+ name: 'stub-astro-imports',
65
+ setup(build) {
66
+ build.onResolve({ filter: /.*\.astro$/ }, () => {
67
+ return {
68
+ // Stub with an unused default export
69
+ path: 'data:text/javascript,export default true',
70
+ external: true,
71
+ };
72
+ });
73
+ },
74
+ },
75
+ ],
76
+ });
77
+ const { text } = result.outputFiles[0];
78
+ return {
79
+ code: text,
80
+ dependencies: result.metafile ? Object.keys(result.metafile.inputs) : [],
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Forked from Vite config loader, replacing CJS-based path concat
86
+ * with ESM only
87
+ * @see https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts#L1074
88
+ */
89
+ async function loadConfigFromBundledFile(root: URL, code: string): Promise<MarkdocConfig> {
90
+ // Write it to disk, load it with native Node ESM, then delete the file.
91
+ const tmpFileUrl = new URL(`markdoc.config.timestamp-${Date.now()}.mjs`, root);
92
+ fs.writeFileSync(tmpFileUrl, code);
93
+ try {
94
+ return (await import(tmpFileUrl.pathname)).default;
95
+ } finally {
96
+ try {
97
+ fs.unlinkSync(tmpFileUrl);
98
+ } catch {
99
+ // already removed if this function is called twice simultaneously
100
+ }
101
+ }
102
+ }
package/src/utils.ts CHANGED
@@ -1,8 +1,4 @@
1
- import type { AstroInstance } from 'astro';
2
- import z from 'astro/zod';
3
1
  import matter from 'gray-matter';
4
- import type fsMod from 'node:fs';
5
- import path from 'node:path';
6
2
  import type { ErrorPayload as ViteErrorPayload } from 'vite';
7
3
 
8
4
  /**
@@ -85,28 +81,6 @@ interface ErrorProperties {
85
81
  frame?: string;
86
82
  }
87
83
 
88
- /**
89
- * Matches `search` function used for resolving `astro.config` files.
90
- * Used by Markdoc for error handling.
91
- * @see 'astro/src/core/config/config.ts'
92
- */
93
- export function getAstroConfigPath(fs: typeof fsMod, root: string): string | undefined {
94
- const paths = [
95
- 'astro.config.mjs',
96
- 'astro.config.js',
97
- 'astro.config.ts',
98
- 'astro.config.mts',
99
- 'astro.config.cjs',
100
- 'astro.config.cts',
101
- ].map((p) => path.join(root, p));
102
-
103
- for (const file of paths) {
104
- if (fs.existsSync(file)) {
105
- return file;
106
- }
107
- }
108
- }
109
-
110
84
  /**
111
85
  * @see 'astro/src/core/path.ts'
112
86
  */
@@ -114,34 +88,11 @@ export function prependForwardSlash(str: string) {
114
88
  return str[0] === '/' ? str : '/' + str;
115
89
  }
116
90
 
117
- export function validateComponentsProp(components: Record<string, AstroInstance['default']>) {
91
+ export function isValidUrl(str: string): boolean {
118
92
  try {
119
- componentsPropValidator.parse(components);
120
- } catch (e) {
121
- throw new MarkdocError({
122
- message:
123
- e instanceof z.ZodError
124
- ? e.issues[0].message
125
- : 'Invalid `components` prop. Ensure you are passing an object of components to <Content />',
126
- });
93
+ new URL(str);
94
+ return true;
95
+ } catch {
96
+ return false;
127
97
  }
128
98
  }
129
-
130
- const componentsPropValidator = z.record(
131
- z
132
- .string()
133
- .min(1, 'Invalid `components` prop. Component names cannot be empty!')
134
- .refine(
135
- (value) => isCapitalized(value),
136
- (value) => ({
137
- message: `Invalid \`components\` prop: ${JSON.stringify(
138
- value
139
- )}. Component name must be capitalized. If you want to render HTML elements as components, try using a Markdoc node (https://docs.astro.build/en/guides/integrations-guide/markdoc/#render-markdoc-nodes--html-elements-as-astro-components)`,
140
- })
141
- ),
142
- z.any()
143
- );
144
-
145
- export function isCapitalized(str: string) {
146
- return str.length > 0 && str[0] === str[0].toUpperCase();
147
- }
@@ -1,9 +1,7 @@
1
1
  declare module 'astro:content' {
2
2
  interface Render {
3
3
  '.mdoc': Promise<{
4
- Content(props: {
5
- components?: Record<string, import('astro').AstroInstance['default']>;
6
- }): import('astro').MarkdownInstance<{}>['Content'];
4
+ Content(props: Record<string, any>): import('astro').MarkdownInstance<{}>['Content'];
7
5
  }>;
8
6
  }
9
7
  }
@@ -1,4 +1,3 @@
1
- import { parseHTML } from 'linkedom';
2
1
  import { parse as parseDevalue } from 'devalue';
3
2
  import { expect } from 'chai';
4
3
  import { loadFixture, fixLineEndings } from '../../../astro/test/test-utils.js';
@@ -37,70 +36,20 @@ describe('Markdoc - Content Collections', () => {
37
36
  it('loads entry', async () => {
38
37
  const res = await baseFixture.fetch('/entry.json');
39
38
  const post = parseDevalue(await res.text());
40
- expect(formatPost(post)).to.deep.equal(simplePostEntry);
39
+ expect(formatPost(post)).to.deep.equal(post1Entry);
41
40
  });
42
41
 
43
42
  it('loads collection', async () => {
44
43
  const res = await baseFixture.fetch('/collection.json');
45
44
  const posts = parseDevalue(await res.text());
46
45
  expect(posts).to.not.be.null;
46
+
47
47
  expect(posts.sort().map((post) => formatPost(post))).to.deep.equal([
48
- simplePostEntry,
49
- withComponentsEntry,
50
- withConfigEntry,
48
+ post1Entry,
49
+ post2Entry,
50
+ post3Entry,
51
51
  ]);
52
52
  });
53
-
54
- it('renders content - simple', async () => {
55
- const res = await baseFixture.fetch('/content-simple');
56
- const html = await res.text();
57
- const { document } = parseHTML(html);
58
- const h2 = document.querySelector('h2');
59
- expect(h2.textContent).to.equal('Simple post');
60
- const p = document.querySelector('p');
61
- expect(p.textContent).to.equal('This is a simple Markdoc post.');
62
- });
63
-
64
- it('renders content - with config', async () => {
65
- const fixture = await getFixtureWithConfig();
66
- const server = await fixture.startDevServer();
67
-
68
- const res = await fixture.fetch('/content-with-config');
69
- const html = await res.text();
70
- const { document } = parseHTML(html);
71
- const h2 = document.querySelector('h2');
72
- expect(h2.textContent).to.equal('Post with config');
73
- const textContent = html;
74
-
75
- expect(textContent).to.not.include('Hello');
76
- expect(textContent).to.include('Hola');
77
- expect(textContent).to.include(`Konnichiwa`);
78
-
79
- await server.stop();
80
- });
81
-
82
- it('renders content - with components', async () => {
83
- const fixture = await getFixtureWithComponents();
84
- const server = await fixture.startDevServer();
85
-
86
- const res = await fixture.fetch('/content-with-components');
87
- const html = await res.text();
88
- const { document } = parseHTML(html);
89
- const h2 = document.querySelector('h2');
90
- expect(h2.textContent).to.equal('Post with components');
91
-
92
- // Renders custom shortcode component
93
- const marquee = document.querySelector('marquee');
94
- expect(marquee).to.not.be.null;
95
- expect(marquee.hasAttribute('data-custom-marquee')).to.equal(true);
96
-
97
- // Renders Astro Code component
98
- const pre = document.querySelector('pre');
99
- expect(pre).to.not.be.null;
100
- expect(pre.className).to.equal('astro-code');
101
-
102
- await server.stop();
103
- });
104
53
  });
105
54
 
106
55
  describe('build', () => {
@@ -111,7 +60,7 @@ describe('Markdoc - Content Collections', () => {
111
60
  it('loads entry', async () => {
112
61
  const res = await baseFixture.readFile('/entry.json');
113
62
  const post = parseDevalue(res);
114
- expect(formatPost(post)).to.deep.equal(simplePostEntry);
63
+ expect(formatPost(post)).to.deep.equal(post1Entry);
115
64
  });
116
65
 
117
66
  it('loads collection', async () => {
@@ -119,140 +68,43 @@ describe('Markdoc - Content Collections', () => {
119
68
  const posts = parseDevalue(res);
120
69
  expect(posts).to.not.be.null;
121
70
  expect(posts.sort().map((post) => formatPost(post))).to.deep.equal([
122
- simplePostEntry,
123
- withComponentsEntry,
124
- withConfigEntry,
71
+ post1Entry,
72
+ post2Entry,
73
+ post3Entry,
125
74
  ]);
126
75
  });
127
-
128
- it('renders content - simple', async () => {
129
- const html = await baseFixture.readFile('/content-simple/index.html');
130
- const { document } = parseHTML(html);
131
- const h2 = document.querySelector('h2');
132
- expect(h2.textContent).to.equal('Simple post');
133
- const p = document.querySelector('p');
134
- expect(p.textContent).to.equal('This is a simple Markdoc post.');
135
- });
136
-
137
- it('renders content - with config', async () => {
138
- const fixture = await getFixtureWithConfig();
139
- await fixture.build();
140
-
141
- const html = await fixture.readFile('/content-with-config/index.html');
142
- const { document } = parseHTML(html);
143
- const h2 = document.querySelector('h2');
144
- expect(h2.textContent).to.equal('Post with config');
145
- const textContent = html;
146
-
147
- expect(textContent).to.not.include('Hello');
148
- expect(textContent).to.include('Hola');
149
- expect(textContent).to.include(`Konnichiwa`);
150
- });
151
-
152
- it('renders content - with components', async () => {
153
- const fixture = await getFixtureWithComponents();
154
- await fixture.build();
155
-
156
- const html = await fixture.readFile('/content-with-components/index.html');
157
- const { document } = parseHTML(html);
158
- const h2 = document.querySelector('h2');
159
- expect(h2.textContent).to.equal('Post with components');
160
-
161
- // Renders custom shortcode component
162
- const marquee = document.querySelector('marquee');
163
- expect(marquee).to.not.be.null;
164
- expect(marquee.hasAttribute('data-custom-marquee')).to.equal(true);
165
-
166
- // Renders Astro Code component
167
- const pre = document.querySelector('pre');
168
- expect(pre).to.not.be.null;
169
- expect(pre.className).to.equal('astro-code');
170
- });
171
76
  });
172
77
  });
173
78
 
174
- function getFixtureWithConfig() {
175
- return loadFixture({
176
- root,
177
- integrations: [
178
- markdoc({
179
- variables: {
180
- countries: ['ES', 'JP'],
181
- },
182
- functions: {
183
- includes: {
184
- transform(parameters) {
185
- const [array, value] = Object.values(parameters);
186
- return Array.isArray(array) ? array.includes(value) : false;
187
- },
188
- },
189
- },
190
- }),
191
- ],
192
- });
193
- }
194
-
195
- function getFixtureWithComponents() {
196
- return loadFixture({
197
- root,
198
- integrations: [
199
- markdoc({
200
- nodes: {
201
- fence: {
202
- render: 'Code',
203
- attributes: {
204
- language: { type: String },
205
- content: { type: String },
206
- },
207
- },
208
- },
209
- tags: {
210
- mq: {
211
- render: 'CustomMarquee',
212
- attributes: {
213
- direction: {
214
- type: String,
215
- default: 'left',
216
- matches: ['left', 'right', 'up', 'down'],
217
- errorLevel: 'critical',
218
- },
219
- },
220
- },
221
- },
222
- }),
223
- ],
224
- });
225
- }
226
-
227
- const simplePostEntry = {
228
- id: 'simple.mdoc',
229
- slug: 'simple',
79
+ const post1Entry = {
80
+ id: 'post-1.mdoc',
81
+ slug: 'post-1',
230
82
  collection: 'blog',
231
83
  data: {
232
84
  schemaWorks: true,
233
- title: 'Simple post',
85
+ title: 'Post 1',
234
86
  },
235
- body: '\n## Simple post\n\nThis is a simple Markdoc post.\n',
87
+ body: '\n## Post 1\n\nThis is the contents of post 1.\n',
236
88
  };
237
89
 
238
- const withComponentsEntry = {
239
- id: 'with-components.mdoc',
240
- slug: 'with-components',
90
+ const post2Entry = {
91
+ id: 'post-2.mdoc',
92
+ slug: 'post-2',
241
93
  collection: 'blog',
242
94
  data: {
243
95
  schemaWorks: true,
244
- title: 'Post with components',
96
+ title: 'Post 2',
245
97
  },
246
- body: '\n## Post with components\n\nThis uses a custom marquee component with a shortcode:\n\n{% mq direction="right" %}\nI\'m a marquee too!\n{% /mq %}\n\nAnd a code component for code blocks:\n\n```js\nconst isRenderedWithShiki = true;\n```\n',
98
+ body: '\n## Post 2\n\nThis is the contents of post 2.\n',
247
99
  };
248
100
 
249
- const withConfigEntry = {
250
- id: 'with-config.mdoc',
251
- slug: 'with-config',
101
+ const post3Entry = {
102
+ id: 'post-3.mdoc',
103
+ slug: 'post-3',
252
104
  collection: 'blog',
253
105
  data: {
254
106
  schemaWorks: true,
255
- title: 'Post with config',
107
+ title: 'Post 3',
256
108
  },
257
- body: '\n## Post with config\n\n{% if includes($countries, "EN") %} Hello {% /if %}\n{% if includes($countries, "ES") %} Hola {% /if %}\n{% if includes($countries, "JP") %} Konnichiwa {% /if %}\n',
109
+ body: '\n## Post 3\n\nThis is the contents of post 3.\n',
258
110
  };
@@ -4,10 +4,6 @@
4
4
  "private": true,
5
5
  "dependencies": {
6
6
  "@astrojs/markdoc": "workspace:*",
7
- "@markdoc/markdoc": "^0.2.2",
8
7
  "astro": "workspace:*"
9
- },
10
- "devDependencies": {
11
- "shiki": "^0.11.1"
12
8
  }
13
9
  }
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: Post 1
3
+ ---
4
+
5
+ ## Post 1
6
+
7
+ This is the contents of post 1.
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: Post 2
3
+ ---
4
+
5
+ ## Post 2
6
+
7
+ This is the contents of post 2.
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: Post 3
3
+ ---
4
+
5
+ ## Post 3
6
+
7
+ This is the contents of post 3.
@@ -3,7 +3,7 @@ import { stringify } from 'devalue';
3
3
  import { stripRenderFn } from '../../utils.js';
4
4
 
5
5
  export async function get() {
6
- const post = await getEntryBySlug('blog', 'simple');
6
+ const post = await getEntryBySlug('blog', 'post-1');
7
7
  return {
8
8
  body: stringify(stripRenderFn(post)),
9
9
  };
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'astro/config';
2
+ import markdoc from '@astrojs/markdoc';
3
+
4
+ // https://astro.build/config
5
+ export default defineConfig({
6
+ experimental: {
7
+ assets: true,
8
+ },
9
+ integrations: [markdoc()],
10
+ });
@@ -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,9 @@
1
+ {
2
+ "name": "@test/image-assets",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "dependencies": {
6
+ "@astrojs/markdoc": "workspace:*",
7
+ "astro": "workspace:*"
8
+ }
9
+ }
@@ -0,0 +1,7 @@
1
+ # Image assets
2
+
3
+ ![Favicon](/favicon.svg) {% #public %}
4
+
5
+ ![Oar](../../assets/relative/oar.jpg) {% #relative %}
6
+
7
+ ![Gray cityscape arial view](~/assets/alias/cityscape.jpg) {% #alias %}
@@ -0,0 +1,19 @@
1
+ ---
2
+ import { getEntryBySlug } from 'astro:content';
3
+
4
+ const intro = await getEntryBySlug('docs', 'intro');
5
+ const { Content } = await intro.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>
@@ -0,0 +1,9 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
2
+ <path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
3
+ <style>
4
+ path { fill: #000; }
5
+ @media (prefers-color-scheme: dark) {
6
+ path { fill: #FFF; }
7
+ }
8
+ </style>
9
+ </svg>
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'astro/config';
2
+ import markdoc from '@astrojs/markdoc';
3
+
4
+ // https://astro.build/config
5
+ export default defineConfig({
6
+ integrations: [markdoc()],
7
+ });
@@ -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,9 @@
1
+ {
2
+ "name": "@test/markdoc-render-simple",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "dependencies": {
6
+ "@astrojs/markdoc": "workspace:*",
7
+ "astro": "workspace:*"
8
+ }
9
+ }
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import { getEntryBySlug } from "astro:content";
3
+
3
4
  const post = await getEntryBySlug('blog', 'simple');
4
5
  const { Content } = await post.render();
5
6
  ---
@@ -10,7 +11,7 @@ const { Content } = await post.render();
10
11
  <meta charset="UTF-8">
11
12
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
12
13
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
13
- <title>Content - Simple</title>
14
+ <title>Content</title>
14
15
  </head>
15
16
  <body>
16
17
  <Content />
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'astro/config';
2
+ import markdoc from '@astrojs/markdoc';
3
+
4
+ // https://astro.build/config
5
+ export default defineConfig({
6
+ integrations: [markdoc()],
7
+ });
@@ -0,0 +1,28 @@
1
+ import Code from './src/components/Code.astro';
2
+ import CustomMarquee from './src/components/CustomMarquee.astro';
3
+ import { defineMarkdocConfig } from '@astrojs/markdoc/config';
4
+
5
+ export default defineMarkdocConfig({
6
+ nodes: {
7
+ fence: {
8
+ render: Code,
9
+ attributes: {
10
+ language: { type: String },
11
+ content: { type: String },
12
+ },
13
+ },
14
+ },
15
+ tags: {
16
+ mq: {
17
+ render: CustomMarquee,
18
+ attributes: {
19
+ direction: {
20
+ type: String,
21
+ default: 'left',
22
+ matches: ['left', 'right', 'up', 'down'],
23
+ errorLevel: 'critical',
24
+ },
25
+ },
26
+ },
27
+ },
28
+ })