@nolebase/vitepress-plugin-meta
Version:
A vitepress plugin to add <meta> (excerpts, author, authors, etc.) to your rendered pages to maximize SEO and social media sharing capabilities.
94 lines (88 loc) • 3.8 kB
JavaScript
;
const defu = require('defu');
const hastUtilSelect = require('hast-util-select');
const hastUtilToText = require('hast-util-to-text');
const RehypeParse = require('rehype-parse');
const RetextStringify = require('retext-stringify');
const unified = require('unified');
const unistUtilRemove = require('unist-util-remove');
const unistUtilRemovePosition = require('unist-util-remove-position');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const RehypeParse__default = /*#__PURE__*/_interopDefaultCompat(RehypeParse);
const RetextStringify__default = /*#__PURE__*/_interopDefaultCompat(RetextStringify);
function RehypeRetext(option) {
return (nodes) => {
const vpDocElement = hastUtilSelect.select(option.selector, nodes);
if (!vpDocElement)
return;
if (vpDocElement.children.length === 0)
return;
for (const selector of option.removeSelectors) {
const elements = hastUtilSelect.selectAll(selector, vpDocElement);
if (elements)
unistUtilRemove.remove(vpDocElement, elements);
}
unistUtilRemovePosition.removePosition(vpDocElement);
if (nodes.type !== "root" && nodes.type !== "element")
return;
const text = hastUtilToText.toText(vpDocElement).replaceAll(/(\n){2,}/g, " ");
nodes.children = [{ type: "text", value: text }];
};
}
function getMeta(head, fromKey, withValue) {
return head.find(([key, attrs]) => key === "meta" && attrs[fromKey] === withValue);
}
function updateMetaOrCreateMeta(head, fromKey, withValue, asContent) {
const meta = head.find(([key, attrs]) => key === "meta" && attrs[fromKey] === withValue);
if (meta) {
meta[1].content = asContent;
return head;
}
head.push(["meta", { [fromKey]: withValue, content: asContent }]);
return head;
}
function transformHeadMeta(options) {
const opts = defu.defu(options, {
length: 200,
contentSelector: "#VPContent div.content main .vp-doc div",
removeContentSelector: [
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
".vp-nolebase-page-properties-container",
".vp-nolebase-git-changelog-history-container",
".vp-nolebase-git-changelog-contributors-container"
],
useTaglineForHomeLayout: true
});
return async (head, context) => {
const result = (await unified.unified().data({ settings: { fragment: true } }).use(RehypeParse__default).use(RehypeRetext, {
selector: opts.contentSelector,
removeSelectors: opts.removeContentSelector
}).use(RetextStringify__default).process(context.content)).toString();
let excerpt = result.slice(0, opts.length).trim();
if (result.length > opts.length)
excerpt += "...";
if (context.pageData.frontmatter?.layout === "home" && opts.useTaglineForHomeLayout)
excerpt = context.pageData.frontmatter?.hero?.tagline ?? context.siteConfig.site.description;
if (opts.handleExcerpt && typeof opts.handleExcerpt === "function") {
const handledResult = opts.handleExcerpt(excerpt, context);
if (handledResult && typeof handledResult === "string")
excerpt = handledResult;
else if (handledResult instanceof Promise)
excerpt = await handledResult;
}
const ogTitle = getMeta(head, "property", "og:title");
if (!ogTitle && context.pageData.title)
head = updateMetaOrCreateMeta(head, "property", "og:title", context.pageData.title);
head = updateMetaOrCreateMeta(head, "name", "description", excerpt);
head = updateMetaOrCreateMeta(head, "property", "og:description", excerpt);
head = updateMetaOrCreateMeta(head, "property", "twitter:description", excerpt);
return head;
};
}
exports.transformHeadMeta = transformHeadMeta;
//# sourceMappingURL=index.cjs.map