@moewolf/moe-icons-cli 0.0.1 → 0.0.3
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 +249 -10
- package/bin/check-node.cjs +36 -0
- package/bin/moeicons.js +12 -1
- package/dist/api/client.d.ts +13 -2
- package/dist/api/client.js +145 -21
- package/dist/auth/device-login.d.ts +10 -7
- package/dist/auth/device-login.js +60 -37
- package/dist/auth/login-schemas.d.ts +24 -0
- package/dist/auth/login-schemas.js +67 -0
- package/dist/catalog/catalog.d.ts +11 -0
- package/dist/catalog/catalog.js +43 -0
- package/dist/catalog/catalog.json +12768 -3965
- package/dist/cli.d.ts +11 -2
- package/dist/cli.js +773 -147
- package/dist/commands/parser.d.ts +13 -2
- package/dist/commands/parser.js +138 -50
- package/dist/config-package/generated/SOURCE.json +25 -0
- package/dist/config-package/generated/moeicons-config.schema.json +191 -0
- package/dist/config-package/generated/moeicons.config.jsonc +42 -0
- package/dist/config-package/generated/render-config.cjs +145 -0
- package/dist/config-package/generated/validate-config.cjs +293 -0
- package/dist/config-package/generated-config.d.ts +32 -0
- package/dist/config-package/generated-config.js +19 -0
- package/dist/core/auth.d.ts +24 -0
- package/dist/core/auth.js +127 -8
- package/dist/core/bitmap-assets.d.ts +19 -5
- package/dist/core/bitmap-assets.js +40 -31
- package/dist/core/bitmap-shard-budget.d.ts +43 -0
- package/dist/core/bitmap-shard-budget.js +16 -0
- package/dist/core/bitmap-shard-cache.d.ts +68 -0
- package/dist/core/bitmap-shard-cache.js +115 -0
- package/dist/core/bitmap-shard-download.d.ts +130 -0
- package/dist/core/bitmap-shard-download.js +359 -0
- package/dist/core/bitmap-shard-resolver.d.ts +129 -0
- package/dist/core/bitmap-shard-resolver.js +262 -0
- package/dist/core/bitmap-shards.d.ts +70 -0
- package/dist/core/bitmap-shards.js +249 -0
- package/dist/core/bootstrap.d.ts +37 -0
- package/dist/core/bootstrap.js +54 -0
- package/dist/core/cache.d.ts +34 -0
- package/dist/core/cache.js +96 -0
- package/dist/core/context.d.ts +26 -0
- package/dist/core/doctor.d.ts +48 -0
- package/dist/core/doctor.js +190 -0
- package/dist/core/free-download.d.ts +64 -6
- package/dist/core/free-download.js +402 -30
- package/dist/core/generate.d.ts +29 -0
- package/dist/core/generate.js +341 -65
- package/dist/core/icon-selection.d.ts +8 -0
- package/dist/core/icon-selection.js +19 -0
- package/dist/core/install.d.ts +14 -0
- package/dist/core/install.js +132 -13
- package/dist/core/library-update.d.ts +5 -1
- package/dist/core/library-update.js +176 -17
- package/dist/core/local-test-env.d.ts +24 -0
- package/dist/core/local-test-env.js +43 -0
- package/dist/core/metadata-sync.d.ts +30 -0
- package/dist/core/metadata-sync.js +97 -0
- package/dist/core/pro-download.d.ts +63 -0
- package/dist/core/pro-download.js +247 -27
- package/dist/core/pro-install.d.ts +11 -3
- package/dist/core/pro-install.js +181 -19
- package/dist/core/pro-resources.d.ts +79 -0
- package/dist/core/pro-resources.js +204 -0
- package/dist/core/pro-selected-download.d.ts +18 -0
- package/dist/core/pro-selected-download.js +269 -0
- package/dist/core/release-descriptor.d.ts +42 -1
- package/dist/core/release-descriptor.js +117 -9
- package/dist/core/resource-variant.d.ts +27 -10
- package/dist/core/resource-variant.js +75 -34
- package/dist/core/selected-resources.d.ts +59 -0
- package/dist/core/selected-resources.js +350 -0
- package/dist/core/signed-artifact.d.ts +8 -1
- package/dist/core/signed-artifact.js +35 -11
- package/dist/core/target-subtree.d.ts +8 -0
- package/dist/core/target-subtree.js +54 -3
- package/dist/core/version-service.d.ts +11 -0
- package/dist/core/version-service.js +129 -24
- package/dist/core/wizard.d.ts +20 -17
- package/dist/core/wizard.js +66 -28
- package/dist/errors/errors.d.ts +2 -1
- package/dist/errors/errors.js +1 -0
- package/dist/generator/generate.d.ts +1 -1
- package/dist/generator/generate.js +420 -213
- package/dist/generator/shared/SOURCE.json +7 -0
- package/dist/generator/shared/svg-model.cjs +156 -0
- package/dist/generator/svg-model.d.ts +16 -0
- package/dist/generator/svg-model.js +4 -0
- package/dist/generator/theme-resolve.d.ts +2 -0
- package/dist/generator/theme-resolve.js +57 -26
- package/dist/mcp/server.d.ts +23 -36
- package/dist/mcp/server.js +74 -152
- package/dist/mcp/services.d.ts +4 -0
- package/dist/mcp/services.js +230 -0
- package/dist/metadata/archive.d.ts +38 -0
- package/dist/metadata/archive.js +94 -0
- package/dist/metadata/manifest.d.ts +33 -0
- package/dist/metadata/manifest.js +136 -0
- package/dist/metadata/version.d.ts +22 -0
- package/dist/metadata/version.js +53 -0
- package/dist/project/anchors/application.d.ts +13 -0
- package/dist/project/anchors/application.js +377 -0
- package/dist/project/anchors/apply.d.ts +28 -0
- package/dist/project/anchors/apply.js +65 -0
- package/dist/project/anchors/diagnose.d.ts +26 -0
- package/dist/project/anchors/diagnose.js +90 -0
- package/dist/project/anchors/helpers.d.ts +20 -0
- package/dist/project/anchors/helpers.js +55 -0
- package/dist/project/anchors/moeicons-config.d.ts +21 -0
- package/dist/project/anchors/moeicons-config.js +83 -0
- package/dist/project/anchors/parse.d.ts +14 -0
- package/dist/project/anchors/parse.js +36 -0
- package/dist/project/anchors/project-manifest.d.ts +19 -0
- package/dist/project/anchors/project-manifest.js +109 -0
- package/dist/project/anchors/style.d.ts +12 -0
- package/dist/project/anchors/style.js +87 -0
- package/dist/project/anchors/types.d.ts +32 -0
- package/dist/project/anchors/types.js +9 -0
- package/dist/project/config.d.ts +59 -5
- package/dist/project/config.js +234 -102
- package/dist/project/install-metadata.d.ts +23 -2
- package/dist/project/install-metadata.js +58 -7
- package/dist/project/install.d.ts +24 -4
- package/dist/project/install.js +402 -190
- package/dist/project/project-lock.d.ts +2 -2
- package/dist/project/project-lock.js +4 -4
- package/dist/project/tailwind.d.ts +2 -2
- package/dist/project/tailwind.js +3 -4
- package/dist/project/tar-gz.d.ts +18 -1
- package/dist/project/tar-gz.js +40 -3
- package/dist/tui/components.d.ts +62 -0
- package/dist/tui/components.js +100 -0
- package/dist/tui/primitives.d.ts +1 -0
- package/dist/tui/primitives.js +8 -1
- package/dist/ui/banner.d.ts +31 -3
- package/dist/ui/banner.js +120 -25
- package/dist/ui/branded-prompts.d.ts +41 -0
- package/dist/ui/branded-prompts.js +80 -0
- package/dist/ui/clack.d.ts +6 -3
- package/dist/ui/clack.js +56 -5
- package/dist/ui/create-ui.d.ts +1 -0
- package/dist/ui/create-ui.js +5 -1
- package/dist/ui/generated/wordmark-large.d.ts +17 -0
- package/dist/ui/generated/wordmark-large.js +28 -0
- package/dist/ui/generated/wordmark.d.ts +2 -0
- package/dist/ui/generated/wordmark.js +2 -0
- package/dist/ui/non-interactive.js +8 -0
- package/dist/ui/stream.js +30 -0
- package/dist/ui/theme.d.ts +42 -0
- package/dist/ui/theme.js +59 -0
- package/package.json +14 -6
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ConfirmPrompt, SelectPrompt, isCancel } from "@clack/core";
|
|
2
|
+
import { CONFIRM_KEY_HINTS, SELECT_KEY_HINTS, renderKeyHints } from "../tui/components.js";
|
|
3
|
+
import { visibleWidth } from "./banner.js";
|
|
4
|
+
export { isCancel };
|
|
5
|
+
/** Format `1. label` with stable width for lists of 10+. */
|
|
6
|
+
export function formatChoiceNumber(index, total, label) {
|
|
7
|
+
const width = String(Math.max(total, 1)).length;
|
|
8
|
+
return `${String(index + 1).padStart(width, " ")}. ${label}`;
|
|
9
|
+
}
|
|
10
|
+
/** Renders every option with 1-based numbers. Back separators are blank lines. */
|
|
11
|
+
export function renderSelectFrame(prompt, message, theme, options = {}) {
|
|
12
|
+
const { pointer, submit, cancel } = theme.symbols;
|
|
13
|
+
const total = prompt.options.length;
|
|
14
|
+
const numbered = (index, label) => formatChoiceNumber(index, total, label);
|
|
15
|
+
if (prompt.state === "cancel")
|
|
16
|
+
return theme.red(`${cancel} Cancelled`);
|
|
17
|
+
if (prompt.state === "submit") {
|
|
18
|
+
const selected = prompt.options[prompt.cursor];
|
|
19
|
+
return theme.blue(`${submit} ${selected ? numbered(prompt.cursor, selected.label) : ""}`);
|
|
20
|
+
}
|
|
21
|
+
const lines = [message];
|
|
22
|
+
const inactivePad = " ".repeat(visibleWidth(pointer) + 1);
|
|
23
|
+
for (const [index, option] of prompt.options.entries()) {
|
|
24
|
+
if (option.separatorBefore)
|
|
25
|
+
lines.push("");
|
|
26
|
+
const text = numbered(index, option.label);
|
|
27
|
+
if (index === prompt.cursor)
|
|
28
|
+
lines.push(theme.blue(`${pointer} ${text}`));
|
|
29
|
+
else
|
|
30
|
+
lines.push(`${inactivePad}${text}`);
|
|
31
|
+
}
|
|
32
|
+
if (options.hints)
|
|
33
|
+
lines.push(renderKeyHints(SELECT_KEY_HINTS, theme));
|
|
34
|
+
return lines.join("\n");
|
|
35
|
+
}
|
|
36
|
+
export function renderConfirmFrame(prompt, message, theme, options = {}) {
|
|
37
|
+
const { radio, submit, cancel } = theme.symbols;
|
|
38
|
+
if (prompt.state === "cancel")
|
|
39
|
+
return theme.red(`${cancel} Cancelled`);
|
|
40
|
+
if (prompt.state === "submit") {
|
|
41
|
+
return prompt.value ? theme.blue(`${submit} Confirmed`) : theme.red(`${cancel} No`);
|
|
42
|
+
}
|
|
43
|
+
const yes = prompt.value ? theme.blue(`${radio} Yes`) : theme.blue("Yes");
|
|
44
|
+
const no = prompt.value ? theme.red("No") : theme.red(`${radio} No`);
|
|
45
|
+
return options.hints ? `${message}\n${yes} ${no}\n${renderKeyHints(CONFIRM_KEY_HINTS, theme)}` : `${message}\n${yes} ${no}`;
|
|
46
|
+
}
|
|
47
|
+
export async function brandedSelect(options) {
|
|
48
|
+
const frameOptions = options.choices.map((choice) => ({
|
|
49
|
+
value: choice.value,
|
|
50
|
+
label: choice.label,
|
|
51
|
+
...(choice.separatorBefore ? { separatorBefore: true } : {}),
|
|
52
|
+
}));
|
|
53
|
+
const prompt = new SelectPrompt({
|
|
54
|
+
options: frameOptions.map((choice) => ({ value: choice.value, label: choice.label })),
|
|
55
|
+
...(options.input ? { input: options.input } : {}),
|
|
56
|
+
...(options.output ? { output: options.output } : {}),
|
|
57
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
58
|
+
render() {
|
|
59
|
+
return renderSelectFrame({ state: this.state, cursor: this.cursor, options: frameOptions }, options.message, options.theme, { hints: true });
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
return prompt.prompt();
|
|
63
|
+
}
|
|
64
|
+
export async function brandedConfirm(options) {
|
|
65
|
+
const prompt = new ConfirmPrompt({
|
|
66
|
+
active: "Yes",
|
|
67
|
+
inactive: "No",
|
|
68
|
+
initialValue: true,
|
|
69
|
+
...(options.input ? { input: options.input } : {}),
|
|
70
|
+
...(options.output ? { output: options.output } : {}),
|
|
71
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
72
|
+
render() {
|
|
73
|
+
return renderConfirmFrame(this, options.message, options.theme, { hints: true });
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const value = await prompt.prompt();
|
|
77
|
+
if (isCancel(value))
|
|
78
|
+
return value;
|
|
79
|
+
return Boolean(value);
|
|
80
|
+
}
|
package/dist/ui/clack.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { CommandUi } from "../core/context.js";
|
|
2
|
+
import type { UiTheme } from "./theme.js";
|
|
3
|
+
export interface ClackUiOptions {
|
|
4
|
+
readonly yes: boolean;
|
|
5
|
+
readonly theme: UiTheme;
|
|
6
|
+
}
|
|
2
7
|
/**
|
|
3
8
|
* Clack adapter. Maps Clack's cancel symbol to `undefined` so core never sees
|
|
4
9
|
* Clack types, ANSI, or `process.exit()`.
|
|
5
10
|
*/
|
|
6
|
-
export declare function createClackUi(options:
|
|
7
|
-
readonly yes: boolean;
|
|
8
|
-
}): CommandUi;
|
|
11
|
+
export declare function createClackUi(options: ClackUiOptions): CommandUi;
|
package/dist/ui/clack.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
+
import { isCancel } from "@clack/core";
|
|
2
3
|
import { CliError } from "../errors/index.js";
|
|
4
|
+
import { brandedConfirm, brandedSelect } from "./branded-prompts.js";
|
|
5
|
+
import { renderProgressBar, renderTaskStatus } from "../tui/components.js";
|
|
3
6
|
function throwIfAborted(signal) {
|
|
4
7
|
if (signal.aborted)
|
|
5
8
|
throw new CliError("CANCELLED", "cancelled");
|
|
@@ -12,11 +15,13 @@ export function createClackUi(options) {
|
|
|
12
15
|
return {
|
|
13
16
|
async select(message, choices, signal) {
|
|
14
17
|
throwIfAborted(signal);
|
|
15
|
-
const value = await
|
|
18
|
+
const value = await brandedSelect({
|
|
16
19
|
message,
|
|
17
|
-
|
|
20
|
+
choices,
|
|
21
|
+
signal,
|
|
22
|
+
theme: options.theme,
|
|
18
23
|
});
|
|
19
|
-
if (
|
|
24
|
+
if (isCancel(value))
|
|
20
25
|
return undefined;
|
|
21
26
|
return String(value);
|
|
22
27
|
},
|
|
@@ -24,8 +29,12 @@ export function createClackUi(options) {
|
|
|
24
29
|
throwIfAborted(signal);
|
|
25
30
|
if (options.yes)
|
|
26
31
|
return true;
|
|
27
|
-
const value = await
|
|
28
|
-
|
|
32
|
+
const value = await brandedConfirm({
|
|
33
|
+
message,
|
|
34
|
+
signal,
|
|
35
|
+
theme: options.theme,
|
|
36
|
+
});
|
|
37
|
+
if (isCancel(value))
|
|
29
38
|
return undefined;
|
|
30
39
|
return value;
|
|
31
40
|
},
|
|
@@ -49,5 +58,47 @@ export function createClackUi(options) {
|
|
|
49
58
|
},
|
|
50
59
|
};
|
|
51
60
|
},
|
|
61
|
+
// W3-A: clack has no bar primitive, so the bar is rendered as the spinner
|
|
62
|
+
// message. Unknown totals degrade to a byte counter (never a fake percent).
|
|
63
|
+
progressBar(label, signal) {
|
|
64
|
+
throwIfAborted(signal);
|
|
65
|
+
const spinner = p.spinner();
|
|
66
|
+
spinner.start(label);
|
|
67
|
+
const startedAt = Date.now();
|
|
68
|
+
let latest = {};
|
|
69
|
+
const paint = () => {
|
|
70
|
+
const columns = process.stdout?.columns ?? 80;
|
|
71
|
+
spinner.message(renderProgressBar({
|
|
72
|
+
label: latest.label ?? label,
|
|
73
|
+
theme: options.theme,
|
|
74
|
+
columns,
|
|
75
|
+
elapsedMs: Date.now() - startedAt,
|
|
76
|
+
...(latest.done !== undefined ? { done: latest.done } : {}),
|
|
77
|
+
...(latest.total !== undefined ? { total: latest.total } : {}),
|
|
78
|
+
...(latest.detail !== undefined ? { detail: latest.detail } : {}),
|
|
79
|
+
}));
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
update(event) {
|
|
83
|
+
latest = { ...latest, ...(event ?? {}) };
|
|
84
|
+
paint();
|
|
85
|
+
},
|
|
86
|
+
stop(done) { spinner.stop(done ?? renderTaskStatus({ state: "success", label, theme: options.theme })); },
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
// W3-C: strict task lifecycle for work without a progress bar.
|
|
90
|
+
task(label, signal) {
|
|
91
|
+
throwIfAborted(signal);
|
|
92
|
+
const spinner = p.spinner();
|
|
93
|
+
spinner.start(`${options.theme.dim("…")} ${label}`);
|
|
94
|
+
const finish = (state, message) => {
|
|
95
|
+
spinner.stop(renderTaskStatus({ state, label, ...(message ? { detail: message } : {}), theme: options.theme }));
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
succeed(message) { finish("success", message); },
|
|
99
|
+
fail(message) { finish("failure", message); },
|
|
100
|
+
timeout(message) { finish("timeout", message); },
|
|
101
|
+
};
|
|
102
|
+
},
|
|
52
103
|
};
|
|
53
104
|
}
|
package/dist/ui/create-ui.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface CreateUiOptions {
|
|
|
6
6
|
readonly isTTY: boolean;
|
|
7
7
|
/** Present in tests (and optional in production). When set, skip Clack so prompts are injectable. */
|
|
8
8
|
readonly streams?: StreamUiRuntime;
|
|
9
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Pick a UI adapter. `--json` and non-TTY never render Clack/banner-capable prompts.
|
package/dist/ui/create-ui.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createClackUi } from "./clack.js";
|
|
2
2
|
import { createNonInteractiveUi } from "./non-interactive.js";
|
|
3
3
|
import { createStreamUi } from "./stream.js";
|
|
4
|
+
import { createTheme, isThemeEnabled } from "./theme.js";
|
|
4
5
|
/**
|
|
5
6
|
* Pick a UI adapter. `--json` and non-TTY never render Clack/banner-capable prompts.
|
|
6
7
|
* TTY with injected streams uses the stream adapter; real TTY uses Clack.
|
|
@@ -12,5 +13,8 @@ export function createCommandUi(options) {
|
|
|
12
13
|
if (options.streams?.readLine) {
|
|
13
14
|
return createStreamUi(options.streams, { yes: options.yes });
|
|
14
15
|
}
|
|
15
|
-
return createClackUi({
|
|
16
|
+
return createClackUi({
|
|
17
|
+
yes: options.yes,
|
|
18
|
+
theme: createTheme(isThemeEnabled(options.env, options.isTTY)),
|
|
19
|
+
});
|
|
16
20
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen DOS Rebel "MOEICONS" wordmark (PLAN 2026-09-07).
|
|
3
|
+
* No ANSI. Trailing spaces stripped. Glyph column ranges are exclusive `end`.
|
|
4
|
+
* Colors alternate blue/red by letter; ██ keep the terminal default foreground.
|
|
5
|
+
*/
|
|
6
|
+
export declare const WORDMARK_LARGE_WIDTH = 101;
|
|
7
|
+
/** Eight content rows; max visible width is 101. */
|
|
8
|
+
export declare const MOEICONS_WORDMARK_LARGE: readonly [" ██████ ██████ ███████ ██████████ █████ █████████ ███████ ██████ █████ █████████", "░░██████ ██████ ███░░░░░███ ░░███░░░░░█░░███ ███░░░░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███", " ░███░█████░███ ███ ░░███ ░███ █ ░ ░███ ███ ░░░ ███ ░░███ ░███░███ ░███ ░███ ░░░", " ░███░░███ ░███ ░███ ░███ ░██████ ░███ ░███ ░███ ░███ ░███░░███░███ ░░█████████", " ░███ ░░░ ░███ ░███ ░███ ░███░░█ ░███ ░███ ░███ ░███ ░███ ░░██████ ░░░░░░░░███", " ░███ ░███ ░░███ ███ ░███ ░ █ ░███ ░░███ ███░░███ ███ ░███ ░░█████ ███ ░███", " █████ █████ ░░░███████░ ██████████ █████ ░░█████████ ░░░███████░ █████ ░░█████░░█████████", "░░░░░ ░░░░░ ░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░"];
|
|
9
|
+
export type WordmarkGlyphColor = "blue" | "red";
|
|
10
|
+
export interface WordmarkGlyphRegion {
|
|
11
|
+
readonly letter: string;
|
|
12
|
+
readonly start: number;
|
|
13
|
+
readonly end: number;
|
|
14
|
+
readonly shade: WordmarkGlyphColor;
|
|
15
|
+
}
|
|
16
|
+
/** DOS Rebel per-letter advance widths; indices assume a 101-column padded canvas. */
|
|
17
|
+
export declare const WORDMARK_LARGE_GLYPHS: readonly WordmarkGlyphRegion[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen DOS Rebel "MOEICONS" wordmark (PLAN 2026-09-07).
|
|
3
|
+
* No ANSI. Trailing spaces stripped. Glyph column ranges are exclusive `end`.
|
|
4
|
+
* Colors alternate blue/red by letter; ██ keep the terminal default foreground.
|
|
5
|
+
*/
|
|
6
|
+
export const WORDMARK_LARGE_WIDTH = 101;
|
|
7
|
+
/** Eight content rows; max visible width is 101. */
|
|
8
|
+
export const MOEICONS_WORDMARK_LARGE = [
|
|
9
|
+
" ██████ ██████ ███████ ██████████ █████ █████████ ███████ ██████ █████ █████████",
|
|
10
|
+
"░░██████ ██████ ███░░░░░███ ░░███░░░░░█░░███ ███░░░░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███",
|
|
11
|
+
" ░███░█████░███ ███ ░░███ ░███ █ ░ ░███ ███ ░░░ ███ ░░███ ░███░███ ░███ ░███ ░░░",
|
|
12
|
+
" ░███░░███ ░███ ░███ ░███ ░██████ ░███ ░███ ░███ ░███ ░███░░███░███ ░░█████████",
|
|
13
|
+
" ░███ ░░░ ░███ ░███ ░███ ░███░░█ ░███ ░███ ░███ ░███ ░███ ░░██████ ░░░░░░░░███",
|
|
14
|
+
" ░███ ░███ ░░███ ███ ░███ ░ █ ░███ ░░███ ███░░███ ███ ░███ ░░█████ ███ ░███",
|
|
15
|
+
" █████ █████ ░░░███████░ ██████████ █████ ░░█████████ ░░░███████░ █████ ░░█████░░█████████",
|
|
16
|
+
"░░░░░ ░░░░░ ░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░",
|
|
17
|
+
];
|
|
18
|
+
/** DOS Rebel per-letter advance widths; indices assume a 101-column padded canvas. */
|
|
19
|
+
export const WORDMARK_LARGE_GLYPHS = [
|
|
20
|
+
{ letter: "M", start: 0, end: 16, shade: "blue" },
|
|
21
|
+
{ letter: "O", start: 16, end: 30, shade: "red" },
|
|
22
|
+
{ letter: "E", start: 30, end: 41, shade: "blue" },
|
|
23
|
+
{ letter: "I", start: 41, end: 47, shade: "red" },
|
|
24
|
+
{ letter: "C", start: 47, end: 60, shade: "blue" },
|
|
25
|
+
{ letter: "O", start: 60, end: 74, shade: "red" },
|
|
26
|
+
{ letter: "N", start: 74, end: 89, shade: "blue" },
|
|
27
|
+
{ letter: "S", start: 89, end: 101, shade: "red" },
|
|
28
|
+
];
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** ASCII wordmark generated by scripts/generate-banner.mjs (figlet, Standard font). Do not edit by hand. */
|
|
2
|
+
export declare const MOEICONS_BANNER = "\n __ __ ___ _____ ___ ____ ___ _ _ ____\n | \\/ |/ _ \\| ____|_ _/ ___/ _ \\| \\ | / ___|\n | |\\/| | | | | _| | | | | | | | \\| \\___ \\\n | | | | |_| | |___ | | |__| |_| | |\\ |___) |\n |_| |_|\\___/|_____|___\\____\\___/|_| \\_|____/\n";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** ASCII wordmark generated by scripts/generate-banner.mjs (figlet, Standard font). Do not edit by hand. */
|
|
2
|
+
export const MOEICONS_BANNER = "\n __ __ ___ _____ ___ ____ ___ _ _ ____\n | \\/ |/ _ \\| ____|_ _/ ___/ _ \\| \\ | / ___|\n | |\\/| | | | | _| | | | | | | | \\| \\___ \\\n | | | | |_| | |___ | | |__| |_| | |\\ |___) |\n |_| |_|\\___/|_____|___\\____\\___/|_| \\_|____/\n";
|
|
@@ -26,5 +26,13 @@ export function createNonInteractiveUi(options) {
|
|
|
26
26
|
progress() {
|
|
27
27
|
return { stop() { return undefined; } };
|
|
28
28
|
},
|
|
29
|
+
// W3: JSON / non-TTY must never emit progress noise; the structured result
|
|
30
|
+
// is the contract. These no-ops keep callers free of adapter branching.
|
|
31
|
+
progressBar() {
|
|
32
|
+
return { update() { return undefined; }, stop() { return undefined; } };
|
|
33
|
+
},
|
|
34
|
+
task() {
|
|
35
|
+
return { succeed() { return undefined; }, fail() { return undefined; }, timeout() { return undefined; } };
|
|
36
|
+
},
|
|
29
37
|
};
|
|
30
38
|
}
|
package/dist/ui/stream.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { confirm as promptConfirm, select as promptSelect, CancelledError } from "../tui/primitives.js";
|
|
2
2
|
import { CliError } from "../errors/index.js";
|
|
3
|
+
import { renderProgressBar, renderTaskStatus } from "../tui/components.js";
|
|
4
|
+
import { createTheme } from "./theme.js";
|
|
3
5
|
/** Injected-stream adapter used by tests. Production TTY uses the Clack adapter. */
|
|
4
6
|
export function createStreamUi(runtime, options) {
|
|
5
7
|
const deps = {
|
|
@@ -46,5 +48,33 @@ export function createStreamUi(runtime, options) {
|
|
|
46
48
|
runtime.stdout(`${message}\n`);
|
|
47
49
|
return { update(next) { runtime.stdout(`${next}\n`); }, stop() { return undefined; } };
|
|
48
50
|
},
|
|
51
|
+
// W3-A: injected-stream adapter logs one deterministic line per tick (no
|
|
52
|
+
// ANSI, no carriage returns) so tests assert exact progress output.
|
|
53
|
+
progressBar(label) {
|
|
54
|
+
const theme = createTheme(false);
|
|
55
|
+
let latest = {};
|
|
56
|
+
return {
|
|
57
|
+
update(event) {
|
|
58
|
+
latest = { ...latest, ...(event ?? {}) };
|
|
59
|
+
runtime.stdout(`${renderProgressBar({
|
|
60
|
+
label: latest.label ?? label,
|
|
61
|
+
theme,
|
|
62
|
+
...(latest.done !== undefined ? { done: latest.done } : {}),
|
|
63
|
+
...(latest.total !== undefined ? { total: latest.total } : {}),
|
|
64
|
+
...(latest.detail !== undefined ? { detail: latest.detail } : {}),
|
|
65
|
+
})}\n`);
|
|
66
|
+
},
|
|
67
|
+
stop(message) { if (message)
|
|
68
|
+
runtime.stdout(`${message}\n`); },
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
task(label) {
|
|
72
|
+
const theme = createTheme(false);
|
|
73
|
+
return {
|
|
74
|
+
succeed(message) { runtime.stdout(`${renderTaskStatus({ state: "success", label, ...(message ? { detail: message } : {}), theme })}\n`); },
|
|
75
|
+
fail(message) { runtime.stdout(`${renderTaskStatus({ state: "failure", label, ...(message ? { detail: message } : {}), theme })}\n`); },
|
|
76
|
+
timeout(message) { runtime.stdout(`${renderTaskStatus({ state: "timeout", label, ...(message ? { detail: message } : {}), theme })}\n`); },
|
|
77
|
+
};
|
|
78
|
+
},
|
|
49
79
|
};
|
|
50
80
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const ANSI_FG_RESET = "\u001B[39m";
|
|
2
|
+
export declare const ANSI_DIM_OPEN = "\u001B[2m";
|
|
3
|
+
export declare const ANSI_DIM_RESET = "\u001B[22m";
|
|
4
|
+
export declare const BRAND_BLUE_RGB: {
|
|
5
|
+
readonly r: 59;
|
|
6
|
+
readonly g: 130;
|
|
7
|
+
readonly b: 246;
|
|
8
|
+
};
|
|
9
|
+
export declare const BRAND_RED_RGB: {
|
|
10
|
+
readonly r: 239;
|
|
11
|
+
readonly g: 68;
|
|
12
|
+
readonly b: 68;
|
|
13
|
+
};
|
|
14
|
+
export declare const THEME_SYMBOLS: {
|
|
15
|
+
readonly pointer: "›";
|
|
16
|
+
readonly radio: "●";
|
|
17
|
+
readonly submit: "◆";
|
|
18
|
+
readonly cancel: "■";
|
|
19
|
+
readonly success: "✔";
|
|
20
|
+
readonly failure: "✖";
|
|
21
|
+
readonly timeout: "⏱";
|
|
22
|
+
readonly pending: "…";
|
|
23
|
+
readonly barFilled: "█";
|
|
24
|
+
readonly barEmpty: "░";
|
|
25
|
+
};
|
|
26
|
+
export interface UiTheme {
|
|
27
|
+
readonly enabled: boolean;
|
|
28
|
+
readonly blue: (text: string) => string;
|
|
29
|
+
readonly red: (text: string) => string;
|
|
30
|
+
/** W3: de-emphasised text for key hints and secondary detail. */
|
|
31
|
+
readonly dim: (text: string) => string;
|
|
32
|
+
/** Raw SGR open sequences for multi-span painting (empty when color is off). */
|
|
33
|
+
readonly openBlue: string;
|
|
34
|
+
readonly openRed: string;
|
|
35
|
+
readonly openDim: string;
|
|
36
|
+
readonly symbols: typeof THEME_SYMBOLS;
|
|
37
|
+
}
|
|
38
|
+
/** Brand SGR open sequence; only place outside theme that should need RGB → ANSI. */
|
|
39
|
+
export declare function brandAnsiFgOpen(color: "blue" | "red"): string;
|
|
40
|
+
/** Banner and branded prompts only. Does not control leftover Clack text/note/spinner colors. */
|
|
41
|
+
export declare function isThemeEnabled(env: Readonly<Record<string, string | undefined>>, isTTY: boolean): boolean;
|
|
42
|
+
export declare function createTheme(enabled: boolean): UiTheme;
|
package/dist/ui/theme.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const ANSI_FG_RESET = "\x1b[39m";
|
|
2
|
+
export const ANSI_DIM_OPEN = "\x1b[2m";
|
|
3
|
+
export const ANSI_DIM_RESET = "\x1b[22m";
|
|
4
|
+
export const BRAND_BLUE_RGB = { r: 59, g: 130, b: 246 };
|
|
5
|
+
export const BRAND_RED_RGB = { r: 239, g: 68, b: 68 };
|
|
6
|
+
export const THEME_SYMBOLS = {
|
|
7
|
+
pointer: "›",
|
|
8
|
+
radio: "●",
|
|
9
|
+
submit: "◆",
|
|
10
|
+
cancel: "■",
|
|
11
|
+
// W3: task-status glyphs. Colour stays within the frozen white/blue/red
|
|
12
|
+
// palette (success = blue, failure/timeout = red), so the theme keeps working
|
|
13
|
+
// with NO_COLOR and a dumb terminal.
|
|
14
|
+
success: "✔",
|
|
15
|
+
failure: "✖",
|
|
16
|
+
timeout: "⏱",
|
|
17
|
+
pending: "…",
|
|
18
|
+
barFilled: "█",
|
|
19
|
+
barEmpty: "░",
|
|
20
|
+
};
|
|
21
|
+
function ansiFg(r, g, b) {
|
|
22
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
23
|
+
}
|
|
24
|
+
/** Brand SGR open sequence; only place outside theme that should need RGB → ANSI. */
|
|
25
|
+
export function brandAnsiFgOpen(color) {
|
|
26
|
+
const rgb = color === "blue" ? BRAND_BLUE_RGB : BRAND_RED_RGB;
|
|
27
|
+
return ansiFg(rgb.r, rgb.g, rgb.b);
|
|
28
|
+
}
|
|
29
|
+
/** Do not nest `theme.blue`/`theme.red`: reset returns to the default foreground, not an outer color. */
|
|
30
|
+
function paint(enabled, r, g, b) {
|
|
31
|
+
const open = ansiFg(r, g, b);
|
|
32
|
+
return (text) => (enabled ? `${open}${text}${ANSI_FG_RESET}` : text);
|
|
33
|
+
}
|
|
34
|
+
/** Banner and branded prompts only. Does not control leftover Clack text/note/spinner colors. */
|
|
35
|
+
export function isThemeEnabled(env, isTTY) {
|
|
36
|
+
if (!isTTY)
|
|
37
|
+
return false;
|
|
38
|
+
if (Object.prototype.hasOwnProperty.call(env, "NO_COLOR"))
|
|
39
|
+
return false;
|
|
40
|
+
if (env.TERM === "dumb")
|
|
41
|
+
return false;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
/** Dim/intensity paint. Independent of foreground colour, so it composes safely. */
|
|
45
|
+
function paintDim(enabled) {
|
|
46
|
+
return (text) => (enabled ? `${ANSI_DIM_OPEN}${text}${ANSI_DIM_RESET}` : text);
|
|
47
|
+
}
|
|
48
|
+
export function createTheme(enabled) {
|
|
49
|
+
return {
|
|
50
|
+
enabled,
|
|
51
|
+
blue: paint(enabled, BRAND_BLUE_RGB.r, BRAND_BLUE_RGB.g, BRAND_BLUE_RGB.b),
|
|
52
|
+
red: paint(enabled, BRAND_RED_RGB.r, BRAND_RED_RGB.g, BRAND_RED_RGB.b),
|
|
53
|
+
dim: paintDim(enabled),
|
|
54
|
+
openBlue: enabled ? brandAnsiFgOpen("blue") : "",
|
|
55
|
+
openRed: enabled ? brandAnsiFgOpen("red") : "",
|
|
56
|
+
openDim: enabled ? ANSI_DIM_OPEN : "",
|
|
57
|
+
symbols: THEME_SYMBOLS,
|
|
58
|
+
};
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moewolf/moe-icons-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Moeicons CLI: install React, Vue, Vanilla, or Assets icon targets, manage releases and login, and expose an MCP server.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"moeicons": "bin/moeicons.js"
|
|
28
28
|
},
|
|
29
29
|
"engines": {
|
|
30
|
-
"node": ">=
|
|
30
|
+
"node": ">=22.0.0"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"bin",
|
|
@@ -36,18 +36,22 @@
|
|
|
36
36
|
"LICENSE"
|
|
37
37
|
],
|
|
38
38
|
"scripts": {
|
|
39
|
+
"dev:prepare": "npm --prefix ../moe-icons-clitest run dev:prepare",
|
|
39
40
|
"generate-banner": "node scripts/generate-banner.mjs",
|
|
41
|
+
"sync:config-package": "node scripts/sync-config-package.mjs",
|
|
40
42
|
"prebuild": "rimraf dist",
|
|
41
|
-
"build": "tsc -p tsconfig.build.json && node scripts/copy-catalog.mjs",
|
|
43
|
+
"build": "tsc -p tsconfig.build.json && node scripts/copy-catalog.mjs && node scripts/copy-config-package.mjs",
|
|
42
44
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
43
45
|
"lint": "eslint src --ext .ts",
|
|
44
46
|
"test": "vitest run",
|
|
47
|
+
"policy:verify-remote": "node scripts/verify-release-policy-remote.mjs",
|
|
45
48
|
"release:preflight": "node scripts/release-preflight.mjs",
|
|
49
|
+
"release:bump": "node scripts/release-bump.mjs",
|
|
46
50
|
"prepublishOnly": "npm run release:preflight",
|
|
47
51
|
"format": "prettier --write src tests"
|
|
48
52
|
},
|
|
49
53
|
"devDependencies": {
|
|
50
|
-
"@types/node": "^
|
|
54
|
+
"@types/node": "^22.0.0",
|
|
51
55
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
52
56
|
"@typescript-eslint/parser": "^7.0.0",
|
|
53
57
|
"@vue/server-renderer": "^3.5.41",
|
|
@@ -57,14 +61,18 @@
|
|
|
57
61
|
"figlet": "^1.11.4",
|
|
58
62
|
"happy-dom": "^20.11.1",
|
|
59
63
|
"prettier": "^3.2.0",
|
|
64
|
+
"sharp": "^0.35.4",
|
|
60
65
|
"typescript": "^5.5.0",
|
|
61
|
-
"vitest": "^
|
|
66
|
+
"vitest": "^4.1.11",
|
|
62
67
|
"vue": "^3.5.41"
|
|
63
68
|
},
|
|
64
69
|
"dependencies": {
|
|
70
|
+
"@babel/parser": "^7.29.8",
|
|
71
|
+
"@clack/core": "^0.4.2",
|
|
65
72
|
"@clack/prompts": "^0.10.1",
|
|
66
73
|
"commander": "^12.1.0",
|
|
67
74
|
"fflate": "^0.8.2",
|
|
68
75
|
"jsonc-parser": "^3.3.1"
|
|
69
|
-
}
|
|
76
|
+
},
|
|
77
|
+
"payloadHash": "b890d559f2625d622f87d9c628ec96b39da2e66a6c65408883d0e8a2b462db4e"
|
|
70
78
|
}
|