oh-skillhub 0.1.3 → 0.1.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-skillhub",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "OpenHarmony Skills installer for Codex, Claude Code, and OpenCode.",
5
5
  "type": "commonjs",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -21,6 +21,14 @@ const DOMAIN_NAMES = [
21
21
  "kernel",
22
22
  "security",
23
23
  ];
24
+ const ANSI = {
25
+ reset: "\x1b[0m",
26
+ bold: "\x1b[1m",
27
+ dim: "\x1b[2m",
28
+ cyan: "\x1b[36m",
29
+ green: "\x1b[32m",
30
+ reverse: "\x1b[7m",
31
+ };
24
32
 
25
33
  async function main(argv = []) {
26
34
  if (argv.length === 0) {
@@ -165,12 +173,12 @@ async function runInteractiveInstaller(input = process.stdin, output = process.s
165
173
  function buildRepositoryChoices(manifest) {
166
174
  const choices = [];
167
175
  for (const stage of COMMON_STAGES) {
168
- const count = manifest.skills.filter((skill) => skill.scope === "common" && skill.stage === stage).length;
169
- choices.push({ scope: "common", stage, path: `common / ${stage}`, count });
176
+ const skills = manifest.skills.filter((skill) => skill.scope === "common" && skill.stage === stage);
177
+ choices.push({ scope: "common", stage, path: `common / ${stage}`, count: skills.length, skills });
170
178
  }
171
179
  for (const domain of DOMAIN_NAMES) {
172
- const count = manifest.skills.filter((skill) => skill.scope === "domain" && skill.domain === domain).length;
173
- choices.push({ scope: "domain", domain, path: `domain / ${domain}`, count });
180
+ const skills = manifest.skills.filter((skill) => skill.scope === "domain" && skill.domain === domain);
181
+ choices.push({ scope: "domain", domain, path: `domain / ${domain}`, count: skills.length, skills });
174
182
  }
175
183
  return choices;
176
184
  }
@@ -196,6 +204,9 @@ function renderTuiMenu(choices) {
196
204
  choices.forEach((choice, index) => {
197
205
  const marker = choice.count > 0 ? "[ ]" : "[ ]";
198
206
  lines.push(` ${String(index + 1).padStart(2, " ")}. ${marker} ${choice.path.padEnd(28, " ")} ${choice.count} skill(s)`);
207
+ for (const leaf of renderSkillLeaves(choice)) {
208
+ lines.push(` - ${leaf}`);
209
+ }
199
210
  });
200
211
  lines.push("");
201
212
  return `${lines.join("\n")}\n`;
@@ -271,27 +282,62 @@ function renderRawTuiMenu(choices, cursor, selected) {
271
282
  const line = `+${"-".repeat(width - 2)}+`;
272
283
  const lines = [
273
284
  line,
274
- `| ${padRight("OH SkillHub", width - 4)} |`,
275
- `| ${padRight("OpenHarmony Skills Installer", width - 4)} |`,
285
+ rawHeaderLine("OH SkillHub", width, ANSI.cyan, ANSI.bold),
286
+ rawHeaderLine("OpenHarmony Skills Installer", width, ANSI.dim),
276
287
  line,
277
288
  "",
278
- "Target",
289
+ colorize("Target", ANSI.bold),
279
290
  " Agent: codex",
280
291
  " Scope: user",
281
292
  "",
282
- "Choose skill groups",
283
- " Up/Down or j/k: move Space: select Enter: install Ctrl+C: cancel",
293
+ colorize("Choose skill groups", ANSI.bold),
294
+ colorize(" Up/Down or j/k: move Space: select Enter: install Ctrl+C: cancel", ANSI.dim),
284
295
  "",
285
296
  ];
286
297
  choices.forEach((choice, index) => {
287
298
  const pointer = index === cursor ? ">" : " ";
288
- const checkbox = selected.has(index) ? "[x]" : "[ ]";
289
- lines.push(`${pointer} ${checkbox} ${choice.path.padEnd(28, " ")} ${choice.count} skill(s)`);
299
+ const highlighted = index === cursor;
300
+ const checkbox = rawCheckbox(selected.has(index), highlighted);
301
+ const row = `${pointer} ${checkbox} ${choice.path.padEnd(28, " ")} ${choice.count} skill(s)`;
302
+ lines.push(highlighted ? colorize(row, ANSI.reverse, ANSI.bold) : row);
303
+ for (const leaf of renderSkillLeaves(choice)) {
304
+ lines.push(colorize(` - ${leaf}`, ANSI.dim));
305
+ }
290
306
  });
291
307
  lines.push("");
292
308
  return `${lines.join("\n")}\n`;
293
309
  }
294
310
 
311
+ function colorize(value, ...codes) {
312
+ return `${codes.join("")}${value}${ANSI.reset}`;
313
+ }
314
+
315
+ function rawHeaderLine(value, width, ...codes) {
316
+ const styled = colorize(value, ...codes);
317
+ return `| ${styled}${" ".repeat(width - 4 - value.length)} |`;
318
+ }
319
+
320
+ function rawCheckbox(isSelected, highlighted) {
321
+ if (!isSelected) {
322
+ return "[ ]";
323
+ }
324
+ const restore = highlighted ? `${ANSI.reverse}${ANSI.bold}` : "";
325
+ return `${colorize("[✓]", ANSI.green, ANSI.bold)}${restore}`;
326
+ }
327
+
328
+ function renderSkillLeaves(choice) {
329
+ return (choice.skills || []).map((skill) => {
330
+ if (choice.scope === "common") {
331
+ return skill.name;
332
+ }
333
+ const prefix = `skills/domain/${choice.domain}/`;
334
+ if (skill.path.startsWith(prefix)) {
335
+ return skill.path.slice(prefix.length).split("/").join(" / ");
336
+ }
337
+ return skill.name;
338
+ });
339
+ }
340
+
295
341
  function padRight(value, width) {
296
342
  return value.length >= width ? value.slice(0, width) : `${value}${" ".repeat(width - value.length)}`;
297
343
  }
@@ -439,6 +485,7 @@ module.exports = {
439
485
  renderTelemetry,
440
486
  buildRepositoryChoices,
441
487
  parseSelection,
488
+ renderRawTuiMenu,
442
489
  renderTuiMenu,
443
490
  selectSkillsForChoices,
444
491
  };
@@ -144,6 +144,17 @@
144
144
  "version": "0.1.0",
145
145
  "status": "stable",
146
146
  "tags": ["arkui", "review"]
147
+ },
148
+ {
149
+ "name": "ohos-design-graphics-explain-code",
150
+ "scope": "domain",
151
+ "domain": "graphics",
152
+ "stage": "design",
153
+ "path": "skills/domain/graphics/design/ohos-design-graphics-explain-code",
154
+ "description": "Use when explaining OpenHarmony graphics design code.",
155
+ "version": "0.1.0",
156
+ "status": "stable",
157
+ "tags": ["graphics", "design"]
147
158
  }
148
159
  ]
149
160
  }