@vuepress/markdown 2.0.0-rc.3 → 2.0.0-rc.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,599 +1,322 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
6
-
7
- // src/markdown.ts
8
- import { slugify as defaultSlugify } from "@mdit-vue/shared";
1
+ import { slugify } from "@mdit-vue/shared";
2
+ import { colors, fs, logger, path } from "@vuepress/utils";
9
3
  import MarkdownIt from "markdown-it";
10
-
11
- // src/plugins.ts
12
- import {
13
- componentPlugin
14
- } from "@mdit-vue/plugin-component";
15
- import {
16
- frontmatterPlugin
17
- } from "@mdit-vue/plugin-frontmatter";
18
- import {
19
- headersPlugin
20
- } from "@mdit-vue/plugin-headers";
4
+ import { componentPlugin } from "@mdit-vue/plugin-component";
5
+ import { frontmatterPlugin } from "@mdit-vue/plugin-frontmatter";
6
+ import { headersPlugin } from "@mdit-vue/plugin-headers";
21
7
  import { sfcPlugin } from "@mdit-vue/plugin-sfc";
22
8
  import { titlePlugin } from "@mdit-vue/plugin-title";
23
9
  import { tocPlugin } from "@mdit-vue/plugin-toc";
24
-
25
- // src/plugins/anchorPlugin.ts
26
- import { default as anchorPlugin } from "markdown-it-anchor";
27
-
28
- // src/plugins/assetsPlugin/resolveLink.ts
29
- import { path } from "@vuepress/utils";
10
+ import anchorPlugin from "markdown-it-anchor";
30
11
  import { decode } from "mdurl";
31
- var resolveLink = (link, {
32
- env,
33
- absolutePathPrependBase = false,
34
- relativePathPrefix,
35
- strict = false
36
- }) => {
37
- if (link.startsWith("data:"))
38
- return link;
39
- let resolvedLink = decode(link);
40
- const isRelativePath = strict ? (
41
- // in strict mode, only link that starts with `./` or `../` is considered as relative path
42
- /^\.{1,2}\//.test(link)
43
- ) : (
44
- // in non-strict mode, link that does not start with `/` and does not have protocol is considered as relative path
45
- !link.startsWith("/") && !/[A-z]+:\/\//.test(link)
46
- );
47
- if (isRelativePath && env.filePathRelative) {
48
- resolvedLink = `${relativePathPrefix}/${path.join(
49
- path.dirname(env.filePathRelative),
50
- resolvedLink
51
- )}`;
52
- }
53
- if (absolutePathPrependBase && env.base && link.startsWith("/")) {
54
- resolvedLink = path.join(env.base, resolvedLink);
55
- }
56
- return resolvedLink;
57
- };
58
-
59
- // src/plugins/assetsPlugin/assetsPlugin.ts
60
- var assetsPlugin = (md, {
61
- absolutePathPrependBase = false,
62
- relativePathPrefix = "@source"
63
- } = {}) => {
64
- const rawImageRule = md.renderer.rules.image;
65
- md.renderer.rules.image = (tokens, idx, options, env, self) => {
66
- const token = tokens[idx];
67
- const link = token.attrGet("src");
68
- if (link) {
69
- token.attrSet(
70
- "src",
71
- resolveLink(link, { env, absolutePathPrependBase, relativePathPrefix })
72
- );
73
- }
74
- return rawImageRule(tokens, idx, options, env, self);
75
- };
76
- const createHtmlRule = (rawHtmlRule) => (tokens, idx, options, env, self) => {
77
- tokens[idx].content = tokens[idx].content.replace(
78
- /(<img\b.*?src=)(['"])([^\2]*?)\2/gs,
79
- (_, prefix, quote, src) => `${prefix}${quote}${resolveLink(src.trim(), {
80
- env,
81
- absolutePathPrependBase,
82
- relativePathPrefix,
83
- strict: true
84
- })}${quote}`
85
- ).replace(
86
- /(<img\b.*?srcset=)(['"])([^\2]*?)\2/gs,
87
- (_, prefix, quote, srcset) => `${prefix}${quote}${srcset.split(",").map(
88
- (item) => item.trim().replace(
89
- /^([^ ]*?)([ \n].*)?$/,
90
- (_2, url, descriptor = "") => `${resolveLink(url.trim(), {
91
- env,
92
- absolutePathPrependBase,
93
- relativePathPrefix,
94
- strict: true
95
- })}${descriptor.replace(/[ \n]+/g, " ").trimEnd()}`
96
- )
97
- ).join(", ")}${quote}`
98
- );
99
- return rawHtmlRule(tokens, idx, options, env, self);
100
- };
101
- const rawHtmlBlockRule = md.renderer.rules.html_block;
102
- const rawHtmlInlineRule = md.renderer.rules.html_inline;
103
- md.renderer.rules.html_block = createHtmlRule(rawHtmlBlockRule);
104
- md.renderer.rules.html_inline = createHtmlRule(rawHtmlInlineRule);
105
- };
106
-
107
- // src/plugins/codePlugin/resolveAttr.ts
108
- var resolveAttr = (info, attr) => {
109
- const pattern = `\\b${attr}\\s*=\\s*(?<quote>['"])(?<content>.+?)\\k<quote>(\\s|$)`;
110
- const regex = new RegExp(pattern, "i");
111
- const match = info.match(regex);
112
- return match?.groups?.content ?? null;
113
- };
114
-
115
- // src/plugins/codePlugin/resolveHighlightLines.ts
116
- var resolveHighlightLines = (info) => {
117
- const match = info.match(/{([\d,-]+)}/);
118
- if (match === null) {
119
- return null;
120
- }
121
- return match[1].split(",").map((item) => {
122
- const range = item.split("-");
123
- if (range.length === 1) {
124
- range.push(range[0]);
125
- }
126
- return range.map((str) => Number.parseInt(str, 10));
127
- });
128
- };
129
- var isHighlightLine = (lineNumber, ranges) => ranges.some(([start, end]) => lineNumber >= start && lineNumber <= end);
130
-
131
- // src/plugins/codePlugin/languages.ts
132
- var languages_exports = {};
133
- __export(languages_exports, {
134
- languageBash: () => languageBash,
135
- languageCsharp: () => languageCsharp,
136
- languageDocker: () => languageDocker,
137
- languageFsharp: () => languageFsharp,
138
- languageJavascript: () => languageJavascript,
139
- languageKotlin: () => languageKotlin,
140
- languageMarkdown: () => languageMarkdown,
141
- languagePython: () => languagePython,
142
- languageRuby: () => languageRuby,
143
- languageRust: () => languageRust,
144
- languageStylus: () => languageStylus,
145
- languageTypescript: () => languageTypescript,
146
- languageYaml: () => languageYaml
147
- });
148
- var languageBash = {
149
- name: "bash",
150
- ext: "sh",
151
- aliases: ["bash", "sh", "shell", "zsh"]
152
- };
153
- var languageCsharp = {
154
- name: "csharp",
155
- ext: "cs",
156
- aliases: ["cs", "csharp"]
157
- };
158
- var languageDocker = {
159
- name: "docker",
160
- ext: "docker",
161
- aliases: ["docker", "dockerfile"]
162
- };
163
- var languageFsharp = {
164
- name: "fsharp",
165
- ext: "fs",
166
- aliases: ["fs", "fsharp"]
167
- };
168
- var languageJavascript = {
169
- name: "javascript",
170
- ext: "js",
171
- aliases: ["javascript", "js"]
172
- };
173
- var languageKotlin = {
174
- name: "kotlin",
175
- ext: "kt",
176
- aliases: ["kotlin", "kt"]
177
- };
178
- var languageMarkdown = {
179
- name: "markdown",
180
- ext: "md",
181
- aliases: ["markdown", "md"]
182
- };
183
- var languagePython = {
184
- name: "python",
185
- ext: "py",
186
- aliases: ["py", "python"]
187
- };
188
- var languageRuby = {
189
- name: "ruby",
190
- ext: "rb",
191
- aliases: ["rb", "ruby"]
192
- };
193
- var languageRust = {
194
- name: "rust",
195
- ext: "rs",
196
- aliases: ["rs", "rust"]
197
- };
198
- var languageStylus = {
199
- name: "stylus",
200
- ext: "styl",
201
- aliases: ["styl", "stylus"]
202
- };
203
- var languageTypescript = {
204
- name: "typescript",
205
- ext: "ts",
206
- aliases: ["ts", "typescript"]
207
- };
208
- var languageYaml = {
209
- name: "yaml",
210
- ext: "yml",
211
- aliases: ["yaml", "yml"]
212
- };
213
-
214
- // src/plugins/codePlugin/resolveLanguage.ts
215
- var languagesMap;
216
- var getLanguagesMap = () => {
217
- if (!languagesMap) {
218
- languagesMap = Object.values(languages_exports).reduce((result, item) => {
219
- item.aliases.forEach((alias) => {
220
- result[alias] = item;
221
- });
222
- return result;
223
- }, {});
224
- }
225
- return languagesMap;
226
- };
227
- var resolveLanguage = (info) => {
228
- const alias = info.match(/^([^ :[{]+)/)?.[1] || "text";
229
- return getLanguagesMap()[alias] ?? {
230
- name: alias,
231
- ext: alias,
232
- aliases: [alias]
233
- };
234
- };
235
-
236
- // src/plugins/codePlugin/resolveLineNumbers.ts
237
- var resolveLineNumbers = (info) => {
238
- if (/:line-numbers\b/.test(info)) {
239
- return true;
240
- }
241
- if (/:no-line-numbers\b/.test(info)) {
242
- return false;
243
- }
244
- return null;
12
+ import { full as emojiPlugin } from "markdown-it-emoji";
13
+ import { inferRoutePath, isLinkExternal, removeLeadingSlash } from "@vuepress/shared";
14
+ //#region src/plugins/assetsPlugin/resolveLink.ts
15
+ const resolveLink = (link, { env, absolutePathPrependBase = false, aliasSupport = true }) => {
16
+ if (link.startsWith("data:")) return link;
17
+ let resolvedLink = decode(link);
18
+ if (aliasSupport === false || aliasSupport === "@-prefix") {
19
+ if (!(link.startsWith("/") || link.startsWith("./") || link.startsWith("../") || /[A-Za-z]+:\/\//.test(link))) {
20
+ if (aliasSupport === false || !link.startsWith("@")) resolvedLink = `./${resolvedLink}`;
21
+ }
22
+ }
23
+ if (absolutePathPrependBase && env.base && link.startsWith("/")) resolvedLink = path.join(env.base, resolvedLink);
24
+ return resolvedLink;
245
25
  };
246
-
247
- // src/plugins/codePlugin/resolveVPre.ts
248
- var resolveVPre = (info) => {
249
- if (/:v-pre\b/.test(info)) {
250
- return true;
251
- }
252
- if (/:no-v-pre\b/.test(info)) {
253
- return false;
254
- }
255
- return null;
26
+ //#endregion
27
+ //#region src/plugins/assetsPlugin/assetsPlugin.ts
28
+ /**
29
+ * Plugin to handle assets links
30
+ */
31
+ const assetsPlugin = (md, { absolutePathPrependBase = false, aliasSupport = true } = {}) => {
32
+ const rawImageRule = md.renderer.rules.image;
33
+ md.renderer.rules.image = (tokens, idx, options, env, self) => {
34
+ const token = tokens[idx];
35
+ const link = token.attrGet("src");
36
+ if (link) token.attrSet("src", resolveLink(link, {
37
+ env,
38
+ absolutePathPrependBase,
39
+ aliasSupport
40
+ }));
41
+ return rawImageRule(tokens, idx, options, env, self);
42
+ };
43
+ const createHtmlRule = (rawHtmlRule) => (tokens, idx, options, env, self) => {
44
+ tokens[idx].content = tokens[idx].content.replace(/(<(?:img|source|video|audio)\b.*?\bsrc=)(['"])(.*?)\2/gs, (_, prefix, quote, src) => `${prefix}${quote}${resolveLink(src.trim(), {
45
+ env,
46
+ absolutePathPrependBase,
47
+ aliasSupport
48
+ })}${quote}`).replace(/(<(?:img|source|video|audio)\b.*?\bsrcset=)(['"])(.*?)\2/gs, (_, prefix, quote, srcset) => `${prefix}${quote}${srcset.split(",").map((item) => item.trim().replace(/^([^ ]*?)([ \n].*)?$/, (__, url, descriptor = "") => `${resolveLink(url.trim(), {
49
+ env,
50
+ absolutePathPrependBase,
51
+ aliasSupport
52
+ })}${descriptor.replace(/[ \n]+/g, " ").trimEnd()}`)).join(", ")}${quote}`);
53
+ return rawHtmlRule(tokens, idx, options, env, self);
54
+ };
55
+ const rawHtmlBlockRule = md.renderer.rules.html_block;
56
+ const rawHtmlInlineRule = md.renderer.rules.html_inline;
57
+ md.renderer.rules.html_block = createHtmlRule(rawHtmlBlockRule);
58
+ md.renderer.rules.html_inline = createHtmlRule(rawHtmlInlineRule);
256
59
  };
257
-
258
- // src/plugins/codePlugin/codePlugin.ts
259
- var codePlugin = (md, {
260
- highlightLines = true,
261
- lineNumbers = true,
262
- preWrapper = true,
263
- vPre: { block: vPreBlock = true, inline: vPreInline = true } = {}
264
- } = {}) => {
265
- md.renderer.rules.fence = (tokens, idx, options, env, slf) => {
266
- const token = tokens[idx];
267
- const info = token.info ? md.utils.unescapeAll(token.info).trim() : "";
268
- const language = resolveLanguage(info);
269
- const languageClass = `${options.langPrefix}${language.name}`;
270
- const code = options.highlight?.(token.content, language.name, "") || md.utils.escapeHtml(token.content);
271
- token.attrJoin("class", languageClass);
272
- let result = code.startsWith("<pre") ? code : `<pre${slf.renderAttrs(token)}><code>${code}</code></pre>`;
273
- const useVPre = resolveVPre(info) ?? vPreBlock;
274
- if (useVPre) {
275
- result = `<pre v-pre${result.slice("<pre".length)}`;
276
- }
277
- if (!preWrapper) {
278
- return result;
279
- }
280
- const lines = code.split("\n").slice(0, -1);
281
- const highlightLinesRanges = highlightLines ? resolveHighlightLines(info) : null;
282
- if (highlightLinesRanges) {
283
- const highlightLinesCode = lines.map((_, index) => {
284
- if (isHighlightLine(index + 1, highlightLinesRanges)) {
285
- return '<div class="highlight-line">&nbsp;</div>';
286
- }
287
- return "<br>";
288
- }).join("");
289
- result = `${result}<div class="highlight-lines">${highlightLinesCode}</div>`;
290
- }
291
- const useLineNumbers = resolveLineNumbers(info) ?? (typeof lineNumbers === "number" ? lines.length >= lineNumbers : lineNumbers);
292
- if (useLineNumbers) {
293
- const lineNumbersCode = lines.map(() => `<div class="line-number"></div>`).join("");
294
- result = `${result}<div class="line-numbers" aria-hidden="true">${lineNumbersCode}</div>`;
295
- }
296
- const title = resolveAttr(info, "title") ?? language.ext;
297
- result = `<div class="${languageClass}${useLineNumbers ? " line-numbers-mode" : ""}" data-ext="${language.ext}" data-title="${title}">${result}</div>`;
298
- return result;
299
- };
300
- if (vPreInline) {
301
- const rawInlineCodeRule = md.renderer.rules.code_inline;
302
- md.renderer.rules.code_inline = (tokens, idx, options, env, slf) => {
303
- const result = rawInlineCodeRule(tokens, idx, options, env, slf);
304
- return `<code v-pre${result.slice("<code".length)}`;
305
- };
306
- }
60
+ //#endregion
61
+ //#region src/plugins/importCodePlugin/createImportCodeBlockRule.ts
62
+ const MIN_LENGTH = 9;
63
+ const START_CODES = [
64
+ 64,
65
+ 91,
66
+ 99,
67
+ 111,
68
+ 100,
69
+ 101
70
+ ];
71
+ const SYNTAX_RE = /^@\[code(?:{(?:(?:(?<lineStart>\d+)?-(?<lineEnd>\d+)?)|(?<lineSingle>\d+))})?(?: (?<info>[^\]]+))?\]\((?<importPath>[^)]*)\)/;
72
+ /**
73
+ * Utility function to parse line number from line string that matched by SYNTAX_RE
74
+ */
75
+ const parseLineNumber = (line) => line ? Number.parseInt(line, 10) : void 0;
76
+ const createImportCodeBlockRule = ({ handleImportPath = (str) => str }) => (state, startLine, endLine, silent) => {
77
+ /* istanbul ignore if */
78
+ if (state.sCount[startLine] - state.blkIndent >= 4) return false;
79
+ const pos = state.bMarks[startLine] + state.tShift[startLine];
80
+ const max = state.eMarks[startLine];
81
+ if (pos + MIN_LENGTH > max) return false;
82
+ for (let i = 0; i < START_CODES.length; i += 1) if (state.src.charCodeAt(pos + i) !== START_CODES[i]) return false;
83
+ const match = state.src.slice(pos, max).match(SYNTAX_RE);
84
+ if (!match?.groups) return false;
85
+ if (silent) return true;
86
+ const { info, importPath } = match.groups;
87
+ const lineSingle = parseLineNumber(match.groups.lineSingle);
88
+ const lineStart = lineSingle ?? parseLineNumber(match.groups.lineStart) ?? 0;
89
+ const lineEnd = lineSingle ?? parseLineNumber(match.groups.lineEnd);
90
+ const meta = {
91
+ importPath: handleImportPath(importPath),
92
+ lineStart,
93
+ lineEnd
94
+ };
95
+ const token = state.push("import_code", "code", 0);
96
+ token.info = info ?? path.extname(meta.importPath).slice(1);
97
+ token.markup = "```";
98
+ token.map = [startLine, startLine + 1];
99
+ token.meta = meta;
100
+ state.line = startLine + 1;
101
+ return true;
307
102
  };
308
-
309
- // src/plugins/emojiPlugin.ts
310
- import { full as emojiPlugin } from "markdown-it-emoji";
311
-
312
- // src/plugins/importCodePlugin/createImportCodeBlockRule.ts
313
- import { path as path2 } from "@vuepress/utils";
314
- var MIN_LENGTH = 9;
315
- var START_CODES = [64, 91, 99, 111, 100, 101];
316
- var SYNTAX_RE = /^@\[code(?:{(?:(\d+)?-(\d+)?)})?(?: ([^\]]+))?\]\(([^)]*)\)/;
317
- var createImportCodeBlockRule = ({ handleImportPath = (str) => str }) => (state, startLine, endLine, silent) => {
318
- if (state.sCount[startLine] - state.blkIndent >= 4) {
319
- return false;
320
- }
321
- const pos = state.bMarks[startLine] + state.tShift[startLine];
322
- const max = state.eMarks[startLine];
323
- if (pos + MIN_LENGTH > max)
324
- return false;
325
- for (let i = 0; i < START_CODES.length; i += 1) {
326
- if (state.src.charCodeAt(pos + i) !== START_CODES[i]) {
327
- return false;
328
- }
329
- }
330
- const match = state.src.slice(pos, max).match(SYNTAX_RE);
331
- if (!match)
332
- return false;
333
- if (silent)
334
- return true;
335
- const [, lineStart, lineEnd, info, importPath] = match;
336
- const meta = {
337
- importPath: handleImportPath(importPath),
338
- lineStart: lineStart ? Number.parseInt(lineStart, 10) : 0,
339
- lineEnd: lineEnd ? Number.parseInt(lineEnd, 10) : void 0
340
- };
341
- const token = state.push("import_code", "code", 0);
342
- token.info = info ?? path2.extname(meta.importPath).slice(1);
343
- token.markup = "```";
344
- token.map = [startLine, startLine + 1];
345
- token.meta = meta;
346
- state.line = startLine + 1;
347
- return true;
103
+ //#endregion
104
+ //#region src/plugins/importCodePlugin/resolveImportCode.ts
105
+ const resolveImportCode = ({ importPath, lineStart, lineEnd }, { filePath }) => {
106
+ let importFilePath = importPath;
107
+ if (!path.isAbsolute(importPath)) {
108
+ if (!filePath) {
109
+ logger.error(`Import file ${colors.magenta(importPath)} can not be resolved`);
110
+ return {
111
+ importFilePath: null,
112
+ importCode: "Error when resolving path"
113
+ };
114
+ }
115
+ importFilePath = path.resolve(filePath, "..", importPath);
116
+ }
117
+ if (!fs.existsSync(importFilePath)) {
118
+ logger.error(`Import file ${colors.magenta(importPath)} not found`);
119
+ return {
120
+ importFilePath,
121
+ importCode: "File not found"
122
+ };
123
+ }
124
+ const fileContent = fs.readFileSync(importFilePath).toString();
125
+ return {
126
+ importFilePath,
127
+ importCode: fileContent.split("\n").slice(lineStart ? lineStart - 1 : lineStart, lineEnd).join("\n").replace(/\n?$/, "\n")
128
+ };
348
129
  };
349
-
350
- // src/plugins/importCodePlugin/resolveImportCode.ts
351
- import { colors, fs, logger, path as path3 } from "@vuepress/utils";
352
- var resolveImportCode = ({ importPath, lineStart, lineEnd }, { filePath }) => {
353
- let importFilePath = importPath;
354
- if (!path3.isAbsolute(importPath)) {
355
- if (!filePath) {
356
- logger.error(
357
- `Import file ${colors.magenta(importPath)} can not be resolved`
358
- );
359
- return {
360
- importFilePath: null,
361
- importCode: "Error when resolving path"
362
- };
363
- }
364
- importFilePath = path3.resolve(filePath, "..", importPath);
365
- }
366
- if (!fs.existsSync(importFilePath)) {
367
- logger.error(`Import file ${colors.magenta(importPath)} not found`);
368
- return {
369
- importFilePath,
370
- importCode: "File not found"
371
- };
372
- }
373
- const fileContent = fs.readFileSync(importFilePath).toString();
374
- return {
375
- importFilePath,
376
- importCode: fileContent.split("\n").slice(lineStart ? lineStart - 1 : lineStart, lineEnd).join("\n").replace(/\n?$/, "\n")
377
- };
130
+ //#endregion
131
+ //#region src/plugins/importCodePlugin/importCodePlugin.ts
132
+ const importCodePlugin = (md, options = {}) => {
133
+ md.block.ruler.before("fence", "import_code", createImportCodeBlockRule(options), { alt: [
134
+ "paragraph",
135
+ "reference",
136
+ "blockquote",
137
+ "list"
138
+ ] });
139
+ md.renderer.rules.import_code = (tokens, idx, opts, env, slf) => {
140
+ const token = tokens[idx];
141
+ const { importFilePath, importCode } = resolveImportCode(token.meta, env);
142
+ token.content = importCode;
143
+ if (importFilePath) (env.importedFiles ??= []).push(importFilePath);
144
+ return md.renderer.rules.fence(tokens, idx, opts, env, slf);
145
+ };
378
146
  };
379
-
380
- // src/plugins/importCodePlugin/importCodePlugin.ts
381
- var importCodePlugin = (md, options = {}) => {
382
- md.block.ruler.before(
383
- "fence",
384
- "import_code",
385
- createImportCodeBlockRule(options),
386
- {
387
- alt: ["paragraph", "reference", "blockquote", "list"]
388
- }
389
- );
390
- md.renderer.rules.import_code = (tokens, idx, options2, env, slf) => {
391
- const token = tokens[idx];
392
- const { importFilePath, importCode } = resolveImportCode(token.meta, env);
393
- token.content = importCode;
394
- if (importFilePath) {
395
- ;
396
- (env.importedFiles ??= []).push(importFilePath);
397
- }
398
- return md.renderer.rules.fence(tokens, idx, options2, env, slf);
399
- };
147
+ //#endregion
148
+ //#region src/plugins/linksPlugin/resolvePaths.ts
149
+ /**
150
+ * Resolve relative and absolute paths according to the `base` and `filePathRelative`
151
+ */
152
+ const resolvePaths = (rawPath, base, filePathRelative) => {
153
+ let absolutePath;
154
+ let relativePath;
155
+ if (rawPath.startsWith("/")) if (rawPath.endsWith(".md")) {
156
+ absolutePath = path.join(base, rawPath);
157
+ relativePath = removeLeadingSlash(rawPath);
158
+ } else {
159
+ absolutePath = rawPath;
160
+ relativePath = path.relative(base, absolutePath);
161
+ }
162
+ else if (filePathRelative) {
163
+ relativePath = path.join(path.dirname(encodeURI(filePathRelative)), rawPath);
164
+ absolutePath = path.join(base, relativePath);
165
+ } else {
166
+ relativePath = rawPath.replace(/^(?:\.\/)?(.*)$/, "$1");
167
+ absolutePath = null;
168
+ }
169
+ return {
170
+ absolutePath,
171
+ relativePath
172
+ };
400
173
  };
401
-
402
- // src/plugins/linksPlugin/linksPlugin.ts
403
- import { isLinkExternal } from "@vuepress/shared";
404
-
405
- // src/plugins/linksPlugin/resolvePaths.ts
406
- import { removeLeadingSlash } from "@vuepress/shared";
407
- import { path as path4 } from "@vuepress/utils";
408
- var resolvePaths = (rawPath, base, filePathRelative) => {
409
- let absolutePath;
410
- let relativePath;
411
- if (rawPath.startsWith("/")) {
412
- if (rawPath.endsWith(".md")) {
413
- absolutePath = path4.join(base, rawPath);
414
- relativePath = removeLeadingSlash(rawPath);
415
- } else {
416
- absolutePath = rawPath;
417
- relativePath = path4.relative(base, absolutePath);
418
- }
419
- } else {
420
- if (filePathRelative) {
421
- relativePath = path4.join(
422
- // file path may contain non-ASCII characters
423
- path4.dirname(encodeURI(filePathRelative)),
424
- rawPath
425
- );
426
- absolutePath = path4.join(base, relativePath);
427
- } else {
428
- relativePath = rawPath.replace(/^(?:\.\/)?(.*)$/, "$1");
429
- absolutePath = relativePath;
430
- }
431
- }
432
- return {
433
- absolutePath,
434
- relativePath
435
- };
174
+ //#endregion
175
+ //#region src/plugins/linksPlugin/linksPlugin.ts
176
+ /**
177
+ * Process links in markdown file
178
+ *
179
+ * - internal links: convert `<a>` tag into internalTag
180
+ * - external links: add extra attrs
181
+ */
182
+ const linksPlugin = (md, options = {}) => {
183
+ const internalTag = options.internalTag || "RouteLink";
184
+ const isExternal = options.isExternal ?? ((href, env) => isLinkExternal(href, env.base));
185
+ const externalAttrs = {
186
+ target: "_blank",
187
+ rel: "noopener noreferrer",
188
+ ...options.externalAttrs
189
+ };
190
+ let hasOpenInternalLink = false;
191
+ const handleLinkOpen = (tokens, idx, env) => {
192
+ const token = tokens[idx];
193
+ const hrefIndex = token.attrIndex("href");
194
+ /* istanbul ignore if */
195
+ if (hrefIndex < 0) return;
196
+ const hrefAttr = token.attrs[hrefIndex];
197
+ const hrefLink = hrefAttr[1];
198
+ const { base = "/", filePathRelative = null } = env;
199
+ if (isExternal(hrefLink, env)) {
200
+ Object.entries(externalAttrs).forEach(([key, val]) => {
201
+ token.attrSet(key, val);
202
+ });
203
+ return;
204
+ }
205
+ const internalLinkMatch = hrefLink.match(/^([^#?]*?(?:\/|\.md|\.html))([#?].*)?$/);
206
+ if (!internalLinkMatch) return;
207
+ const rawPath = internalLinkMatch[1];
208
+ const rawHashAndQueries = (internalLinkMatch[2] || "").replace(/^#(\d)/, "#_$1");
209
+ const { relativePath, absolutePath } = resolvePaths(rawPath, base, filePathRelative);
210
+ if (["RouterLink", "RouteLink"].includes(internalTag)) {
211
+ token.tag = internalTag;
212
+ hrefAttr[0] = "to";
213
+ hrefAttr[1] = `${inferRoutePath(absolutePath ? absolutePath.replace(new RegExp(`^${base}`), "/") : relativePath)}${rawHashAndQueries}`;
214
+ hasOpenInternalLink = true;
215
+ } else hrefAttr[1] = `${inferRoutePath(absolutePath ?? relativePath)}${rawHashAndQueries}`;
216
+ (env.links ??= []).push({
217
+ raw: hrefLink,
218
+ relative: relativePath,
219
+ absolute: absolutePath
220
+ });
221
+ };
222
+ md.renderer.rules.link_open = (tokens, idx, opts, env, self) => {
223
+ handleLinkOpen(tokens, idx, env);
224
+ return self.renderToken(tokens, idx, opts);
225
+ };
226
+ md.renderer.rules.link_close = (tokens, idx, opts, _env, self) => {
227
+ if (hasOpenInternalLink) {
228
+ hasOpenInternalLink = false;
229
+ tokens[idx].tag = internalTag;
230
+ }
231
+ return self.renderToken(tokens, idx, opts);
232
+ };
436
233
  };
437
-
438
- // src/plugins/linksPlugin/linksPlugin.ts
439
- var linksPlugin = (md, options = {}) => {
440
- const internalTag = options.internalTag || "VPLink";
441
- const externalAttrs = {
442
- target: "_blank",
443
- rel: "noopener noreferrer",
444
- ...options.externalAttrs
445
- };
446
- let hasOpenInternalLink = false;
447
- const handleLinkOpen = (tokens, idx, env) => {
448
- const token = tokens[idx];
449
- const hrefIndex = token.attrIndex("href");
450
- if (hrefIndex < 0) {
451
- return;
452
- }
453
- const hrefAttr = token.attrs[hrefIndex];
454
- const hrefLink = hrefAttr[1];
455
- const { base = "/", filePathRelative = null } = env;
456
- if (isLinkExternal(hrefLink, base)) {
457
- Object.entries(externalAttrs).forEach(
458
- ([key, val]) => token.attrSet(key, val)
459
- );
460
- return;
461
- }
462
- const internalLinkMatch = hrefLink.match(
463
- /^((?:.*)(?:\/|\.md|\.html))(#.*)?$/
464
- );
465
- if (!internalLinkMatch) {
466
- return;
467
- }
468
- const rawPath = internalLinkMatch[1];
469
- const rawHash = internalLinkMatch[2] || "";
470
- const { relativePath, absolutePath } = resolvePaths(
471
- rawPath,
472
- base,
473
- filePathRelative
474
- );
475
- const normalizedPath = absolutePath.replace(new RegExp(`^${base}`), "/").replace(/(^|\/)(README|index).md$/i, "$1").replace(/\.md$/, ".html");
476
- if (["RouterLink", "VPLink"].includes(internalTag)) {
477
- token.tag = internalTag;
478
- hrefAttr[0] = "to";
479
- hasOpenInternalLink = true;
480
- }
481
- hrefAttr[1] = `${normalizedPath}${rawHash}`;
482
- (env.links ??= []).push({
483
- raw: hrefLink,
484
- relative: relativePath,
485
- absolute: absolutePath
486
- });
487
- };
488
- md.renderer.rules.link_open = (tokens, idx, options2, env, self) => {
489
- handleLinkOpen(tokens, idx, env);
490
- return self.renderToken(tokens, idx, options2);
491
- };
492
- md.renderer.rules.link_close = (tokens, idx, options2, env, self) => {
493
- if (hasOpenInternalLink) {
494
- hasOpenInternalLink = false;
495
- tokens[idx].tag = internalTag;
496
- }
497
- return self.renderToken(tokens, idx, options2);
498
- };
234
+ //#endregion
235
+ //#region src/plugins/vPrePlugin/resolveVPre.ts
236
+ /**
237
+ * Resolve the `:v-pre` / `:no-v-pre` mark from token info
238
+ */
239
+ const resolveVPre = (info) => {
240
+ if (/:v-pre\b/.test(info)) return true;
241
+ if (/:no-v-pre\b/.test(info)) return false;
242
+ return null;
499
243
  };
500
-
501
- // src/markdown.ts
502
- var createMarkdown = ({
503
- anchor,
504
- assets,
505
- code,
506
- component,
507
- emoji,
508
- frontmatter,
509
- headers,
510
- title,
511
- importCode,
512
- links,
513
- sfc,
514
- slugify = defaultSlugify,
515
- toc,
516
- ...markdownItOptions
517
- } = {}) => {
518
- const md = MarkdownIt({
519
- ...markdownItOptions,
520
- // should always enable html option
521
- html: true
522
- });
523
- if (anchor !== false) {
524
- md.use(anchorPlugin, {
525
- level: [1, 2, 3, 4, 5, 6],
526
- slugify,
527
- permalink: anchorPlugin.permalink.headerLink({
528
- class: "header-anchor",
529
- // Add a span inside the link so Safari shows headings in reader view.
530
- safariReaderFix: true
531
- }),
532
- ...anchor
533
- });
534
- }
535
- if (assets !== false) {
536
- md.use(assetsPlugin, assets);
537
- }
538
- if (code !== false) {
539
- md.use(codePlugin, code);
540
- }
541
- if (component !== false) {
542
- md.use(componentPlugin);
543
- }
544
- if (emoji !== false) {
545
- md.use(emojiPlugin, emoji);
546
- }
547
- if (frontmatter !== false) {
548
- md.use(frontmatterPlugin, {
549
- ...frontmatter,
550
- grayMatterOptions: {
551
- excerpt: false,
552
- ...frontmatter?.grayMatterOptions
553
- }
554
- });
555
- }
556
- if (headers !== false) {
557
- md.use(headersPlugin, {
558
- level: [2, 3],
559
- slugify,
560
- ...headers
561
- });
562
- }
563
- if (importCode !== false) {
564
- md.use(importCodePlugin, importCode);
565
- }
566
- if (links !== false) {
567
- md.use(linksPlugin, links);
568
- }
569
- if (sfc !== false) {
570
- md.use(sfcPlugin, sfc);
571
- }
572
- if (toc !== false) {
573
- md.use(tocPlugin, {
574
- level: [2, 3],
575
- slugify,
576
- linkTag: "router-link",
577
- ...toc
578
- });
579
- }
580
- if (title !== false) {
581
- md.use(titlePlugin);
582
- }
583
- return md;
244
+ //#endregion
245
+ //#region src/plugins/vPrePlugin/vPrePlugin.ts
246
+ /**
247
+ * v-pre plugin
248
+ */
249
+ const vPrePlugin = (md, { inline = true, block = true } = {}) => {
250
+ const rawFence = md.renderer.rules.fence;
251
+ md.renderer.rules.fence = (...args) => {
252
+ const [tokens, idx] = args;
253
+ const token = tokens[idx];
254
+ const info = token.info ? md.utils.unescapeAll(token.info).trim() : "";
255
+ let result = rawFence(...args);
256
+ if (resolveVPre(info) ?? block) result = `<pre v-pre${result.slice(4)}`;
257
+ return result;
258
+ };
259
+ if (inline) {
260
+ const rawInlineCodeRule = md.renderer.rules.code_inline;
261
+ md.renderer.rules.code_inline = (...args) => {
262
+ return `<code v-pre${rawInlineCodeRule(...args).slice(5)}`;
263
+ };
264
+ }
584
265
  };
585
- export {
586
- anchorPlugin,
587
- assetsPlugin,
588
- codePlugin,
589
- componentPlugin,
590
- createMarkdown,
591
- emojiPlugin,
592
- frontmatterPlugin,
593
- headersPlugin,
594
- importCodePlugin,
595
- linksPlugin,
596
- sfcPlugin,
597
- titlePlugin,
598
- tocPlugin
266
+ //#endregion
267
+ //#region src/markdown.ts
268
+ /**
269
+ * Create vuepress customized markdown-it instance
270
+ */
271
+ const createMarkdown = ({ anchor, assets, code, vPre, component, emoji, frontmatter, headers, title, importCode, links, sfc, slugify: slugify$1 = slugify, toc, ...markdownItOptions } = {}) => {
272
+ const md = MarkdownIt({
273
+ ...markdownItOptions,
274
+ html: true
275
+ });
276
+ if (anchor !== false) md.use(anchorPlugin, {
277
+ level: [
278
+ 1,
279
+ 2,
280
+ 3,
281
+ 4,
282
+ 5,
283
+ 6
284
+ ],
285
+ slugify: slugify$1,
286
+ permalink: anchorPlugin.permalink.headerLink({
287
+ class: "header-anchor",
288
+ safariReaderFix: true
289
+ }),
290
+ ...anchor
291
+ });
292
+ if (assets !== false) md.use(assetsPlugin, assets);
293
+ if (code) logger.warn(`\`markdown.code\` option has been removed, please use '@vuepress/plugin-shiki' or '@vuepress/plugin-prismjs' instead.\n See https://vuepress.vuejs.org/reference/config.html#markdown-code`);
294
+ if (component !== false) md.use(componentPlugin);
295
+ if (emoji !== false) md.use(emojiPlugin, emoji);
296
+ if (frontmatter !== false) md.use(frontmatterPlugin, {
297
+ ...frontmatter,
298
+ grayMatterOptions: {
299
+ excerpt: false,
300
+ ...frontmatter?.grayMatterOptions
301
+ }
302
+ });
303
+ if (headers !== false) md.use(headersPlugin, {
304
+ level: [2, 3],
305
+ slugify: slugify$1,
306
+ ...headers
307
+ });
308
+ if (importCode !== false) md.use(importCodePlugin, importCode);
309
+ if (links !== false) md.use(linksPlugin, links);
310
+ if (sfc !== false) md.use(sfcPlugin, sfc);
311
+ if (toc !== false) md.use(tocPlugin, {
312
+ level: [2, 3],
313
+ slugify: slugify$1,
314
+ linkTag: "router-link",
315
+ ...toc
316
+ });
317
+ if (title !== false) md.use(titlePlugin);
318
+ if (vPre !== false) md.use(vPrePlugin, vPre);
319
+ return md;
599
320
  };
321
+ //#endregion
322
+ export { anchorPlugin, assetsPlugin, componentPlugin, createMarkdown, emojiPlugin, frontmatterPlugin, headersPlugin, importCodePlugin, linksPlugin, sfcPlugin, titlePlugin, tocPlugin, vPrePlugin };