1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 |
x43
x43
x43
x43
x43
x43
x405
x405
x2487
x829
x1248
x1248
x829
x405
x405
x405
x406
x406
x406
x405
x406
x406
x406
x405
x406
x406
x405
x405
x43
x993
x993
x993
x993
x2050
x2050
x2050
x12905
x2581
x2050
x2576
x2576
x2576
x2050
x1417
x993
x43
x569
x569
x569
x569
x569
x569
x569
x569
x569
x569 |
|
import hljs from "highlight.js/lib/core"
import typescript from "highlight.js/lib/languages/typescript"
import { bgBlack, bgWhite, bgYellow, black, blue, cyan, gray, green, stripAnsiCode, underline, yellow } from "@std/fmt/colors"
import { unescape } from "@std/html/entities"
hljs.registerLanguage("typescript", typescript)
export function highlight(text: string, { underline: underlined = false, header = "", type = "" } = {} as { underline?: boolean; header?: string; type?: string }): string {
text = text
.replace(/`([^`]*?)`/g, (_, content) => {
let highlighted = process(unescape(hljs.highlight(content, { language: "typescript" }).value))
if (underlined) {
highlighted = underline(highlighted)
}
return highlighted
})
let background = bgWhite
if (type === "warn") {
text = yellow(stripAnsiCode(text))
background = bgYellow
}
if (type === "debug") {
text = gray(stripAnsiCode(text))
background = bgBlack
}
if (header) {
text = `${background(black(` ${header} `))} ${text}`
}
return text
}
function process(html: string) {
const stack = []
const regex = /(?<open><span[^>]*class="(?<classname>[^"]*)"[^>]*>)|(?<close><\/span>)/gs
let match = null as ReturnType<typeof regex.exec>
while ((match = regex.exec(html)) !== null) {
const [captured] = match
const { open, close, classname } = match.groups!
if (open) {
stack.push({ classname, a: match.index, b: match.index + captured.length })
}
if (close) {
const { a, b, classname } = stack.pop()!
return process(`${html.substring(0, a)}${color(html.substring(b, match.index), classname)}${html.substring(match.index + close.length)}`)
}
}
return html
}
function color(content: string, classname: string) {
return ({
"hljs-comment": gray,
"hljs-keyword": cyan,
"hljs-string": green,
"hljs-title function_": blue,
"hljs-title class_": blue,
"hljs-literal": yellow,
"hljs-number": yellow,
}[classname] ?? ((text: string) => text))(content)
}
|