fuc-new/doc/node_modules/vuepress-plugin-md-power/lib/node/index.js
hellcat 6adbc04d4b 1
2025-10-03 17:17:08 +08:00

4435 lines
144 KiB
JavaScript

import { createRequire } from "node:module";
import { tab } from "@mdit/plugin-tab";
import { addViteOptimizeDepsInclude, encodeData, ensureEndingSlash, isArray, isLinkAbsolute, isLinkExternal, isLinkHttp, isPlainObject } from "@vuepress/helper";
import { Buffer } from "node:buffer";
import http from "node:https";
import { URL, URLSearchParams } from "node:url";
import { camelCase, isBoolean, isEmptyObject, isNull, isNumber, isPlainObject as isPlainObject$1, isString, isUndefined, kebabCase, notNullish, omit, toArray, uniqueBy, withTimeout } from "@pengzhanbo/utils";
import imageSize from "image-size";
import { colors, fs, getDirname, logger, ora, path } from "vuepress/utils";
import path$1 from "node:path";
import { globSync } from "tinyglobby";
import { isLinkHttp as isLinkHttp$1, isLinkWithProtocol, removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
import fs$1, { promises } from "node:fs";
import process from "node:process";
import container from "markdown-it-container";
import { isPackageExists, resolveModule } from "local-pkg";
import { LRUCache } from "lru-cache";
import { watch } from "chokidar";
import { customAlphabet } from "nanoid";
import { removeLeadingSlash as removeLeadingSlash$1 } from "@vuepress/shared";
import { path as path$2 } from "@vuepress/utils";
import { attrs } from "@mdit/plugin-attrs";
import { footnote } from "@mdit/plugin-footnote";
import { mark } from "@mdit/plugin-mark";
import { sub } from "@mdit/plugin-sub";
import { sup } from "@mdit/plugin-sup";
import { tasklist } from "@mdit/plugin-tasklist";
//#region src/node/fileIcons/definitions.ts
const defaultFolder = "vscode-icons:default-folder";
const defaultFile = "vscode-icons:default-file";
const definitions = {
named: {
"pnpm": "vscode-icons:file-type-light-pnpm",
"PNPM": "vscode-icons:file-type-light-pnpm",
"npm": "logos:npm-icon",
"NPM": "logos:npm-icon",
"yarn": "vscode-icons:file-type-yarn",
"Yarn": "vscode-icons:file-type-yarn",
"bun": "vscode-icons:file-type-bun",
"Bun": "vscode-icons:file-type-bun",
"deno": "vscode-icons:file-type-light-deno",
"Deno": "vscode-icons:file-type-light-deno",
"rollup": "vscode-icons:file-type-rollup",
"Rollup": "vscode-icons:file-type-rollup",
"webpack": "vscode-icons:file-type-webpack",
"Webpack": "vscode-icons:file-type-webpack",
"vite": "vscode-icons:file-type-vite",
"Vite": "vscode-icons:file-type-vite",
"esbuild": "vscode-icons:file-type-esbuild",
"Esbuild": "vscode-icons:file-type-esbuild",
"vue": "vscode-icons:file-type-vue",
"Vue": "vscode-icons:file-type-vue",
"svelte": "vscode-icons:file-type-svelte",
"Svelte": "vscode-icons:file-type-svelte",
"sveltekit": "vscode-icons:file-type-svelte",
"SvelteKit": "vscode-icons:file-type-svelte",
"angular": "vscode-icons:file-type-angular",
"Angular": "vscode-icons:file-type-angular",
"react": "vscode-icons:file-type-reactjs",
"React": "vscode-icons:file-type-reactjs",
"next": "vscode-icons:file-type-light-next",
"Next": "vscode-icons:file-type-light-next",
"Nextjs": "vscode-icons:file-type-light-next",
"NextJS": "vscode-icons:file-type-light-next",
"nuxt": "vscode-icons:file-type-nuxt",
"Nuxt": "vscode-icons:file-type-nuxt",
"Nuxtjs": "vscode-icons:file-type-nuxt",
"NuxtJS": "vscode-icons:file-type-nuxt",
"solid": "logos:solidjs-icon",
"Solid": "logos:solidjs-icon",
"solidjs": "logos:solidjs-icon",
"astro": "vscode-icons:file-type-light-astro",
"Astro": "vscode-icons:file-type-light-astro",
"vitest": "vscode-icons:file-type-vitest",
"Vitest": "vscode-icons:file-type-vitest",
"playwright": "vscode-icons:file-type-playwright",
"Playwright": "vscode-icons:file-type-playwright",
"jest": "vscode-icons:file-type-jest",
"Jest": "vscode-icons:file-type-jest",
"cypress": "vscode-icons:file-type-cypress",
"Cypress": "vscode-icons:file-type-cypress",
"docker": "vscode-icons:file-type-docker",
"Docker": "vscode-icons:file-type-docker",
"html": "vscode-icons:file-type-html",
"Html": "vscode-icons:file-type-html",
"HTML": "vscode-icons:file-type-html",
"javascript": "vscode-icons:file-type-js-official",
"Javascript": "vscode-icons:file-type-js-official",
"JavaScript": "vscode-icons:file-type-js-official",
"js": "vscode-icons:file-type-js-official",
"JS": "vscode-icons:file-type-js-official",
"typescript": "vscode-icons:file-type-typescript-official",
"Typescript": "vscode-icons:file-type-typescript-official",
"TypeScript": "vscode-icons:file-type-typescript-official",
"ts": "vscode-icons:file-type-typescript-official",
"TS": "vscode-icons:file-type-typescript-official",
"css": "vscode-icons:file-type-css",
"CSS": "vscode-icons:file-type-css",
"less": "vscode-icons:file-type-less",
"Less": "vscode-icons:file-type-less",
"LESS": "vscode-icons:file-type-less",
"scss": "vscode-icons:file-type-scss",
"Scss": "vscode-icons:file-type-scss",
"SCSS": "vscode-icons:file-type-scss",
"sass": "vscode-icons:file-type-sass",
"Sass": "vscode-icons:file-type-sass",
"SASS": "vscode-icons:file-type-sass",
"stylus": "vscode-icons:file-type-light-stylus",
"Stylus": "vscode-icons:file-type-light-stylus",
"postcss": "vscode-icons:file-type-postcss",
"Postcss": "vscode-icons:file-type-postcss",
"PostCSS": "vscode-icons:file-type-postcss",
"sh": "vscode-icons:file-type-shell",
"shell": "vscode-icons:file-type-shell",
"Shell": "vscode-icons:file-type-shell",
"bash": "vscode-icons:file-type-shell",
"Bash": "vscode-icons:file-type-shell",
"java": "vscode-icons:file-type-java",
"Java": "vscode-icons:file-type-java",
"JAVA": "vscode-icons:file-type-java",
"php": "vscode-icons:file-type-php3",
"PHP": "vscode-icons:file-type-php3",
"c": "vscode-icons:file-type-c",
"C": "vscode-icons:file-type-c",
"python": "vscode-icons:file-type-python",
"Python": "vscode-icons:file-type-python",
"kotlin": "vscode-icons:file-type-kotlin",
"Kotlin": "vscode-icons:file-type-kotlin",
"go": "vscode-icons:file-type-go-gopher",
"golang": "vscode-icons:file-type-go-gopher",
"Go": "vscode-icons:file-type-go-gopher",
"GoLang": "vscode-icons:file-type-go-gopher",
"rust": "vscode-icons:file-type-rust",
"Rust": "vscode-icons:file-type-rust",
"zig": "vscode-icons:file-type-zig",
"Zig": "vscode-icons:file-type-zig",
"swift": "vscode-icons:file-type-swift",
"Swift": "vscode-icons:file-type-swift",
"c#": "vscode-icons:file-type-csharp",
"CSharp": "vscode-icons:file-type-csharp",
"c++": "vscode-icons:file-type-cpp",
"C++": "vscode-icons:file-type-cpp",
"ruby": "vscode-icons:file-type-ruby",
"Ruby": "vscode-icons:file-type-ruby",
"makefile": "vscode-icons:file-type-makefile",
"Makefile": "vscode-icons:file-type-makefile",
"Object-C": "vscode-icons:file-type-objectivec",
"object-c": "vscode-icons:file-type-objectivec",
"SQL": "vscode-icons:file-type-sql",
"sql": "vscode-icons:file-type-sql",
"mysql": "vscode-icons:file-type-mysql",
"MySQL": "vscode-icons:file-type-mysql",
"MySql": "vscode-icons:file-type-mysql",
"pgsql": "vscode-icons:file-type-pgsql",
"PostgreSQL": "vscode-icons:file-type-pgsql",
"PGSQL": "vscode-icons:file-type-pgsql",
"xml": "vscode-icons:file-type-xml",
"XML": "vscode-icons:file-type-xml",
"wasm": "vscode-icons:file-type-wasm",
"webassembly": "vscode-icons:file-type-wasm",
"WebAssembly": "vscode-icons:file-type-wasm",
"WASM": "vscode-icons:file-type-wasm",
"toml": "vscode-icons:file-type-light-toml",
"Toml": "vscode-icons:file-type-light-toml",
"TOML": "vscode-icons:file-type-light-toml",
"yaml": "vscode-icons:file-type-light-yaml",
"Yaml": "vscode-icons:file-type-light-yaml",
"YAML": "vscode-icons:file-type-light-yaml"
},
folders: {
"default": "vscode-icons:default-folder",
"src": "vscode-icons:folder-type-src",
"srcs": "vscode-icons:folder-type-src",
"source": "vscode-icons:folder-type-src",
"sources": "vscode-icons:folder-type-src",
"code": "vscode-icons:folder-type-src",
"tauri-src": "vscode-icons:folder-type-tauri",
"dist": "vscode-icons:folder-type-dist",
"out": "vscode-icons:folder-type-dist",
"output": "vscode-icons:folder-type-dist",
"release": "vscode-icons:folder-type-dist",
"bin": "vscode-icons:folder-type-dist",
"distribution": "vscode-icons:folder-type-dist",
"docs": "vscode-icons:folder-type-docs",
"doc": "vscode-icons:folder-type-docs",
"document": "vscode-icons:folder-type-docs",
"documents": "vscode-icons:folder-type-docs",
"documentation": "vscode-icons:folder-type-docs",
"post": "vscode-icons:folder-type-docs",
"posts": "vscode-icons:folder-type-docs",
"article": "vscode-icons:folder-type-docs",
"articles": "vscode-icons:folder-type-docs",
"scripts": "vscode-icons:folder-type-script",
"script": "vscode-icons:folder-type-script",
"node_modules": "vscode-icons:folder-type-light-node",
"cli": "vscode-icons:folder-type-cli",
"template": "vscode-icons:folder-type-template",
"templates": "vscode-icons:folder-type-template",
"theme": "vscode-icons:folder-type-theme",
"themes": "vscode-icons:folder-type-theme",
"color": "vscode-icons:folder-type-theme",
"colors": "vscode-icons:folder-type-theme",
"design": "vscode-icons:folder-type-theme",
"designs": "vscode-icons:folder-type-theme",
"packages": "vscode-icons:folder-type-package",
"package": "vscode-icons:folder-type-package",
"pkg": "vscode-icons:folder-type-package",
"pkgs": "vscode-icons:folder-type-package",
"shared": "vscode-icons:folder-type-shared",
"utils": "vscode-icons:folder-type-tools",
"util": "vscode-icons:folder-type-tools",
"utility": "vscode-icons:folder-type-tools",
"utilities": "vscode-icons:folder-type-tools",
"helper": "vscode-icons:folder-type-helper",
"helpers": "vscode-icons:folder-type-helper",
"tools": "vscode-icons:folder-type-tools",
"toolkit": "vscode-icons:folder-type-tools",
"toolkits": "vscode-icons:folder-type-tools",
"tooling": "vscode-icons:folder-type-tools",
"devtools": "vscode-icons:folder-type-tools",
"component": "vscode-icons:folder-type-component",
"components": "vscode-icons:folder-type-component",
"Component": "vscode-icons:folder-type-component",
"Components": "vscode-icons:folder-type-component",
"widget": "vscode-icons:folder-type-component",
"widgets": "vscode-icons:folder-type-component",
"fragments": "vscode-icons:folder-type-component",
"hooks": "vscode-icons:folder-type-hook",
"composables": "vscode-icons:folder-type-hook",
"public": "vscode-icons:folder-type-public",
"www": "vscode-icons:folder-type-public",
"web": "vscode-icons:folder-type-public",
"wwwroot": "vscode-icons:folder-type-public",
"website": "vscode-icons:folder-type-public",
"site": "vscode-icons:folder-type-public",
"browser": "vscode-icons:folder-type-public",
"browsers": "vscode-icons:folder-type-public",
"fonts": "vscode-icons:folder-type-fonts",
"font": "vscode-icons:folder-type-fonts",
"images": "vscode-icons:folder-type-images",
"image": "vscode-icons:folder-type-images",
"imgs": "vscode-icons:folder-type-images",
"img": "vscode-icons:folder-type-images",
"icon": "vscode-icons:folder-type-images",
"icons": "vscode-icons:folder-type-images",
"ico": "vscode-icons:folder-type-images",
"icos": "vscode-icons:folder-type-images",
"figure": "vscode-icons:folder-type-images",
"figures": "vscode-icons:folder-type-images",
"fig": "vscode-icons:folder-type-images",
"figs": "vscode-icons:folder-type-images",
"screenshot": "vscode-icons:folder-type-images",
"screenshots": "vscode-icons:folder-type-images",
"screengrab": "vscode-icons:folder-type-images",
"screengrabs": "vscode-icons:folder-type-images",
"pic": "vscode-icons:folder-type-images",
"pics": "vscode-icons:folder-type-images",
"picture": "vscode-icons:folder-type-images",
"pictures": "vscode-icons:folder-type-images",
"photo": "vscode-icons:folder-type-images",
"photos": "vscode-icons:folder-type-images",
"photograph": "vscode-icons:folder-type-images",
"photographs": "vscode-icons:folder-type-images",
"asset": "vscode-icons:folder-type-asset",
"assets": "vscode-icons:folder-type-asset",
"resource": "vscode-icons:folder-type-asset",
"resources": "vscode-icons:folder-type-asset",
"res": "vscode-icons:folder-type-asset",
"static": "vscode-icons:folder-type-asset",
"report": "vscode-icons:folder-type-asset",
"reports": "vscode-icons:folder-type-asset",
"apis": "vscode-icons:folder-type-api",
"api": "vscode-icons:folder-type-api",
"restapi": "vscode-icons:folder-type-api",
"style": "vscode-icons:folder-type-style",
"styles": "vscode-icons:folder-type-style",
"stylesheet": "vscode-icons:folder-type-style",
"stylesheets": "vscode-icons:folder-type-style",
"css": "vscode-icons:folder-type-css",
"scss": "vscode-icons:folder-type-light-sass",
"sass": "vscode-icons:folder-type-light-sass",
"less": "vscode-icons:folder-type-less",
"plugin": "vscode-icons:folder-type-plugin",
"plugins": "vscode-icons:folder-type-plugin",
"typings": "vscode-icons:folder-type-typings",
"types": "vscode-icons:folder-type-typings",
"mock": "vscode-icons:folder-type-mock",
"i18n": "vscode-icons:folder-type-locale",
"locales": "vscode-icons:folder-type-locale",
"locale": "vscode-icons:folder-type-locale",
"lang": "vscode-icons:folder-type-locale",
"langs": "vscode-icons:folder-type-locale",
"language": "vscode-icons:folder-type-locale",
"languages": "vscode-icons:folder-type-locale",
"l10n": "vscode-icons:folder-type-locale",
"localization": "vscode-icons:folder-type-locale",
"translation": "vscode-icons:folder-type-locale",
"translate": "vscode-icons:folder-type-locale",
"translations": "vscode-icons:folder-type-locale",
"tx": "vscode-icons:folder-type-locale",
"config": "vscode-icons:folder-type-config",
"configs": "vscode-icons:folder-type-config",
".config": "vscode-icons:folder-type-config",
".configs": "vscode-icons:folder-type-config",
"cfg": "vscode-icons:folder-type-config",
"cfgs": "vscode-icons:folder-type-config",
"conf": "vscode-icons:folder-type-config",
"confs": "vscode-icons:folder-type-config",
"configuration": "vscode-icons:folder-type-config",
"configurations": "vscode-icons:folder-type-config",
"setting": "vscode-icons:folder-type-config",
"settings": "vscode-icons:folder-type-config",
"option": "vscode-icons:folder-type-config",
"options": "vscode-icons:folder-type-config",
"controller": "vscode-icons:folder-type-controller",
"controllers": "vscode-icons:folder-type-controller",
"Controller": "vscode-icons:folder-type-controller",
"Controllers": "vscode-icons:folder-type-controller",
"model": "vscode-icons:folder-type-model",
"models": "vscode-icons:folder-type-model",
"Model": "vscode-icons:folder-type-model",
"Models": "vscode-icons:folder-type-model",
"service": "vscode-icons:folder-type-services",
"services": "vscode-icons:folder-type-services",
"Service": "vscode-icons:folder-type-services",
"Services": "vscode-icons:folder-type-services",
"view": "vscode-icons:folder-type-view",
"views": "vscode-icons:folder-type-view",
"View": "vscode-icons:folder-type-view",
"Views": "vscode-icons:folder-type-view",
"page": "vscode-icons:folder-type-view",
"pages": "vscode-icons:folder-type-view",
"html": "vscode-icons:folder-type-view",
"app": "vscode-icons:folder-type-app",
"apps": "vscode-icons:folder-type-app",
"client": "vscode-icons:folder-type-client",
"clients": "vscode-icons:folder-type-client",
"frontend": "vscode-icons:folder-type-client",
"frontends": "vscode-icons:folder-type-client",
"server": "vscode-icons:folder-type-server",
"servers": "vscode-icons:folder-type-server",
"backend": "vscode-icons:folder-type-server",
"backends": "vscode-icons:folder-type-server",
"db": "vscode-icons:folder-type-db",
"database": "vscode-icons:folder-type-db",
"databases": "vscode-icons:folder-type-db",
"data": "vscode-icons:folder-type-db",
"sql": "vscode-icons:folder-type-db",
"e2e": "vscode-icons:folder-type-e2e",
"cypress": "vscode-icons:folder-type-light-cypress",
"test": "vscode-icons:folder-type-test",
"tests": "vscode-icons:folder-type-test",
"testing": "vscode-icons:folder-type-test",
"snapshots": "vscode-icons:folder-type-test",
"spec": "vscode-icons:folder-type-test",
"specs": "vscode-icons:folder-type-test",
"lib": "vscode-icons:folder-type-library",
"libs": "vscode-icons:folder-type-library",
"library": "vscode-icons:folder-type-library",
"libraries": "vscode-icons:folder-type-library",
"vendor": "vscode-icons:folder-type-library",
"vendors": "vscode-icons:folder-type-library",
"third-party": "vscode-icons:folder-type-library",
"lib64": "vscode-icons:folder-type-library",
"include": "vscode-icons:folder-type-include",
"inc": "vscode-icons:folder-type-include",
"includes": "vscode-icons:folder-type-include",
"partial": "vscode-icons:folder-type-include",
"partials": "vscode-icons:folder-type-include",
"inc64": "vscode-icons:folder-type-include",
"temp": "vscode-icons:folder-type-temp",
"tmp": "vscode-icons:folder-type-temp",
"cache": "vscode-icons:folder-type-temp",
"cached": "vscode-icons:folder-type-temp",
".temp": "vscode-icons:folder-type-temp",
".cache": "vscode-icons:folder-type-temp",
"log": "vscode-icons:folder-type-log",
"logs": "vscode-icons:folder-type-log",
"logging": "vscode-icons:folder-type-log",
".git": "vscode-icons:folder-type-git",
".github": "vscode-icons:folder-type-github",
".gitlab": "vscode-icons:folder-type-gitlab",
".vscode": "vscode-icons:folder-type-vscode",
".husky": "vscode-icons:folder-type-husky",
".idea": "vscode-icons:folder-type-idea"
},
files: {
"package.json": "vscode-icons:file-type-node",
"pnpm-debug.log": "vscode-icons:file-type-light-pnpm",
"pnpm-lock.yaml": "vscode-icons:file-type-light-pnpm",
"pnpm-workspace.yaml": "vscode-icons:file-type-light-pnpm",
"biome.json": "vscode-icons:file-type-biome",
"bun.lockb": "vscode-icons:file-type-bun",
"COMMIT_EDITMSG": "vscode-icons:file-type-git",
"MERGE_MSG": "vscode-icons:file-type-git",
"karma.conf.js": "vscode-icons:file-type-karma",
"karma.conf.cjs": "vscode-icons:file-type-karma",
"karma.conf.mjs": "vscode-icons:file-type-karma",
"karma.conf.coffee": "vscode-icons:file-type-karma",
"README.md": "flat-color-icons:info",
"README.txt": "flat-color-icons:info",
"README": "flat-color-icons:info",
"CHANGELOG.md": "catppuccin:changelog",
"CHANGELOG.txt": "catppuccin:changelog",
"CHANGELOG": "catppuccin:changelog",
"CHANGES.md": "catppuccin:changelog",
"CHANGES.txt": "catppuccin:changelog",
"CHANGES": "catppuccin:changelog",
"VERSION.md": "catppuccin:changelog",
"VERSION.txt": "catppuccin:changelog",
"VERSION": "catppuccin:changelog",
"mvnw": "vscode-icons:file-type-maven",
"pom.xml": "vscode-icons:file-type-maven",
"tsconfig.json": "vscode-icons:file-type-tsconfig",
"swagger.json": "vscode-icons:file-type-swagger",
"swagger.yml": "vscode-icons:file-type-swagger",
"swagger.yaml": "vscode-icons:file-type-swagger",
"mime.types": "vscode-icons:file-type-light-config",
"Jenkinsfile": "vscode-icons:file-type-jenkins",
"babel.config.js": "vscode-icons:file-type-babel2",
"babel.config.json": "vscode-icons:file-type-babel2",
"babel.config.cjs": "vscode-icons:file-type-babel2",
"BUILD": "vscode-icons:file-type-bazel",
"BUILD.bazel": "vscode-icons:file-type-bazel",
"WORKSPACE": "vscode-icons:file-type-bazel",
"WORKSPACE.bazel": "vscode-icons:file-type-bazel",
"bower.json": "vscode-icons:file-type-bower2",
"Bower.json": "vscode-icons:file-type-bower2",
"eslint.config.js": "vscode-icons:file-type-eslint",
"eslint.config.ts": "vscode-icons:file-type-eslint",
"firebase.json": "vscode-icons:file-type-firebase",
"geckodriver": "openmoji:firefox",
"Gruntfile.js": "vscode-icons:file-type-grunt",
"gruntfile.babel.js": "vscode-icons:file-type-grunt",
"Gruntfile.babel.js": "vscode-icons:file-type-grunt",
"gruntfile.js": "vscode-icons:file-type-grunt",
"Gruntfile.coffee": "vscode-icons:file-type-grunt",
"gruntfile.coffee": "vscode-icons:file-type-grunt",
"ionic.config.json": "vscode-icons:file-type-ionic",
"Ionic.config.json": "vscode-icons:file-type-ionic",
"ionic.project": "vscode-icons:file-type-ionic",
"Ionic.project": "vscode-icons:file-type-ionic",
"platformio.ini": "vscode-icons:file-type-platformio",
"rollup.config.js": "vscode-icons:file-type-rollup",
"sass-lint.yml": "vscode-icons:file-type-sass",
"stylelint.config.js": "vscode-icons:file-type-light-stylelint",
"stylelint.config.cjs": "vscode-icons:file-type-light-stylelint",
"stylelint.config.mjs": "vscode-icons:file-type-light-stylelint",
"yarn.clean": "vscode-icons:file-type-yarn",
"yarn.lock": "vscode-icons:file-type-yarn",
"webpack.config.js": "vscode-icons:file-type-webpack",
"webpack.config.cjs": "vscode-icons:file-type-webpack",
"webpack.config.mjs": "vscode-icons:file-type-webpack",
"webpack.config.ts": "vscode-icons:file-type-webpack",
"webpack.config.build.js": "vscode-icons:file-type-webpack",
"webpack.config.build.cjs": "vscode-icons:file-type-webpack",
"webpack.config.build.mjs": "vscode-icons:file-type-webpack",
"webpack.config.build.ts": "vscode-icons:file-type-webpack",
"webpack.common.js": "vscode-icons:file-type-webpack",
"webpack.common.cjs": "vscode-icons:file-type-webpack",
"webpack.common.mjs": "vscode-icons:file-type-webpack",
"webpack.common.ts": "vscode-icons:file-type-webpack",
"webpack.dev.js": "vscode-icons:file-type-webpack",
"webpack.dev.cjs": "vscode-icons:file-type-webpack",
"webpack.dev.mjs": "vscode-icons:file-type-webpack",
"webpack.dev.ts": "vscode-icons:file-type-webpack",
"webpack.prod.js": "vscode-icons:file-type-webpack",
"webpack.prod.cjs": "vscode-icons:file-type-webpack",
"webpack.prod.mjs": "vscode-icons:file-type-webpack",
"webpack.prod.ts": "vscode-icons:file-type-webpack",
"vite.config.js": "vscode-icons:file-type-vite",
"vite.config.ts": "vscode-icons:file-type-vite",
"vite.config.mjs": "vscode-icons:file-type-vite",
"vite.config.cjs": "vscode-icons:file-type-vite",
"vitest.config.ts": "vscode-icons:file-type-vitest",
"vitest.config.js": "vscode-icons:file-type-vitest",
"vitest.config.mjs": "vscode-icons:file-type-vitest",
"vitest.config.cjs": "vscode-icons:file-type-vitest",
"turbo.json": "vscode-icons:file-type-light-turbo",
"vercel.json": "vscode-icons:file-type-light-vercel",
"netlify.toml": "vscode-icons:file-type-light-netlify",
"Cargo.toml": "vscode-icons:file-type-cargo",
"Cargo.lock": "vscode-icons:file-type-cargo",
"npm-debug.log": "vscode-icons:file-type-npm"
},
extensions: {
".astro": "vscode-icons:file-type-light-astro",
".mdx": "vscode-icons:file-type-light-mdx",
".cls": "vscode-icons:file-type-apex",
".apex": "vscode-icons:file-type-apex",
".asm": "vscode-icons:file-type-assembly",
".s": "vscode-icons:file-type-assembly",
".bicep": "vscode-icons:file-type-bicep",
".bzl": "vscode-icons:file-type-bazel",
".bazel": "vscode-icons:file-type-bazel",
".BUILD": "vscode-icons:file-type-bazel",
".WORKSPACE": "vscode-icons:file-type-bazel",
".bazelignore": "vscode-icons:file-type-bazel",
".bazelversion": "vscode-icons:file-type-bazel",
".c": "vscode-icons:file-type-c",
".h": "vscode-icons:file-type-c",
".m": "vscode-icons:file-type-c",
".cs": "vscode-icons:file-type-csharp",
".cshtml": "vscode-icons:file-type-html",
".aspx": "vscode-icons:file-type-aspx",
".ascx": "vscode-icons:file-type-aspx",
".asax": "vvscode-icons:file-type-aspx",
".master": "vscode-icons:file-type-html",
".cc": "vscode-icons:file-type-cpp",
".cpp": "vscode-icons:file-type-cpp",
".cxx": "vscode-icons:file-type-cpp",
".c++": "vscode-icons:file-type-cpp",
".hh": "vscode-icons:file-type-cppheader",
".hpp": "vscode-icons:file-type-cppheader",
".hxx": "vscode-icons:file-type-cppheader",
".h++": "vscode-icons:file-type-cppheader",
".mm": "vscode-icons:file-type-cpp",
".clj": "vscode-icons:file-type-clojure",
".cljs": "vscode-icons:file-type-clojure",
".cljc": "vscode-icons:file-type-clojure",
".edn": "vscode-icons:file-type-clojure",
".cfc": "vscode-icons:file-type-cfc",
".cfm": "vscode-icons:file-type-cfm",
".coffee": "vscode-icons:file-type-coffeescript",
".litcoffee": "vscode-icons:file-type-coffeescript",
".config": "vscode-icons:file-type-config",
".cfg": "vscode-icons:file-type-config",
".conf": "vscode-icons:file-type-config",
".cr": "vscode-icons:file-type-light-crystal",
".ecr": "vscode-icons:file-type-light-crystal",
".slang": "vscode-icons:file-type-slang",
".cson": "vscode-icons:file-type-json",
".css": "vscode-icons:file-type-css",
".css.map": "vscode-icons:file-type-cssmap",
".sss": "vscode-icons:file-type-sss",
".csv": "vscode-icons:file-type-excel",
".xls": "vscode-icons:file-type-excel2",
".xlsx": "vscode-icons:file-type-excel2",
".cu": "vscode-icons:file-type-cuda",
".cuh": "vscode-icons:file-type-cuda",
".hu": "vscode-icons:file-type-cuda",
".cake": "vscode-icons:file-type-cake",
".ctp": "vscode-icons:file-type-cakephp",
".d": "vscode-icons:file-type-dependencies",
".doc": "vscode-icons:file-type-word2",
".docx": "vscode-icons:file-type-word2",
".ejs": "vscode-icons:file-type-ejs",
".ex": "vscode-icons:file-type-elixir",
".exs": "vscode-icons:file-type-elixir",
".elm": "vscode-icons:file-type-elm",
".ico": "vscode-icons:file-type-favicon",
".fs": "vscode-icons:file-type-fsharp",
".fsx": "vscode-icons:file-type-fsharp",
".gitignore": "vscode-icons:file-type-git",
".gitconfig": "vscode-icons:file-type-git",
".gitkeep": "vscode-icons:file-type-git",
".gitattributes": "vscode-icons:file-type-git",
".gitmodules": "vscode-icons:file-type-git",
".go": "vscode-icons:file-type-go",
".slide": "vscode-icons:file-type-go",
".article": "vscode-icons:file-type-go",
".gd": "vscode-icons:file-type-godot",
".godot": "vscode-icons:file-type-godot",
".tres": "vscode-icons:file-type-godot",
".tscn": "vscode-icons:file-type-godot",
".gradle": "vscode-icons:file-type-light-gradle",
".groovy": "vscode-icons:file-type-groovy",
".gsp": "vscode-icons:file-type-groovy",
".gql": "vscode-icons:file-type-graphql",
".graphql": "vscode-icons:file-type-graphql",
".graphqls": "vscode-icons:file-type-graphql",
".hack": "logos:hack",
".haml": "vscode-icons:file-type-haml",
".handlebars": "vscode-icons:file-type-handlebars",
".hbs": "vscode-icons:file-type-handlebars",
".hjs": "vscode-icons:file-type-handlebars",
".hs": "vscode-icons:file-type-haskell",
".lhs": "vscode-icons:file-type-haskell",
".hx": "vscode-icons:file-type-haxe",
".hxs": "vscode-icons:file-type-haxe",
".hxp": "vscode-icons:file-type-haxe",
".hxml": "vscode-icons:file-type-haxe",
".html": "vscode-icons:file-type-html",
".jade": "file-icons:jade",
".java": "vscode-icons:file-type-java",
".class": "vscode-icons:file-type-java",
".classpath": "vscode-icons:file-type-java",
".properties": "vscode-icons:file-type-java",
".js": "vscode-icons:file-type-js",
".js.map": "vscode-icons:file-type-jsmap",
".cjs": "vscode-icons:file-type-js",
".cjs.map": "vscode-icons:file-type-jsmap",
".mjs": "vscode-icons:file-type-js",
".mjs.map": "vscode-icons:file-type-jsmap",
".spec.js": "vscode-icons:file-type-light-testjs",
".spec.cjs": "vscode-icons:file-type-light-testjs",
".spec.mjs": "vscode-icons:file-type-light-testjs",
".test.js": "vscode-icons:file-type-light-testjs",
".test.cjs": "vscode-icons:file-type-light-testjs",
".test.mjs": "vscode-icons:file-type-light-testjs",
".es": "vscode-icons:file-type-js",
".es5": "vscode-icons:file-type-js",
".es6": "vscode-icons:file-type-js",
".es7": "vscode-icons:file-type-js",
".jinja": "vscode-icons:file-type-jinja",
".jinja2": "vscode-icons:file-type-jinja",
".json": "vscode-icons:file-type-json",
".jl": "vscode-icons:file-type-julia",
".kt": "vscode-icons:file-type-kotlin",
".kts": "vscode-icons:file-type-kotlin",
".dart": "vscode-icons:file-type-dartlang",
".less": "vscode-icons:file-type-less",
".liquid": "vscode-icons:file-type-liquid",
".ls": "vscode-icons:file-type-livescript",
".lua": "vscode-icons:file-type-lua",
".markdown": "vscode-icons:file-type-markdown",
".md": "vscode-icons:file-type-markdown",
".mustache": "vscode-icons:file-type-light-mustache",
".stache": "vscode-icons:file-type-light-mustache",
".nim": "vscode-icons:file-type-light-nim",
".nims": "vscode-icons:file-type-light-nim",
".github-issues": "mdi:github",
".ipynb": "vscode-icons:file-type-jupyter",
".njk": "vscode-icons:file-type-nunjucks",
".nunjucks": "vscode-icons:file-type-nunjucks",
".nunjs": "vscode-icons:file-type-nunjucks",
".nunj": "vscode-icons:file-type-nunjucks",
".njs": "vscode-icons:file-type-nunjucks",
".nj": "vscode-icons:file-type-nunjucks",
".npm-debug.log": "vscode-icons:file-type-npm",
".npmignore": "catppuccin:npm-ignore",
".npmrc": "vscode-icons:file-type-npm",
".ml": "vscode-icons:file-type-ocaml",
".mli": "vscode-icons:file-type-ocaml",
".cmx": "vscode-icons:file-type-ocaml",
".cmxa": "vscode-icons:file-type-ocaml",
".pl": "vscode-icons:file-type-perl",
".php": "vscode-icons:file-type-php",
".php.inc": "vscode-icons:file-type-php",
".pipeline": "vscode-icons:file-type-pipeline",
".pddl": "vscode-icons:file-type-pddl",
".plan": "vscode-icons:file-type-pddl-plan",
".happenings": "vscode-icons:file-type-pddl-happenings",
".ps1": "vscode-icons:file-type-powershell",
".psd1": "vscode-icons:file-type-powershell",
".psm1": "vscode-icons:file-type-powershell",
".prisma": "vscode-icons:file-type-light-prisma",
".pug": "vscode-icons:file-type-pug",
".pp": "vscode-icons:file-type-puppet",
".epp": "vscode-icons:file-type-puppet",
".purs": "vscode-icons:file-type-light-purescript",
".py": "vscode-icons:file-type-python",
".jsx": "vscode-icons:file-type-reactjs",
".spec.jsx": "vscode-icons:file-type-reactjs",
".test.jsx": "vscode-icons:file-type-reactjs",
".cjsx": "vscode-icons:file-type-reactjs",
".tsx": "vscode-icons:file-type-reactts",
".spec.tsx": "vscode-icons:file-type-reactts",
".test.tsx": "vscode-icons:file-type-reactts",
".res": "vscode-icons:file-type-rescript",
".resi": "vscode-icons:file-type-rescript",
".R": "vscode-icons:file-type-r",
".rmd": "vscode-icons:file-type-rmd",
".rb": "vscode-icons:file-type-ruby",
".erb": "vscode-icons:file-type-html",
".erb.html": "vscode-icons:file-type-html",
".html.erb": "vscode-icons:file-type-html",
".rs": "vscode-icons:file-type-rust",
".sass": "vscode-icons:file-type-sass",
".scss": "vscode-icons:file-type-sass",
".springBeans": "seti:spring",
".slim": "vscode-icons:file-type-slim",
".smarty.tpl": "vscode-icons:file-type-smarty",
".tpl": "vscode-icons:file-type-smarty",
".sbt": "vscode-icons:file-type-sbt",
".scala": "vscode-icons:file-type-scala",
".sol": "logos:ethereum-color",
".styl": "vscode-icons:file-type-light-stylus",
".svelte": "vscode-icons:file-type-svelte",
".swift": "vscode-icons:file-type-swift",
".sql": "vscode-icons:file-type-sql",
".soql": "vscode-icons:file-type-sql",
".tf": "vscode-icons:file-type-terraform",
".tf.json": "vscode-icons:file-type-terraform",
".tfvars": "vscode-icons:file-type-terraform",
".tfvars.json": "vscode-icons:file-type-terraform",
".tex": "vscode-icons:file-type-light-tex",
".sty": "vscode-icons:file-type-light-tex",
".dtx": "vscode-icons:file-type-light-tex",
".ins": "vscode-icons:file-type-light-tex",
".txt": "vscode-icons:file-type-text",
".toml": "vscode-icons:file-type-light-toml",
".twig": "vscode-icons:file-type-twig",
".ts": "vscode-icons:file-type-typescript",
".spec.ts": "vscode-icons:file-type-testts",
".test.ts": "vscode-icons:file-type-testts",
".vala": "vscode-icons:file-type-vala",
".vapi": "vscode-icons:file-type-vala",
".component": "vscode-icons:file-type-html",
".vue": "vscode-icons:file-type-vue",
".wasm": "vscode-icons:file-type-wasm",
".wat": "vscode-icons:file-type-wasm",
".xml": "vscode-icons:file-type-xml",
".yml": "vscode-icons:file-type-light-yaml",
".yaml": "vscode-icons:file-type-light-yaml",
".pro": "vscode-icons:file-type-prolog",
".zig": "vscode-icons:file-type-zig",
".jar": "vscode-icons:file-type-jar",
".zip": "vscode-icons:file-type-zip",
".ai": "vscode-icons:file-type-ai",
".psd": "vscode-icons:file-type-photoshop",
".pdf": "vscode-icons:file-type-pdf2",
".eot": "vscode-icons:file-type-light-font",
".ttf": "vscode-icons:file-type-light-font",
".woff": "vscode-icons:file-type-light-font",
".woff2": "vscode-icons:file-type-light-font",
".otf": "vscode-icons:file-type-light-font",
".avif": "vscode-icons:file-type-avif",
".gif": "vscode-icons:file-type-image",
".jpg": "vscode-icons:file-type-image",
".jpeg": "vscode-icons:file-type-image",
".png": "vscode-icons:file-type-image",
".pxm": "vscode-icons:file-type-image",
".svg": "vscode-icons:file-type-svg",
".svgx": "vscode-icons:file-type-image",
".tiff": "vscode-icons:file-type-image",
".webp": "vscode-icons:file-type-image",
".sublime-project": "vscode-icons:file-type-sublime",
".sublime-workspace": "vscode-icons:file-type-sublime",
".code-search": "vscode-icons:file-type-search-result",
".sh": "vscode-icons:file-type-shell",
".zsh": "vscode-icons:file-type-shell",
".fish": "vscode-icons:file-type-shell",
".zshrc": "vscode-icons:file-type-shell",
".bashrc": "vscode-icons:file-type-shell",
".mov": "vscode-icons:file-type-video",
".ogv": "vscode-icons:file-type-video",
".webm": "vscode-icons:file-type-video",
".avi": "vscode-icons:file-type-video",
".mpg": "vscode-icons:file-type-video",
".mp4": "vscode-icons:file-type-video",
".mp3": "vscode-icons:file-type-audio",
".ogg": "vscode-icons:file-type-audio",
".wav": "vscode-icons:file-type-audio",
".flac": "vscode-icons:file-type-audio",
".bat": "vscode-icons:file-type-bat",
".cmd": "vscode-icons:file-type-shell",
".babelrc": "vscode-icons:file-type-light-babel",
".babelrc.js": "vscode-icons:file-type-light-babel",
".babelrc.cjs": "vscode-icons:file-type-light-babel",
".bazelrc": "vscode-icons:file-type-bazel",
".bowerrc": "vscode-icons:file-type-bower2",
".codeclimate.yml": "vscode-icons:file-type-codeclimate",
".eslintrc": "vscode-icons:file-type-eslint",
".eslintrc.js": "vscode-icons:file-type-eslint",
".eslintrc.cjs": "vscode-icons:file-type-eslint",
".eslintrc.yaml": "vscode-icons:file-type-eslint",
".eslintrc.yml": "vscode-icons:file-type-eslint",
".eslintrc.json": "vscode-icons:file-type-eslint",
".eslintignore": "vscode-icons:file-type-eslint",
".firebaserc": "vscode-icons:file-type-firebase",
".gitlab-ci.yml": "vscode-icons:file-type-gitlab",
".jshintrc": "vscode-icons:file-type-jshint",
".jscsrc": "vscode-icons:file-type-js",
".stylelintrc": "vscode-icons:file-type-light-stylelint",
".stylelintrc.json": "vscode-icons:file-type-light-stylelint",
".stylelintrc.yaml": "vscode-icons:file-type-light-stylelint",
".stylelintrc.yml": "vscode-icons:file-type-light-stylelint",
".stylelintrc.js": "vscode-icons:file-type-light-stylelint",
".stylelintignore": "vscode-icons:file-type-light-stylelint",
".direnv": "vscode-icons:file-type-dotenv",
".env": "vscode-icons:file-type-dotenv",
".static": "vscode-icons:file-type-config",
".editorconfig": "vscode-icons:file-type-editorconfig",
".slugignore": "vscode-icons:file-type-config",
".tmp": "ph:clock-bold",
".htaccess": "vscode-icons:file-type-config",
".key": "vscode-icons:file-type-key",
".cert": "vscode-icons:file-type-cert",
".cer": "vscode-icons:file-type-cert",
".crt": "vscode-icons:file-type-cert",
".pem": "vscode-icons:file-type-cert",
".DS_Store": "octicon:diff-ignored-16"
},
partials: {
"Gemfile": "vscode-icons:file-type-ruby",
"gemfile": "vscode-icons:file-type-ruby",
"dockerfile": "vscode-icons:file-type-docker",
"Dockerfile": "vscode-icons:file-type-docker",
"DOCKERFILE": "vscode-icons:file-type-docker",
".dockerignore": "vscode-icons:file-type-docker",
"docker-healthcheck": "vscode-icons:file-type-docker",
"docker-compose.yml": "vscode-icons:file-type-docker",
"docker-compose.yaml": "vscode-icons:file-type-docker",
"docker-compose.override.yml": "vscode-icons:file-type-docker",
"docker-compose.override.yaml": "vscode-icons:file-type-docker",
"GULPFILE": "vscode-icons:file-type-gulp",
"Gulpfile": "vscode-icons:file-type-gulp",
"gulpfile": "vscode-icons:file-type-gulp",
"gulpfile.js": "vscode-icons:file-type-gulp",
"LICENSE": "vscode-icons:file-type-license",
"LICENCE": "vscode-icons:file-type-license",
"LICENSE.txt": "vscode-icons:file-type-license",
"LICENCE.txt": "vscode-icons:file-type-license",
"LICENSE.md": "vscode-icons:file-type-license",
"LICENCE.md": "vscode-icons:file-type-license",
"COPYING": "vscode-icons:file-type-license",
"COPYING.txt": "vscode-icons:file-type-license",
"COPYING.md": "vscode-icons:file-type-license",
"COMPILING": "vscode-icons:file-type-license",
"COMPILING.txt": "vscode-icons:file-type-license",
"COMPILING.md": "vscode-icons:file-type-license",
"CONTRIBUTING": "vscode-icons:file-type-license",
"CONTRIBUTING.txt": "vscode-icons:file-type-license",
"CONTRIBUTING.md": "vscode-icons:file-type-license",
"MAKEFILE": "vscode-icons:file-type-makefile",
"Makefile": "vscode-icons:file-type-makefile",
"makefile": "vscode-icons:file-type-makefile",
"QMAKEFILE": "vscode-icons:file-type-makefile",
"QMakefile": "vscode-icons:file-type-makefile",
"qmakefile": "vscode-icons:file-type-makefile",
"OMAKEFILE": "vscode-icons:file-type-makefile",
"OMakefile": "vscode-icons:file-type-makefile",
"omakefile": "vscode-icons:file-type-makefile",
"CMAKELISTS.TXT": "vscode-icons:file-type-makefile",
"CMAKELISTS.txt": "vscode-icons:file-type-makefile",
"CMakeLists.txt": "vscode-icons:file-type-makefile",
"cmakelists.txt": "vscode-icons:file-type-makefile",
"Procfile": "vscode-icons:file-type-procfile",
"TODO": "vscode-icons:file-type-light-todo",
"TODO.txt": "vscode-icons:file-type-light-todo",
"TODO.md": "vscode-icons:file-type-light-todo"
}
};
//#endregion
//#region src/node/fileIcons/findIcon.ts
function getFileIcon(fileName, type) {
const name = getFileIconName(fileName, type);
if (!name) return type !== "folder" ? defaultFile : defaultFolder;
return name;
}
function getFileIconName(fileName, type = "file") {
if (type === "folder") {
const icon$1 = definitions.folders[fileName];
if (icon$1) return icon$1;
if (fileName.includes("/")) return definitions.folders[fileName.slice(fileName.lastIndexOf("/") + 1)];
return;
}
let icon = definitions.named[fileName] || definitions.files[fileName];
if (icon) return icon;
icon = getFileIconTypeFromExtension(fileName) || void 0;
if (icon) return icon;
for (const [partial, partialIcon] of Object.entries(definitions.partials)) if (fileName.includes(partial)) return partialIcon;
return icon;
}
function getFileIconTypeFromExtension(fileName) {
const firstDotIndex = fileName.indexOf(".");
if (firstDotIndex === -1) return;
let extension = fileName.slice(firstDotIndex);
while (extension !== "") {
const icon = definitions.extensions[extension];
if (icon) return icon;
const nextDotIndex = extension.indexOf(".", 1);
if (nextDotIndex === -1) return;
extension = extension.slice(nextDotIndex);
}
}
//#endregion
//#region src/node/utils/cleanMarkdownEnv.ts
const WHITE_LIST = [
"base",
"filePath",
"filePathRelative",
"references",
"abbreviations",
"annotations"
];
function cleanMarkdownEnv(env, excludes = []) {
const result = {};
for (const key of WHITE_LIST) {
if (excludes.includes(key)) continue;
result[key] = env[key];
}
return result;
}
//#endregion
//#region src/node/utils/stringifyProp.ts
function stringifyProp(data) {
return JSON.stringify(data).replace(/'/g, "&#39");
}
//#endregion
//#region src/node/container/codeTabs.ts
function createCodeTabIconGetter(options = {}) {
const noop = () => void 0;
if (options.icon === false) return noop;
const { named, extensions } = isPlainObject(options.icon) ? options.icon : {};
return function getIcon(filename) {
if (named === false && definitions.named[filename]) return void 0;
if (extensions === false && getFileIconTypeFromExtension(filename)) return;
const hasNamed = named && named.length;
const hasExt = extensions && extensions.length;
if (hasNamed || hasExt) {
if (hasNamed && named.includes(filename)) return definitions.named[filename];
if (hasExt && extensions.some((ext) => filename.endsWith(ext))) return getFileIconTypeFromExtension(filename);
return;
}
return getFileIconName(filename);
};
}
const codeTabs = (md, options = {}) => {
const getIcon = createCodeTabIconGetter(options);
tab(md, {
name: "code-tabs",
openRender: ({ active, data }, tokens, index, _, env) => {
const { meta } = tokens[index];
const titles = data.map(({ title }) => md.renderInline(title, cleanMarkdownEnv(env)));
const tabsData = data.map((item, dataIndex) => {
const { id = titles[dataIndex] } = item;
return { id };
});
const titlesContent = titles.map((title, index$1) => {
const icon = getIcon(title);
return `<template #title${index$1}="{ value, isActive }">${icon ? `<VPIcon provider="iconify" name="${icon}"/>` : ""}<span>${title}</span></template>`;
}).join("");
return `<CodeTabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>${titlesContent}`;
},
closeRender: () => `</CodeTabs>`,
tabOpenRender: ({ index }, tokens, tokenIndex) => {
let foundFence = false;
for (let i = tokenIndex; i < tokens.length; i++) {
const { type } = tokens[i];
if (type === "code-tabs_tab_close") break;
if ((type === "fence" || type === "import_code") && !foundFence) {
foundFence = true;
continue;
}
tokens[i].type = "code_tab_empty";
tokens[i].hidden = true;
}
return `<template #tab${index}="{ value, isActive }">`;
},
tabCloseRender: () => `</template>`
});
};
//#endregion
//#region src/node/utils/resolveAttrs.ts
const RE_ATTR_VALUE = /(?:^|\s+)(?<attr>[\w-]+)(?:=(?<quote>['"])(?<valueWithQuote>.+?)\k<quote>|=(?<valueWithoutQuote>\S+))?(?:\s+|$)/;
function resolveAttrs(info) {
info = info.trim();
if (!info) return {
rawAttrs: "",
attrs: {}
};
const attrs$1 = {};
const rawAttrs = info;
let matched;
while (matched = info.match(RE_ATTR_VALUE)) {
const { attr, valueWithQuote, valueWithoutQuote } = matched.groups;
const value = valueWithQuote || valueWithoutQuote || true;
let v = typeof value === "string" ? value.trim() : value;
if (v === "true") v = true;
else if (v === "false") v = false;
else if (v === "\"\"" || v === "''") v = "";
attrs$1[camelCase(attr)] = v;
info = info.slice(matched[0].length);
}
return {
attrs: attrs$1,
rawAttrs
};
}
function resolveAttr(info, key) {
const pattern = /* @__PURE__ */ new RegExp(`(?:^|\\s+)${key}(?:=(?<quote>['"])(?<valueWithQuote>.+?)\\k<quote>|=(?<valueWithoutQuote>\\S+))?(?:\\s+|$)`);
const groups = info.match(pattern)?.groups;
return groups?.valueWithQuote || groups?.valueWithoutQuote;
}
//#endregion
//#region src/node/enhance/imageSize.ts
const REG_IMG = /!\[.*?\]\(.*?\)/g;
const REG_IMG_TAG = /<img(.*?)>/g;
const REG_IMG_TAG_SRC = /src(?:set)?=(['"])(.+?)\1/g;
const BADGE_LIST = [
"https://img.shields.io",
"https://badge.fury.io",
"https://badgen.net",
"https://forthebadge.com",
"https://vercel.com/button"
];
const cache$1 = /* @__PURE__ */ new Map();
async function imageSizePlugin(app, md, type = false) {
if (!app.env.isBuild || !type) return;
if (type === "all") {
const start = performance.now();
try {
await scanRemoteImageSize(app);
} catch {}
if (app.env.isDebug) logger.info(`[vuepress-plugin-md-power] imageSizePlugin: scan all images time spent: ${performance.now() - start}ms`);
}
const imageRule = md.renderer.rules.image;
md.renderer.rules.image = (tokens, idx, options, env, self) => {
if (!env.filePathRelative || !env.filePath) return imageRule(tokens, idx, options, env, self);
const token = tokens[idx];
const src = token.attrGet("src");
const width = token.attrGet("width");
const height = token.attrGet("height");
const size = resolveSize(src, width, height, env);
if (size) {
token.attrSet("width", `${size.width}`);
token.attrSet("height", `${size.height}`);
}
return imageRule(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);
function createHtmlRule(rawHtmlRule) {
return (tokens, idx, options, env, self) => {
const token = tokens[idx];
token.content = token.content.replace(REG_IMG_TAG, (raw, info) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const src = attrs$1.src || attrs$1.srcset;
const size = resolveSize(src, attrs$1.width, attrs$1.height, env);
if (!size) return raw;
attrs$1.width = size.width;
attrs$1.height = size.height;
return `<img ${Object.entries(attrs$1).map(([key, value]) => typeof value === "boolean" ? key : `${key}="${value}"`).join(" ")}>`;
});
return rawHtmlRule(tokens, idx, options, env, self);
};
}
function resolveSize(src, width, height, env) {
if (!src || src.startsWith("data:")) return false;
if (width && height) return false;
const isExternal = isLinkExternal(src, env.base);
const filepath$1 = isExternal ? src : resolveImageUrl(src, env, app);
if (isExternal) {
if (!cache$1.has(filepath$1)) return false;
} else if (!cache$1.has(filepath$1)) {
if (!fs.existsSync(filepath$1)) return false;
try {
const { width: w, height: h } = imageSize(fs.readFileSync(filepath$1));
if (!w || !h) return false;
cache$1.set(filepath$1, {
width: w,
height: h
});
} catch {
return false;
}
}
const { width: originalWidth, height: originalHeight } = cache$1.get(filepath$1);
const ratio = originalWidth / originalHeight;
if (width && !height) {
const w = Number.parseInt(width, 10);
return {
width: w,
height: Math.round(w / ratio)
};
} else if (height && !width) {
const h = Number.parseInt(height, 10);
return {
width: Math.round(h * ratio),
height: h
};
} else return {
width: originalWidth,
height: originalHeight
};
}
}
function resolveImageUrl(src, env, app) {
if (src[0] === "/") return app.dir.public(src.slice(1));
if (env.filePathRelative && src[0] === ".") return app.dir.source(path.join(path.dirname(env.filePathRelative), src));
if (env.filePath && (src[0] === "." || src[0] === "/")) return path.resolve(env.filePath, src);
return path.resolve(src);
}
async function scanRemoteImageSize(app) {
if (!app.env.isBuild) return;
const cwd = app.dir.source();
const files = await fs.readdir(cwd, { recursive: true });
const imgList = [];
for (const file of files) {
const filepath$1 = path.join(cwd, file);
if ((await fs.stat(filepath$1)).isFile() && !filepath$1.includes(".vuepress") && !filepath$1.includes("node_modules") && filepath$1.endsWith(".md")) {
const content = await fs.readFile(filepath$1, "utf-8");
const syntaxMatched = content.match(REG_IMG) ?? [];
for (const img of syntaxMatched) {
const src = img.slice(img.indexOf("](") + 2, -1);
addList(src.split(/\s+/)[0]);
}
const tagMatched = content.match(REG_IMG_TAG) ?? [];
for (const img of tagMatched) {
const src = img.match(REG_IMG_TAG_SRC)?.[2] ?? "";
addList(src);
}
}
}
function addList(src) {
if (src && isLinkHttp(src) && !imgList.includes(src) && !BADGE_LIST.some((badge) => src.startsWith(badge))) imgList.push(src);
}
await Promise.all(imgList.map(async (src) => {
if (!cache$1.has(src)) {
const { width, height } = await fetchImageSize(src);
if (width && height) cache$1.set(src, {
width,
height
});
}
}));
}
function fetchImageSize(src) {
const link = new URL(src);
const promise = new Promise((resolve) => {
http.get(link, async (stream) => {
const chunks = [];
for await (const chunk of stream) {
chunks.push(chunk);
try {
const { width, height } = imageSize(Buffer.concat(chunks));
if (width && height) return resolve({
width,
height
});
} catch {}
}
try {
const { width, height } = imageSize(Buffer.concat(chunks));
resolve({
width,
height
});
} catch {
resolve({
width: 0,
height: 0
});
}
}).on("error", () => resolve({
width: 0,
height: 0
}));
});
try {
return withTimeout(() => promise, 3e3);
} catch {
return Promise.resolve({
width: 0,
height: 0
});
}
}
async function resolveImageSize(app, url, remote = false) {
if (cache$1.has(url)) return cache$1.get(url);
if (isLinkHttp(url) && remote) return await fetchImageSize(url);
if (url[0] === "/") {
const filepath$1 = app.dir.public(url.slice(1));
if (fs.existsSync(filepath$1)) try {
const { width, height } = imageSize(fs.readFileSync(filepath$1));
return {
width,
height
};
} catch {}
}
return {
width: 0,
height: 0
};
}
//#endregion
//#region src/node/demo/supports/file.ts
const require = createRequire(process.cwd());
function findFile(app, env, url) {
if (url.startsWith("/")) return app.dir.source(url.slice(1));
if (url.startsWith("./") || url.startsWith("../")) return app.dir.source(path$1.dirname(env.filePathRelative), url);
if (url.startsWith("@source/")) return app.dir.source(url.slice(8));
try {
return require.resolve(url);
} catch {
return url;
}
}
function readFileSync(filepath$1) {
try {
return fs$1.readFileSync(filepath$1, "utf-8");
} catch {
return false;
}
}
function writeFileSync(filepath$1, content) {
const dirname = path$1.dirname(filepath$1);
fs$1.mkdirSync(dirname, { recursive: true });
fs$1.writeFileSync(filepath$1, content, "utf-8");
}
//#endregion
//#region src/node/embed/createEmbedRuleBlock.ts
function createEmbedRuleBlock(md, { type, name = type, syntaxPattern, beforeName = "import_code", ruleOptions = { alt: [
"paragraph",
"reference",
"blockquote",
"list"
] }, meta, content }) {
const MIN_LENGTH = type.length + 5;
const START_CODES = [
64,
91,
...type.split("").map((c) => c.charCodeAt(0))
];
md.block.ruler.before(beforeName, name, (state, startLine, endLine, silent) => {
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 content$1 = state.src.slice(pos, max);
const match = content$1.match(syntaxPattern);
if (!match) return false;
/* istanbul ignore if -- @preserve */
if (silent) return true;
const token = state.push(name, "", 0);
token.meta = meta(match);
token.content = content$1;
token.map = [startLine, startLine + 1];
state.line = startLine + 1;
return true;
}, ruleOptions);
md.renderer.rules[name] = (tokens, index, _, env) => {
const token = tokens[index];
token.content = content(token.meta, token.content, env);
return token.content;
};
}
//#endregion
//#region src/node/utils/parseRect.ts
function parseRect(str, unit = "px") {
if (Number.parseFloat(str) === Number(str)) return `${str}${unit}`;
return str;
}
//#endregion
//#region src/node/utils/stringifyAttrs.ts
function stringifyAttrs(attrs$1, withUndefinedOrNull = false, forceStringify = []) {
const result = Object.entries(attrs$1).map(([key, value]) => {
const k = kebabCase(key);
if (isUndefined(value) || value === "undefined") return withUndefinedOrNull ? `:${k}="undefined"` : "";
if (isNull(value) || value === "null") return withUndefinedOrNull ? `:${k}="null"` : "";
if (value === "true") value = true;
if (value === "false") value = false;
if (isBoolean(value)) return value ? `${k}` : "";
if (isNumber(value)) return `:${k}="${value}"`;
if (isString(value) && (value[0] === "{" || value[0] === "[")) {
const v = value.replaceAll("\"", "'");
if (forceStringify.includes(key)) return `${k}="${v}"`;
return `:${k}="${v}"`;
}
return `${key[0] === ":" ? ":" : ""}${k}="${String(value)}"`;
}).filter(Boolean).join(" ");
return result ? ` ${result}` : "";
}
//#endregion
//#region src/node/container/createContainer.ts
/**
* 创建 markdown-it 的自定义容器插件。
*
* @param md markdown-it 实例
* @param type 容器类型(如 'tip', 'warning' 等)
* @param options 可选的 before/after 渲染钩子
* @param options.before 渲染容器起始标签时的回调函数
* @param options.after 渲染容器结束标签时的回调函数
*/
function createContainerPlugin(md, type, { before, after } = {}) {
const render = (tokens, index, options, env) => {
const token = tokens[index];
const info = token.info.trim().slice(type.length).trim() || "";
if (token.nesting === 1) return before?.(info, tokens, index, options, env) ?? `<div class="custom-container ${type}">`;
else return after?.(info, tokens, index, options, env) ?? "</div>";
};
md.use(container, type, { render });
}
/**
* 创建一个自定义的容器规则,内容不会交给 markdown-it 处理。
* 需要自定义 content 的处理逻辑
* ```md
* ::: type
* xxxx <-- content: 这部分的内容不会交给 markdown-it 处理
* :::
* ```
*
* @example
* ```ts
* const example = createContainerSyntaxPlugin(md, 'example', (tokens, index, options, env) => {
* const { content, meta } = tokens[index]
* return `<div class="example">${meta.title} | ${content}</div>`
* })
* ```
*/
function createContainerSyntaxPlugin(md, type, render) {
const maker = ":";
const markerMinLen = 3;
/**
* 自定义容器的 block 规则定义。
* @param state 当前 block 状态
* @param startLine 起始行
* @param endLine 结束行
* @param silent 是否为静默模式
* @returns 是否匹配到自定义容器
*/
function defineContainer(state, startLine, endLine, silent) {
const start = state.bMarks[startLine] + state.tShift[startLine];
const max = state.eMarks[startLine];
let pos = start;
if (state.src[pos] !== maker) return false;
pos += markerMinLen;
for (pos = start + 1; pos <= max; pos++) if (state.src[pos] !== maker) break;
if (pos - start < markerMinLen) return false;
const markup = state.src.slice(start, pos);
const info = state.src.slice(pos, max).trim();
if (!info.startsWith(type)) return false;
/* istanbul ignore if -- @preserve */
if (silent) return true;
let line = startLine;
let content = "";
while (++line < endLine) {
if (state.src.slice(state.bMarks[line], state.eMarks[line]).trim() === markup) break;
content += `${state.src.slice(state.bMarks[line], state.eMarks[line])}\n`;
}
const token = state.push(`${type}_container`, "", 0);
token.meta = resolveAttrs(info.slice(type.length)).attrs;
token.content = content;
token.markup = `${markup} ${type}`;
token.map = [startLine, line + 1];
state.line = line + 1;
return true;
}
const defaultRender = (tokens, index) => {
const { content } = tokens[index];
return `<div class="custom-container ${type}">${content}</div>`;
};
md.block.ruler.before("fence", `${type}_definition`, defineContainer);
md.renderer.rules[`${type}_container`] = render ?? defaultRender;
}
//#endregion
//#region src/node/container/codeTree.ts
const UNSUPPORTED_FILE_TYPES = [
"jpg",
"jpeg",
"png",
"gif",
"avif",
"webp",
"mp3",
"mp4",
"ogg",
"m3u8",
"m3u",
"flv",
"webm",
"wav",
"flac",
"aac",
"pdf",
"doc",
"docx",
"ppt",
"pptx",
"xls",
"xlsx"
];
/**
* 将文件路径数组解析为文件树节点结构
* @param files 文件路径数组
* @returns 文件树节点数组
*/
function parseFileNodes(files) {
const nodes = [];
for (const file of files) {
const parts = removeLeadingSlash(file).split("/");
let node = nodes;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
const isFile = i === parts.length - 1;
let child = node.find((n) => n.filename === part);
if (!child) {
child = {
level: i + 1,
filename: part,
filepath: isFile ? file : void 0,
children: isFile ? void 0 : []
};
node.push(child);
}
if (!isFile && child.children) node = child.children;
}
}
return nodes;
}
/**
* 注册 code-tree 容器和嵌入语法的 markdown 插件
* @param md markdown-it 实例
* @param app vuepress app 实例
* @param options code-tree 配置项
*/
function codeTreePlugin(md, app, options = {}) {
/**
* 获取文件或文件夹的图标
*/
const getIcon = (filename, type, mode) => {
mode ||= options.icon || "colored";
if (mode === "simple") return type === "folder" ? defaultFolder : defaultFile;
return getFileIcon(filename, type);
};
/**
* 渲染文件树节点为组件字符串
*/
function renderFileTree(nodes, mode) {
return nodes.map((node) => {
const props = {
filename: node.filename,
level: node.level,
type: node.children?.length ? "folder" : "file",
expanded: true,
filepath: node.filepath
};
return `<FileTreeNode${stringifyAttrs(props, false, ["filename", "filepath"])}>
<template #icon><VPIcon provider="iconify" name="${getIcon(node.filename, props.type, mode)}" /></template>
${node.children?.length ? renderFileTree(node.children, mode) : ""}
</FileTreeNode>`;
}).join("\n");
}
createContainerPlugin(md, "code-tree", {
before: (info, tokens, index) => {
const files = [];
let activeFile;
for (let i = index + 1; !(tokens[i].nesting === -1 && tokens[i].type === "container_code-tree_close"); i++) {
const token = tokens[i];
if (token.type === "fence" && token.tag === "code") {
const fenceInfo = md.utils.unescapeAll(token.info);
const title$1 = resolveAttr(fenceInfo, "title");
if (title$1) {
files.push(title$1);
if (fenceInfo.includes(":active")) activeFile = title$1;
}
}
}
const { attrs: attrs$1 } = resolveAttrs(info);
const { title, icon, height, entry } = attrs$1;
const fileTreeNodes = parseFileNodes(files);
const entryFile = activeFile || entry || files[0];
const h = height || String(options.height);
return `<VPCodeTree${stringifyAttrs({
title,
entryFile,
height: h ? parseRect(h) : void 0
})}><template #file-tree>${renderFileTree(fileTreeNodes, icon)}</template>`;
},
after: () => "</VPCodeTree>"
});
createEmbedRuleBlock(md, {
type: "code-tree",
syntaxPattern: /^@\[code-tree([^\]]*)\]\(([^)]*)\)/,
meta: ([, info, dir]) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const h = attrs$1.height || String(options.height);
return {
title: attrs$1.title,
entryFile: attrs$1.entry,
icon: attrs$1.icon,
height: h ? parseRect(h) : void 0,
dir
};
},
content: ({ dir, icon,...props }, _, env) => {
const codeTreeFiles = env.codeTreeFiles ??= [];
const root = findFile(app, env, dir);
const files = globSync("**/*", {
cwd: root,
onlyFiles: true,
dot: true,
ignore: [
"**/node_modules/**",
"**/.DS_Store",
"**/.gitkeep"
]
}).sort((a, b) => {
const al = a.split("/").length;
return b.split("/").length - al;
});
props.entryFile ||= files[0];
const codeContent = files.map((file) => {
const ext = path$1.extname(file).slice(1);
if (UNSUPPORTED_FILE_TYPES.includes(ext)) return "";
const filepath$1 = path$1.join(root, file);
codeTreeFiles.push(filepath$1);
const content = readFileSync(filepath$1);
return `\`\`\`${ext || "txt"} title="${file}"\n${content}\n\`\`\``;
}).filter(Boolean).join("\n");
const fileTreeNodes = parseFileNodes(files);
return `<VPCodeTree${stringifyAttrs(props)}><template #file-tree>${renderFileTree(fileTreeNodes, icon)}</template>${md.render(codeContent, cleanMarkdownEnv(env))}</VPCodeTree>`;
}
});
}
/**
* 扩展页面依赖,将 codeTreeFiles 添加到页面依赖中
* @param page vuepress 页面对象
*/
function extendsPageWithCodeTree(page) {
const codeTreeFiles = page.markdownEnv.codeTreeFiles ?? [];
if (codeTreeFiles.length) page.deps.push(...codeTreeFiles);
}
//#endregion
//#region src/node/container/align.ts
function alignPlugin(md) {
for (const name of [
"left",
"center",
"right",
"justify"
]) createContainerPlugin(md, name, { before: () => `<div style="text-align:${name}">` });
createContainerPlugin(md, "flex", { before: (info) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const styles = ["margin:16px 0;display:flex"];
const align = attrs$1.start ? "flex-start" : attrs$1.end ? "flex-end" : attrs$1.center ? "center" : "";
const justify = attrs$1.between ? "space-between" : attrs$1.around ? "space-around" : attrs$1.center ? "center" : "";
if (align) styles.push(`align-items:${align}`);
if (justify) styles.push(`justify-content:${justify}`);
if (attrs$1.column) styles.push("flex-direction:column");
if (attrs$1.wrap) styles.push("flex-wrap:wrap");
styles.push(`gap:${parseRect(attrs$1.gap || "16")}`);
return `<div style="${styles.join(";")}">`;
} });
}
//#endregion
//#region src/node/container/card.ts
function cardPlugin(md) {
/**
* ::: card title="xxx" icon="xxx"
* xxx
* :::
*/
createContainerPlugin(md, "card", {
before(info) {
const { attrs: attrs$1 } = resolveAttrs(info);
return `<VPCard${stringifyAttrs(attrs$1)}>`;
},
after: () => "</VPCard>"
});
/**
* :::: card-grid
* ::: card
* xxx
* :::
* ::: card
* xxx
* :::
* ::::
*/
createContainerPlugin(md, "card-grid", {
before: () => "<VPCardGrid>",
after: () => "</VPCardGrid>"
});
/**
* ::: card-masonry cols="2" gap="10"
* ::: card
* xxx
* :::
* ::: card
* xxx
* :::
* ::::
*/
createContainerPlugin(md, "card-masonry", {
before: (info) => {
const { attrs: attrs$1 } = resolveAttrs(info);
if (attrs$1.cols) attrs$1.cols = attrs$1.cols[0] === "{" ? attrs$1.cols : Number.parseInt(`${attrs$1.cols}`);
if (attrs$1.gap) attrs$1.gap = Number(attrs$1.gap);
return `<VPCardMasonry${stringifyAttrs(attrs$1)}>`;
},
after: () => "</VPCardMasonry>"
});
}
//#endregion
//#region src/node/container/chat.ts
function chatMessagesRender(md, env, messages) {
let currentDate = "";
return messages.map(({ sender, username, date, content }) => {
let messageContent = "";
if (!currentDate || currentDate !== date) {
currentDate = date;
messageContent += `<div class="vp-chat-date"><span>${currentDate}</span></div>\n`;
}
messageContent += `<div class="vp-chat-message ${sender}">
<div class="vp-chat-message-body">\
${sender === "user" ? `\n<p class="vp-chat-username">${username}</p>` : ""}
<div class="message-content">
${md.render(content.join("\n"), cleanMarkdownEnv(env)).trim()}
</div>
</div>
</div>`;
return messageContent;
}).join("\n");
}
function parseChatContent(content) {
const lines = content.split("\n");
const messages = [];
let currentDate = "";
let message;
for (const line of lines) {
const lineStr = line.trim();
if (lineStr.startsWith("{:") && lineStr.endsWith("}")) {
currentDate = lineStr.slice(2, -1).trim();
continue;
}
if (lineStr.startsWith("{") && lineStr.endsWith("}")) {
const username = lineStr.slice(1, -1).trim();
message = {
sender: username === "." ? "self" : "user",
username,
date: currentDate,
content: []
};
messages.push(message);
continue;
}
if (message?.sender) message.content.push(line);
}
return messages;
}
const chatPlugin = (md) => createContainerSyntaxPlugin(md, "chat", (tokens, idx, _, env) => `<div class="vp-chat">
<div class="vp-chat-header">
<p class="vp-chat-title">${tokens[idx].meta?.title || "Chat"}</p>
</div>
<div class="vp-chat-content">
${chatMessagesRender(md, env, parseChatContent(tokens[idx].content))}
</div>
</div>`);
//#endregion
//#region src/node/container/collapse.ts
function collapsePlugin(md) {
createContainerPlugin(md, "collapse", {
before: (info, tokens, index) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const idx = parseCollapse(tokens, index, attrs$1);
const { accordion } = attrs$1;
return `<VPCollapse${stringifyAttrs({
accordion,
index: idx
})}>`;
},
after: () => `</VPCollapse>`
});
md.renderer.rules.collapse_item_open = (tokens, idx) => {
const { expand, index } = tokens[idx].meta;
return `<VPCollapseItem${stringifyAttrs({
expand,
index
})}>`;
};
md.renderer.rules.collapse_item_close = () => "</VPCollapseItem>";
md.renderer.rules.collapse_item_title_open = () => "<template #title>";
md.renderer.rules.collapse_item_title_close = () => "</template>";
}
function parseCollapse(tokens, index, attrs$1) {
const listStack = [];
let idx = -1;
let defaultIndex;
let hashExpand = false;
for (let i = index + 1; i < tokens.length; i++) {
const token = tokens[i];
if (token.type === "container_collapse_close") break;
if (token.type === "bullet_list_open") {
listStack.push(0);
if (listStack.length === 1) token.hidden = true;
} else if (token.type === "bullet_list_close") {
listStack.pop();
if (listStack.length === 0) token.hidden = true;
} else if (token.type === "list_item_open") {
if (listStack.length === 1) {
token.type = "collapse_item_open";
tokens[i + 1].type = "collapse_item_title_open";
tokens[i + 3].type = "collapse_item_title_close";
idx++;
const firstToken = tokens[i + 2].children[0];
let flag = "";
let expand;
if (firstToken.type === "text") firstToken.content = firstToken.content.trim().replace(/^:[+\-]\s*/, (match) => {
flag = match.trim();
return "";
});
if (attrs$1.accordion) {
if (!hashExpand && flag === ":+") {
expand = hashExpand = true;
defaultIndex = idx;
}
} else if (flag === ":+") expand = true;
else if (flag === ":-") expand = false;
else expand = !!attrs$1.expand;
token.meta = {
index: idx,
expand
};
}
} else if (token.type === "list_item_close") {
if (listStack.length === 1) token.type = "collapse_item_close";
}
}
if (attrs$1.accordion && attrs$1.expand && !hashExpand) defaultIndex = 0;
return defaultIndex;
}
//#endregion
//#region src/node/container/demoWrapper.ts
/**
* :::demo-wrapper img no-padding title="xxx" height="100px"
* :::
*/
function demoWrapperPlugin(md) {
createContainerPlugin(md, "demo-wrapper", {
before: (info) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const wrapperClasses = ["demo-wrapper"];
let containerStyle = "";
if (attrs$1.title) wrapperClasses.push("has-title");
if (attrs$1.img) wrapperClasses.push("only-img");
if (attrs$1.noPadding) wrapperClasses.push("no-padding");
if (attrs$1.height) {
const h = Number.parseFloat(attrs$1.height) === Number(attrs$1.height) ? `${attrs$1.height}px` : attrs$1.height;
containerStyle += `--demo-container-height: ${h};`;
wrapperClasses.push("has-height");
}
return `<div class="${wrapperClasses.join(" ")}">
<div class="demo-head">
<div class="demo-ctrl"><i></i><i></i><i></i></div>
${attrs$1.title ? `<h4 class="demo-title"><p>${attrs$1.title}</p></h4>` : ""}
</div>
<div class="demo-container" ${containerStyle ? `style="${containerStyle}"` : ""}>\n`;
},
after: () => "</div></div>"
});
}
//#endregion
//#region src/node/container/field.ts
function fieldPlugin(md) {
createContainerPlugin(md, "field", {
before: (info) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const { name, type, required, optional, deprecated, default: defaultValue } = attrs$1;
return `<VPField${stringifyAttrs({
name,
required,
optional,
deprecated
})}${!isUndefined(type) ? ` type="${type}"` : ""}${!isUndefined(defaultValue) ? ` default-value="${defaultValue}"` : ""}>`;
},
after: () => "</VPField>"
});
createContainerPlugin(md, "field-group", { before: () => "<div class=\"vp-field-group\">" });
}
//#endregion
//#region src/node/container/fileTree.ts
/**
* 解析原始文件树内容为节点树结构
* @param content 文件树的原始文本内容
* @returns 文件树节点数组
*/
function parseFileTreeRawContent(content) {
const root = {
info: "",
level: -1,
children: []
};
const stack = [root];
const lines = content.trim().split("\n");
for (const line of lines) {
const match = line.match(/^(\s*)-(.*)$/);
if (!match) continue;
const level = Math.floor(match[1].length / 2);
const info = match[2].trim();
while (stack.length > 0 && stack[stack.length - 1].level >= level) stack.pop();
const parent = stack[stack.length - 1];
const node = {
info,
level,
children: []
};
parent.children.push(node);
stack.push(node);
}
return root.children;
}
const RE_FOCUS = /^\*\*(.*)\*\*(?:$|\s+)/;
/**
* 解析单个节点的 info 字符串,提取文件名、注释、类型等属性
* @param info 节点描述字符串
* @returns 文件树节点属性
*/
function parseFileTreeNodeInfo(info) {
let filename = "";
let comment = "";
let focus = false;
let expanded = true;
let type = "file";
let diff;
if (info.startsWith("++")) {
info = info.slice(2).trim();
diff = "add";
} else if (info.startsWith("--")) {
info = info.slice(2).trim();
diff = "remove";
}
info = info.replace(RE_FOCUS, (_, matched) => {
filename = matched;
focus = true;
return "";
});
if (filename === "" && !focus) {
const spaceIndex = info.indexOf(" ");
filename = info.slice(0, spaceIndex === -1 ? info.length : spaceIndex);
info = spaceIndex === -1 ? "" : info.slice(spaceIndex);
}
comment = info.trim();
if (filename.endsWith("/")) {
type = "folder";
expanded = false;
filename = removeEndingSlash(filename);
}
return {
filename,
comment,
focus,
expanded,
type,
diff
};
}
/**
* 文件树 markdown 插件主函数
* @param md markdown 实例
* @param options 文件树渲染选项
*/
function fileTreePlugin(md, options = {}) {
/**
* 获取文件或文件夹的图标
*/
const getIcon = (filename, type, mode) => {
mode ||= options.icon || "colored";
if (mode === "simple") return type === "folder" ? defaultFolder : defaultFile;
return getFileIcon(filename, type);
};
/**
* 递归渲染文件树节点
*/
const renderFileTree = (nodes, meta) => nodes.map((node) => {
const { info, level, children } = node;
const { filename, comment, focus, expanded, type, diff } = parseFileTreeNodeInfo(info);
const isOmit = filename === "…" || filename === "...";
if (children.length === 0 && type === "folder") children.push({
info: "…",
level: level + 1,
children: []
});
const nodeType = children.length > 0 ? "folder" : type;
const renderedComment = comment ? `<template #comment>${md.renderInline(comment.replaceAll("#", "#"))}</template>` : "";
const renderedIcon = !isOmit ? `<template #icon><VPIcon provider="iconify" name="${getIcon(filename, nodeType, meta.icon)}" /></template>` : "";
return `<FileTreeNode${stringifyAttrs({
expanded: nodeType === "folder" ? expanded : false,
focus,
type: nodeType,
diff,
filename,
level
}, false, ["filename"])}>
${renderedIcon}${renderedComment}${children.length > 0 ? renderFileTree(children, meta) : ""}
</FileTreeNode>`;
}).join("\n");
return createContainerSyntaxPlugin(md, "file-tree", (tokens, index) => {
const token = tokens[index];
const nodes = parseFileTreeRawContent(token.content);
const meta = token.meta;
return `<div class="vp-file-tree">${meta.title ? `<p class="vp-file-tree-title">${meta.title}</p>` : ""}${renderFileTree(nodes, meta)}</div>\n`;
});
}
//#endregion
//#region src/node/container/langRepl.ts
async function langReplPlugin(app, md, { theme, go = false, kotlin = false, rust = false, python = false }) {
const container$1 = (lang) => createContainerPlugin(md, `${lang}-repl`, {
before(info) {
const { attrs: attrs$1 } = resolveAttrs(info);
const { editable, title } = attrs$1;
return `<CodeRepl${stringifyAttrs({
editable,
title: title || `${lang} playground`
})}>`;
},
after: () => "</CodeRepl>"
});
if (kotlin) container$1("kotlin");
if (go) container$1("go");
if (rust) container$1("rust");
if (python) container$1("python");
theme ??= {
light: "github-light",
dark: "github-dark"
};
const data = { grammars: {} };
try {
const themesPath = path.dirname(resolveModule("tm-themes"));
const grammarsPath = path.dirname(resolveModule("tm-grammars"));
const readTheme = (theme$1) => read(path.join(themesPath, "themes", `${theme$1}.json`));
const readGrammar = (grammar) => read(path.join(grammarsPath, "grammars", `${grammar}.json`));
if (typeof theme === "string") data.theme = await readTheme(theme);
else data.theme = await Promise.all([readTheme(theme.light), readTheme(theme.dark)]).then(([light, dark]) => ({
light,
dark
}));
if (kotlin) data.grammars.kotlin = await readGrammar("kotlin");
if (go) data.grammars.go = await readGrammar("go");
if (rust) data.grammars.rust = await readGrammar("rust");
if (python) data.grammars.python = await readGrammar("python");
} catch {
/* istanbul ignore next -- @preserve */
logger.error("[vuepress-plugin-md-power]", `Failed to load packages: ${colors.green("tm-themes")}, ${colors.green("tm-grammars")}, Please install them manually.`);
}
await app.writeTemp("internal/md-power/replEditorData.js", `export default ${JSON.stringify(data, null, 2)}`);
}
async function read(file) {
try {
const content = await promises.readFile(file, "utf-8");
return JSON.parse(content);
} catch {}
}
//#endregion
//#region src/node/utils/logger.ts
/**
* Logger utils
*/
var Logger = class {
constructor(name = "") {
this.name = name;
}
init(subname, text) {
return ora({
prefixText: colors.blue(`${this.name}${subname ? `:${subname}` : ""}: `),
text
});
}
/**
* Create a loading spinner with text
*/
load(subname, msg) {
const instance = this.init(subname, msg);
return {
succeed: (text) => instance.succeed(text),
fail: (text) => instance.succeed(text)
};
}
info(subname, text = "", ...args) {
this.init(subname, colors.blue(text)).info();
if (args.length) console.info(...args);
}
/**
* Log success msg
*/
succeed(subname, text = "", ...args) {
this.init(subname, colors.green(text)).succeed();
if (args.length) console.log(...args);
}
/**
* Log warning msg
*/
warn(subname, text = "", ...args) {
this.init(subname, colors.yellow(text)).warn();
if (args.length) console.warn(...args);
}
/**
* Log error msg
*/
error(subname, text = "", ...args) {
this.init(subname, colors.red(text)).fail();
if (args.length) console.error(...args);
}
};
const logger$1 = new Logger("vuepress-plugin-md-power");
//#endregion
//#region src/node/container/npmToPreset.ts
const ALLOW_LIST = [
"npm",
"pnpm",
"yarn",
"bun",
"deno"
];
const BOOL_FLAGS = [
"--no-save",
"-B",
"--save-bundle",
"--save-dev",
"-D",
"--save-prod",
"-P",
"--save-peer",
"-O",
"--save-optional",
"-E",
"--save-exact",
"-y",
"--yes",
"-g",
"--global"
];
const DEFAULT_TABS = [
"npm",
"pnpm",
"yarn"
];
const MANAGERS_CONFIG = {
install: {
pattern: /(?:^|\s)npm\s+(?:install|i)$/,
pnpm: { cli: "pnpm install" },
yarn: { cli: "yarn" },
bun: { cli: "bun install" },
deno: { cli: "deno install" }
},
add: {
pattern: /(?:^|\s)npm\s+(?:install|i|add)(?:\s|$)/,
pnpm: {
cli: "pnpm add",
flags: {
"--no-save": "",
"-B": "",
"--save-bundle": ""
}
},
yarn: {
cli: "yarn add",
flags: {
"--save-dev": "--dev",
"--save-prod": "--prod",
"-P": "",
"--save-peer": "--peer",
"--save-optional": "--optional",
"--no-save": "",
"--save-exact": "--exact",
"-B": "",
"--save-bundle": ""
}
},
bun: {
cli: "bun add",
flags: {
"--save-dev": "--development",
"-P": "",
"--save-prod": "",
"--save-peer": "",
"-O": "--optional",
"--save-optional": "--optional",
"--no-save": "",
"--save-exact": "--exact",
"-B": "",
"--save-bundle": ""
}
},
deno: {
cli: "deno add",
flags: {
"-g": "",
"--global": "",
"--save-dev": "--dev",
"-P": "",
"--save-prod": "",
"--save-peer": "",
"-O": "",
"--save-optional": "",
"--no-save": "",
"-E": "",
"--save-exact": "",
"-B": "",
"--save-bundle": ""
}
}
},
run: {
pattern: /(?:^|\s)npm\s+(?:run|run-script|rum|urn)(?:\s|$)/,
pnpm: {
cli: "pnpm",
flags: {
"-w": "-F",
"--workspace": "--filter",
"--": ""
}
},
yarn: {
cli: "yarn",
flags: {
"-w": "",
"--workspace": ""
}
},
bun: {
cli: "bun run",
flags: {
"-w": "--filter",
"--workspace": "--filter"
}
},
deno: {
cli: "deno run",
flags: {
"-w": "",
"--workspace": ""
}
}
},
create: {
pattern: /(?:^|\s)npm\s+create\s/,
pnpm: {
cli: "pnpm create",
flags: {
"-y": "",
"--yes": ""
}
},
yarn: {
cli: "yarn create",
flags: {
"-y": "",
"--yes": ""
}
},
bun: {
cli: "bun create",
flags: {
"-y": "",
"--yes": ""
}
},
deno: {
cli: "deno run -A ",
flags: {
"-y": "",
"--yes": ""
}
}
},
init: {
pattern: /(?:^|\s)npm\s+init/,
pnpm: {
cli: "pnpm init",
flags: {
"-y": "",
"--yes": ""
}
},
yarn: {
cli: "yarn init",
flags: {
"-y": "",
"--yes": ""
}
},
bun: {
cli: "bun init",
flags: {
"-y": "",
"--yes": ""
}
},
deno: {
cli: "deno init",
flags: {
"-y": "",
"--yes": ""
}
}
},
npx: {
pattern: /(?:^|\s)npx\s+/,
pnpm: { cli: "pnpm dlx" },
yarn: { cli: "yarn dlx" },
bun: { cli: "bunx" },
deno: { cli: "deno run -A" }
},
remove: {
pattern: /(?:^|\s)npm\s+(?:uninstall|r|rm|remove|unlink|un)(?:\s|$)/,
pnpm: {
cli: "pnpm remove",
flags: {
"--no-save": "",
"--save": "",
"-S": ""
}
},
yarn: {
cli: "yarn remove",
flags: {
"--save-dev": "--dev",
"--save": "",
"-S": "",
"-g": "",
"--global": ""
}
},
bun: {
cli: "bun remove",
flags: {
"--save-dev": "--development",
"--save": "",
"-S": "",
"-g": "",
"--global": ""
}
},
deno: {
cli: "deno uninstall",
flags: {
"--save-dev": "--dev",
"--save": "",
"-S": ""
}
}
},
ci: {
pattern: /(?:^|\s)npm\s+ci$/,
pnpm: { cli: "pnpm install --frozen-lockfile" },
yarn: { cli: "yarn install --immutable" },
bun: { cli: "bun install --frozen-lockfile" },
deno: { cli: "deno install --frozen" }
}
};
//#endregion
//#region src/node/container/npmTo.ts
/**
* 注册 npm-to 容器插件,将 npm 代码块自动转换为多包管理器命令分组
*/
function npmToPlugins(md, options = {}) {
const opt = isArray(options) ? { tabs: options } : options;
const defaultTabs = opt.tabs?.length ? opt.tabs : DEFAULT_TABS;
createContainerPlugin(md, "npm-to", {
before: (info, tokens, idx, _opt, env) => {
const { attrs: attrs$1 } = resolveAttrs(info);
const tabs$1 = attrs$1.tabs ? attrs$1.tabs.split(/,\s*/) : defaultTabs;
const token = tokens[idx + 1];
if (token.type === "fence") {
const content = token.content;
token.hidden = true;
token.type = "text";
token.content = "";
const lines = content.split(/(\n|\s*&&\s*)/);
return md.render(resolveNpmTo(lines, token.info.trim(), idx, tabs$1), cleanMarkdownEnv(env));
}
logger$1.warn("npm-to", `Invalid npm-to container in ${colors.gray(env.filePathRelative || env.filePath)}`);
return "";
},
after: () => ""
});
}
/**
* 将 npm 命令转换为各包管理器命令分组
* @param lines 命令行数组
* @param info 代码块类型
* @param idx token 索引
* @param tabs 需要支持的包管理器
*/
function resolveNpmTo(lines, info, idx, tabs$1) {
tabs$1 = validateTabs(tabs$1);
const res = [];
const map = {};
for (const tab$1 of tabs$1) {
const newLines = [];
for (const line of lines) {
const config = findConfig(line);
if (config && config[tab$1]) {
const parsed = map[line] ??= parseLine(line);
const { cli, flags } = config[tab$1];
let newLine = `${parsed.env ? `${parsed.env} ` : ""}${cli}`;
if (parsed.args && flags) {
let args = parsed.args;
for (const [key, value] of Object.entries(flags)) args = args.replaceAll(key, value);
newLine += ` ${args.replace(/\s+-/g, " -").trim()}`;
}
if (parsed.cmd) newLine += ` ${parsed.cmd}`;
if (parsed.scriptArgs) newLine += ` ${parsed.scriptArgs}`;
newLines.push(newLine.trim());
} else newLines.push(line);
}
res.push(`@tab ${tab$1}\n\`\`\`${info}\n${newLines.join("")}\n\`\`\``);
}
return `:::code-tabs#npm-to-${tabs$1.join("-")}\n${res.join("\n")}\n:::`;
}
/**
* 根据命令行内容查找对应的包管理器配置
*/
function findConfig(line) {
for (const { pattern,...config } of Object.values(MANAGERS_CONFIG)) if (pattern.test(line)) return config;
}
/**
* 校验 tabs 合法性,返回允许的包管理器列表
*/
function validateTabs(tabs$1) {
tabs$1 = tabs$1.filter((tab$1) => ALLOW_LIST.includes(tab$1));
if (tabs$1.length === 0) return DEFAULT_TABS;
return tabs$1;
}
const LINE_REG = /(.*)(npm|npx)\s+(.*)/;
/**
* 解析一行 npm/npx 命令,拆分出环境变量、命令、参数等
*/
function parseLine(line) {
const match = line.match(LINE_REG);
if (!match) return false;
const [, env, cli, rest] = match;
const idx = rest.trim().indexOf(" ");
if (cli === "npx") {
let cmd = "";
let scriptArgs = "";
if (idx !== -1) {
cmd = rest.slice(0, idx);
scriptArgs = rest.slice(idx + 1).trim();
} else cmd = rest;
return {
env,
cli,
cmd,
scriptArgs
};
}
if (idx === -1) return {
env,
cli: `${cli} ${rest.trim()}`,
cmd: ""
};
return {
env,
cli: `${cli} ${rest.slice(0, idx)}`,
...parseArgs(rest.slice(idx + 1))
};
}
/**
* 解析 npm 命令参数,区分命令、参数、脚本参数
*/
function parseArgs(line) {
line = line?.trim();
const [npmArgs, scriptArgs] = line.split(/\s+--\s+/);
let cmd = "";
let args = "";
if (npmArgs[0] !== "-") if (npmArgs[0] === "\"" || npmArgs[0] === "'") {
const idx = npmArgs.slice(1).indexOf(npmArgs[0]);
cmd = npmArgs.slice(0, idx + 2);
args = npmArgs.slice(idx + 2);
} else {
const idx = npmArgs.indexOf(" -");
if (idx === -1) cmd = npmArgs;
else {
cmd = npmArgs.slice(0, idx);
args = npmArgs.slice(idx + 1);
}
}
else {
let newLine = "";
let value = "";
let isQuote = false;
let isBool = false;
let isNextValue = false;
let quote = "";
for (let i = 0; i < npmArgs.length; i++) {
const v = npmArgs[i];
if (!isQuote && (v === "\"" || v === "'")) {
quote = v;
isQuote = true;
value += v;
} else if (isQuote && v === quote) {
isQuote = false;
value += v;
} else if ((v === " " || v === "=" || i === npmArgs.length - 1) && !isQuote && value) {
if (i === npmArgs.length - 1) value += v;
const isKey = value[0] === "-";
if (isKey) {
isBool = BOOL_FLAGS.includes(value);
isNextValue = !isBool;
}
if (!isKey && !isNextValue) cmd += ` ${value}`;
else {
newLine += `${value}${i !== npmArgs.length - 1 ? v : ""}`;
if (!isKey && isNextValue) isNextValue = false;
}
value = "";
} else value += v;
}
args = newLine;
}
return {
cmd: cmd.trim(),
args: args.trim(),
scriptArgs
};
}
//#endregion
//#region src/node/container/steps.ts
/**
* :::steps
* 1. 步骤 1
* xxx
* 2. 步骤 2
* xxx
* 3. ...
* :::
*/
function stepsPlugin(md) {
createContainerPlugin(md, "steps", { before: () => "<div class=\"vp-steps\">" });
}
//#endregion
//#region src/node/container/table.ts
/**
* 在不破坏表格语法的前提下,通过容器语法将表格包裹起来,为表格提供增强功能
*
* @example
* ```md
* ::: table title="表格标题" max-content copy align="center" hl-rows="warning:1,2,3;error:4,5,6" hl-cols="warning:1;error:2,3" hl-cells="warning:(1,2)(2,3);"
*
* | xx | xx | xx |
* | -- | -- | -- |
* | xx | xx | xx |
* :::
* ```
*/
function tablePlugin(md, options = {}) {
createContainerSyntaxPlugin(md, "table", (tokens, index, opt, env) => {
const { hlCols = "", hlRows = "", hlCells = "",...meta } = tokens[index].meta;
const props = {
copy: true,
maxContent: false,
...options,
...meta
};
const content = tokens[index].content;
if (props.copy) {
props.copy = props.copy === true ? "all" : props.copy;
if (props.copy === "all" || props.copy === "md") props.markdown = encodeData(content.trim());
}
if (!hlCols && !hlRows && !hlCells) return `<VPTable ${stringifyAttrs(props)}>${md.render(content, env)}</VPTable>`;
const rows = parseHl(hlRows);
const cols = parseHl(hlCols);
const cells = parseHlCells(hlCells);
const tableTokens = md.parse(content, env);
let isTable = false;
let colIndex = 0;
let rowIndex = 0;
for (const token of tableTokens) {
if (token.type === "table_open") isTable = true;
if (token.type === "table_close") isTable = false;
if (!isTable) continue;
if (token.type === "tr_open") {
rowIndex++;
colIndex = 0;
}
if (token.type === "th_open" || token.type === "td_open") {
colIndex++;
const classes = cells[rowIndex]?.[colIndex] || rows[rowIndex] || cols[colIndex];
if (classes) token.attrJoin("class", classes);
}
}
return `<VPTable ${stringifyAttrs(props)}>${md.renderer.render(tableTokens, opt, env)}</VPTable>`;
});
}
function parseHl(hl) {
const res = {};
if (!hl) return res;
hl.split(";").forEach((item) => {
const [key, value = "1"] = item.split(":");
String(value).split(",").forEach((v) => res[v.trim()] = key.trim());
});
return res;
}
function parseHlCells(hl) {
const res = {};
if (!hl) return res;
hl.split(";").forEach((item) => {
const [key, value = ""] = item.split(":");
value.trim().replace(/\s*\((\d+)\s*,\s*(\d+)\)\s*/g, (_, row, col) => {
res[row] ??= {};
res[row][col] = key.trim();
return "";
});
});
return res;
}
//#endregion
//#region src/node/container/tabs.ts
const tabs = (md) => {
tab(md, {
name: "tabs",
openRender: ({ active, data }, tokens, index, _, env) => {
const { meta } = tokens[index];
const titles = data.map(({ title }) => md.renderInline(title, cleanMarkdownEnv(env)));
const tabsData = data.map((item, dataIndex) => {
const { id = titles[dataIndex] } = item;
return { id };
});
return `<Tabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>
${titles.map((title, titleIndex) => `<template #title${titleIndex}="{ value, isActive }">${title}</template>`).join("")}`;
},
closeRender: () => `</Tabs>`,
tabOpenRender: ({ index }) => `<template #tab${index}="{ value, isActive }">`,
tabCloseRender: () => `</template>`
});
};
//#endregion
//#region src/node/container/timeline.ts
const RE_KEY = /(\w+)=\s*/;
const RE_SEARCH_KEY = /\s+\w+=\s*|$/;
const RE_CLEAN_VALUE = /(?<quote>["'])(.*?)(\k<quote>)/;
function timelinePlugin(md) {
createContainerPlugin(md, "timeline", {
before(info, tokens, index) {
parseTimeline(tokens, index);
const { attrs: attrs$1 } = resolveAttrs(info);
attrs$1.card ??= void 0;
return `<VPTimeline${stringifyAttrs(attrs$1, true)}>`;
},
after: () => "</VPTimeline>"
});
md.renderer.rules.timeline_item_open = (tokens, idx) => {
const attrs$1 = tokens[idx].meta;
attrs$1.card ??= void 0;
const icon = attrs$1.icon;
return `<VPTimelineItem${stringifyAttrs(attrs$1, true)}>${icon ? `<template #icon><VPIcon provider="iconify" name="${icon}"/></template>` : ""}`;
};
md.renderer.rules.timeline_item_close = () => "</VPTimelineItem>";
md.renderer.rules.timeline_item_title_open = () => "<template #title>";
md.renderer.rules.timeline_item_title_close = () => "</template>";
}
function parseTimeline(tokens, index) {
const listStack = [];
for (let i = index + 1; i < tokens.length; i++) {
const token = tokens[i];
if (token.type === "container_timeline_close") break;
if (token.type === "bullet_list_open") {
listStack.push(0);
if (listStack.length === 1) token.hidden = true;
} else if (token.type === "bullet_list_close") {
listStack.pop();
if (listStack.length === 0) token.hidden = true;
} else if (token.type === "list_item_open") {
if (listStack.length === 1) {
token.type = "timeline_item_open";
tokens[i + 1].type = "timeline_item_title_open";
tokens[i + 3].type = "timeline_item_title_close";
const inlineToken = tokens[i + 2];
const softbreakIndex = inlineToken.children.findLastIndex((token$1) => token$1.type === "softbreak");
if (softbreakIndex !== -1) {
const lastToken = inlineToken.children[inlineToken.children.length - 1];
token.meta = extractTimelineAttributes(lastToken.content.trim());
if (!isEmptyObject(token.meta)) inlineToken.children = inlineToken.children.slice(0, softbreakIndex);
} else token.meta = {};
}
} else if (token.type === "list_item_close") {
if (listStack.length === 1) token.type = "timeline_item_close";
}
}
}
function extractTimelineAttributes(rawText) {
const attrKeys = [
"time",
"type",
"icon",
"line",
"color",
"card",
"placement"
];
const attrs$1 = {};
let buffer = rawText.trim();
while (buffer.length) {
const keyMatch = buffer.match(RE_KEY);
if (!keyMatch) break;
const matchedKey = keyMatch[1].toLowerCase();
if (!attrKeys.includes(matchedKey)) break;
const keyEnd = keyMatch.index + keyMatch[0].length;
buffer = buffer.slice(keyEnd);
let valueEnd = buffer.search(RE_SEARCH_KEY);
/* istanbul ignore if -- @preserve */
if (valueEnd === -1) valueEnd = buffer.length;
attrs$1[matchedKey] = buffer.slice(0, valueEnd).trim().replace(RE_CLEAN_VALUE, "$2");
buffer = buffer.slice(valueEnd);
}
return attrs$1;
}
//#endregion
//#region src/node/container/index.ts
async function containerPlugin(app, md, options) {
alignPlugin(md);
tabs(md);
codeTabs(md, options.codeTabs);
demoWrapperPlugin(md);
stepsPlugin(md);
cardPlugin(md);
if (options.npmTo) npmToPlugins(md, typeof options.npmTo === "boolean" ? {} : options.npmTo);
if (options.repl) await langReplPlugin(app, md, options.repl);
if (options.fileTree) fileTreePlugin(md, isPlainObject(options.fileTree) ? options.fileTree : {});
if (options.codeTree) codeTreePlugin(md, app, isPlainObject(options.codeTree) ? options.codeTree : {});
if (options.timeline) timelinePlugin(md);
if (options.collapse) collapsePlugin(md);
if (options.chat) chatPlugin(md);
if (options.field) fieldPlugin(md);
if (options.table) tablePlugin(md, isPlainObject(options.table) ? options.table : {});
}
//#endregion
//#region src/node/demo/markdown.ts
function markdownEmbed(app, md, env, { url, title, desc, codeSetting = "", expanded = false }) {
const filepath$1 = findFile(app, env, url);
const code = readFileSync(filepath$1);
if (code === false) {
logger$1.warn("demo-markdown", `Cannot read markdown file: ${colors.gray(filepath$1)}\n at: ${colors.gray(env.filePathRelative || "")}`);
return "";
}
const demo = {
type: "markdown",
path: filepath$1
};
env.demoFiles ??= [];
if (!env.demoFiles.some((d) => d.path === filepath$1)) env.demoFiles.push(demo);
return `<VPDemoBasic${stringifyAttrs({
type: "markdown",
title,
desc,
expanded
})}>
${md.render(code, {
filepath: env.filePath,
filepathRelative: env.filePathRelative
})}
<template #code>
${md.render(`\`\`\`md ${codeSetting}\n${code}\n\`\`\``, {})}
</template>
</VPDemoBasic>`;
}
const markdownContainerRender = {
before(app, md, env, meta, codeMap) {
const { title, desc, expanded = false } = meta;
const code = codeMap.md || "";
return `<VPDemoBasic${stringifyAttrs({
type: "markdown",
title,
desc,
expanded
})}>
${md.render(code, {
filepath: env.filePath,
filepathRelative: env.filePathRelative
})}
<template #code>`;
},
after: () => "</template></VPDemoBasic>"
};
//#endregion
//#region src/node/utils/package.ts
async function interopDefault(m) {
const resolved = await m;
return resolved.default || resolved;
}
//#endregion
//#region src/node/demo/supports/compiler.ts
const cache = new LRUCache({ max: 64 });
const compiler = {
script: importer(async () => {
const { transform } = await import("esbuild");
return transform;
}),
less: importer(() => import("less")),
sass: importer(async () => {
if (isPackageExists("sass-embedded")) return await import("sass-embedded");
return await import("sass");
}),
stylus: importer(() => import("stylus"))
};
async function compileScript(source, type) {
const key = `${type}:::${source}`;
if (cache.has(key)) return cache.get(key);
const res = await (await compiler.script())(source, {
target: "es2018",
platform: "browser",
format: "cjs",
loader: type === "ts" ? "ts" : "js",
sourcemap: false
});
cache.set(key, res.code);
return res.code;
}
async function compileStyle(source, type) {
const key = `${type}:::${source}`;
if (cache.has(key)) return cache.get(key);
if (type === "css") return source;
if (type === "less") {
const res = await (await compiler.less()).render(source);
cache.set(key, res.css);
return res.css;
}
if (type === "scss") {
const res = (await compiler.sass()).compileString(source);
cache.set(key, res.css);
return res.css;
}
if (type === "stylus") {
const res = (await compiler.stylus()).render(source);
cache.set(key, res);
return res;
}
return source;
}
function importer(func) {
let imported;
return async () => {
if (!imported) imported = interopDefault(await func());
return imported;
};
}
//#endregion
//#region src/node/demo/supports/insertScript.ts
const SCRIPT_RE$1 = /<script.*?>/;
function insertSetupScript({ export: name, path: path$3 }, env) {
const imports = `import ${name ? `${name} from ` : ""}'${path$3}';`;
const scriptSetup = env.sfcBlocks.scriptSetup ??= {
type: "script",
content: "<script setup>\n<\/script>",
contentStripped: "",
tagOpen: "<script setup>",
tagClose: "<\/script>"
};
scriptSetup.contentStripped = `${imports}\n${scriptSetup.contentStripped}`;
scriptSetup.content = scriptSetup.content.replace(SCRIPT_RE$1, (matched) => `${matched}\n${imports}`);
}
//#endregion
//#region src/node/demo/watcher.ts
/**
* 消除异步编译 demo 代码 与 markdown 同步 render 的时间差问题
* 确保 在 vuepress onPrepared 阶段完成所有 demo 代码的编译与输出
*/
let renderDone = null;
let renderCount = 0;
let renderPromise;
function createDemoRender() {
renderPromise = new Promise((resolve) => {
renderDone = resolve;
});
}
async function waitDemoRender() {
if (renderCount === 0) {
renderDone?.();
renderDone = null;
}
await renderPromise;
}
function markDemoRender() {
renderCount++;
}
function checkDemoRender() {
if (renderCount > 0) renderCount--;
if (renderCount === 0) {
renderDone?.();
renderDone = null;
}
}
let watcher = null;
const tasks = {};
const target$2 = "md-power/demo/watcher.txt";
function demoWatcher(app, watchers) {
if (!watcher) watcher = watch([], { ignoreInitial: true });
Object.keys(tasks).forEach((path$3) => {
watcher.add(path$3);
});
const code = readFileSync(app.dir.temp(target$2));
if (code) {
const paths = JSON.parse(code || "{}");
Object.entries(paths).forEach(([path$3, output]) => {
watcher.add(path$3);
tasks[path$3] = output;
});
}
updateWatchFiles(app);
watcher.on("change", (path$3) => {
if (tasks[path$3]) {
const code$1 = readFileSync(path$3);
if (code$1 === false) return;
const source = parseEmbedCode(code$1);
compileCode(source, tasks[path$3]);
}
});
watcher.on("unlink", (path$3) => {
delete tasks[path$3];
watcher.unwatch(path$3);
});
watchers.push({ close: () => {
watcher.close();
watcher = null;
} });
}
function addTask(app, path$3, output) {
if (tasks[path$3]) return;
tasks[path$3] = output;
if (watcher) watcher.add(path$3);
updateWatchFiles(app);
}
async function updateWatchFiles(app) {
await fs$1.promises.mkdir(app.dir.temp(path$1.dirname(target$2)), { recursive: true });
await fs$1.promises.writeFile(app.dir.temp(target$2), JSON.stringify(tasks));
}
//#endregion
//#region src/node/demo/normal.ts
const CONFIG_RE = /<script type="config">([\s\S]*?)\n<\/script>/;
const SCRIPT_RE = /<script\s?(?:lang="(\w+)")?>([\s\S]*?)\n<\/script>/;
const STYLE_RE$1 = /<style\s?(?:lang="(\w+)")?>([\s\S]*?)\n<\/style>/;
const scriptSupported = ["ts", "js"];
const styleSupported = [
"css",
"scss",
"less",
"stylus",
"styl"
];
const target$1 = "md-power/demo/normal";
const FENCE = "```";
function parseEmbedCode(code) {
const res = {
html: "",
css: "",
script: "",
imports: "",
jsType: "js",
cssType: "css"
};
res.html = code.replace(CONFIG_RE, (_, config) => {
res.imports = config;
return "";
}).replace(SCRIPT_RE, (_, lang, script) => {
res.script = script;
res.jsType = scriptSupported.includes(lang) ? lang : "js";
return "";
}).replace(STYLE_RE$1, (_, lang, style) => {
res.css = style;
res.cssType = styleSupported.includes(lang) ? lang === "styl" ? "stylus" : lang : "css";
return "";
});
return res;
}
function codeToHtml(md, source, info) {
let content = "::: code-tabs\n";
if (source.html) content += `@tab HTML\n${FENCE}html ${info}\n${source.html.trim()}\n${FENCE}\n`;
if (source.script) {
const title = source.jsType === "ts" ? "Typescript" : "Javascript";
content += `@tab ${title}\n${FENCE}${source.jsType} ${info}\n${source.script.trim()}\n${FENCE}\n`;
}
if (source.css) {
const title = source.cssType === "stylus" ? "Stylus" : source.cssType.toUpperCase();
content += `@tab ${title}\n${FENCE}${source.cssType} ${info}\n${source.css.trim()}\n${FENCE}\n`;
}
content += "\n:::";
return md.render(content, {});
}
async function compileCode(code, output) {
markDemoRender();
const res = {
jsLib: [],
cssLib: [],
script: "",
css: "",
html: ""
};
if (!fs$1.existsSync(output)) writeFileSync(output, `import { ref } from "vue"\nexport default ref(${JSON.stringify(res, null, 2)})`);
try {
if (code.imports) {
const imports = JSON.parse(code.imports);
res.jsLib = imports.jsLib ?? [];
res.cssLib = imports.cssLib ?? [];
}
if (code.script) res.script = await compileScript(code.script.trim(), code.jsType);
if (code.css) res.css = await compileStyle(code.css.trim(), code.cssType);
if (code.html) res.html = code.html.trim();
} catch (e) {
logger$1.error("demo-normal", "demo parse error: \n", e);
}
writeFileSync(output, `import { ref } from "vue"\nexport default ref(${JSON.stringify(res, null, 2)})`);
checkDemoRender();
}
function normalEmbed(app, md, env, { url, title, desc, codeSetting = "", expanded = false }) {
const filepath$1 = findFile(app, env, url);
const code = readFileSync(filepath$1);
if (code === false) {
logger$1.warn("demo-normal", `Cannot read demo file: ${colors.gray(filepath$1)}\n at: ${colors.gray(env.filePathRelative || "")}`);
return "";
}
const source = parseEmbedCode(code);
const prefix = (env.filePathRelative || "").replace(/\.md$/, "").replace(/\//g, "-");
const basename = path$1.basename(filepath$1).replace(/-|\./g, "_");
const name = `Demo${basename[0].toUpperCase()}${basename.slice(1)}`;
const demo = {
type: "normal",
export: name,
path: filepath$1
};
const output = app.dir.temp(target$1, `${prefix}-${name}.js`);
compileCode(source, output);
addTask(app, filepath$1, output);
env.demoFiles ??= [];
if (!env.demoFiles.some((d) => d.path === filepath$1)) {
env.demoFiles.push(demo);
insertSetupScript({
...demo,
path: output
}, env);
}
return `<VPDemoNormal${stringifyAttrs({
":config": name,
title,
desc,
expanded
})}>
${codeToHtml(md, source, codeSetting)}
</VPDemoNormal>`;
}
const normalContainerRender = {
before(app, md, env, meta, codeMap) {
const { url, title, desc, expanded = false } = meta;
const name = `DemoContainer${url}`;
const prefix = (env.filePathRelative || "").replace(/\.md$/, "").replace(/\//g, "-");
const output = app.dir.temp(path$1.join(target$1, `${prefix}-${name}.js`));
env.demoFiles ??= [];
if (!env.demoFiles.some((d) => d.path === output)) {
const demo = {
type: "normal",
export: name,
gitignore: true,
path: output
};
env.demoFiles.push(demo);
insertSetupScript(demo, env);
}
const source = parseContainerCode(codeMap);
compileCode(source, output);
return `<VPDemoNormal${stringifyAttrs({
":config": name,
title,
desc,
expanded
})}>`;
},
after: () => "</VPDemoNormal>",
token(token) {
if (token.info.trim().startsWith("json")) {
token.hidden = true;
token.type = "text";
token.content = "";
}
}
};
function parseContainerCode(map) {
const res = {
html: "",
css: "",
script: "",
imports: "",
jsType: "js",
cssType: "css"
};
if (map.html) res.html = map.html;
if (map.js) {
res.script = map.js;
res.jsType = "js";
}
if (map.ts) {
res.script = map.ts;
res.jsType = "ts";
}
if (map.css) {
res.css = map.css;
res.cssType = "css";
}
if (map.less) {
res.css = map.less;
res.cssType = "less";
}
if (map.scss) {
res.css = map.scss;
res.cssType = "scss";
}
if (map.styl || map.stylus) {
res.css = map.styl || map.stylus;
res.cssType = "stylus";
}
if (map.json) res.imports = map.json;
return res;
}
//#endregion
//#region src/node/demo/supports/alias.ts
function normalizeAlias(info) {
const [lang] = info.trim().split(/\s+|:|\{/);
switch (lang) {
case "vue": return "vue";
case "js":
case "javascript": return "js";
case "ts":
case "typescript": return "ts";
case "stylus":
case "styl": return "stylus";
case "md":
case "markdown": return "md";
}
return lang;
}
//#endregion
//#region src/node/demo/vue.ts
function vueEmbed(app, md, env, { url, title, desc, codeSetting = "", expanded = false }) {
const filepath$1 = findFile(app, env, url);
const code = readFileSync(filepath$1);
if (code === false) {
logger$1.warn("demo-vue", `Cannot read vue demo file: ${colors.gray(filepath$1)}\n at: ${colors.gray(env.filePathRelative || "")}`);
return "";
}
const basename = path$1.basename(filepath$1).replace(/-|\./g, "_");
const ext = path$1.extname(filepath$1).slice(1);
const name = `Demo${basename[0].toUpperCase()}${basename.slice(1)}`;
const demo = {
type: "vue",
export: name,
path: filepath$1
};
env.demoFiles ??= [];
if (!env.demoFiles.some((d) => d.path === filepath$1)) {
env.demoFiles.push(demo);
insertSetupScript(demo, env);
}
return `<VPDemoBasic${stringifyAttrs({
type: "vue",
title,
desc,
expanded
})}>
<${name} />
<template #code>
${md.render(`\`\`\`${ext}${codeSetting}\n${code}\n\`\`\``, {})}
</template>
</VPDemoBasic>`;
}
const target = "md-power/demo/vue";
const vueContainerRender = {
before: (app, md, env, meta, codeMap) => {
const { url, title, desc, expanded = false } = meta;
const componentName = `DemoContainer${url}`;
const prefix = (env.filePathRelative || "").replace(/\.md$/, "").replace(/\//g, "-");
env.demoFiles ??= [];
const output = app.dir.temp(path$1.join(target, `${prefix}-${componentName}`));
if (codeMap.vue || codeMap.js || codeMap.ts) {
let scriptOutput = output;
let content = "";
if (codeMap.vue) {
scriptOutput += ".vue";
content = transformStyle(codeMap.vue);
} else if (codeMap.ts) {
scriptOutput += ".ts";
content = codeMap.ts;
} else if (codeMap.js) {
scriptOutput += ".js";
content = codeMap.js;
}
content = transformImports(content, env.filePath || "");
const script = {
type: "vue",
export: componentName,
path: scriptOutput,
gitignore: true
};
writeFileSync(scriptOutput, content);
if (!env.demoFiles.some((d) => d.path === scriptOutput)) {
env.demoFiles.push(script);
insertSetupScript(script, env);
}
}
if (codeMap.css || codeMap.scss || codeMap.less || codeMap.stylus) {
let styleOutput = output;
let content = "";
if (codeMap.css) {
styleOutput += ".css";
content = codeMap.css;
} else if (codeMap.scss) {
styleOutput += ".scss";
content = codeMap.scss;
} else if (codeMap.less) {
styleOutput += ".less";
content = codeMap.less;
} else if (codeMap.stylus) {
styleOutput += ".styl";
content = codeMap.stylus;
}
writeFileSync(styleOutput, content);
const style = {
type: "css",
path: styleOutput,
gitignore: true
};
if (!env.demoFiles.some((d) => d.path === styleOutput)) {
env.demoFiles.push(style);
insertSetupScript(style, env);
}
}
return `<VPDemoBasic${stringifyAttrs({
type: "vue",
title,
desc,
expanded
})}>
<${componentName} />
<template #code>\n`;
},
after: () => "</template></VPDemoBasic>"
};
const IMPORT_RE = /import\s+(?:\w+\s+from\s+)?['"]([^'"]+)['"]/g;
const STYLE_RE = /<style.*?>/;
function transformImports(code, filepath$1) {
return code.replace(IMPORT_RE, (matched, url) => {
if (url.startsWith("./") || url.startsWith("../")) return matched.replace(url, `${path$1.resolve(path$1.dirname(filepath$1), url)}`);
return matched;
});
}
function transformStyle(code) {
return code.replace(STYLE_RE, (matched) => {
if (matched.includes("scoped")) return matched;
return matched.replace("<style", "<style scoped");
});
}
//#endregion
//#region src/node/demo/demo.ts
const embedMap = {
vue: vueEmbed,
normal: normalEmbed,
markdown: markdownEmbed
};
/**
* 嵌入语法
* @[demo type info](url)
*/
function demoEmbed(app, md) {
createEmbedRuleBlock(md, {
type: "demo",
syntaxPattern: /^@\[demo(?:\s(vue|normal|markdown))?\s?(.*)\]\((.*)\)/,
meta: ([, type, info, url]) => ({
type: type || "normal",
url,
...resolveAttrs(info).attrs
}),
content: (meta, content, env) => {
const { url, type } = meta;
if (!url) {
logger$1.warn("demo-vue", `Invalid filepath: ${colors.gray(url)}`);
return content;
}
if (embedMap[type]) return embedMap[type](app, md, env, meta);
return content;
}
});
}
const INFO_RE = /(vue|normal|markdown)?\s?(.*)/;
const renderMap = {
vue: vueContainerRender,
normal: normalContainerRender,
markdown: markdownContainerRender
};
function demoContainer(app, md) {
let currentRender;
const render = (tokens, index, _, env) => {
const token = tokens[index];
if (token.nesting === 1) {
const meta = getContainerMeta(token.info);
meta.url = `${index}`;
currentRender = renderMap[meta.type];
return currentRender?.before(app, md, env, meta, parseCodeMapping(tokens, index, currentRender.token)) || "";
} else {
const res = currentRender?.after() || "";
currentRender = void 0;
return res;
}
};
md.use(container, "demo", { render });
}
function parseCodeMapping(tokens, index, cb) {
const codeMap = {};
for (let i = index + 1; !(tokens[i].nesting === -1 && tokens[i].type === "container_demo_close"); ++i) {
const token = tokens[i];
if (token.type === "fence") {
codeMap[normalizeAlias(token.info)] = token.content.trim();
cb?.(token, tokens, i);
}
}
return codeMap;
}
function getContainerMeta(info) {
const [, type, raw] = (info.trim().slice(4).trim() || "").match(INFO_RE) || [];
const { attrs: attrs$1 } = resolveAttrs(raw);
return {
url: "",
type: type || "normal",
...attrs$1
};
}
//#endregion
//#region src/node/demo/extendPage.ts
function extendsPageWithDemo(page) {
const demoFiles = page.markdownEnv.demoFiles ?? [];
page.deps.push(...demoFiles.filter(({ type }) => type === "markdown").map(({ path: path$3 }) => path$3));
(page.frontmatter.gitInclude ??= []).push(...demoFiles.filter(({ gitignore }) => !gitignore).map(({ path: path$3 }) => path$3));
}
//#endregion
//#region src/node/demo/index.ts
function demoPlugin(app, md) {
createDemoRender();
demoEmbed(app, md);
demoContainer(app, md);
}
//#endregion
//#region src/node/embed/audio/reader.ts
const audioReader = (state, silent) => {
const max = state.posMax;
let start = state.pos;
let href = "";
if (state.src.slice(start, start + 13) !== "@[audioReader") return false;
if (max - start < 17) return false;
const labelStart = state.pos + 13;
const labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, true);
if (labelEnd < 0) return false;
let pos = labelEnd + 1;
if (pos < max && state.src.charCodeAt(pos) === 40) {
pos++;
const code = state.src.charCodeAt(pos);
if (code === 10 || code === 32) return false;
start = pos;
const res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);
if (res.ok) {
href = state.md.normalizeLink(res.str);
if (state.md.validateLink(href)) pos = res.pos;
else href = "";
}
if (pos >= max || state.src.charCodeAt(pos) !== 41) return false;
} else return false;
/* istanbul ignore else -- @preserve */
if (!silent) {
state.pos = labelStart;
state.posMax = labelEnd;
const info = state.src.slice(labelStart, labelEnd).trim();
const { attrs: attrs$1 } = resolveAttrs(info);
const token = state.push("audio_reader", "AudioReader", 0);
token.info = info;
token.meta = {
src: href,
...attrs$1
};
}
state.pos = pos + 1;
state.posMax = max;
return true;
};
const audioReaderPlugin = (md) => {
md.renderer.rules.audio_reader = (tokens, idx) => {
const meta = tokens[idx].meta;
if (meta.startTime) meta.startTime = Number(meta.startTime);
if (meta.endTime) meta.endTime = Number(meta.endTime);
if (meta.volume) meta.volume = Number(meta.volume);
return `<AudioReader${stringifyAttrs(meta)} />`;
};
md.inline.ruler.before("link", "audio-reader", audioReader);
};
//#endregion
//#region src/node/utils/nanoid.ts
const nanoid = customAlphabet("abcdefghijklmnopqrstuvwxyz", 5);
//#endregion
//#region src/node/embed/caniuse.ts
const UNDERLINE_RE = /_+/g;
/**
* @example
* ```md
* @[caniuse](feature_name)
* ```
*/
const caniusePlugin = (md, { mode: defaultMode = "embed" } = {}) => {
createEmbedRuleBlock(md, {
type: "caniuse",
syntaxPattern: /^@\[caniuse\s*(embed|image)?(?:\{([0-9,\-]*)\})?\]\(([^)]*)\)/,
meta: ([, mode, versions = "", feature]) => ({
feature,
mode: mode || defaultMode,
versions
}),
content: (meta) => resolveCanIUse(meta)
});
};
/**
* @deprecated use caniuse plugin
*
* 兼容旧语法
* @example
* ```md
* :::caniuse <feature_name>
* :::
* ```
*/
function legacyCaniuse(md, { mode = "embed" } = {}) {
const modeMap = ["image", "embed"];
const isMode = (mode$1) => modeMap.includes(mode$1);
mode = isMode(mode) ? mode : modeMap[0];
createContainerPlugin(md, "caniuse", {
before: (info) => {
const feature = info.split(/\s+/)[0];
const versions = info.match(/\{(.*)\}/)?.[1] || "";
return feature ? resolveCanIUse({
feature,
mode,
versions
}) : "";
},
after: () => ""
});
}
function resolveCanIUse({ feature, mode, versions }) {
if (!feature) return "";
if (mode === "image") {
const link = "https://caniuse.bitsofco.de/image/";
const alt = `Data on support for the ${feature} feature across the major browsers from caniuse.com`;
return `<ClientOnly><p><picture>
<source type="image/webp" srcset="${link}${feature}.webp">
<source type="image/png" srcset="${link}${feature}.png">
<img src="${link}${feature}.jpg" alt="${alt}" width="100%">
</picture></p></ClientOnly>`;
}
feature = feature.replace(UNDERLINE_RE, "_");
const { past, future } = resolveVersions(versions);
const meta = nanoid();
return `<CanIUseViewer${stringifyAttrs({
feature,
meta,
past,
future
})} />`;
}
function resolveVersions(versions) {
if (!versions) return {
past: 2,
future: 1
};
const list = versions.split(",").map((v) => Number(v.trim())).filter((v) => !Number.isNaN(v) && v >= -5 && v <= 3);
list.push(0);
const uniq = [...new Set(list)].sort((a, b) => b - a);
return {
future: uniq[0],
past: Math.abs(uniq[uniq.length - 1])
};
}
//#endregion
//#region src/node/embed/code/codepen.ts
const codepenPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "codepen",
syntaxPattern: /^@\[codepen([^\]]*)\]\(([^)]*)\)/,
meta: ([, info, source]) => {
const { width, height, title, tab: tab$1, preview, editable, theme } = resolveAttrs(info).attrs;
const [user, slash] = source.split("/");
return {
title: title || "Code Pen",
tab: tab$1 || "result",
width: width ? parseRect(width) : "100%",
height: height ? parseRect(height) : "400px",
user,
slash,
preview,
editable,
theme
};
},
content: (meta) => `<CodePenViewer${stringifyAttrs(meta)} />`
});
};
//#endregion
//#region src/node/embed/code/codeSandbox.ts
const codeSandboxPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "codesandbox",
syntaxPattern: /^@\[codesandbox(?:\s+(embed|button))?([^\]]*)\]\(([^)]*)\)/,
meta([, type, info, source]) {
const { attrs: attrs$1 } = resolveAttrs(info);
const [profile, filepath$1 = ""] = source.split("#");
const [user, id] = profile.includes("/") ? profile.split("/") : ["", profile];
return {
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : "500px",
user,
id,
title: attrs$1.title ?? "",
console: attrs$1.console ?? false,
navbar: attrs$1.navbar ?? true,
layout: attrs$1.layout ?? "",
type: type || "embed",
filepath: filepath$1
};
},
content: (meta) => `<CodeSandboxViewer${stringifyAttrs(meta)} />`
});
};
//#endregion
//#region src/node/embed/code/jsfiddle.ts
const jsfiddlePlugin = (md) => {
createEmbedRuleBlock(md, {
type: "jsfiddle",
syntaxPattern: /^@\[jsfiddle([^\]]*)\]\(([^)]*)\)/,
meta([, info, source]) {
const { width, height, title, tab: tab$1, theme } = resolveAttrs(info).attrs;
return {
width: width ? parseRect(width) : "100%",
height: height ? parseRect(height) : "400px",
source,
title: title || "JS Fiddle",
tab: tab$1?.replace(/\s+/g, "") || "js,css,html,result",
theme
};
},
content: (meta) => `<JSFiddleViewer${stringifyAttrs(meta)} />`
});
};
//#endregion
//#region src/node/embed/code/replit.ts
const replitPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "replit",
syntaxPattern: /^@\[replit([^\]]*)\]\(([^)]*)\)/,
meta: ([, info = "", source = ""]) => {
const { attrs: attrs$1 } = resolveAttrs(info);
return {
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : "450px",
source: source.startsWith("@") ? source : `@${source}`,
title: attrs$1.title,
theme: attrs$1.theme || ""
};
},
content: (meta) => `<ReplitViewer${stringifyAttrs(meta)} />`
});
};
//#endregion
//#region src/node/embed/pdf.ts
const pdfPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "pdf",
syntaxPattern: /^@\[pdf(?:\s+(\d+))?([^\]]*)\]\(([^)]*)\)/,
meta([, page, info, src]) {
const { attrs: attrs$1 } = resolveAttrs(info);
return {
src,
page: +page || 1,
noToolbar: Boolean(attrs$1.noToolbar ?? false),
zoom: +attrs$1.zoom || 50,
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : "",
ratio: attrs$1.ratio ? parseRect(attrs$1.ratio) : "",
title: path.basename(src || "")
};
},
content: (meta) => `<PDFViewer${stringifyAttrs(meta)} />`
});
};
//#endregion
//#region src/node/embed/video/acfun.ts
const AC_FUN_LINK = "https://www.acfun.cn/player";
const acfunPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "acfun",
name: "video_acfun",
syntaxPattern: /^@\[acfun([^\]]*)\]\(([^)]*)\)/,
meta([, info, id]) {
const { attrs: attrs$1 } = resolveAttrs(info);
return {
id,
title: attrs$1.title || "AcFun",
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
ratio: attrs$1.ratio ?? "16:10"
};
},
content(meta) {
const { id, width, height, ratio, title } = meta;
const src = `${AC_FUN_LINK}/${id}`;
return `<VPVideoEmbed${stringifyAttrs({
src,
width,
height,
ratio,
title,
type: "acfun"
})} />`;
}
});
};
//#endregion
//#region src/node/embed/video/artPlayer.ts
const installed = {
dashjs: isPackageExists("dashjs"),
hlsjs: isPackageExists("hls.js"),
mpegtsjs: isPackageExists("mpegts.js")
};
const SUPPORTED_VIDEO_TYPES = [
"mp4",
"mp3",
"webm",
"ogg",
"mpd",
"dash",
"m3u8",
"hls",
"ts",
"flv"
];
const artPlayerPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "artPlayer",
name: "video_artPlayer",
syntaxPattern: /^@\[artPlayer([^\]]*)\]\(([^)]*)\)/,
meta([, info, source]) {
const { attrs: attrs$1 } = resolveAttrs(info);
const url = source.trim();
checkSupportType(attrs$1.type ?? url.split(".").pop());
return {
url,
type: attrs$1.type,
autoplay: attrs$1.autoplay ?? false,
muted: attrs$1.muted ?? attrs$1.autoplay ?? false,
autoMini: attrs$1.autoMini ?? false,
loop: attrs$1.loop ?? false,
volume: typeof attrs$1.volume !== "undefined" ? Number(attrs$1.volume) : .75,
poster: attrs$1.poster,
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
ratio: attrs$1.ratio ? parseRect(`${attrs$1.ratio}`) : void 0
};
},
content({ url,...meta }) {
meta.muted = meta.muted || meta.autoplay;
return `<ArtPlayer src="${url}" fullscreen flip playback-rate aspect-ratio setting pip${stringifyAttrs(meta)}/>`;
}
});
};
function checkSupportType(type) {
if (!type) return;
/* istanbul ignore if -- @preserve */
if (SUPPORTED_VIDEO_TYPES.includes(type)) {
let name = "";
switch (type.toLowerCase()) {
case "m3u8":
case "hls":
name = !installed.hlsjs ? "hls.js" : "";
break;
case "flv":
case "ts":
name = !installed.mpegtsjs ? "mpegts.js" : "";
break;
case "mpd":
case "dash":
name = !installed.dashjs ? "dashjs" : "";
break;
}
/* istanbul ignore if -- @preserve */
if (name) logger$1.warn("artPlayer", `${colors.cyan(name)} is not installed, please install it via npm or yarn or pnpm`);
} else
/* istanbul ignore next -- @preserve */
logger$1.warn("artPlayer", `unsupported video type: ${colors.cyan(type)}`);
}
//#endregion
//#region src/node/utils/timeToSeconds.ts
function timeToSeconds(time) {
if (!time) return 0;
if (Number.parseFloat(time) === Number(time)) return Number(time);
const [s, m, h = 0] = time.split(/\s*:\s*/).reverse().map((n) => Number(n) || 0);
return s + m * 60 + h * 3600;
}
//#endregion
//#region src/node/embed/video/bilibili.ts
const BILIBILI_LINK = "https://player.bilibili.com/player.html";
const bilibiliPlugin = (md) => {
createEmbedRuleBlock(md, {
type: "bilibili",
name: "video_bilibili",
syntaxPattern: /^@\[bilibili(?:\s+p(\d+))?([^\]]*)\]\(([^)]*)\)/,
meta([, page, info, source]) {
const { attrs: attrs$1 } = resolveAttrs(info);
const ids = source.trim().split(/\s+/);
const bvid = ids.find((id) => id.startsWith("BV"));
const [aid, cid] = ids.filter((id) => !id.startsWith("BV"));
return {
page: +page,
bvid,
aid,
cid,
autoplay: attrs$1.autoplay ?? false,
time: timeToSeconds(attrs$1.time),
title: attrs$1.title || "Bilibili",
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
ratio: attrs$1.ratio
};
},
content(meta) {
const params = new URLSearchParams();
if (meta.bvid) params.set("bvid", meta.bvid);
if (meta.aid) params.set("aid", meta.aid);
if (meta.cid) params.set("cid", meta.cid);
if (meta.page) params.set("p", meta.page.toString());
if (meta.time) params.set("t", meta.time.toString());
params.set("autoplay", meta.autoplay ? "1" : "0");
params.set("high_quality", "1");
const src = `${BILIBILI_LINK}?${params.toString()}`;
const { width, height, ratio, title } = meta;
return `<VPVideoEmbed${stringifyAttrs({
src,
width,
height,
ratio,
title,
type: "bilibili"
})} />`;
}
});
};
//#endregion
//#region src/node/embed/video/youtube.ts
const YOUTUBE_LINK = "https://www.youtube.com/embed/";
const youtubePlugin = (md) => {
createEmbedRuleBlock(md, {
type: "youtube",
name: "video_youtube",
syntaxPattern: /^@\[youtube([^\]]*)\]\(([^)]*)\)/,
meta([, info, id]) {
const { attrs: attrs$1 } = resolveAttrs(info);
return {
id,
autoplay: attrs$1.autoplay ?? false,
loop: attrs$1.loop ?? false,
start: timeToSeconds(attrs$1.start),
end: timeToSeconds(attrs$1.end),
title: attrs$1.title || "YouTube",
width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
ratio: attrs$1.ratio
};
},
content(meta) {
const params = new URLSearchParams();
if (meta.autoplay) params.set("autoplay", "1");
if (meta.loop) params.set("loop", "1");
if (meta.start) params.set("start", meta.start.toString());
if (meta.end) params.set("end", meta.end.toString());
const src = `${YOUTUBE_LINK}/${meta.id}?${params.toString()}`;
const { width, height, ratio, title } = meta;
return `<VPVideoEmbed${stringifyAttrs({
src,
width,
height,
ratio,
title,
type: "youtube"
})} />`;
}
});
};
//#endregion
//#region src/node/embed/index.ts
function embedSyntaxPlugin(md, options) {
if (options.caniuse) {
const caniuse = options.caniuse === true ? {} : options.caniuse;
md.use(caniusePlugin, caniuse);
legacyCaniuse(md, caniuse);
}
if (options.pdf) md.use(pdfPlugin);
if (options.acfun) md.use(acfunPlugin);
if (options.bilibili) md.use(bilibiliPlugin);
if (options.youtube) md.use(youtubePlugin);
if (options.artPlayer) md.use(artPlayerPlugin);
if (options.audioReader) md.use(audioReaderPlugin);
if (options.codepen) md.use(codepenPlugin);
if (options.replit) md.use(replitPlugin);
if (options.codeSandbox) md.use(codeSandboxPlugin);
if (options.jsfiddle) md.use(jsfiddlePlugin);
}
//#endregion
//#region src/node/enhance/docsTitle.ts
const REG_HEADING = /^#\s*?([^#\s].*)?\n/;
/**
* 适配 主题的 文档页面标题,将 markdown 中的 h1 标题提取到 frontmatter 中,并将其删除,
* 以避免重复显示标题。
*/
function docsTitlePlugin(md) {
const render = md.render;
md.render = (source, env) => {
if (!env.filePathRelative) return render(source, env);
let { matter, content } = parseSource(source.trim());
let title = "";
content = content.trim().replace(REG_HEADING, (_, match) => {
title = match.trim();
return "";
});
source = `${matter}\n${content}`;
const result = render(source, env);
if (title) {
env.frontmatter ??= {};
env.frontmatter.title ??= title;
}
return result;
};
}
function parseSource(source) {
const char = "---";
if (!source.startsWith(char)) return {
matter: "",
content: source
};
else {
const end = source.indexOf(`\n${char}`);
const len = 4;
return {
matter: source.slice(0, end + len),
content: source.slice(end + len)
};
}
}
//#endregion
//#region src/node/enhance/links.ts
function linksPlugin(md) {
const externalAttrs = {
target: "_blank",
rel: "noopener noreferrer"
};
let hasOpenInternalLink = false;
const internalTag = "VPLink";
function handleLinkOpen(tokens, idx, env) {
hasOpenInternalLink = false;
const token = tokens[idx];
const hrefIndex = token.attrIndex("href");
/* istanbul ignore if -- @preserve */
if (hrefIndex < 0) return;
const hrefLink = token.attrs[hrefIndex][1];
if (isLinkWithProtocol(hrefLink)) {
Object.entries(externalAttrs).forEach(([key, val]) => {
token.attrSet(key, val);
});
return;
}
if (hrefLink[0] === "#") return;
hasOpenInternalLink = true;
token.tag = internalTag;
const matched = hrefLink.match(/^([^#?]*?(?:\/|\.md|\.html))([#?].*)?$/);
if (matched) {
const rawPath = matched[1];
const { absolutePath, relativePath } = resolvePaths(rawPath, env.base || "/", env.filePathRelative ?? null);
(env.links ??= []).push({
raw: rawPath,
absolute: absolutePath,
relative: relativePath
});
}
}
md.renderer.rules.link_open = (tokens, idx, opts, env, self) => {
handleLinkOpen(tokens, idx, env);
return self.renderToken(tokens, idx, opts);
};
md.renderer.rules.link_close = (tokens, idx, opts, _env, self) => {
if (hasOpenInternalLink) {
hasOpenInternalLink = false;
tokens[idx].tag = internalTag;
}
return self.renderToken(tokens, idx, opts);
};
}
/**
* Resolve relative and absolute paths according to the `base` and `filePathRelative`
*/
function resolvePaths(rawPath, base, filePathRelative) {
let absolutePath;
let relativePath;
if (rawPath.startsWith("/")) if (rawPath.endsWith(".md")) {
absolutePath = path$2.join(base, rawPath);
relativePath = removeLeadingSlash$1(rawPath);
} else {
absolutePath = rawPath;
relativePath = path$2.relative(base, absolutePath);
}
else if (filePathRelative) {
relativePath = path$2.join(path$2.dirname(encodeURI(filePathRelative)), rawPath);
absolutePath = path$2.join(base, relativePath);
} else {
relativePath = rawPath.replace(/^(?:\.\/)?(.*)$/, "$1");
absolutePath = null;
}
return {
absolutePath,
relativePath
};
}
//#endregion
//#region src/node/icon/createIconRule.ts
function createIconRule([l1, l2, r1, r2], deprecated) {
return (state, silent) => {
let found = false;
const max = state.posMax;
const start = state.pos;
if (state.src.charCodeAt(start) !== l1 || state.src.charCodeAt(start + 1) !== l2) return false;
const next = state.src.charCodeAt(start + 2);
if (next === 32 || next === 58) return false;
/* istanbul ignore if -- @preserve */
if (silent) return false;
if (max - start < 5) return false;
state.pos = start + 2;
while (state.pos < max) {
if (state.src.charCodeAt(state.pos) === r1 && state.src.charCodeAt(state.pos + 1) === r2) {
found = true;
break;
}
state.md.inline.skipToken(state);
}
if (!found || start + 2 === state.pos || state.src.charCodeAt(state.pos - 1) === 32) {
state.pos = start;
return false;
}
const info = state.src.slice(start + 2, state.pos);
state.posMax = state.pos;
state.pos = start + 2;
const icon = state.push("icon", "i", 0);
icon.markup = "::";
icon.content = info;
icon.meta = { deprecated };
state.pos = state.posMax + 2;
state.posMax = max;
return true;
};
}
//#endregion
//#region src/node/icon/resolveIcon.ts
const RE_SIZE = /(?<=\s|^)=(.+?)(?:\s|$)/;
const RE_COLOR = /(?<=\s|^)\/(.+?)(?:\s|$)/;
const RE_PROVIDER = /^(iconify|iconfont|fontawesome)\s+/;
const RE_EXTRA_KEY = /(?:^|-)\d-/g;
function resolveIcon(content, options) {
let size = options.size;
let color = options.color;
let provider = options.provider || "iconify";
content = content.replace(RE_PROVIDER, (_, p) => {
provider = p;
return "";
}).replace(RE_SIZE, (_, s) => {
size = s;
return "";
}).replace(RE_COLOR, (_, c) => {
color = c;
return "";
}).trim();
const index = content.indexOf(" ");
const name = index === -1 ? content : content.slice(0, index);
const extra = index === -1 ? "" : content.slice(index + 1);
const props = {
provider,
size,
color,
name
};
if (!extra) return props;
const { attrs: attrs$1 } = resolveAttrs(extra);
const info = [];
const excludes = [];
for (const key in attrs$1) if (attrs$1[key] === true) {
excludes.push(key);
info.push(kebabCase(key).replace(RE_EXTRA_KEY, (m) => `${m.slice(0, -1)}`));
}
return {
...props,
extra: info.join(" "),
...omit(attrs$1, excludes)
};
}
//#endregion
//#region src/node/icon/icon.ts
function iconRender(content, options) {
const icon = resolveIcon(content, options);
return `<VPIcon${stringifyAttrs(icon)} />`;
}
const iconPlugin = (md, options = {}) => {
/**
* ::collect:icon_name =size /color::
*/
md.inline.ruler.before("link", "icon", createIconRule([
58,
58,
58,
58
]));
/**
* :[collect:icon_name size/color]:
* @deprecated
*/
md.inline.ruler.before("link", "icon_deprecated", createIconRule([
58,
91,
93,
58
], true));
md.renderer.rules.icon = (tokens, idx, _, env) => {
const { content, meta } = tokens[idx];
let icon = content;
/* istanbul ignore if -- @preserve */
if (meta.deprecated) {
const [name, opt = ""] = content.split(" ");
const [size, color] = opt.trim().split("/");
icon = `${name}${size ? ` =${size}` : ""}${color ? ` /${color}` : ""}`;
logger$1.warn("icon", `The icon syntax of \`${colors.yellow(`:[${content}]:`)}\` is deprecated, please use \`${colors.green(`::${icon}::`)}\` instead. (${colors.gray(env.filePathRelative || env.filePath)})`);
}
return iconRender(icon, options);
};
};
//#endregion
//#region src/node/icon/prepareIcon.ts
function getFontAwesomeCDNLink(type) {
return `https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/js/${type}.min.js`;
}
function prepareIcon(imports, options = {}) {
const setupContent = [];
const assets = [];
if (options.provider === "iconfont") assets.push(...toArray(options.assets).map((asset) => normalizeAsset(asset)).filter(notNullish));
else if (options.provider === "fontawesome") assets.push(...toArray(options.assets || "fontawesome").map((asset) => {
if (asset === "fontawesome") return [
"solid",
"regular",
"fontawesome"
].map(getFontAwesomeCDNLink).map((asset$1) => normalizeAsset(asset$1, "fontawesome"));
if (asset === "fontawesome-with-brands") return normalizeAsset(getFontAwesomeCDNLink("brands"), "fontawesome");
return null;
}).flat().filter(notNullish));
let hasStyle = false;
let hasScript = false;
for (const asset of uniqueBy(assets, (a, b) => a.link === b.link)) if (asset.type === "style") {
hasStyle = true;
setupContent.push(`useStyleTag('@import url("${asset.link}");')`);
} else if (asset.type === "script") {
hasScript = true;
setupContent.push(asset.provide === "fontawesome" ? `useScriptTag("${asset.link}", () => {}, { attrs: { "data-auto-replace-svg": "nest" } })` : `useScriptTag("${asset.link}")`);
}
if (hasScript || hasStyle) {
const exports = [];
if (hasScript) exports.push("useScriptTag");
if (hasStyle) exports.push("useStyleTag");
imports.add(`import { ${exports.join(", ")} } from '@vueuse/core'`);
}
return setupContent.join("\n ");
}
function normalizeAsset(asset, provide) {
const link = normalizeLink(asset);
if (asset.endsWith(".js")) return {
type: "script",
link,
provide
};
if (asset.endsWith(".css")) return {
type: "style",
link,
provide
};
logger$1.error("icon", `Can not recognize icon link: "${asset}"`);
return null;
}
function normalizeLink(link) {
if (isLinkHttp$1(link) || isLinkAbsolute(link)) return link;
return `//${link}`;
}
//#endregion
//#region src/node/inline/abbr.ts
const abbrPlugin = (md) => {
const { arrayReplaceAt, escapeRE, lib } = md.utils;
const OTHER_CHARS = " \r\n$+<=>^`|~";
const UNICODE_PUNCTUATION_REGEXP = lib.ucmicro.P.source;
const UNICODE_SPACE_REGEXP = lib.ucmicro.Z.source;
const WORDING_REGEXP_TEXT = `${UNICODE_PUNCTUATION_REGEXP}|${UNICODE_SPACE_REGEXP}|[${OTHER_CHARS.split("").map(escapeRE).join("")}]`;
const abbrDefinition = (state, startLine, _endLine, silent) => {
let labelEnd = -1;
let pos = state.bMarks[startLine] + state.tShift[startLine];
const max = state.eMarks[startLine];
if (pos + 2 >= max || state.src.charAt(pos++) !== "*" || state.src.charAt(pos++) !== "[") return false;
const labelStart = pos;
while (pos < max) {
const ch = state.src.charAt(pos);
if (ch === "[") return false;
if (ch === "]") {
labelEnd = pos;
break;
}
if (ch === "\\") pos++;
pos++;
}
if (labelEnd < 0 || state.src.charAt(labelEnd + 1) !== ":") return false;
if (silent) return true;
const label = state.src.slice(labelStart, labelEnd).replace(/\\(.)/g, "$1");
const title = state.src.slice(labelEnd + 2, max).trim();
if (!label.length || !title.length) return false;
(state.env.abbreviations ??= {})[`:${label}`] ??= title;
state.line = startLine + 1;
return true;
};
const abbrReplace = (state) => {
const tokens = state.tokens;
const { abbreviations } = state.env;
if (!abbreviations) return;
const abbreviationsRegExpText = Object.keys(abbreviations).map((x) => x.substring(1)).sort((a, b) => b.length - a.length).map(escapeRE).join("|");
const regexpSimple = /* @__PURE__ */ new RegExp(`(?:${abbreviationsRegExpText})`);
const regExp = new RegExp(`(^|${WORDING_REGEXP_TEXT})(${abbreviationsRegExpText})($|${WORDING_REGEXP_TEXT})`, "g");
for (const token of tokens) {
if (token.type !== "inline") continue;
let children = token.children;
for (let index = children.length - 1; index >= 0; index--) {
const currentToken = children[index];
if (currentToken.type !== "text") continue;
const text = currentToken.content;
regExp.lastIndex = 0;
if (!regexpSimple.test(text)) continue;
const nodes = [];
let match;
let pos = 0;
while (match = regExp.exec(text)) {
const [, before, word, after] = match;
if (match.index > 0 || before.length > 0) {
const token$1 = new state.Token("text", "", 0);
token$1.content = text.slice(pos, match.index + before.length);
nodes.push(token$1);
}
const abbrToken = new state.Token("abbreviation", "Abbreviation", 0);
abbrToken.content = word;
abbrToken.info = abbreviations[`:${word}`];
nodes.push(abbrToken);
regExp.lastIndex -= after.length;
pos = regExp.lastIndex;
}
if (!nodes.length) continue;
if (pos < text.length) {
const token$1 = new state.Token("text", "", 0);
token$1.content = text.slice(pos);
nodes.push(token$1);
}
token.children = children = arrayReplaceAt(children, index, nodes);
}
}
};
md.block.ruler.before("reference", "abbr_definition", abbrDefinition, { alt: ["paragraph", "reference"] });
md.core.ruler.after("linkify", "abbr_replace", abbrReplace);
md.renderer.rules.abbreviation = (tokens, idx, _, env) => {
const { content, info } = tokens[idx];
const rendered = md.renderInline(info, cleanMarkdownEnv(env));
return `<Abbreviation aria-label="${rendered.replace(/<[^>]*>/g, "")}">${content}${info ? `<template #tooltip>${rendered}</template>` : ""}</Abbreviation>`;
};
};
//#endregion
//#region src/node/inline/annotation.ts
const annotationDef = (state, startLine, endLine, silent) => {
const start = state.bMarks[startLine] + state.tShift[startLine];
const max = state.eMarks[startLine];
if (start + 4 > max || state.src.charAt(start) !== "[" || state.src.charAt(start + 1) !== "+") return false;
let pos = start + 2;
while (pos < max) {
if (state.src.charAt(pos) === " ") return false;
if (state.src.charAt(pos) === "]") break;
pos++;
}
if (pos === start + 2 || pos + 1 >= max || state.src.charAt(++pos) !== ":") return false;
if (silent) return true;
pos++;
const data = state.env.annotations ??= {};
const label = state.src.slice(start + 2, pos - 2);
let annotation = state.src.slice(pos, max).trim();
let nextLine = startLine + 1;
while (nextLine < endLine) {
const nextStart = state.bMarks[nextLine] + state.tShift[nextLine];
const nextMax = state.eMarks[nextLine];
const source = state.src.slice(nextStart, nextMax).trim();
if (state.sCount[nextLine] < state.blkIndent + 2 && source !== "") break;
annotation += `\n${source}`;
nextLine++;
}
(data[`:${label}`] ??= {
sources: [],
rendered: []
}).sources.push(annotation);
state.line = nextLine;
return true;
};
const annotationRef = (state, silent) => {
const start = state.pos;
const max = state.posMax;
if (start + 3 > max || typeof state.env.annotations === "undefined" || state.src.charAt(start) !== "[" || state.src.charAt(start + 1) !== "+") return false;
let pos = start + 2;
while (pos < max) {
if (state.src.charAt(pos) === " " || state.src.charAt(pos) === "\n") return false;
if (state.src.charAt(pos) === "]") break;
pos++;
}
if (pos === start + 2 || pos >= max) return false;
pos++;
const label = state.src.slice(start + 2, pos - 1);
if ((state.env.annotations?.[`:${label}`]?.sources ?? []).length === 0) return false;
if (!silent) {
const refToken = state.push("annotation_ref", "", 0);
refToken.meta = { label };
}
state.pos = pos;
state.posMax = max;
return true;
};
const annotationPlugin = (md) => {
md.renderer.rules.annotation_ref = (tokens, idx, _, env) => {
const label = tokens[idx].meta.label;
const data = env.annotations[`:${label}`];
return `<Annotation label="${label}" :total="${data.sources.length}">${data.sources.map((source, i) => {
const annotation = data.rendered[i] ??= md.render(source, cleanMarkdownEnv(env, ["references"]));
return `<template #item-${i}>${annotation}</template>`;
}).join("")}</Annotation>`;
};
md.inline.ruler.before("image", "annotation_ref", annotationRef);
md.block.ruler.before("reference", "annotation", annotationDef, { alt: ["paragraph", "reference"] });
};
//#endregion
//#region src/node/inline/plot.ts
const plotDef = (state, silent) => {
let found = false;
const max = state.posMax;
const start = state.pos;
if (state.src.charCodeAt(start) !== 33 || state.src.charCodeAt(start + 1) !== 33) return false;
const next = state.src.charCodeAt(start + 2);
if (next === 32 || next === 33) return false;
/* istanbul ignore if -- @preserve */
if (silent) return false;
if (max - start < 5) return false;
state.pos = start + 2;
while (state.pos < max) {
if (state.src.charCodeAt(state.pos) === 33 && state.src.charCodeAt(state.pos + 1) === 33) {
found = true;
break;
}
state.md.inline.skipToken(state);
}
if (!found || start + 2 === state.pos || state.src.charCodeAt(state.pos - 1) === 32) {
state.pos = start;
return false;
}
const content = state.src.slice(start + 2, state.pos);
state.posMax = state.pos;
state.pos = start + 2;
const openToken = state.push("plot_inline_open", "Plot", 1);
openToken.markup = "!!";
openToken.content = content;
const contentToken = state.push("text", "", 0);
contentToken.content = content;
const closeToken = state.push("plot_inline_close", "Plot", -1);
closeToken.markup = "!!";
state.pos = state.posMax + 2;
state.posMax = max;
return true;
};
const plotPlugin = (md) => {
md.inline.ruler.before("emphasis", "plot", plotDef);
};
//#endregion
//#region src/node/inline/index.ts
function inlineSyntaxPlugin(md, options) {
md.use(attrs);
md.use(mark);
md.use(sub);
md.use(sup);
md.use(footnote);
md.use(tasklist);
if (options.annotation)
/**
* xxx [+foo] xxx
*
* [+foo]: xxx
*/
md.use(annotationPlugin);
if (options.abbr)
/**
* a HTML element
*
* [HTML]: A HTML element description
*/
md.use(abbrPlugin);
if (options.plot === true || isPlainObject(options.plot)) md.use(plotPlugin);
}
//#endregion
//#region src/node/prepareConfigFile.ts
const { url: filepath } = import.meta;
const __dirname = getDirname(filepath);
const CLIENT_FOLDER = ensureEndingSlash(path.resolve(__dirname, "../client"));
async function prepareConfigFile(app, options) {
const imports = /* @__PURE__ */ new Set();
const enhances = /* @__PURE__ */ new Set();
imports.add(`import Tabs from '${CLIENT_FOLDER}components/Tabs.vue'`);
enhances.add(`app.component('Tabs', Tabs)`);
imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`);
enhances.add(`app.component('CodeTabs', CodeTabs)`);
if (options.pdf) {
imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`);
enhances.add(`app.component('PDFViewer', PDFViewer)`);
}
if (options.acfun || options.bilibili || options.youtube) {
imports.add(`import VPVideoEmbed from '${CLIENT_FOLDER}components/VPVideoEmbed.vue'`);
enhances.add(`app.component('VPVideoEmbed', VPVideoEmbed)`);
}
if (options.codepen) {
imports.add(`import CodePen from '${CLIENT_FOLDER}components/CodePen.vue'`);
enhances.add(`app.component('CodePenViewer', CodePen)`);
}
if (options.jsfiddle) {
imports.add(`import JSFiddle from '${CLIENT_FOLDER}components/JsFiddle.vue'`);
enhances.add(`app.component('JSFiddleViewer', JSFiddle)`);
}
if (options.replit) {
imports.add(`import Replit from '${CLIENT_FOLDER}components/Replit.vue'`);
enhances.add(`app.component('ReplitViewer', Replit)`);
}
if (options.codeSandbox) {
imports.add(`import CodeSandbox from '${CLIENT_FOLDER}components/CodeSandbox.vue'`);
enhances.add(`app.component('CodeSandboxViewer', CodeSandbox)`);
}
if (options.plot) {
imports.add(`import Plot from '${CLIENT_FOLDER}components/Plot.vue'`);
enhances.add(`app.component('Plot', Plot)`);
}
if (options.repl) {
imports.add(`import CodeRepl from '${CLIENT_FOLDER}components/CodeRepl.vue'`);
enhances.add(`app.component('CodeRepl', CodeRepl)`);
}
if (options.caniuse) {
imports.add(`import CanIUse from '${CLIENT_FOLDER}components/CanIUse.vue'`);
enhances.add(`app.component('CanIUseViewer', CanIUse)`);
}
if (options.fileTree || options.codeTree) {
imports.add(`import FileTreeNode from '${CLIENT_FOLDER}components/FileTreeNode.vue'`);
enhances.add(`app.component('FileTreeNode', FileTreeNode)`);
}
if (options.codeTree) {
imports.add(`import VPCodeTree from '${CLIENT_FOLDER}components/VPCodeTree.vue'`);
enhances.add(`app.component('VPCodeTree', VPCodeTree)`);
}
if (options.artPlayer) {
imports.add(`import ArtPlayer from '${CLIENT_FOLDER}components/ArtPlayer.vue'`);
enhances.add(`app.component('ArtPlayer', ArtPlayer)`);
}
if (options.audioReader) {
imports.add(`import AudioReader from '${CLIENT_FOLDER}components/AudioReader.vue'`);
enhances.add(`app.component('AudioReader', AudioReader)`);
}
if (options.demo) {
imports.add(`import VPDemoBasic from '${CLIENT_FOLDER}components/VPDemoBasic.vue'`);
imports.add(`import VPDemoNormal from '${CLIENT_FOLDER}components/VPDemoNormal.vue'`);
enhances.add(`app.component('VPDemoBasic', VPDemoBasic)`);
enhances.add(`app.component('VPDemoNormal', VPDemoNormal)`);
}
if (options.annotation) {
imports.add(`import Annotation from '${CLIENT_FOLDER}components/Annotation.vue'`);
enhances.add(`app.component('Annotation', Annotation)`);
}
if (options.abbr) {
imports.add(`import Abbreviation from '${CLIENT_FOLDER}components/Abbreviation.vue'`);
enhances.add(`app.component('Abbreviation', Abbreviation)`);
}
if (options.timeline) {
imports.add(`import VPTimeline from '${CLIENT_FOLDER}components/VPTimeline.vue'`);
imports.add(`import VPTimelineItem from '${CLIENT_FOLDER}components/VPTimelineItem.vue'`);
enhances.add(`app.component('VPTimeline', VPTimeline)`);
enhances.add(`app.component('VPTimelineItem', VPTimelineItem)`);
}
if (options.collapse) {
imports.add(`import VPCollapse from '${CLIENT_FOLDER}components/VPCollapse.vue'`);
imports.add(`import VPCollapseItem from '${CLIENT_FOLDER}components/VPCollapseItem.vue'`);
enhances.add(`app.component('VPCollapse', VPCollapse)`);
enhances.add(`app.component('VPCollapseItem', VPCollapseItem)`);
}
if (options.chat) imports.add(`import '${CLIENT_FOLDER}styles/chat.css'`);
if (options.field) {
imports.add(`import VPField from '${CLIENT_FOLDER}components/VPField.vue'`);
enhances.add(`app.component('VPField', VPField)`);
}
if (options.table) {
imports.add(`import VPTable from '${CLIENT_FOLDER}components/VPTable.vue'`);
enhances.add(`app.component('VPTable', VPTable)`);
}
const setupIcon = prepareIcon(imports, options.icon);
return app.writeTemp("md-power/config.js", `\
import { defineClientConfig } from 'vuepress/client'
${Array.from(imports.values()).join("\n")}
import '${CLIENT_FOLDER}styles/index.css'
export default defineClientConfig({
enhance({ router, app }) {
${Array.from(enhances.values()).map((item) => ` ${item}`).join("\n")}
},
setup() {
${setupIcon}
}
})
`);
}
//#endregion
//#region src/node/provideData.ts
function provideData(options) {
const mardownOptions = {
plot: options.plot,
pdf: options.pdf
};
const icon = options.icon ?? { provider: "iconify" };
return {
__MD_POWER_INJECT_OPTIONS__: mardownOptions,
__MD_POWER_DASHJS_INSTALLED__: isPackageExists("dashjs"),
__MD_POWER_HLSJS_INSTALLED__: isPackageExists("hls.js"),
__MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists("mpegts.js"),
__MD_POWER_ICON_PROVIDER__: icon.provider || "iconify",
__MD_POWER_ICON_PREFIX__: icon.prefix || ""
};
}
//#endregion
//#region src/node/plugin.ts
function markdownPowerPlugin(options = {}) {
return {
name: "vuepress-plugin-md-power",
clientConfigFile: (app) => prepareConfigFile(app, options),
define: provideData(options),
extendsBundlerOptions(bundlerOptions, app) {
if (options.repl) {
addViteOptimizeDepsInclude(bundlerOptions, app, [
"shiki/core",
"shiki/wasm",
"shiki/engine/oniguruma"
]);
if (options.repl.python) addViteOptimizeDepsInclude(bundlerOptions, app, ["pyodide"]);
}
if (options.artPlayer) addViteOptimizeDepsInclude(bundlerOptions, app, [
"artplayer",
"dashjs",
"hls.js",
"mpegts.js/dist/mpegts.js"
]);
},
extendsMarkdown: async (md, app) => {
linksPlugin(md);
docsTitlePlugin(md);
embedSyntaxPlugin(md, options);
inlineSyntaxPlugin(md, options);
iconPlugin(md, options.icon ?? (isPlainObject$1(options.icons) ? options.icons : {}));
if (options.demo) demoPlugin(app, md);
await containerPlugin(app, md, options);
await imageSizePlugin(app, md, options.imageSize);
},
onPrepared: async () => {
if (options.demo) await waitDemoRender();
},
onWatched(app, watchers) {
if (options.demo) demoWatcher(app, watchers);
},
extendsPage: (page) => {
if (options.demo) extendsPageWithDemo(page);
if (options.codeTree) extendsPageWithCodeTree(page);
}
};
}
//#endregion
export { createCodeTabIconGetter, markdownPowerPlugin, resolveImageSize };