Skip to content

Commit d3e5409

Browse files
fix(markdown): decode assets link to ensure bundler can find the file (#144)
Co-authored-by: meteorlxy <[email protected]>
1 parent e028f88 commit d3e5409

File tree

3 files changed

+81
-20
lines changed

3 files changed

+81
-20
lines changed

Diff for: packages/@vuepress/markdown/__tests__/plugins/assetsPlugin.spec.ts

+64-12
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,31 @@ import { assetsPlugin } from '@vuepress/markdown'
33
import type { MarkdownEnv } from '@vuepress/markdown'
44

55
const source = [
6+
// relative paths
67
'![foo](./foo.png)',
78
'![foo2](../sub/foo.png)',
89
'![foo-bar](./foo/bar.png)',
910
'![foo-bar2](../sub/foo/bar.png)',
1011
'![baz](../baz.png)',
1112
'![out](../../out.png)',
12-
'![invalid](.../invalid.png)',
13+
'![汉字](./汉字.png)',
14+
'![100%](./100%.png)',
15+
// aliases
16+
'![alias](@alias/foo.png)',
17+
'![汉字](@alias/汉字.png)',
18+
'![100%](@alias/100%.png)',
19+
// webpack legacy aliases
20+
'![~alias](~@alias/foo.png)',
21+
'![~汉字](~@alias/汉字.png)',
22+
'![~100%](~@alias/100%.png)',
23+
// keep as is
1324
'![absolute](/absolute.png)',
1425
'![url](http://foobar.com/icon.png)',
1526
'![empty]()',
16-
'![alias](@alias/foo.png)',
17-
'![~alias](~@alias/foo.png)',
27+
// invalid paths
28+
'![invalid](.../invalid.png)',
29+
'![汉字](.../汉字.png)',
30+
'![100%](.../100%.png)',
1831
].join('\n\n')
1932

2033
describe('@vuepress/markdown > plugins > assetsPlugin', () => {
@@ -28,18 +41,31 @@ describe('@vuepress/markdown > plugins > assetsPlugin', () => {
2841

2942
expect(rendered).toEqual(
3043
[
44+
// relative paths
3145
'<img src="@source/sub/foo.png" alt="foo">',
3246
'<img src="@source/sub/foo.png" alt="foo2">',
3347
'<img src="@source/sub/foo/bar.png" alt="foo-bar">',
3448
'<img src="@source/sub/foo/bar.png" alt="foo-bar2">',
3549
'<img src="@source/baz.png" alt="baz">',
3650
'<img src="@source/../out.png" alt="out">',
37-
'<img src=".../invalid.png" alt="invalid">',
51+
'<img src="@source/sub/汉字.png" alt="汉字">',
52+
'<img src="@source/sub/100%.png" alt="100%">',
53+
// aliases
54+
'<img src="@alias/foo.png" alt="alias">',
55+
'<img src="@alias/汉字.png" alt="汉字">',
56+
'<img src="@alias/100%.png" alt="100%">',
57+
// webpack legacy aliases
58+
'<img src="~@alias/foo.png" alt="~alias">',
59+
'<img src="~@alias/汉字.png" alt="~汉字">',
60+
'<img src="~@alias/100%.png" alt="~100%">',
61+
// keep as is
3862
'<img src="/absolute.png" alt="absolute">',
3963
'<img src="http://foobar.com/icon.png" alt="url">',
4064
'<img src="" alt="empty">',
41-
'<img src="@alias/foo.png" alt="alias">',
42-
'<img src="~@alias/foo.png" alt="~alias">',
65+
// invalid paths
66+
'<img src=".../invalid.png" alt="invalid">',
67+
'<img src=".../汉字.png" alt="汉字">',
68+
'<img src=".../100%.png" alt="100%">',
4369
]
4470
.map((item) => `<p>${item}</p>`)
4571
.join('\n') + '\n'
@@ -58,18 +84,31 @@ describe('@vuepress/markdown > plugins > assetsPlugin', () => {
5884

5985
expect(rendered).toEqual(
6086
[
87+
// relative paths
6188
'<img src="@foo/sub/foo.png" alt="foo">',
6289
'<img src="@foo/sub/foo.png" alt="foo2">',
6390
'<img src="@foo/sub/foo/bar.png" alt="foo-bar">',
6491
'<img src="@foo/sub/foo/bar.png" alt="foo-bar2">',
6592
'<img src="@foo/baz.png" alt="baz">',
6693
'<img src="@foo/../out.png" alt="out">',
67-
'<img src=".../invalid.png" alt="invalid">',
94+
'<img src="@foo/sub/汉字.png" alt="汉字">',
95+
'<img src="@foo/sub/100%.png" alt="100%">',
96+
// aliases
97+
'<img src="@alias/foo.png" alt="alias">',
98+
'<img src="@alias/汉字.png" alt="汉字">',
99+
'<img src="@alias/100%.png" alt="100%">',
100+
// webpack legacy aliases
101+
'<img src="~@alias/foo.png" alt="~alias">',
102+
'<img src="~@alias/汉字.png" alt="~汉字">',
103+
'<img src="~@alias/100%.png" alt="~100%">',
104+
// keep as is
68105
'<img src="/absolute.png" alt="absolute">',
69106
'<img src="http://foobar.com/icon.png" alt="url">',
70107
'<img src="" alt="empty">',
71-
'<img src="@alias/foo.png" alt="alias">',
72-
'<img src="~@alias/foo.png" alt="~alias">',
108+
// invalid paths
109+
'<img src=".../invalid.png" alt="invalid">',
110+
'<img src=".../汉字.png" alt="汉字">',
111+
'<img src=".../100%.png" alt="100%">',
73112
]
74113
.map((item) => `<p>${item}</p>`)
75114
.join('\n') + '\n'
@@ -84,18 +123,31 @@ describe('@vuepress/markdown > plugins > assetsPlugin', () => {
84123

85124
expect(rendered).toEqual(
86125
[
126+
// relative paths
87127
'<img src="./foo.png" alt="foo">',
88128
'<img src="../sub/foo.png" alt="foo2">',
89129
'<img src="./foo/bar.png" alt="foo-bar">',
90130
'<img src="../sub/foo/bar.png" alt="foo-bar2">',
91131
'<img src="../baz.png" alt="baz">',
92132
'<img src="../../out.png" alt="out">',
93-
'<img src=".../invalid.png" alt="invalid">',
133+
'<img src="./汉字.png" alt="汉字">',
134+
'<img src="./100%.png" alt="100%">',
135+
// aliases
136+
'<img src="@alias/foo.png" alt="alias">',
137+
'<img src="@alias/汉字.png" alt="汉字">',
138+
'<img src="@alias/100%.png" alt="100%">',
139+
// webpack legacy aliases
140+
'<img src="~@alias/foo.png" alt="~alias">',
141+
'<img src="~@alias/汉字.png" alt="~汉字">',
142+
'<img src="~@alias/100%.png" alt="~100%">',
143+
// keep as is
94144
'<img src="/absolute.png" alt="absolute">',
95145
'<img src="http://foobar.com/icon.png" alt="url">',
96146
'<img src="" alt="empty">',
97-
'<img src="@alias/foo.png" alt="alias">',
98-
'<img src="~@alias/foo.png" alt="~alias">',
147+
// invalid paths
148+
'<img src=".../invalid.png" alt="invalid">',
149+
'<img src=".../汉字.png" alt="汉字">',
150+
'<img src=".../100%.png" alt="100%">',
99151
]
100152
.map((item) => `<p>${item}</p>`)
101153
.join('\n') + '\n'

Diff for: packages/@vuepress/markdown/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
"@vuepress/utils": "2.0.0-beta.11",
3232
"markdown-it": "^12.0.6",
3333
"markdown-it-anchor": "^7.1.0",
34-
"markdown-it-emoji": "^2.0.0"
34+
"markdown-it-emoji": "^2.0.0",
35+
"mdurl": "^1.0.1"
3536
},
3637
"publishConfig": {
3738
"access": "public"

Diff for: packages/@vuepress/markdown/src/plugins/assetsPlugin.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { PluginWithOptions } from 'markdown-it'
2+
import { decode } from 'mdurl'
23
import { path } from '@vuepress/utils'
34
import type { MarkdownEnv } from '../types'
45

@@ -24,18 +25,25 @@ export const assetsPlugin: PluginWithOptions<AssetsPluginOptions> = (
2425
// get the image link
2526
const link = token.attrGet('src')
2627

28+
if (!link) {
29+
return rawRule(tokens, idx, options, env, self)
30+
}
31+
32+
// decode link to ensure bundler can find the file correctly
33+
let resolvedLink = decode(link)
34+
2735
// if the link is relative path, and the `env.filePathRelative` exists
28-
if (link && /^\.{1,2}\//.test(link) && env.filePathRelative) {
29-
// add `@source` alias to the link
30-
const resolvedLink = `${relativePathPrefix}/${path.join(
36+
// add `@source` alias to the link
37+
if (/^\.{1,2}\//.test(link) && env.filePathRelative) {
38+
resolvedLink = `${relativePathPrefix}/${path.join(
3139
path.dirname(env.filePathRelative),
32-
link
40+
resolvedLink
3341
)}`
34-
35-
// replace the original link with absolute path
36-
token.attrSet('src', resolvedLink)
3742
}
3843

44+
// replace the original link with resolved link
45+
token.attrSet('src', resolvedLink)
46+
3947
return rawRule(tokens, idx, options, env, self)
4048
}
4149
}

0 commit comments

Comments
 (0)