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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 |
x62
x62
x62
x62
x62
x62
x62
x873
x873
x1140
x1140
x1135
x1135
x1140
x873
x873
x873
x1
x1
x1
x873
x1
x1
x1
x873
x1
x1
x873
x873
x62
x653
x16
x16
x637
x637
x637
x637
x637
x637
x637
x637
x653
x62
x3348
x3348
x3348
x3348
x4421
x4421
x4421
x2213
x2213
x4421
x2208
x2208
x2208
x4421
x1140
x3348
x62
x2208
x2208
x2208
x2208
x2208
x2208
x2208
x2208
x2208
x2208 |
I
|
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"
import { runtime } from "./runtime.ts"
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
}
export function inspect(value: unknown): string {
if (typeof value === "function") {
return "fn"
}
if (runtime !== "deno") {
return `${value}`
}
return Deno.inspect(value, { colors: true, compact: true, depth: Infinity })
.replace(/\n\s+/g, " ")
.replace(/AbortSignal \{[^}]+?\}/g, "AbortSignal")
.replace(/\[Function: ([A-Z]\w*)\]/g, "$1")
.replace(/\[Function: (\w*)\]/g, "Function")
.replace(/\[Function \(anonymous\)]/g, "Function")
.replace(/\{ \[class (\w+)\] [^}]+?\}/g, "$1")
.replace(/\[Object: null prototype\] \{ url: [^,]+?, main: [^}]+?, filename: [^,]+?, dirname: [^,]+?\}/g, "import.meta")
}
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)
}
|