Ensure file and url are always present in MDX for Astro.glob (#4076)
This commit is contained in:
parent
6fb95dbdd6
commit
6120a71e54
6 changed files with 100 additions and 5 deletions
5
.changeset/silent-files-promise.md
Normal file
5
.changeset/silent-files-promise.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/mdx': patch
|
||||
---
|
||||
|
||||
Ensure file and url are always present in MDX for Astro.glob
|
|
@ -96,10 +96,14 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
|
|||
// or otherwise refactored to not require copy-paste handling logic.
|
||||
code += `\nimport "${'astro:scripts/page-ssr.js'}";`;
|
||||
|
||||
const { fileUrl, fileId } = getFileInfo(id, config);
|
||||
if (!moduleExports.includes('url')) {
|
||||
const { fileUrl } = getFileInfo(id, config);
|
||||
code += `\nexport const url = ${JSON.stringify(fileUrl)};`;
|
||||
}
|
||||
if (!moduleExports.includes('file')) {
|
||||
code += `\nexport const file = ${JSON.stringify(fileId)};`;
|
||||
}
|
||||
|
||||
if (command === 'dev') {
|
||||
// TODO: decline HMR updates until we have a stable approach
|
||||
code += `\nif (import.meta.hot) {
|
||||
|
|
|
@ -4,16 +4,34 @@ function appendForwardSlash(path: string) {
|
|||
return path.endsWith('/') ? path : path + '/';
|
||||
}
|
||||
|
||||
interface FileInfo {
|
||||
fileId: string;
|
||||
fileUrl: string;
|
||||
}
|
||||
|
||||
/** @see 'vite-plugin-utils' for source */
|
||||
export function getFileInfo(id: string, config: AstroConfig) {
|
||||
export function getFileInfo(id: string, config: AstroConfig): FileInfo {
|
||||
const sitePathname = appendForwardSlash(
|
||||
config.site ? new URL(config.base, config.site).pathname : config.base
|
||||
);
|
||||
|
||||
// Try to grab the file's actual URL
|
||||
let url: URL | undefined = undefined;
|
||||
try {
|
||||
url = new URL(`file://${id}`);
|
||||
} catch {}
|
||||
|
||||
const fileId = id.split('?')[0];
|
||||
let fileUrl = fileId.includes('/pages/')
|
||||
? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, '')
|
||||
: undefined;
|
||||
let fileUrl: string;
|
||||
const isPage = fileId.includes('/pages/');
|
||||
if(isPage) {
|
||||
fileUrl = fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.mdx$/, '');
|
||||
} else if(url && url.pathname.startsWith(config.root.pathname)) {
|
||||
fileUrl = url.pathname.slice(config.root.pathname.length);
|
||||
} else {
|
||||
fileUrl = fileId;
|
||||
}
|
||||
|
||||
if (fileUrl && config.trailingSlash === 'always') {
|
||||
fileUrl = appendForwardSlash(fileUrl);
|
||||
}
|
||||
|
|
5
packages/integrations/mdx/test/fixtures/mdx-get-static-paths/src/content/1.mdx
vendored
Normal file
5
packages/integrations/mdx/test/fixtures/mdx-get-static-paths/src/content/1.mdx
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
one: hello
|
||||
slug: one
|
||||
---
|
||||
First mdx file
|
34
packages/integrations/mdx/test/fixtures/mdx-get-static-paths/src/pages/[slug].astro
vendored
Normal file
34
packages/integrations/mdx/test/fixtures/mdx-get-static-paths/src/pages/[slug].astro
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
export const getStaticPaths = async () => {
|
||||
const content = await Astro.glob('../content/*.mdx');
|
||||
|
||||
return content
|
||||
.filter((page) => !page.frontmatter.draft) // skip drafts
|
||||
.map(({ default: MdxContent, frontmatter, url, file }) => {
|
||||
return {
|
||||
params: { slug: frontmatter.slug || "index" },
|
||||
props: {
|
||||
MdxContent,
|
||||
file,
|
||||
frontmatter,
|
||||
url
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const { MdxContent, frontmatter, url, file } = Astro.props;
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<MdxContent />
|
||||
|
||||
<div id="one">{frontmatter.one}</div>
|
||||
<div id="url">{url}</div>
|
||||
<div id="file">{file}</div>
|
||||
</body>
|
||||
</html>
|
29
packages/integrations/mdx/test/mdx-get-static-paths.test.js
Normal file
29
packages/integrations/mdx/test/mdx-get-static-paths.test.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import mdx from '@astrojs/mdx';
|
||||
|
||||
import { expect } from 'chai';
|
||||
import { loadFixture } from '../../../astro/test/test-utils.js';
|
||||
import * as cheerio from 'cheerio';
|
||||
|
||||
const FIXTURE_ROOT = new URL('./fixtures/mdx-get-static-paths', import.meta.url);
|
||||
|
||||
describe('getStaticPaths', () => {
|
||||
/** @type {import('astro/test/test-utils').Fixture} */
|
||||
let fixture;
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: FIXTURE_ROOT,
|
||||
integrations: [mdx()],
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('Provides file and url', async () => {
|
||||
const html = await fixture.readFile('/one/index.html');
|
||||
|
||||
const $ = cheerio.load(html);
|
||||
expect($('p').text()).to.equal('First mdx file');
|
||||
expect($('#one').text()).to.equal('hello', 'Frontmatter included');
|
||||
expect($('#url').text()).to.equal('/src/content/1.mdx', 'url is included');
|
||||
expect($('#file').text()).to.contain('fixtures/mdx-get-static-paths/src/content/1.mdx', 'file is included');
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue