@astrojs/mdx 0.3.0 → 0.3.1

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 5ec97556db3f4322
2
- @astrojs/mdx:build: 
3
- @astrojs/mdx:build: > @astrojs/mdx@0.3.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 0a3d73b5c732032a
2
+ @astrojs/mdx:build: 
3
+ @astrojs/mdx:build: > @astrojs/mdx@0.3.1 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,11 @@
1
1
  # @astrojs/mdx
2
2
 
3
+ ## 0.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4076](https://github.com/withastro/astro/pull/4076) [`6120a71e5`](https://github.com/withastro/astro/commit/6120a71e5425ad55a17ddac800d64a3f50273bce) Thanks [@matthewp](https://github.com/matthewp)! - Ensure file and url are always present in MDX for Astro.glob
8
+
3
9
  ## 0.3.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -134,6 +134,47 @@ const posts = await Astro.glob('./*.mdx');
134
134
  ))}
135
135
  ```
136
136
 
137
+ ### Layouts
138
+
139
+ You can use the [MDX layout component](https://mdxjs.com/docs/using-mdx/#layout) to specify a layout component to wrap all page content. This is done with a default export statement at the end of your `.mdx` file:
140
+
141
+ ```mdx
142
+ // src/pages/my-page.mdx
143
+
144
+ export {default} from '../../layouts/BaseLayout.astro';
145
+ ```
146
+
147
+ You can also import and use a [`<Layout />` component](/en/core-concepts/layouts/) for your MDX page content, and pass all the variables declared in frontmatter as props.
148
+
149
+ ```mdx
150
+ ---
151
+ // src/pages/posts/first-post.mdx
152
+
153
+ title: 'My first MDX post'
154
+ publishDate: '21 September 2022'
155
+ ---
156
+ import BaseLayout from '../layouts/BaseLayout.astro';
157
+
158
+ <BaseLayout {...frontmatter}>
159
+ # {frontmatter.title}
160
+
161
+ Welcome to my new Astro blog, using MDX!
162
+ </BaseLayout>
163
+ ```
164
+ Then, your values are available to you through `Astro.props` in your layout, and your MDX content will be injected into the page where your `<slot />` component is written:
165
+
166
+ ```astro
167
+ ---
168
+ // src/layouts/BaseLayout.astro
169
+ const { title, publishDate } = Astro.props;
170
+ ---
171
+ <!-- -->
172
+ <h1>{title}</h1>
173
+ <slot />
174
+ <p>Published on {publishDate}</p>
175
+ <!-- -->
176
+ ```
177
+
137
178
  ### Syntax highlighting
138
179
 
139
180
  The MDX integration respects [your project's `markdown.syntaxHighlight` configuration](https://docs.astro.build/en/guides/markdown-content/#syntax-highlighting).
package/dist/index.js CHANGED
@@ -64,10 +64,14 @@ function mdx(mdxOptions = {}) {
64
64
  const [, moduleExports] = parseESM(code);
65
65
  code += `
66
66
  import "${"astro:scripts/page-ssr.js"}";`;
67
+ const { fileUrl, fileId } = getFileInfo(id, config);
67
68
  if (!moduleExports.includes("url")) {
68
- const { fileUrl } = getFileInfo(id, config);
69
69
  code += `
70
70
  export const url = ${JSON.stringify(fileUrl)};`;
71
+ }
72
+ if (!moduleExports.includes("file")) {
73
+ code += `
74
+ export const file = ${JSON.stringify(fileId)};`;
71
75
  }
72
76
  if (command === "dev") {
73
77
  code += `
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type { AstroConfig } from 'astro';
2
- /** @see 'vite-plugin-utils' for source */
3
- export declare function getFileInfo(id: string, config: AstroConfig): {
2
+ interface FileInfo {
4
3
  fileId: string;
5
- fileUrl: string | undefined;
6
- };
4
+ fileUrl: string;
5
+ }
6
+ /** @see 'vite-plugin-utils' for source */
7
+ export declare function getFileInfo(id: string, config: AstroConfig): FileInfo;
8
+ export {};
package/dist/utils.js CHANGED
@@ -5,8 +5,21 @@ function getFileInfo(id, config) {
5
5
  const sitePathname = appendForwardSlash(
6
6
  config.site ? new URL(config.base, config.site).pathname : config.base
7
7
  );
8
+ let url = void 0;
9
+ try {
10
+ url = new URL(`file://${id}`);
11
+ } catch {
12
+ }
8
13
  const fileId = id.split("?")[0];
9
- let fileUrl = fileId.includes("/pages/") ? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, "") : void 0;
14
+ let fileUrl;
15
+ const isPage = fileId.includes("/pages/");
16
+ if (isPage) {
17
+ fileUrl = fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, "");
18
+ } else if (url && url.pathname.startsWith(config.root.pathname)) {
19
+ fileUrl = url.pathname.slice(config.root.pathname.length);
20
+ } else {
21
+ fileUrl = fileId;
22
+ }
10
23
  if (fileUrl && config.trailingSlash === "always") {
11
24
  fileUrl = appendForwardSlash(fileUrl);
12
25
  }
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.3.0",
4
+ "version": "0.3.1",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
7
7
  "author": "withastro",
@@ -42,7 +42,7 @@
42
42
  "@types/chai": "^4.3.1",
43
43
  "@types/mocha": "^9.1.1",
44
44
  "@types/yargs-parser": "^21.0.0",
45
- "astro": "1.0.0-rc.1",
45
+ "astro": "1.0.0-rc.2",
46
46
  "astro-scripts": "0.0.6",
47
47
  "chai": "^4.3.6",
48
48
  "linkedom": "^0.14.12",
package/src/index.ts CHANGED
@@ -96,10 +96,14 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
96
96
  // or otherwise refactored to not require copy-paste handling logic.
97
97
  code += `\nimport "${'astro:scripts/page-ssr.js'}";`;
98
98
 
99
+ const { fileUrl, fileId } = getFileInfo(id, config);
99
100
  if (!moduleExports.includes('url')) {
100
- const { fileUrl } = getFileInfo(id, config);
101
101
  code += `\nexport const url = ${JSON.stringify(fileUrl)};`;
102
102
  }
103
+ if (!moduleExports.includes('file')) {
104
+ code += `\nexport const file = ${JSON.stringify(fileId)};`;
105
+ }
106
+
103
107
  if (command === 'dev') {
104
108
  // TODO: decline HMR updates until we have a stable approach
105
109
  code += `\nif (import.meta.hot) {
package/src/utils.ts CHANGED
@@ -4,16 +4,34 @@ function appendForwardSlash(path: string) {
4
4
  return path.endsWith('/') ? path : path + '/';
5
5
  }
6
6
 
7
+ interface FileInfo {
8
+ fileId: string;
9
+ fileUrl: string;
10
+ }
11
+
7
12
  /** @see 'vite-plugin-utils' for source */
8
- export function getFileInfo(id: string, config: AstroConfig) {
13
+ export function getFileInfo(id: string, config: AstroConfig): FileInfo {
9
14
  const sitePathname = appendForwardSlash(
10
15
  config.site ? new URL(config.base, config.site).pathname : config.base
11
16
  );
12
17
 
18
+ // Try to grab the file's actual URL
19
+ let url: URL | undefined = undefined;
20
+ try {
21
+ url = new URL(`file://${id}`);
22
+ } catch {}
23
+
13
24
  const fileId = id.split('?')[0];
14
- let fileUrl = fileId.includes('/pages/')
15
- ? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, '')
16
- : undefined;
25
+ let fileUrl: string;
26
+ const isPage = fileId.includes('/pages/');
27
+ if (isPage) {
28
+ fileUrl = fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, '');
29
+ } else if (url && url.pathname.startsWith(config.root.pathname)) {
30
+ fileUrl = url.pathname.slice(config.root.pathname.length);
31
+ } else {
32
+ fileUrl = fileId;
33
+ }
34
+
17
35
  if (fileUrl && config.trailingSlash === 'always') {
18
36
  fileUrl = appendForwardSlash(fileUrl);
19
37
  }
@@ -0,0 +1,5 @@
1
+ ---
2
+ one: hello
3
+ slug: one
4
+ ---
5
+ First mdx file
@@ -0,0 +1,34 @@
1
+ ---
2
+ export const getStaticPaths = async () => {
3
+ const content = await Astro.glob('../content/*.mdx');
4
+
5
+ return content
6
+ .filter((page) => !page.frontmatter.draft) // skip drafts
7
+ .map(({ default: MdxContent, frontmatter, url, file }) => {
8
+ return {
9
+ params: { slug: frontmatter.slug || "index" },
10
+ props: {
11
+ MdxContent,
12
+ file,
13
+ frontmatter,
14
+ url
15
+ }
16
+ }
17
+ })
18
+ }
19
+
20
+ const { MdxContent, frontmatter, url, file } = Astro.props;
21
+ ---
22
+
23
+ <html>
24
+ <head>
25
+ <title>Page</title>
26
+ </head>
27
+ <body>
28
+ <MdxContent />
29
+
30
+ <div id="one">{frontmatter.one}</div>
31
+ <div id="url">{url}</div>
32
+ <div id="file">{file}</div>
33
+ </body>
34
+ </html>
@@ -0,0 +1,32 @@
1
+ import mdx from '@astrojs/mdx';
2
+
3
+ import { expect } from 'chai';
4
+ import { loadFixture } from '../../../astro/test/test-utils.js';
5
+ import * as cheerio from 'cheerio';
6
+
7
+ const FIXTURE_ROOT = new URL('./fixtures/mdx-get-static-paths', import.meta.url);
8
+
9
+ describe('getStaticPaths', () => {
10
+ /** @type {import('astro/test/test-utils').Fixture} */
11
+ let fixture;
12
+ before(async () => {
13
+ fixture = await loadFixture({
14
+ root: FIXTURE_ROOT,
15
+ integrations: [mdx()],
16
+ });
17
+ await fixture.build();
18
+ });
19
+
20
+ it('Provides file and url', async () => {
21
+ const html = await fixture.readFile('/one/index.html');
22
+
23
+ const $ = cheerio.load(html);
24
+ expect($('p').text()).to.equal('First mdx file');
25
+ expect($('#one').text()).to.equal('hello', 'Frontmatter included');
26
+ expect($('#url').text()).to.equal('/src/content/1.mdx', 'url is included');
27
+ expect($('#file').text()).to.contain(
28
+ 'fixtures/mdx-get-static-paths/src/content/1.mdx',
29
+ 'file is included'
30
+ );
31
+ });
32
+ });