Skip to content

fix: resolve 4 bugs in termui - #3487

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

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

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes real bugs found in the codebase:

  • Added explicit radix to parseInt: without 10, strings like '0x1F' or '08' parse in unintended bases.
  • Added Number.EPSILON to Math.round: prevents floating-point drift (e.g. 1.005 * 100 rounding to 100 instead of 101).
  • Removed redundant boolean comparison: x === true is equivalent to x (and x === false to !x), and shorter to read.
  • Replaced global isNaN with Number.isNaN: the global version coerces its argument, so isNaN('1') returns false while Number.isNaN is strict.

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: #3486

Summary by CodeRabbit

  • Bug Fixes
    • Improved progress-bar percentage rounding for more accurate displayed values.
    • Fixed hexadecimal HTML entity decoding to correctly limit parsed values.
    • Improved numeric selection validation for more reliable prompt interactions.

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

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The changes refine numeric handling in the Pomodoro timer, RSS reader, and UI prompt selection. They adjust rounding precision, bound hexadecimal entity parsing to eight characters, and replace global isNaN validation with Number.isNaN.

Changes

Numeric correctness fixes

Layer / File(s) Summary
Example numeric handling
examples/pomodoro-timer/src/index.tsx, examples/rss-reader/src/index.tsx
Progress percentage rounding adds Number.EPSILON. Hexadecimal entity parsing reads at most eight characters.
Prompt choice validation
packages/ui/src/prompts.ts
promptSelect uses Number.isNaN when validating parsed choices.

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

Possibly related PRs

Suggested reviewers: karanjot786

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies a bug-fix change and summarizes the primary objective of resolving four TermUI bugs.
Description check ✅ Passed The description explains the fixes, identifies issue #3486, states the change type, and documents manual testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
🧪 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: 2

🤖 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/pomodoro-timer/src/index.tsx`:
- Line 185: Update the percentage label calculation in the timer’s
label-rendering method to add an epsilon scaled to the percentage value after
multiplying _value by 100, so values such as 0.285 round to 29%. Add a boundary
test covering this near-half percentage case and preserve the existing
conditional label behavior.

In `@examples/rss-reader/src/index.tsx`:
- Around line 30-31: Update the entity-decoding logic around codePoint to
validate the hexadecimal digit portion before parsing: reject entities with more
than eight digits, and reject parsed values above 0x10FFFF, returning match
unchanged in both cases. Only call String.fromCodePoint for valid Unicode scalar
values while preserving the existing finite-value check.
🪄 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: b95e24f8-700f-4d0e-bf3a-11fa183d948b

📥 Commits

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

📒 Files selected for processing (3)
  • examples/pomodoro-timer/src/index.tsx
  • examples/rss-reader/src/index.tsx
  • packages/ui/src/prompts.ts

const attrs = styleToCellAttrs(this._style);

const label = this._showLabel ? ` ${Math.round(this._value * 100)}%` : '';
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';

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

Scale the epsilon to the percentage value.

At Line 185, the calculation adds Number.EPSILON after multiplying by 100. That epsilon can be too small to change values near 28.5. For example, 0.285 * 100 can produce 28.499999999999996, so the label can still display 28% instead of 29%.

Use an epsilon scaled for the percentage range and add a boundary test.

Proposed fix
-        const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';
+        const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON * 100)}%` : '';
📝 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
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON * 100)}%` : '';
🤖 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/pomodoro-timer/src/index.tsx` at line 185, Update the percentage
label calculation in the timer’s label-rendering method to add an epsilon scaled
to the percentage value after multiplying _value by 100, so values such as 0.285
round to 29%. Add a boundary test covering this near-half percentage case and
preserve the existing conditional label behavior.

Comment on lines +30 to 31
const codePoint = Number.parseInt(entity.slice(2, 10), 16);
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;

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 and out-of-range entities instead of truncating them.

entity contains the complete match, but slice(2, 10) discards digits after the first eight. An input such as A is therefore decoded as 0x4 instead of remaining unchanged. Check the digit length before parsing. Also reject values above 0x10FFFF before calling String.fromCodePoint.

Proposed fix
-      const codePoint = Number.parseInt(entity.slice(2, 10), 16);
-      return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
+      const digits = entity.slice(2);
+      if (digits.length > 8) return match;
+      const codePoint = Number.parseInt(digits, 16);
+      return Number.isFinite(codePoint) && codePoint <= 0x10FFFF
+        ? String.fromCodePoint(codePoint)
+        : match;
📝 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
const codePoint = Number.parseInt(entity.slice(2, 10), 16);
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
const digits = entity.slice(2);
if (digits.length > 8) return match;
const codePoint = Number.parseInt(digits, 16);
return Number.isFinite(codePoint) && codePoint <= 0x10FFFF
? String.fromCodePoint(codePoint)
: match;
🤖 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` around lines 30 - 31, Update the
entity-decoding logic around codePoint to validate the hexadecimal digit portion
before parsing: reject entities with more than eight digits, and reject parsed
values above 0x10FFFF, returning match unchanged in both cases. Only call
String.fromCodePoint for valid Unicode scalar values while preserving the
existing finite-value check.

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