nv-html-term-paint 1.0.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/TEST/tst-cli.js +8 -0
- package/colors.js +97 -0
- package/index.js +92 -0
- package/package.json +14 -0
package/TEST/tst-cli.js
ADDED
package/colors.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
//终端染色
|
|
2
|
+
|
|
3
|
+
// ANSI Escape Codes
|
|
4
|
+
const RESET = "\x1b[0m";
|
|
5
|
+
const UNDERLINE = "\x1b[4m";
|
|
6
|
+
const DIM = "\x1b[2m";
|
|
7
|
+
const BRIGHT = "\x1b[1m";
|
|
8
|
+
|
|
9
|
+
// 建议在 colors.js 中这样定义
|
|
10
|
+
const C = {
|
|
11
|
+
STRUCT: "\x1b[38;5;208m", // 橙色:骨架标签 (html, body, div, section)
|
|
12
|
+
INLINE: "\x1b[38;5;148m", // 黄绿色:行内文本 (span, a, b, i)
|
|
13
|
+
FORM: "\x1b[38;5;39m", // 蓝色:交互控件 (input, button, select)
|
|
14
|
+
HEAD: "\x1b[38;5;244m", // 灰色:头部元数据 (meta, link, title)
|
|
15
|
+
MEDIA: "\x1b[38;5;170m", // 紫色:多媒体 (img, video, canvas, svg)
|
|
16
|
+
GOLD: "\x1b[38;5;214m",
|
|
17
|
+
CYAN: "\x1b[36m",
|
|
18
|
+
L_BLUE: "\x1b[94m",
|
|
19
|
+
GRAY: "\x1b[90m",
|
|
20
|
+
D_GRAY: "\x1b[38;5;237m",
|
|
21
|
+
WHITE: "\x1b[37m",
|
|
22
|
+
GREEN: "\x1b[32m"
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const DFLT_BUILTIN_TAGS = {
|
|
26
|
+
// 1. 骨架与块级容器 (Structural)
|
|
27
|
+
"html": C.STRUCT, "body": C.STRUCT, "head": C.HEAD,
|
|
28
|
+
"div": C.STRUCT, "section": C.STRUCT, "article": C.STRUCT,
|
|
29
|
+
"nav": C.STRUCT, "header": C.STRUCT, "footer": C.STRUCT,
|
|
30
|
+
"main": C.STRUCT, "aside": C.STRUCT, "details": C.STRUCT, "summary": C.STRUCT,
|
|
31
|
+
|
|
32
|
+
// 2. 文本内容 (Content)
|
|
33
|
+
"h1": C.STRUCT, "h2": C.STRUCT, "h3": C.STRUCT, "h4": C.STRUCT, "h5": C.STRUCT, "h6": C.STRUCT,
|
|
34
|
+
"p": C.INLINE, "li": C.INLINE, "ul": C.STRUCT, "ol": C.STRUCT, "dl": C.STRUCT, "dt": C.STRUCT, "dd": C.STRUCT,
|
|
35
|
+
"blockquote": C.INLINE, "pre": C.INLINE, "code": C.INLINE, "span": C.INLINE, "a": C.INLINE,
|
|
36
|
+
|
|
37
|
+
// 3. 表单与交互 (Forms & Interactive)
|
|
38
|
+
"form": C.FORM, "input": C.FORM, "button": C.FORM, "select": C.FORM,
|
|
39
|
+
"textarea": C.FORM, "label": C.FORM, "option": C.FORM, "optgroup": C.FORM,
|
|
40
|
+
"datalist": C.FORM, "progress": C.FORM, "meter": C.FORM,
|
|
41
|
+
|
|
42
|
+
// 4. 多媒体与图形 (Media)
|
|
43
|
+
"img": C.MEDIA, "video": C.MEDIA, "audio": C.MEDIA, "canvas": C.MEDIA,
|
|
44
|
+
"svg": C.MEDIA, "picture": C.MEDIA, "source": C.MEDIA, "track": C.MEDIA,
|
|
45
|
+
|
|
46
|
+
// 5. 表格 (Table)
|
|
47
|
+
"table": C.STRUCT, "thead": C.STRUCT, "tbody": C.STRUCT, "tfoot": C.STRUCT,
|
|
48
|
+
"tr": C.STRUCT, "th": C.INLINE, "td": C.INLINE, "caption": C.INLINE,
|
|
49
|
+
|
|
50
|
+
// 6. 元数据与脚本 (Meta & Script) - 通常建议用暗色,因为它们不是视觉重点
|
|
51
|
+
"meta": C.HEAD, "link": C.HEAD, "title": C.HEAD, "style": C.HEAD, "script": C.HEAD,
|
|
52
|
+
"noscript": C.HEAD, "template": C.HEAD, "base": C.HEAD,
|
|
53
|
+
|
|
54
|
+
// 7. 其他/功能性
|
|
55
|
+
"br": C.HEAD, "hr": C.HEAD, "wbr": C.HEAD, "iframe": C.MEDIA, "embed": C.MEDIA, "object": C.MEDIA
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const theme = {
|
|
59
|
+
underline_tags: [],
|
|
60
|
+
tag: {
|
|
61
|
+
...DFLT_BUILTIN_TAGS,
|
|
62
|
+
___other___: C.L_BLUE // 自定义标签用亮蓝色区分
|
|
63
|
+
},
|
|
64
|
+
attrk: {
|
|
65
|
+
id: C.CYAN,
|
|
66
|
+
class: C.GREEN,
|
|
67
|
+
href: C.HEAD,
|
|
68
|
+
src : C.HEAD,
|
|
69
|
+
___other___: C.D_GRAY
|
|
70
|
+
},
|
|
71
|
+
attrv: {
|
|
72
|
+
id: BRIGHT + C.CYAN, // 更亮的青色
|
|
73
|
+
class: BRIGHT + C.GREEN, // 更亮的绿色
|
|
74
|
+
src:BRIGHT + C.L_BLUE,
|
|
75
|
+
href:BRIGHT + C.L_BLUE,
|
|
76
|
+
___other___: C.D_GRAY
|
|
77
|
+
},
|
|
78
|
+
underline_attrvs: ["id", "class", "href","src"],
|
|
79
|
+
txt: C.GRAY,
|
|
80
|
+
punc: C.D_GRAY,
|
|
81
|
+
reset:RESET,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// 辅助包装函数:处理 underline 和颜色合成
|
|
85
|
+
const paint = (type, key, val) => {
|
|
86
|
+
let color = theme[type][key] || theme[type].___other___;
|
|
87
|
+
let style = color;
|
|
88
|
+
if (type === 'tag' && theme.underline_tags.includes(key)) style += UNDERLINE;
|
|
89
|
+
if (type === 'attrv' && theme.underline_attrvs.includes(key)) style += UNDERLINE;
|
|
90
|
+
return `${style}${val}${RESET}`;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
module.exports = {
|
|
94
|
+
theme,
|
|
95
|
+
paint,
|
|
96
|
+
RESET,
|
|
97
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const {crsync} = require("nv-hson-der-from-str-cmmn");
|
|
4
|
+
|
|
5
|
+
const {theme,paint,RESET} = require("./colors");
|
|
6
|
+
|
|
7
|
+
const DFLT_CFG= ()=>({
|
|
8
|
+
just_show : true,
|
|
9
|
+
ignore_text: true,
|
|
10
|
+
max_depth : 5,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
module.exports = (html_str, cfg = DFLT_CFG(), COLORS = theme) => {
|
|
14
|
+
const { just_show, ignore_text, max_depth } = { ...DFLT_CFG(), ...cfg };
|
|
15
|
+
let painted_str = "";
|
|
16
|
+
|
|
17
|
+
const write = (s) => {
|
|
18
|
+
if (just_show) {
|
|
19
|
+
process.stdout.write(s);
|
|
20
|
+
} else {
|
|
21
|
+
painted_str += s;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const cbs = {
|
|
26
|
+
open: (tag, attr, id, depth) => {
|
|
27
|
+
if (depth > max_depth) return;
|
|
28
|
+
|
|
29
|
+
const indent = " ".repeat(depth);
|
|
30
|
+
const p_tag = paint('tag', tag, tag);
|
|
31
|
+
const p_lt = COLORS.punc + "<" + RESET;
|
|
32
|
+
const p_gt = COLORS.punc + ">" + RESET;
|
|
33
|
+
|
|
34
|
+
let attr_str = "";
|
|
35
|
+
for (let k in attr) {
|
|
36
|
+
const pk = paint('attrk', k, k);
|
|
37
|
+
const pv = paint('attrv', k, `"${attr[k]}"`);
|
|
38
|
+
attr_str += ` ${pk}${COLORS.punc}=${RESET}${pv}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
write(`${indent}${p_lt}${p_tag}${attr_str}${p_gt}\n`);
|
|
42
|
+
},
|
|
43
|
+
leaf: (tag, attr, id, depth) => {
|
|
44
|
+
if (depth > max_depth) return;
|
|
45
|
+
|
|
46
|
+
const indent = " ".repeat(depth);
|
|
47
|
+
const p_tag = paint('tag', tag, tag);
|
|
48
|
+
const p_lt = COLORS.punc + "<" + RESET;
|
|
49
|
+
const p_gt = COLORS.punc + " />" + RESET;
|
|
50
|
+
|
|
51
|
+
let attr_str = "";
|
|
52
|
+
for (let k in attr) {
|
|
53
|
+
const pk = paint('attrk', k, k);
|
|
54
|
+
const pv = paint('attrv', k, `"${attr[k]}"`);
|
|
55
|
+
attr_str += ` ${pk}${COLORS.punc}=${RESET}${pv}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
write(`${indent}${p_lt}${p_tag}${attr_str}${p_gt}\n`);
|
|
59
|
+
},
|
|
60
|
+
clos: (tag, id, depth, open_id) => {
|
|
61
|
+
if (depth > max_depth) return;
|
|
62
|
+
|
|
63
|
+
const indent = " ".repeat(depth);
|
|
64
|
+
const p_tag = paint('tag', tag, tag);
|
|
65
|
+
const p_punc_start = COLORS.punc + "</" + RESET;
|
|
66
|
+
const p_punc_end = COLORS.punc + ">" + RESET;
|
|
67
|
+
|
|
68
|
+
write(`${indent}${p_punc_start}${p_tag}${p_punc_end}\n`);
|
|
69
|
+
},
|
|
70
|
+
text: (txt, id, depth) => {
|
|
71
|
+
if (ignore_text || depth > max_depth) return;
|
|
72
|
+
|
|
73
|
+
const content = txt.trim();
|
|
74
|
+
if (content.length === 0) return;
|
|
75
|
+
|
|
76
|
+
const indent = " ".repeat(depth);
|
|
77
|
+
const p_txt = COLORS.txt + content + RESET;
|
|
78
|
+
write(`${indent}${p_txt}\n`);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const ma = crsync(cbs);
|
|
83
|
+
ma.exe(html_str);
|
|
84
|
+
ma.fin();
|
|
85
|
+
|
|
86
|
+
if (!just_show) {
|
|
87
|
+
return painted_str;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
module.exports.THEME =theme;
|
|
92
|
+
module.exports.DFLT_CFG = DFLT_CFG();
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nv-html-term-paint",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"author": "",
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"description": "",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"nv-hson-der-from-str-cmmn": "^1.0.3"
|
|
13
|
+
}
|
|
14
|
+
}
|