fix(markdown): preserve queries on index page links (#5436)

pull/5439/head
lllleolin-max 2 weeks ago committed by GitHub
parent a32f618fe5
commit 034fd0c754
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -61,6 +61,42 @@ describe('node/markdown/plugins/link', () => {
expect(env.links).toEqual(['./missing']) expect(env.links).toEqual(['./missing'])
expect(env.linkLines).toEqual([3]) expect(env.linkLines).toEqual([3])
}) })
test.each([false, true])(
'preserves index page queries (cleanUrls: %s)',
async (cleanUrls) => {
for (const [source, expected] of [
['/guide/index.md?lang=fr', '/guide/?lang=fr'],
[
'./index.md?lang=fr&mode=full#Hello%20World',
'./?lang=fr&mode=full#hello-world'
],
[
'/guide/index.md?next=/other/index.md#Hello%20World',
'/guide/?next=/other/index.md#hello-world'
],
[
'/guide/index.md?lang=fr#:~:text=Hello%20World',
'/guide/?lang=fr#:~:text=Hello%20World'
]
]) {
expect(
await md.renderAsync(`[link](${source})`, { cleanUrls })
).toContain(`href="${expected}"`)
}
}
)
test.each([false, true])(
'only removes the exact index.md filename (cleanUrls: %s)',
async (cleanUrls) => {
for (const file of ['indexAmd', 'index.md-extra']) {
expect(
await md.renderAsync(`[link](/guide/${file})`, { cleanUrls })
).toContain(`href="/guide/${file}${cleanUrls ? '' : '.html'}"`)
}
}
)
}) })
describe('node/markdown/plugins/link with a relative base', () => { describe('node/markdown/plugins/link with a relative base', () => {
@ -114,6 +150,19 @@ describe('node/markdown/plugins/link with a relative base', () => {
) )
}) })
test.each([false, true])(
'preserves index page queries with a relative base (cleanUrls: %s)',
async (cleanUrls) => {
expect(
await render('[link](/guide/index.md?lang=fr#Hello%20World)', {
cleanUrls
})
).toContain(
`href="../guide/${cleanUrls ? '' : 'index.html'}?lang=fr#hello-world"`
)
}
)
test('content-loader renders keep absolute links site-absolute', async () => { test('content-loader renders keep absolute links site-absolute', async () => {
// content loaders set relativePath but not relativizeUrls — their html // content loaders set relativePath but not relativizeUrls — their html
// is embedded in other pages, so the source's depth must not apply // is embedded in other pages, so the source's depth must not apply

@ -16,7 +16,7 @@ import {
type MarkdownEnv type MarkdownEnv
} from '../../shared' } from '../../shared'
const indexRE = /(^|.*\/)index.md(#?.*)$/i const indexRE = /(^|.*\/)index\.md$/i
export const linkPlugin = ( export const linkPlugin = (
md: MarkdownItAsync, md: MarkdownItAsync,
@ -112,12 +112,11 @@ export const linkPlugin = (
// directory urls need a server to resolve them, and file:// has none // directory urls need a server to resolve them, and file:// has none
const explicitIndex = isRelativeBase(base) && !env.cleanUrls const explicitIndex = isRelativeBase(base) && !env.cleanUrls
const indexMatch = url.match(indexRE) let cleanUrl = url.replace(/[?#].*$/, '')
const indexMatch = cleanUrl.match(indexRE)
if (indexMatch) { if (indexMatch) {
const [, path, hash] = indexMatch cleanUrl = indexMatch[1] + (explicitIndex ? 'index.html' : '')
url = path + (explicitIndex ? 'index.html' : '') + normalizeHash(hash)
} else { } else {
let cleanUrl = url.replace(/[?#].*$/, '')
// transform foo.md -> foo[.html] // transform foo.md -> foo[.html]
if (cleanUrl.endsWith('.md')) { if (cleanUrl.endsWith('.md')) {
cleanUrl = cleanUrl.replace(/\.md$/, env.cleanUrls ? '' : '.html') cleanUrl = cleanUrl.replace(/\.md$/, env.cleanUrls ? '' : '.html')
@ -133,9 +132,9 @@ export const linkPlugin = (
if (explicitIndex && cleanUrl.endsWith('/')) { if (explicitIndex && cleanUrl.endsWith('/')) {
cleanUrl += 'index.html' cleanUrl += 'index.html'
} }
const parsed = new URL(url, 'http://a.com')
url = cleanUrl + parsed.search + normalizeHash(parsed.hash)
} }
const parsed = new URL(url, 'http://a.com')
url = cleanUrl + parsed.search + normalizeHash(parsed.hash)
// ensure leading . for relative paths // ensure leading . for relative paths
if (!url.startsWith('/') && !url.startsWith('./')) { if (!url.startsWith('/') && !url.startsWith('./')) {

Loading…
Cancel
Save