@triflare/fx 1.0.3 → 2.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/README.md +32 -0
- package/bin/fx.js +4 -1162
- package/package.json +5 -3
- package/product.yml +1 -1
- package/src/brand.js +9 -3
- package/src/cli/commands/build.js +98 -0
- package/src/cli/commands/catalog.js +42 -0
- package/src/cli/commands/check.js +44 -0
- package/src/cli/commands/completion.js +54 -0
- package/src/cli/commands/decompile.js +266 -0
- package/src/cli/commands/dev.js +179 -0
- package/src/cli/commands/extension.js +110 -0
- package/src/cli/commands/index.js +39 -0
- package/src/cli/commands/init.js +169 -0
- package/src/cli/commands/package.js +137 -0
- package/src/cli/commands/sprite/add.js +85 -0
- package/src/cli/commands/sprite/build.js +62 -0
- package/src/cli/commands/sprite/helpers.js +66 -0
- package/src/cli/commands/sprite/index.js +29 -0
- package/src/cli/commands/sprite/list.js +31 -0
- package/src/cli/commands/sprite/remove.js +51 -0
- package/src/cli/commands/vendor/add.js +98 -0
- package/src/cli/commands/vendor/helpers.js +50 -0
- package/src/cli/commands/vendor/index.js +39 -0
- package/src/cli/commands/vendor/install.js +64 -0
- package/src/cli/commands/vendor/list.js +45 -0
- package/src/cli/commands/vendor/migrate.js +47 -0
- package/src/cli/commands/vendor/outdated.js +51 -0
- package/src/cli/commands/vendor/remove.js +34 -0
- package/src/cli/commands/vendor/update.js +49 -0
- package/src/cli/commands/vendor/verify.js +44 -0
- package/src/cli/completion/bash.js +10 -0
- package/src/cli/completion/fish.js +9 -0
- package/src/cli/completion/index.js +97 -0
- package/src/cli/completion/zsh.js +11 -0
- package/src/cli/context.js +257 -0
- package/src/cli/define-command.js +140 -0
- package/src/cli/errors.js +111 -0
- package/src/cli/format.js +31 -0
- package/src/cli/prompts.js +183 -0
- package/src/cli/reporter.js +194 -0
- package/src/cli/run.js +248 -0
- package/src/cli/templates/index.js +112 -0
- package/src/cli/theme.js +84 -0
- package/src/config-edit.js +280 -1
- package/src/config.js +137 -3
- package/src/extensions.js +72 -19
- package/src/index.js +21 -0
- package/src/vendor.js +1323 -0
- package/vendor/pm-packager-dist/.fx-build.json +1 -1
package/src/cli/run.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entrypoint: commander setup, global options, and top-level error
|
|
3
|
+
* handling.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { Command, CommanderError } from "commander";
|
|
8
|
+
import { brandText } from "../brand.js";
|
|
9
|
+
import { loadProduct } from "../product.js";
|
|
10
|
+
import { registerCommands } from "./commands/index.js";
|
|
11
|
+
import {
|
|
12
|
+
CliError,
|
|
13
|
+
EXIT,
|
|
14
|
+
UsageError,
|
|
15
|
+
errorToJson,
|
|
16
|
+
formatError,
|
|
17
|
+
} from "./errors.js";
|
|
18
|
+
import { createReporter } from "./reporter.js";
|
|
19
|
+
import { createTheme } from "./theme.js";
|
|
20
|
+
|
|
21
|
+
const USAGE_CODES = new Set([
|
|
22
|
+
"commander.unknownCommand",
|
|
23
|
+
"commander.unknownOption",
|
|
24
|
+
"commander.missingArgument",
|
|
25
|
+
"commander.optionMissingArgument",
|
|
26
|
+
"commander.invalidArgument",
|
|
27
|
+
"commander.excessArguments",
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
function resolveColor(options = {}) {
|
|
31
|
+
if (options.color === false || options.color === "never") return "never";
|
|
32
|
+
if (options.color === "always") return "always";
|
|
33
|
+
return "auto";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Read the global flags needed before commander has parsed successfully. */
|
|
37
|
+
function scanGlobalFlags(argv) {
|
|
38
|
+
const result = {
|
|
39
|
+
json: false,
|
|
40
|
+
quiet: false,
|
|
41
|
+
verbose: false,
|
|
42
|
+
color: "auto",
|
|
43
|
+
};
|
|
44
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
45
|
+
const token = argv[i];
|
|
46
|
+
if (token === "--json") result.json = true;
|
|
47
|
+
else if (token === "-q" || token === "--quiet") result.quiet = true;
|
|
48
|
+
else if (token === "-v" || token === "--verbose") result.verbose = true;
|
|
49
|
+
else if (token === "--no-color") result.color = "never";
|
|
50
|
+
else if (token === "--color") result.color = argv[++i] ?? "auto";
|
|
51
|
+
else if (token.startsWith("--color="))
|
|
52
|
+
result.color = token.slice("--color=".length);
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function commandFromArgv(argv, program) {
|
|
58
|
+
const names = new Set();
|
|
59
|
+
for (const command of program.commands)
|
|
60
|
+
for (const name of [command.name(), ...command.aliases()]) names.add(name);
|
|
61
|
+
for (const token of argv) if (names.has(token)) return token;
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function styleUsage(text, theme) {
|
|
66
|
+
return text
|
|
67
|
+
.split(" ")
|
|
68
|
+
.map((word) => {
|
|
69
|
+
if (word === "[options]") return theme.option(word);
|
|
70
|
+
if (word === "[command]") return theme.command(word);
|
|
71
|
+
if (word.startsWith("[") || word.startsWith("<"))
|
|
72
|
+
return theme.argument(word);
|
|
73
|
+
return theme.command(word);
|
|
74
|
+
})
|
|
75
|
+
.join(" ");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function styleOptionTerm(text, theme) {
|
|
79
|
+
return text
|
|
80
|
+
.split(" ")
|
|
81
|
+
.map((word) =>
|
|
82
|
+
word.startsWith("<") || word.startsWith("[")
|
|
83
|
+
? theme.argument(word)
|
|
84
|
+
: theme.option(word),
|
|
85
|
+
)
|
|
86
|
+
.join(" ");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function styleSubcommandTerm(text, theme) {
|
|
90
|
+
return text
|
|
91
|
+
.split(" ")
|
|
92
|
+
.map((word) => {
|
|
93
|
+
if (word === "[options]") return theme.option(word);
|
|
94
|
+
if (word.startsWith("[") || word.startsWith("<"))
|
|
95
|
+
return theme.argument(word);
|
|
96
|
+
return theme.command(word);
|
|
97
|
+
})
|
|
98
|
+
.join(" ");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function createProgram(product, theme, color) {
|
|
102
|
+
const program = new Command();
|
|
103
|
+
program
|
|
104
|
+
.name(product.command)
|
|
105
|
+
.description(product.tagline)
|
|
106
|
+
.version(
|
|
107
|
+
`${product.name} ${product.version}`,
|
|
108
|
+
"-V, --version",
|
|
109
|
+
"Print the version",
|
|
110
|
+
)
|
|
111
|
+
.helpOption("-h, --help", "Show help")
|
|
112
|
+
.helpCommand("help [command]", "Show help for a command")
|
|
113
|
+
.showSuggestionAfterError(true)
|
|
114
|
+
.configureHelp({
|
|
115
|
+
sortCommands: false,
|
|
116
|
+
sortOptions: false,
|
|
117
|
+
showGlobalOptions: true,
|
|
118
|
+
styleTitle: (text) => theme.heading(text),
|
|
119
|
+
styleUsage: (text) => styleUsage(text, theme),
|
|
120
|
+
styleCommandText: (text) => theme.command(text),
|
|
121
|
+
styleSubcommandText: (text) => theme.command(text),
|
|
122
|
+
styleOptionText: (text) => theme.option(text),
|
|
123
|
+
styleArgumentText: (text) => theme.argument(text),
|
|
124
|
+
styleCommandDescription: (text) => theme.muted(text),
|
|
125
|
+
styleOptionDescription: (text) => theme.muted(text),
|
|
126
|
+
styleSubcommandDescription: (text) => theme.muted(text),
|
|
127
|
+
styleArgumentDescription: (text) => theme.muted(text),
|
|
128
|
+
styleOptionTerm: (text) => styleOptionTerm(text, theme),
|
|
129
|
+
styleSubcommandTerm: (text) => styleSubcommandTerm(text, theme),
|
|
130
|
+
styleArgumentTerm: (text) => theme.argument(text),
|
|
131
|
+
})
|
|
132
|
+
.optionsGroup("Global Options:")
|
|
133
|
+
.option("-v, --verbose", "Show timings, stack traces, and extra detail")
|
|
134
|
+
.option("--json", "Emit machine-readable JSON")
|
|
135
|
+
.option("-q, --quiet", "Suppress success and informational output")
|
|
136
|
+
.option("--color <mode>", "Color output: auto, always, or never", "auto")
|
|
137
|
+
.option("--no-color", "Disable color output")
|
|
138
|
+
.option("--cwd <dir>", "Run as if started in <dir>")
|
|
139
|
+
.option("--config <file>", "Use a specific config file")
|
|
140
|
+
.option("--no-config", "Ignore the project config file")
|
|
141
|
+
.option("--no-input", "Never prompt for input")
|
|
142
|
+
.option("-y, --yes", "Accept defaults and confirm destructive actions")
|
|
143
|
+
.option(
|
|
144
|
+
"--no-upgrade-prompt",
|
|
145
|
+
"Do not offer to migrate project.extensions",
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
program.addHelpText(
|
|
149
|
+
"before",
|
|
150
|
+
`\n ${brandText(product.name, process.stdout, {
|
|
151
|
+
force: color === "always",
|
|
152
|
+
})} ${theme.muted(product.version)}\n ${theme.muted(product.tagline)}\n`,
|
|
153
|
+
);
|
|
154
|
+
program.addHelpText(
|
|
155
|
+
"after",
|
|
156
|
+
`\n ${theme.accent("↳")} Run ${theme.command(
|
|
157
|
+
`${product.command} <command> --help`,
|
|
158
|
+
)} for command details.\n`,
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
return program;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Run the CLI and return an exit code instead of terminating the process.
|
|
166
|
+
*
|
|
167
|
+
* @param {string[]} [argv]
|
|
168
|
+
* @returns {Promise<number>}
|
|
169
|
+
*/
|
|
170
|
+
export async function run(argv = process.argv.slice(2)) {
|
|
171
|
+
const product = loadProduct();
|
|
172
|
+
const raw = scanGlobalFlags(argv);
|
|
173
|
+
const color = resolveColor(raw);
|
|
174
|
+
const theme = createTheme({ product, color, stream: process.stdout });
|
|
175
|
+
const reporter = createReporter({
|
|
176
|
+
product,
|
|
177
|
+
json: raw.json,
|
|
178
|
+
quiet: raw.quiet,
|
|
179
|
+
verbose: raw.verbose,
|
|
180
|
+
color,
|
|
181
|
+
});
|
|
182
|
+
const state = { exitCode: EXIT.OK, command: null };
|
|
183
|
+
const program = createProgram(product, theme, color);
|
|
184
|
+
program.exitOverride();
|
|
185
|
+
program.configureOutput({
|
|
186
|
+
writeOut: (text) => process.stdout.write(text),
|
|
187
|
+
writeErr: (text) => process.stderr.write(text),
|
|
188
|
+
getOutHasColors: () => theme.enabled,
|
|
189
|
+
getErrHasColors: () => theme.enabled,
|
|
190
|
+
// Keep commander's usage text out of the stream; run() renders one
|
|
191
|
+
// consistent diagnostic (or JSON document) below.
|
|
192
|
+
outputError: () => {},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
registerCommands(program, { state, product });
|
|
196
|
+
// With no command, print help to stdout instead of commander's stderr usage.
|
|
197
|
+
program.action(() => program.outputHelp());
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
await program.parseAsync(argv, { from: "user" });
|
|
201
|
+
return state.exitCode;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (error instanceof CommanderError) {
|
|
204
|
+
if (
|
|
205
|
+
error.code === "commander.helpDisplayed" ||
|
|
206
|
+
error.code === "commander.help" ||
|
|
207
|
+
error.code === "commander.version"
|
|
208
|
+
)
|
|
209
|
+
return EXIT.OK;
|
|
210
|
+
|
|
211
|
+
const usage = new UsageError(error.message.replace(/^error:\s*/, ""), {
|
|
212
|
+
code: USAGE_CODES.has(error.code) ? "USAGE_ERROR" : "COMMANDER_ERROR",
|
|
213
|
+
hint: `run "${product.command} help" for usage`,
|
|
214
|
+
});
|
|
215
|
+
usage.command = state.command ?? commandFromArgv(argv, program);
|
|
216
|
+
usage.warnings = [];
|
|
217
|
+
return reportError(usage, reporter);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (error && typeof error === "object") {
|
|
221
|
+
error.warnings ??= [];
|
|
222
|
+
error.command ??= state.command ?? commandFromArgv(argv, program);
|
|
223
|
+
}
|
|
224
|
+
return reportError(error, reporter);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function reportError(error, reporter) {
|
|
229
|
+
const exitCode = error instanceof CliError ? error.exitCode : EXIT.FAILURE;
|
|
230
|
+
const command = error?.command ?? null;
|
|
231
|
+
|
|
232
|
+
if (reporter.json) {
|
|
233
|
+
reporter.document({
|
|
234
|
+
schemaVersion: 1,
|
|
235
|
+
command,
|
|
236
|
+
ok: false,
|
|
237
|
+
warnings: error?.warnings ?? [],
|
|
238
|
+
error: errorToJson(error),
|
|
239
|
+
});
|
|
240
|
+
return exitCode;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (error instanceof CliError && error.silent) return exitCode;
|
|
244
|
+
|
|
245
|
+
reporter.error(formatError(error, { verbose: reporter.verbose }));
|
|
246
|
+
if (error instanceof CliError && error.hint) reporter.hint(error.hint);
|
|
247
|
+
return exitCode;
|
|
248
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffolding templates used by `fx init`.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
configFilename,
|
|
7
|
+
sourceDirectory,
|
|
8
|
+
sourceExtension,
|
|
9
|
+
} from "../../brand.js";
|
|
10
|
+
|
|
11
|
+
const CAT_ASSET = `<svg xmlns="http://www.w3.org/2000/svg" width="95" height="101" viewBox="0 0 95 101">
|
|
12
|
+
<ellipse cx="47" cy="60" rx="35" ry="35" fill="#ffab19" stroke="#cf8b17" stroke-width="4"/>
|
|
13
|
+
<circle cx="35" cy="50" r="6" fill="#000"/>
|
|
14
|
+
<circle cx="60" cy="50" r="6" fill="#000"/>
|
|
15
|
+
</svg>
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
function configText({ name, width, height, target }) {
|
|
19
|
+
const lines = [
|
|
20
|
+
"project:",
|
|
21
|
+
` name: ${JSON.stringify(name)}`,
|
|
22
|
+
" fps: 60",
|
|
23
|
+
` width: ${width}`,
|
|
24
|
+
` height: ${height}`,
|
|
25
|
+
" turbo: false",
|
|
26
|
+
" interpolation: true",
|
|
27
|
+
"fx:",
|
|
28
|
+
" partialSprites: false",
|
|
29
|
+
];
|
|
30
|
+
if (target !== "none") {
|
|
31
|
+
lines.push("package:", ` target: ${target}`);
|
|
32
|
+
}
|
|
33
|
+
return `${lines.join("\n")}\n`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const CAT_SOURCE = `sprite "Cat" {
|
|
37
|
+
costumes: {
|
|
38
|
+
cat: "../assets/cat.svg"
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
let score = 0;
|
|
42
|
+
|
|
43
|
+
when greenFlag {
|
|
44
|
+
motion.goToXY(0, 0);
|
|
45
|
+
control.forever {
|
|
46
|
+
motion.turnRight(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
when keyPressed("space") {
|
|
51
|
+
score += 1;
|
|
52
|
+
looks.sayForSecs(operators.join("Score: ", score), 1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const EMPTY_SOURCE = `// Your project starts here.
|
|
58
|
+
when greenFlag {
|
|
59
|
+
looks.say("Hello, world!");
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
const BLANK_SOURCE = `// Your project starts here.
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Build the file map for an init run.
|
|
68
|
+
*
|
|
69
|
+
* @param {{
|
|
70
|
+
* product: object,
|
|
71
|
+
* name: string,
|
|
72
|
+
* template: "cat"|"empty"|"blank",
|
|
73
|
+
* width: number,
|
|
74
|
+
* height: number,
|
|
75
|
+
* target: string,
|
|
76
|
+
* }} options
|
|
77
|
+
*/
|
|
78
|
+
export function initFiles({ product, name, template, width, height, target }) {
|
|
79
|
+
const files = {
|
|
80
|
+
[configFilename(product)]: configText({ name, width, height, target }),
|
|
81
|
+
[`${sourceDirectory(product)}/main${sourceExtension(product)}`]:
|
|
82
|
+
template === "cat"
|
|
83
|
+
? CAT_SOURCE
|
|
84
|
+
: template === "empty"
|
|
85
|
+
? EMPTY_SOURCE
|
|
86
|
+
: BLANK_SOURCE,
|
|
87
|
+
};
|
|
88
|
+
if (template === "cat") files["assets/cat.svg"] = CAT_ASSET;
|
|
89
|
+
return files;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const TEMPLATES = [
|
|
93
|
+
{
|
|
94
|
+
value: "cat",
|
|
95
|
+
label: "Cat demo",
|
|
96
|
+
hint: "sprite, costumes, events, variables",
|
|
97
|
+
},
|
|
98
|
+
{ value: "empty", label: "Empty project", hint: "one green-flag script" },
|
|
99
|
+
{ value: "blank", label: "Blank", hint: "just the config and a source file" },
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
export const TARGETS = [
|
|
103
|
+
{ value: "none", label: "None", hint: "source only" },
|
|
104
|
+
{ value: "html", label: "HTML", hint: "single-file web build" },
|
|
105
|
+
{ value: "zip", label: "ZIP", hint: "packaged archive" },
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
export const STAGE_SIZES = [
|
|
109
|
+
{ value: "480x360", label: "480 × 360", hint: "Scratch default" },
|
|
110
|
+
{ value: "640x360", label: "640 × 360", hint: "wide" },
|
|
111
|
+
{ value: "1920x1080", label: "1920 × 1080", hint: "full HD" },
|
|
112
|
+
];
|
package/src/cli/theme.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal theme shared by help output and the reporter.
|
|
3
|
+
*
|
|
4
|
+
* Colors are derived from the product palette so a rebrand reaches the CLI
|
|
5
|
+
* too. Everything falls back to plain text when the stream cannot show color.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { styleText } from "node:util";
|
|
9
|
+
import { brandingColors } from "../brand.js";
|
|
10
|
+
|
|
11
|
+
const STATUS_COLORS = {
|
|
12
|
+
success: "#34D399",
|
|
13
|
+
warning: "#FBBF24",
|
|
14
|
+
danger: "#F87171",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function rgb(hex) {
|
|
18
|
+
const digits =
|
|
19
|
+
hex.length === 4 ? hex.slice(1).replace(/./g, "$&$&") : hex.slice(1);
|
|
20
|
+
return digits.match(/../g).map((part) => parseInt(part, 16));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function mix(from, to, amount) {
|
|
24
|
+
const [r1, g1, b1] = rgb(from);
|
|
25
|
+
const [r2, g2, b2] = rgb(to);
|
|
26
|
+
const channel = (a, b) => Math.round(a + (b - a) * amount);
|
|
27
|
+
return [channel(r1, r2), channel(g1, g2), channel(b1, b2)];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function supportsColor(stream) {
|
|
31
|
+
if (!stream?.isTTY) return false;
|
|
32
|
+
if (process.env.NO_COLOR) return false;
|
|
33
|
+
if (process.env.TERM === "dumb") return false;
|
|
34
|
+
return styleText("red", "x", { stream }).includes("\x1b");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {{ product?: object, color?: "auto"|"always"|"never", stream?: NodeJS.WriteStream }} [options]
|
|
39
|
+
*/
|
|
40
|
+
export function createTheme({
|
|
41
|
+
product,
|
|
42
|
+
color = "auto",
|
|
43
|
+
stream = process.stdout,
|
|
44
|
+
} = {}) {
|
|
45
|
+
const palette = brandingColors(product);
|
|
46
|
+
const enabled =
|
|
47
|
+
color === "always" || (color !== "never" && supportsColor(stream));
|
|
48
|
+
|
|
49
|
+
const paint = (text, codes) => {
|
|
50
|
+
if (!enabled || codes.length === 0) return String(text);
|
|
51
|
+
return `\x1b[${codes.join(";")}m${text}\x1b[0m`;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const foreground = (colorValue) => {
|
|
55
|
+
const [r, g, b] = Array.isArray(colorValue) ? colorValue : rgb(colorValue);
|
|
56
|
+
return `38;2;${r};${g};${b}`;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const command = mix(palette.primary, "#FFFFFF", 0.35);
|
|
60
|
+
const heading = mix(palette.primary, "#FFFFFF", 0.2);
|
|
61
|
+
const option = mix(palette.primary, "#FFFFFF", 0.58);
|
|
62
|
+
const argument = mix(palette.primary, "#FFFFFF", 0.74);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
enabled,
|
|
66
|
+
stream,
|
|
67
|
+
|
|
68
|
+
accent: (text) => paint(text, [foreground(palette.primary)]),
|
|
69
|
+
command: (text) => paint(text, ["1", foreground(command)]),
|
|
70
|
+
heading: (text) => paint(text, ["1", foreground(heading)]),
|
|
71
|
+
option: (text) => paint(text, [foreground(option)]),
|
|
72
|
+
argument: (text) => paint(text, [foreground(argument)]),
|
|
73
|
+
muted: (text) => paint(text, ["2"]),
|
|
74
|
+
bold: (text) => paint(text, ["1"]),
|
|
75
|
+
success: (text) => paint(text, [foreground(STATUS_COLORS.success)]),
|
|
76
|
+
warning: (text) => paint(text, [foreground(STATUS_COLORS.warning)]),
|
|
77
|
+
danger: (text) => paint(text, [foreground(STATUS_COLORS.danger)]),
|
|
78
|
+
|
|
79
|
+
tone(name, text) {
|
|
80
|
+
const value = STATUS_COLORS[name] ?? palette.primary;
|
|
81
|
+
return paint(text, [foreground(value)]);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|