Skip to content

fix: resolve 4 bugs in termui - #3553

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

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

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes real bugs found in the codebase:

  • Added Number.EPSILON to Math.round: prevents floating-point drift (e.g. 1.005 * 100 rounding to 100 instead of 101).
  • Prevented interval leak: repeated mounts now clear the previous interval before scheduling a new one.
  • 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: #3552

Summary by CodeRabbit

  • Bug Fixes
    • Improved Pomodoro timer percentage display accuracy at rounding boundaries.
    • Enhanced RSS reader handling of hexadecimal HTML entities, preventing malformed values from being processed.
    • Improved Showcase keyboard tab selection for more reliable navigation.
    • Fixed weather dashboard refresh behavior to prevent overlapping update timers and ensure consistent five-second refreshes.

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

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Four example applications update percentage rounding, hexadecimal entity parsing, tab-key parsing, and weather refresh interval setup.

Changes

Example correctness fixes

Layer / File(s) Summary
Numeric rounding and parsing fixes
examples/pomodoro-timer/src/index.tsx, examples/rss-reader/src/index.tsx, examples/showcase/src/index.tsx
Percentage rounding adds Number.EPSILON. Hexadecimal parsing limits the entity substring to eight characters. Tab-key parsing uses radix 10.
Weather refresh interval lifecycle
examples/weather/src/index.tsx
The dashboard clears the stored interval before creating and storing a new five-second interval.

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

Possibly related PRs

Suggested reviewers: karanjot786

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the fixes but omits required package, GSSoC, checklist, and reviewer-note sections, and does not use the required issue-closing format. Add all required template sections, identify the affected packages, complete the checklist and GSSoC fields, and replace Ref: #3552 with `Closes `#3552.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies a bug-fix pull request that resolves four TermUI bugs.
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: 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/pomodoro-timer/src/index.tsx`:
- Line 185: Update the percentage calculation in the label expression within the
timer display so Number.EPSILON is added to this._value before multiplying by
100, then round the scaled result as before. Preserve the existing conditional
label behavior and formatting.

In `@examples/rss-reader/src/index.tsx`:
- Around line 30-31: Update the entity decoding logic around the hexadecimal and
decimal branches to parse the complete numeric value without truncating digits,
reject hexadecimal entities with more than eight digits, and only decode values
in the valid Unicode range 0x0–0x10FFFF. Apply the same range validation before
String.fromCodePoint in the decimal branch, returning match for invalid or
out-of-range entities.

In `@examples/weather/src/index.tsx`:
- Line 204: Declare the __interval property used by the weather polling setup in
index.tsx by adding a global Window augmentation with the appropriate
timer-handle type, or replace the window attachment with a typed module-level
variable. Ensure both clearInterval and setInterval calls remain type-safe under
strict TypeScript checking.
🪄 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: 3bdbd58b-300f-4bc4-8c5e-e8eb20da2dc4

📥 Commits

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

📒 Files selected for processing (4)
  • examples/pomodoro-timer/src/index.tsx
  • examples/rss-reader/src/index.tsx
  • examples/showcase/src/index.tsx
  • examples/weather/src/index.tsx

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

🧩 Analysis chain

🏁 Script executed:

node <<'NODE'
const value = 29 / 200;
const current = Math.round(value * 100 + Number.EPSILON);
const corrected = Math.round((value + Number.EPSILON) * 100);
console.log({ current, corrected });
if (current === 15 || corrected !== 15) process.exit(1);
NODE

Repository: Karanjot786/TermUI

Length of output: 187


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate target file and class:"
fd -a 'index.tsx$' . | sed 's#^\./##' | grep 'examples/pomodoro-timer/src/index.tsx' || true

echo
echo "Relevant file context:"
sed -n '160,200p' examples/pomodoro-timer/src/index.tsx | cat -n | sed 's/^/165+/'

echo
echo "Search for GradientProgressBar setValue:"
rg -n "class GradientProgressBar|_value|setValue|Number\.EPSILON|percent|showLabel" examples/pomodoro-timer/src/index.tsx

Repository: Karanjot786/TermUI

Length of output: 3046


Apply the epsilon before scaling the percentage value.

Number.EPSILON is too small after multiplying by 100. For example, this._value = 29 / 200 can produce 14.499999999999998, so the current expression displays 14% instead of 15%.

Proposed fix
-        const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';
+        const label = this._showLabel ? ` ${Math.round((this._value + 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 + 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
calculation in the label expression within the timer display so Number.EPSILON
is added to this._value before multiplying by 100, then round the scaled result
as before. Preserve the existing conditional label behavior and formatting.

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

node <<'NODE'
const truncated = Number.parseInt('000000041'.slice(0, 8), 16);
console.log({ truncated });

try {
  String.fromCodePoint(Number.parseInt('110000', 16));
  process.exit(1);
} catch (error) {
  console.log(error.name);
}
NODE

Repository: Karanjot786/TermUI

Length of output: 184


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Files matching index.tsx:\n'
fd -a 'index\.tsx$' . | sed 's#^\./##'

printf '\nRelevant excerpt from examples/rss-reader/src/index.tsx:\n'
if [ -f examples/rss-reader/src/index.tsx ]; then
  nl -ba examples/rss-reader/src/index.tsx | sed -n '1,80p'
else
  echo 'not found'
fi

printf '\nSearch for decodeEntities usages:\n'
rg -n "decodeEntities|decodeEntity|&`#x`|`#x`|String\.fromCodePoint|fromCodePoint" examples/rss-reader/src || true

Repository: Karanjot786/TermUI

Length of output: 2181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Relevant excerpt from examples/rss-reader/src/index.tsx:\n'
awk '{printf "%6d  %s\n", NR, $0}' examples/rss-reader/src/index.tsx | sed -n '1,100p'

printf '\nSearch for decodeEntities and code-point parsing usages:\n'
grep -RInE "decodeEntities|decodeEntity|&`#x`|`#x`|String\.fromCodePoint|fromCodePoint|Number\.parseInt" examples/rss-reader/src || true

Repository: Karanjot786/TermUI

Length of output: 5050


Reject invalid hexadecimal entities before decoding.

entity.slice(2, 10) drops digits after the eighth, so &#x000000041; decodes as U+00000004 instead of U+0041. The Number.isFinite check also allows overlong entities like &#x110000; to call String.fromCodePoint, which throws RangeError. Parse the full entity value, reject more than eight hex digits, and keep valid code points only within 0x10FFFF; apply the same range check to the decimal branch.

🤖 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 the hexadecimal and decimal branches to parse the complete
numeric value without truncating digits, reject hexadecimal entities with more
than eight digits, and only decode values in the valid Unicode range
0x0–0x10FFFF. Apply the same range validation before String.fromCodePoint in the
decimal branch, returning match for invalid or out-of-range entities.

}

setInterval(fetchWeather, 5000);
clearInterval(window.__interval); window.__interval = setInterval(fetchWeather, 5000);

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 3 '__interval|interface Window|declare global' examples/weather --glob '*.{ts,tsx,d.ts}' || true
rg -n -C 2 '"strict"[[:space:]]*:[[:space:]]*true' --glob 'tsconfig*.json' --glob '!node_modules' || true

Repository: Karanjot786/TermUI

Length of output: 582


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)tsconfig.*\.json$|examples/weather/src/index\.tsx$|\.d\.ts$|package\.json$|pnpm-lock\.yaml$|yarn\.lock$|package-lock\.json$' || true

echo "== example index relevant section =="
sed -n '180,215p' examples/weather/src/index.tsx | cat -n -v

echo "== ts configs =="
for f in $(git ls-files '*tsconfig*.json' 'packages/**/tsconfig*.json' 'apps/**/tsconfig*.json' '**/tsconfig*.json' | rg -v node_modules || true); do
  echo "--- $f"
  sed -n '1,80p' "$f"
done

echo "== window declarations repo-wide =="
rg -n -C 3 '^\s*(declare )?(interface|type|namespace)\s+Window\s*|declare global|__interval|interface\s+Global.*Window|--extends|--skipLibCheck|--noImplicitAny|--strict' . --glob '*.{ts,tsx,d.ts,json,yaml,yml}' --glob '!node_modules/**' || true

Repository: Karanjot786/TermUI

Length of output: 21330


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== weather package metadata =="
cat examples/weather/package.json

echo "== root package scripts/typecheck =="
sed -n '1,160p' package.json

echo "== lockfile TS version candidates =="
for f in pnpm-lock.yaml package-lock.json yarn.lock; do
  [ -f "$f" ] || continue
  echo "--- $f"
  rg -n 'typescript|`@types/node`|`@types/react`|`@termuijs`' "$f" | head -80 || true
done

echo "== examples/weather typecheck if TS is available =="
if command -v npx >/dev/null 2>&; then
  (set -x; npx --package typescript -- tsc --version 2>&1);
  npx --package typescript -- tsc --noEmit --strict --module ESNext --moduleResolution Bundler --target ES2022 examples/weather/src/index.tsx 2>&1 | sed -n '1,120p' || true
else
  echo "npx not available"
fi

echo "== declare global occurrences excluding node_modules =="
rg -n -C 2 'declare global|interface Window|declare module' . --glob '!node_modules/**' || true

Repository: Karanjot786/TermUI

Length of output: 1965


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cd examples/weather

if command -v bun >/dev/null 2>&1; then
  echo "== bun tsc if available =="
  bun tsc --version 2>&1 || true
  bun tsc --noEmit 2>&1 | sed -n '1,160p'
else
  echo "bun not available"
fi

echo "== node_modules/typescript availability =="
if [ -x node_modules/.bin/tsc ]; then
  ./node_modules/.bin/tsc --version
  ./node_modules/.bin/tsc --noEmit 2>&1 | sed -n '1,160p' || true
else
  echo "node_modules/.bin/tsc not available"
fi

Repository: Karanjot786/TermUI

Length of output: 253


Declare window.__interval.

examples/weather runs strict: true, but window.__interval has no TypeScript declaration. Add a Window augmentation for this timer handle, or avoid attaching it directly to window.

🤖 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/weather/src/index.tsx` at line 204, Declare the __interval property
used by the weather polling setup in index.tsx by adding a global Window
augmentation with the appropriate timer-handle type, or replace the window
attachment with a typed module-level variable. Ensure both clearInterval and
setInterval calls remain type-safe under strict TypeScript checking.

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. type:bug +10 pts. Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant