Skip to content

Enhance CLI TUI; Fix formatting issues and filename padding#7

Merged
chris-c-thomas merged 6 commits intomainfrom
feat/tui
Mar 3, 2026
Merged

Enhance CLI TUI; Fix formatting issues and filename padding#7
chris-c-thomas merged 6 commits intomainfrom
feat/tui

Conversation

@chris-c-thomas
Copy link
Copy Markdown
Owner

@chris-c-thomas chris-c-thomas commented Mar 3, 2026

This pull request releases version 0.6.0 for the law2md monorepo, focusing on improved CLI output formatting, especially for multi-title conversions, and fixes some output and filename resolution issues. It also updates documentation and package versions, and introduces new tests for edge cases. The most important changes are grouped below:

CLI Output Improvements:

  • Multi-title convert --titles output now displays a single compact summary table (one row per title) with columns for Title, Name, Sections, Chapters, Tokens, and Duration, plus a bold totals row, instead of a full summary block per title. Single-file mode retains the detailed summary block. [1]], [2]])
  • The summary table and block now use the XML <heading> element for the title name (e.g., "GENERAL PROVISIONS") instead of dc:title ("Title N"). [1]], [2]], [3]])
  • Table border formatting is fixed so horizontal rules span the full width, matching column separators, by setting mid-intersection characters to "──". [1]], [2]], [3]], [4]])

Bug Fixes and Robustness:

  • The resolveUscXmlPath() function now correctly handles zero-padded and unpadded USC XML filenames, improving compatibility and fixing a bug with noUncheckedIndexedAccess. [1]], [2]], [3]])
  • Added comprehensive tests for resolveUscXmlPath() to cover edge cases and ensure correct fallback behavior. ([packages/cli/src/commands/convert.test.tsR1-R58])

Documentation and Project Structure:

  • Added .github/copilot-instructions.md with workspace instructions, architecture overview, code style, and XML/USLM handling conventions. ([.github/copilot-instructions.mdR1-R60])
  • Updated all package versions to 0.6.0 and changelogs to reflect the new release and changes. [1]], [2]], [3]], [4]], [5]], [6]])

Dependency and Monorepo Updates:

  • Added a law2md-monorepo dependency using a local link and updated pnpm-lock.yaml accordingly. [1]], [2]])

References: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18]

Summary by CodeRabbit

  • New Features

    • Compact multi-title conversion output with single aggregated metrics table and totals row
    • Title naming now derives from XML document structure instead of metadata
  • Bug Fixes

    • Corrected horizontal rules in table rendering
    • Fixed filename zero-padding resolution in path handling
  • Documentation

    • Added comprehensive workspace and development guidelines
  • Tests

    • Expanded test coverage for file path resolution

@chris-c-thomas chris-c-thomas requested a review from Copilot March 3, 2026 20:32
@chris-c-thomas chris-c-thomas self-assigned this Mar 3, 2026
@chris-c-thomas chris-c-thomas added fix enhancement Enhancements made to exisiting features or codebase labels Mar 3, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 3, 2026

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Free

📥 Commits

Reviewing files that changed from the base of the PR and between ec62953 and a8e6cbc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .github/copilot-instructions.md
  • CHANGELOG.md
  • package.json
  • packages/cli/CHANGELOG.md
  • packages/cli/package.json
  • packages/cli/src/commands/convert.test.ts
  • packages/cli/src/commands/convert.ts
  • packages/cli/src/ui.ts
  • packages/core/CHANGELOG.md
  • packages/core/package.json
  • packages/usc/CHANGELOG.md
  • packages/usc/package.json
  • packages/usc/src/converter.test.ts
  • packages/usc/src/converter.ts

📝 Walkthrough

Walkthrough

This PR represents a 0.6.0 release across the monorepo. Changes include version bumps to all packages, enhanced CLI output with data table metrics and timing, file path resolution with zero-padding fallback, and adjusted titleName derivation in the converter to prioritize XML headings. Workspace documentation and test coverage are added.

Changes

Cohort / File(s) Summary
Workspace Documentation & Guidelines
.github/copilot-instructions.md
New documentation file detailing repository workspace guidelines, architecture overview, code style conventions, testing practices, and XML/USLM handling rules.
Release 0.6.0 Changelog Entries
CHANGELOG.md, packages/cli/CHANGELOG.md, packages/core/CHANGELOG.md, packages/usc/CHANGELOG.md
Added version 0.6.0 sections documenting compact convert output, fixed horizontal rules in tables, filename zero-padding fixes, and CLI TUI formatting improvements. Dependency updates recorded.
Version Bumps
package.json, packages/cli/package.json, packages/core/package.json, packages/usc/package.json
Version increments from 0.5.0 to 0.6.0 across all packages. Root package.json adds local monorepo dependency link.
CLI Convert Logic Enhancements
packages/cli/src/commands/convert.ts, packages/cli/src/commands/convert.test.ts
New resolveUscXmlPath utility for file resolution with zero-padding fallback, new runConversion runner with elapsed timing, refactored single/multi-file conversion flows to aggregate per-title metrics, and structured summary output with data table. Comprehensive test suite added for file resolution logic.
CLI UI Refactoring
packages/cli/src/ui.ts
Introduces ANSI escape handling utilities and dynamic column width calculation. Centralizes table styling constants (TABLE_CHARS, TABLE_STYLE) and refactors summaryBlock and dataTable for consistent, width-aware rendering without altering exported signatures.
Converter Title Resolution
packages/usc/src/converter.ts, packages/usc/src/converter.test.ts
Updated convertTitle to prioritize titleHeading over metadata when deriving titleName. Test expectation adjusted to reflect "GENERAL PROVISIONS" (from heading) instead of "Title 1" (from metadata).

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI
    participant Resolver as File Resolver
    participant Converter
    participant UI
    participant Output

    User->>CLI: convert input.xml output.md
    CLI->>Resolver: resolveUscXmlPath(inputPath)
    alt File exists
        Resolver-->>CLI: resolved path
    else Try zero-padded variant
        Resolver->>Resolver: construct zero-padded name
        alt Padded file exists
            Resolver-->>CLI: padded path
        else Not found
            Resolver-->>CLI: undefined
            CLI->>Output: error & exit
        end
    end
    CLI->>Converter: runConversion(resolvedPath, options)
    Converter->>Converter: process XML (titleHeading preferred)
    Converter-->>CLI: {result, elapsed}
    CLI->>CLI: aggregate per-title metrics
    CLI->>UI: dataTable(metrics array + totals)
    UI->>UI: fillWidths (ANSI-aware measurement)
    UI->>UI: apply TABLE_CHARS & TABLE_STYLE
    UI-->>Output: formatted table
    CLI->>Output: final summary with totals
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Releases law2md v0.6.0 with a focus on improving CLI TUI formatting (especially multi-title convert --titles) and strengthening USC XML filename resolution, alongside version/changelog updates and new tests.

Changes:

  • Reworked CLI output formatting: shared table border config, full-width horizontal rules, and a compact multi-title conversion summary table with totals.
  • Updated USC conversion metadata to prefer <heading> for titleName and added a path resolver for padded/unpadded USC XML filenames.
  • Bumped package versions/changelogs to 0.6.0 and added repo workspace instructions.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds a root link: dependency entry (currently looks like a self-link).
package.json Adds law2md-monorepo: link: dependency at repo root.
CHANGELOG.md Documents 0.6.0 formatting + filename resolution changes.
packages/cli/src/ui.ts Introduces shared table chars/style and terminal-filling column width logic.
packages/cli/src/commands/convert.ts Adds resolveUscXmlPath, refactors conversion runs, and prints compact multi-title summary table.
packages/cli/src/commands/convert.test.ts Adds tests for resolveUscXmlPath.
packages/cli/package.json Version bump to 0.6.0.
packages/cli/CHANGELOG.md Changelog entry for 0.6.0.
packages/core/package.json Version bump to 0.6.0.
packages/core/CHANGELOG.md Changelog entry for 0.6.0.
packages/usc/package.json Version bump to 0.6.0.
packages/usc/CHANGELOG.md Changelog entry for 0.6.0.
packages/usc/src/converter.ts Sets titleName from <heading> when available.
packages/usc/src/converter.test.ts Updates expected titleName to match <heading>.
.github/copilot-instructions.md Adds repo/workspace guidance, conventions, and pitfalls.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm-lock.yaml
Comment on lines +10 to +13
dependencies:
law2md-monorepo:
specifier: 'link:'
version: 'link:'
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

pnpm-lock.yaml now contains a law2md-monorepo: link: dependency for the root importer. This appears to come from the self-dependency added in package.json and will likely cause the same install/cycle issues. Removing/fixing the root law2md-monorepo dependency should also remove this lockfile entry.

Suggested change
dependencies:
law2md-monorepo:
specifier: 'link:'
version: 'link:'

Copilot uses AI. Check for mistakes.
Comment thread packages/cli/src/ui.ts
): number[] | undefined {
const termWidth = process.stdout.columns || 80;
// Compute natural width per column (max visual length across all rows)
const natural = Array.from<number>({ length: colCount }).fill(0);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

Array.from<number>({ length: colCount }) is not assignable to ArrayLike<number> under strict TypeScript (missing numeric index signature) and will fail typechecking. Use Array(colCount).fill(0) or Array.from({ length: colCount }, () => 0) instead.

Suggested change
const natural = Array.from<number>({ length: colCount }).fill(0);
const natural = Array(colCount).fill(0);

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +75
// Check if filename matches usc{N}.xml pattern and try zero-padded
const dir = dirname(inputPath);
const base = basename(inputPath);
const match = /^usc(\d+)\.xml$/.exec(base);
if (match?.[1]) {
const padded = match[1].padStart(2, "0");
const paddedPath = join(dir, `usc${padded}.xml`);
if (existsSync(paddedPath)) return paddedPath;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

resolveUscXmlPath only falls back from unpadded → padded (e.g. usc3.xmlusc03.xml). If the user passes a padded filename but the actual file on disk is unpadded (usc03.xml input, usc3.xml exists), this will still return undefined. Consider trying the reverse fallback as well (strip leading zeros) to fully "handle zero-padded and unpadded" filenames.

Suggested change
// Check if filename matches usc{N}.xml pattern and try zero-padded
const dir = dirname(inputPath);
const base = basename(inputPath);
const match = /^usc(\d+)\.xml$/.exec(base);
if (match?.[1]) {
const padded = match[1].padStart(2, "0");
const paddedPath = join(dir, `usc${padded}.xml`);
if (existsSync(paddedPath)) return paddedPath;
// Check if filename matches usc{N}.xml pattern and try zero-padded / unpadded variants
const dir = dirname(inputPath);
const base = basename(inputPath);
const match = /^usc(\d+)\.xml$/.exec(base);
if (match?.[1]) {
const originalNumber = match[1];
// Fallback 1: unpadded → padded (e.g. usc3.xml → usc03.xml)
const padded = originalNumber.padStart(2, "0");
const paddedPath = join(dir, `usc${padded}.xml`);
if (existsSync(paddedPath)) return paddedPath;
// Fallback 2: padded → unpadded (e.g. usc03.xml → usc3.xml)
const unpadded = String(Number(originalNumber));
if (unpadded !== originalNumber) {
const unpaddedPath = join(dir, `usc${unpadded}.xml`);
if (existsSync(unpaddedPath)) return unpaddedPath;
}

Copilot uses AI. Check for mistakes.
Comment on lines 232 to 239
for (const [i, titleNum] of titles.entries()) {
const xmlPath = titleXmlPath(inputDir, titleNum);

if (!existsSync(xmlPath)) {
spinner.stop();
console.error(error(`XML file not found: ${xmlPath}`));
process.exit(1);
}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

Multi-title mode still hard-codes usc${pad2(titleNum)}.xml and exits early if that exact padded path doesn't exist. This bypasses the new resolveUscXmlPath() behavior, so directories containing usc1.xml (unpadded) will fail for --titles 1. Consider resolving xmlPath via resolveUscXmlPath(xmlPath) (or extending titleXmlPath) before the existence check and conversion.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +14
let tempDir: string;

afterEach(() => {
if (tempDir) {
rmSync(tempDir, { recursive: true, force: true });
}
});
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

tempDir is declared as string but is read in afterEach before being assigned in some tests. Under strict TypeScript this can trigger "used before being assigned" / type errors. Initialize it (e.g. let tempDir: string | undefined) and handle the undefined case, or assign a default empty string.

Copilot uses AI. Check for mistakes.
Comment thread package.json
Comment on lines +40 to 42
"dependencies": {
"law2md-monorepo": "link:"
}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

Root package.json adds a dependency on law2md-monorepo (the package's own name) using an empty link: specifier. A self-dependency like this is unusual and can break installs / create cyclic resolution; link: normally includes a path. If the intent was to depend on a local package, specify the actual target path (e.g. link:../...) and avoid depending on the root package itself.

Suggested change
"dependencies": {
"law2md-monorepo": "link:"
}
"dependencies": {}

Copilot uses AI. Check for mistakes.
@chris-c-thomas chris-c-thomas merged commit 4a103a9 into main Mar 3, 2026
7 checks passed
@chris-c-thomas chris-c-thomas deleted the feat/tui branch March 3, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Enhancements made to exisiting features or codebase fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants