diff --git a/.changeset/large-birds-repair.md b/.changeset/large-birds-repair.md new file mode 100644 index 000000000..669ab6b86 --- /dev/null +++ b/.changeset/large-birds-repair.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Markdown file.url now respects `trailingSlash` and `base` diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index e76d51ca3..d68f8faf3 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -179,7 +179,7 @@ async function generatePath( // If a base path was provided, append it to the site URL. This ensures that // all injected scripts and links are referenced relative to the site and subpath. const site = - astroConfig.base && astroConfig.base !== './' + astroConfig.base !== '/' ? joinPaths(astroConfig.site?.toString() || 'http://localhost/', astroConfig.base) : astroConfig.site; const links = createLinkStylesheetElementSet(linkIds.reverse(), site); diff --git a/packages/astro/src/core/config.ts b/packages/astro/src/core/config.ts index 57b45ef1b..de947530d 100644 --- a/packages/astro/src/core/config.ts +++ b/packages/astro/src/core/config.ts @@ -94,8 +94,8 @@ export const AstroConfigSchema = z.object({ base: z .string() .optional() - .default('./') - .transform((val) => (val ? appendForwardSlash(trimSlashes(val)) : val)), + .default('/') + .transform((val) => appendForwardSlash(trimSlashes(val))), trailingSlash: z .union([z.literal('always'), z.literal('never'), z.literal('ignore')]) .optional() diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts index d21fa7e8e..0fdb8705b 100644 --- a/packages/astro/src/vite-plugin-astro-server/index.ts +++ b/packages/astro/src/vite-plugin-astro-server/index.ts @@ -114,8 +114,7 @@ async function handle404Response( // HACK: redirect without the base path for assets in publicDir const redirectTo = req.method === 'GET' && - config.base && - config.base !== './' && + config.base !== '/' && pathname.startsWith(config.base) && pathname.replace(config.base, '/'); diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts index 231977002..105ff47e0 100644 --- a/packages/astro/src/vite-plugin-markdown/index.ts +++ b/packages/astro/src/vite-plugin-markdown/index.ts @@ -78,13 +78,18 @@ export default function markdown({ config }: AstroPluginOptions): Plugin { // Return the file's JS representation, including all Markdown // frontmatter and a deferred `import() of the compiled markdown content. if (id.endsWith(`.md${MARKDOWN_IMPORT_FLAG}`)) { - const sitePathname = config.site - ? appendForwardSlash(new URL(config.base, config.site).pathname) - : '/'; + const sitePathname = appendForwardSlash( + config.site ? new URL(config.base, config.site).pathname : config.base + ); + const fileId = id.replace(MARKDOWN_IMPORT_FLAG, ''); - const fileUrl = fileId.includes('/pages/') - ? fileId.replace(/^.*\/pages\//, sitePathname).replace(/(\/index)?\.md$/, '') + let fileUrl = fileId.includes('/pages/') + ? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.md$/, '') : undefined; + if (fileUrl && config.trailingSlash === 'always') { + fileUrl = appendForwardSlash(fileUrl); + } + const source = await fs.promises.readFile(fileId, 'utf8'); const { data: frontmatter } = matter(source); return { diff --git a/packages/astro/test/astro-markdown-url.test.js b/packages/astro/test/astro-markdown-url.test.js new file mode 100644 index 000000000..54ce8bfba --- /dev/null +++ b/packages/astro/test/astro-markdown-url.test.js @@ -0,0 +1,100 @@ +import { expect } from 'chai'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Astro Markdown URL', () => { + describe('With subpath', () => { + const baseUrl = `/my-cool-base/docs/pages/how-to-make-a-page`; + + it('trailingSlash: always', async () => { + let fixture = await loadFixture({ + root: './fixtures/astro-markdown-url/', + outDir: new URL('./fixtures/astro-markdown-url/with-subpath-always/', import.meta.url), + base: '/my-cool-base', + trailingSlash: 'always', + }); + await fixture.build(); + + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#url').attr('href')).to.equal(baseUrl + '/'); + }); + + it('trailingSlash: never', async () => { + let fixture = await loadFixture({ + root: './fixtures/astro-markdown-url/', + outDir: new URL('./fixtures/astro-markdown-url/with-subpath-never/', import.meta.url), + base: '/my-cool-base', + trailingSlash: 'never', + }); + await fixture.build(); + + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#url').attr('href')).to.equal(baseUrl); + }); + + it('trailingSlash: ignore', async () => { + let fixture = await loadFixture({ + root: './fixtures/astro-markdown-url/', + outDir: new URL('./fixtures/astro-markdown-url/with-subpath-ignore/', import.meta.url), + base: '/my-cool-base', + trailingSlash: 'ignore', + }); + await fixture.build(); + + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#url').attr('href')).to.equal(baseUrl); + }); + }); + + describe('Without subpath', () => { + const baseUrl = `/docs/pages/how-to-make-a-page`; + + it('trailingSlash: always', async () => { + let fixture = await loadFixture({ + root: './fixtures/astro-markdown-url/', + outDir: new URL('./fixtures/astro-markdown-url/without-subpath-always/', import.meta.url), + trailingSlash: 'always', + }); + await fixture.build(); + + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#url').attr('href')).to.equal(baseUrl + '/'); + }); + + it('trailingSlash: never', async () => { + let fixture = await loadFixture({ + root: './fixtures/astro-markdown-url/', + outDir: new URL('./fixtures/astro-markdown-url/without-subpath-never/', import.meta.url), + trailingSlash: 'never', + }); + await fixture.build(); + + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#url').attr('href')).to.equal(baseUrl); + }); + + it('trailingSlash: ignore', async () => { + let fixture = await loadFixture({ + root: './fixtures/astro-markdown-url/', + outDir: new URL('./fixtures/astro-markdown-url/without-subpath-ignore/', import.meta.url), + trailingSlash: 'ignore', + }); + await fixture.build(); + + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#url').attr('href')).to.equal(baseUrl); + }); + }); +}); diff --git a/packages/astro/test/fixtures/astro-markdown-url/.gitignore b/packages/astro/test/fixtures/astro-markdown-url/.gitignore new file mode 100644 index 000000000..dad853294 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-url/.gitignore @@ -0,0 +1,6 @@ +with-subpath-always/ +with-subpath-never/ +with-subpath-ignore/ +without-subpath-always/ +without-subpath-never/ +without-subpath-ignore/ diff --git a/packages/astro/test/fixtures/astro-markdown-url/package.json b/packages/astro/test/fixtures/astro-markdown-url/package.json new file mode 100644 index 000000000..341814951 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-url/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/astro-markdown-url", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/astro-markdown-url/src/pages/docs/pages/how-to-make-a-page.md b/packages/astro/test/fixtures/astro-markdown-url/src/pages/docs/pages/how-to-make-a-page.md new file mode 100644 index 000000000..901c35955 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-url/src/pages/docs/pages/how-to-make-a-page.md @@ -0,0 +1,5 @@ +--- +title: How to make a page +--- + +Test diff --git a/packages/astro/test/fixtures/astro-markdown-url/src/pages/index.astro b/packages/astro/test/fixtures/astro-markdown-url/src/pages/index.astro new file mode 100644 index 000000000..c6a77b0e1 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-url/src/pages/index.astro @@ -0,0 +1,5 @@ +--- +import * as page from './docs/pages/how-to-make-a-page.md' +--- + +{page.frontmatter.title} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a470892d..baa7a59ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -860,6 +860,12 @@ importers: dependencies: astro: link:../../../.. + packages/astro/test/fixtures/astro-markdown-url: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + packages/astro/test/fixtures/astro-page-directory-url: specifiers: astro: workspace:*