@astrojs/mdx 0.1.1 → 0.3.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/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +28 -0
- package/README.md +182 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +54 -4
- package/dist/remark-prism.d.ts +2 -0
- package/dist/remark-prism.js +49 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +17 -0
- package/package.json +18 -5
- package/src/index.ts +85 -6
- package/src/remark-prism.ts +60 -0
- package/src/utils.ts +21 -0
- package/test/fixtures/mdx-custom-frontmatter-name/src/pages/glob.json.js +9 -0
- package/test/fixtures/mdx-custom-frontmatter-name/src/pages/index.mdx +6 -0
- package/test/fixtures/mdx-frontmatter/src/pages/glob.json.js +9 -0
- package/test/fixtures/mdx-frontmatter/src/pages/index.mdx +6 -0
- package/test/fixtures/mdx-remark-plugins/src/pages/with-gfm.mdx +3 -0
- package/test/fixtures/mdx-remark-plugins/src/pages/with-toc.mdx +19 -0
- package/test/fixtures/mdx-syntax-hightlighting/src/pages/index.mdx +9 -0
- package/test/fixtures/mdx-url-export/src/pages/pages.json.js +9 -0
- package/test/fixtures/mdx-url-export/src/pages/test-1.mdx +1 -0
- package/test/fixtures/mdx-url-export/src/pages/test-2.mdx +1 -0
- package/test/fixtures/mdx-url-export/src/pages/with-url-override.mdx +3 -0
- package/test/mdx-frontmatter.test.js +45 -0
- package/test/mdx-remark-plugins.test.js +62 -0
- package/test/mdx-syntax-highlighting.test.js +67 -0
- package/test/mdx-url-export.test.js +28 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
[
|
|
2
|
-
[
|
|
3
|
-
[
|
|
4
|
-
[
|
|
5
|
-
[
|
|
1
|
+
[35m@astrojs/mdx:build: [0mcache hit, replaying output [2m5ec97556db3f4322[0m
|
|
2
|
+
[35m@astrojs/mdx:build: [0m
|
|
3
|
+
[35m@astrojs/mdx:build: [0m> @astrojs/mdx@0.3.0 build /home/runner/work/astro/astro/packages/integrations/mdx
|
|
4
|
+
[35m@astrojs/mdx:build: [0m> astro-scripts build "src/**/*.ts" && tsc
|
|
5
|
+
[35m@astrojs/mdx:build: [0m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @astrojs/mdx
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#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
|
|
8
|
+
|
|
9
|
+
* [#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
|
|
10
|
+
|
|
11
|
+
- [#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
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#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
|
|
16
|
+
|
|
17
|
+
* [#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
|
|
18
|
+
|
|
19
|
+
## 0.2.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- [#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
|
|
24
|
+
|
|
25
|
+
## 0.2.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- [#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`.
|
|
30
|
+
|
|
3
31
|
## 0.1.1
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -78,9 +78,190 @@ To write your first MDX page in Astro, head to our [UI framework documentation][
|
|
|
78
78
|
|
|
79
79
|
Also check our [Astro Integration Documentation][astro-integration] for more on integrations.
|
|
80
80
|
|
|
81
|
+
### Variables
|
|
82
|
+
|
|
83
|
+
MDX supports `export` statements to add variables to your templates. These variables are accessible both from the template itself _and_ as named properties when importing the template somewhere else.
|
|
84
|
+
|
|
85
|
+
For instance, you can export a `title` field from an MDX page or component to use as a heading with `{JSX expressions}`:
|
|
86
|
+
|
|
87
|
+
```mdx
|
|
88
|
+
export const title = 'My first MDX post'
|
|
89
|
+
|
|
90
|
+
# {title}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This `title` will be accessible from `import` and [glob](https://docs.astro.build/en/reference/api-reference/#astroglob) statements as well:
|
|
94
|
+
|
|
95
|
+
```astro
|
|
96
|
+
---
|
|
97
|
+
// src/pages/index.astro
|
|
98
|
+
const posts = await Astro.glob('./*.mdx');
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
{posts.map(post => <p>{post.title}</p>)}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
See [the official "how MDX works" guide](https://mdxjs.com/docs/using-mdx/#how-mdx-works) for more on MDX variables.
|
|
105
|
+
|
|
106
|
+
### Frontmatter
|
|
107
|
+
|
|
108
|
+
Astro also supports YAML-based frontmatter out-of-the-box using the [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) plugin. By default, all variables declared in a frontmatter fence (`---`) will be accessible via the `frontmatter` export. See the `frontmatterOptions` configuration to customize this behavior.
|
|
109
|
+
|
|
110
|
+
For example, we can add a `title` and `publishDate` to an MDX page or component like so:
|
|
111
|
+
|
|
112
|
+
```mdx
|
|
113
|
+
---
|
|
114
|
+
title: 'My first MDX post'
|
|
115
|
+
publishDate: '21 September 2022'
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
# {frontmatter.title}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Now, this `title` and `publishDate` will be accessible from `import` and [glob](https://docs.astro.build/en/reference/api-reference/#astroglob) statements via the `frontmatter` property. This matches the behavior of [plain markdown in Astro](https://docs.astro.build/en/reference/api-reference/#markdown-files) as well!
|
|
122
|
+
|
|
123
|
+
```astro
|
|
124
|
+
---
|
|
125
|
+
// src/pages/index.astro
|
|
126
|
+
const posts = await Astro.glob('./*.mdx');
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
{posts.map(post => (
|
|
130
|
+
<Fragment>
|
|
131
|
+
<h2>{post.frontmatter.title}</h2>
|
|
132
|
+
<time>{post.frontmatter.publishDate}</time>
|
|
133
|
+
</Fragment>
|
|
134
|
+
))}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Syntax highlighting
|
|
138
|
+
|
|
139
|
+
The MDX integration respects [your project's `markdown.syntaxHighlight` configuration](https://docs.astro.build/en/guides/markdown-content/#syntax-highlighting).
|
|
140
|
+
|
|
141
|
+
We will highlight your code blocks with [Shiki](https://github.com/shikijs/shiki) by default [using Shiki twoslash](https://shikijs.github.io/twoslash/). You can customize [this remark plugin](https://www.npmjs.com/package/remark-shiki-twoslash) using the `markdown.shikiConfig` option in your `astro.config`. For example, you can apply a different built-in theme like so:
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
// astro.config.mjs
|
|
145
|
+
export default {
|
|
146
|
+
markdown: {
|
|
147
|
+
shikiConfig: {
|
|
148
|
+
theme: 'dracula',
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
integrations: [mdx()],
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Visit [our Shiki configuration docs](https://docs.astro.build/en/guides/markdown-content/#shiki-configuration) for more on using Shiki with Astro.
|
|
156
|
+
|
|
157
|
+
#### Switch to Prism
|
|
158
|
+
|
|
159
|
+
You can also use the [Prism](https://prismjs.com/) syntax highlighter by setting `markdown.syntaxHighlight` to `'prism'` in your `astro.config` like so:
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
// astro.config.mjs
|
|
163
|
+
export default {
|
|
164
|
+
markdown: {
|
|
165
|
+
syntaxHighlight: 'prism',
|
|
166
|
+
},
|
|
167
|
+
integrations: [mdx()],
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
This applies a minimal Prism renderer with added support for `astro` code blocks. Visit [our "Prism configuration" docs](https://docs.astro.build/en/guides/markdown-content/#prism-configuration) for more on using Prism with Astro.
|
|
172
|
+
|
|
81
173
|
## Configuration
|
|
82
174
|
|
|
83
|
-
|
|
175
|
+
<details>
|
|
176
|
+
<summary><strong>remarkPlugins</strong></summary>
|
|
177
|
+
|
|
178
|
+
**Default plugins:** [remark-gfm](https://github.com/remarkjs/remark-gfm), [remark-smartypants](https://github.com/silvenon/remark-smartypants)
|
|
179
|
+
|
|
180
|
+
[Remark plugins](https://github.com/remarkjs/remark/blob/main/doc/plugins.md) allow you to extend your Markdown with new capabilities. This includes [auto-generating a table of contents](https://github.com/remarkjs/remark-toc), [applying accessible emoji labels](https://github.com/florianeckerstorfer/remark-a11y-emoji), and more. We encourage you to browse [awesome-remark](https://github.com/remarkjs/awesome-remark) for a full curated list!
|
|
181
|
+
|
|
182
|
+
We apply [GitHub-flavored Markdown](https://github.com/remarkjs/remark-gfm) and [Smartypants](https://github.com/silvenon/remark-smartypants) by default. This brings some niceties like auto-generating clickable links from text (ex. `https://example.com`) and formatting quotes for readability. When applying your own plugins, you can choose to preserve or remove these defaults.
|
|
183
|
+
|
|
184
|
+
To apply plugins _while preserving_ Astro's default plugins, use a nested `extends` object like so:
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
// astro.config.mjs
|
|
188
|
+
import remarkToc from 'remark-toc';
|
|
189
|
+
|
|
190
|
+
export default {
|
|
191
|
+
integrations: [mdx({
|
|
192
|
+
// apply remark-toc alongside GitHub-flavored markdown and Smartypants
|
|
193
|
+
remarkPlugins: { extends: [remarkToc] },
|
|
194
|
+
})],
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
To apply plugins _without_ Astro's defaults, you can apply a plain array:
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
// astro.config.mjs
|
|
202
|
+
import remarkToc from 'remark-toc';
|
|
203
|
+
|
|
204
|
+
export default {
|
|
205
|
+
integrations: [mdx({
|
|
206
|
+
// apply remark-toc alone, removing other defaults
|
|
207
|
+
remarkPlugins: [remarkToc],
|
|
208
|
+
})],
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
</details>
|
|
213
|
+
|
|
214
|
+
<details>
|
|
215
|
+
<summary><strong>rehypePlugins</strong></summary>
|
|
216
|
+
|
|
217
|
+
**Default plugins:** none
|
|
218
|
+
|
|
219
|
+
[Rehype plugins](https://github.com/rehypejs/rehype/blob/main/doc/plugins.md) allow you to transform the HTML that your Markdown generates. We recommend checking the [Remark plugin](https://github.com/remarkjs/remark/blob/main/doc/plugins.md) catalog first _before_ considering rehype plugins, since most users want to transform their Markdown syntax instead. If HTML transforms are what you need, we encourage you to browse [awesome-rehype](https://github.com/rehypejs/awesome-rehype) for a full curated list of plugins!
|
|
220
|
+
|
|
221
|
+
To apply rehype plugins, use the `rehypePlugins` configuration option like so:
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
// astro.config.mjs
|
|
225
|
+
import rehypeMinifyHtml from 'rehype-minify';
|
|
226
|
+
|
|
227
|
+
export default {
|
|
228
|
+
integrations: [mdx({
|
|
229
|
+
rehypePlugins: [rehypeMinifyHtml],
|
|
230
|
+
})],
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
</details>
|
|
234
|
+
|
|
235
|
+
<details>
|
|
236
|
+
<summary><strong>frontmatterOptions</strong></summary>
|
|
237
|
+
|
|
238
|
+
**Default:** `{ name: 'frontmatter' }`
|
|
239
|
+
|
|
240
|
+
We use [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) to parse YAML-based frontmatter in your MDX files. If you want to override our default configuration or extend remark-mdx-frontmatter (ex. to [apply a custom frontmatter parser](https://github.com/remcohaszing/remark-mdx-frontmatter#parsers)), you can supply a `frontmatterOptions` configuration.
|
|
241
|
+
|
|
242
|
+
For example, say you want to access frontmatter as root-level variables without a nested `frontmatter` object. You can override the [`name` configuration option](https://github.com/remcohaszing/remark-mdx-frontmatter#name) like so:
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
// astro.config.mjs
|
|
246
|
+
export default {
|
|
247
|
+
integrations: [mdx({
|
|
248
|
+
frontmatterOptions: {
|
|
249
|
+
name: '',
|
|
250
|
+
}
|
|
251
|
+
})],
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
```mdx
|
|
256
|
+
---
|
|
257
|
+
title: I'm just a variable now!
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
# {title}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
See the [remark-mdx-frontmatter README](https://github.com/remcohaszing/remark-mdx-frontmatter#options) for a complete list of options.
|
|
264
|
+
</details>
|
|
84
265
|
|
|
85
266
|
## Examples
|
|
86
267
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,18 @@
|
|
|
1
|
+
import { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
|
|
1
2
|
import type { AstroIntegration } from 'astro';
|
|
2
|
-
|
|
3
|
+
import type { RemarkMdxFrontmatterOptions } from 'remark-mdx-frontmatter';
|
|
4
|
+
declare type WithExtends<T> = T | {
|
|
5
|
+
extends: T;
|
|
6
|
+
};
|
|
7
|
+
declare type MdxOptions = {
|
|
8
|
+
remarkPlugins?: WithExtends<MdxRollupPluginOptions['remarkPlugins']>;
|
|
9
|
+
rehypePlugins?: WithExtends<MdxRollupPluginOptions['rehypePlugins']>;
|
|
10
|
+
/**
|
|
11
|
+
* Configure the remark-mdx-frontmatter plugin
|
|
12
|
+
* @see https://github.com/remcohaszing/remark-mdx-frontmatter#options for a full list of options
|
|
13
|
+
* @default {{ name: 'frontmatter' }}
|
|
14
|
+
*/
|
|
15
|
+
frontmatterOptions?: RemarkMdxFrontmatterOptions;
|
|
16
|
+
};
|
|
17
|
+
export default function mdx(mdxOptions?: MdxOptions): AstroIntegration;
|
|
18
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,81 @@
|
|
|
1
|
+
import { nodeTypes } from "@mdx-js/mdx";
|
|
1
2
|
import mdxPlugin from "@mdx-js/rollup";
|
|
2
|
-
|
|
3
|
+
import { parse as parseESM } from "es-module-lexer";
|
|
4
|
+
import rehypeRaw from "rehype-raw";
|
|
5
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
6
|
+
import remarkGfm from "remark-gfm";
|
|
7
|
+
import remarkMdxFrontmatter from "remark-mdx-frontmatter";
|
|
8
|
+
import remarkShikiTwoslash from "remark-shiki-twoslash";
|
|
9
|
+
import remarkSmartypants from "remark-smartypants";
|
|
10
|
+
import remarkPrism from "./remark-prism.js";
|
|
11
|
+
import { getFileInfo } from "./utils.js";
|
|
12
|
+
const DEFAULT_REMARK_PLUGINS = [remarkGfm, remarkSmartypants];
|
|
13
|
+
function handleExtends(config, defaults = []) {
|
|
14
|
+
if (Array.isArray(config))
|
|
15
|
+
return config;
|
|
16
|
+
return [...defaults, ...(config == null ? void 0 : config.extends) ?? []];
|
|
17
|
+
}
|
|
18
|
+
function mdx(mdxOptions = {}) {
|
|
3
19
|
return {
|
|
4
20
|
name: "@astrojs/mdx",
|
|
5
21
|
hooks: {
|
|
6
|
-
"astro:config:setup": ({ updateConfig, addPageExtension, command }) => {
|
|
22
|
+
"astro:config:setup": ({ updateConfig, config, addPageExtension, command }) => {
|
|
7
23
|
addPageExtension(".mdx");
|
|
24
|
+
let remarkPlugins = handleExtends(mdxOptions.remarkPlugins, DEFAULT_REMARK_PLUGINS);
|
|
25
|
+
let rehypePlugins = handleExtends(mdxOptions.rehypePlugins);
|
|
26
|
+
if (config.markdown.syntaxHighlight === "shiki") {
|
|
27
|
+
remarkPlugins.push([
|
|
28
|
+
remarkShikiTwoslash.default,
|
|
29
|
+
config.markdown.shikiConfig
|
|
30
|
+
]);
|
|
31
|
+
rehypePlugins.push([rehypeRaw, { passThrough: nodeTypes }]);
|
|
32
|
+
}
|
|
33
|
+
if (config.markdown.syntaxHighlight === "prism") {
|
|
34
|
+
remarkPlugins.push(remarkPrism);
|
|
35
|
+
rehypePlugins.push([rehypeRaw, { passThrough: nodeTypes }]);
|
|
36
|
+
}
|
|
37
|
+
remarkPlugins.push(remarkFrontmatter);
|
|
38
|
+
remarkPlugins.push([
|
|
39
|
+
remarkMdxFrontmatter,
|
|
40
|
+
{
|
|
41
|
+
name: "frontmatter",
|
|
42
|
+
...mdxOptions.frontmatterOptions
|
|
43
|
+
}
|
|
44
|
+
]);
|
|
8
45
|
updateConfig({
|
|
9
46
|
vite: {
|
|
10
47
|
plugins: [
|
|
11
48
|
{
|
|
12
49
|
enforce: "pre",
|
|
13
50
|
...mdxPlugin({
|
|
51
|
+
remarkPlugins,
|
|
52
|
+
rehypePlugins,
|
|
14
53
|
jsx: true,
|
|
15
54
|
jsxImportSource: "astro",
|
|
16
55
|
format: "mdx",
|
|
17
56
|
mdExtensions: []
|
|
18
57
|
})
|
|
19
58
|
},
|
|
20
|
-
|
|
59
|
+
{
|
|
21
60
|
name: "@astrojs/mdx",
|
|
22
61
|
transform(code, id) {
|
|
23
62
|
if (!id.endsWith(".mdx"))
|
|
24
63
|
return;
|
|
25
|
-
|
|
64
|
+
const [, moduleExports] = parseESM(code);
|
|
65
|
+
code += `
|
|
66
|
+
import "${"astro:scripts/page-ssr.js"}";`;
|
|
67
|
+
if (!moduleExports.includes("url")) {
|
|
68
|
+
const { fileUrl } = getFileInfo(id, config);
|
|
69
|
+
code += `
|
|
70
|
+
export const url = ${JSON.stringify(fileUrl)};`;
|
|
71
|
+
}
|
|
72
|
+
if (command === "dev") {
|
|
73
|
+
code += `
|
|
26
74
|
if (import.meta.hot) {
|
|
27
75
|
import.meta.hot.decline();
|
|
28
76
|
}`;
|
|
77
|
+
}
|
|
78
|
+
return code;
|
|
29
79
|
}
|
|
30
80
|
}
|
|
31
81
|
]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { addAstro } from "@astrojs/prism/internal";
|
|
2
|
+
import Prism from "prismjs";
|
|
3
|
+
import loadLanguages from "prismjs/components/index.js";
|
|
4
|
+
import { visit } from "unist-util-visit";
|
|
5
|
+
const languageMap = /* @__PURE__ */ new Map([["ts", "typescript"]]);
|
|
6
|
+
function runHighlighter(lang, code) {
|
|
7
|
+
let classLanguage = `language-${lang}`;
|
|
8
|
+
if (lang == null) {
|
|
9
|
+
lang = "plaintext";
|
|
10
|
+
}
|
|
11
|
+
const ensureLoaded = (language) => {
|
|
12
|
+
if (language && !Prism.languages[language]) {
|
|
13
|
+
loadLanguages([language]);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
if (languageMap.has(lang)) {
|
|
17
|
+
ensureLoaded(languageMap.get(lang));
|
|
18
|
+
} else if (lang === "astro") {
|
|
19
|
+
ensureLoaded("typescript");
|
|
20
|
+
addAstro(Prism);
|
|
21
|
+
} else {
|
|
22
|
+
ensureLoaded("markup-templating");
|
|
23
|
+
ensureLoaded(lang);
|
|
24
|
+
}
|
|
25
|
+
if (lang && !Prism.languages[lang]) {
|
|
26
|
+
console.warn(`Unable to load the language: ${lang}`);
|
|
27
|
+
}
|
|
28
|
+
const grammar = Prism.languages[lang];
|
|
29
|
+
let html = code;
|
|
30
|
+
if (grammar) {
|
|
31
|
+
html = Prism.highlight(code, grammar, lang);
|
|
32
|
+
}
|
|
33
|
+
return { classLanguage, html };
|
|
34
|
+
}
|
|
35
|
+
function remarkPrism() {
|
|
36
|
+
return (tree) => visit(tree, "code", (node) => {
|
|
37
|
+
let { lang, value } = node;
|
|
38
|
+
node.type = "html";
|
|
39
|
+
let { html, classLanguage } = runHighlighter(lang, value);
|
|
40
|
+
let classes = [classLanguage];
|
|
41
|
+
node.value = `<pre class="${classes.join(
|
|
42
|
+
" "
|
|
43
|
+
)}"><code class="${classLanguage}">${html}</code></pre>`;
|
|
44
|
+
return node;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
remarkPrism as default
|
|
49
|
+
};
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function appendForwardSlash(path) {
|
|
2
|
+
return path.endsWith("/") ? path : path + "/";
|
|
3
|
+
}
|
|
4
|
+
function getFileInfo(id, config) {
|
|
5
|
+
const sitePathname = appendForwardSlash(
|
|
6
|
+
config.site ? new URL(config.base, config.site).pathname : config.base
|
|
7
|
+
);
|
|
8
|
+
const fileId = id.split("?")[0];
|
|
9
|
+
let fileUrl = fileId.includes("/pages/") ? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, "") : void 0;
|
|
10
|
+
if (fileUrl && config.trailingSlash === "always") {
|
|
11
|
+
fileUrl = appendForwardSlash(fileUrl);
|
|
12
|
+
}
|
|
13
|
+
return { fileId, fileUrl };
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
getFileInfo
|
|
17
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/mdx",
|
|
3
3
|
"description": "Use MDX within Astro",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "withastro",
|
|
@@ -24,20 +24,33 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@
|
|
27
|
+
"@astrojs/prism": "^0.6.1",
|
|
28
|
+
"@mdx-js/mdx": "^2.1.2",
|
|
29
|
+
"@mdx-js/rollup": "^2.1.1",
|
|
30
|
+
"es-module-lexer": "^0.10.5",
|
|
31
|
+
"prismjs": "^1.28.0",
|
|
32
|
+
"rehype-raw": "^6.1.1",
|
|
33
|
+
"remark-gfm": "^3.0.1",
|
|
34
|
+
"remark-shiki-twoslash": "^3.1.0",
|
|
35
|
+
"remark-smartypants": "^2.0.0",
|
|
36
|
+
"shiki": "^0.10.1",
|
|
37
|
+
"unist-util-visit": "^4.1.0",
|
|
38
|
+
"remark-frontmatter": "^4.0.1",
|
|
39
|
+
"remark-mdx-frontmatter": "^2.0.2"
|
|
28
40
|
},
|
|
29
41
|
"devDependencies": {
|
|
30
42
|
"@types/chai": "^4.3.1",
|
|
31
43
|
"@types/mocha": "^9.1.1",
|
|
32
44
|
"@types/yargs-parser": "^21.0.0",
|
|
33
|
-
"astro": "1.0.0-
|
|
45
|
+
"astro": "1.0.0-rc.1",
|
|
34
46
|
"astro-scripts": "0.0.6",
|
|
35
47
|
"chai": "^4.3.6",
|
|
48
|
+
"linkedom": "^0.14.12",
|
|
36
49
|
"mocha": "^9.2.2",
|
|
37
|
-
"
|
|
50
|
+
"remark-toc": "^8.0.1"
|
|
38
51
|
},
|
|
39
52
|
"engines": {
|
|
40
|
-
"node": "^14.
|
|
53
|
+
"node": "^14.18.0 || >=16.12.0"
|
|
41
54
|
},
|
|
42
55
|
"scripts": {
|
|
43
56
|
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,81 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { nodeTypes } from '@mdx-js/mdx';
|
|
2
|
+
import mdxPlugin, { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
|
|
2
3
|
import type { AstroIntegration } from 'astro';
|
|
4
|
+
import { parse as parseESM } from 'es-module-lexer';
|
|
5
|
+
import rehypeRaw from 'rehype-raw';
|
|
6
|
+
import remarkFrontmatter from 'remark-frontmatter';
|
|
7
|
+
import remarkGfm from 'remark-gfm';
|
|
8
|
+
import type { RemarkMdxFrontmatterOptions } from 'remark-mdx-frontmatter';
|
|
9
|
+
import remarkMdxFrontmatter from 'remark-mdx-frontmatter';
|
|
10
|
+
import remarkShikiTwoslash from 'remark-shiki-twoslash';
|
|
11
|
+
import remarkSmartypants from 'remark-smartypants';
|
|
12
|
+
import remarkPrism from './remark-prism.js';
|
|
13
|
+
import { getFileInfo } from './utils.js';
|
|
3
14
|
|
|
4
|
-
|
|
15
|
+
type WithExtends<T> = T | { extends: T };
|
|
16
|
+
|
|
17
|
+
type MdxOptions = {
|
|
18
|
+
remarkPlugins?: WithExtends<MdxRollupPluginOptions['remarkPlugins']>;
|
|
19
|
+
rehypePlugins?: WithExtends<MdxRollupPluginOptions['rehypePlugins']>;
|
|
20
|
+
/**
|
|
21
|
+
* Configure the remark-mdx-frontmatter plugin
|
|
22
|
+
* @see https://github.com/remcohaszing/remark-mdx-frontmatter#options for a full list of options
|
|
23
|
+
* @default {{ name: 'frontmatter' }}
|
|
24
|
+
*/
|
|
25
|
+
frontmatterOptions?: RemarkMdxFrontmatterOptions;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const DEFAULT_REMARK_PLUGINS = [remarkGfm, remarkSmartypants];
|
|
29
|
+
|
|
30
|
+
function handleExtends<T>(config: WithExtends<T[] | undefined>, defaults: T[] = []): T[] {
|
|
31
|
+
if (Array.isArray(config)) return config;
|
|
32
|
+
|
|
33
|
+
return [...defaults, ...(config?.extends ?? [])];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
|
|
5
37
|
return {
|
|
6
38
|
name: '@astrojs/mdx',
|
|
7
39
|
hooks: {
|
|
8
|
-
'astro:config:setup': ({ updateConfig, addPageExtension, command }: any) => {
|
|
40
|
+
'astro:config:setup': ({ updateConfig, config, addPageExtension, command }: any) => {
|
|
9
41
|
addPageExtension('.mdx');
|
|
42
|
+
let remarkPlugins = handleExtends(mdxOptions.remarkPlugins, DEFAULT_REMARK_PLUGINS);
|
|
43
|
+
let rehypePlugins = handleExtends(mdxOptions.rehypePlugins);
|
|
44
|
+
|
|
45
|
+
if (config.markdown.syntaxHighlight === 'shiki') {
|
|
46
|
+
remarkPlugins.push([
|
|
47
|
+
// Default export still requires ".default" chaining for some reason
|
|
48
|
+
// Workarounds tried:
|
|
49
|
+
// - "import * as remarkShikiTwoslash"
|
|
50
|
+
// - "import { default as remarkShikiTwoslash }"
|
|
51
|
+
(remarkShikiTwoslash as any).default,
|
|
52
|
+
config.markdown.shikiConfig,
|
|
53
|
+
]);
|
|
54
|
+
rehypePlugins.push([rehypeRaw, { passThrough: nodeTypes }]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (config.markdown.syntaxHighlight === 'prism') {
|
|
58
|
+
remarkPlugins.push(remarkPrism);
|
|
59
|
+
rehypePlugins.push([rehypeRaw, { passThrough: nodeTypes }]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
remarkPlugins.push(remarkFrontmatter);
|
|
63
|
+
remarkPlugins.push([
|
|
64
|
+
remarkMdxFrontmatter,
|
|
65
|
+
{
|
|
66
|
+
name: 'frontmatter',
|
|
67
|
+
...mdxOptions.frontmatterOptions,
|
|
68
|
+
},
|
|
69
|
+
]);
|
|
70
|
+
|
|
10
71
|
updateConfig({
|
|
11
72
|
vite: {
|
|
12
73
|
plugins: [
|
|
13
74
|
{
|
|
14
75
|
enforce: 'pre',
|
|
15
76
|
...mdxPlugin({
|
|
77
|
+
remarkPlugins,
|
|
78
|
+
rehypePlugins,
|
|
16
79
|
jsx: true,
|
|
17
80
|
jsxImportSource: 'astro',
|
|
18
81
|
// Note: disable `.md` support
|
|
@@ -20,14 +83,30 @@ export default function mdx(): AstroIntegration {
|
|
|
20
83
|
mdExtensions: [],
|
|
21
84
|
}),
|
|
22
85
|
},
|
|
23
|
-
|
|
86
|
+
{
|
|
24
87
|
name: '@astrojs/mdx',
|
|
25
88
|
transform(code: string, id: string) {
|
|
26
89
|
if (!id.endsWith('.mdx')) return;
|
|
27
|
-
|
|
28
|
-
|
|
90
|
+
const [, moduleExports] = parseESM(code);
|
|
91
|
+
|
|
92
|
+
// This adds support for injected "page-ssr" scripts in MDX files.
|
|
93
|
+
// TODO: This should only be happening on page entrypoints, not all imported MDX.
|
|
94
|
+
// TODO: This code is copy-pasted across all Astro/Vite plugins that deal with page
|
|
95
|
+
// entrypoints (.astro, .md, .mdx). This should be handled in some centralized place,
|
|
96
|
+
// or otherwise refactored to not require copy-paste handling logic.
|
|
97
|
+
code += `\nimport "${'astro:scripts/page-ssr.js'}";`;
|
|
98
|
+
|
|
99
|
+
if (!moduleExports.includes('url')) {
|
|
100
|
+
const { fileUrl } = getFileInfo(id, config);
|
|
101
|
+
code += `\nexport const url = ${JSON.stringify(fileUrl)};`;
|
|
102
|
+
}
|
|
103
|
+
if (command === 'dev') {
|
|
104
|
+
// TODO: decline HMR updates until we have a stable approach
|
|
105
|
+
code += `\nif (import.meta.hot) {
|
|
29
106
|
import.meta.hot.decline();
|
|
30
107
|
}`;
|
|
108
|
+
}
|
|
109
|
+
return code;
|
|
31
110
|
},
|
|
32
111
|
},
|
|
33
112
|
],
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// TODO: discuss extracting this file to @astrojs/prism
|
|
2
|
+
import { addAstro } from '@astrojs/prism/internal';
|
|
3
|
+
import Prism from 'prismjs';
|
|
4
|
+
import loadLanguages from 'prismjs/components/index.js';
|
|
5
|
+
import { visit } from 'unist-util-visit';
|
|
6
|
+
|
|
7
|
+
const languageMap = new Map([['ts', 'typescript']]);
|
|
8
|
+
|
|
9
|
+
function runHighlighter(lang: string, code: string) {
|
|
10
|
+
let classLanguage = `language-${lang}`;
|
|
11
|
+
|
|
12
|
+
if (lang == null) {
|
|
13
|
+
lang = 'plaintext';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const ensureLoaded = (language: string) => {
|
|
17
|
+
if (language && !Prism.languages[language]) {
|
|
18
|
+
loadLanguages([language]);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
if (languageMap.has(lang)) {
|
|
23
|
+
ensureLoaded(languageMap.get(lang)!);
|
|
24
|
+
} else if (lang === 'astro') {
|
|
25
|
+
ensureLoaded('typescript');
|
|
26
|
+
addAstro(Prism);
|
|
27
|
+
} else {
|
|
28
|
+
ensureLoaded('markup-templating'); // Prism expects this to exist for a number of other langs
|
|
29
|
+
ensureLoaded(lang);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (lang && !Prism.languages[lang]) {
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.warn(`Unable to load the language: ${lang}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const grammar = Prism.languages[lang];
|
|
38
|
+
let html = code;
|
|
39
|
+
if (grammar) {
|
|
40
|
+
html = Prism.highlight(code, grammar, lang);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { classLanguage, html };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** */
|
|
47
|
+
export default function remarkPrism() {
|
|
48
|
+
return (tree: any) =>
|
|
49
|
+
visit(tree, 'code', (node: any) => {
|
|
50
|
+
let { lang, value } = node;
|
|
51
|
+
node.type = 'html';
|
|
52
|
+
|
|
53
|
+
let { html, classLanguage } = runHighlighter(lang, value);
|
|
54
|
+
let classes = [classLanguage];
|
|
55
|
+
node.value = `<pre class="${classes.join(
|
|
56
|
+
' '
|
|
57
|
+
)}"><code class="${classLanguage}">${html}</code></pre>`;
|
|
58
|
+
return node;
|
|
59
|
+
});
|
|
60
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AstroConfig } from 'astro';
|
|
2
|
+
|
|
3
|
+
function appendForwardSlash(path: string) {
|
|
4
|
+
return path.endsWith('/') ? path : path + '/';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** @see 'vite-plugin-utils' for source */
|
|
8
|
+
export function getFileInfo(id: string, config: AstroConfig) {
|
|
9
|
+
const sitePathname = appendForwardSlash(
|
|
10
|
+
config.site ? new URL(config.base, config.site).pathname : config.base
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const fileId = id.split('?')[0];
|
|
14
|
+
let fileUrl = fileId.includes('/pages/')
|
|
15
|
+
? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, '')
|
|
16
|
+
: undefined;
|
|
17
|
+
if (fileUrl && config.trailingSlash === 'always') {
|
|
18
|
+
fileUrl = appendForwardSlash(fileUrl);
|
|
19
|
+
}
|
|
20
|
+
return { fileId, fileUrl };
|
|
21
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# TOC test
|
|
2
|
+
|
|
3
|
+
## Table of contents
|
|
4
|
+
|
|
5
|
+
## Section 1
|
|
6
|
+
|
|
7
|
+
Some text!
|
|
8
|
+
|
|
9
|
+
### Subsection 1
|
|
10
|
+
|
|
11
|
+
Some subsection test!
|
|
12
|
+
|
|
13
|
+
### Subsection 2
|
|
14
|
+
|
|
15
|
+
Oh cool, more text!
|
|
16
|
+
|
|
17
|
+
## Section 2
|
|
18
|
+
|
|
19
|
+
And section 2, with a hyperlink to check GFM is preserved: https://handle-me-gfm.com
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# I'm a page with a url of "/test-1!"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# I'm a page with a url of "/test-2!"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
5
|
+
|
|
6
|
+
const FIXTURE_ROOT = new URL('./fixtures/mdx-frontmatter/', import.meta.url);
|
|
7
|
+
|
|
8
|
+
describe('MDX frontmatter', () => {
|
|
9
|
+
it('builds when "frontmatter.property" is in JSX expression', async () => {
|
|
10
|
+
const fixture = await loadFixture({
|
|
11
|
+
root: FIXTURE_ROOT,
|
|
12
|
+
integrations: [mdx()],
|
|
13
|
+
});
|
|
14
|
+
await fixture.build();
|
|
15
|
+
expect(true).to.equal(true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('extracts frontmatter to "frontmatter" export', async () => {
|
|
19
|
+
const fixture = await loadFixture({
|
|
20
|
+
root: FIXTURE_ROOT,
|
|
21
|
+
integrations: [mdx()],
|
|
22
|
+
});
|
|
23
|
+
await fixture.build();
|
|
24
|
+
|
|
25
|
+
const { titles } = JSON.parse(await fixture.readFile('/glob.json'));
|
|
26
|
+
expect(titles).to.include('Using YAML frontmatter');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('extracts frontmatter to "customFrontmatter" export when configured', async () => {
|
|
30
|
+
const fixture = await loadFixture({
|
|
31
|
+
root: new URL('./fixtures/mdx-custom-frontmatter-name/', import.meta.url),
|
|
32
|
+
integrations: [
|
|
33
|
+
mdx({
|
|
34
|
+
frontmatterOptions: {
|
|
35
|
+
name: 'customFrontmatter',
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
await fixture.build();
|
|
41
|
+
|
|
42
|
+
const { titles } = JSON.parse(await fixture.readFile('/glob.json'));
|
|
43
|
+
expect(titles).to.include('Using YAML frontmatter');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { parseHTML } from 'linkedom';
|
|
5
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
6
|
+
import remarkToc from 'remark-toc';
|
|
7
|
+
|
|
8
|
+
const FIXTURE_ROOT = new URL('./fixtures/mdx-remark-plugins/', import.meta.url);
|
|
9
|
+
|
|
10
|
+
describe('MDX remark plugins', () => {
|
|
11
|
+
it('supports custom remark plugins - TOC', async () => {
|
|
12
|
+
const fixture = await loadFixture({
|
|
13
|
+
root: FIXTURE_ROOT,
|
|
14
|
+
integrations: [
|
|
15
|
+
mdx({
|
|
16
|
+
remarkPlugins: [remarkToc],
|
|
17
|
+
}),
|
|
18
|
+
],
|
|
19
|
+
});
|
|
20
|
+
await fixture.build();
|
|
21
|
+
|
|
22
|
+
const html = await fixture.readFile('/with-toc/index.html');
|
|
23
|
+
const { document } = parseHTML(html);
|
|
24
|
+
|
|
25
|
+
const tocLink1 = document.querySelector('ul a[href="#section-1"]');
|
|
26
|
+
expect(tocLink1).to.not.be.null;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('applies GitHub-flavored markdown by default', async () => {
|
|
30
|
+
const fixture = await loadFixture({
|
|
31
|
+
root: FIXTURE_ROOT,
|
|
32
|
+
integrations: [mdx()],
|
|
33
|
+
});
|
|
34
|
+
await fixture.build();
|
|
35
|
+
|
|
36
|
+
const html = await fixture.readFile('/with-gfm/index.html');
|
|
37
|
+
const { document } = parseHTML(html);
|
|
38
|
+
|
|
39
|
+
const autoGenLink = document.querySelector('a[href="https://example.com"]');
|
|
40
|
+
expect(autoGenLink).to.not.be.null;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('preserves default GitHub-flavored markdown with "extends"', async () => {
|
|
44
|
+
const fixture = await loadFixture({
|
|
45
|
+
root: FIXTURE_ROOT,
|
|
46
|
+
integrations: [
|
|
47
|
+
mdx({
|
|
48
|
+
remarkPlugins: { extends: [remarkToc] },
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
await fixture.build();
|
|
53
|
+
|
|
54
|
+
const html = await fixture.readFile('/with-toc/index.html');
|
|
55
|
+
const { document } = parseHTML(html);
|
|
56
|
+
|
|
57
|
+
const tocLink1 = document.querySelector('ul a[href="#section-1"]');
|
|
58
|
+
expect(tocLink1).to.not.be.null;
|
|
59
|
+
const autoGenLink = document.querySelector('a[href="https://handle-me-gfm.com"]');
|
|
60
|
+
expect(autoGenLink).to.not.be.null;
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { parseHTML } from 'linkedom';
|
|
5
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
6
|
+
|
|
7
|
+
const FIXTURE_ROOT = new URL('./fixtures/mdx-syntax-hightlighting/', import.meta.url);
|
|
8
|
+
|
|
9
|
+
describe('MDX syntax highlighting', () => {
|
|
10
|
+
describe('shiki', () => {
|
|
11
|
+
it('works', async () => {
|
|
12
|
+
const fixture = await loadFixture({
|
|
13
|
+
root: FIXTURE_ROOT,
|
|
14
|
+
markdown: {
|
|
15
|
+
syntaxHighlight: 'shiki',
|
|
16
|
+
},
|
|
17
|
+
integrations: [mdx()],
|
|
18
|
+
});
|
|
19
|
+
await fixture.build();
|
|
20
|
+
|
|
21
|
+
const html = await fixture.readFile('/index.html');
|
|
22
|
+
const { document } = parseHTML(html);
|
|
23
|
+
|
|
24
|
+
const shikiCodeBlock = document.querySelector('pre.shiki');
|
|
25
|
+
expect(shikiCodeBlock).to.not.be.null;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('respects markdown.shikiConfig.theme', async () => {
|
|
29
|
+
const fixture = await loadFixture({
|
|
30
|
+
root: FIXTURE_ROOT,
|
|
31
|
+
markdown: {
|
|
32
|
+
syntaxHighlight: 'shiki',
|
|
33
|
+
shikiConfig: {
|
|
34
|
+
theme: 'dracula',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
integrations: [mdx()],
|
|
38
|
+
});
|
|
39
|
+
await fixture.build();
|
|
40
|
+
|
|
41
|
+
const html = await fixture.readFile('/index.html');
|
|
42
|
+
const { document } = parseHTML(html);
|
|
43
|
+
|
|
44
|
+
const shikiCodeBlock = document.querySelector('pre.shiki.dracula');
|
|
45
|
+
expect(shikiCodeBlock).to.not.be.null;
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('prism', () => {
|
|
50
|
+
it('works', async () => {
|
|
51
|
+
const fixture = await loadFixture({
|
|
52
|
+
root: FIXTURE_ROOT,
|
|
53
|
+
markdown: {
|
|
54
|
+
syntaxHighlight: 'prism',
|
|
55
|
+
},
|
|
56
|
+
integrations: [mdx()],
|
|
57
|
+
});
|
|
58
|
+
await fixture.build();
|
|
59
|
+
|
|
60
|
+
const html = await fixture.readFile('/index.html');
|
|
61
|
+
const { document } = parseHTML(html);
|
|
62
|
+
|
|
63
|
+
const prismCodeBlock = document.querySelector('pre.language-astro');
|
|
64
|
+
expect(prismCodeBlock).to.not.be.null;
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
5
|
+
|
|
6
|
+
describe('MDX url export', () => {
|
|
7
|
+
let fixture;
|
|
8
|
+
|
|
9
|
+
before(async () => {
|
|
10
|
+
fixture = await loadFixture({
|
|
11
|
+
root: new URL('./fixtures/mdx-url-export/', import.meta.url),
|
|
12
|
+
integrations: [mdx()],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
await fixture.build();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('generates correct urls in glob result', async () => {
|
|
19
|
+
const { urls } = JSON.parse(await fixture.readFile('/pages.json'));
|
|
20
|
+
expect(urls).to.include('/test-1');
|
|
21
|
+
expect(urls).to.include('/test-2');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('respects "export url" overrides in glob result', async () => {
|
|
25
|
+
const { urls } = JSON.parse(await fixture.readFile('/pages.json'));
|
|
26
|
+
expect(urls).to.include('/AH!');
|
|
27
|
+
});
|
|
28
|
+
});
|