test02/node_modules/@vuepress/markdown/dist/index.js
罗佳鸿 6aa1ebe342
Some checks are pending
部署文档 / deploy-gh-pages (push) Waiting to run
first commit
2024-08-13 10:11:19 +08:00

439 lines
13 KiB
JavaScript

// src/markdown.ts
import { slugify as defaultSlugify } from "@mdit-vue/shared";
import { logger as logger2 } from "@vuepress/utils";
import MarkdownIt from "markdown-it";
// src/plugins.ts
import {
componentPlugin
} from "@mdit-vue/plugin-component";
import {
frontmatterPlugin
} from "@mdit-vue/plugin-frontmatter";
import {
headersPlugin
} from "@mdit-vue/plugin-headers";
import { sfcPlugin } from "@mdit-vue/plugin-sfc";
import { titlePlugin } from "@mdit-vue/plugin-title";
import { tocPlugin } from "@mdit-vue/plugin-toc";
// src/plugins/anchorPlugin.ts
import { default as anchorPlugin } from "markdown-it-anchor";
// src/plugins/assetsPlugin/resolveLink.ts
import { path } from "@vuepress/utils";
import { decode } from "mdurl";
var resolveLink = (link, {
env,
absolutePathPrependBase = false,
relativePathPrefix,
strict = false
}) => {
if (link.startsWith("data:")) return link;
let resolvedLink = decode(link);
const isRelativePath = strict ? (
// in strict mode, only link that starts with `./` or `../` is considered as relative path
/^\.{1,2}\//.test(link)
) : (
// in non-strict mode, link that does not start with `/` and does not have protocol is considered as relative path
!link.startsWith("/") && !/[A-z]+:\/\//.test(link)
);
if (isRelativePath && env.filePathRelative) {
resolvedLink = `${relativePathPrefix}/${path.join(
path.dirname(env.filePathRelative),
resolvedLink
)}`;
}
if (absolutePathPrependBase && env.base && link.startsWith("/")) {
resolvedLink = path.join(env.base, resolvedLink);
}
return resolvedLink;
};
// src/plugins/assetsPlugin/assetsPlugin.ts
var assetsPlugin = (md, {
absolutePathPrependBase = false,
relativePathPrefix = "@source"
} = {}) => {
const rawImageRule = md.renderer.rules.image;
md.renderer.rules.image = (tokens, idx, options, env, self) => {
const token = tokens[idx];
const link = token.attrGet("src");
if (link) {
token.attrSet(
"src",
resolveLink(link, { env, absolutePathPrependBase, relativePathPrefix })
);
}
return rawImageRule(tokens, idx, options, env, self);
};
const createHtmlRule = (rawHtmlRule) => (tokens, idx, options, env, self) => {
tokens[idx].content = tokens[idx].content.replace(
/(<img\b.*?src=)(['"])([^\2]*?)\2/gs,
(_, prefix, quote, src) => `${prefix}${quote}${resolveLink(src.trim(), {
env,
absolutePathPrependBase,
relativePathPrefix,
strict: true
})}${quote}`
).replace(
/(<img\b.*?srcset=)(['"])([^\2]*?)\2/gs,
(_, prefix, quote, srcset) => `${prefix}${quote}${srcset.split(",").map(
(item) => item.trim().replace(
/^([^ ]*?)([ \n].*)?$/,
(_2, url, descriptor = "") => `${resolveLink(url.trim(), {
env,
absolutePathPrependBase,
relativePathPrefix,
strict: true
})}${descriptor.replace(/[ \n]+/g, " ").trimEnd()}`
)
).join(", ")}${quote}`
);
return rawHtmlRule(tokens, idx, options, env, self);
};
const rawHtmlBlockRule = md.renderer.rules.html_block;
const rawHtmlInlineRule = md.renderer.rules.html_inline;
md.renderer.rules.html_block = createHtmlRule(rawHtmlBlockRule);
md.renderer.rules.html_inline = createHtmlRule(rawHtmlInlineRule);
};
// src/plugins/emojiPlugin.ts
import { full as emojiPlugin } from "markdown-it-emoji";
// src/plugins/importCodePlugin/createImportCodeBlockRule.ts
import { path as path2 } from "@vuepress/utils";
var MIN_LENGTH = 9;
var START_CODES = [64, 91, 99, 111, 100, 101];
var SYNTAX_RE = /^@\[code(?:{(?:(?:(?<lineStart>\d+)?-(?<lineEnd>\d+)?)|(?<lineSingle>\d+))})?(?: (?<info>[^\]]+))?\]\((?<importPath>[^)]*)\)/;
var parseLineNumber = (line) => line ? Number.parseInt(line, 10) : void 0;
var createImportCodeBlockRule = ({ handleImportPath = (str) => str }) => (state, startLine, endLine, silent) => {
if (state.sCount[startLine] - state.blkIndent >= 4) {
return false;
}
const pos = state.bMarks[startLine] + state.tShift[startLine];
const max = state.eMarks[startLine];
if (pos + MIN_LENGTH > max) return false;
for (let i = 0; i < START_CODES.length; i += 1) {
if (state.src.charCodeAt(pos + i) !== START_CODES[i]) {
return false;
}
}
const match = state.src.slice(pos, max).match(SYNTAX_RE);
if (!match?.groups) return false;
if (silent) return true;
const { info, importPath } = match.groups;
const lineSingle = parseLineNumber(match.groups.lineSingle);
const lineStart = lineSingle ?? parseLineNumber(match.groups.lineStart) ?? 0;
const lineEnd = lineSingle ?? parseLineNumber(match.groups.lineEnd);
const meta = {
importPath: handleImportPath(importPath),
lineStart,
lineEnd
};
const token = state.push("import_code", "code", 0);
token.info = info ?? path2.extname(meta.importPath).slice(1);
token.markup = "```";
token.map = [startLine, startLine + 1];
token.meta = meta;
state.line = startLine + 1;
return true;
};
// src/plugins/importCodePlugin/resolveImportCode.ts
import { colors, fs, logger, path as path3 } from "@vuepress/utils";
var resolveImportCode = ({ importPath, lineStart, lineEnd }, { filePath }) => {
let importFilePath = importPath;
if (!path3.isAbsolute(importPath)) {
if (!filePath) {
logger.error(
`Import file ${colors.magenta(importPath)} can not be resolved`
);
return {
importFilePath: null,
importCode: "Error when resolving path"
};
}
importFilePath = path3.resolve(filePath, "..", importPath);
}
if (!fs.existsSync(importFilePath)) {
logger.error(`Import file ${colors.magenta(importPath)} not found`);
return {
importFilePath,
importCode: "File not found"
};
}
const fileContent = fs.readFileSync(importFilePath).toString();
return {
importFilePath,
importCode: fileContent.split("\n").slice(lineStart ? lineStart - 1 : lineStart, lineEnd).join("\n").replace(/\n?$/, "\n")
};
};
// src/plugins/importCodePlugin/importCodePlugin.ts
var importCodePlugin = (md, options = {}) => {
md.block.ruler.before(
"fence",
"import_code",
createImportCodeBlockRule(options),
{
alt: ["paragraph", "reference", "blockquote", "list"]
}
);
md.renderer.rules.import_code = (tokens, idx, options2, env, slf) => {
const token = tokens[idx];
const { importFilePath, importCode } = resolveImportCode(token.meta, env);
token.content = importCode;
if (importFilePath) {
;
(env.importedFiles ??= []).push(importFilePath);
}
return md.renderer.rules.fence(tokens, idx, options2, env, slf);
};
};
// src/plugins/linksPlugin/linksPlugin.ts
import { inferRoutePath, isLinkExternal } from "@vuepress/shared";
// src/plugins/linksPlugin/resolvePaths.ts
import { removeLeadingSlash } from "@vuepress/shared";
import { path as path4 } from "@vuepress/utils";
var resolvePaths = (rawPath, base, filePathRelative) => {
let absolutePath;
let relativePath;
if (rawPath.startsWith("/")) {
if (rawPath.endsWith(".md")) {
absolutePath = path4.join(base, rawPath);
relativePath = removeLeadingSlash(rawPath);
} else {
absolutePath = rawPath;
relativePath = path4.relative(base, absolutePath);
}
} else {
if (filePathRelative) {
relativePath = path4.join(
// file path may contain non-ASCII characters
path4.dirname(encodeURI(filePathRelative)),
rawPath
);
absolutePath = path4.join(base, relativePath);
} else {
relativePath = rawPath.replace(/^(?:\.\/)?(.*)$/, "$1");
absolutePath = null;
}
}
return {
absolutePath,
relativePath
};
};
// src/plugins/linksPlugin/linksPlugin.ts
var linksPlugin = (md, options = {}) => {
const internalTag = options.internalTag || "RouteLink";
const externalAttrs = {
target: "_blank",
rel: "noopener noreferrer",
...options.externalAttrs
};
let hasOpenInternalLink = false;
const handleLinkOpen = (tokens, idx, env) => {
const token = tokens[idx];
const hrefIndex = token.attrIndex("href");
if (hrefIndex < 0) {
return;
}
const hrefAttr = token.attrs[hrefIndex];
const hrefLink = hrefAttr[1];
const { base = "/", filePathRelative = null } = env;
if (isLinkExternal(hrefLink, base)) {
Object.entries(externalAttrs).forEach(
([key, val]) => token.attrSet(key, val)
);
return;
}
const internalLinkMatch = hrefLink.match(
/^([^#?]*?(?:\/|\.md|\.html))([#?].*)?$/
);
if (!internalLinkMatch) {
return;
}
const rawPath = internalLinkMatch[1];
const rawHashAndQueries = internalLinkMatch[2] || "";
const { relativePath, absolutePath } = resolvePaths(
rawPath,
base,
filePathRelative
);
if (["RouterLink", "RouteLink"].includes(internalTag)) {
token.tag = internalTag;
hrefAttr[0] = "to";
const normalizedPath = inferRoutePath(
absolutePath ? absolutePath.replace(new RegExp(`^${base}`), "/") : relativePath
);
hrefAttr[1] = `${normalizedPath}${rawHashAndQueries}`;
hasOpenInternalLink = true;
} else {
const normalizedPath = inferRoutePath(absolutePath ?? relativePath);
hrefAttr[1] = `${normalizedPath}${rawHashAndQueries}`;
}
;
(env.links ??= []).push({
raw: hrefLink,
relative: relativePath,
absolute: absolutePath
});
};
md.renderer.rules.link_open = (tokens, idx, options2, env, self) => {
handleLinkOpen(tokens, idx, env);
return self.renderToken(tokens, idx, options2);
};
md.renderer.rules.link_close = (tokens, idx, options2, _env, self) => {
if (hasOpenInternalLink) {
hasOpenInternalLink = false;
tokens[idx].tag = internalTag;
}
return self.renderToken(tokens, idx, options2);
};
};
// src/plugins/vPrePlugin/resolveVPre.ts
var resolveVPre = (info) => {
if (/:v-pre\b/.test(info)) {
return true;
}
if (/:no-v-pre\b/.test(info)) {
return false;
}
return null;
};
// src/plugins/vPrePlugin/vPrePlugin.ts
var vPrePlugin = (md, { inline = true, block = true } = {}) => {
const rawFence = md.renderer.rules.fence;
md.renderer.rules.fence = (...args) => {
const [tokens, idx] = args;
const token = tokens[idx];
const info = token.info ? md.utils.unescapeAll(token.info).trim() : "";
let result = rawFence(...args);
if (resolveVPre(info) ?? block) {
result = `<pre v-pre${result.slice("<pre".length)}`;
}
return result;
};
if (inline) {
const rawInlineCodeRule = md.renderer.rules.code_inline;
md.renderer.rules.code_inline = (...args) => {
const result = rawInlineCodeRule(...args);
return `<code v-pre${result.slice("<code".length)}`;
};
}
};
// src/markdown.ts
var createMarkdown = ({
anchor,
assets,
code,
vPre,
component,
emoji,
frontmatter,
headers,
title,
importCode,
links,
sfc,
slugify = defaultSlugify,
toc,
...markdownItOptions
} = {}) => {
const md = MarkdownIt({
...markdownItOptions,
// should always enable html option
html: true
});
if (anchor !== false) {
md.use(anchorPlugin, {
level: [1, 2, 3, 4, 5, 6],
slugify,
permalink: anchorPlugin.permalink.headerLink({
class: "header-anchor",
// Add a span inside the link so Safari shows headings in reader view.
safariReaderFix: true
}),
...anchor
});
}
if (assets !== false) {
md.use(assetsPlugin, assets);
}
if (code) {
logger2.warn(
`\`markdown.code\` option has been removed, please use '@vuepress/plugin-shiki' or '@vuepress/plugin-prismjs' instead.
See https://v2.vuepress.vuejs.org/reference/config.html#markdown-code`
);
}
if (component !== false) {
md.use(componentPlugin);
}
if (emoji !== false) {
md.use(emojiPlugin, emoji);
}
if (frontmatter !== false) {
md.use(frontmatterPlugin, {
...frontmatter,
grayMatterOptions: {
excerpt: false,
...frontmatter?.grayMatterOptions
}
});
}
if (headers !== false) {
md.use(headersPlugin, {
level: [2, 3],
slugify,
...headers
});
}
if (importCode !== false) {
md.use(importCodePlugin, importCode);
}
if (links !== false) {
md.use(linksPlugin, links);
}
if (sfc !== false) {
md.use(sfcPlugin, sfc);
}
if (toc !== false) {
md.use(tocPlugin, {
level: [2, 3],
slugify,
linkTag: "router-link",
...toc
});
}
if (title !== false) {
md.use(titlePlugin);
}
if (vPre !== false) {
md.use(vPrePlugin, vPre);
}
return md;
};
export {
anchorPlugin,
assetsPlugin,
componentPlugin,
createMarkdown,
emojiPlugin,
frontmatterPlugin,
headersPlugin,
importCodePlugin,
linksPlugin,
sfcPlugin,
titlePlugin,
tocPlugin,
vPrePlugin
};