@astrojs/mdx 0.17.0 → 0.18.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.
@@ -1,5 +1,5 @@
1
- @astrojs/mdx:build: cache hit, replaying output 0e77d93ea69c7ebc
2
- @astrojs/mdx:build: 
3
- @astrojs/mdx:build: > @astrojs/mdx@0.17.0 build /home/runner/work/astro/astro/packages/integrations/mdx
4
- @astrojs/mdx:build: > astro-scripts build "src/**/*.ts" && tsc
5
- @astrojs/mdx:build: 
1
+ @astrojs/mdx:build: cache hit, replaying output 61e81c86fa4b4798
2
+ @astrojs/mdx:build: 
3
+ @astrojs/mdx:build: > @astrojs/mdx@0.18.0 build /home/runner/work/astro/astro/packages/integrations/mdx
4
+ @astrojs/mdx:build: > astro-scripts build "src/**/*.ts" && tsc
5
+ @astrojs/mdx:build: 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # @astrojs/mdx
2
2
 
3
+ ## 0.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#6344](https://github.com/withastro/astro/pull/6344) [`694918a56`](https://github.com/withastro/astro/commit/694918a56b01104831296be0c25456135a63c784) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Add a new experimental flag (`experimental.assets`) to enable our new core Assets story.
8
+
9
+ This unlocks a few features:
10
+
11
+ - A new built-in image component and JavaScript API to transform and optimize images.
12
+ - Relative images with automatic optimization in Markdown.
13
+ - Support for validating assets using content collections.
14
+ - and more!
15
+
16
+ See [Assets (Experimental)](https://docs.astro.build/en/guides/assets/) on our docs site for more information on how to use this feature!
17
+
18
+ - [#6213](https://github.com/withastro/astro/pull/6213) [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updated compilation settings to disable downlevelling for Node 14
19
+
20
+ ### Patch Changes
21
+
22
+ - [#6209](https://github.com/withastro/astro/pull/6209) [`fec583909`](https://github.com/withastro/astro/commit/fec583909ab62829dc0c1600e2387979365f2b94) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Introduce the (experimental) `@astrojs/markdoc` integration. This unlocks Markdoc inside your Content Collections, bringing support for Astro and UI components in your content. This also improves Astro core internals to make Content Collections extensible to more file types in the future.
23
+
24
+ You can install this integration using the `astro add` command:
25
+
26
+ ```
27
+ astro add markdoc
28
+ ```
29
+
30
+ [Read the `@astrojs/markdoc` documentation](https://docs.astro.build/en/guides/integrations-guide/markdoc/) for usage instructions, and browse the [new `with-markdoc` starter](https://astro.new/with-markdoc) to try for yourself.
31
+
32
+ - Updated dependencies [[`694918a56`](https://github.com/withastro/astro/commit/694918a56b01104831296be0c25456135a63c784), [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808)]:
33
+ - @astrojs/markdown-remark@2.1.0
34
+ - @astrojs/prism@2.1.0
35
+
36
+ ## 0.17.2
37
+
38
+ ### Patch Changes
39
+
40
+ - [#6296](https://github.com/withastro/astro/pull/6296) [`075b87e8b`](https://github.com/withastro/astro/commit/075b87e8b72a69a608cd2ff1196dc0989e2cf1e1) Thanks [@RaphaelBossek](https://github.com/RaphaelBossek)! - Update to `es-module-lexer@1.1.1`
41
+
42
+ ## 0.17.1
43
+
44
+ - Updated to es-module-lexer@1.1.1
45
+
3
46
  ## 0.17.0
4
47
 
5
48
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { markdownConfigDefaults } from '@astrojs/markdown-remark';
2
2
  import { PluggableList } from '@mdx-js/mdx/lib/core.js';
3
- import type { AstroIntegration } from 'astro';
3
+ import type { AstroIntegration, ContentEntryType, HookParameters } from 'astro';
4
4
  import type { Options as RemarkRehypeOptions } from 'remark-rehype';
5
5
  export declare type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | 'rehypePlugins'> & {
6
6
  extendMarkdownConfig: boolean;
@@ -9,4 +9,14 @@ export declare type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlug
9
9
  rehypePlugins: PluggableList;
10
10
  remarkRehype: RemarkRehypeOptions;
11
11
  };
12
- export default function mdx(partialMdxOptions?: Partial<MdxOptions>): AstroIntegration;
12
+ declare type IntegrationWithPrivateHooks = {
13
+ name: string;
14
+ hooks: Omit<AstroIntegration['hooks'], 'astro:config:setup'> & {
15
+ 'astro:config:setup': (params: HookParameters<'astro:config:setup'> & {
16
+ addPageExtension: (extension: string) => void;
17
+ addContentEntryType: (contentEntryType: ContentEntryType) => void;
18
+ }) => void | Promise<void>;
19
+ };
20
+ };
21
+ export default function mdx(partialMdxOptions?: Partial<MdxOptions>): IntegrationWithPrivateHooks;
22
+ export {};
package/dist/index.js CHANGED
@@ -4,19 +4,44 @@ import { compile as mdxCompile } from "@mdx-js/mdx";
4
4
  import mdxPlugin from "@mdx-js/rollup";
5
5
  import { parse as parseESM } from "es-module-lexer";
6
6
  import fs from "node:fs/promises";
7
+ import { fileURLToPath } from "node:url";
7
8
  import { VFile } from "vfile";
8
9
  import { getRehypePlugins, getRemarkPlugins, recmaInjectImportMetaEnvPlugin } from "./plugins.js";
9
- import { getFileInfo, parseFrontmatter } from "./utils.js";
10
+ import { getFileInfo, ignoreStringPlugins, parseFrontmatter } from "./utils.js";
10
11
  function mdx(partialMdxOptions = {}) {
11
12
  return {
12
13
  name: "@astrojs/mdx",
13
14
  hooks: {
14
- "astro:config:setup": async ({ updateConfig, config, addPageExtension, command }) => {
15
+ "astro:config:setup": async ({
16
+ updateConfig,
17
+ config,
18
+ addPageExtension,
19
+ addContentEntryType,
20
+ command
21
+ }) => {
15
22
  addPageExtension(".mdx");
16
- const extendMarkdownConfig = partialMdxOptions.extendMarkdownConfig ?? defaultOptions.extendMarkdownConfig;
23
+ addContentEntryType({
24
+ extensions: [".mdx"],
25
+ async getEntryInfo({ fileUrl, contents }) {
26
+ const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
27
+ return {
28
+ data: parsed.data,
29
+ body: parsed.content,
30
+ slug: parsed.data.slug,
31
+ rawData: parsed.matter
32
+ };
33
+ },
34
+ contentModuleTypes: await fs.readFile(
35
+ new URL("../template/content-module-types.d.ts", import.meta.url),
36
+ "utf-8"
37
+ )
38
+ });
39
+ const extendMarkdownConfig = partialMdxOptions.extendMarkdownConfig ?? defaultMdxOptions.extendMarkdownConfig;
17
40
  const mdxOptions = applyDefaultOptions({
18
41
  options: partialMdxOptions,
19
- defaults: extendMarkdownConfig ? config.markdown : defaultOptions
42
+ defaults: markdownConfigToMdxOptions(
43
+ extendMarkdownConfig ? config.markdown : markdownConfigDefaults
44
+ )
20
45
  });
21
46
  const mdxPluginOpts = {
22
47
  remarkPlugins: await getRemarkPlugins(mdxOptions, config),
@@ -78,15 +103,15 @@ function mdx(partialMdxOptions = {}) {
78
103
  code = 'import { Fragment } from "astro/jsx-runtime"\n' + code;
79
104
  }
80
105
  const { fileUrl, fileId } = getFileInfo(id, config);
81
- if (!moduleExports.includes("url")) {
106
+ if (!moduleExports.find(({ n }) => n === "url")) {
82
107
  code += `
83
108
  export const url = ${JSON.stringify(fileUrl)};`;
84
109
  }
85
- if (!moduleExports.includes("file")) {
110
+ if (!moduleExports.find(({ n }) => n === "file")) {
86
111
  code += `
87
112
  export const file = ${JSON.stringify(fileId)};`;
88
113
  }
89
- if (!moduleExports.includes("Content")) {
114
+ if (!moduleExports.find(({ n }) => n === "Content")) {
90
115
  code = code.replace("export default MDXContent;", "");
91
116
  code += `
92
117
  export const Content = (props = {}) => MDXContent({
@@ -113,14 +138,19 @@ if (import.meta.hot) {
113
138
  }
114
139
  };
115
140
  }
116
- const defaultOptions = {
117
- ...markdownConfigDefaults,
141
+ const defaultMdxOptions = {
118
142
  extendMarkdownConfig: true,
119
- recmaPlugins: [],
120
- remarkPlugins: [],
121
- rehypePlugins: [],
122
- remarkRehype: {}
143
+ recmaPlugins: []
123
144
  };
145
+ function markdownConfigToMdxOptions(markdownConfig) {
146
+ return {
147
+ ...defaultMdxOptions,
148
+ ...markdownConfig,
149
+ remarkPlugins: ignoreStringPlugins(markdownConfig.remarkPlugins),
150
+ rehypePlugins: ignoreStringPlugins(markdownConfig.rehypePlugins),
151
+ remarkRehype: markdownConfig.remarkRehype ?? {}
152
+ };
153
+ }
124
154
  function applyDefaultOptions({
125
155
  options,
126
156
  defaults
package/dist/plugins.js CHANGED
@@ -5,17 +5,15 @@ import {
5
5
  } from "@astrojs/markdown-remark/dist/internal.js";
6
6
  import { nodeTypes } from "@mdx-js/mdx";
7
7
  import { visit as estreeVisit } from "estree-util-visit";
8
- import { bold, yellow } from "kleur/colors";
9
- import { pathToFileURL } from "node:url";
10
8
  import rehypeRaw from "rehype-raw";
11
9
  import remarkGfm from "remark-gfm";
12
10
  import remarkSmartypants from "remark-smartypants";
13
- import { visit } from "unist-util-visit";
14
11
  import { rehypeInjectHeadingsExport } from "./rehype-collect-headings.js";
15
12
  import rehypeMetaString from "./rehype-meta-string.js";
16
13
  import remarkPrism from "./remark-prism.js";
17
14
  import remarkShiki from "./remark-shiki.js";
18
- import { isRelativePath, jsToTreeNode } from "./utils.js";
15
+ import { jsToTreeNode } from "./utils.js";
16
+ const isPerformanceBenchmark = Boolean(process.env.ASTRO_PERFORMANCE_BENCHMARK);
19
17
  function recmaInjectImportMetaEnvPlugin({
20
18
  importMetaEnv
21
19
  }) {
@@ -75,43 +73,25 @@ function rehypeApplyFrontmatterExport() {
75
73
  tree.children = exportNodes.concat(tree.children);
76
74
  };
77
75
  }
78
- function toRemarkContentRelImageError({ srcDir }) {
79
- const contentDir = new URL("content/", srcDir);
80
- return function remarkContentRelImageError() {
81
- return (tree, vfile) => {
82
- const isContentFile = pathToFileURL(vfile.path).href.startsWith(contentDir.href);
83
- if (!isContentFile)
84
- return;
85
- const relImagePaths = /* @__PURE__ */ new Set();
86
- visit(tree, "image", function raiseError(node) {
87
- if (isRelativePath(node.url)) {
88
- relImagePaths.add(node.url);
89
- }
90
- });
91
- if (relImagePaths.size === 0)
92
- return;
93
- const errorMessage = `Relative image paths are not supported in the content/ directory. Place local images in the public/ directory and use absolute paths (see https://docs.astro.build/en/guides/images/#in-markdown-files):
94
- ` + [...relImagePaths].map((path) => JSON.stringify(path)).join(",\n");
95
- throw new Error(errorMessage);
96
- };
97
- };
98
- }
99
76
  async function getRemarkPlugins(mdxOptions, config) {
100
77
  let remarkPlugins = [];
101
- if (mdxOptions.gfm) {
102
- remarkPlugins.push(remarkGfm);
103
- }
104
- if (mdxOptions.smartypants) {
105
- remarkPlugins.push(remarkSmartypants);
106
- }
107
- remarkPlugins = [...remarkPlugins, ...ignoreStringPlugins(mdxOptions.remarkPlugins)];
108
- if (mdxOptions.syntaxHighlight === "shiki") {
109
- remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
78
+ if (!isPerformanceBenchmark) {
79
+ if (mdxOptions.gfm) {
80
+ remarkPlugins.push(remarkGfm);
81
+ }
82
+ if (mdxOptions.smartypants) {
83
+ remarkPlugins.push(remarkSmartypants);
84
+ }
110
85
  }
111
- if (mdxOptions.syntaxHighlight === "prism") {
112
- remarkPlugins.push(remarkPrism);
86
+ remarkPlugins = [...remarkPlugins, ...mdxOptions.remarkPlugins];
87
+ if (!isPerformanceBenchmark) {
88
+ if (mdxOptions.syntaxHighlight === "shiki") {
89
+ remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
90
+ }
91
+ if (mdxOptions.syntaxHighlight === "prism") {
92
+ remarkPlugins.push(remarkPrism);
93
+ }
113
94
  }
114
- remarkPlugins.push(toRemarkContentRelImageError(config));
115
95
  return remarkPlugins;
116
96
  }
117
97
  function getRehypePlugins(mdxOptions) {
@@ -121,34 +101,12 @@ function getRehypePlugins(mdxOptions) {
121
101
  ];
122
102
  rehypePlugins = [
123
103
  ...rehypePlugins,
124
- ...ignoreStringPlugins(mdxOptions.rehypePlugins),
125
- rehypeHeadingIds,
126
- rehypeInjectHeadingsExport,
104
+ ...mdxOptions.rehypePlugins,
105
+ ...isPerformanceBenchmark ? [] : [rehypeHeadingIds, rehypeInjectHeadingsExport],
127
106
  rehypeApplyFrontmatterExport
128
107
  ];
129
108
  return rehypePlugins;
130
109
  }
131
- function ignoreStringPlugins(plugins) {
132
- let validPlugins = [];
133
- let hasInvalidPlugin = false;
134
- for (const plugin of plugins) {
135
- if (typeof plugin === "string") {
136
- console.warn(yellow(`[MDX] ${bold(plugin)} not applied.`));
137
- hasInvalidPlugin = true;
138
- } else if (Array.isArray(plugin) && typeof plugin[0] === "string") {
139
- console.warn(yellow(`[MDX] ${bold(plugin[0])} not applied.`));
140
- hasInvalidPlugin = true;
141
- } else {
142
- validPlugins.push(plugin);
143
- }
144
- }
145
- if (hasInvalidPlugin) {
146
- console.warn(
147
- `To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`
148
- );
149
- }
150
- return validPlugins;
151
- }
152
110
  function getImportMetaEnvVariableName(node) {
153
111
  try {
154
112
  if (node.object.type !== "MemberExpression" || node.property.type !== "Identifier")
@@ -4,7 +4,7 @@ function rehypeMetaString() {
4
4
  visit(tree, (node) => {
5
5
  var _a;
6
6
  if (node.type === "element" && node.tagName === "code" && ((_a = node.data) == null ? void 0 : _a.meta)) {
7
- node.properties ?? (node.properties = {});
7
+ node.properties ??= {};
8
8
  node.properties.metastring = node.data.meta;
9
9
  }
10
10
  });
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { PluggableList } from '@mdx-js/mdx/lib/core.js';
1
2
  import type { Options as AcornOpts } from 'acorn';
2
3
  import type { AstroConfig } from 'astro';
3
4
  import matter from 'gray-matter';
@@ -14,5 +15,5 @@ export declare function getFileInfo(id: string, config: AstroConfig): FileInfo;
14
15
  */
15
16
  export declare function parseFrontmatter(code: string, id: string): matter.GrayMatterFile<string>;
16
17
  export declare function jsToTreeNode(jsString: string, acornOpts?: AcornOpts): MdxjsEsm;
17
- export declare function isRelativePath(path: string): boolean;
18
+ export declare function ignoreStringPlugins(plugins: any[]): PluggableList;
18
19
  export {};
package/dist/utils.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { parse } from "acorn";
2
2
  import matter from "gray-matter";
3
+ import { bold, yellow } from "kleur/colors";
3
4
  function appendForwardSlash(path) {
4
5
  return path.endsWith("/") ? path : path + "/";
5
6
  }
@@ -59,23 +60,30 @@ function jsToTreeNode(jsString, acornOpts = {
59
60
  }
60
61
  };
61
62
  }
62
- function isRelativePath(path) {
63
- return startsWithDotDotSlash(path) || startsWithDotSlash(path);
64
- }
65
- function startsWithDotDotSlash(path) {
66
- const c1 = path[0];
67
- const c2 = path[1];
68
- const c3 = path[2];
69
- return c1 === "." && c2 === "." && c3 === "/";
70
- }
71
- function startsWithDotSlash(path) {
72
- const c1 = path[0];
73
- const c2 = path[1];
74
- return c1 === "." && c2 === "/";
63
+ function ignoreStringPlugins(plugins) {
64
+ let validPlugins = [];
65
+ let hasInvalidPlugin = false;
66
+ for (const plugin of plugins) {
67
+ if (typeof plugin === "string") {
68
+ console.warn(yellow(`[MDX] ${bold(plugin)} not applied.`));
69
+ hasInvalidPlugin = true;
70
+ } else if (Array.isArray(plugin) && typeof plugin[0] === "string") {
71
+ console.warn(yellow(`[MDX] ${bold(plugin[0])} not applied.`));
72
+ hasInvalidPlugin = true;
73
+ } else {
74
+ validPlugins.push(plugin);
75
+ }
76
+ }
77
+ if (hasInvalidPlugin) {
78
+ console.warn(
79
+ `To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`
80
+ );
81
+ }
82
+ return validPlugins;
75
83
  }
76
84
  export {
77
85
  getFileInfo,
78
- isRelativePath,
86
+ ignoreStringPlugins,
79
87
  jsToTreeNode,
80
88
  parseFrontmatter
81
89
  };
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.17.0",
4
+ "version": "0.18.0",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
7
7
  "author": "withastro",
@@ -23,12 +23,12 @@
23
23
  "./package.json": "./package.json"
24
24
  },
25
25
  "dependencies": {
26
- "@astrojs/markdown-remark": "^2.0.1",
27
- "@astrojs/prism": "^2.0.0",
26
+ "@astrojs/markdown-remark": "^2.1.0",
27
+ "@astrojs/prism": "^2.1.0",
28
28
  "@mdx-js/mdx": "^2.3.0",
29
29
  "@mdx-js/rollup": "^2.3.0",
30
30
  "acorn": "^8.8.0",
31
- "es-module-lexer": "^0.10.5",
31
+ "es-module-lexer": "^1.1.1",
32
32
  "estree-util-visit": "^1.2.0",
33
33
  "github-slugger": "^1.4.0",
34
34
  "gray-matter": "^4.0.3",
@@ -48,8 +48,8 @@
48
48
  "@types/mdast": "^3.0.10",
49
49
  "@types/mocha": "^9.1.1",
50
50
  "@types/yargs-parser": "^21.0.0",
51
- "astro": "2.0.13",
52
- "astro-scripts": "0.0.10",
51
+ "astro": "2.1.0",
52
+ "astro-scripts": "0.0.14",
53
53
  "chai": "^4.3.6",
54
54
  "cheerio": "^1.0.0-rc.11",
55
55
  "linkedom": "^0.14.12",
@@ -61,7 +61,7 @@
61
61
  "remark-rehype": "^10.1.0",
62
62
  "remark-shiki-twoslash": "^3.1.0",
63
63
  "remark-toc": "^8.0.1",
64
- "vite": "^4.0.3"
64
+ "vite": "^4.1.2"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">=16.12.0"
package/src/index.ts CHANGED
@@ -3,14 +3,15 @@ import { toRemarkInitializeAstroData } from '@astrojs/markdown-remark/dist/inter
3
3
  import { compile as mdxCompile } from '@mdx-js/mdx';
4
4
  import { PluggableList } from '@mdx-js/mdx/lib/core.js';
5
5
  import mdxPlugin, { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
6
- import type { AstroIntegration } from 'astro';
6
+ import type { AstroIntegration, ContentEntryType, HookParameters } from 'astro';
7
7
  import { parse as parseESM } from 'es-module-lexer';
8
8
  import fs from 'node:fs/promises';
9
+ import { fileURLToPath } from 'node:url';
9
10
  import type { Options as RemarkRehypeOptions } from 'remark-rehype';
10
11
  import { VFile } from 'vfile';
11
12
  import type { Plugin as VitePlugin } from 'vite';
12
13
  import { getRehypePlugins, getRemarkPlugins, recmaInjectImportMetaEnvPlugin } from './plugins.js';
13
- import { getFileInfo, parseFrontmatter } from './utils.js';
14
+ import { getFileInfo, ignoreStringPlugins, parseFrontmatter } from './utils.js';
14
15
 
15
16
  export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | 'rehypePlugins'> & {
16
17
  extendMarkdownConfig: boolean;
@@ -22,19 +23,59 @@ export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | '
22
23
  remarkRehype: RemarkRehypeOptions;
23
24
  };
24
25
 
25
- export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroIntegration {
26
+ type IntegrationWithPrivateHooks = {
27
+ name: string;
28
+ hooks: Omit<AstroIntegration['hooks'], 'astro:config:setup'> & {
29
+ 'astro:config:setup': (
30
+ params: HookParameters<'astro:config:setup'> & {
31
+ // `addPageExtension` and `contentEntryType` are not a public APIs
32
+ // Add type defs here
33
+ addPageExtension: (extension: string) => void;
34
+ addContentEntryType: (contentEntryType: ContentEntryType) => void;
35
+ }
36
+ ) => void | Promise<void>;
37
+ };
38
+ };
39
+
40
+ export default function mdx(
41
+ partialMdxOptions: Partial<MdxOptions> = {}
42
+ ): IntegrationWithPrivateHooks {
26
43
  return {
27
44
  name: '@astrojs/mdx',
28
45
  hooks: {
29
- 'astro:config:setup': async ({ updateConfig, config, addPageExtension, command }: any) => {
46
+ 'astro:config:setup': async ({
47
+ updateConfig,
48
+ config,
49
+ addPageExtension,
50
+ addContentEntryType,
51
+ command,
52
+ }) => {
30
53
  addPageExtension('.mdx');
54
+ addContentEntryType({
55
+ extensions: ['.mdx'],
56
+ async getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) {
57
+ const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
58
+ return {
59
+ data: parsed.data,
60
+ body: parsed.content,
61
+ slug: parsed.data.slug,
62
+ rawData: parsed.matter,
63
+ };
64
+ },
65
+ contentModuleTypes: await fs.readFile(
66
+ new URL('../template/content-module-types.d.ts', import.meta.url),
67
+ 'utf-8'
68
+ ),
69
+ });
31
70
 
32
71
  const extendMarkdownConfig =
33
- partialMdxOptions.extendMarkdownConfig ?? defaultOptions.extendMarkdownConfig;
72
+ partialMdxOptions.extendMarkdownConfig ?? defaultMdxOptions.extendMarkdownConfig;
34
73
 
35
74
  const mdxOptions = applyDefaultOptions({
36
75
  options: partialMdxOptions,
37
- defaults: extendMarkdownConfig ? config.markdown : defaultOptions,
76
+ defaults: markdownConfigToMdxOptions(
77
+ extendMarkdownConfig ? config.markdown : markdownConfigDefaults
78
+ ),
38
79
  });
39
80
 
40
81
  const mdxPluginOpts: MdxRollupPluginOptions = {
@@ -112,13 +153,13 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
112
153
  }
113
154
 
114
155
  const { fileUrl, fileId } = getFileInfo(id, config);
115
- if (!moduleExports.includes('url')) {
156
+ if (!moduleExports.find(({ n }) => n === 'url')) {
116
157
  code += `\nexport const url = ${JSON.stringify(fileUrl)};`;
117
158
  }
118
- if (!moduleExports.includes('file')) {
159
+ if (!moduleExports.find(({ n }) => n === 'file')) {
119
160
  code += `\nexport const file = ${JSON.stringify(fileId)};`;
120
161
  }
121
- if (!moduleExports.includes('Content')) {
162
+ if (!moduleExports.find(({ n }) => n === 'Content')) {
122
163
  // Make `Content` the default export so we can wrap `MDXContent` and pass in `Fragment`
123
164
  code = code.replace('export default MDXContent;', '');
124
165
  code += `\nexport const Content = (props = {}) => MDXContent({
@@ -149,15 +190,21 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
149
190
  };
150
191
  }
151
192
 
152
- const defaultOptions: MdxOptions = {
153
- ...markdownConfigDefaults,
193
+ const defaultMdxOptions = {
154
194
  extendMarkdownConfig: true,
155
195
  recmaPlugins: [],
156
- remarkPlugins: [],
157
- rehypePlugins: [],
158
- remarkRehype: {},
159
196
  };
160
197
 
198
+ function markdownConfigToMdxOptions(markdownConfig: typeof markdownConfigDefaults): MdxOptions {
199
+ return {
200
+ ...defaultMdxOptions,
201
+ ...markdownConfig,
202
+ remarkPlugins: ignoreStringPlugins(markdownConfig.remarkPlugins),
203
+ rehypePlugins: ignoreStringPlugins(markdownConfig.rehypePlugins),
204
+ remarkRehype: (markdownConfig.remarkRehype as any) ?? {},
205
+ };
206
+ }
207
+
161
208
  function applyDefaultOptions({
162
209
  options,
163
210
  defaults,
package/src/plugins.ts CHANGED
@@ -9,20 +9,19 @@ import type { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
9
9
  import type { AstroConfig } from 'astro';
10
10
  import type { Literal, MemberExpression } from 'estree';
11
11
  import { visit as estreeVisit } from 'estree-util-visit';
12
- import { bold, yellow } from 'kleur/colors';
13
- import type { Image } from 'mdast';
14
- import { pathToFileURL } from 'node:url';
15
12
  import rehypeRaw from 'rehype-raw';
16
13
  import remarkGfm from 'remark-gfm';
17
14
  import remarkSmartypants from 'remark-smartypants';
18
- import { visit } from 'unist-util-visit';
19
15
  import type { VFile } from 'vfile';
20
16
  import { MdxOptions } from './index.js';
21
17
  import { rehypeInjectHeadingsExport } from './rehype-collect-headings.js';
22
18
  import rehypeMetaString from './rehype-meta-string.js';
23
19
  import remarkPrism from './remark-prism.js';
24
20
  import remarkShiki from './remark-shiki.js';
25
- import { isRelativePath, jsToTreeNode } from './utils.js';
21
+ import { jsToTreeNode } from './utils.js';
22
+
23
+ // Skip nonessential plugins during performance benchmark runs
24
+ const isPerformanceBenchmark = Boolean(process.env.ASTRO_PERFORMANCE_BENCHMARK);
26
25
 
27
26
  export function recmaInjectImportMetaEnvPlugin({
28
27
  importMetaEnv,
@@ -96,60 +95,33 @@ export function rehypeApplyFrontmatterExport() {
96
95
  };
97
96
  }
98
97
 
99
- /**
100
- * `src/content/` does not support relative image paths.
101
- * This plugin throws an error if any are found
102
- */
103
- function toRemarkContentRelImageError({ srcDir }: { srcDir: URL }) {
104
- const contentDir = new URL('content/', srcDir);
105
- return function remarkContentRelImageError() {
106
- return (tree: any, vfile: VFile) => {
107
- const isContentFile = pathToFileURL(vfile.path).href.startsWith(contentDir.href);
108
- if (!isContentFile) return;
109
-
110
- const relImagePaths = new Set<string>();
111
- visit(tree, 'image', function raiseError(node: Image) {
112
- if (isRelativePath(node.url)) {
113
- relImagePaths.add(node.url);
114
- }
115
- });
116
- if (relImagePaths.size === 0) return;
117
-
118
- const errorMessage =
119
- `Relative image paths are not supported in the content/ directory. Place local images in the public/ directory and use absolute paths (see https://docs.astro.build/en/guides/images/#in-markdown-files):\n` +
120
- [...relImagePaths].map((path) => JSON.stringify(path)).join(',\n');
121
-
122
- throw new Error(errorMessage);
123
- };
124
- };
125
- }
126
-
127
98
  export async function getRemarkPlugins(
128
99
  mdxOptions: MdxOptions,
129
100
  config: AstroConfig
130
101
  ): Promise<MdxRollupPluginOptions['remarkPlugins']> {
131
102
  let remarkPlugins: PluggableList = [];
132
103
 
133
- if (mdxOptions.gfm) {
134
- remarkPlugins.push(remarkGfm);
135
- }
136
- if (mdxOptions.smartypants) {
137
- remarkPlugins.push(remarkSmartypants);
104
+ if (!isPerformanceBenchmark) {
105
+ if (mdxOptions.gfm) {
106
+ remarkPlugins.push(remarkGfm);
107
+ }
108
+ if (mdxOptions.smartypants) {
109
+ remarkPlugins.push(remarkSmartypants);
110
+ }
138
111
  }
139
112
 
140
- remarkPlugins = [...remarkPlugins, ...ignoreStringPlugins(mdxOptions.remarkPlugins)];
113
+ remarkPlugins = [...remarkPlugins, ...mdxOptions.remarkPlugins];
141
114
 
142
- // Apply syntax highlighters after user plugins to match `markdown/remark` behavior
143
- if (mdxOptions.syntaxHighlight === 'shiki') {
144
- remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
145
- }
146
- if (mdxOptions.syntaxHighlight === 'prism') {
147
- remarkPlugins.push(remarkPrism);
115
+ if (!isPerformanceBenchmark) {
116
+ // Apply syntax highlighters after user plugins to match `markdown/remark` behavior
117
+ if (mdxOptions.syntaxHighlight === 'shiki') {
118
+ remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
119
+ }
120
+ if (mdxOptions.syntaxHighlight === 'prism') {
121
+ remarkPlugins.push(remarkPrism);
122
+ }
148
123
  }
149
124
 
150
- // Apply last in case user plugins resolve relative image paths
151
- remarkPlugins.push(toRemarkContentRelImageError(config));
152
-
153
125
  return remarkPlugins;
154
126
  }
155
127
 
@@ -163,39 +135,16 @@ export function getRehypePlugins(mdxOptions: MdxOptions): MdxRollupPluginOptions
163
135
 
164
136
  rehypePlugins = [
165
137
  ...rehypePlugins,
166
- ...ignoreStringPlugins(mdxOptions.rehypePlugins),
138
+ ...mdxOptions.rehypePlugins,
167
139
  // getHeadings() is guaranteed by TS, so this must be included.
168
140
  // We run `rehypeHeadingIds` _last_ to respect any custom IDs set by user plugins.
169
- rehypeHeadingIds,
170
- rehypeInjectHeadingsExport,
141
+ ...(isPerformanceBenchmark ? [] : [rehypeHeadingIds, rehypeInjectHeadingsExport]),
171
142
  // computed from `astro.data.frontmatter` in VFile data
172
143
  rehypeApplyFrontmatterExport,
173
144
  ];
174
145
  return rehypePlugins;
175
146
  }
176
147
 
177
- function ignoreStringPlugins(plugins: any[]) {
178
- let validPlugins: PluggableList = [];
179
- let hasInvalidPlugin = false;
180
- for (const plugin of plugins) {
181
- if (typeof plugin === 'string') {
182
- console.warn(yellow(`[MDX] ${bold(plugin)} not applied.`));
183
- hasInvalidPlugin = true;
184
- } else if (Array.isArray(plugin) && typeof plugin[0] === 'string') {
185
- console.warn(yellow(`[MDX] ${bold(plugin[0])} not applied.`));
186
- hasInvalidPlugin = true;
187
- } else {
188
- validPlugins.push(plugin);
189
- }
190
- }
191
- if (hasInvalidPlugin) {
192
- console.warn(
193
- `To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`
194
- );
195
- }
196
- return validPlugins;
197
- }
198
-
199
148
  /**
200
149
  * Check if estree entry is "import.meta.env.VARIABLE"
201
150
  * If it is, return the variable name (i.e. "VARIABLE")
package/src/utils.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import type { PluggableList } from '@mdx-js/mdx/lib/core.js';
1
2
  import type { Options as AcornOpts } from 'acorn';
2
3
  import { parse } from 'acorn';
3
4
  import type { AstroConfig, SSRError } from 'astro';
4
5
  import matter from 'gray-matter';
6
+ import { bold, yellow } from 'kleur/colors';
5
7
  import type { MdxjsEsm } from 'mdast-util-mdx';
6
8
 
7
9
  function appendForwardSlash(path: string) {
@@ -83,20 +85,24 @@ export function jsToTreeNode(
83
85
  };
84
86
  }
85
87
 
86
- // Following utils taken from `packages/astro/src/core/path.ts`:
87
- export function isRelativePath(path: string) {
88
- return startsWithDotDotSlash(path) || startsWithDotSlash(path);
89
- }
90
-
91
- function startsWithDotDotSlash(path: string) {
92
- const c1 = path[0];
93
- const c2 = path[1];
94
- const c3 = path[2];
95
- return c1 === '.' && c2 === '.' && c3 === '/';
96
- }
97
-
98
- function startsWithDotSlash(path: string) {
99
- const c1 = path[0];
100
- const c2 = path[1];
101
- return c1 === '.' && c2 === '/';
88
+ export function ignoreStringPlugins(plugins: any[]): PluggableList {
89
+ let validPlugins: PluggableList = [];
90
+ let hasInvalidPlugin = false;
91
+ for (const plugin of plugins) {
92
+ if (typeof plugin === 'string') {
93
+ console.warn(yellow(`[MDX] ${bold(plugin)} not applied.`));
94
+ hasInvalidPlugin = true;
95
+ } else if (Array.isArray(plugin) && typeof plugin[0] === 'string') {
96
+ console.warn(yellow(`[MDX] ${bold(plugin[0])} not applied.`));
97
+ hasInvalidPlugin = true;
98
+ } else {
99
+ validPlugins.push(plugin);
100
+ }
101
+ }
102
+ if (hasInvalidPlugin) {
103
+ console.warn(
104
+ `To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`
105
+ );
106
+ }
107
+ return validPlugins;
102
108
  }
@@ -0,0 +1,9 @@
1
+ declare module 'astro:content' {
2
+ interface Render {
3
+ '.mdx': Promise<{
4
+ Content: import('astro').MarkdownInstance<{}>['Content'];
5
+ headings: import('astro').MarkdownHeading[];
6
+ remarkPluginFrontmatter: Record<string, any>;
7
+ }>;
8
+ }
9
+ }
package/tsconfig.json CHANGED
@@ -3,8 +3,8 @@
3
3
  "include": ["src"],
4
4
  "compilerOptions": {
5
5
  "allowJs": true,
6
- "module": "ES2020",
6
+ "module": "ES2022",
7
7
  "outDir": "./dist",
8
- "target": "ES2020"
8
+ "target": "ES2021"
9
9
  }
10
10
  }