fix: resolve 4 bugs in termui - #3657
Conversation
📝 WalkthroughWalkthroughFour example applications receive focused fixes for whitespace detection, hexadecimal entity parsing, floating-point percentage rounding, and decimal tab-key parsing. ChangesExample correctness fixes
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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/rss-reader/src/index.tsx`:
- Around line 28-31: Update the entity-decoding callback in the RSS reader’s
value replacement logic to validate parsed numeric code points before calling
String.fromCodePoint: require an integer within the Unicode range 0 through
0x10ffff, and return the original match for invalid or out-of-range values.
Apply this validation to both hexadecimal and decimal numeric entities.
In `@examples/todo-app/src/index.ts`:
- Line 107: Update the percentage calculation in the progress-value conversion
to add Number.EPSILON after scaling value by 100, ensuring values such as 0.145
round to 15 instead of 14 while preserving the existing Math.round behavior.
🪄 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: 0e838808-c101-4991-b3d9-38d0560e7e9e
📒 Files selected for processing (4)
examples/chat-app/src/index.tsxexamples/rss-reader/src/index.tsxexamples/todo-app/src/index.tsexamples/widget-gallery/src/index.ts
| 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); | ||
| return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
node <<'NODE'
for (const entity of ['&`#x00000041dead`;', '&`#x110000`;']) {
const value = entity.match(/&(`#x`?[0-9a-fA-F]+);/)[1];
const codePoint = Number.parseInt(value.slice(2, 10), 16);
try {
console.log(entity, String.fromCodePoint(codePoint));
} catch (error) {
console.error(entity, error.name);
}
}
NODERepository: Karanjot786/TermUI
Length of output: 197
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'File matches:\n'
fd -a 'index\.tsx$' . | sed 's#^\./##' | rg 'examples/rss-reader/src/index\.tsx|rss-reader' || true
printf '\nRelevant source:\n'
cat -n examples/rss-reader/src/index.tsx | sed -n '1,70p'
printf '\nBehavioral probe matching exact logic:\n'
node - <<'NODE'
function decode(value, entity) {
const codePoint = Number.parseInt(entity.slice(2, 10), 16);
try {
return { ok: true, value: Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : value };
} catch (error) {
return { ok: false, name: error.name, message: error.message };
}
}
for (const entity of [
'&`#x00000041dead`;',
'&`#x110000`;',
'&`#x10ffff`;',
'&`#x110001`;',
'&`#12345`;',
'&`#9999999`;',
'&`#110000`;',
'&`#x0041`;',
'&`#xc0`;'
]) {
const match = entity.match(/&(`#x`?[0-9a-fA-F]+);/);
if (!match) throw new TypeError('Unexpected entity shape');
const result = decode(entity, match[1]);
console.log(JSON.stringify({ entity, parsed: match[1], result }));
}
NODERepository: Karanjot786/TermUI
Length of output: 3709
Reject out-of-range numeric entities before decoding.
The current checks allow decimal values such as 𚶰, which exceeds the Unicode code-point limit and throws in String.fromCodePoint. Reject non-integer code points and values above 0x10ffff before decoding.
🤖 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 28 - 31, Update the
entity-decoding callback in the RSS reader’s value replacement logic to validate
parsed numeric code points before calling String.fromCodePoint: require an
integer within the Unicode range 0 through 0x10ffff, and return the original
match for invalid or out-of-range values. Apply this validation to both
hexadecimal and decimal numeric entities.
| const filled = Math.round(barWidth * value); | ||
|
|
||
| const pct = Math.round(value * 100); | ||
| const pct = Math.round(value * 100 + Number.EPSILON); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
node <<'NODE'
const value = 0.145;
const current = Math.round(value * 100 + Number.EPSILON);
const corrected = Math.round((value + Number.EPSILON) * 100);
if (current !== 14 || corrected !== 15) {
throw new Error(`Unexpected results: ${current}, ${corrected}`);
}
NODERepository: Karanjot786/TermUI
Length of output: 156
🌐 Web query:
MDN Number.EPSILON value JavaScript
💡 Result:
The Number.EPSILON property in JavaScript represents the difference between 1 and the smallest floating-point number greater than 1 [1][2]. Its value is 2^-52, which is approximately 2.220446049250313e-16 [1][3]. This property is a static data property of the Number object and cannot be changed, as its attributes are [[Writable]]: false, [[Enumerable]]: false, and [[Configurable]]: false [4][5]. It is primarily used to handle floating-point arithmetic inaccuracies when comparing numbers that are close in value, as standard equality operators (===) can be unreliable for floating-point calculations [2].
Citations:
- 1: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
- 2: https://github.com/mdn/content/blob/main/files/en-us/web/javascript/reference/global_objects/number/epsilon/index.md
- 3: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_strings
- 4: https://tc39.es/ecma262/multipage/numbers-and-dates.html
- 5: https://tc39.es/ecma262/2026/multipage/numbers-and-dates.html
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
node - <<'NODE'
const cases = [
{ value: 0.145, label: '0.145' },
{ value: Number.EPSILON / 100, label: 'Number.EPSILON/100' },
{ value: 0.005, label: '0.005' },
{ value: 0.999999999999999, label: 'near 1' },
];
for (const { value, label } of cases) {
const current = Math.round(value * 100 + Number.EPSILON);
const corrected = Math.round((value + Number.EPSILON) * 100);
console.log(label.padEnd(22), 'current:', current, 'corrected:', corrected, 'same:', current === corrected, 'value:', value, '0.145*100:', 0.145 * 100, 'eps:', Number.EPSILON);
}
NODERepository: Karanjot786/TermUI
Length of output: 703
Add Number.EPSILON before scaling the percentage.
Number.EPSILON is too small to reliably change the result after multiplication by 100. Use the scaled input so 0.145 rounds to 15 instead of 14.
- const pct = Math.round(value * 100 + Number.EPSILON);
+ const pct = Math.round((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.
| const pct = Math.round(value * 100 + Number.EPSILON); | |
| const pct = Math.round((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/todo-app/src/index.ts` at line 107, Update the percentage
calculation in the progress-value conversion to add Number.EPSILON after scaling
value by 100, ensuring values such as 0.145 round to 15 instead of 14 while
preserving the existing Math.round behavior.
Description
This PR fixes real bugs found in the codebase:
trim()to''misses whitespace-only input;.trim().length === 0is explicit.parseInt: without10, strings like'0x1F'or'08'parse in unintended bases.parseInt: without10, strings like'0x1F'or'08'parse in unintended bases.Number.EPSILONtoMath.round: prevents floating-point drift (e.g.1.005 * 100rounding to 100 instead of 101).Type of Change
How Has This Been Tested?
Checklist
Related Issue
Ref: #3656
Summary by CodeRabbit