UNPKG

vitepress-plugin-pagefind

Version:

vitepress plugin, Offline full-text search based on pagefind implementation.

340 lines (336 loc) 11.7 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { chineseSearchOptimize: () => chineseSearchOptimize, formatShowDate: () => formatShowDate, meta2string: () => meta2string, pagefindPlugin: () => pagefindPlugin }); module.exports = __toCommonJS(src_exports); var import_node_buffer = require("buffer"); var import_node_path = __toESM(require("path")); var import_node_url = require("url"); var import_node_fs = __toESM(require("fs")); var import_node_process = __toESM(require("process")); var import_javascript_stringify = require("javascript-stringify"); var import_theme_shared2 = require("@sugarat/theme-shared"); // src/node.ts var import_node_child_process = require("child_process"); var import_theme_shared = require("@sugarat/theme-shared"); var ignoreSelectors = [ // 侧边栏内容 "div.aside", // 标题锚点 "a.header-anchor" ]; async function buildEnd(pagefindOps, siteConfig) { const ignore = [ ...new Set(ignoreSelectors.concat(pagefindOps?.excludeSelector || [])) ]; const { log } = console; log(); log("=== pagefind: https://pagefind.app/ ==="); let command = `npx pagefind --site "${siteConfig.outDir}"`; if (ignore.length) { command += ` --exclude-selectors "${ignore.join(", ")}"`; } if (typeof pagefindOps.forceLanguage === "string") { command += ` --force-language ${pagefindOps.forceLanguage}`; } if (pagefindOps.indexingCommand) { command = pagefindOps.indexingCommand; } log(command); log(); (0, import_node_child_process.execSync)(command, { stdio: "inherit" }); } function getPagefindHead(base) { return [ [ "script", {}, ` const load = () => { import('${(0, import_theme_shared.withBase)(base || "", "/pagefind/pagefind.js")}') .then((module) => { window.__pagefind__ = module module.init() }) .catch(() => { // console.log('not load /pagefind/pagefind.js') }) } if (window.requestIdleCallback) { window.requestIdleCallback(load) } else { setTimeout(load, 0) } ` ] ]; } function chineseSearchOptimize(input) { const segmenter = new Intl.Segmenter("zh-CN", { granularity: "word" }); const result = []; for (const it of segmenter.segment(input)) { if (it.isWordLike) { result.push(it.segment); } } return result.join(" "); } // src/utils/index.ts function formatDate(d, fmt = "yyyy-MM-dd hh:mm:ss") { if (!(d instanceof Date)) { d = new Date(d); } const o = { "M+": d.getMonth() + 1, // 月份 "d+": d.getDate(), // 日 "h+": d.getHours(), // 小时 "m+": d.getMinutes(), // 分 "s+": d.getSeconds(), // 秒 "q+": Math.floor((d.getMonth() + 3) / 3), // 季度 "S": d.getMilliseconds() // 毫秒 }; if (/(y+)/.test(fmt)) { fmt = fmt.replace( RegExp.$1, `${d.getFullYear()}`.substr(4 - RegExp.$1.length) ); } for (const k in o) { if (new RegExp(`(${k})`).test(fmt)) fmt = fmt.replace( RegExp.$1, RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length) ); } return fmt; } function formatShowDate(date, lang) { const source = +new Date(date); const now = +/* @__PURE__ */ new Date(); const diff = now - source; const oneSeconds = 1e3; const oneMinute = oneSeconds * 60; const oneHour = oneMinute * 60; const oneDay = oneHour * 24; const oneWeek = oneDay * 7; const langMap = { "zh-cn": { justNow: "\u521A\u521A", secondsAgo: "\u79D2\u524D", minutesAgo: "\u5206\u949F\u524D", hoursAgo: "\u5C0F\u65F6\u524D", daysAgo: "\u5929\u524D", weeksAgo: "\u5468\u524D" }, "en-us": { justNow: " just now", secondsAgo: " seconds ago", minutesAgo: " minutes ago", hoursAgo: " hours ago", daysAgo: " days ago", weeksAgo: " weeks ago" } }; const mapValue = langMap[lang.toLowerCase()] || langMap["en-us"]; if (diff < 10) { return mapValue.justNow; } if (diff < oneMinute) { return `${Math.floor(diff / oneSeconds)}${mapValue.secondsAgo}`; } if (diff < oneHour) { return `${Math.floor(diff / oneMinute)}${mapValue.minutesAgo}`; } if (diff < oneDay) { return `${Math.floor(diff / oneHour)}${mapValue.hoursAgo}`; } if (diff < oneWeek) { return `${Math.floor(diff / oneDay)}${mapValue.daysAgo}`; } return formatDate(new Date(date), "yyyy-MM-dd"); } // src/index.ts var import_meta = {}; function isESM() { return typeof __filename === "undefined" || typeof __dirname === "undefined"; } function getDirname() { return isESM() ? import_node_path.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)) : __dirname; } var aliasSearchVueFile = `${getDirname()}/../src/Search.vue`; var aliasSearchVueFileMPA = `${getDirname()}/../src/SearchMPA.vue`; var aliasSearchVueFileMPADefault = `${getDirname()}/../src/SearchMPADefault.vue`; function meta2string(frontmatter) { return `base64:${import_node_buffer.Buffer.from(encodeURIComponent(JSON.stringify(frontmatter))).toString("base64")}`; } function pagefindPlugin(searchConfig = {}) { const virtualModuleId = "virtual:pagefind"; const resolvedVirtualModuleId = `\0${virtualModuleId}`; let resolveConfig; let vitepressConfig; let dynamicRoutes; const pluginOps = { name: "vitepress-plugin-pagefind", config: (cfg) => { const isMPA = !!cfg.vitepress.mpa; const isMPADefaultUI = searchConfig.mpaDefaultUI; return { resolve: { alias: { "./VPNavBarSearch.vue": isMPA ? isMPADefaultUI ? aliasSearchVueFileMPADefault : aliasSearchVueFileMPA : aliasSearchVueFile } } }; }, async configResolved(config) { if (searchConfig.manual) { return; } if (resolveConfig) { return; } resolveConfig = config; vitepressConfig = config.vitepress; if (vitepressConfig) { dynamicRoutes = vitepressConfig.dynamicRoutes; } if (!vitepressConfig) { return; } if (!searchConfig.manual) { await (0, import_theme_shared2.cacheAllGitTimestamps)(vitepressConfig.srcDir); } const selfBuildEnd = vitepressConfig.buildEnd; vitepressConfig.buildEnd = async (siteConfig) => { const okMark = "\x1B[32m\u2713\x1B[0m"; console.time(`${okMark} generating pagefind Indexing...`); await selfBuildEnd?.(siteConfig); await buildEnd(searchConfig, siteConfig); console.timeEnd(`${okMark} generating pagefind Indexing...`); }; const selfTransformHead = vitepressConfig.transformHead; vitepressConfig.transformHead = async (ctx) => { const selfHead = await Promise.resolve(selfTransformHead?.(ctx)) || []; return selfHead.concat(getPagefindHead(ctx.siteData.base)); }; }, resolveId(id) { if (id === virtualModuleId) { return resolvedVirtualModuleId; } }, load(id) { if (id !== resolvedVirtualModuleId) return; return ` export const searchConfig = ${(0, import_javascript_stringify.stringify)(searchConfig)} `; }, // 添加检索的内容标识 async transform(code, id, options) { if (!id.includes(".md")) { return code; } let { searchParams, pathname, protocol } = new URL(id, "file:"); pathname = decodeURIComponent(pathname); if (!pathname.endsWith(".md")) { return code; } const isWindows = import_node_process.default.platform === "win32"; const fullPath = isWindows ? `${protocol}${pathname}` : pathname; const _dynamicRoutes = Array.isArray(dynamicRoutes) ? dynamicRoutes : dynamicRoutes?.routes || []; const dynamicRoute = _dynamicRoutes.find((route) => fullPath.toLowerCase() === route.fullPath.toLowerCase()); const isDynamicRoute = !!dynamicRoute; const filepath = isDynamicRoute ? (0, import_theme_shared2.joinPath)(vitepressConfig.srcDir, `/${dynamicRoute.route}`) : pathname; const isExist = import_node_fs.default.existsSync(filepath); if (!isExist) { this.warn(`${id}: not parse ${filepath} please contact the author for assistance`); return code; } if (!searchParams.size || searchParams.has("lang.ts")) { const fileContent = await import_node_fs.default.promises.readFile(filepath, "utf-8"); const { data: frontmatter, content } = (0, import_theme_shared2.grayMatter)(fileContent, { excerpt: true }); if (!content.trim()) { return code; } if (frontmatter["pagefind-indexed"] === false) { return code; } const attrs = { "data-pagefind-body": true }; if (!searchConfig.manual) { const cleanId = id.split("?")[0]; frontmatter.date = +new Date(frontmatter.date || await (0, import_theme_shared2.getFileLastModifyTime)(cleanId, vitepressConfig.cacheDir)); attrs["data-pagefind-meta"] = `date:${frontmatter.date}`; if (typeof searchConfig.filter === "function") { attrs["data-pagefind-meta"] = `${meta2string(frontmatter)}`; } } if (!code.includes(options?.ssr ? "_push(`" : '_createElementBlock("div", null')) { if (!code.includes(`${id}?vue&type=script&setup=true&lang.ts`)) { this.warn(`${options?.ssr ? "SSR" : "Client"} ${id} may not be a valid file, will not be indexed, please contact the author for assistance`); } return code; } if (options?.ssr) { return code.replace("_push(`", `Object.assign(_attrs, ${(0, import_javascript_stringify.stringify)(attrs)});_push(\``); } return code.replace('_createElementBlock("div", null', `_createElementBlock("div", ${(0, import_javascript_stringify.stringify)(attrs)}`); } return code; } }; return pluginOps; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { chineseSearchOptimize, formatShowDate, meta2string, pagefindPlugin }); //# sourceMappingURL=index.js.map