Skip to content

fix: resolve 4 bugs in termui - #3719

Closed
saurabhhhcodes wants to merge 1 commit into
Karanjot786:mainfrom
saurabhhhcodes:fix/termui-82659
Closed

fix: resolve 4 bugs in termui#3719
saurabhhhcodes wants to merge 1 commit into
Karanjot786:mainfrom
saurabhhhcodes:fix/termui-82659

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes real bugs found in the codebase:

  • Fixed default sort: .sort() coerces elements to strings, so [10, 9, 2] sorts as [10, 2, 9]; numeric comparator sorts correctly.
  • Removed redundant boolean comparison: x === true is equivalent to x (and x === false to !x), and shorter to read.
  • Added explicit radix to parseInt: without 10, strings like '0x1F' or '08' parse in unintended bases.
  • Added explicit radix to parseInt: without 10, strings like '0x1F' or '08' parse in unintended bases.

Type of Change

  • Bug fix (non-breaking change fixing an issue)

How Has This Been Tested?

  • Local manual testing

Checklist

  • My code follows the style guidelines
  • I have performed a self-review

Related Issue

Ref: #3718

Summary by CodeRabbit

  • Bug Fixes
    • Improved form keyboard shortcut handling when modifier keys are pressed.
    • Fixed RSS reader parsing for hexadecimal character references with long numeric values.
    • Corrected tab-key navigation parsing for consistent decimal values.
    • Improved TreeSelect value comparison to handle numeric string ordering correctly.

@github-actions github-actions Bot added type:bug +10 pts. Bug fix. area:examples Example apps. area:ui @termuijs/ui labels Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The changes update keyboard shortcut conditions, limit hexadecimal entity parsing to eight digits, enforce decimal tab parsing, and apply numeric sorting during TreeSelect value comparison.

Changes

Parsing and comparison corrections

Layer / File(s) Summary
Keyboard and numeric parsing updates
examples/forms-and-validation/src/index.tsx, examples/rss-reader/src/index.tsx, examples/showcase/src/index.tsx
The form shortcut uses the changed control-key expression. RSS hexadecimal parsing limits the digit substring to eight characters. Showcase tab parsing uses an explicit decimal radix.
TreeSelect value comparison
packages/ui/src/TreeSelect.ts
_valuesEqual sorts values with numeric coercion before comparing arrays.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: karanjot786

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the changes and testing, but it omits required sections, package information, and most template checklist items. Add all required template sections, identify affected packages, link the issue with Closes #3718``, and complete the checklist accurately.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the four bug fixes and follows the required type: short description format.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/forms-and-validation/src/index.tsx`:
- Line 125: In the clear-form keyboard shortcut condition, replace the non-null
assertion on event.ctrl with logical negation so the modal is shown for plain
“c” and Ctrl+C remains handled by the earlier path. Update the condition in the
visible event-key handler without changing the surrounding shortcut behavior.

In `@examples/rss-reader/src/index.tsx`:
- Line 30: Update the entity-decoding logic around codePoint to validate the
hexadecimal digit length before parsing; when the entity exceeds eight digits,
return match unchanged, otherwise preserve the existing Number.parseInt
behavior.

In `@packages/ui/src/TreeSelect.ts`:
- Around line 185-186: Update _valuesEqual to define one named comparator and
pass it to both sortedA and sortedB, ensuring numeric and nonnumeric string
values are ordered consistently without NaN comparisons. Add regression tests
covering both numeric and nonnumeric string arrays.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ab2b69cd-21df-4bc2-b90e-b8a3287a317b

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7584e and 10a973a.

📒 Files selected for processing (4)
  • examples/forms-and-validation/src/index.tsx
  • examples/rss-reader/src/index.tsx
  • examples/showcase/src/index.tsx
  • packages/ui/src/TreeSelect.ts

}

if (event.key === 'c' && event.ctrl === false) {
if (event.key === 'c' && event.ctrl !) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/forms-and-validation/src/index.tsx"
rg -n -C 3 "event\.key === 'c'|event\.ctrl" "$file"

Repository: Karanjot786/TermUI

Length of output: 906


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'JS'
const cases = [
  { key: 'c', ctrl: false },
  { key: 'c', ctrl: true },
  { key: 'C', ctrl: false },
];
for (const event of cases) {
  const firstCondition = event.key === 'q' || (event.ctrl && event.key === 'c');
  // Simulate TS "event.ctrl !" as runtime event.ctrl with no boolean inversion.
  const secondCondition = event.key === 'c' && event.ctrl;
  console.log(JSON.stringify({
    event,
    branch: firstCondition ? 'return false' : secondCondition ? 'show modal' : 'char input',
  }));
}
JS

Repository: Karanjot786/TermUI

Length of output: 328


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/forms-and-validation/src/index.tsx"
sed -n '112,132p' "$file"

Repository: Karanjot786/TermUI

Length of output: 840


Use logical negation for the clear-form shortcut.

event.ctrl ! asserts non-null, so it still checks event.ctrl. The path consumes Ctrl+C earlier, and plain c now reaches character input, so this.modal.show() never runs.

Replace it with !event.ctrl.

Proposed fix
-        if (event.key === 'c' && event.ctrl !) {
+        if (event.key === 'c' && !event.ctrl) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (event.key === 'c' && event.ctrl !) {
if (event.key === 'c' && !event.ctrl) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/forms-and-validation/src/index.tsx` at line 125, In the clear-form
keyboard shortcut condition, replace the non-null assertion on event.ctrl with
logical negation so the modal is shown for plain “c” and Ctrl+C remains handled
by the earlier path. Update the condition in the visible event-key handler
without changing the surrounding shortcut behavior.

return value.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, entity: string) => {
if (entity.startsWith('#x')) {
const codePoint = Number.parseInt(entity.slice(2), 16);
const codePoint = Number.parseInt(entity.slice(2, 10), 16);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject overlong hexadecimal entities instead of truncating them.

The regular expression accepts all hexadecimal digits, but Line 30 parses only the first eight. For example, &#x00000041F; decodes as A and silently drops the final F.

Validate the digit length before parsing. Return match when the entity exceeds the supported limit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/rss-reader/src/index.tsx` at line 30, Update the entity-decoding
logic around codePoint to validate the hexadecimal digit length before parsing;
when the entity exceeds eight digits, return match unchanged, otherwise preserve
the existing Number.parseInt behavior.

Comment on lines +185 to 186
const sortedA = [...a].sort((a, b) => a - b);
const sortedB = [...b].sort();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

npx tsc --noEmit --pretty false

Repository: Karanjot786/TermUI

Length of output: 5708


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- locate files ---\n'
git ls-files | rg '(^|/)TreeSelect\.(ts|test\.ts)$|(^|/)tsconfig\.json$|packages/ui/src/index\.ts$' || true

printf '\n--- TreeSelect.ts outline ---\n'
ast-grep outline packages/ui/src/TreeSelect.ts --view expanded || true

printf '\n--- TreeSelect.ts relevant lines 140-210 ---\n'
cat -n packages/ui/src/TreeSelect.ts | sed -n '140,210p'

printf '\n--- TreeSelect.test.ts relevant lines ---\n'
cat -n packages/ui/src/TreeSelect.test.ts | sed -n '1,220p'

printf '\n--- package/compiler flags references ---\n'
for f in $(git ls-files '*tsconfig*.json'); do
  echo "--- $f ---"
  cat -n "$f" | sed -n '1,180p'
done

printf '\n--- string subtraction runtime probe ---\n'
node - <<'JS'
const inputs = [
  ['10', '2'],
  ['2', '10'],
  ['10', '10'],
  ['s', 'a'],
  ['a', 's']
];
for (const [a, b] of inputs) {
  const diff = a - b;
  console.log(JSON.stringify([a, b, diff, diff === diff]))
}
JS

Repository: Karanjot786/TermUI

Length of output: 247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- locate files ---'
git ls-files | rg '(^|/)TreeSelect\.(ts|test\.ts)$|(^|/)tsconfig\.json$|packages/ui/src/index\.ts$' || true

printf '%s\n' ''
printf '%s\n' '--- TreeSelect.ts outline ---'
ast-grep outline packages/ui/src/TreeSelect.ts --view expanded || true

printf '%s\n' ''
printf '%s\n' '--- TreeSelect.ts relevant lines 140-210 ---'
cat -n packages/ui/src/TreeSelect.ts | sed -n '140,210p'

printf '%s\n' ''
printf '%s\n' '--- TreeSelect.test.ts relevant lines ---'
cat -n packages/ui/src/TreeSelect.test.ts | sed -n '1,220p'

printf '%s\n' ''
printf '%s\n' '--- package/compiler flags references ---'
for f in $(git ls-files '*tsconfig*.json'); do
  echo "--- $f ---"
  cat -n "$f" | sed -n '1,180p'
done

printf '%s\n' ''
printf '%s\n' '--- string subtraction runtime probe ---'
node - <<'JS'
const inputs = [
  ['10', '2'],
  ['2', '10'],
  ['10', '10'],
  ['s', 'a'],
  ['a', 's']
];
for (const [a, b] of inputs) {
  const diff = a - b;
  console.log(JSON.stringify([a, b, diff, diff === diff]))
}
JS

Repository: Karanjot786/TermUI

Length of output: 29869


Use one comparator for _valuesEqual.

a - b can produce NaN for nonnumeric strings like 's' and 'a', and sortedB still uses lexicographic order. Apply the same named comparator to both sorted arrays, and include regression tests for numeric and nonnumeric string values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/TreeSelect.ts` around lines 185 - 186, Update _valuesEqual to
define one named comparator and pass it to both sortedA and sortedB, ensuring
numeric and nonnumeric string values are ordered consistently without NaN
comparisons. Add regression tests covering both numeric and nonnumeric string
arrays.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:examples Example apps. area:ui @termuijs/ui type:bug +10 pts. Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant