-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.ts
110 lines (95 loc) · 2.94 KB
/
main.ts
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2024 Im-Beast. All rights reserved. MIT license.
import { ColorSupport, prototype } from "@crayon/crayon/raw";
import { replace, replaceAll } from "@crayon/crayon/utils";
import crayon from "@crayon/crayon/base";
import type { Attribute, FourBitColor } from "@crayon/crayon/styles";
type BaseStyle = FourBitColor | Attribute;
const literalStyleRegex = /{([^\s{}]+)\s([^{}]+)}/;
// Parse string to a type
// e.g. "0" -> 0
// "\"Hello\"" -> "Hello"
// "`Hello`" -> "Hello"
// "true" -> true
function compileType(string: string): string | number | boolean {
switch (string) {
case "true":
return true;
case "false":
return false;
default:
switch (string[0]) {
case '"':
case "'":
case "`":
return string.slice(1, -1);
default:
return Number(string);
}
}
}
// Parse string to crayon style method's styleBuffer
// e.g
// "rgb(123,50,30)" -> crayon.rgb(123, 50, 30).styleBuffer
// "bgHex(0xFF00FF)" -> crayon.bgHex(0xFF00FF).styleBuffer
export function parseStyleMethod(call: string): string {
let methodName = "";
let intermediate = "";
const args = [];
loop: for (let i = 0; i < call.length; i++) {
const char = call[i];
switch (char) {
case ")":
if (intermediate) args.push(compileType(intermediate));
break loop;
case "(":
methodName = intermediate;
intermediate = "";
continue;
case ",":
args.push(compileType(intermediate));
intermediate = "";
continue;
default:
intermediate += char;
}
}
// @ts-expect-error dynamic type
return crayon[methodName]?.(...args)?.styleBuffer;
}
export function parseStyle(style: string): string {
if (style.endsWith(")")) {
return parseStyleMethod(style);
}
return crayon[style as BaseStyle]?.styleBuffer;
}
/** Implementation for Crayon's `prototype.literal` call when using ES6 Literal Templates */
export function literal(
callSite: TemplateStringsArray,
...substitutions: unknown[]
): string {
let text = "";
for (let i = 0; i < callSite.length; ++i) {
text += callSite[i];
text += substitutions[i] ?? "";
}
let matches = text.match(literalStyleRegex);
while (matches?.length) {
const [section, styles, body] = matches;
if (prototype.$colorSupport === ColorSupport.NoColor) {
text = replace(text, section, body);
matches = text.match(literalStyleRegex);
continue;
}
let styleBuffer = "";
for (const style of styles.split(".")) {
const parsedStyle = parseStyle(style);
if (!parsedStyle) throw new Error(`Invalid style: ${style}`);
styleBuffer += parsedStyle;
}
const matchedText = replaceAll(body, "\x1b[0m\x1b[0m", "\x1b[0m" + styleBuffer);
text = replace(text, section, styleBuffer + matchedText + "\x1b[0m\x1b[0m");
matches = text.match(literalStyleRegex);
}
return text;
}
prototype.literal = literal;