chore: improve plugin-md-power code comments
This commit is contained in:
parent
552f0f5c32
commit
77856e36c5
@ -5,18 +5,63 @@ import { http } from '../utils/http.js'
|
|||||||
import { sleep } from '../utils/sleep.js'
|
import { sleep } from '../utils/sleep.js'
|
||||||
import { rustExecute } from './rustRepl.js'
|
import { rustExecute } from './rustRepl.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS selectors for nodes to ignore when extracting code.
|
||||||
|
*
|
||||||
|
* 提取代码时要忽略的节点的 CSS 选择器。
|
||||||
|
*/
|
||||||
const ignoredNodes = ['.diff.remove', '.vp-copy-ignore']
|
const ignoredNodes = ['.diff.remove', '.vp-copy-ignore']
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression for matching language class.
|
||||||
|
*
|
||||||
|
* 匹配语言类的正则表达式。
|
||||||
|
*/
|
||||||
const RE_LANGUAGE = /language-(\w+)/
|
const RE_LANGUAGE = /language-(\w+)/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API endpoints for code execution backends.
|
||||||
|
*
|
||||||
|
* 代码执行后端的 API 端点。
|
||||||
|
*/
|
||||||
const api = {
|
const api = {
|
||||||
go: 'https://api.pengzhanbo.cn/repl/golang/run',
|
go: 'https://api.pengzhanbo.cn/repl/golang/run',
|
||||||
kotlin: 'https://api.pengzhanbo.cn/repl/kotlin/run',
|
kotlin: 'https://api.pengzhanbo.cn/repl/kotlin/run',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pyodide instance for Python execution.
|
||||||
|
*
|
||||||
|
* 用于 Python 执行的 Pyodide 实例。
|
||||||
|
*/
|
||||||
let pyodide: PyodideInterface | null = null
|
let pyodide: PyodideInterface | null = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported languages for code execution.
|
||||||
|
*
|
||||||
|
* 支持代码执行的语言。
|
||||||
|
*/
|
||||||
type Lang = 'kotlin' | 'go' | 'rust' | 'python'
|
type Lang = 'kotlin' | 'go' | 'rust' | 'python'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function type for code execution.
|
||||||
|
*
|
||||||
|
* 代码执行的函数类型。
|
||||||
|
*/
|
||||||
type ExecuteFn = (code: string) => Promise<any>
|
type ExecuteFn = (code: string) => Promise<any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of language to execution function.
|
||||||
|
*
|
||||||
|
* 语言到执行函数的映射。
|
||||||
|
*/
|
||||||
type ExecuteMap = Record<Lang, ExecuteFn>
|
type ExecuteMap = Record<Lang, ExecuteFn>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language alias mapping.
|
||||||
|
*
|
||||||
|
* 语言别名映射。
|
||||||
|
*/
|
||||||
const langAlias: Record<string, string> = {
|
const langAlias: Record<string, string> = {
|
||||||
kt: 'kotlin',
|
kt: 'kotlin',
|
||||||
kotlin: 'kotlin',
|
kotlin: 'kotlin',
|
||||||
@ -27,12 +72,33 @@ const langAlias: Record<string, string> = {
|
|||||||
python: 'python',
|
python: 'python',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of supported languages.
|
||||||
|
*
|
||||||
|
* 支持的语言列表。
|
||||||
|
*/
|
||||||
const supportLang: Lang[] = ['kotlin', 'go', 'rust', 'python']
|
const supportLang: Lang[] = ['kotlin', 'go', 'rust', 'python']
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve language name from alias.
|
||||||
|
*
|
||||||
|
* 从别名解析语言名称。
|
||||||
|
*
|
||||||
|
* @param lang - Language or alias / 语言或别名
|
||||||
|
* @returns Resolved language name / 解析后的语言名称
|
||||||
|
*/
|
||||||
function resolveLang(lang?: string) {
|
function resolveLang(lang?: string) {
|
||||||
return lang ? langAlias[lang] || lang : ''
|
return lang ? langAlias[lang] || lang : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve code content from HTML element, ignoring specified nodes.
|
||||||
|
*
|
||||||
|
* 从 HTML 元素解析代码内容,忽略指定的节点。
|
||||||
|
*
|
||||||
|
* @param el - HTML element / HTML 元素
|
||||||
|
* @returns Code content / 代码内容
|
||||||
|
*/
|
||||||
export function resolveCode(el: HTMLElement): string {
|
export function resolveCode(el: HTMLElement): string {
|
||||||
const clone = el.cloneNode(true) as HTMLElement
|
const clone = el.cloneNode(true) as HTMLElement
|
||||||
clone
|
clone
|
||||||
@ -42,6 +108,14 @@ export function resolveCode(el: HTMLElement): string {
|
|||||||
return clone.textContent || ''
|
return clone.textContent || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve code information from HTML element.
|
||||||
|
*
|
||||||
|
* 从 HTML 元素解析代码信息。
|
||||||
|
*
|
||||||
|
* @param el - HTML element / HTML 元素
|
||||||
|
* @returns Object with language and code / 包含语言和代码的对象
|
||||||
|
*/
|
||||||
export function resolveCodeInfo(el: HTMLDivElement): {
|
export function resolveCodeInfo(el: HTMLDivElement): {
|
||||||
lang: Lang
|
lang: Lang
|
||||||
code: string
|
code: string
|
||||||
@ -57,19 +131,55 @@ export function resolveCodeInfo(el: HTMLDivElement): {
|
|||||||
return { lang: resolveLang(lang) as Lang, code }
|
return { lang: resolveLang(lang) as Lang, code }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result interface for useCodeRepl composable.
|
||||||
|
*
|
||||||
|
* useCodeRepl 组合式函数的结果接口。
|
||||||
|
*/
|
||||||
interface UseCodeReplResult {
|
interface UseCodeReplResult {
|
||||||
|
/** Current language / 当前语言 */
|
||||||
lang: Ref<Lang | undefined>
|
lang: Ref<Lang | undefined>
|
||||||
|
/** Whether the code is loaded / 代码是否已加载 */
|
||||||
loaded: Ref<boolean>
|
loaded: Ref<boolean>
|
||||||
|
/** Whether this is the first run / 是否为首次运行 */
|
||||||
firstRun: Ref<boolean>
|
firstRun: Ref<boolean>
|
||||||
|
/** Whether execution is finished / 执行是否完成 */
|
||||||
finished: Ref<boolean>
|
finished: Ref<boolean>
|
||||||
|
/** Standard output lines / 标准输出行 */
|
||||||
stdout: Ref<string[]>
|
stdout: Ref<string[]>
|
||||||
|
/** Standard error lines / 标准错误行 */
|
||||||
stderr: Ref<string[]>
|
stderr: Ref<string[]>
|
||||||
|
/** Error message / 错误信息 */
|
||||||
error: Ref<string>
|
error: Ref<string>
|
||||||
|
/** Backend version / 后端版本 */
|
||||||
backendVersion: Ref<string>
|
backendVersion: Ref<string>
|
||||||
|
/** Clean run state / 清理运行状态 */
|
||||||
onCleanRun: () => void
|
onCleanRun: () => void
|
||||||
|
/** Run code execution / 运行代码执行 */
|
||||||
onRunCode: () => Promise<void>
|
onRunCode: () => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composable for code REPL functionality.
|
||||||
|
*
|
||||||
|
* 代码 REPL 功能的组合式函数。
|
||||||
|
*
|
||||||
|
* This composable provides functionality to execute code in various languages
|
||||||
|
* (Kotlin, Go, Rust, Python) and manage the execution state.
|
||||||
|
*
|
||||||
|
* 该组合式函数提供在各种语言(Kotlin、Go、Rust、Python)中执行代码和管理执行状态的功能。
|
||||||
|
*
|
||||||
|
* @param el - Reference to the code element / 代码元素的引用
|
||||||
|
* @returns REPL state and methods / REPL 状态和方法
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```vue
|
||||||
|
* <script setup>
|
||||||
|
* const codeEl = ref(null)
|
||||||
|
* const { onRunCode, stdout, stderr, loaded } = useCodeRepl(codeEl)
|
||||||
|
* </script>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export function useCodeRepl(el: Ref<HTMLDivElement | null>): UseCodeReplResult {
|
export function useCodeRepl(el: Ref<HTMLDivElement | null>): UseCodeReplResult {
|
||||||
const lang = ref<Lang>()
|
const lang = ref<Lang>()
|
||||||
const loaded = ref(true)
|
const loaded = ref(true)
|
||||||
@ -227,36 +337,74 @@ export function useCodeRepl(el: Ref<HTMLDivElement | null>): UseCodeReplResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request interface for Golang execution API.
|
||||||
|
*
|
||||||
|
* Golang 执行 API 的请求接口。
|
||||||
|
*/
|
||||||
interface GolangRequest {
|
interface GolangRequest {
|
||||||
|
/** Code to execute / 要执行的代码 */
|
||||||
code: string
|
code: string
|
||||||
|
/** Go version / Go 版本 */
|
||||||
version?: '' | 'goprev' | 'gotip'
|
version?: '' | 'goprev' | 'gotip'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response interface for Golang execution API.
|
||||||
|
*
|
||||||
|
* Golang 执行 API 的响应接口。
|
||||||
|
*/
|
||||||
interface GolangResponse {
|
interface GolangResponse {
|
||||||
|
/** Execution events / 执行事件 */
|
||||||
events?: {
|
events?: {
|
||||||
|
/** Event message / 事件消息 */
|
||||||
message: ''
|
message: ''
|
||||||
|
/** Event kind / 事件类型 */
|
||||||
kind: 'stdout' | 'stderr'
|
kind: 'stdout' | 'stderr'
|
||||||
|
/** Event delay / 事件延迟 */
|
||||||
delay: number
|
delay: number
|
||||||
}[]
|
}[]
|
||||||
|
/** Error message / 错误信息 */
|
||||||
error?: string
|
error?: string
|
||||||
|
/** Go version / Go 版本 */
|
||||||
version: string
|
version: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request interface for Kotlin execution API.
|
||||||
|
*
|
||||||
|
* Kotlin 执行 API 的请求接口。
|
||||||
|
*/
|
||||||
interface KotlinRequest {
|
interface KotlinRequest {
|
||||||
|
/** Command line arguments / 命令行参数 */
|
||||||
args?: string
|
args?: string
|
||||||
|
/** Files to compile / 要编译的文件 */
|
||||||
files: {
|
files: {
|
||||||
|
/** File name / 文件名 */
|
||||||
name: string
|
name: string
|
||||||
|
/** Public ID / 公共 ID */
|
||||||
publicId: string
|
publicId: string
|
||||||
|
/** File content / 文件内容 */
|
||||||
text: string
|
text: string
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response interface for Kotlin execution API.
|
||||||
|
*
|
||||||
|
* Kotlin 执行 API 的响应接口。
|
||||||
|
*/
|
||||||
interface KotlinResponse {
|
interface KotlinResponse {
|
||||||
|
/** Execution output / 执行输出 */
|
||||||
text: string
|
text: string
|
||||||
|
/** Kotlin version / Kotlin 版本 */
|
||||||
version: string
|
version: string
|
||||||
|
/** Compilation errors / 编译错误 */
|
||||||
errors: {
|
errors: {
|
||||||
[filename: string]: {
|
[filename: string]: {
|
||||||
|
/** Error message / 错误信息 */
|
||||||
message: string
|
message: string
|
||||||
|
/** Error severity / 错误严重程度 */
|
||||||
severity: 'ERROR' | 'WARNING'
|
severity: 'ERROR' | 'WARNING'
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,48 @@
|
|||||||
import type { ComputedRef } from 'vue'
|
import type { ComputedRef } from 'vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composable for decrypting encrypted content.
|
||||||
|
*
|
||||||
|
* 用于解密加密内容的组合式函数。
|
||||||
|
*
|
||||||
|
* This composable provides a decrypt function that uses the Web Crypto API
|
||||||
|
* to decrypt content encrypted with AES-CBC algorithm.
|
||||||
|
*
|
||||||
|
* 该组合式函数提供一个解密函数,使用 Web Crypto API 解密使用 AES-CBC 算法加密的内容。
|
||||||
|
*
|
||||||
|
* @param config - Configuration containing salt and IV / 包含盐值和 IV 的配置
|
||||||
|
* @returns Object with decrypt function / 包含解密函数的对象
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const config = computed(() => ({ salt: [...], iv: [...] }))
|
||||||
|
* const { decrypt } = useDecrypt(config)
|
||||||
|
* const content = await decrypt('password', 'encrypted-content')
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export function useDecrypt(
|
export function useDecrypt(
|
||||||
config: ComputedRef<{ salt: number[], iv: number[] }>,
|
config: ComputedRef<{ salt: number[], iv: number[] }>,
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* Convert number array to Uint8Array.
|
||||||
|
*
|
||||||
|
* 将数字数组转换为 Uint8Array。
|
||||||
|
*
|
||||||
|
* @param raw - Number array / 数字数组
|
||||||
|
* @returns Uint8Array / Uint8Array
|
||||||
|
*/
|
||||||
const toUnit8Array = (raw: number[]) => Uint8Array.from(raw)
|
const toUnit8Array = (raw: number[]) => Uint8Array.from(raw)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Decrypt encrypted content using password.
|
||||||
|
*
|
||||||
|
* 使用密码解密加密内容。
|
||||||
|
*
|
||||||
|
* @param password - Decryption password / 解密密码
|
||||||
|
* @param text - Encrypted content / 加密内容
|
||||||
|
* @returns Decrypted content or undefined / 解密后的内容或 undefined
|
||||||
|
*/
|
||||||
decrypt: async (password: string, text: string) => {
|
decrypt: async (password: string, text: string) => {
|
||||||
if (!password)
|
if (!password)
|
||||||
return
|
return
|
||||||
@ -29,6 +66,14 @@ export function useDecrypt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get key material from password using PBKDF2.
|
||||||
|
*
|
||||||
|
* 使用 PBKDF2 从密码获取密钥材料。
|
||||||
|
*
|
||||||
|
* @param password - Password string / 密码字符串
|
||||||
|
* @returns CryptoKey for key derivation / 用于密钥派生的 CryptoKey
|
||||||
|
*/
|
||||||
function getKeyMaterial(password: string) {
|
function getKeyMaterial(password: string) {
|
||||||
const enc = new TextEncoder()
|
const enc = new TextEncoder()
|
||||||
return window.crypto.subtle.importKey(
|
return window.crypto.subtle.importKey(
|
||||||
@ -41,7 +86,13 @@ function getKeyMaterial(password: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* crypto
|
* Derive encryption key from key material using PBKDF2.
|
||||||
|
*
|
||||||
|
* 使用 PBKDF2 从密钥材料派生加密密钥。
|
||||||
|
*
|
||||||
|
* @param keyMaterial - Key material from password / 从密码获取的密钥材料
|
||||||
|
* @param salt - Salt for key derivation / 密钥派生盐值
|
||||||
|
* @returns Derived CryptoKey for AES-CBC / 用于 AES-CBC 的派生 CryptoKey
|
||||||
*/
|
*/
|
||||||
function getCryptoDeriveKey(keyMaterial: CryptoKey, salt: BufferSource) {
|
function getCryptoDeriveKey(keyMaterial: CryptoKey, salt: BufferSource) {
|
||||||
return window.crypto.subtle.deriveKey(
|
return window.crypto.subtle.deriveKey(
|
||||||
|
|||||||
@ -1,12 +1,61 @@
|
|||||||
import { onContentUpdated } from 'vuepress/client'
|
import { onContentUpdated } from 'vuepress/client'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute name for mark mode.
|
||||||
|
*
|
||||||
|
* 标记模式属性名。
|
||||||
|
*/
|
||||||
const MARK_MODE_ATTR = 'data-mark-mode'
|
const MARK_MODE_ATTR = 'data-mark-mode'
|
||||||
|
/**
|
||||||
|
* Lazy mode constant.
|
||||||
|
*
|
||||||
|
* 懒加载模式常量。
|
||||||
|
*/
|
||||||
const MARK_MODE_LAZY = 'lazy'
|
const MARK_MODE_LAZY = 'lazy'
|
||||||
|
/**
|
||||||
|
* CSS class for visible marks.
|
||||||
|
*
|
||||||
|
* 可见标记的 CSS 类名。
|
||||||
|
*/
|
||||||
const MARK_VISIBLE_CLASS = 'vp-mark-visible'
|
const MARK_VISIBLE_CLASS = 'vp-mark-visible'
|
||||||
|
/**
|
||||||
|
* Attribute name for mark boundary.
|
||||||
|
*
|
||||||
|
* 标记边界属性名。
|
||||||
|
*/
|
||||||
const MARK_BOUND_ATTR = 'data-vp-mark-bound'
|
const MARK_BOUND_ATTR = 'data-vp-mark-bound'
|
||||||
|
/**
|
||||||
|
* CSS selector for mark elements.
|
||||||
|
*
|
||||||
|
* 标记元素的 CSS 选择器。
|
||||||
|
*/
|
||||||
const MARK_SELECTOR = 'mark'
|
const MARK_SELECTOR = 'mark'
|
||||||
|
/**
|
||||||
|
* CSS selector for bounded mark elements.
|
||||||
|
*
|
||||||
|
* 已绑定标记元素的 CSS 选择器。
|
||||||
|
*/
|
||||||
const BOUND_SELECTOR = `${MARK_SELECTOR}[${MARK_BOUND_ATTR}="1"]`
|
const BOUND_SELECTOR = `${MARK_SELECTOR}[${MARK_BOUND_ATTR}="1"]`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup mark highlight animation for lazy mode.
|
||||||
|
*
|
||||||
|
* 为懒加载模式设置标记高亮动画。
|
||||||
|
*
|
||||||
|
* When mode is 'lazy', marks will animate into view using IntersectionObserver.
|
||||||
|
* When mode is 'eager', marks are immediately visible without animation.
|
||||||
|
*
|
||||||
|
* 当模式为 'lazy' 时,标记将使用 IntersectionObserver 在进入视口时显示动画。
|
||||||
|
* 当模式为 'eager' 时,标记立即显示,没有动画效果。
|
||||||
|
*
|
||||||
|
* @param mode - Animation mode: 'lazy' or 'eager' / 动画模式:'lazy' 或 'eager'
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* // In client config setup
|
||||||
|
* setupMarkHighlight('lazy')
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export function setupMarkHighlight(mode: 'lazy' | 'eager'): void {
|
export function setupMarkHighlight(mode: 'lazy' | 'eager'): void {
|
||||||
if (typeof window === 'undefined' || __VUEPRESS_SSR__)
|
if (typeof window === 'undefined' || __VUEPRESS_SSR__)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -17,6 +17,14 @@ import { withBase } from 'vuepress/client'
|
|||||||
import { ensureEndingSlash, isLinkHttp } from 'vuepress/shared'
|
import { ensureEndingSlash, isLinkHttp } from 'vuepress/shared'
|
||||||
import { pluginOptions } from '../options.js'
|
import { pluginOptions } from '../options.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build query string from PDF options.
|
||||||
|
*
|
||||||
|
* 从 PDF 选项构建查询字符串。
|
||||||
|
*
|
||||||
|
* @param options - PDF token metadata / PDF 令牌元数据
|
||||||
|
* @returns Query string / 查询字符串
|
||||||
|
*/
|
||||||
function queryStringify(options: PDFTokenMeta): string {
|
function queryStringify(options: PDFTokenMeta): string {
|
||||||
const { page, noToolbar, zoom } = options
|
const { page, noToolbar, zoom } = options
|
||||||
const params = [
|
const params = [
|
||||||
@ -32,6 +40,16 @@ function queryStringify(options: PDFTokenMeta): string {
|
|||||||
return queryString
|
return queryString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render PDF viewer in the specified element.
|
||||||
|
*
|
||||||
|
* 在指定元素中渲染 PDF 查看器。
|
||||||
|
*
|
||||||
|
* @param el - Container element / 容器元素
|
||||||
|
* @param url - PDF URL / PDF URL
|
||||||
|
* @param embedType - Embed type: 'pdfjs', 'iframe', or 'embed' / 嵌入类型
|
||||||
|
* @param options - PDF token metadata / PDF 令牌元数据
|
||||||
|
*/
|
||||||
export function renderPDF(
|
export function renderPDF(
|
||||||
el: HTMLElement,
|
el: HTMLElement,
|
||||||
url: string,
|
url: string,
|
||||||
@ -72,6 +90,20 @@ export function renderPDF(
|
|||||||
el.appendChild(pdf)
|
el.appendChild(pdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composable for PDF viewer functionality.
|
||||||
|
*
|
||||||
|
* PDF 查看器功能的组合式函数。
|
||||||
|
*
|
||||||
|
* This function detects browser capabilities and chooses the appropriate
|
||||||
|
* embedding method for PDF display (PDF.js, iframe, or embed).
|
||||||
|
*
|
||||||
|
* 该函数检测浏览器能力并选择适当的嵌入方法来显示 PDF(PDF.js、iframe 或 embed)。
|
||||||
|
*
|
||||||
|
* @param el - Container element / 容器元素
|
||||||
|
* @param url - PDF URL / PDF URL
|
||||||
|
* @param options - PDF token metadata / PDF 令牌元数据
|
||||||
|
*/
|
||||||
export function usePDF(
|
export function usePDF(
|
||||||
el: HTMLElement,
|
el: HTMLElement,
|
||||||
url: string,
|
url: string,
|
||||||
@ -86,10 +118,10 @@ export function usePDF(
|
|||||||
const isModernBrowser = typeof window.Promise === 'function'
|
const isModernBrowser = typeof window.Promise === 'function'
|
||||||
|
|
||||||
// Quick test for mobile devices.
|
// Quick test for mobile devices.
|
||||||
const isMobileDevice = isiPad(userAgent) || isMobile(userAgent)
|
const isMobileDevice = isiPad() || isMobile()
|
||||||
|
|
||||||
// Safari desktop requires special handling
|
// Safari desktop requires special handling
|
||||||
const isSafariDesktop = !isMobileDevice && isSafari(userAgent)
|
const isSafariDesktop = !isMobileDevice && isSafari()
|
||||||
|
|
||||||
const isFirefoxWithPDFJS
|
const isFirefoxWithPDFJS
|
||||||
= !isMobileDevice
|
= !isMobileDevice
|
||||||
|
|||||||
@ -8,8 +8,18 @@ declare const __MD_POWER_HLSJS_INSTALLED__: boolean
|
|||||||
declare const __MD_POWER_MPEGTSJS_INSTALLED__: boolean
|
declare const __MD_POWER_MPEGTSJS_INSTALLED__: boolean
|
||||||
declare const __MD_POWER_ENCRYPT_LOCALES__: LocaleConfig<EncryptSnippetLocale>
|
declare const __MD_POWER_ENCRYPT_LOCALES__: LocaleConfig<EncryptSnippetLocale>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin options injected at build time.
|
||||||
|
*
|
||||||
|
* 构建时注入的插件选项。
|
||||||
|
*/
|
||||||
export const pluginOptions: MarkdownPowerPluginOptions = __MD_POWER_INJECT_OPTIONS__
|
export const pluginOptions: MarkdownPowerPluginOptions = __MD_POWER_INJECT_OPTIONS__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package installation status for video streaming libraries.
|
||||||
|
*
|
||||||
|
* 视频流媒体库的安装状态。
|
||||||
|
*/
|
||||||
export const installed: {
|
export const installed: {
|
||||||
dashjs: boolean
|
dashjs: boolean
|
||||||
hlsjs: boolean
|
hlsjs: boolean
|
||||||
@ -20,6 +30,11 @@ export const installed: {
|
|||||||
mpegtsjs: __MD_POWER_MPEGTSJS_INSTALLED__,
|
mpegtsjs: __MD_POWER_MPEGTSJS_INSTALLED__,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported video types for ArtPlayer.
|
||||||
|
*
|
||||||
|
* ArtPlayer 支持的视频类型。
|
||||||
|
*/
|
||||||
export const ART_PLAYER_SUPPORTED_VIDEO_TYPES: string[] = ['mp4', 'mp3', 'webm', 'ogg']
|
export const ART_PLAYER_SUPPORTED_VIDEO_TYPES: string[] = ['mp4', 'mp3', 'webm', 'ogg']
|
||||||
|
|
||||||
if (installed.dashjs) {
|
if (installed.dashjs) {
|
||||||
@ -34,12 +49,27 @@ if (installed.mpegtsjs) {
|
|||||||
ART_PLAYER_SUPPORTED_VIDEO_TYPES.push('ts', 'flv')
|
ART_PLAYER_SUPPORTED_VIDEO_TYPES.push('ts', 'flv')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection key for timeline component communication.
|
||||||
|
*
|
||||||
|
* 时间线组件通信的注入键。
|
||||||
|
*/
|
||||||
export const INJECT_TIMELINE_KEY: symbol = Symbol(
|
export const INJECT_TIMELINE_KEY: symbol = Symbol(
|
||||||
__VUEPRESS_DEV__ ? 'timeline' : '',
|
__VUEPRESS_DEV__ ? 'timeline' : '',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection key for collapse component communication.
|
||||||
|
*
|
||||||
|
* 折叠面板组件通信的注入键。
|
||||||
|
*/
|
||||||
export const INJECT_COLLAPSE_KEY: symbol = Symbol(
|
export const INJECT_COLLAPSE_KEY: symbol = Symbol(
|
||||||
__VUEPRESS_DEV__ ? 'collapse' : '',
|
__VUEPRESS_DEV__ ? 'collapse' : '',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt snippet locale data.
|
||||||
|
*
|
||||||
|
* 加密片段本地化数据。
|
||||||
|
*/
|
||||||
export const ENCRYPT_LOCALES = __MD_POWER_ENCRYPT_LOCALES__
|
export const ENCRYPT_LOCALES = __MD_POWER_ENCRYPT_LOCALES__
|
||||||
|
|||||||
@ -3,6 +3,19 @@ import type { Markdown } from 'vuepress/markdown'
|
|||||||
import { demoContainer, demoEmbed } from './demo.js'
|
import { demoContainer, demoEmbed } from './demo.js'
|
||||||
import { createDemoRender } from './watcher.js'
|
import { createDemoRender } from './watcher.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register demo plugin for markdown-it.
|
||||||
|
*
|
||||||
|
* 为 markdown-it 注册 demo 插件。
|
||||||
|
*
|
||||||
|
* This plugin enables demo syntax in markdown files, allowing users to
|
||||||
|
* create interactive code demonstrations with live preview.
|
||||||
|
*
|
||||||
|
* 该插件在 markdown 文件中启用 demo 语法,允许用户创建带有实时预览的交互式代码演示。
|
||||||
|
*
|
||||||
|
* @param app - VuePress app instance / VuePress 应用实例
|
||||||
|
* @param md - Markdown-it instance / Markdown-it 实例
|
||||||
|
*/
|
||||||
export function demoPlugin(app: App, md: Markdown): void {
|
export function demoPlugin(app: App, md: Markdown): void {
|
||||||
createDemoRender()
|
createDemoRender()
|
||||||
demoEmbed(app, md)
|
demoEmbed(app, md)
|
||||||
|
|||||||
@ -9,6 +9,17 @@ import { ruLocale } from './ru'
|
|||||||
import { zhLocale } from './zh'
|
import { zhLocale } from './zh'
|
||||||
import { zhTWLocale } from './zh-tw'
|
import { zhTWLocale } from './zh-tw'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default locale options for the plugin.
|
||||||
|
*
|
||||||
|
* 插件的默认本地化选项。
|
||||||
|
*
|
||||||
|
* This constant defines the default locale configurations for all supported languages.
|
||||||
|
* Each locale entry maps language codes to their respective locale data.
|
||||||
|
*
|
||||||
|
* 该常量定义了所有支持语言的默认本地化配置。
|
||||||
|
* 每个本地化条目将语言代码映射到其相应的本地化数据。
|
||||||
|
*/
|
||||||
export const LOCALE_OPTIONS: DefaultLocaleInfo<MDPowerLocaleData> = [
|
export const LOCALE_OPTIONS: DefaultLocaleInfo<MDPowerLocaleData> = [
|
||||||
[['en', 'en-US'], enLocale],
|
[['en', 'en-US'], enLocale],
|
||||||
[['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhLocale],
|
[['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhLocale],
|
||||||
|
|||||||
@ -16,6 +16,41 @@ import { LOCALE_OPTIONS } from './locales/index.js'
|
|||||||
import { prepareConfigFile } from './prepareConfigFile.js'
|
import { prepareConfigFile } from './prepareConfigFile.js'
|
||||||
import { provideData } from './provideData.js'
|
import { provideData } from './provideData.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create markdown power plugin for VuePress.
|
||||||
|
*
|
||||||
|
* 为 VuePress 创建 markdown 增强插件。
|
||||||
|
*
|
||||||
|
* This plugin provides various markdown enhancements including:
|
||||||
|
* - Custom containers (tabs, collapse, timeline, etc.)
|
||||||
|
* - Code blocks enhancements (code tabs, file tree, demo)
|
||||||
|
* - Embed syntax (video, PDF, code playground)
|
||||||
|
* - Inline syntax (mark, subscript, superscript, footnote)
|
||||||
|
* - Icon support
|
||||||
|
*
|
||||||
|
* 该插件提供多种 markdown 增强功能,包括:
|
||||||
|
* - 自定义容器(标签页、折叠面板、时间线等)
|
||||||
|
* - 代码块增强(代码标签页、文件树、演示)
|
||||||
|
* - 嵌入语法(视频、PDF、代码游乐场)
|
||||||
|
* - 行内语法(标记、下标、上标、脚注)
|
||||||
|
* - 图标支持
|
||||||
|
*
|
||||||
|
* @param options - Plugin options / 插件配置选项
|
||||||
|
* @returns VuePress plugin instance / VuePress 插件实例
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* // Basic usage
|
||||||
|
* markdownPowerPlugin()
|
||||||
|
*
|
||||||
|
* // With options
|
||||||
|
* markdownPowerPlugin({
|
||||||
|
* tabs: true,
|
||||||
|
* collapse: true,
|
||||||
|
* pdf: true,
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export function markdownPowerPlugin(
|
export function markdownPowerPlugin(
|
||||||
options: MarkdownPowerPluginOptions = {},
|
options: MarkdownPowerPluginOptions = {},
|
||||||
): Plugin {
|
): Plugin {
|
||||||
|
|||||||
@ -7,10 +7,38 @@ import { prepareIcon } from './icon/index.js'
|
|||||||
const { url: filepath } = import.meta
|
const { url: filepath } = import.meta
|
||||||
const __dirname = getDirname(filepath)
|
const __dirname = getDirname(filepath)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client folder path constant.
|
||||||
|
*
|
||||||
|
* 客户端文件夹路径常量。
|
||||||
|
*/
|
||||||
const CLIENT_FOLDER = ensureEndingSlash(
|
const CLIENT_FOLDER = ensureEndingSlash(
|
||||||
path.resolve(__dirname, '../client'),
|
path.resolve(__dirname, '../client'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare client configuration file for the plugin.
|
||||||
|
*
|
||||||
|
* 为插件准备客户端配置文件。
|
||||||
|
*
|
||||||
|
* This function dynamically generates the client config file based on the plugin options.
|
||||||
|
* It imports and registers Vue components conditionally based on which features are enabled.
|
||||||
|
*
|
||||||
|
* 该函数根据插件选项动态生成客户端配置文件。
|
||||||
|
* 它根据启用的功能有条件地导入和注册 Vue 组件。
|
||||||
|
*
|
||||||
|
* @param app - VuePress app instance / VuePress 应用实例
|
||||||
|
* @param options - Plugin options / 插件配置选项
|
||||||
|
* @returns Path to the generated config file / 生成的配置文件路径
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const configPath = await prepareConfigFile(app, {
|
||||||
|
* pdf: true,
|
||||||
|
* tabs: true,
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOptions): Promise<string> {
|
export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOptions): Promise<string> {
|
||||||
const imports = new Set<string>()
|
const imports = new Set<string>()
|
||||||
const enhances = new Set<string>()
|
const enhances = new Set<string>()
|
||||||
|
|||||||
@ -3,6 +3,34 @@ import type { MarkdownPowerPluginOptions, MDPowerLocaleData } from '../shared/in
|
|||||||
import { isPackageExists } from 'local-pkg'
|
import { isPackageExists } from 'local-pkg'
|
||||||
import { findLocales } from './utils/findLocales.js'
|
import { findLocales } from './utils/findLocales.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide data to be injected into the client-side application.
|
||||||
|
*
|
||||||
|
* 提供要注入到客户端应用的数据。
|
||||||
|
*
|
||||||
|
* This function creates a record of data that will be defined as global constants
|
||||||
|
* in the client bundle, allowing the client to access plugin configuration and
|
||||||
|
* runtime information.
|
||||||
|
*
|
||||||
|
* 该函数创建一个数据记录,将作为全局常量定义在客户端包中,
|
||||||
|
* 允许客户端访问插件配置和运行时信息。
|
||||||
|
*
|
||||||
|
* @param options - Plugin options / 插件配置选项
|
||||||
|
* @param locales - Locale configuration / 本地化配置
|
||||||
|
* @returns Record of data to be defined / 要定义的数据记录
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const data = provideData(options, locales)
|
||||||
|
* // Returns:
|
||||||
|
* // {
|
||||||
|
* // __MD_POWER_INJECT_OPTIONS__: { plot: true, pdf: true },
|
||||||
|
* // __MD_POWER_DASHJS_INSTALLED__: true,
|
||||||
|
* // __MD_POWER_HLSJS_INSTALLED__: false,
|
||||||
|
* // ...
|
||||||
|
* // }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export function provideData(
|
export function provideData(
|
||||||
options: MarkdownPowerPluginOptions,
|
options: MarkdownPowerPluginOptions,
|
||||||
locales: ExactLocaleConfig<MDPowerLocaleData>,
|
locales: ExactLocaleConfig<MDPowerLocaleData>,
|
||||||
|
|||||||
@ -36,13 +36,26 @@ const WHITE_LIST = ['base', 'filePath', 'filePathRelative', 'references', 'abbre
|
|||||||
type WhiteListUnion = (typeof WHITE_LIST)[number]
|
type WhiteListUnion = (typeof WHITE_LIST)[number]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean markdown environment, keeping only whitelisted keys
|
* Clean markdown environment for inline rendering.
|
||||||
*
|
*
|
||||||
* 清理 Markdown 环境,仅保留白名单中的键
|
* 清理 markdown 环境以用于行内渲染。
|
||||||
|
*
|
||||||
|
* When using `md.renderInline()` in custom renderers, some environment properties
|
||||||
|
* may cause issues. This function creates a clean environment object with only
|
||||||
|
* the necessary properties preserved.
|
||||||
|
*
|
||||||
|
* 在自定义渲染器中使用 `md.renderInline()` 时,某些环境属性可能会导致问题。
|
||||||
|
* 该函数创建一个只保留必要属性的干净环境对象。
|
||||||
*
|
*
|
||||||
* @param env - Markdown environment / Markdown 环境
|
* @param env - Markdown environment / Markdown 环境
|
||||||
* @param excludes - Keys to exclude / 要排除的键
|
* @param excludes - Keys to exclude / 要排除的键
|
||||||
* @returns Cleaned environment / 清理后的环境
|
* @returns Cleaned environment / 清理后的环境
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const cleanEnv = cleanMarkdownEnv(env)
|
||||||
|
* const rendered = md.renderInline(content, cleanEnv)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export function cleanMarkdownEnv(env: CleanMarkdownEnv, excludes: WhiteListUnion[] = []): CleanMarkdownEnv {
|
export function cleanMarkdownEnv(env: CleanMarkdownEnv, excludes: WhiteListUnion[] = []): CleanMarkdownEnv {
|
||||||
const result: CleanMarkdownEnv = {}
|
const result: CleanMarkdownEnv = {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user