1 |
|
2 |
|
3 |
|
4 |
|
5 | const url = require('url')
|
6 |
|
7 | const indexRE = /(^|.*\/)(index|readme).md(#?.*)$/i
|
8 |
|
9 | module.exports = (md, externalAttrs, pageSuffix = '.html') => {
|
10 | let hasOpenRouterLink = false
|
11 | let hasOpenExternalLink = false
|
12 |
|
13 | md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
|
14 | const { relativePath } = env
|
15 | const token = tokens[idx]
|
16 | const hrefIndex = token.attrIndex('href')
|
17 | if (hrefIndex >= 0) {
|
18 | const link = token.attrs[hrefIndex]
|
19 | const href = link[1]
|
20 | const isExternal = /^https?:/.test(href)
|
21 | const isSourceLink = /(\/|\.md|\.html)(#.*)?$/.test(href)
|
22 | if (isExternal) {
|
23 | Object.entries(externalAttrs).forEach(([key, val]) => {
|
24 | token.attrSet(key, val)
|
25 | })
|
26 | if (/_blank/i.test(externalAttrs['target'])) {
|
27 | hasOpenExternalLink = true
|
28 | }
|
29 | } else if (isSourceLink) {
|
30 | hasOpenRouterLink = true
|
31 | tokens[idx] = toRouterLink(token, link, relativePath, pageSuffix)
|
32 | }
|
33 | }
|
34 | return self.renderToken(tokens, idx, options)
|
35 | }
|
36 |
|
37 | function toRouterLink (token, link, relativePath, suffix) {
|
38 | link[0] = 'to'
|
39 | let to = link[1]
|
40 |
|
41 |
|
42 | const links = md.$data.links || (md.$data.links = [])
|
43 | links.push(to)
|
44 |
|
45 |
|
46 | if (!to.startsWith('/')) {
|
47 | to = relativePath
|
48 | ? url.resolve('/' + relativePath, to)
|
49 | : ensureBeginningDotSlash(to)
|
50 | }
|
51 |
|
52 | const indexMatch = to.match(indexRE)
|
53 | if (indexMatch) {
|
54 | const [, path, , hash] = indexMatch
|
55 | to = path + hash
|
56 | } else {
|
57 | to = to
|
58 | .replace(/\.md$/, suffix)
|
59 | .replace(/\.md(#.*)$/, `${suffix}$1`)
|
60 | }
|
61 |
|
62 |
|
63 | link[1] = decodeURI(to)
|
64 |
|
65 |
|
66 | const routerLinks = md.$data.routerLinks || (md.$data.routerLinks = [])
|
67 | routerLinks.push(to)
|
68 |
|
69 | return Object.create(token, {
|
70 | tag: { value: 'RouterLink' }
|
71 | })
|
72 | }
|
73 |
|
74 | md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
|
75 | const token = tokens[idx]
|
76 | if (hasOpenRouterLink) {
|
77 | token.tag = 'RouterLink'
|
78 | hasOpenRouterLink = false
|
79 | }
|
80 | if (hasOpenExternalLink) {
|
81 | hasOpenExternalLink = false
|
82 |
|
83 | return '<OutboundLink/>' + self.renderToken(tokens, idx, options)
|
84 | }
|
85 | return self.renderToken(tokens, idx, options)
|
86 | }
|
87 | }
|
88 |
|
89 | const beginningSlashRE = /^\.\//
|
90 |
|
91 | function ensureBeginningDotSlash (path) {
|
92 | if (beginningSlashRE.test(path)) {
|
93 | return path
|
94 | }
|
95 | return './' + path
|
96 | }
|