Skip to content

✨ [feat] improve CLI and language discovery - #10

Merged
Nick2bad4u merged 5 commits into
mainfrom
feat/cli-terminal-experience
Aug 24, 2026
Merged

Nick2bad4u merged 5 commits into
mainfrom
feat/cli-terminal-experience

Conversation

@Nick2bad4u

@Nick2bad4u Nick2bad4u commented Aug 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • expand the canonical library to 75 layouts and 470 badges, including live-validated combinations from the official Badgen catalog
  • add 45 language facets across the generated catalog, package API, CLI, URL state, and responsive gallery
  • overhaul the CLI with structured help, aliases, validated options, ANSI styling, NO_COLOR support, Git context detection, output/copy modes, and JSON output
  • add offline terminal badge rendering, bounded live Badgen SVG-title previews, and clean Markdown previews through Glow
  • harden persisted gallery preferences so URL-controlled values resolve to trusted literals before reaching browser storage
  • keep SonarQube Cloud Automatic Analysis with the existing coverage-free .sonarcloud.properties scope

Findings resolved during PR verification

  • fix CodeQL js/double-escaping by replacing the multi-pass SVG title decoder with a single-pass XML entity parser
  • remove both Sonar maintainability findings by simplifying CLI argument recording and layout-count formatting
  • add behavioral terminal and preview tests to restore the repository-owned coverage gate without lowering thresholds

Validation

  • npm run release:verify
  • 44 Vitest tests across 6 files
  • coverage: 97.82% statements, 91.41% branches, 100% functions, and 99.19% lines
  • Publint and ATTW package-surface validation
  • npm pack dry run
  • Actionlint, Gitleaks, JSCPD, Lychee, Secretlint, ESLint, Stylelint, Remark, Prettier, and TypeScript
  • desktop and 390px mobile Playwright QA with zero console errors
  • ANSI, live Badgen, and Glow CLI smoke tests

Hosted verification

Final candidate 1dad51b8e4f6dccdab5e9977b4bd0dd1ba3d31a8 has no blocking checks. SonarQube Cloud reports an OK gate with zero open PR issues and zero hotspots. CodeQL alert 11 is fixed. Validate, CodeQL, Codecov project/patch/components, dependency review, Gitleaks, TruffleHog, Socket, and StepSecurity all pass.

Coverage remains owned by Codecov; SonarQube Cloud intentionally uses Automatic Analysis without coverage imports.

✨ [feat] Classify all 75 layouts across 45 language facets, add three live-validated badge combinations, and expose language metadata through the generated catalog and package API.

✨ [feat] Add URL-persisted language filtering, responsive gallery controls, language metadata on cards, and trusted-literal normalization for persisted view and sort preferences.

🧪 [test] Cover language filtering, generated catalog metadata, pagination, and untrusted gallery preference fallbacks.

📝 [docs] Document canonical language annotations and live SVG-title validation rules for future layout contributions.
✨ [feat] Add structured command help, language-aware discovery, Git context detection, validated command options, output files, clipboard support, JSON modes, aliases, and actionable error suggestions.

✨ [feat] Render responsive ANSI badge previews with NO_COLOR support, optional bounded live Badgen SVG-title lookups, and clean Markdown summaries piped to Glow.

🧪 [test] Cover terminal width behavior, preview parsing and warnings, CLI discovery, rendering, and option validation.

📝 [docs] Replace the CLI guide and refresh README examples for the expanded terminal workflow.
@github-actions github-actions Bot added documentation Improvements or additions to documentation enhancement New feature or request build Build system or packaging changes cli Command-line interface changes testing Test coverage, fixtures, or test infrastructure website labels Aug 24, 2026
Comment thread src/preview.ts Fixed
🐛 [fix] Replace the multi-pass SVG title decoder with a single-pass XML entity parser that preserves nested encodings and rejects invalid XML code points.

🧪 [test] Cover named, decimal, hexadecimal, nested, and out-of-range entity behavior reported by CodeQL.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 834890e694

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli.ts
Comment on lines +435 to +437
const match =
/github\.com[\/:](?<owner>[^\s\/:]+)\/(?<repo>[^\s\/]+?)(?:\.git)?$/iv.exec(
remote.trim()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Anchor GitHub detection to the actual remote host

When a non-GitHub remote merely contains github.com/ in its hostname or path—for example, https://gitlab.com/github.com/foo/bar.git—this unanchored regex reports foo/bar as a GitHub repository. The new automatic context then silently renders badges and README blocks for github.com/foo/bar instead of requiring explicit coordinates as documented; parse the URL/SSH host and require it to equal github.com.

Useful? React with 👍 / 👎.

Comment thread library.md
[![Coveralls coverage.](https://flat.badgen.net/coveralls/c/github/OWNER/REPO/BRANCH)](https://coveralls.io/github/OWNER/REPO?branch=BRANCH)
[![DeepScan grade.](https://flat.badgen.net/deepscan/grade/team/DEEPSCAN_TEAM/project/DEEPSCAN_PROJECT/branch/DEEPSCAN_BRANCH)](https://deepscan.io/dashboard/#view=project&tid=DEEPSCAN_TEAM&pid=DEEPSCAN_PROJECT&bid=DEEPSCAN_BRANCH)
[![XO code style.](https://flat.badgen.net/xo/status/PACKAGE)](https://github.com/xojs/xo)
[![Tidelift subscription status.](https://flat.badgen.net/tidelift/npm/PACKAGE)](https://www.sonarsource.com/solutions/security/)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point the Tidelift badge at its package report

When users copy or render this canonical conditional layout, clicking the Tidelift subscription badge opens a generic SonarSource security page that is unrelated to both Tidelift and PACKAGE. Replace the destination with the corresponding Tidelift package/subscription page so the badge leads to the report it describes.

AGENTS.md reference: AGENTS.md:L3-L3

Useful? React with 👍 / 👎.

Comment thread docs/app.js
/** @param {BadgeCatalogEntry} entry @param {string} placeholder */
function exampleValue(entry, placeholder) {
const haystack = `${entry.category} ${entry.title}`;
const haystack = `${entry.category} ${entry.languages.join(" ")} ${entry.title}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add preview values for the new service placeholders

When the gallery initially renders the new Mastodon layout or the DeepScan row in Conditional badges, generalExamples has no values for MASTODON_USER, MASTODON_SERVER, or any DEEPSCAN_* placeholder, so exampleValue falls back to the literal uppercase names and the supposedly personalized preview requests invalid service coordinates. Add working non-secret examples for these newly canonical placeholders, as is already done for the other service-specific fields.

AGENTS.md reference: AGENTS.md:L3-L3

Useful? React with 👍 / 👎.

Comment thread src/preview.ts
Comment on lines +14 to +15
const suspiciousTitlePattern =
/(?:^|\b)(?:429|500|discontinued|error|timeout|undefined|unknown)(?:\b|$)/iv;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict numeric error detection to actual error titles

When a valid live metric happens to equal 429 or 500—for example, a repository with exactly 500 stars or a package with 1,500 downloads—the word-boundary pattern matches that ordinary count and marks the badge as an error. Detect these numbers only in an HTTP/error context rather than anywhere in the SVG title so legitimate milestone values are not rendered as red warnings.

Useful? React with 👍 / 👎.

🚜 [refactor] Extract parsed-option recording from the argument loop and centralize singular layout-count formatting to remove the two Sonar maintainability findings without changing CLI behavior.
🧪 [test] Exercise automatic color policy, all semantic ANSI roles, badge contrast, malformed tables, constrained widths, safe URL metadata, network and HTTP failures, missing SVG titles, and single-pass XML entities.

🦺 [test] Restore the existing coverage gate without lowering thresholds: 97.82% statements, 91.41% branches, 100% functions, and 99.19% lines.
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.15686% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/terminal.ts 90.66% 0 Missing and 7 partials ⚠️
src/preview.ts 92.06% 0 Missing and 5 partials ⚠️
@@            Coverage Diff             @@
##             main      #10      +/-   ##
==========================================
- Coverage   93.44%   92.56%   -0.88%     
==========================================
  Files           4        6       +2     
  Lines         122      269     +147     
  Branches       30       79      +49     
==========================================
+ Hits          114      249     +135     
  Misses          2        2              
- Partials        6       18      +12     
Files with missing lines Coverage Δ
docs/gallery-state.js 100.00% <100.00%> (ø)
src/catalog.ts 96.55% <100.00%> (+0.71%) ⬆️
src/preview.ts 92.06% <92.06%> (ø)
src/terminal.ts 90.66% <90.66%> (ø)

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6b889be...1dad51b. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dad51b8e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/terminal.ts
Comment on lines +89 to +93
const maximumWidth = Math.max(
headers.length * 8,
options.maxWidth ??
(process.stdout.columns > 0 ? process.stdout.columns : 100)
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor narrow terminal widths

When stdout is narrower than headers.length * 8—for example, badge-layouts list in a 30-column terminal—this lower bound ignores the detected terminal width, and the per-column minimums can make the five-column list at least 46 characters wide. The terminal then wraps or misaligns the table instead of contracting to the available width; permit narrower columns or switch to a compact layout when the requested width is below the table minimum.

Useful? React with 👍 / 👎.

Comment thread src/cli.ts
Comment on lines 689 to +690
if (parsed.booleans.has("json")) {
ensureNoOutputFile(parsed);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate output combinations before copying

When a supported clipboard utility is installed and the user combines --copy --json --output, the command updates the clipboard and prints a success message before ensureNoOutputFile rejects the invocation and returns a failure status. The same ordering exists in the render path, so both commands can perform an externally visible side effect despite reporting failure; reject the incompatible output combination before invoking the clipboard tool.

Useful? React with 👍 / 👎.

@Nick2bad4u

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dad51b8e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/preview.ts
return { ...badge, error: "SVG title unavailable" };
}
const decodedTitle = decodeXml(title.trim());
return suspiciousTitlePattern.test(decodedTitle)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip terminal controls from live badge titles

When --live receives an SVG title containing terminal control characters—whether reflected from upstream badge metadata or returned by a compromised service—decodedTitle is passed unchanged to the ANSI renderer and Glow, allowing escape sequences such as OSC links or cursor-control codes to affect the user's terminal. Remove C0/C1 and escape characters from fetched titles before storing or displaying them.

Useful? React with 👍 / 👎.

Comment thread src/preview.ts
Comment on lines +105 to +107
if (!response.ok) return { ...badge, error: `HTTP ${response.status}` };
const title = /<title>(?<title>[\s\S]*?)<\/title>/v.exec(
await response.text()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject non-SVG live-preview responses

When Badgen or an intermediary returns a successful HTML error page containing a <title> element, this code accepts that page title as the badge's live value because it checks only the HTTP status before applying a generic title regex. Validate the response content type or SVG root before extracting the title so --live reports these responses as failures instead of displaying unrelated HTML page titles as badge data.

Useful? React with 👍 / 👎.

@Nick2bad4u
Nick2bad4u merged commit a3fe55f into main Aug 24, 2026
24 checks passed
@Nick2bad4u
Nick2bad4u deleted the feat/cli-terminal-experience branch August 24, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Build system or packaging changes cli Command-line interface changes documentation Improvements or additions to documentation enhancement New feature or request testing Test coverage, fixtures, or test infrastructure website

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants