@shikijs/cli 3.23.0 → 4.0.0
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/dist/cli.d.mts +6 -8
- package/dist/cli.mjs +76 -84
- package/dist/code-to-ansi-CSjnm3mQ.mjs +66 -0
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +3 -4
- package/package.json +7 -4
- package/dist/shared/cli.Ddl0vE4t.mjs +0 -68
package/dist/cli.d.mts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
//#region src/cli.d.ts
|
|
1
2
|
declare function isUrl(path: string): boolean;
|
|
2
3
|
declare function getExtFromUrl(url: string): string;
|
|
3
4
|
declare function readSource(path: string): Promise<{
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
content: string;
|
|
6
|
+
ext: string;
|
|
6
7
|
}>;
|
|
7
|
-
declare function run(argv?: string[], log?:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}): Promise<void>;
|
|
11
|
-
|
|
12
|
-
export { getExtFromUrl, isUrl, readSource, run };
|
|
8
|
+
declare function run(argv?: string[], log?: (...data: any[]) => void): Promise<void>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { getExtFromUrl, isUrl, readSource, run };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,96 +1,88 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import '@shikijs/vscode-textmate';
|
|
7
|
-
import 'ansis';
|
|
8
|
-
import 'shiki';
|
|
1
|
+
import { t as codeToANSI } from "./code-to-ansi-CSjnm3mQ.mjs";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { parse } from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import cac from "cac";
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
//#region package.json
|
|
8
|
+
var version = "4.0.0";
|
|
11
9
|
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/cli.ts
|
|
12
12
|
function isUrl(path) {
|
|
13
|
-
|
|
13
|
+
return path.startsWith("http://") || path.startsWith("https://");
|
|
14
14
|
}
|
|
15
15
|
function getExtFromUrl(url) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
try {
|
|
17
|
+
const pathname = new URL(url).pathname;
|
|
18
|
+
return parse(pathname).ext.slice(1).toLowerCase();
|
|
19
|
+
} catch {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
22
|
}
|
|
23
23
|
async function readSource(path) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return { content, ext };
|
|
36
|
-
}
|
|
24
|
+
if (isUrl(path)) {
|
|
25
|
+
const response = await fetch(path);
|
|
26
|
+
if (!response.ok) throw new Error(`Failed to fetch ${path}: ${response.status} ${response.statusText}`);
|
|
27
|
+
return {
|
|
28
|
+
content: await response.text(),
|
|
29
|
+
ext: getExtFromUrl(path)
|
|
30
|
+
};
|
|
31
|
+
} else return {
|
|
32
|
+
content: await fs.readFile(path, "utf-8"),
|
|
33
|
+
ext: parse(path).ext.slice(1).toLowerCase()
|
|
34
|
+
};
|
|
37
35
|
}
|
|
38
36
|
async function run(argv = process.argv, log = console.log) {
|
|
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
|
-
} else {
|
|
88
|
-
return await codeToANSI(content, lang, options.theme);
|
|
89
|
-
}
|
|
90
|
-
}));
|
|
91
|
-
for (const code of codes)
|
|
92
|
-
log(code);
|
|
37
|
+
const cli = cac("shiki");
|
|
38
|
+
cli.option("--theme <theme>", "Color theme to use", { default: "vitesse-dark" }).option("--lang <lang>", "Programming language").option("--format <format>", "Output format (ansi, html)", { default: "ansi" }).option("--list-themes", "List all available themes").option("--list-langs", "List all available languages").help().version(version);
|
|
39
|
+
const { options, args } = cli.parse(argv);
|
|
40
|
+
if (options.listThemes) {
|
|
41
|
+
const { bundledThemes } = await import("shiki");
|
|
42
|
+
for (const theme of Object.keys(bundledThemes)) log(theme);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (options.listLangs) {
|
|
46
|
+
const { bundledLanguages } = await import("shiki");
|
|
47
|
+
for (const lang of Object.keys(bundledLanguages)) log(lang);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const files = args;
|
|
51
|
+
if (files.length === 0) {
|
|
52
|
+
if (!process.stdin.isTTY) {
|
|
53
|
+
const content = await new Promise((resolve, reject) => {
|
|
54
|
+
let data = "";
|
|
55
|
+
process.stdin.on("data", (chunk) => data += chunk);
|
|
56
|
+
process.stdin.on("end", () => resolve(data));
|
|
57
|
+
process.stdin.on("error", reject);
|
|
58
|
+
});
|
|
59
|
+
const lang = options.lang || "text";
|
|
60
|
+
if (options.format === "html") {
|
|
61
|
+
const { codeToHtml } = await import("shiki");
|
|
62
|
+
log(await codeToHtml(content, {
|
|
63
|
+
lang,
|
|
64
|
+
theme: options.theme
|
|
65
|
+
}));
|
|
66
|
+
} else log(await codeToANSI(content, lang, options.theme));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
cli.outputHelp();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const codes = await Promise.all(files.map(async (path) => {
|
|
73
|
+
const { content, ext } = await readSource(path);
|
|
74
|
+
const lang = (options.lang || ext).toLowerCase();
|
|
75
|
+
if (options.format === "html") {
|
|
76
|
+
const { codeToHtml } = await import("shiki");
|
|
77
|
+
return await codeToHtml(content, {
|
|
78
|
+
lang,
|
|
79
|
+
theme: options.theme
|
|
80
|
+
});
|
|
81
|
+
} else return await codeToANSI(content, lang, options.theme);
|
|
82
|
+
}));
|
|
83
|
+
for (const code of codes) log(code);
|
|
93
84
|
}
|
|
94
85
|
run();
|
|
95
86
|
|
|
96
|
-
|
|
87
|
+
//#endregion
|
|
88
|
+
export { getExtFromUrl, isUrl, readSource, run };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { FontStyle } from "@shikijs/vscode-textmate";
|
|
2
|
+
import c from "ansis";
|
|
3
|
+
import { codeToTokensBase, getSingletonHighlighter } from "shiki";
|
|
4
|
+
|
|
5
|
+
//#region src/colors.ts
|
|
6
|
+
function normalizeHex(hex) {
|
|
7
|
+
hex = hex.replace(/#/, "");
|
|
8
|
+
if (hex.length === 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
9
|
+
if (hex.length === 4) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
|
|
10
|
+
if (hex.length === 6) hex = `${hex}ff`;
|
|
11
|
+
return hex.toLowerCase();
|
|
12
|
+
}
|
|
13
|
+
function hexToRgba(hex) {
|
|
14
|
+
hex = normalizeHex(hex);
|
|
15
|
+
return {
|
|
16
|
+
r: Number.parseInt(hex.slice(0, 2), 16),
|
|
17
|
+
g: Number.parseInt(hex.slice(2, 4), 16),
|
|
18
|
+
b: Number.parseInt(hex.slice(4, 6), 16),
|
|
19
|
+
a: Number.parseInt(hex.slice(6, 8), 16) / 255
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function RgbToHex(r, g, b) {
|
|
23
|
+
return [
|
|
24
|
+
r,
|
|
25
|
+
g,
|
|
26
|
+
b
|
|
27
|
+
].map((x) => {
|
|
28
|
+
const hex = x.toString(16);
|
|
29
|
+
return hex.length === 1 ? `0${hex}` : hex;
|
|
30
|
+
}).join("");
|
|
31
|
+
}
|
|
32
|
+
function hexApplyAlpha(hex, type = "dark") {
|
|
33
|
+
const { r, g, b, a } = hexToRgba(hex);
|
|
34
|
+
if (type === "dark") return RgbToHex(r * a, g * a, b * a);
|
|
35
|
+
else return RgbToHex(r * a + 255 * (1 - a), g * a + 255 * (1 - a), b * a + 255 * (1 - a));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/code-to-ansi.ts
|
|
40
|
+
async function codeToANSI(code, lang, theme) {
|
|
41
|
+
let output = "";
|
|
42
|
+
const lines = await codeToTokensBase(code, {
|
|
43
|
+
lang,
|
|
44
|
+
theme
|
|
45
|
+
});
|
|
46
|
+
const themeReg = (await getSingletonHighlighter()).getTheme(theme);
|
|
47
|
+
for (const line of lines) {
|
|
48
|
+
for (const token of line) {
|
|
49
|
+
let text = token.content;
|
|
50
|
+
const color = token.color || themeReg.fg;
|
|
51
|
+
if (color) text = c.hex(hexApplyAlpha(color, themeReg.type))(text);
|
|
52
|
+
if (token.fontStyle) {
|
|
53
|
+
if (token.fontStyle & FontStyle.Bold) text = c.bold(text);
|
|
54
|
+
if (token.fontStyle & FontStyle.Italic) text = c.italic(text);
|
|
55
|
+
if (token.fontStyle & FontStyle.Underline) text = c.underline(text);
|
|
56
|
+
if (token.fontStyle & FontStyle.Strikethrough) text = c.strikethrough(text);
|
|
57
|
+
}
|
|
58
|
+
output += text;
|
|
59
|
+
}
|
|
60
|
+
output += "\n";
|
|
61
|
+
}
|
|
62
|
+
return output;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
export { codeToANSI as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { BundledLanguage, BundledTheme } from
|
|
1
|
+
import { BundledLanguage, BundledTheme } from "shiki";
|
|
2
2
|
|
|
3
|
+
//#region src/code-to-ansi.d.ts
|
|
3
4
|
declare function codeToANSI(code: string, lang: BundledLanguage, theme: BundledTheme): Promise<string>;
|
|
4
|
-
|
|
5
|
-
export { codeToANSI };
|
|
5
|
+
//#endregion
|
|
6
|
+
export { codeToANSI };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import 'shiki';
|
|
1
|
+
import { t as codeToANSI } from "./code-to-ansi-CSjnm3mQ.mjs";
|
|
2
|
+
|
|
3
|
+
export { codeToANSI };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shikijs/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"description": "Shiki in the command line",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -35,14 +35,17 @@
|
|
|
35
35
|
"bin.mjs",
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
},
|
|
38
41
|
"dependencies": {
|
|
39
42
|
"@shikijs/vscode-textmate": "^10.0.2",
|
|
40
43
|
"ansis": "^4.2.0",
|
|
41
44
|
"cac": "^6.7.14",
|
|
42
|
-
"shiki": "
|
|
45
|
+
"shiki": "4.0.0"
|
|
43
46
|
},
|
|
44
47
|
"scripts": {
|
|
45
|
-
"build": "
|
|
46
|
-
"dev": "
|
|
48
|
+
"build": "tsdown",
|
|
49
|
+
"dev": "tsdown --watch"
|
|
47
50
|
}
|
|
48
51
|
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { FontStyle } from '@shikijs/vscode-textmate';
|
|
2
|
-
import c from 'ansis';
|
|
3
|
-
import { codeToTokensBase, getSingletonHighlighter } from 'shiki';
|
|
4
|
-
|
|
5
|
-
function normalizeHex(hex) {
|
|
6
|
-
hex = hex.replace(/#/, "");
|
|
7
|
-
if (hex.length === 3)
|
|
8
|
-
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
9
|
-
if (hex.length === 4)
|
|
10
|
-
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
|
|
11
|
-
if (hex.length === 6)
|
|
12
|
-
hex = `${hex}ff`;
|
|
13
|
-
return hex.toLowerCase();
|
|
14
|
-
}
|
|
15
|
-
function hexToRgba(hex) {
|
|
16
|
-
hex = normalizeHex(hex);
|
|
17
|
-
const r = Number.parseInt(hex.slice(0, 2), 16);
|
|
18
|
-
const g = Number.parseInt(hex.slice(2, 4), 16);
|
|
19
|
-
const b = Number.parseInt(hex.slice(4, 6), 16);
|
|
20
|
-
const a = Number.parseInt(hex.slice(6, 8), 16) / 255;
|
|
21
|
-
return { r, g, b, a };
|
|
22
|
-
}
|
|
23
|
-
function RgbToHex(r, g, b) {
|
|
24
|
-
return [r, g, b].map((x) => {
|
|
25
|
-
const hex = x.toString(16);
|
|
26
|
-
return hex.length === 1 ? `0${hex}` : hex;
|
|
27
|
-
}).join("");
|
|
28
|
-
}
|
|
29
|
-
function hexApplyAlpha(hex, type = "dark") {
|
|
30
|
-
const { r, g, b, a } = hexToRgba(hex);
|
|
31
|
-
if (type === "dark")
|
|
32
|
-
return RgbToHex(r * a, g * a, b * a);
|
|
33
|
-
else
|
|
34
|
-
return RgbToHex(r * a + 255 * (1 - a), g * a + 255 * (1 - a), b * a + 255 * (1 - a));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function codeToANSI(code, lang, theme) {
|
|
38
|
-
let output = "";
|
|
39
|
-
const lines = await codeToTokensBase(code, {
|
|
40
|
-
lang,
|
|
41
|
-
theme
|
|
42
|
-
});
|
|
43
|
-
const highlight = await getSingletonHighlighter();
|
|
44
|
-
const themeReg = highlight.getTheme(theme);
|
|
45
|
-
for (const line of lines) {
|
|
46
|
-
for (const token of line) {
|
|
47
|
-
let text = token.content;
|
|
48
|
-
const color = token.color || themeReg.fg;
|
|
49
|
-
if (color)
|
|
50
|
-
text = c.hex(hexApplyAlpha(color, themeReg.type))(text);
|
|
51
|
-
if (token.fontStyle) {
|
|
52
|
-
if (token.fontStyle & FontStyle.Bold)
|
|
53
|
-
text = c.bold(text);
|
|
54
|
-
if (token.fontStyle & FontStyle.Italic)
|
|
55
|
-
text = c.italic(text);
|
|
56
|
-
if (token.fontStyle & FontStyle.Underline)
|
|
57
|
-
text = c.underline(text);
|
|
58
|
-
if (token.fontStyle & FontStyle.Strikethrough)
|
|
59
|
-
text = c.strikethrough(text);
|
|
60
|
-
}
|
|
61
|
-
output += text;
|
|
62
|
-
}
|
|
63
|
-
output += "\n";
|
|
64
|
-
}
|
|
65
|
-
return output;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export { codeToANSI as c };
|