348 lines
12 KiB
JavaScript
348 lines
12 KiB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
|
|
|
|
var _chunkPMBWJGAHcjs = require('./chunk-PMBWJGAH.cjs');
|
|
|
|
// src/index.ts
|
|
var _pluginutils = require('@rollup/pluginutils');
|
|
var _unplugin = require('unplugin');
|
|
|
|
// node_modules/.pnpm/@antfu+utils@0.7.10/node_modules/@antfu/utils/dist/index.mjs
|
|
function toArray(array) {
|
|
array = _nullishCoalesce(array, () => ( []));
|
|
return Array.isArray(array) ? array : [array];
|
|
}
|
|
function uniq(array) {
|
|
return Array.from(new Set(array));
|
|
}
|
|
var VOID = Symbol("p-void");
|
|
|
|
// src/core/markdown.ts
|
|
var _plugincomponent = require('@mdit-vue/plugin-component');
|
|
var _pluginfrontmatter = require('@mdit-vue/plugin-frontmatter');
|
|
var _markdownitasync = require('markdown-it-async'); var _markdownitasync2 = _interopRequireDefault(_markdownitasync);
|
|
|
|
// src/core/head.ts
|
|
var headProperties = [
|
|
"title",
|
|
"meta",
|
|
"link",
|
|
"base",
|
|
"style",
|
|
"script",
|
|
"htmlAttrs",
|
|
"bodyAttrs"
|
|
];
|
|
function preprocessHead(frontmatter, options) {
|
|
if (!options.headEnabled)
|
|
return frontmatter;
|
|
const head = options.headField ? frontmatter[options.headField] || {} : frontmatter;
|
|
const meta = head.meta = head.meta || [];
|
|
if (head.title) {
|
|
if (!meta.find((i) => i.property === "og:title"))
|
|
meta.push({ property: "og:title", content: head.title });
|
|
if (!meta.find((i) => i.name === "twitter:title"))
|
|
meta.push({ name: "twitter:title", content: head.title });
|
|
}
|
|
if (head.description) {
|
|
if (!meta.find((i) => i.name === "description"))
|
|
meta.push({ name: "description", content: head.description });
|
|
if (!meta.find((i) => i.property === "og:description"))
|
|
meta.push({ property: "og:description", content: head.description });
|
|
if (!meta.find((i) => i.name === "twitter:description"))
|
|
meta.push({ name: "twitter:description", content: head.description });
|
|
}
|
|
if (head.image) {
|
|
if (!meta.find((i) => i.property === "og:image"))
|
|
meta.push({ property: "og:image", content: head.image });
|
|
if (!meta.find((i) => i.name === "twitter:image"))
|
|
meta.push({ name: "twitter:image", content: head.image });
|
|
if (!meta.find((i) => i.property === "twitter:card"))
|
|
meta.push({ name: "twitter:card", content: "summary_large_image" });
|
|
}
|
|
const result = {};
|
|
for (const [key, value] of Object.entries(head)) {
|
|
if (headProperties.includes(key))
|
|
result[key] = value;
|
|
}
|
|
return Object.entries(result).length === 0 ? null : result;
|
|
}
|
|
|
|
// src/core/markdown.ts
|
|
var scriptSetupRE = /<\s*script([^>]*)\bsetup\b([^>]*)>([\s\S]*)<\/script>/g;
|
|
var defineExposeRE = /defineExpose\s*\(/g;
|
|
var EXPORTS_KEYWORDS = [
|
|
"class",
|
|
"default",
|
|
"export",
|
|
"function",
|
|
"import",
|
|
"let",
|
|
"var",
|
|
"const",
|
|
"from",
|
|
"as",
|
|
"return",
|
|
"if",
|
|
"else",
|
|
"switch",
|
|
"case",
|
|
"break",
|
|
"for",
|
|
"while",
|
|
"do"
|
|
];
|
|
function extractScriptSetup(html) {
|
|
const scripts = [];
|
|
html = html.replace(scriptSetupRE, (_, attr1, attr2, code) => {
|
|
scripts.push({
|
|
code,
|
|
attr: `${attr1} ${attr2}`.trim()
|
|
});
|
|
return "";
|
|
});
|
|
return { html, scripts };
|
|
}
|
|
function extractCustomBlock(html, options) {
|
|
const blocks = [];
|
|
for (const tag of options.customSfcBlocks) {
|
|
html = html.replace(new RegExp(`<${tag}[^>]*\\b[^>]*>[^<]*<\\/${tag}>`, "gm"), (code) => {
|
|
blocks.push(code);
|
|
return "";
|
|
});
|
|
}
|
|
return { html, blocks };
|
|
}
|
|
function createMarkdown(options) {
|
|
const isVue2 = options.vueVersion.startsWith("2.");
|
|
const markdown = _markdownitasync2.default.call(void 0, {
|
|
html: true,
|
|
linkify: true,
|
|
typographer: true,
|
|
...options.markdownItOptions
|
|
});
|
|
markdown.use(_plugincomponent.componentPlugin, options.componentOptions);
|
|
if (options.frontmatter || options.excerpt) {
|
|
markdown.use(_pluginfrontmatter.frontmatterPlugin, {
|
|
...options.frontmatterOptions,
|
|
grayMatterOptions: {
|
|
excerpt: options.excerpt,
|
|
...options.frontmatterOptions.grayMatterOptions
|
|
}
|
|
});
|
|
}
|
|
markdown.linkify.set({ fuzzyLink: false });
|
|
options.markdownItUses.forEach((e) => {
|
|
const [plugin, options2] = toArray(e);
|
|
markdown.use(plugin, options2);
|
|
});
|
|
const setupPromise = (async () => {
|
|
await options.markdownItSetup(markdown);
|
|
})();
|
|
return async (id, raw) => {
|
|
await setupPromise;
|
|
const {
|
|
wrapperClasses,
|
|
wrapperComponent,
|
|
transforms,
|
|
headEnabled,
|
|
frontmatterPreprocess
|
|
} = options;
|
|
raw = raw.trimStart();
|
|
raw = _nullishCoalesce(_optionalChain([transforms, 'access', _2 => _2.before, 'optionalCall', _3 => _3(raw, id)]), () => ( raw));
|
|
const env = { id };
|
|
let html = await markdown.renderAsync(raw, env);
|
|
const { excerpt = "", frontmatter: data = null } = env;
|
|
const wrapperClassesResolved = toArray(
|
|
typeof wrapperClasses === "function" ? wrapperClasses(id, raw) : wrapperClasses
|
|
).filter(Boolean).join(" ");
|
|
if (wrapperClassesResolved)
|
|
html = `<div class="${wrapperClassesResolved}">${html}</div>`;
|
|
else
|
|
html = `<div>${html}</div>`;
|
|
const wrapperComponentName = typeof wrapperComponent === "function" ? wrapperComponent(id, raw) : wrapperComponent;
|
|
if (wrapperComponentName) {
|
|
const attrs2 = [
|
|
options.frontmatter && ':frontmatter="frontmatter"',
|
|
options.excerpt && ':excerpt="excerpt"'
|
|
].filter(Boolean).join(" ");
|
|
html = `<${wrapperComponentName} ${attrs2}>${html}</${wrapperComponentName}>`;
|
|
}
|
|
html = _nullishCoalesce(_optionalChain([transforms, 'access', _4 => _4.after, 'optionalCall', _5 => _5(html, id)]), () => ( html));
|
|
if (options.escapeCodeTagInterpolation) {
|
|
html = html.replace(/<code(.*?)>/g, "<code$1 v-pre>");
|
|
}
|
|
const hoistScripts = extractScriptSetup(html);
|
|
html = hoistScripts.html;
|
|
const customBlocks = extractCustomBlock(html, options);
|
|
html = customBlocks.html;
|
|
const scriptLines = [];
|
|
let frontmatterExportsLines = [];
|
|
let excerptExportsLine = "";
|
|
let excerptKeyOverlapping = false;
|
|
function hasExplicitExports() {
|
|
return defineExposeRE.test(hoistScripts.scripts.map((i) => i.code).join(""));
|
|
}
|
|
if (options.frontmatter) {
|
|
if (options.excerpt && data) {
|
|
if (data.excerpt !== void 0)
|
|
excerptKeyOverlapping = true;
|
|
data.excerpt = excerpt;
|
|
}
|
|
const { head, frontmatter } = frontmatterPreprocess(data || {}, options, id, preprocessHead);
|
|
if (options.excerpt && !excerptKeyOverlapping && frontmatter.excerpt !== void 0)
|
|
delete frontmatter.excerpt;
|
|
scriptLines.push(`const frontmatter = ${JSON.stringify(frontmatter)}`);
|
|
if (options.exportFrontmatter) {
|
|
frontmatterExportsLines = Object.entries(frontmatter).map(([key, value]) => {
|
|
if (EXPORTS_KEYWORDS.includes(key))
|
|
key = `_${key}`;
|
|
return `export const ${key} = ${JSON.stringify(value)}`;
|
|
});
|
|
}
|
|
if (!isVue2 && options.exposeFrontmatter && !hasExplicitExports())
|
|
scriptLines.push("defineExpose({ frontmatter })");
|
|
if (!isVue2 && headEnabled && head) {
|
|
if (headEnabled === "vueuse")
|
|
throw new Error("unplugin-vue-markdown no longer supports @vueuse/head. Change `headEnabled` to `true` and install `@unhead/vue` instead.");
|
|
scriptLines.push(`const head = ${JSON.stringify(head)}`);
|
|
scriptLines.unshift(`import { useHead } from "@unhead/vue"`);
|
|
scriptLines.push("useHead(head)");
|
|
}
|
|
scriptLines.push(..._optionalChain([transforms, 'access', _6 => _6.extraScripts, 'optionalCall', _7 => _7(frontmatter, id)]) || []);
|
|
}
|
|
if (options.excerpt) {
|
|
scriptLines.push(`const excerpt = ${JSON.stringify(excerpt)}`);
|
|
if (!excerptKeyOverlapping)
|
|
excerptExportsLine = `export const excerpt = ${JSON.stringify(excerpt)}
|
|
`;
|
|
if (!isVue2 && options.exposeExcerpt && !hasExplicitExports())
|
|
scriptLines.push("defineExpose({ excerpt })");
|
|
}
|
|
scriptLines.push(...hoistScripts.scripts.map((i) => i.code));
|
|
let attrs = uniq(hoistScripts.scripts.map((i) => i.attr)).join(" ").trim();
|
|
if (attrs)
|
|
attrs = ` ${attrs}`;
|
|
const scripts = isVue2 ? [
|
|
`<script${attrs}>`,
|
|
...scriptLines,
|
|
...frontmatterExportsLines,
|
|
excerptExportsLine,
|
|
"export default { data() { return { frontmatter } } }",
|
|
"</script>"
|
|
] : [
|
|
`<script setup${attrs}>`,
|
|
...scriptLines,
|
|
"</script>",
|
|
...frontmatterExportsLines.length || excerptExportsLine ? [
|
|
`<script${attrs}>`,
|
|
...frontmatterExportsLines,
|
|
excerptExportsLine,
|
|
"</script>"
|
|
] : []
|
|
];
|
|
const code = [
|
|
`<template>${html}</template>`,
|
|
...scripts.map((i) => i.trim()).filter(Boolean),
|
|
...customBlocks.blocks
|
|
].join("\n");
|
|
return {
|
|
code,
|
|
map: { mappings: "" }
|
|
};
|
|
};
|
|
}
|
|
|
|
// src/core/utils.ts
|
|
var _module = require('module');
|
|
var _require = typeof _chunkPMBWJGAHcjs.__require === "undefined" ? _module.createRequire.call(void 0, _chunkPMBWJGAHcjs.importMetaUrl) : _chunkPMBWJGAHcjs.__require;
|
|
function getVueVersion(defaultVersion = "3.2.0") {
|
|
try {
|
|
let v = _require("vue");
|
|
if (v.default)
|
|
v = v.default;
|
|
return v.version || defaultVersion;
|
|
} catch (e2) {
|
|
return defaultVersion;
|
|
}
|
|
}
|
|
|
|
// src/core/options.ts
|
|
function resolveOptions(userOptions) {
|
|
const defaultOptions = {
|
|
headEnabled: false,
|
|
headField: "",
|
|
frontmatter: true,
|
|
excerpt: false,
|
|
exposeFrontmatter: true,
|
|
exposeExcerpt: false,
|
|
exportFrontmatter: true,
|
|
escapeCodeTagInterpolation: true,
|
|
customSfcBlocks: ["route", "i18n", "style"],
|
|
componentOptions: {},
|
|
frontmatterOptions: {},
|
|
markdownItOptions: {},
|
|
markdownItUses: [],
|
|
markdownItSetup: () => {
|
|
},
|
|
wrapperComponent: null,
|
|
transforms: {},
|
|
vueVersion: userOptions.vueVersion || getVueVersion(),
|
|
wrapperClasses: "markdown-body",
|
|
include: null,
|
|
exclude: null,
|
|
frontmatterPreprocess: (frontmatter, options2, _id, defaults) => {
|
|
return {
|
|
head: defaults(frontmatter, options2),
|
|
frontmatter
|
|
};
|
|
}
|
|
};
|
|
const options = {
|
|
...defaultOptions,
|
|
...userOptions
|
|
};
|
|
return options;
|
|
}
|
|
|
|
// src/index.ts
|
|
var cssIdRE = /\.(css|postcss|sass|scss|less|stylus|styl)($|\?)/;
|
|
var unpluginFactory = (userOptions = {}) => {
|
|
const options = resolveOptions(userOptions);
|
|
const markdownToVue = createMarkdown(options);
|
|
const filter = _pluginutils.createFilter.call(void 0,
|
|
userOptions.include || /\.md$|\.md\?vue/,
|
|
userOptions.exclude || cssIdRE
|
|
);
|
|
return {
|
|
name: "unplugin-vue-markdown",
|
|
enforce: "pre",
|
|
transformInclude(id) {
|
|
return filter(id);
|
|
},
|
|
async transform(raw, id) {
|
|
try {
|
|
return await markdownToVue(id, raw);
|
|
} catch (e) {
|
|
this.error(e);
|
|
}
|
|
},
|
|
vite: {
|
|
async handleHotUpdate(ctx) {
|
|
if (!filter(ctx.file))
|
|
return;
|
|
const defaultRead = ctx.read;
|
|
ctx.read = async function() {
|
|
return (await markdownToVue(ctx.file, await defaultRead())).code;
|
|
};
|
|
}
|
|
}
|
|
};
|
|
};
|
|
var src_default = /* @__PURE__ */ _unplugin.createUnplugin.call(void 0, unpluginFactory);
|
|
|
|
|
|
|
|
|
|
exports.unpluginFactory = unpluginFactory; exports.src_default = src_default;
|