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 |
x65
x65
x65
x65
x65
x65
x65
x881
x881
x1149
x1149
x1144
x1144
x1149
x881
x881
x881
x1
x1
x1
x881
x1
x1
x1
x881
x1
x1
x881
x881
x65
x653
x16
x16
x637
x637
x637
x637
x637
x637
x637
x637
x653
x65
x3367
x3367
x3367
x3367
x4441
x4441
x4441
x2223
x2223
x4441
x2218
x2218
x2218
x4441
x1149
x3367
x65
x2218
x2218
x2218
x2218
x2218
x2218
x2218
x2218
x2218
x2218 |
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)
}
|