@lewishowles/cli-style 0.3.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.1 - 2026-07-01
4
+
5
+ ### Fixed
6
+
7
+ - Updated grouped reporter summaries so skipped rows outrank success rows while warnings and failures still take precedence.
8
+ - Added the project-local vite-plus pre-commit hook setup so commits run the existing staged checks.
9
+
10
+ ## 0.4.0 - 2026-06-30
11
+
12
+ ### Added
13
+
14
+ - Added `reporter.divider()` for compact phase headings in grouped CLI output.
15
+ - Added `renderReporterDivider()` for rendering reporter phase dividers without a reporter instance.
16
+
17
+ ### Changed
18
+
19
+ - Updated reporter docs and gallery examples to use dividers for major phases and reserve panels for framed content blocks.
20
+
3
21
  ## 0.3.0 - 2026-06-29
4
22
 
5
23
  ### Added
package/README.md CHANGED
@@ -52,24 +52,30 @@ const reporter = createReporter({
52
52
  colour: false,
53
53
  });
54
54
 
55
- reporter.section("Setting up Claude + Codex", "(project)");
56
- reporter.group("Agent scripts", [
55
+ reporter.divider("Project setup", "Claude + Codex");
56
+ reporter.group(
57
+ "Agent scripts",
58
+ [
59
+ {
60
+ label: "project-diagnostics.py",
61
+ result: "unchanged",
62
+ },
63
+ {
64
+ label: "repo-context.py",
65
+ result: "unchanged",
66
+ },
67
+ ],
57
68
  {
58
- label: "project-diagnostics.py",
59
- result: "unchanged",
69
+ summary: "2 already linked",
60
70
  },
61
- {
62
- label: "repo-context.py",
63
- result: "unchanged",
64
- },
65
- ], {
66
- summary: "2 already linked",
67
- });
71
+ );
68
72
  reporter.status("success", "Done.");
69
73
 
70
74
  console.log(reporter.render());
71
75
  ```
72
76
 
77
+ Use `reporter.divider()` for major phases. Use `reporter.section()` when you want a normal `info` status row inside a phase. Panels are for framed content blocks, not headings.
78
+
73
79
  Groups can include verbose detail rows when a caller opts in:
74
80
 
75
81
  ```js
@@ -22,9 +22,11 @@ const report = {
22
22
  title: "Diagnostics",
23
23
  };
24
24
 
25
- console.log(diagnosticReport(report, {
26
- colour: false,
27
- profile: "diagnostic",
28
- unicode: true,
29
- width: 80,
30
- }));
25
+ console.log(
26
+ diagnosticReport(report, {
27
+ colour: false,
28
+ profile: "diagnostic",
29
+ unicode: true,
30
+ width: 80,
31
+ }),
32
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lewishowles/cli-style",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Shared terminal output styles for Lewis Howles tools, diagnostics, and package CLIs.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,6 +32,7 @@
32
32
  "check": "vp check --fix",
33
33
  "cli-style:gallery": "bun ./bin/cli-style.js gallery",
34
34
  "package:binary": "scripts/package-binary.sh",
35
+ "prepare": "vp config",
35
36
  "smoke:binary": "./dist/bin/cli-style render status --plain < tests/fixtures/render/status-success.json",
36
37
  "test:unit": "bun test"
37
38
  },
@@ -1,19 +1,10 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
 
3
- import {
4
- galleryFixtures,
5
- gallerySections,
6
- galleryVariants,
7
- } from "../gallery/render-gallery.js";
3
+ import { galleryFixtures, gallerySections, galleryVariants } from "../gallery/render-gallery.js";
8
4
  import { isProfile, profiles } from "../profiles/profiles.js";
9
5
 
10
6
  // Global rendering flags accepted after `gallery` for focused review commands.
11
- const globalRenderingFlags = new Set([
12
- "--no-color",
13
- "--no-colour",
14
- "--no-unicode",
15
- "--plain",
16
- ]);
7
+ const globalRenderingFlags = new Set(["--no-color", "--no-colour", "--no-unicode", "--plain"]);
17
8
 
18
9
  /**
19
10
  * Parse gallery command arguments.
@@ -25,6 +16,7 @@ const globalRenderingFlags = new Set([
25
16
  */
26
17
  export function parseGalleryRequest(args = []) {
27
18
  let hasVariant = false;
19
+
28
20
  const request = {
29
21
  fixture: undefined,
30
22
  interactive: false,
@@ -96,15 +88,13 @@ export function selectInteractiveGalleryRequest(request) {
96
88
  ...gallerySections.map((section) => `section:${section}`),
97
89
  ...galleryFixtures.map((fixture) => `fixture:${fixture}`),
98
90
  ];
99
- const selection = spawnSync("fzf", [
100
- "--height=60%",
101
- "--layout=reverse",
102
- "--prompt=Gallery > ",
103
- ], {
91
+
92
+ const selection = spawnSync("fzf", ["--height=60%", "--layout=reverse", "--prompt=Gallery > "], {
104
93
  encoding: "utf8",
105
94
  input: choices.join("\n"),
106
95
  stdio: ["pipe", "pipe", "inherit"],
107
96
  });
97
+
108
98
  const value = selection.status === 0 ? selection.stdout.trim() : "";
109
99
 
110
100
  if (value === "") {
@@ -22,73 +22,81 @@ import { isProfile, profiles } from "../profiles/profiles.js";
22
22
  const renderers = {
23
23
  "agent-transcript": (input, options) => agentTranscript(input, options),
24
24
  "audit-finding": (input, options) => auditFinding(input, options),
25
- "bar-chart": (input, options) => barChart({
26
- ...input,
27
- ...options,
28
- }),
29
- chip: (input, options) => chip(input.label, input.tone, {
30
- ...input,
31
- ...options,
32
- }),
25
+ "bar-chart": (input, options) =>
26
+ barChart({
27
+ ...input,
28
+ ...options,
29
+ }),
30
+ chip: (input, options) =>
31
+ chip(input.label, input.tone, {
32
+ ...input,
33
+ ...options,
34
+ }),
33
35
  "command-result": (input, options) => commandResult(input, options),
34
36
  "compact-data-table": (input, options) => compactDataTable(input, options),
35
37
  "confirmation-result": (input, options) => confirmationResult(input, options),
36
38
  "diagnostic-report": (input, options) => diagnosticReport(input, options),
37
- divider: (input, options) => divider({
38
- ...input,
39
- ...options,
40
- }),
41
- "empty-state": (input, options) => emptyState(input.title, input.detail, {
42
- ...input,
43
- ...options,
44
- }),
45
- "error-block": (input, options) => errorBlock(input.title, input.lines, {
46
- ...input,
47
- ...options,
48
- }),
49
- hint: (input, options) => hint(input.message, {
50
- ...input,
51
- ...options,
52
- }),
39
+ divider: (input, options) =>
40
+ divider({
41
+ ...input,
42
+ ...options,
43
+ }),
44
+ "empty-state": (input, options) =>
45
+ emptyState(input.title, input.detail, {
46
+ ...input,
47
+ ...options,
48
+ }),
49
+ "error-block": (input, options) =>
50
+ errorBlock(input.title, input.lines, {
51
+ ...input,
52
+ ...options,
53
+ }),
54
+ hint: (input, options) =>
55
+ hint(input.message, {
56
+ ...input,
57
+ ...options,
58
+ }),
53
59
  "next-step-block": (input, options) => nextStepBlock(input, options),
54
- panel: (input, options) => panel({
55
- ...input,
56
- ...options,
57
- }),
58
- "progress-bar": (input, options) => progressBar({
59
- ...input,
60
- ...options,
61
- }),
62
- row: (input, options) => row(input.label, input.value, {
63
- ...input,
64
- ...options,
65
- }),
66
- status: (input, options) => status(input.type, input.detail, {
67
- ...input,
68
- ...options,
69
- }),
70
- step: (input, options) => step(input.label, input.state, {
71
- ...input,
72
- ...options,
73
- }),
74
- "step-progress": (input, options) => stepProgress({
75
- ...input,
76
- ...options,
77
- }),
78
- table: (input, options) => table({
79
- ...input,
80
- ...options,
81
- }),
60
+ panel: (input, options) =>
61
+ panel({
62
+ ...input,
63
+ ...options,
64
+ }),
65
+ "progress-bar": (input, options) =>
66
+ progressBar({
67
+ ...input,
68
+ ...options,
69
+ }),
70
+ row: (input, options) =>
71
+ row(input.label, input.value, {
72
+ ...input,
73
+ ...options,
74
+ }),
75
+ status: (input, options) =>
76
+ status(input.type, input.detail, {
77
+ ...input,
78
+ ...options,
79
+ }),
80
+ step: (input, options) =>
81
+ step(input.label, input.state, {
82
+ ...input,
83
+ ...options,
84
+ }),
85
+ "step-progress": (input, options) =>
86
+ stepProgress({
87
+ ...input,
88
+ ...options,
89
+ }),
90
+ table: (input, options) =>
91
+ table({
92
+ ...input,
93
+ ...options,
94
+ }),
82
95
  "task-summary": (input, options) => taskSummary(input, options),
83
96
  };
84
97
 
85
98
  // Global rendering flags accepted after `render <renderer>`.
86
- const globalRenderingFlags = new Set([
87
- "--no-color",
88
- "--no-colour",
89
- "--no-unicode",
90
- "--plain",
91
- ]);
99
+ const globalRenderingFlags = new Set(["--no-color", "--no-colour", "--no-unicode", "--plain"]);
92
100
 
93
101
  // Renderer names exposed for help text and tests.
94
102
  export const rendererNames = Object.keys(renderers);
@@ -28,10 +28,11 @@ export function createCliStyle(options = {}) {
28
28
  print: (value) => {
29
29
  console.log(value);
30
30
  },
31
- reporter: (reporterOptions = {}) => createReporter({
32
- ...resolvedOptions,
33
- ...reporterOptions,
34
- }),
31
+ reporter: (reporterOptions = {}) =>
32
+ createReporter({
33
+ ...resolvedOptions,
34
+ ...reporterOptions,
35
+ }),
35
36
  write: (value) => {
36
37
  process.stdout.write(value);
37
38
  },