优化页面、修复BUG
This commit is contained in:
@@ -1,46 +1,102 @@
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import hljs from 'highlight.js'
|
||||
import type { HLJSApi, LanguageFn } from 'highlight.js'
|
||||
import hljsCore from 'highlight.js/lib/core'
|
||||
import javascript from 'highlight.js/lib/languages/javascript'
|
||||
import typescript from 'highlight.js/lib/languages/typescript'
|
||||
import python from 'highlight.js/lib/languages/python'
|
||||
import go from 'highlight.js/lib/languages/go'
|
||||
import java from 'highlight.js/lib/languages/java'
|
||||
import css from 'highlight.js/lib/languages/css'
|
||||
import xml from 'highlight.js/lib/languages/xml'
|
||||
import json from 'highlight.js/lib/languages/json'
|
||||
import bash from 'highlight.js/lib/languages/bash'
|
||||
import sql from 'highlight.js/lib/languages/sql'
|
||||
import yaml from 'highlight.js/lib/languages/yaml'
|
||||
import markdown from 'highlight.js/lib/languages/markdown'
|
||||
import rust from 'highlight.js/lib/languages/rust'
|
||||
import cpp from 'highlight.js/lib/languages/cpp'
|
||||
import c from 'highlight.js/lib/languages/c'
|
||||
import php from 'highlight.js/lib/languages/php'
|
||||
import shell from 'highlight.js/lib/languages/shell'
|
||||
|
||||
const md = new MarkdownIt({
|
||||
html: true,
|
||||
linkify: true,
|
||||
typographer: true,
|
||||
})
|
||||
const LANGUAGE_REGISTRY: Array<[string, LanguageFn]> = [
|
||||
['javascript', javascript],
|
||||
['typescript', typescript],
|
||||
['python', python],
|
||||
['go', go],
|
||||
['java', java],
|
||||
['css', css],
|
||||
['xml', xml],
|
||||
['html', xml],
|
||||
['json', json],
|
||||
['bash', bash],
|
||||
['sh', bash],
|
||||
['sql', sql],
|
||||
['yaml', yaml],
|
||||
['yml', yaml],
|
||||
['markdown', markdown],
|
||||
['md', markdown],
|
||||
['rust', rust],
|
||||
['cpp', cpp],
|
||||
['c', c],
|
||||
['php', php],
|
||||
['shell', shell],
|
||||
]
|
||||
|
||||
md.renderer.rules.heading_open = function (tokens, idx) {
|
||||
const token = tokens[idx]
|
||||
const contentToken = tokens[idx + 1]
|
||||
const title = contentToken ? contentToken.content : ''
|
||||
const slug = 'heading-' + title.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-') + '-' + idx
|
||||
return `<${token.tag} id="${slug}">`
|
||||
let hljsInstance: HLJSApi | null = null
|
||||
let mdInstance: MarkdownIt | null = null
|
||||
|
||||
function getHljs(): HLJSApi {
|
||||
if (!hljsInstance) {
|
||||
hljsInstance = hljsCore
|
||||
for (const [name, register] of LANGUAGE_REGISTRY) {
|
||||
hljsInstance.registerLanguage(name, register)
|
||||
}
|
||||
}
|
||||
return hljsInstance
|
||||
}
|
||||
|
||||
md.renderer.rules.fence = function (tokens, idx) {
|
||||
const token = tokens[idx]
|
||||
const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''
|
||||
let langName = ''
|
||||
let highlighted
|
||||
function buildMarkdownRenderer(hljs: HLJSApi): MarkdownIt {
|
||||
const md = new MarkdownIt({
|
||||
html: true,
|
||||
linkify: true,
|
||||
typographer: true,
|
||||
})
|
||||
|
||||
if (info) {
|
||||
langName = info.split(/\s+/g)[0]
|
||||
md.renderer.rules.heading_open = function (tokens, idx) {
|
||||
const token = tokens[idx]
|
||||
const contentToken = tokens[idx + 1]
|
||||
const title = contentToken ? contentToken.content : ''
|
||||
const slug = 'heading-' + title.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-') + '-' + idx
|
||||
return `<${token.tag} id="${slug}">`
|
||||
}
|
||||
|
||||
if (langName && hljs.getLanguage(langName)) {
|
||||
try {
|
||||
highlighted = hljs.highlight(token.content, { language: langName, ignoreIllegals: true }).value
|
||||
} catch {
|
||||
md.renderer.rules.fence = function (tokens, idx) {
|
||||
const token = tokens[idx]
|
||||
const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''
|
||||
let langName = ''
|
||||
let highlighted
|
||||
|
||||
if (info) {
|
||||
langName = info.split(/\s+/g)[0]
|
||||
}
|
||||
|
||||
if (langName && hljs.getLanguage(langName)) {
|
||||
try {
|
||||
highlighted = hljs.highlight(token.content, { language: langName, ignoreIllegals: true }).value
|
||||
} catch {
|
||||
highlighted = md.utils.escapeHtml(token.content)
|
||||
}
|
||||
} else {
|
||||
highlighted = md.utils.escapeHtml(token.content)
|
||||
}
|
||||
} else {
|
||||
highlighted = md.utils.escapeHtml(token.content)
|
||||
}
|
||||
|
||||
const lines = token.content.trimEnd().split('\n')
|
||||
const lineNumbers = lines.map((_, i) => i + 1).join('\n')
|
||||
const lines = token.content.trimEnd().split('\n')
|
||||
const lineNumbers = lines.map((_, i) => i + 1).join('\n')
|
||||
|
||||
const copyIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: block;"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`
|
||||
const copyIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: block;"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`
|
||||
|
||||
return `
|
||||
return `
|
||||
<div class="ios-code-container w-full max-w-full my-6 md:my-10 rounded-lg md:rounded-xl overflow-hidden shadow-2xl bg-[#1e1e1e] border border-white/5 relative group/code text-sm">
|
||||
<div class="mac-window-header flex items-center justify-between px-3 md:px-4 py-2 md:py-3 bg-[#282828] border-b border-white/5">
|
||||
<div class="flex items-center gap-3 md:gap-4">
|
||||
@@ -66,9 +122,25 @@ md.renderer.rules.fence = function (tokens, idx) {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
return md
|
||||
}
|
||||
|
||||
export function renderMarkdown(content: string): string {
|
||||
function getMarkdownRenderer(): MarkdownIt {
|
||||
if (!mdInstance) {
|
||||
mdInstance = buildMarkdownRenderer(getHljs())
|
||||
}
|
||||
return mdInstance
|
||||
}
|
||||
|
||||
export async function renderMarkdown(content: string): Promise<string> {
|
||||
if (!content) return ''
|
||||
const md = getMarkdownRenderer()
|
||||
return md.render(content)
|
||||
}
|
||||
|
||||
/** 预加载 highlight.js(可在路由进入详情页时调用) */
|
||||
export function preloadMarkdownRenderer(): void {
|
||||
getHljs()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user