Skip to content

Highlight whitespaces on renderer#78

Open
yanabel1996 wants to merge 22 commits into
mainfrom
feature/highlight-whitespaces
Open

Highlight whitespaces on renderer#78
yanabel1996 wants to merge 22 commits into
mainfrom
feature/highlight-whitespaces

Conversation

@yanabel1996

@yanabel1996 yanabel1996 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

I have implement highlighting white spaces, but i have a question. When we copy text should we have included whitespaces (i mean how it was before transforming visual). Now it copies only text without transforming whitespaces and whitespaces themselfs

Screenshot 2026-06-09 at 11 23 46 Screenshot 2026-06-09 at 11 23 55 Screenshot 2026-06-09 at 11 24 11

Summary by CodeRabbit

  • New Features

    • Invisible and problematic Unicode characters are now visibly marked in rendered text.
    • Added full-text search highlighting with theme-aware styling.
    • Search highlighting works across nested rendered content.
    • Text-formatting utilities are now available for broader integration.
  • Bug Fixes

    • Renderer wrappers now preserve additional rendering properties.
  • Changelog

    • Updated release information for version 27.5.7.

@yanabel1996 yanabel1996 self-assigned this Jun 9, 2026
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Unicode whitespace visualization and full-text highlighting utilities, integrates both transformations into RendererWrapper, exposes the new utilities from the package entry point, and updates styling and release metadata.

Changes

Highlighting Features

Layer / File(s) Summary
Unicode visualization utilities
src/utils/textFormatting/visualizeInvisibleCharacters.jsx
Defines special Unicode classification, renders visible markers for whitespace and special code points, and provides child/wrapper adapters.
Search term highlighting
src/utils/textFormatting/highlightSearchedFulltexts.jsx, src/utils/textFormatting/highlightSearchedFulltexts.scss
Normalizes search terms, highlights case-insensitive matches with themed spans, and adds highlight styling.
Renderer child transformation
src/utils/textFormatting/highlightChildren.jsx
Recursively processes primitive, array, and nested React children while honoring data-no-highlight.
Renderer highlighting integration
src/abc/Renderer.js, src/abc/Renderer.scss, src/components/RendererWrapper/RendererWrapper.jsx
Passes wrapper parameters from Renderer, visualizes children, applies optional full-text highlighting, and adds whitespace styling.
Text-formatting public exports
src/index.js, package.json, CHANGELOG.md
Exports the new utilities and records release version 27.5.7.
Estimated code review effort: 4 (Complex) ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Renderer
  participant RendererWrapper
  participant visualizeInvisibleCharacters
  participant highlightChildren
  participant highlightSearchedFulltexts
  Renderer->>RendererWrapper: pass children and wrapper props
  RendererWrapper->>visualizeInvisibleCharacters: visualize invisible characters
  visualizeInvisibleCharacters-->>RendererWrapper: processed children
  RendererWrapper->>highlightChildren: apply fulltextHighlightTerms
  highlightChildren->>highlightSearchedFulltexts: highlight text segments
  highlightSearchedFulltexts-->>highlightChildren: span-wrapped matches
  highlightChildren-->>RendererWrapper: highlighted children
  RendererWrapper-->>Renderer: render processed content
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: rendering whitespace visibly in the renderer.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/highlight-whitespaces

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.

@yanabel1996

Copy link
Copy Markdown
Collaborator Author
screen-recording-2026-06-09-at-113507_iq4eegKJ.mp4

@yanabel1996
yanabel1996 requested a review from Pe5h4 June 9, 2026 09:40

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/abc/Renderer.js (1)

51-71: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

plain() should return plain data, not React elements.

The plain() method is expected to return primitive values or plain strings (based on its name and separation from render()), but lines 55-56 and 68-70 now call highlightUnicodeChildren, which returns arrays of React elements for string inputs. This breaks the method's contract and will cause runtime errors in any code expecting plain values from plain().

🐛 Proposed fix: Remove highlighting from plain()
 	plain(key, value, schemaField)	{
 		// Render stringified component if value is a object
 		if (typeof value === 'object') {
 			try {
-				const highlightedValue = highlightUnicodeChildren(JSON.stringify(value));
-				return highlightedValue;
+				return JSON.stringify(value);
 			} catch(e) {
 				console.warn('Failed to stringify the renderer value:', value, e);
 				return value;
 			}
 		}
 
 		// Convert bigint to string (to preserve precision and to display the value when no other renderer is applied)
 		if (typeof value === "bigint") {
 			value = value.toString();
 		}
 
-		const highlightedValue = highlightUnicodeChildren(value);
-
-		return highlightedValue;
+		return value;
 	}
🤖 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 `@src/abc/Renderer.js` around lines 51 - 71, The plain(key, value, schemaField)
function must return primitive/plain string values but currently calls
highlightUnicodeChildren (which returns React elements) for objects and strings;
change plain() to return raw primitive values: for objects return
JSON.stringify(value) (or the original value on stringify failure) and for
bigint return value.toString(), then return that plain string without calling
highlightUnicodeChildren; update references to highlightUnicodeChildren only in
render() or UI-specific code, keeping plain() pure.
🧹 Nitpick comments (3)
src/abc/Renderer.scss (1)

3-7: 💤 Low value

Simplify vendor prefixes for modern browsers.

The -khtml-user-select, -o-user-select, and -ms-user-select prefixes are outdated as of 2026. Modern browsers support the standard user-select property, and at most -webkit-user-select and -moz-user-select may be needed for older browser versions.

♻️ Simplified CSS
 .renderer-whitespace {
 	color: var(--bs-secondary-color);
+	-webkit-user-select: none;
+	-moz-user-select: none;
+	user-select: none;
-	-webkit-user-select: none;
-	-khtml-user-select: none;
-	-moz-user-select: none;
-	-ms-user-select: none;
-	-o-user-select: none;
-	user-select: none;
 }
🤖 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 `@src/abc/Renderer.scss` around lines 3 - 7, Remove the outdated vendor
prefixes in the user-select rules in Renderer.scss: delete -khtml-user-select,
-o-user-select, and -ms-user-select and ensure the block contains only the
modern properties needed (keep -webkit-user-select and -moz-user-select if you
need older compatibility, plus the standard user-select). Update the rule where
those properties appear so the final set is: -webkit-user-select,
-moz-user-select (optional), and user-select.
src/utils/highlightWhitespaces.js (1)

62-98: ⚡ Quick win

Remove unused SPECIAL_UNICODE_RANGES and commented-out range check.

SPECIAL_UNICODE_RANGES is defined but never used because the range check on line 96 is commented out. If range checking is not needed for this feature, remove the constant and the dead code path to reduce confusion and maintenance burden.

♻️ Proposed cleanup
-/**
- * Inclusive [start, end] code point ranges.
- * `@type` {[number, number][]}
- */
-export const SPECIAL_UNICODE_RANGES = [
-	// Whitespace
-	[0x2000, 0x200A], // En/Em quad, En/Em space, thin/hair space, etc.
-
-	// Bidirectional control
-	[0x202A, 0x202E], // LRE, RLE, PDF, LRO, RLO
-	[0x2066, 0x2069], // LRI, RLI, FSI, PDI
-
-	// C0 / C1 controls
-	[0x0001, 0x0008], // SOH–BS
-	[0x000E, 0x001F], // SO–US
-	[0x0080, 0x009F], // C1 controls (incl. NEL U+0085, CSI U+009B)
-
-	// Other problematic
-	[0xFFF9, 0xFFFB], // Interlinear annotation
-	[0xFDD0, 0xFDEF], // Noncharacters
-	[0xE0000, 0xE007F], // Tag characters (ASCII smuggling)
-	[0xE0100, 0xE01EF], // Variation Selectors Supplement
-	[0xFE00, 0xFE0F], // Variation Selectors
-	[0xD800, 0xDFFF], // Surrogates (invalid standalone)
-	[0xE000, 0xF8FF], // Private Use Area (BMP)
-	[0xF0000, 0xFFFFD], // Private Use Area (supplementary)
-	[0x100000, 0x10FFFD], // Private Use Area (supplementary)
-	[0x2400, 0x2426], // Control Pictures (display glyphs)
-];
-
 /**
  * `@param` {number} codePoint
  * `@returns` {boolean}
  */
 export function isSpecialUnicodeCodePoint(codePoint) {
-	if (SPECIAL_UNICODE_CODE_POINTS.has(codePoint)) {
-		return true;
-	}
-	// return SPECIAL_UNICODE_RANGES.some(([start, end]) => codePoint >= start && codePoint <= end);
-    return false;
+	return SPECIAL_UNICODE_CODE_POINTS.has(codePoint);
 }
🤖 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 `@src/utils/highlightWhitespaces.js` around lines 62 - 98, The file defines
SPECIAL_UNICODE_RANGES but never uses it and has a commented-out range check in
isSpecialUnicodeCodePoint; remove the dead constant and the commented-out line
so isSpecialUnicodeCodePoint simply returns whether SPECIAL_UNICODE_CODE_POINTS
has the codePoint (ensure SPECIAL_UNICODE_CODE_POINTS remains defined/
imported); if range checking is actually required instead, re-enable and use
SPECIAL_UNICODE_RANGES in the function (e.g., iterate its [start,end] tuples) —
choose one approach and delete the unused code path accordingly.
src/components/DataTable2/DataTable2.jsx (1)

326-342: Optional refactor: explicit return is stylistic.

The change from implicit to explicit return in the map callback is purely stylistic and doesn't add functional value. The implicit return was already clear and concise. However, this change is acceptable and doesn't introduce issues.

🤖 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 `@src/components/DataTable2/DataTable2.jsx` around lines 326 - 342, The
rows.map callback was changed from an implicit to an explicit return which is
purely stylistic; revert the callback in the JSX block that uses rows.map to the
prior concise implicit-return form (the mapping that returns the <tr> directly)
or, if you prefer to keep the explicit return, ensure consistency across
DataTable2.jsx by updating other similar map callbacks (e.g., columns.map and
rows.map usages) to the same style; touch the rows.map callback and related
column rendering logic (column.render, loading branch) to restore consistent
concise mapping style.
🤖 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 `@src/abc/Renderer.js`:
- Around line 37-47: The Renderer currently calls
highlightUnicodeChildren(value) before passing children into RendererWrapper,
causing duplicate highlighting because RendererWrapper already memoizes and
highlights its children; remove the call to highlightUnicodeChildren from
Renderer.render and pass the raw value as the child into <RendererWrapper> (keep
data-value={value} and data-key={key} and component prop) so only
RendererWrapper performs the highlighting logic.

In `@src/components/DataTable2/readme.md`:
- Around line 63-71: The fenced code block showing the DataTableCard2 usage
lacks a language specifier; update the opening fence to include a language
(e.g., change ``` to ```jsx) so the JSX snippet (DataTableCard2, props app,
columns, loader, header, disableFooter) is properly highlighted and linted in
the readme.

In `@src/utils/highlightWhitespaces.js`:
- Around line 8-9: The JSDoc type for SPECIAL_UNICODE_CODE_POINTS is wrong (says
`@type` {number[]}) while the value is a Set; update the comment above the export
of SPECIAL_UNICODE_CODE_POINTS to use the correct JSDoc type annotation `@type`
{Set<number>} so the doc matches the actual exported Set and tooling/linters
understand the correct type.
- Line 149: The span in src/utils/highlightWhitespaces.js is adding a dynamic
class name unicode-${hexUnicode} (alongside renderer-whitespace) that has no
matching CSS; remove the dynamic class and instead add a stable attribute (e.g.,
data-unicode or data-codepoint with the hexUnicode value) and update the
stylesheet to target the single .renderer-whitespace or the new data-* selector
for any per-code-point styling; locate the span generation in
highlightWhitespaces.js and replace the dynamic class with the data attribute,
then add/adjust CSS rules to use .renderer-whitespace or [data-unicode] rather
than unicode-XXXX.

---

Outside diff comments:
In `@src/abc/Renderer.js`:
- Around line 51-71: The plain(key, value, schemaField) function must return
primitive/plain string values but currently calls highlightUnicodeChildren
(which returns React elements) for objects and strings; change plain() to return
raw primitive values: for objects return JSON.stringify(value) (or the original
value on stringify failure) and for bigint return value.toString(), then return
that plain string without calling highlightUnicodeChildren; update references to
highlightUnicodeChildren only in render() or UI-specific code, keeping plain()
pure.

---

Nitpick comments:
In `@src/abc/Renderer.scss`:
- Around line 3-7: Remove the outdated vendor prefixes in the user-select rules
in Renderer.scss: delete -khtml-user-select, -o-user-select, and -ms-user-select
and ensure the block contains only the modern properties needed (keep
-webkit-user-select and -moz-user-select if you need older compatibility, plus
the standard user-select). Update the rule where those properties appear so the
final set is: -webkit-user-select, -moz-user-select (optional), and user-select.

In `@src/components/DataTable2/DataTable2.jsx`:
- Around line 326-342: The rows.map callback was changed from an implicit to an
explicit return which is purely stylistic; revert the callback in the JSX block
that uses rows.map to the prior concise implicit-return form (the mapping that
returns the <tr> directly) or, if you prefer to keep the explicit return, ensure
consistency across DataTable2.jsx by updating other similar map callbacks (e.g.,
columns.map and rows.map usages) to the same style; touch the rows.map callback
and related column rendering logic (column.render, loading branch) to restore
consistent concise mapping style.

In `@src/utils/highlightWhitespaces.js`:
- Around line 62-98: The file defines SPECIAL_UNICODE_RANGES but never uses it
and has a commented-out range check in isSpecialUnicodeCodePoint; remove the
dead constant and the commented-out line so isSpecialUnicodeCodePoint simply
returns whether SPECIAL_UNICODE_CODE_POINTS has the codePoint (ensure
SPECIAL_UNICODE_CODE_POINTS remains defined/ imported); if range checking is
actually required instead, re-enable and use SPECIAL_UNICODE_RANGES in the
function (e.g., iterate its [start,end] tuples) — choose one approach and delete
the unused code path accordingly.
🪄 Autofix (Beta)

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

Run ID: 5efed192-f77f-4ce8-a094-c9c6c2617d28

📥 Commits

Reviewing files that changed from the base of the PR and between 877067d and 44b7a3f.

📒 Files selected for processing (6)
  • src/abc/Renderer.js
  • src/abc/Renderer.scss
  • src/components/DataTable2/DataTable2.jsx
  • src/components/DataTable2/readme.md
  • src/components/RendererWrapper/RendererWrapper.jsx
  • src/utils/highlightWhitespaces.js

Comment thread src/abc/Renderer.js Outdated
Comment on lines 63 to 71
```
<DataTableCard2
app={app}
columns={columns}
loader={loader}
header={<Header />}
hideFooter={true}
disableFooter={true}
/>
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language specifier to fenced code block.

The code block starting at line 63 should specify a language identifier for proper syntax highlighting and linting compliance.

📝 Proposed fix
-```
+```jsx
 <DataTableCard2
 	app={app}
 	columns={columns}
 	loader={loader}
 	header={<Header />}
 	disableFooter={true}
 />
 ```
📝 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
```
<DataTableCard2
app={app}
columns={columns}
loader={loader}
header={<Header />}
hideFooter={true}
disableFooter={true}
/>
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 63-63: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 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 `@src/components/DataTable2/readme.md` around lines 63 - 71, The fenced code
block showing the DataTableCard2 usage lacks a language specifier; update the
opening fence to include a language (e.g., change ``` to ```jsx) so the JSX
snippet (DataTableCard2, props app, columns, loader, header, disableFooter) is
properly highlighted and linted in the readme.

Source: Linters/SAST tools

Comment thread src/utils/highlightWhitespaces.js Outdated
Comment on lines +8 to +9
/** @type {number[]} */
export const SPECIAL_UNICODE_CODE_POINTS = new Set([

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Correct the JSDoc type annotation.

The JSDoc comment states @type {number[]} but SPECIAL_UNICODE_CODE_POINTS is instantiated as a Set, not an array.

📝 Suggested fix
-/** `@type` {number[]} */
+/** `@type` {Set<number>} */
 export const SPECIAL_UNICODE_CODE_POINTS = new Set([
📝 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
/** @type {number[]} */
export const SPECIAL_UNICODE_CODE_POINTS = new Set([
/** `@type` {Set<number>} */
export const SPECIAL_UNICODE_CODE_POINTS = new Set([
🤖 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 `@src/utils/highlightWhitespaces.js` around lines 8 - 9, The JSDoc type for
SPECIAL_UNICODE_CODE_POINTS is wrong (says `@type` {number[]}) while the value is
a Set; update the comment above the export of SPECIAL_UNICODE_CODE_POINTS to use
the correct JSDoc type annotation `@type` {Set<number>} so the doc matches the
actual exported Set and tooling/linters understand the correct type.

Comment thread src/utils/highlightWhitespaces.js Outdated
Comment thread src/abc/Renderer.js Outdated
quotesOnKeys={false}
enableClipboard={false}
indentWidth={8}
src={value}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

indentation here and there

Comment thread src/abc/Renderer.js Outdated
Comment thread src/abc/Renderer.js Outdated
Comment thread src/abc/Renderer.scss

// Wrapper for datatable context
export function DataTableCard2({ columns, loader, loaderParams, header, className, initialLimit = 0, rowHeight = 38, disableParams = undefined, hideFooter = false, rowStyle }) {
export function DataTableCard2({ columns, loader, loaderParams, header, className, initialLimit = 0, rowHeight = 38, disableParams = undefined, disableFooter = false, rowStyle }) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why there are changes to DataTable2? I dont think its necessary for the whitespaces highligher :)

Comment thread src/components/DataTable2/readme.md Outdated
```

To remove footer from the DataTable2, `hideFooter={true}` should be set.
To remove footer from the DataTable2, `disableFooter={true}` should be set.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

do it in other PR eventually

Comment thread src/utils/highlightWhitespaces.js Outdated
if (SPECIAL_UNICODE_CODE_POINTS.has(codePoint)) {
return true;
}
// return SPECIAL_UNICODE_RANGES.some(([start, end]) => codePoint >= start && codePoint <= end);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove it or write a commentary why it is commented in

@yanabel1996
yanabel1996 force-pushed the feature/highlight-whitespaces branch from 44b7a3f to 1751ac7 Compare June 16, 2026 07:26
@yanabel1996
yanabel1996 force-pushed the feature/highlight-whitespaces branch from 1751ac7 to 64ce28b Compare June 16, 2026 07:31
@yanabel1996

Copy link
Copy Markdown
Collaborator Author

Hi, I have mistakenly pushed commit from another branch, resolved it.

Then I deleted double highlighting in renerer, deleted unnecessary styles and added a new condition (checking if in the end or in the start of the string are special unicode points before spaces to highlight that spaces too). You can see that case on the photo, in the end of the page are space + unicode

Screenshot 2026-06-16 at 10 32 02

@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: 1

🤖 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 `@src/utils/highlightWhitespaces.js`:
- Around line 101-115: The getAsciiSpaceEdges function has a surrogate pair
handling bug where it increments/decrements indices by 1 regardless of character
width, causing incorrect edge detection when supplementary plane characters are
present. Fix this by updating both the leading edge loop (where leadingEnd is
incremented) and trailing edge loop (where trailingStart is decremented) to
increment/decrement by the correct number of UTF-16 code units for each
character: use 2 code units for code points > 0xFFFF and 1 code unit otherwise.
Reference the correct handling already implemented in the main
highlightWhitespaces function at line 154 to ensure consistency.
🪄 Autofix (Beta)

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

Run ID: df1dac27-b1de-4155-8688-b063099523c2

📥 Commits

Reviewing files that changed from the base of the PR and between 44b7a3f and 1b25058.

📒 Files selected for processing (4)
  • src/abc/Renderer.js
  • src/abc/Renderer.scss
  • src/components/RendererWrapper/RendererWrapper.jsx
  • src/utils/highlightWhitespaces.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/abc/Renderer.scss
  • src/components/RendererWrapper/RendererWrapper.jsx

Comment thread src/utils/textFormatting/visualizeInvisibleCharacters.jsx
@yanabel1996
yanabel1996 requested a review from Pe5h4 June 16, 2026 08:49
Comment thread src/abc/Renderer.js Outdated
Comment thread src/abc/Renderer.js
Comment thread src/abc/Renderer.js
Comment thread src/utils/highlightWhitespaces.js Outdated
@yanabel1996
yanabel1996 requested a review from Pe5h4 June 19, 2026 12:17

@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: 1

🤖 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 `@src/utils/highlightRendererChildren.js`:
- Around line 24-29: The array handling in the `if (Array.isArray(children))`
branch only applies text highlighting to string nodes within the array but
ignores React elements nested inside it. Modify this block to recursively
process React elements in the array as well. Instead of only calling
`highlightFulltextInNodes`, map through the array children and for each child
element, recursively apply the highlighting logic (similar to how non-array
elements are handled) so that text descendants within React elements in the
array also receive fulltext highlighting.
🪄 Autofix (Beta)

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

Run ID: 5cffef1f-676c-4938-a2d8-29e5aa62d542

📥 Commits

Reviewing files that changed from the base of the PR and between af1adbe and cbedbc3.

📒 Files selected for processing (6)
  • src/abc/Renderer.js
  • src/abc/Renderer.scss
  • src/index.js
  • src/utils/highlightRendererChildren.js
  • src/utils/highlightSearchedFulltexts.js
  • src/utils/highlightWhitespaces.js
💤 Files with no reviewable changes (1)
  • src/abc/Renderer.js
✅ Files skipped from review due to trivial changes (1)
  • src/abc/Renderer.scss

Comment thread src/utils/textFormatting/highlightChildren.jsx

@Pe5h4 Pe5h4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we may need to do some restructuralization. in utils create another folder named highlighting or similar, then put these highliting utils there

Comment thread src/utils/highlightSearchedFulltexts.js Outdated
};

// Highlight searched fulltexts in the text by replacing matched terms with a span
export const highlightSearchedFulltexts = (text, searchValue, highlightClassName = 'bg-warning') => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please have a look here and reuse the colors TeskaLabs/asab-webui-shell-lib#53

Comment thread src/index.js Outdated
} from './utils/highlightWhitespaces.js';
export { highlightSearchedFulltexts } from './utils/highlightSearchedFulltexts.js';
export {
highlightRendererChildren,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is it called highlightRendererChildren? I would focus on reuse, so it should not be named as such if we want to use it elsewhere as well

Comment thread src/index.js Outdated
export {
highlightRendererChildren,
createFulltextHighlightWrapper,
} from './utils/highlightRendererChildren.js';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not sure if this is a viable name of the file. also use jsx filetype

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

it this a viable name? it does not highlight, it just make the whitespaces visible, or not?

@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: 1

🤖 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 `@src/utils/highlightRendererChildren.js`:
- Around line 24-40: The array-handling branch in highlightRendererChildren is
re-processing spans created by highlightFulltextInNodes, causing redundant
recursive highlighting. Replace the current two-step flow in
highlightRendererChildren with a single-pass traversal that handles string nodes
and React elements directly, so highlighted <span
className='search-text-highlight'> nodes are not fed back into the recursion.
Keep the logic localized to highlightRendererChildren and its use of
highlightText/highlightFulltextInNodes behavior.
🪄 Autofix (Beta)

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

Run ID: be751106-e9ca-4c9c-918b-9b3bed57a2e5

📥 Commits

Reviewing files that changed from the base of the PR and between cbedbc3 and 3bb454e.

📒 Files selected for processing (3)
  • src/utils/highlightRendererChildren.js
  • src/utils/highlightSearchedFulltexts.js
  • src/utils/highlightSearchedFulltexts.scss
✅ Files skipped from review due to trivial changes (1)
  • src/utils/highlightSearchedFulltexts.scss

Comment thread src/utils/textFormatting/highlightChildren.jsx
@yanabel1996

Copy link
Copy Markdown
Collaborator Author

@Pe5h4 Hi, I have refactored code how you said (rename components and files, restructure architecture).

But I don't understand you comment - please have a look here and reuse the colors TeskaLabs/asab-webui-shell-lib#53

I did that. That MR just change colors for searching on web highlighting (that's not a class or variable). Please, can you explain what do you mean

@yanabel1996
yanabel1996 requested a review from Pe5h4 June 30, 2026 12:06
};

// Wrap a renderer wrapper component with fulltext search highlighting
export const createFulltextHighlightWrapper = (BaseWrapper, fulltextHighlightTerms) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

hmm, I am thinking here. wont this factory recreate the wrapper every time it is called? I mean even if you wrap it in the useMemo (as you have in your other MR) in lower level components, it may still recreate and therefore it is not ideal. Like we can loose some info/state of wrapped components because of this. can you validate that?

@yanabel1996

Copy link
Copy Markdown
Collaborator Author

So, i reconsider the highlighting and remove wrapper for that, so it highlights just with function hightlightChildren. It avoids recreating the componnent

@yanabel1996
yanabel1996 requested a review from Pe5h4 July 2, 2026 15:50
return children;
};

export const createUnicodeVisualizeWrapper = (BaseWrapper) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am a bit puzzled here and would like to understand the code more broadly. You have removed the highlighting factory, which was creating re-renders, but this factory is still here. It does the same thing... I am not really convinced over the implementation.

I understand that we need something which will identify the empty chars in the component and renders the marks, but is this really a solution here? I may be wrong, but on the same side, I am not convinced that your code is sustainable and that it works effectively without any unnecessary re-rendering and stuff either.

Also, why the visualization of the whitespaces is not default part of the RendererWrapper and needs to be set up in lower level?

@yanabel1996

Copy link
Copy Markdown
Collaborator Author

You were right, i replace all logic here.
Now all logic for fulltext highlighting and whitespace visualizing are in webui-components-lib. Thanks then you clarify me that part.

@yanabel1996
yanabel1996 requested a review from Pe5h4 July 8, 2026 13:29

@Pe5h4 Pe5h4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks better, but I would advice a bit more updates here

Comment thread src/abc/Renderer.js Outdated
data-key={key} // Passing key (to eventually work with in the external wrapper)
component={params?.WrapperComponent || "span"}
>{value}</RendererWrapper>);
fulltextHighlightTerms={params?.fulltextHighlightTerms}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this would require a commentary. dont leave that uncommented, because devs then can only guess what is that. Also since its not a required value, I would maybe dont pass that at all (specifically), but you can pass the whole params

<RendererWrapper
         {...(params ?? {})} // Passing wrapper params down to the children
	    data-value={value} // Passing value (to eventually work with in the external wrapper)
	    data-key={key} // Passing key (to eventually work with in the external wrapper)
	    component={params?.WrapperComponent || 'span'}
>{value}</RendererWrapper>

export function RendererWrapper({
children,
component: Component = 'span', // Default tag, can be overloaded
fulltextHighlightTerms,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this can be removed

const dataValue = rest?.['data-value'];

let processedChildren = visualizeUnicodeChildren(children);
if (fulltextHighlightTerms) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

// Validate if fulltext terms exist to proceed with highliting of a fulltext based search
const fulltextTerms = rest?.params?.fulltextTerms;
if (fulltextTerms) { ... }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

there wouldn't be params - const fulltextTerms = rest?.params?.fulltextTerms; just rest?.fulltextTerms;

Because of destructurization

Яна Белоусова added 2 commits July 13, 2026 13:54
@yanabel1996
yanabel1996 requested a review from Pe5h4 July 13, 2026 12:03
Comment thread src/abc/Renderer.js Outdated
data-key={key} // Passing key (to eventually work with in the external wrapper)
component={params?.WrapperComponent || "span"}
>{value}</RendererWrapper>);
>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

indentation

}) {
const dataValue = rest?.['data-value'];
let processedChildren = visualizeUnicodeChildren(children);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

unnecessary empty line

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

visualizeInvisibleCharacters would be a bit better name, also the folder name should change

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@Pe5h4 renamed it

@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 `@src/utils/textFormatting/highlightChildren.jsx`:
- Around line 59-64: Update the custom-component fallback in the
highlightChildren flow so React elements are returned unchanged rather than
replaced with highlightText output from nestedDataValue. Preserve
primitive-value highlighting for supported text content, and use the existing
children return path for custom components.
- Around line 30-33: Update highlightChildren to detect the visualization
wrapper’s no-highlight marker before recursing and return that element
unchanged. Add the same generic marker to the spans created by
visualizeInvisibleCharacters, ensuring searches cannot match or highlight their
rendered artifacts while ordinary elements retain the existing recursion
behavior.
🪄 Autofix (Beta)

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

Run ID: 09f3f935-d5db-4c3b-9047-9b27bd885ce7

📥 Commits

Reviewing files that changed from the base of the PR and between cbedbc3 and f7cb5d9.

📒 Files selected for processing (7)
  • src/abc/Renderer.js
  • src/components/RendererWrapper/RendererWrapper.jsx
  • src/index.js
  • src/utils/textFormatting/highlightChildren.jsx
  • src/utils/textFormatting/highlightSearchedFulltexts.js
  • src/utils/textFormatting/highlightSearchedFulltexts.scss
  • src/utils/textFormatting/visualizeInvisibleCharacters.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/abc/Renderer.js

Comment thread src/utils/textFormatting/highlightChildren.jsx
Comment thread src/utils/textFormatting/highlightChildren.jsx Outdated
@yanabel1996
yanabel1996 requested a review from Pe5h4 July 15, 2026 12:11

@Pe5h4 Pe5h4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Seems fine from my side, please add changelog + upgrade version in package.json file.

I will add @ateska as a reviewer now because of the visulalizeInvisibleCharacters

@Pe5h4
Pe5h4 requested a review from ateska July 15, 2026 15:02

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

oh and can you please change the file extensions from js to jsx ? thanks

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

here as well

@ateska

ateska commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Seems fine from my side, please add changelog + upgrade version in package.json file.

I will add @ateska as a reviewer now because of the visulalizeInvisibleCharacters

Ok - but I need some kind of briefing here ;-)

@Pe5h4

Pe5h4 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Seems fine from my side, please add changelog + upgrade version in package.json file.
I will add @ateska as a reviewer now because of the visulalizeInvisibleCharacters

Ok - but I need some kind of briefing here ;-)

@ateska oh, sorry, sure - this PR is about rendering a whitespaces/special characters. the reason for that is we (and users) want to be aware of them, so thats easier to locate them and fix these inconsitencies properly in parsers, etc.. This is to be used first in Discover screen,

In visulalizeInvisibleCharacters.jsx, there is a list of special characters for determination, since I am not very into that (I have insufficient knowledge here), I would like you to validate that as well, that we did not forget for any and that the rendering(visualizing) process of the special characters/whitespaces is proper.

@yanabel1996 will add more context here eventually

@ateska ateska left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we have some kind of extendible unit test that will allow easy addition on all possible malicious strings .... so that we can evolve this?


// Possible whitespace unicode code points
export const SPECIAL_UNICODE_CODE_POINTS = new Set([
// Whitespace

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suggest to include all characters 0x00 - 0x31.

@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: 1

🧹 Nitpick comments (1)
src/utils/textFormatting/highlightSearchedFulltexts.jsx (1)

38-48: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Simplify match detection by leveraging split capturing group behavior.

When using String.prototype.split with a regex containing exactly one capturing group (...), the returned array strictly alternates between non-matched and matched segments. This guarantees every matched term will be placed at an odd index (1, 3, 5...), and every non-match at an even index (0, 2, 4...).

You can completely remove the highlightedTerms Set and the toLowerCase() comparisons, which improves performance and simplifies the logic.

♻️ Proposed refactor
-	const highlightedTerms = new Set(terms.map((term) => term.toLowerCase()));
-
	return sourceText.split(matchRegex).map((part, index) => {
-		if (highlightedTerms.has(part.toLowerCase())) {
+		if (index % 2 !== 0) {
			return (
				<span key={`${part}-${index}`} className='search-text-highlight'>
					{part}
				</span>
			);
		}
🤖 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 `@src/utils/textFormatting/highlightSearchedFulltexts.jsx` around lines 38 -
48, In the sourceText.split(matchRegex) mapping, remove the highlightedTerms Set
and lowercase comparisons, and determine matches by the segment index being odd,
leveraging matchRegex’s single capturing group. Preserve the existing
highlighted span and plain-text rendering for matched and non-matched segments.
🤖 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 `@src/utils/textFormatting/visualizeInvisibleCharacters.jsx`:
- Around line 189-195: Update visualizeInvisibleCharacters to recursively
process array children, applying visualizeWhitespaces to each string or number
element while preserving the existing handling of scalar values and non-text
children. Use the function’s own recursive path so nested arrays are visualized
consistently.

---

Nitpick comments:
In `@src/utils/textFormatting/highlightSearchedFulltexts.jsx`:
- Around line 38-48: In the sourceText.split(matchRegex) mapping, remove the
highlightedTerms Set and lowercase comparisons, and determine matches by the
segment index being odd, leveraging matchRegex’s single capturing group.
Preserve the existing highlighted span and plain-text rendering for matched and
non-matched segments.
🪄 Autofix (Beta)

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

Run ID: 96c772f2-d971-436e-aed5-9e66621989c9

📥 Commits

Reviewing files that changed from the base of the PR and between a53b440 and 0e238e1.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • package.json
  • src/utils/textFormatting/highlightSearchedFulltexts.jsx
  • src/utils/textFormatting/visualizeInvisibleCharacters.jsx

Comment on lines +189 to +195
export const visualizeInvisibleCharacters = (children) => {
if (typeof children === 'string' || typeof children === 'number') {
return visualizeWhitespaces(String(children));
}

return children;
};

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

Support arrays of children to ensure whitespace visualization applies consistently.

If RendererWrapper receives an array of text nodes (e.g., ["Hello", " ", "World"]), visualizeInvisibleCharacters will currently return the array untouched, skipping the whitespace visualization.

Consider recursively processing arrays so that text fragments within them are correctly visualized.

🐛 Proposed fix
 export const visualizeInvisibleCharacters = (children) => {
 	if (typeof children === 'string' || typeof children === 'number') {
 		return visualizeWhitespaces(String(children));
 	}
+
+	if (Array.isArray(children)) {
+		return React.Children.map(children, (child) => visualizeInvisibleCharacters(child));
+	}
 
 	return children;
 };
📝 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
export const visualizeInvisibleCharacters = (children) => {
if (typeof children === 'string' || typeof children === 'number') {
return visualizeWhitespaces(String(children));
}
return children;
};
export const visualizeInvisibleCharacters = (children) => {
if (typeof children === 'string' || typeof children === 'number') {
return visualizeWhitespaces(String(children));
}
if (Array.isArray(children)) {
return React.Children.map(children, (child) => visualizeInvisibleCharacters(child));
}
return children;
};
🤖 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 `@src/utils/textFormatting/visualizeInvisibleCharacters.jsx` around lines 189 -
195, Update visualizeInvisibleCharacters to recursively process array children,
applying visualizeWhitespaces to each string or number element while preserving
the existing handling of scalar values and non-text children. Use the function’s
own recursive path so nested arrays are visualized consistently.

@yanabel1996

Copy link
Copy Markdown
Collaborator Author

@ateska i have added missing special characters and create the file with extendible tests. But I am not sure where to put that file. We have discussed with Franta about it and decided, that here is not a good place to store

@yanabel1996
yanabel1996 requested a review from ateska July 17, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants