import type { LanguageFn } from 'highlight.js' const IMAGE_EXT = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif']) const TEXT_EXT = new Set([ 'txt', 'md', 'log', 'json', 'yaml', 'yml', 'ini', 'toml', 'conf', 'cfg', 'csv', 'xml', 'html', 'htm', 'css', 'js', 'ts', 'sh', 'py', 'go', 'env', 'properties', 'sql', ]) /** office/pdf 预览形态(vue-office 渲染);doc/xls/ppt 老格式不支持 */ const OFFICE_KIND: Record = { docx: 'docx', xlsx: 'xlsx', pdf: 'pdf', pptx: 'pptx', } export type PreviewKind = 'image' | 'text' | 'docx' | 'xlsx' | 'pdf' | 'pptx' | 'none' export function extOf(name: string): string { return name.split('.').pop()?.toLowerCase() ?? '' } /** 对象是否支持预览及预览形态 */ export function previewKindOf(name: string): PreviewKind { const ext = extOf(name) // svg 按文本处理:预览「渲染 ↔ 代码」双态由文本生成,且可在线编辑 if (ext === 'svg') return 'text' if (IMAGE_EXT.has(ext)) return 'image' if (TEXT_EXT.has(ext)) return 'text' return OFFICE_KIND[ext] ?? 'none' } /** 扩展名 → highlight.js 语言;不在表内的按纯文本展示 */ const EXT_LANG: Record = { py: 'python', json: 'json', yaml: 'yaml', yml: 'yaml', ini: 'ini', toml: 'ini', conf: 'ini', cfg: 'ini', env: 'ini', properties: 'ini', xml: 'xml', html: 'xml', htm: 'xml', sh: 'bash', js: 'javascript', ts: 'typescript', go: 'go', sql: 'sql', md: 'markdown', css: 'css', svg: 'xml', } /** 语言按需动态加载,各自成 chunk,不预览不下载 */ const LANG_LOADERS: Record Promise<{ default: LanguageFn }>> = { python: () => import('highlight.js/lib/languages/python'), json: () => import('highlight.js/lib/languages/json'), yaml: () => import('highlight.js/lib/languages/yaml'), ini: () => import('highlight.js/lib/languages/ini'), xml: () => import('highlight.js/lib/languages/xml'), bash: () => import('highlight.js/lib/languages/bash'), javascript: () => import('highlight.js/lib/languages/javascript'), typescript: () => import('highlight.js/lib/languages/typescript'), go: () => import('highlight.js/lib/languages/go'), sql: () => import('highlight.js/lib/languages/sql'), markdown: () => import('highlight.js/lib/languages/markdown'), css: () => import('highlight.js/lib/languages/css'), } /** * 高亮一段代码;lang 可传语言名(md 围栏标签,如 python/bash)或扩展名(如 py/sh)。 * 返回 hljs 生成的 HTML(输入已转义,可安全 v-html);不支持或失败返回 null。 */ export async function highlightCode(code: string, lang: string): Promise { const name = LANG_LOADERS[lang] ? lang : EXT_LANG[lang] const load = name ? LANG_LOADERS[name] : undefined if (!name || !load) return null try { const { default: hljs } = await import('highlight.js/lib/core') if (!hljs.getLanguage(name)) hljs.registerLanguage(name, (await load()).default) return hljs.highlight(code, { language: name }).value } catch { return null } } /** 按扩展名高亮整份源码,语义同 highlightCode(ext 分支)。 */ export async function highlightSource(text: string, ext: string): Promise { return highlightCode(text, ext) }