mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
feat(plugin-md-power): add links to markdown env (#631)
This commit is contained in:
parent
a8fac92bf0
commit
cd2b7fd26d
@ -26,4 +26,17 @@ describe('linksPlugin', () => {
|
||||
expect(md.render('[link](/path)')).toContain('href="/path"')
|
||||
expect(md.render('[link](/path)')).toContain('</VPLink>')
|
||||
})
|
||||
|
||||
it('should work with internal link extension and empty env', () => {
|
||||
const env = {}
|
||||
expect(md.render('[link](/path.md)', env)).toContain('href="/path.md"')
|
||||
expect(md.render('[link](../path.md)', env)).toContain('href="../path.md"')
|
||||
})
|
||||
|
||||
it('should work with internal link extension and env', () => {
|
||||
const env = { base: '/', filePathRelative: '../foo.md' }
|
||||
expect(md.render('[link](/path.html)', env)).toContain('href="/path.html"')
|
||||
expect(md.render('[link](/path.md)', env)).toContain('href="/path.md"')
|
||||
expect(md.render('[link](../path.md)', env)).toContain('href="../path.md"')
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type Token from 'markdown-it/lib/token.mjs'
|
||||
import type { Markdown, MarkdownEnv } from 'vuepress/markdown'
|
||||
import { removeLeadingSlash } from '@vuepress/shared'
|
||||
import { path } from '@vuepress/utils'
|
||||
import { isLinkWithProtocol } from 'vuepress/shared'
|
||||
|
||||
export function linksPlugin(md: Markdown): void {
|
||||
@ -12,7 +14,7 @@ export function linksPlugin(md: Markdown): void {
|
||||
let hasOpenInternalLink = false
|
||||
const internalTag = 'VPLink'
|
||||
|
||||
function handleLinkOpen(tokens: Token[], idx: number) {
|
||||
function handleLinkOpen(tokens: Token[], idx: number, env: MarkdownEnv) {
|
||||
hasOpenInternalLink = false
|
||||
const token = tokens[idx]
|
||||
// get `href` attr index
|
||||
@ -42,10 +44,29 @@ export function linksPlugin(md: Markdown): void {
|
||||
// convert starting tag of internal link
|
||||
hasOpenInternalLink = true
|
||||
token.tag = internalTag
|
||||
|
||||
const matched = hrefLink.match(/^([^#?]*?(?:\/|\.md|\.html))([#?].*)?$/)
|
||||
|
||||
if (matched) {
|
||||
const rawPath = matched[1]
|
||||
const { absolutePath, relativePath } = resolvePaths(
|
||||
rawPath,
|
||||
env.base || '/',
|
||||
env.filePathRelative ?? null,
|
||||
)
|
||||
// extract internal links for file / page existence check
|
||||
// 并不能保证文件存在,以及是否属于内部链接
|
||||
// 需要进一步在 extendPage 阶段中与 page.path / page.filePath 进行对比
|
||||
;(env.links ??= []).push({
|
||||
raw: rawPath,
|
||||
absolute: absolutePath,
|
||||
relative: relativePath,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
md.renderer.rules.link_open = (tokens, idx, opts, env: MarkdownEnv, self) => {
|
||||
handleLinkOpen(tokens, idx)
|
||||
handleLinkOpen(tokens, idx, env)
|
||||
return self.renderToken(tokens, idx, opts)
|
||||
}
|
||||
|
||||
@ -58,3 +79,54 @@ export function linksPlugin(md: Markdown): void {
|
||||
return self.renderToken(tokens, idx, opts)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve relative and absolute paths according to the `base` and `filePathRelative`
|
||||
*/
|
||||
export function resolvePaths(rawPath: string, base: string, filePathRelative: string | null): {
|
||||
absolutePath: string | null
|
||||
relativePath: string
|
||||
} {
|
||||
let absolutePath: string | null
|
||||
let relativePath: string
|
||||
|
||||
// if raw path is absolute
|
||||
if (rawPath.startsWith('/')) {
|
||||
// if raw path is a link to markdown file
|
||||
if (rawPath.endsWith('.md')) {
|
||||
// prepend `base` to the link
|
||||
absolutePath = path.join(base, rawPath)
|
||||
relativePath = removeLeadingSlash(rawPath)
|
||||
}
|
||||
// if raw path is a link to other kind of file
|
||||
else {
|
||||
// keep the link as is
|
||||
absolutePath = rawPath
|
||||
relativePath = path.relative(base, absolutePath)
|
||||
}
|
||||
}
|
||||
// if raw path is relative
|
||||
// if `filePathRelative` is available
|
||||
else if (filePathRelative) {
|
||||
// resolve relative path according to `filePathRelative`
|
||||
relativePath = path.join(
|
||||
// file path may contain non-ASCII characters
|
||||
path.dirname(encodeURI(filePathRelative)),
|
||||
rawPath,
|
||||
)
|
||||
// resolve absolute path according to `base`
|
||||
absolutePath = path.join(base, relativePath)
|
||||
}
|
||||
// if `filePathRelative` is not available
|
||||
else {
|
||||
// remove leading './'
|
||||
relativePath = rawPath.replace(/^(?:\.\/)?(.*)$/, '$1')
|
||||
// just take relative link as absolute link
|
||||
absolutePath = null
|
||||
}
|
||||
|
||||
return {
|
||||
absolutePath,
|
||||
relativePath,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user