keri-ts 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/esm/app/cli/annotate-color.js +215 -0
- package/esm/app/cli/annotate.js +6 -1
- package/esm/app/cli/command-definitions.js +2 -0
- package/esm/app/version.js +2 -2
- package/package.json +1 -1
- package/types/app/cli/annotate-color.d.ts +6 -0
- package/types/app/cli/annotate-color.d.ts.map +1 -0
- package/types/app/cli/annotate.d.ts.map +1 -1
- package/types/app/version.d.ts +2 -2
package/README.md
CHANGED
|
@@ -61,6 +61,14 @@ tufa annotate --qb2 --in <binary.qb2> --out <annotation.txt>
|
|
|
61
61
|
- `--out <path>`: output file path (defaults to stdout)
|
|
62
62
|
- `--qb2`: parse input as qb2 binary
|
|
63
63
|
- `--pretty`: pretty-print annotation output
|
|
64
|
+
- `--colored`: colorize annotation output on stdout only (ignored with `--out`)
|
|
65
|
+
|
|
66
|
+
Optional color overrides:
|
|
67
|
+
|
|
68
|
+
- File: `$HOME/.tufa/annot-color.yaml` or `$HOME/.tufa/annot-color.yml`
|
|
69
|
+
- Keys: `counter`, `group`, `body`, `signature`, `said`, `opaque`, `comment`
|
|
70
|
+
- Values: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`,
|
|
71
|
+
or bright variants (`brightBlack` ... `brightWhite`)
|
|
64
72
|
|
|
65
73
|
## Package entrypoints
|
|
66
74
|
|
|
@@ -72,3 +80,8 @@ npx tufa --help
|
|
|
72
80
|
deno task tufa --help
|
|
73
81
|
deno task tufa version
|
|
74
82
|
```
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
Licensed under the Apache License, Version 2.0 (`Apache-2.0`). See the
|
|
87
|
+
top-level `LICENSE` file in this repository.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
const ANSI_CODES = {
|
|
3
|
+
black: "\x1b[30m",
|
|
4
|
+
red: "\x1b[31m",
|
|
5
|
+
green: "\x1b[32m",
|
|
6
|
+
yellow: "\x1b[33m",
|
|
7
|
+
blue: "\x1b[34m",
|
|
8
|
+
magenta: "\x1b[35m",
|
|
9
|
+
cyan: "\x1b[36m",
|
|
10
|
+
white: "\x1b[37m",
|
|
11
|
+
brightBlack: "\x1b[90m",
|
|
12
|
+
brightRed: "\x1b[91m",
|
|
13
|
+
brightGreen: "\x1b[92m",
|
|
14
|
+
brightYellow: "\x1b[93m",
|
|
15
|
+
brightBlue: "\x1b[94m",
|
|
16
|
+
brightMagenta: "\x1b[95m",
|
|
17
|
+
brightCyan: "\x1b[96m",
|
|
18
|
+
brightWhite: "\x1b[97m",
|
|
19
|
+
};
|
|
20
|
+
const RESET = "\x1b[0m";
|
|
21
|
+
const COLOR_KEYS = [
|
|
22
|
+
"counter",
|
|
23
|
+
"group",
|
|
24
|
+
"body",
|
|
25
|
+
"signature",
|
|
26
|
+
"said",
|
|
27
|
+
"opaque",
|
|
28
|
+
"comment",
|
|
29
|
+
];
|
|
30
|
+
const DEFAULT_COLORS = {
|
|
31
|
+
counter: "cyan",
|
|
32
|
+
group: "magenta",
|
|
33
|
+
body: "green",
|
|
34
|
+
signature: "yellow",
|
|
35
|
+
said: "brightBlue",
|
|
36
|
+
opaque: "brightRed",
|
|
37
|
+
comment: "brightBlack",
|
|
38
|
+
};
|
|
39
|
+
const SAID_CAPTURE = /(said=)(\S+)/g;
|
|
40
|
+
const COMMENT_DELIM = " # ";
|
|
41
|
+
function isColorName(value) {
|
|
42
|
+
return typeof value === "string" && value in ANSI_CODES;
|
|
43
|
+
}
|
|
44
|
+
function parseColorConfig(raw) {
|
|
45
|
+
const parsed = {};
|
|
46
|
+
const lines = raw.split(/\r?\n/);
|
|
47
|
+
for (const line of lines) {
|
|
48
|
+
const trimmed = line.trim();
|
|
49
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
50
|
+
continue;
|
|
51
|
+
const match = /^([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.+?)\s*$/.exec(trimmed);
|
|
52
|
+
if (!match)
|
|
53
|
+
return null;
|
|
54
|
+
const key = match[1];
|
|
55
|
+
let value = match[2];
|
|
56
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
57
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
58
|
+
value = value.slice(1, -1);
|
|
59
|
+
}
|
|
60
|
+
parsed[key] = value;
|
|
61
|
+
}
|
|
62
|
+
const config = {};
|
|
63
|
+
for (const key of COLOR_KEYS) {
|
|
64
|
+
const value = parsed[key];
|
|
65
|
+
if (value === undefined)
|
|
66
|
+
continue;
|
|
67
|
+
if (!isColorName(value))
|
|
68
|
+
return null;
|
|
69
|
+
config[key] = value;
|
|
70
|
+
}
|
|
71
|
+
return config;
|
|
72
|
+
}
|
|
73
|
+
function resolveConfigPath(homeDir) {
|
|
74
|
+
const basePath = `${homeDir}/.tufa`;
|
|
75
|
+
const yamlPath = `${basePath}/annot-color.yaml`;
|
|
76
|
+
const ymlPath = `${basePath}/annot-color.yml`;
|
|
77
|
+
try {
|
|
78
|
+
const stat = dntShim.Deno.statSync(yamlPath);
|
|
79
|
+
if (stat.isFile)
|
|
80
|
+
return yamlPath;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Continue to .yml fallback
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const stat = dntShim.Deno.statSync(ymlPath);
|
|
87
|
+
if (stat.isFile)
|
|
88
|
+
return ymlPath;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// No config file, use defaults
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
function readUserColorConfig() {
|
|
96
|
+
const homeDir = dntShim.Deno.env.get("HOME");
|
|
97
|
+
if (!homeDir)
|
|
98
|
+
return null;
|
|
99
|
+
const configPath = resolveConfigPath(homeDir);
|
|
100
|
+
if (!configPath)
|
|
101
|
+
return null;
|
|
102
|
+
try {
|
|
103
|
+
return parseColorConfig(dntShim.Deno.readTextFileSync(configPath));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function toAnsiColors(userConfig) {
|
|
110
|
+
const names = { ...DEFAULT_COLORS };
|
|
111
|
+
if (userConfig) {
|
|
112
|
+
for (const key of COLOR_KEYS) {
|
|
113
|
+
const value = userConfig[key];
|
|
114
|
+
if (value)
|
|
115
|
+
names[key] = value;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
counter: ANSI_CODES[names.counter],
|
|
120
|
+
group: ANSI_CODES[names.group],
|
|
121
|
+
body: ANSI_CODES[names.body],
|
|
122
|
+
signature: ANSI_CODES[names.signature],
|
|
123
|
+
said: ANSI_CODES[names.said],
|
|
124
|
+
opaque: ANSI_CODES[names.opaque],
|
|
125
|
+
comment: ANSI_CODES[names.comment],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function color(text, ansiCode) {
|
|
129
|
+
if (!text)
|
|
130
|
+
return text;
|
|
131
|
+
return `${ansiCode}${text}${RESET}`;
|
|
132
|
+
}
|
|
133
|
+
function colorizeComment(comment, colors) {
|
|
134
|
+
const saidTinted = comment.replace(SAID_CAPTURE, (_whole, prefix, said) => `${prefix}${color(said, colors.said)}`);
|
|
135
|
+
return color(saidTinted, colors.comment);
|
|
136
|
+
}
|
|
137
|
+
function colorizeValue(value, comment, colors) {
|
|
138
|
+
const text = value.trim();
|
|
139
|
+
if (!text)
|
|
140
|
+
return value;
|
|
141
|
+
if (comment && /opaque/i.test(comment)) {
|
|
142
|
+
return color(value, colors.opaque);
|
|
143
|
+
}
|
|
144
|
+
if (comment && /(Indexer|Sig|Sigs|Signature)/.test(comment)) {
|
|
145
|
+
return color(value, colors.signature);
|
|
146
|
+
}
|
|
147
|
+
if (comment && /(Group|count=|counter)/.test(comment)) {
|
|
148
|
+
return color(value, colors.group);
|
|
149
|
+
}
|
|
150
|
+
if (comment && /SERDER/.test(comment)) {
|
|
151
|
+
return color(value, colors.body);
|
|
152
|
+
}
|
|
153
|
+
if (/^[\[{]/.test(text)) {
|
|
154
|
+
return color(value, colors.body);
|
|
155
|
+
}
|
|
156
|
+
if (/^-[A-Za-z0-9_-]+$/.test(text)) {
|
|
157
|
+
return color(value, colors.counter);
|
|
158
|
+
}
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
function colorizeLine(line, colors) {
|
|
162
|
+
const trimmed = line.trimStart();
|
|
163
|
+
if (trimmed.startsWith("#")) {
|
|
164
|
+
return color(line, colors.comment);
|
|
165
|
+
}
|
|
166
|
+
const idx = line.indexOf(COMMENT_DELIM);
|
|
167
|
+
if (idx === -1) {
|
|
168
|
+
return colorizeValue(line, null, colors);
|
|
169
|
+
}
|
|
170
|
+
const value = line.slice(0, idx);
|
|
171
|
+
const comment = line.slice(idx + COMMENT_DELIM.length);
|
|
172
|
+
const valueTinted = colorizeValue(value, comment, colors);
|
|
173
|
+
const commentTinted = colorizeComment(comment, colors);
|
|
174
|
+
return `${valueTinted}${COMMENT_DELIM}${commentTinted}`;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Apply ANSI styling for CLI-only CESR annotation display.
|
|
178
|
+
* This is intentionally presentation-only and must not alter persisted output.
|
|
179
|
+
*/
|
|
180
|
+
export function colorizeAnnotatedOutput(annotated) {
|
|
181
|
+
const colors = toAnsiColors(readUserColorConfig());
|
|
182
|
+
const lines = annotated.split("\n");
|
|
183
|
+
const out = [];
|
|
184
|
+
let inPrettyJsonBody = false;
|
|
185
|
+
// support colorizing lines even with --pretty arg
|
|
186
|
+
for (const line of lines) {
|
|
187
|
+
const idx = line.indexOf(COMMENT_DELIM);
|
|
188
|
+
const value = idx === -1 ? line : line.slice(0, idx);
|
|
189
|
+
const comment = idx === -1 ? null : line.slice(idx + COMMENT_DELIM.length);
|
|
190
|
+
const trimmed = value.trim();
|
|
191
|
+
if (comment && /SERDER/.test(comment)) {
|
|
192
|
+
if (trimmed === "}" || trimmed === "]") {
|
|
193
|
+
const valueTinted = color(value, colors.body);
|
|
194
|
+
const commentTinted = colorizeComment(comment, colors);
|
|
195
|
+
out.push(`${valueTinted}${COMMENT_DELIM}${commentTinted}`);
|
|
196
|
+
inPrettyJsonBody = false;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
out.push(colorizeLine(line, colors));
|
|
200
|
+
inPrettyJsonBody = false;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (inPrettyJsonBody && idx === -1) {
|
|
204
|
+
out.push(color(line, colors.body));
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (idx === -1 && (trimmed === "{" || trimmed === "[")) {
|
|
208
|
+
inPrettyJsonBody = true;
|
|
209
|
+
out.push(color(line, colors.body));
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
out.push(colorizeLine(line, colors));
|
|
213
|
+
}
|
|
214
|
+
return out.join("\n");
|
|
215
|
+
}
|
package/esm/app/cli/annotate.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
2
|
import { annotate } from "cesr-ts";
|
|
3
|
+
import { colorizeAnnotatedOutput } from "./annotate-color.js";
|
|
3
4
|
const TEXT_DECODER = new TextDecoder();
|
|
4
5
|
/**
|
|
5
6
|
* Reads bytes from stdin in chunks of 64KB and returns them as a single Uint8Array
|
|
@@ -34,6 +35,7 @@ export function* annotateCommand(args) {
|
|
|
34
35
|
outPath: args.outPath,
|
|
35
36
|
qb2: args.qb2,
|
|
36
37
|
pretty: args.pretty,
|
|
38
|
+
colored: args.colored,
|
|
37
39
|
};
|
|
38
40
|
const inputBytes = options.inPath
|
|
39
41
|
? dntShim.Deno.readFileSync(options.inPath)
|
|
@@ -48,5 +50,8 @@ export function* annotateCommand(args) {
|
|
|
48
50
|
dntShim.Deno.writeTextFileSync(options.outPath, annotated);
|
|
49
51
|
return;
|
|
50
52
|
}
|
|
51
|
-
|
|
53
|
+
const output = options.colored
|
|
54
|
+
? colorizeAnnotatedOutput(annotated)
|
|
55
|
+
: annotated;
|
|
56
|
+
console.log(output);
|
|
52
57
|
}
|
|
@@ -199,6 +199,7 @@ function regAnnotateCmd(program, dispatch) {
|
|
|
199
199
|
.option("--out <path>", "Output file path (defaults to stdout)")
|
|
200
200
|
.option("--qb2", "Treat input as qb2 binary instead of text CESR")
|
|
201
201
|
.option("--pretty", "Pretty-print annotation output")
|
|
202
|
+
.option("--colored", "Colorize annotation output (stdout only)")
|
|
202
203
|
.action((options) => {
|
|
203
204
|
dispatch({
|
|
204
205
|
name: "annotate",
|
|
@@ -207,6 +208,7 @@ function regAnnotateCmd(program, dispatch) {
|
|
|
207
208
|
outPath: options.out,
|
|
208
209
|
qb2: options.qb2 || false,
|
|
209
210
|
pretty: options.pretty || false,
|
|
211
|
+
colored: options.colored || false,
|
|
210
212
|
},
|
|
211
213
|
});
|
|
212
214
|
return Promise.resolve();
|
package/esm/app/version.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Generated by scripts/generate_versions.ts.
|
|
3
3
|
* Do not edit by hand.
|
|
4
4
|
*/
|
|
5
|
-
export const PACKAGE_VERSION = "0.3.
|
|
6
|
-
export const BUILD_METADATA = "build.
|
|
5
|
+
export const PACKAGE_VERSION = "0.3.1";
|
|
6
|
+
export const BUILD_METADATA = "build.4.f47c821b";
|
|
7
7
|
export const DISPLAY_VERSION = BUILD_METADATA
|
|
8
8
|
? `${PACKAGE_VERSION}+${BUILD_METADATA}`
|
|
9
9
|
: PACKAGE_VERSION;
|
package/package.json
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply ANSI styling for CLI-only CESR annotation display.
|
|
3
|
+
* This is intentionally presentation-only and must not alter persisted output.
|
|
4
|
+
*/
|
|
5
|
+
export declare function colorizeAnnotatedOutput(annotated: string): string;
|
|
6
|
+
//# sourceMappingURL=annotate-color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotate-color.d.ts","sourceRoot":"","sources":["../../../src/app/cli/annotate-color.ts"],"names":[],"mappings":"AAyOA;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAyCjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotate.d.ts","sourceRoot":"","sources":["../../../src/app/cli/annotate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"annotate.d.ts","sourceRoot":"","sources":["../../../src/app/cli/annotate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AA4D3C,wBAAiB,eAAe,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,SAAS,CAAC,IAAI,CAAC,CA6BjB"}
|
package/types/app/version.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generated by scripts/generate_versions.ts.
|
|
3
3
|
* Do not edit by hand.
|
|
4
4
|
*/
|
|
5
|
-
export declare const PACKAGE_VERSION = "0.3.
|
|
6
|
-
export declare const BUILD_METADATA = "build.
|
|
5
|
+
export declare const PACKAGE_VERSION = "0.3.1";
|
|
6
|
+
export declare const BUILD_METADATA = "build.4.f47c821b";
|
|
7
7
|
export declare const DISPLAY_VERSION: string;
|
|
8
8
|
//# sourceMappingURL=version.d.ts.map
|