Add new RichTextEditor component (#12505)#12531
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe PR replaces the Quill-based RichTextEditor with a native Blazor editor backed by a DOM JavaScript bridge. It removes legacy Quill typings and assets, adds new editor contracts and feature partials, rewrites the component UI and styling, and updates the demo and tests. ChangesNative RichTextEditor replacement
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 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: 17
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (5)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs-333-336 (1)
333-336: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
[Required]should treat visually empty HTML as empty
AtBitRichTextEditorDemo.razor.cslines 333-336 and 431-435, the editor sends rawinnerHTMLback to .NET, so markup like<p><br></p>still satisfies[Required]. Use a validator that checks rendered text/content facts or normalize empty HTML before binding.🤖 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/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs` around lines 333 - 336, The FormModel.Body field is being validated with [Required] on raw innerHTML, so visually empty editor content like <p><br></p> still passes. Update the binding path in BitRichTextEditorDemo and the FormModel validation flow to normalize the editor value before it reaches Body, or replace [Required] with a custom validator that checks for meaningful rendered text/content instead of HTML markup.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss-243-243 (1)
243-243: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winFix the quoted font-family names to satisfy Stylelint.
These two declarations currently violate
font-family-name-quotesand will keep the stylesheet linting red.Suggested change
- font-family: "SFMono-Regular", Consolas, monospace; + font-family: SFMono-Regular, Consolas, monospace; ... - font-family: "SFMono-Regular", Consolas, monospace; + font-family: SFMono-Regular, Consolas, monospace;Also applies to: 312-312
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss` at line 243, Update the font-family declarations in RichTextEditor.scss to satisfy Stylelint’s font-family-name-quotes rule by removing quotes from the font names in the affected RichTextEditor styles. Make the same adjustment at both occurrences of the monospace stack in the SCSS so the stylesheet passes linting consistently.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cs-19-20 (1)
19-20: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDefault
Blockto"p"instead of an empty string.The block-format dropdown binds straight to
_state.Block, and the current options do not include"". That leaves the toolbar blank until JS sends a selection state, even though the editor's default block is effectively a paragraph.Suggested change
- public string Block { get; set; } = ""; + public string Block { get; set; } = "p";🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cs` around lines 19 - 20, The RichTextEditor selection state is initializing Block to an empty string, which leaves the block-format dropdown without a matching option until JavaScript updates it. Update the default value in BitRichTextEditorSelectionState.Block so it starts as "p", matching the editor’s default paragraph block and the options bound from _state.Block.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cs-24-31 (1)
24-31: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winBlock slash actions in read-only mode.
This path can still open the slash menu and mutate content after the component becomes read-only. The other insertion flows already guard
ReadOnly, so slash commands are the remaining write bypass.Proposed fix
[JSInvokable("OnSlashTrigger")] public void _OnSlashTrigger() { + if (ReadOnly) return; _slashFilter = ""; _showSlash = true; StateHasChanged(); } @@ private async Task ApplySlashAsync(string command) { + if (ReadOnly) + { + CloseSlash(); + return; + } _showSlash = false; _slashFilter = ""; await _js.BitRichTextEditorApplySlashCommand(_editorRef, command); }Also applies to: 46-50
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cs` around lines 24 - 31, The slash trigger handler in BitRichTextEditor.Slash (_OnSlashTrigger) still opens the menu even when the editor is read-only, creating a write bypass. Add the same ReadOnly guard used by the other insertion paths before changing _slashFilter, _showSlash, or calling StateHasChanged, and apply the same protection to the related slash-action flow referenced in the comment so slash commands are fully blocked in read-only mode.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs-19-23 (1)
19-23: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winMerge case-insensitive attribute keys before
ToDictionary().Lowercasing the key here means a policy that contains both
"A"and"a"will throw during setup instead of producing a deterministic allowlist. Since this is a public configuration surface, normalize with a case-insensitive comparer or merge duplicates before building the payload.Proposed fix
allowedAttributes = SanitizationPolicy.AllowedAttributes - .ToDictionary( - kv => kv.Key.ToLowerInvariant(), - kv => kv.Value.Select(a => a.ToLowerInvariant()).ToArray()), + .GroupBy(kv => kv.Key, StringComparer.OrdinalIgnoreCase) + .ToDictionary( + g => g.Key.ToLowerInvariant(), + g => g.SelectMany(kv => kv.Value) + .Select(a => a.ToLowerInvariant()) + .Distinct() + .ToArray()),🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs` around lines 19 - 23, The allowedAttributes mapping in BitRichTextEditor sanitization currently lowercases keys before ToDictionary, which can throw if SanitizationPolicy.AllowedAttributes contains duplicate keys that differ only by case. Update the normalization step in the sanitization setup to use a case-insensitive merge/comparer or otherwise coalesce duplicate attribute names before building the allowlist, so the payload is deterministic and does not fail during initialization.
🧹 Nitpick comments (1)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs (1)
12-20: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winAdd coverage for the sanitization interop path.
This rewrite moved XSS filtering behind the new bridge, but the suite never exercises
BitBlazorUI.RichTextEditor.sanitizeHtmlor a non-nullSanitizationPolicy. A broken JS identifier or allowlist payload would still pass here.🤖 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/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs` around lines 12 - 20, The RichTextEditor tests only cover the existing JS interop calls and miss the sanitization bridge path. Update BitRichTextEditorTests to exercise BitBlazorUI.RichTextEditor.sanitizeHtml by configuring a non-null SanitizationPolicy and asserting the sanitization interop is invoked as part of the editor flow. Use the existing JSInterop setup in the test class to add coverage for the bridge identifier and verify the allowlist/payload is passed through correctly so a broken identifier or malformed policy can’t slip through.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cs`:
- Around line 20-25: The cached FieldIdentifier in EnsureField() is only
initialized once, so it can become stale when ValueExpression changes. Update
RichTextEditor’s field-tracking logic in EnsureField() to detect binding changes
and recompute _fieldIdentifier whenever the current ValueExpression differs from
the one previously cached, so NotifyFieldChanged() always uses the active bound
field.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cs`:
- Around line 61-69: Reject protocol-relative URLs in IsAcceptableLinkUrl by
narrowing the current slash check so only true site-relative paths are allowed;
the existing StartsWith('/') branch also accepts //example.com, which should be
treated as external. Update the link allowlist in BitRichTextEditor.Links.cs to
distinguish a single leading slash from a double-slash URL, while keeping the
explicit http(s), mailto, tel, and hash cases intact.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs`:
- Around line 41-52: Apply the same ReadOnly protection used by ExecAsync and
the other formatting handlers to ApplyImageUrlAsync in BitRichTextEditor.Media,
so image insertion is blocked when the editor is read-only. Before calling
_js.BitRichTextEditorInsertImageUrl, check ReadOnly and return early (optionally
raising the same no-edit error pattern used elsewhere), and keep the dialog
state reset only when insertion is actually allowed.
- Around line 80-83: The upload failure handler in RichTextEditor.Media is
leaking raw exception details into the UI via RaiseErrorAsync in the
OnImageUpload catch block. Update the catch path in the image upload flow to
send a generic user-facing message for upload-failed instead of ex.Message, and
keep the full exception details only in logging/telemetry so
BitRichTextEditorError and RaiseErrorAsync do not expose infrastructure or auth
information.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 206-334: The toolbar button class/style hook is only applied in
HistoryGroup, leaving the other button groups inconsistent. Update the button
markup in the RichTextEditor toolbar fragments (such as InlineGroup, ColorGroup,
ListsGroup, AlignmentGroup, and the other group render fragments) to use
`@Classes`?.Button and `@Styles`?.Button on each bit-rte-btn so the public styling
contract is applied uniformly across all toolbar buttons.
- Around line 21-125: The new form controls in BitRichTextEditor.razor rely on
placeholders only, so they are missing accessible names. Add explicit labels or
aria-label/aria-labelledby for the URL inputs, find/replace fields, emoji
search, slash filter, and the source-view textarea so screen readers can
identify them. Update the inputs in the _showLinkInput, _showImageInput,
_showMediaInput, _showFind, _showEmoji, _showSlash, and _inSourceView sections
without changing their current behavior.
- Around line 13-18: The rich text editor toolbar still hard-codes English
labels and tooltips instead of using the new localizer, so route all user-facing
toolbar strings in BitRichTextEditor.razor through IBitRichTextEditorLocalizer.
Update the toolbar container label and the text/tooltip values used by
RenderGroup, OrderedToolbarIds, and the button/menu rendering paths so items
like Undo, Paragraph format, Heading 1, and Full screen come from the localizer
rather than literals. Verify the main toolbar surface and all related
label/tooltip helpers in the BitRichTextEditor component use the localizer
consistently.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 246-249: The toolbar roving setup in BitRichTextEditor is only
performed on the first-render path, so when ShowToolbar changes from false to
true later it never gets initialized. Update the component logic around the
toolbar initialization flow in BitRichTextEditor.razor.cs so that
BitRichTextEditorEnableToolbarRoving is also invoked when ShowToolbar
transitions to true after render, using the existing _toolbarRef and the
relevant lifecycle/update method in BitRichTextEditor.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs`:
- Around line 25-30: The keyboard bridge is ignoring the handled/unhandled
result from BitRichTextEditor._OnShortcut, so shortcuts beyond b/i/u still fall
through to the browser default. Update the JS side in BitRichTextEditor.ts to
await the OnShortcut JSInvokable call and, when it returns true, call
preventDefault() (and stop further processing) for all mapped combos including
ctrl+z, ctrl+y, and any custom shortcut keys.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 38-39: The source-view save path in RichTextEditor currently
updates the value and fires OnChange but skips EditContext notification, so it
won’t behave like the normal edit flow. Update the source-view handler that
calls AssignValue and OnChange to also invoke NotifyEditContextChanged after the
bound value is assigned, matching the existing edit path behavior so EditForm
tracking and validation run correctly.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cs`:
- Around line 47-50: The YouTube embed path in BuildMediaEmbed/TryGetYouTubeId
is inserting an unescaped video id into iframe HTML, creating an XSS risk.
Validate the id extracted from GetQueryValue/TryGetYouTubeId against the
expected YouTube id format before using it, and HTML-escape or otherwise safely
encode it when building the iframe in BuildMediaEmbed. Apply the same fix to the
other embed branch referenced by the comment so no user-controlled value is
concatenated into HTML attributes unsafely.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 156-176: The URI allowlist from
BitRichTextEditorSanitizationPolicy is not being applied in the link/image
flows, so custom allowedUriSchemes and allowDataImageUris have no effect. Update
the URL handling in BitRichTextEditor’s createLink, updateLink, and
insertImageUrl paths to validate against the active sanitization policy before
writing href/src or dispatching createLink/insertImage, and reuse the existing
URI sanitization helper(s) so only allowed schemes/data URIs are accepted.
- Around line 724-731: The MaxLength enforcement in BitRichTextEditor’s
insert/edit path currently treats every change as additive, so replacing an
existing selection is blocked or over-truncated at the limit. Update the logic
around the max check in the editor insertion flow to account for the currently
selected range size (and any content being replaced) before deciding whether to
return or slice the input, so in-place edits at max length are allowed when the
net length does not increase. Apply the same adjustment in the other affected
insert path referenced by the review so both branches use the selection-aware
length calculation consistently.
- Around line 261-301: The RichTextEditor.find/clearFind flow is inserting
transient <mark class="bit-rte-find"> nodes into the live editable DOM, which
can leak into editor.innerHTML and Value. Update the RichTextEditor search
highlighting so it is only temporary: before any content snapshot or persistence
path (especially afterChange and any toolbar command that reads innerHTML),
ensure clearFind(editor) runs, and keep the find state isolated so the editable
content itself is restored before saving. Use the existing clearFind, find, and
afterChange hooks to contain the search markup.
- Around line 108-126: Sanitize inbound HTML before it reaches the DOM in
BitRichTextEditor.setHtml. The current editor assignment path writes the
provided Value/html directly to innerHTML, so update the RichTextEditor flow to
apply BitRichTextEditorSanitizeHtml (or an equivalent safe default) before any
innerHTML or insertHTML call, especially when SanitizationPolicy is null. Make
sure the fix is applied in the setHtml method and the BitRichTextEditor.razor.cs
ValueChanged/default policy path so all entry points use the same secure HTML
handling.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs`:
- Around line 23-52: The shared Default policy in
BitRichTextEditorSanitizationPolicy is mutable, so any consumer modifying its
sets or dictionaries can unintentionally change sanitization for all later
editors. Update the Default property to return a fresh policy instance or switch
the allowlists in BitRichTextEditorSanitizationPolicy to immutable/read-only
collections so callers cannot mutate the process-wide default.
- Around line 48-50: Remove "data" from the generic AllowedUriSchemes set in
BitRichTextEditorSanitizationPolicy so the default href/src scheme allowlist
only covers non-data schemes. Keep data URI handling behind the existing
AllowDataImageUris image-specific switch, and update the policy initialization
so data: URLs are only permitted where image sanitization explicitly allows
them.
---
Minor comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs`:
- Around line 19-23: The allowedAttributes mapping in BitRichTextEditor
sanitization currently lowercases keys before ToDictionary, which can throw if
SanitizationPolicy.AllowedAttributes contains duplicate keys that differ only by
case. Update the normalization step in the sanitization setup to use a
case-insensitive merge/comparer or otherwise coalesce duplicate attribute names
before building the allowlist, so the payload is deterministic and does not fail
during initialization.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss`:
- Line 243: Update the font-family declarations in RichTextEditor.scss to
satisfy Stylelint’s font-family-name-quotes rule by removing quotes from the
font names in the affected RichTextEditor styles. Make the same adjustment at
both occurrences of the monospace stack in the SCSS so the stylesheet passes
linting consistently.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cs`:
- Around line 24-31: The slash trigger handler in BitRichTextEditor.Slash
(_OnSlashTrigger) still opens the menu even when the editor is read-only,
creating a write bypass. Add the same ReadOnly guard used by the other insertion
paths before changing _slashFilter, _showSlash, or calling StateHasChanged, and
apply the same protection to the related slash-action flow referenced in the
comment so slash commands are fully blocked in read-only mode.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cs`:
- Around line 19-20: The RichTextEditor selection state is initializing Block to
an empty string, which leaves the block-format dropdown without a matching
option until JavaScript updates it. Update the default value in
BitRichTextEditorSelectionState.Block so it starts as "p", matching the editor’s
default paragraph block and the options bound from _state.Block.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs`:
- Around line 333-336: The FormModel.Body field is being validated with
[Required] on raw innerHTML, so visually empty editor content like <p><br></p>
still passes. Update the binding path in BitRichTextEditorDemo and the FormModel
validation flow to normalize the editor value before it reaches Body, or replace
[Required] with a custom validator that checks for meaningful rendered
text/content instead of HTML markup.
---
Nitpick comments:
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs`:
- Around line 12-20: The RichTextEditor tests only cover the existing JS interop
calls and miss the sanitization bridge path. Update BitRichTextEditorTests to
exercise BitBlazorUI.RichTextEditor.sanitizeHtml by configuring a non-null
SanitizationPolicy and asserting the sanitization interop is invoked as part of
the editor flow. Use the existing JSInterop setup in the test class to add
coverage for the bridge identifier and verify the allowlist/payload is passed
through correctly so a broken identifier or malformed policy can’t slip through.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: afc9b637-5a12-4633-9a3f-974f7c3974e5
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
|
@coderabbitai re-review |
|
✅ Action performedReview finished.
|
There was a problem hiding this comment.
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
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 123-125: The URI checks in RichTextEditor.isAllowedUri and the
sanitization flow in RichTextEditor.sanitize are too permissive for obfuscated
schemes and do not consistently protect pasted/source/setHtml HTML. Normalize
the candidate URI before scheme validation so whitespace/control-obfuscated
values like java\nscript: are treated as unsafe, and reuse the same validator
inside sanitize() so all inbound HTML paths (including paste, source import, and
setHtml) are enforced by the active policy rather than only the command
handlers. Ensure the shared logic is applied consistently across the affected
RichTextEditor methods.
- Around line 798-804: The shortcut handling in BitRichTextEditor is still
awaiting OnShortcut before deciding to cancel, which lets browser defaults win
for custom combos. Update the key handling around the
editor._dotNetRef.invokeMethodAsync flow so owned shortcuts are identified and
prevented synchronously in JS before any await, using the existing key handling
logic in BitRichTextEditor and the shortcut path that currently checks ['b',
'i', 'u', 'z', 'y']. Keep the .NET callback for custom handling, but do not rely
on its returned handled flag to stop native behavior for overlapping shortcuts.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor`:
- Around line 77-78: The demo is rendering editor-controlled content through
MarkupString, which bypasses Blazor’s HTML encoding. Update
BitRichTextEditorDemo and the rendered output block to show the bound HTML as
plain text instead of injecting it into the DOM, or only render it after it has
passed through the trusted sanitization path used by the editor workflow. Keep
the bindingHtml display intact, but remove the direct MarkupString-based
rendering so the sample code does not encourage unsafe usage.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b80d2455-482a-46ef-a7d3-535245069a24
📒 Files selected for processing (16)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
🚧 Files skipped from review as they are similar to previous changes (13)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs
- src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs
- src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 14
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cs (1)
17-36: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winDon’t cache
FieldIdentifieronly byValueExpressionreference.
FieldIdentifier.Create(...)captures the current model behind the expression. Line 32 only invalidates the cache when theExpressionobject changes, so a parent that reuses the sameValueExpressioninstance while swapping theEditFormmodel can still notify the old field. That leaves validation attached to the wrong model. The safest fix is to rebuild theFieldIdentifiereach timeEnsureField()runs, or include the currentEditContext/model identity in the cache key.Minimal fix
private FieldIdentifier _fieldIdentifier; private bool _hasField; - private Expression<Func<string?>>? _cachedValueExpression; private void EnsureField() { if (ValueExpression is null) { _hasField = false; - _cachedValueExpression = null; return; } - // Recompute whenever the bound expression changes so a rebinding never leaves us - // notifying a stale field. - if (_hasField is false || _cachedValueExpression != ValueExpression) - { - _fieldIdentifier = FieldIdentifier.Create(ValueExpression); - _cachedValueExpression = ValueExpression; - _hasField = true; - } + _fieldIdentifier = FieldIdentifier.Create(ValueExpression); + _hasField = true; }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cs` around lines 17 - 36, The caching in EnsureField() is too narrow because FieldIdentifier.Create(ValueExpression) can still point to an old model even when the same ValueExpression instance is reused. Update BitRichTextEditor.Forms so EnsureField() rebuilds the FieldIdentifier every time it runs, or expand the cache invalidation in EnsureField() to also consider the current EditContext/model identity instead of only _cachedValueExpression.
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cs (1)
11-38: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winLocalize the emoji catalog instead of hard-coding English search terms.
The picker’s labels and searchable keywords are fixed English strings, so localized hosts still surface and search this menu in English only. Consider separating invariant emoji ids from localized display/search text, or make the catalog injectable through the same localization path as the rest of the editor.
Also applies to: 46-53
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cs` around lines 11 - 38, The Emoji catalog in BitRichTextEditor.Emoji is hard-coded with English labels and keywords, so localized editors still show English-only labels and search terms. Update the static EmojiEntry list to use localized display/search text or route it through the same localization/injection mechanism used by the rest of the editor, keeping the invariant emoji identifiers separate from user-facing strings.src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs (1)
83-95: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winTighten the toolbar filtering assertion.
This test should fail if
Toolbar=Inlinerenders extra groups. Assert the exact inline button count instead of>= 4.Proposed fix
- Assert.IsTrue(component.FindAll(".bit-rte-tlb .bit-rte-btn").Count >= 4); + Assert.AreEqual(4, component.FindAll(".bit-rte-tlb .bit-rte-btn").Count);🤖 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/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs` around lines 83 - 95, The BitRichTextEditorShouldRenderToolbarGroups test is too permissive because it uses a minimum count check, so extra toolbar groups could still pass. In BitRichTextEditorShouldRenderToolbarGroups, tighten the assertion on component.FindAll(".bit-rte-tlb .bit-rte-btn") to verify the exact Inline toolbar button count for BitRichTextEditorToolbar.Inline, so the test fails if BitRichTextEditor renders any additional groups.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cs`:
- Around line 24-45: ApplyLinkAsync in BitRichTextEditor.Links should respect
the editor’s ReadOnly state before mutating the document. Add the same ReadOnly
guard used by the other command helpers and RemoveLinkAsync, so the method exits
early without calling BitRichTextEditorUpdateLink or BitRichTextEditorCreateLink
when the editor is read-only. Keep the existing validation flow intact, but
block the JS link update/create path and only close/reset the dialog when the
write is allowed.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 119-124: The editable surface in BitRichTextEditor is missing an
accessible textbox name and role; update the contenteditable div in the editor
markup to expose it as a textbox with multiline semantics and a clear accessible
name. Add role="textbox" and aria-multiline="true", and provide either
aria-label or aria-labelledby on the same element so assistive technologies can
identify the editor properly while keeping the existing ReadOnly and
_inSourceView behavior unchanged.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 233-251: The first-render flow in
BitRichTextEditor.OnAfterRenderAsync is writing the initial Value directly into
the editor before sanitization is applied, so unsafe HTML can bypass
SanitizationPolicy. Update the first-render path (including the later update
path referenced in the comment) to sanitize _currentHtml/Value using the same
policy logic used by OnValueSet before calling BitRichTextEditorSetHtml, and
keep the behavior consistent with _initialized so the editor never receives
unsanitized initial content.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs`:
- Around line 43-47: BuildOwnedShortcutCombos() is advertising custom shortcut
keys that _OnShortcut() and IsKnownCommand() may later reject as unknown, so
only include shortcuts whose command can actually be executed. Update the
shortcut-building logic in BitRichTextEditor.Shortcuts to filter custom key
entries against the known command set (the same check used in _OnShortcut), so
the JS bridge only suppresses browser defaults for combos the editor truly
handles.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 43-49: LooksLikeValidHtml in BitRichTextEditor.SourceView is only
counting angle brackets, so malformed or misnested markup can still pass and be
committed. Replace that heuristic with a real HTML parse/validation step in the
source-view exit path, using the bridge logic that decides whether to leave
source view, so invalid HTML is rejected before committing user input.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cs`:
- Around line 53-57: The YouTube and Vimeo host validation in the RichTextEditor
embed parsing is too permissive because substring matching can accept spoofed
hosts like youtube.com.evil.test. Update the host checks in the embed-handling
logic (the YouTube/Vimeo branches in BitRichTextEditor.Structured) to use exact
host comparison or a proper subdomain-suffix match against the parsed Uri.Host,
so only legitimate youtube.com, youtu.be, and vimeo.com hosts are accepted
before generating iframe embeds.
- Around line 18-39: ApplyMediaAsync in BitRichTextEditor.Structured should
respect the editor’s ReadOnly state before mutating content. Add the same
read-only guard used by other insert/update paths near the start of
ApplyMediaAsync, before building or inserting the embed, and return early
without calling _js.BitRichTextEditorInsertMedia when the editor is read-only.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cs`:
- Around line 89-98: The InvokeCustomItemAsync catch block is surfacing the raw
exception message through RaiseErrorAsync, which can leak host callback
internals to the UI. Update the BitRichTextEditorToolbarItem activation error
handling to pass a generic user-facing BitRichTextEditorError message instead of
ex.Message, and keep the caught exception only for logging/telemetry outside the
inline UI path.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 220-223: The insertMedia method in RichTextEditor is inserting the
provided HTML directly via insertHTML without sanitization. Update insertMedia
to route media content through the existing safe media-building path or apply a
media-specific allowlist/sanitizer before dispatching the insertMedia action, so
only approved markup reaches RichTextEditor.dispatch and afterChange.
- Around line 967-1001: The sanitize method in BitRichTextEditor currently only
removes a small denylist when editor._policy is absent, so it does not enforce
the documented secure default allowlist. Update sanitize to start from an
explicit built-in allowlist of permitted tags, attributes, and URI schemes, then
merge or override with the custom policy from editor._policy; ensure non-URI
attributes like form/action-related fields are blocked unless explicitly
allowed, while keeping the existing isAllowedUri checks and attribute filtering
behavior in place.
- Around line 606-617: The mergeSelectedCells method currently merges all
intersecting cells into the first cell by only increasing colspan, which breaks
multi-row selections and can create malformed tables. Update the logic in
mergeSelectedCells to compute the selected rectangle across rows and columns,
then set both rowspan and colspan on the top-left cell and remove or normalize
the other cells in the merged area. Use the existing table/cell selection
handling in BitRichTextEditor.ts to locate the fix and keep the merge behavior
correct for 2×2 and larger selections.
- Around line 703-710: The image handling in RichTextEditor.handleImageFiles
should fail per file instead of letting readAsDataUrl or ResolveImageUrl
rejections escape the whole paste/drop flow. Wrap the per-file upload/read logic
in a try/catch around the existing dataUrl,
editor._dotNetRef.invokeMethodAsync('ResolveImageUrl'), and insertImage path,
then route any failure through OnClientError (via the existing RichTextEditor
error dispatch pattern) and continue to the next file. Keep the fix localized to
handleImageFiles and its use of readAsDataUrl/ResolveImageUrl so one bad file
does not abort the entire batch.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cs`:
- Around line 11-16: The ToggleFullScreen flow in BitRichTextEditor.View
currently updates _fullScreen before calling BitRichTextEditorSetFullScreen,
which can leave the component visually out of sync if the JS interop fails. Move
the _fullScreen state change to after the await on
_js.BitRichTextEditorSetFullScreen(_editorRef, _fullScreen) succeeds, and keep
ClassBuilder.Reset and StateHasChanged aligned with the confirmed state so the
fullscreen UI only updates when the browser action succeeds.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs`:
- Around line 23-55: The secure default in
BitRichTextEditorSanitizationPolicy.Default still allows arbitrary iframe embeds
via the "iframe" tag and its src-related attributes, which should not be part of
the baseline formatting allowlist. Remove iframe from the default AllowedTags
and drop the iframe entry from AllowedAttributes in Default, leaving iframe
support to be opt-in via custom policies while keeping the rest of the editor
sanitization defaults intact.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cs`:
- Around line 17-36: The caching in EnsureField() is too narrow because
FieldIdentifier.Create(ValueExpression) can still point to an old model even
when the same ValueExpression instance is reused. Update BitRichTextEditor.Forms
so EnsureField() rebuilds the FieldIdentifier every time it runs, or expand the
cache invalidation in EnsureField() to also consider the current
EditContext/model identity instead of only _cachedValueExpression.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cs`:
- Around line 11-38: The Emoji catalog in BitRichTextEditor.Emoji is hard-coded
with English labels and keywords, so localized editors still show English-only
labels and search terms. Update the static EmojiEntry list to use localized
display/search text or route it through the same localization/injection
mechanism used by the rest of the editor, keeping the invariant emoji
identifiers separate from user-facing strings.
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs`:
- Around line 83-95: The BitRichTextEditorShouldRenderToolbarGroups test is too
permissive because it uses a minimum count check, so extra toolbar groups could
still pass. In BitRichTextEditorShouldRenderToolbarGroups, tighten the assertion
on component.FindAll(".bit-rte-tlb .bit-rte-btn") to verify the exact Inline
toolbar button count for BitRichTextEditorToolbar.Inline, so the test fails if
BitRichTextEditor renders any additional groups.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b09ac936-2f59-49b9-b400-f4a7070c8758
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 11
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs (1)
236-250: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winSanitize the initial
Valuebefore the firstSetHtml.
OnValueSet()sanitizes external HTML, but the first-render path writesValuestraight into the editor. That bypassesSanitizationPolicyfor the initial load.Patch idea
await _js.BitRichTextEditorSetup(_editorRef, _dotnetObj, new() { Debounce = DebounceMs, Policy = BuildPolicyPayload(), HasUpload = OnImageUpload is not null, PlainTextPaste = PasteAsPlainText, MaxLength = MaxLength, ShortcutKeys = BuildOwnedShortcutCombos() }); + if (SanitizationPolicy is not null && string.IsNullOrEmpty(_currentHtml) is false) + { + _currentHtml = await _js.BitRichTextEditorSanitizeHtml(_editorRef, _currentHtml); + } + if (string.IsNullOrEmpty(_currentHtml) is false) { await _js.BitRichTextEditorSetHtml(_editorRef, _currentHtml); }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs` around lines 236 - 250, The initial editor load in BitRichTextEditor bypasses SanitizationPolicy because _currentHtml is assigned directly from Value before the first BitRichTextEditorSetHtml call. Update the BitRichTextEditor.razor.cs initialization path so the same sanitization used by OnValueSet is applied to the initial Value before setting _currentHtml and passing it to _js.BitRichTextEditorSetHtml, keeping the setup flow in sync with the existing policy handling in BitRichTextEditorSetup.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts (1)
478-489: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReturn the fullscreen promise before flipping C# state.
requestFullscreen().catch(...)is not returned, so the interop call resolves before the browser accepts/rejects fullscreen.ToggleFullScreen()can still set_fullScreen = trueafter a denied request.🐛 Proposed fix direction
public static setFullScreen(editor: any, on: boolean) { @@ if (on) { if (root.requestFullscreen) { - root.requestFullscreen().catch(() => { + return root.requestFullscreen().catch(() => { if (editor._dotNetRef) editor._dotNetRef.invokeMethodAsync('OnClientError', 'fullscreen-denied', 'Full-screen mode was blocked by the browser.'); + throw new Error('fullscreen-denied'); }); } } else if (document.fullscreenElement) { - document.exitFullscreen?.(); + return document.exitFullscreen?.(); }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts` around lines 478 - 489, The setFullScreen flow in BitRichTextEditor currently fires requestFullscreen().catch(...) without returning it, so the interop completes before fullscreen is actually accepted or denied. Update the setFullScreen method to return the fullscreen promise from the root.requestFullscreen path, and ensure the caller path in ToggleFullScreen waits on that promise before updating C# state like _fullScreen. Preserve the existing OnClientError handling in the catch branch so denial is still reported correctly.
🧹 Nitpick comments (3)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs (1)
145-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake this assertion prove the call came from the
Valueupdate.
VerifyInvoke("BitBlazorUI.RichTextEditor.sanitizeHtml")still passes if the bridge is only hit during the initial render. Capture the pre-update invocation count (or clear prior invocations) beforeSetParametersAndRender, then assert the count increases after theValuechange so the test covers the behavior its name describes.🤖 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/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs` around lines 145 - 163, The test for BitRichTextEditor sanitization is too weak because `VerifyInvoke("BitBlazorUI.RichTextEditor.sanitizeHtml")` can pass from an earlier render. In `BitRichTextEditorShouldInvokeSanitizeBridgeWhenPolicyIsSet`, capture the JSInterop invocation count or clear invocations after the initial `RenderComponent<BitRichTextEditor>` setup and before `SetParametersAndRender`, then assert the sanitize bridge is invoked again only after the `Value` parameter change so the test specifically proves the update path.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts (1)
1146-1148: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winMerge wildcard attributes with tag-specific attributes.
policy.allowedAttributes[tag] || policy.allowedAttributes['*']means global attributes likeclass,style, anddirare dropped from tags that define their own attributes, such asaandimg.♻️ Proposed fix
if (policy && policy.allowedAttributes) { - const allowed = policy.allowedAttributes[tag] || policy.allowedAttributes['*'] || []; + const allowed = [ + ...(policy.allowedAttributes['*'] || []), + ...(policy.allowedAttributes[tag] || []) + ]; if (!allowed.includes(name)) el.removeAttribute(attr.name); }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts` around lines 1146 - 1148, The attribute allowlist logic in BitRichTextEditor is incorrectly choosing either tag-specific attributes or wildcard attributes, which drops global attributes for tags like a and img. Update the sanitization path around the allowedAttributes check to merge policy.allowedAttributes[tag] with policy.allowedAttributes['*'] in the attribute filtering logic, so both sets are honored before removing el.removeAttribute(attr.name).src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cs (1)
8-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider exposing built-in toolbar ids as constants.
Orderis intentionally stringly typed and unknown ids are skipped, so a typo in"blockformat"or"fullscreen"silently changes the rendered toolbar. Publishing the built-in ids from code would make this API much harder to misuse.🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cs` around lines 8 - 18, Expose the built-in toolbar entry ids as named constants or a shared readonly list alongside BitRichTextEditorToolbarConfig so callers can reference them instead of hardcoding strings in Order; update the config surface to publish the existing built-in ids (history, blockformat, font, inline, color, script, lists, indent, blocks, link, media, image, table, rule, alignment, direction, emoji, find, source, fullscreen, clear) and keep Order accepting those symbols to reduce typo-prone string usage.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cs`:
- Around line 47-58: Apply the same 1000-character validation used by
RunFindAsync to the replace paths in BitRichTextEditor.Find.cs. Update
ReplaceCurrentAsync and ReplaceAllAsync so they reject oversized _findTerm
values before calling _js.BitRichTextEditorReplaceCurrent or
_js.BitRichTextEditorReplaceAll, using the same guard behavior as the find flow.
Keep the fix localized to the replace methods so all search/replace entry points
enforce the same term-length limit.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 100-110: Move the slash filter textbox out of the element with
role="listbox" in BitRichTextEditor.razor so the listbox contains only the slash
command options rendered by FilteredSlash() and the bit-rte-slash-item buttons.
Keep the filtering input separate from the options container, while preserving
its current bindings and Escape handling in the _showSlash block. This will keep
the accessibility tree valid and avoid nesting non-option content inside the
listbox.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 238-246: The first-render setup in BitRichTextEditor.razor.cs
freezes bridge options by passing Debounce, Policy, HasUpload, PlainTextPaste,
MaxLength, and ShortcutKeys only through BitRichTextEditorSetup, so later
parameter changes never reach the JS bridge. Update the RichTextEditor
initialization flow (around the BitRichTextEditorSetup call and related
setup/state methods) so these options are refreshed whenever their corresponding
component parameters change, not only on first render. Use the existing symbols
BuildPolicyPayload, BuildOwnedShortcutCombos, and BitRichTextEditorSetup to
locate the setup path and ensure the JS config stays aligned with the current C#
state.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs`:
- Around line 20-27: The sanitization payload builder is dropping wildcard
attributes because `BitRichTextEditor.Sanitization.cs` only emits per-tag
entries from `SanitizationPolicy.AllowedAttributes`, so the JS sanitizer’s
`allowedAttributes[tag] || allowedAttributes['*']` fallback never gets the
shared `"*"` values when a specific tag exists. Update the payload construction
in the sanitization mapping logic to preserve and merge the `"*"` attributes
into each tag-specific entry (or otherwise emit `"*"` separately without being
shadowed), using the existing `SanitizationPolicy.AllowedAttributes` and the
builder that produces the `allowedAttributes` dictionary.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss`:
- Around line 212-237: The editor surfaces in BitRichTextEditor.scss suppress
focus outlines on .bit-rte-src and .bit-rte-edt without providing an accessible
replacement. Update these selectors to restore a visible keyboard focus state,
preferably using :focus-visible on both the source textarea and the editable
surface, and keep the styling consistent with the existing editor theme.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs`:
- Around line 34-39: The shortcut lookup in BitRichTextEditor.Shortcuts uses the
raw combo string from BuildComboKey, but custom shortcuts are normalized to
lowercase in BuildOwnedShortcutCombos, so case-variant keys can be advertised
yet never match. Update the lookup in the shortcut handling path to normalize
the generated combo the same way before probing KeyboardShortcuts and
DefaultShortcuts, keeping the matching behavior consistent with
BuildOwnedShortcutCombos and the related shortcut methods in BitRichTextEditor.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cs`:
- Around line 12-22: The slash menu item labels in BitRichTextEditor.Slash.cs
are hardcoded and bypass the existing localization path used by the component.
Update the SlashCommands definitions so each display label is passed through the
same Label(...) localization mechanism used in BitRichTextEditor.razor, and keep
the command values unchanged; use the SlashCommands array as the main place to
align these menu entries with the localized placeholder and empty state.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 847-854: The image insertion flow in RichTextEditor currently
skips URI policy checks for both the raw data URL and the URL returned by
ResolveImageUrl. Update the upload/paste/drop path around the
dataUrl/ResolveImageUrl handling to validate the final URL with the existing
isAllowedUri logic before calling dispatch with insertImage, and reject or skip
insertion when the policy disallows data URIs or the resolved scheme. Keep the
fix localized to the RichTextEditor upload insertion code so the existing
allowlist behavior is enforced consistently.
- Around line 293-318: The media insertion flow in RichTextEditor is bypassing
the active sanitization policy because insertMedia() and sanitizeMedia() allow
iframe embeds even when DEFAULT_POLICY would reject them. Update
insertMedia()/sanitizeMedia() to first honor the current editor policy before
allowing media tags, so iframe/embed markup is only permitted when the active
policy allows it and won’t be stripped later by setHtml(). Keep the fix
localized to the RichTextEditor media sanitization path and reuse the existing
policy checks used elsewhere in the component.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cs`:
- Around line 19-20: The default value for BitRichTextEditorSelectionState.Block
is incorrect because it represents an active paragraph format instead of an
inactive/unknown state. Update the Block property in
BitRichTextEditorSelectionState so omitted JS data deserializes as no active
block, and keep the summary aligned with the inactive-by-default behavior.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scss`:
- Around line 6-7: The wrapping layout in the RichTextEditor demo styles is
being negated by the container’s max-width setting. Update the styling in
BitRichTextEditorDemo.razor.scss for the flex container that uses flex-flow so
it can shrink on narrow viewports by removing max-width: max-content or
replacing it with a width-constrained value, allowing the wrapped buttons to
flow instead of overflowing.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 236-250: The initial editor load in BitRichTextEditor bypasses
SanitizationPolicy because _currentHtml is assigned directly from Value before
the first BitRichTextEditorSetHtml call. Update the BitRichTextEditor.razor.cs
initialization path so the same sanitization used by OnValueSet is applied to
the initial Value before setting _currentHtml and passing it to
_js.BitRichTextEditorSetHtml, keeping the setup flow in sync with the existing
policy handling in BitRichTextEditorSetup.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 478-489: The setFullScreen flow in BitRichTextEditor currently
fires requestFullscreen().catch(...) without returning it, so the interop
completes before fullscreen is actually accepted or denied. Update the
setFullScreen method to return the fullscreen promise from the
root.requestFullscreen path, and ensure the caller path in ToggleFullScreen
waits on that promise before updating C# state like _fullScreen. Preserve the
existing OnClientError handling in the catch branch so denial is still reported
correctly.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 1146-1148: The attribute allowlist logic in BitRichTextEditor is
incorrectly choosing either tag-specific attributes or wildcard attributes,
which drops global attributes for tags like a and img. Update the sanitization
path around the allowedAttributes check to merge policy.allowedAttributes[tag]
with policy.allowedAttributes['*'] in the attribute filtering logic, so both
sets are honored before removing el.removeAttribute(attr.name).
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cs`:
- Around line 8-18: Expose the built-in toolbar entry ids as named constants or
a shared readonly list alongside BitRichTextEditorToolbarConfig so callers can
reference them instead of hardcoding strings in Order; update the config surface
to publish the existing built-in ids (history, blockformat, font, inline, color,
script, lists, indent, blocks, link, media, image, table, rule, alignment,
direction, emoji, find, source, fullscreen, clear) and keep Order accepting
those symbols to reduce typo-prone string usage.
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs`:
- Around line 145-163: The test for BitRichTextEditor sanitization is too weak
because `VerifyInvoke("BitBlazorUI.RichTextEditor.sanitizeHtml")` can pass from
an earlier render. In
`BitRichTextEditorShouldInvokeSanitizeBridgeWhenPolicyIsSet`, capture the
JSInterop invocation count or clear invocations after the initial
`RenderComponent<BitRichTextEditor>` setup and before `SetParametersAndRender`,
then assert the sanitize bridge is invoked again only after the `Value`
parameter change so the test specifically proves the update path.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1deeb3ae-2957-4eef-8c84-8575ab376c2b
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 12
♻️ Duplicate comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs (1)
90-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winKeep owned shortcuts aligned with custom overrides.
KeyboardShortcutswins in_OnShortcut, butBuildOwnedShortcutCombos()always seeds built-ins. If a consumer overridesctrl+bwith an unknown command,ctrl+bremains advertised as owned while_OnShortcutrejects it, so the bridge can suppress a shortcut the editor does not handle. This is a remaining edge case of the previously flagged shortcut-advertising issue.Proposed fix
private string[] BuildOwnedShortcutCombos() { - var combos = new HashSet<string>(DefaultShortcuts.Keys, StringComparer.OrdinalIgnoreCase); + var combos = new Dictionary<string, string>(DefaultShortcuts, StringComparer.OrdinalIgnoreCase); if (KeyboardShortcuts is not null) { // Only advertise custom combos whose command can actually be executed; otherwise the // JS bridge would suppress the browser default for a combo _OnShortcut later rejects. foreach (var (key, command) in KeyboardShortcuts) - if (IsKnownCommand(command)) - combos.Add(key); + { + if (IsKnownCommand(command)) + combos[key] = command; + else + combos.Remove(key); + } } - return combos.Select(c => c.ToLowerInvariant()).ToArray(); + return combos.Keys.Select(c => c.ToLowerInvariant()).ToArray(); }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs` around lines 90 - 100, `BuildOwnedShortcutCombos()` still seeds `DefaultShortcuts`, which leaves built-in combos advertised as owned even when `KeyboardShortcuts` overrides them with an unknown command. Update `BitRichTextEditor.Shortcuts` so owned shortcuts are computed from the effective shortcut map used by `_OnShortcut`, not from the defaults alone; when a custom override exists for a key, only advertise it if `IsKnownCommand(command)` returns true, otherwise omit the combo so the bridge does not suppress an unhandled browser shortcut.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor (1)
107-116: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winKeep non-option content out of the listbox.
The filter input was moved out, but the “No matching command” div is still inside
role="listbox". Render the empty state outside the listbox or only render the listbox when options exist.Proposed fix
- <div class="bit-rte-slash-list" role="listbox" aria-label="`@Label`("filter-commands", "Filter commands")"> - `@foreach` (var c in FilteredSlash()) - { - <button type="button" class="bit-rte-slash-item" role="option" - `@onmousedown`:preventDefault="true" `@onclick`="() => ApplySlashAsync(c.Command)">`@Label`(c.Key, c.Label)</button> - } - `@if` (FilteredSlash().Any() is false) - { - <div class="bit-rte-emoji-empty">`@Label`("no-command", "No matching command")</div> - } - </div> + `@if` (FilteredSlash().Any()) + { + <div class="bit-rte-slash-list" role="listbox" aria-label="`@Label`("commands", "Commands")"> + `@foreach` (var c in FilteredSlash()) + { + <button type="button" class="bit-rte-slash-item" role="option" + `@onmousedown`:preventDefault="true" `@onclick`="() => ApplySlashAsync(c.Command)">`@Label`(c.Key, c.Label)</button> + } + </div> + } + else + { + <div class="bit-rte-emoji-empty" role="status">`@Label`("no-command", "No matching command")</div> + }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor` around lines 107 - 116, The empty-state “No matching command” content is still being rendered inside the element with role="listbox" in BitRichTextEditor.razor, which leaves non-option content in the listbox; update the slash-command UI so only option items are inside the listbox, either by moving the empty state outside the listbox or by rendering the listbox only when FilteredSlash().Any() is true. Use the existing BitRichTextEditor and FilteredSlash() section to keep the listbox restricted to the button options.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs (1)
20-27: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winMerge wildcard attributes into tag-specific entries.
The builder still leaves
"*"attributes separate, so tag-specific entries can shadow shared attributes in the JS sanitizer path. This is the same wildcard-preservation issue previously flagged.Proposed fix
private object? BuildPolicyPayload() { if (SanitizationPolicy is null) return null; + + var wildcardAttributes = SanitizationPolicy.AllowedAttributes + .Where(kv => string.Equals(kv.Key, "*", StringComparison.OrdinalIgnoreCase)) + .SelectMany(kv => kv.Value) + .Select(a => a.ToLowerInvariant()) + .Distinct() + .ToArray(); + return new { allowedTags = SanitizationPolicy.AllowedTags.Select(t => t.ToLowerInvariant()).ToArray(), allowedAttributes = SanitizationPolicy.AllowedAttributes .GroupBy(kv => kv.Key.ToLowerInvariant()) .ToDictionary( g => g.Key, g => g.SelectMany(kv => kv.Value) .Select(a => a.ToLowerInvariant()) + .Concat(g.Key == "*" ? Array.Empty<string>() : wildcardAttributes) .Distinct() .ToArray()),🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs` around lines 20 - 27, The AllowedAttributes normalization in RichTextEditor sanitization still keeps the "*" entry separate, so update the builder around SanitizationPolicy.AllowedAttributes to merge wildcard attributes into every tag-specific entry instead of leaving them isolated. Preserve the shared attributes when building the dictionary in BitRichTextEditor.Sanitization, ensuring each tag entry includes both its own attributes and the wildcard set before the JS sanitizer consumes it.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cs`:
- Around line 10-11: The RichTextEditor `MaxLength` parameter currently accepts
negative values, so update the `BitRichTextEditor.Count`/`MaxLength` handling to
reject them before they reach the footer or bridge enforcement. Add validation
in the `MaxLength` property path (or the component’s parameter-setting logic if
that’s where other bounds are enforced) so only null or non-negative values are
allowed, and ensure invalid negatives are handled consistently with the rest of
the component’s parameter validation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cs`:
- Around line 12-21: The ToggleFind method currently discards the ClearFindAsync
call when closing the panel, which can leave stale highlight nodes and hide JS
interop failures. Update ToggleFind so the clear operation is awaited as part of
the close path, and preserve any exception handling needed around ClearFindAsync
to keep failures visible while resetting _showFind, _findTerm, _replaceTerm, and
_findCount.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs`:
- Around line 58-71: `IsAcceptableImageUrl` currently allows any `data:` URL and
`_ResolveImageUrl` embeds the raw client `contentType`, which can permit
non-image payloads. Update the `BitRichTextEditor.Media` logic to only
accept/emit `data:` URLs when `SanitizationPolicy.AllowDataImageUris` is enabled
and the MIME type is a known image type, and validate the fallback in
`_ResolveImageUrl` before constructing the inline data URL.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 94-98: The inline error display is currently nested under the
ShowToolbar block in BitRichTextEditor, so it is hidden when the toolbar is
disabled. Move the _inlineError alert rendering in BitRichTextEditor.razor
outside the toolbar-only section while keeping the same bit-rte-err alert markup
and role="alert" behavior, so errors still render for toolbar-less editor
configurations.
- Around line 132-137: The source-view textarea in BitRichTextEditor still
allows edits when ReadOnly is enabled, unlike the main contenteditable surface.
Update the _inSourceView rendering in BitRichTextEditor.razor so the source
<textarea> also respects ReadOnly, likely by binding the readonly/disabled state
alongside value="`@_sourceText`" and `@oninput`="OnSourceTextChanged". Make sure the
same ReadOnly state used by the editor surface is applied consistently in the
source editing path.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 25-27: The source-view validation path in
BitRichTextEditor.SourceView currently hardcodes the inline error text, which
bypasses localization. Update the invalid HTML branch in the
BitRichTextEditor.SourceView logic to use the existing Label(...) fallback path
for the error message before calling RaiseErrorAsync, so localized editors
display the translated text instead of the English literal.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cs`:
- Around line 9-11: The invalid-table validation in BitRichTextEditor.Tables
still uses a hardcoded English string instead of the localizer. Update the error
creation in the table row/column bounds check to use the existing localizer path
used elsewhere in BitRichTextEditor, so the "invalid-table" message is
translated consistently. Keep the same error key and wire the localized text
through RaiseErrorAsync and BitRichTextEditorError.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 271-275: Restore the saved editor range before running
selection-dependent actions in `updateLink`, `tableOp`, and `setBlockDirection`,
since they currently read `document.getSelection()` first and may act on the
toolbar/dialog selection instead of the editor. Use the existing `editor._range`
restoration logic in `BitRichTextEditor` before calling
`RichTextEditor.linkAtSelection`, `RichTextEditor.dispatch`, or any
direction/table commands so the editor selection is active when these commands
run.
- Around line 28-37: The default sanitizer in BitRichTextEditor currently allows
the global style attribute, which lets arbitrary inline CSS through pasted or
source HTML. Update the sanitizer allowlist in the BitRichTextEditor
configuration to remove style from the global allowedAttributes, or restrict it
to only the safe editor-generated properties/values if it must remain. Make the
same change in the other sanitizer configuration block referenced by the comment
so both paths use the same safe policy.
- Around line 359-362: The imperative insertion path in
RichTextEditor.insertText bypasses the same _maxLength enforcement used by
onBeforeInput and paste, so programmatic inserts can exceed the configured
limit. Update insertText (and any related insertion helpers in the
RichTextEditor flow) to check the current content length against _maxLength
before dispatching the insert, truncating or skipping the insertion as needed.
Reuse the existing length-counting logic already used for user input so
emoji/custom toolbar inserts are handled consistently. Also review the related
insertion path referenced by insertText to ensure all programmatic text entry
honors the same limit.
- Around line 17-37: The RichTextEditor sanitizer policy currently allows no
<font> tags, so font formatting created by fontName/fontSize is lost after
sanitization; update the generated markup in BitRichTextEditor to emit allowed
<span style="..."> wrappers instead of <font> elements. Make the change in the
editor’s font formatting handling paths (the places referenced by the comment,
including the font-related generation logic) so the output survives
DEFAULT_POLICY roundtrips without unwrapping or dropping styles.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cs`:
- Around line 11-20: The full-screen state in ToggleFullScreen is only updated
after the JS call, but external exits are not reflected back into the component,
so _fullScreen can stay stale. Add a JS-to-.NET callback for fullscreenchange in
the rich text editor bridge, and use it to clear _fullScreen and refresh the
class/state when the browser exits full screen via Escape or UI controls. Update
the relevant RichTextEditor view/interop symbols
(_js.BitRichTextEditorSetFullScreen, ToggleFullScreen, and the editor fullscreen
handling) so the component stays in sync with the actual browser state.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 107-116: The empty-state “No matching command” content is still
being rendered inside the element with role="listbox" in
BitRichTextEditor.razor, which leaves non-option content in the listbox; update
the slash-command UI so only option items are inside the listbox, either by
moving the empty state outside the listbox or by rendering the listbox only when
FilteredSlash().Any() is true. Use the existing BitRichTextEditor and
FilteredSlash() section to keep the listbox restricted to the button options.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cs`:
- Around line 20-27: The AllowedAttributes normalization in RichTextEditor
sanitization still keeps the "*" entry separate, so update the builder around
SanitizationPolicy.AllowedAttributes to merge wildcard attributes into every
tag-specific entry instead of leaving them isolated. Preserve the shared
attributes when building the dictionary in BitRichTextEditor.Sanitization,
ensuring each tag entry includes both its own attributes and the wildcard set
before the JS sanitizer consumes it.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs`:
- Around line 90-100: `BuildOwnedShortcutCombos()` still seeds
`DefaultShortcuts`, which leaves built-in combos advertised as owned even when
`KeyboardShortcuts` overrides them with an unknown command. Update
`BitRichTextEditor.Shortcuts` so owned shortcuts are computed from the effective
shortcut map used by `_OnShortcut`, not from the defaults alone; when a custom
override exists for a key, only advertise it if `IsKnownCommand(command)`
returns true, otherwise omit the combo so the bridge does not suppress an
unhandled browser shortcut.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7f4d9627-7c75-44c6-8be4-c0cc22162d26
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cs (1)
8-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExpose the built-in toolbar ids as code, not only XML docs.
Orderis a public stringly-typed contract, and the downstream ordering code silently drops unknown ids. That makes typos or future renames fail as “missing buttons” with no signal. Please publish stable constants (or a typed wrapper) for the built-in ids instead of requiring consumers to copy doc strings.🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cs` around lines 8 - 18, The public Order contract in BitRichTextEditorToolbarConfig is stringly typed and only documents the built-in toolbar ids in XML comments, so consumers have no safe way to reference them. Add stable public constants or a typed wrapper for the built-in ids on BitRichTextEditorToolbarConfig (or a related shared type) and expose them as the source of truth for ordering, so callers can use the same identifiers instead of copying names from the docs.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 229-250: OnValue-driven rerenders in BitRichTextEditor are causing
unnecessary BitRichTextEditorUpdateOptions JS calls even when bridge-backed
settings are unchanged. Update OnParametersSetAsync and BuildSetupOptions to
cache the last setup payload (or its relevant fields) and only invoke
_js.BitRichTextEditorUpdateOptions when DebounceMs, BuildPolicyPayload,
PasteAsPlainText, MaxLength, OnImageUpload, or BuildOwnedShortcutCombos actually
differ from the previous snapshot. Keep the existing _initialized gate and use
the BitRichTextEditorSetupOptions shape to compare and skip redundant updates.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss`:
- Around line 120-127: The auxiliary editor bars are locked to a single flex
row, causing the link/media/find controls to overflow on narrow widths or high
zoom. Update the .bit-rte-bar styles (and the other matching auxiliary bar rules
referenced by the same comment) so they can wrap instead of forcing one line,
while keeping spacing/alignment intact and preserving the existing bar structure
in BitRichTextEditor.scss.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 32-41: The exit path in BitRichTextEditor.SourceView currently
always writes back and raises notifications even when the sanitized source text
matches the existing HTML. In the source-view close flow, compare the sanitized
result against the pre-existing _currentHtml before calling
BitRichTextEditorSetHtml, AssignValue, NotifyEditContextChanged, and OnChange.
If there is no effective content change, skip the save/notify path and only exit
source view state. Keep the check localized around the existing
_inSourceView/_currentHtml update logic.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cs`:
- Around line 79-84: The custom toolbar button rendering in
BitRichTextEditor.Toolbar should not rely on item.AriaLabel alone for
accessibility. Update the attribute values in the button-building logic to use a
fallback chain like item.AriaLabel ?? item.Label ?? item.Id so icon-only items
still get a usable name, and keep the same fallback consistent across the title
and aria-label attributes in the toolbar item rendering path.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 546-551: The fullscreen request path in BitRichTextEditor’s
ToggleFullScreen/requestFullscreen handling is swallowing failures by resolving
the promise after catch, which makes the C# interop think fullscreen succeeded;
update the promise flow so a denied request still rejects or otherwise signals
failure to the caller, while keeping OnClientError reporting in place, and make
the change in the requestFullscreen branch tied to editor._dotNetRef and
ToggleFullScreen.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cs`:
- Around line 6-19: Add fail-fast validation for blank Id and AriaLabel instead
of relying on required on BitRichTextEditorToolbarItem. Update the normalization
path in ToolbarConfig.CustomItems to reject null/empty/whitespace values for
these fields before items are used for ordering, lookup, title, or aria-label,
and make the guard explicit where custom toolbar items are prepared.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs`:
- Around line 386-390: The FormModel validation currently applies MinLength to
the raw HTML from BitRichTextEditor, so markup can satisfy the rule without
enough visible text. Update FormModel.Body validation to check the plain-text
content instead of the HTML payload by stripping tags before enforcing length,
or remove the minimum-length constraint from this demo. Use the FormModel and
Body property to locate the change.
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs`:
- Around line 157-168: The RichTextEditor test assumes the sanitize bridge entry
already exists, which can fail on initial renders with empty values. Update the
test in BitRichTextEditorTests to read the pre-update invocation count for
BitBlazorUI.RichTextEditor.sanitizeHtml using a safe lookup instead of indexing
directly, then keep the SetParametersAndRender update-path assertion by
comparing the count before and after the Value change.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cs`:
- Around line 8-18: The public Order contract in BitRichTextEditorToolbarConfig
is stringly typed and only documents the built-in toolbar ids in XML comments,
so consumers have no safe way to reference them. Add stable public constants or
a typed wrapper for the built-in ids on BitRichTextEditorToolbarConfig (or a
related shared type) and expose them as the source of truth for ordering, so
callers can use the same identifiers instead of copying names from the docs.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: ac4e7152-a4e6-4524-8313-77ffca0349b6
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs (1)
84-90: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winParse the
data:MIME type exactly.The prefix check accepts non-exact MIME declarations like
data:image/pngfoo,.... Reuse the MIME parser shape fromIsKnownImageMimeTypeand require a valid data URL delimiter before allowing inline image URLs.Proposed fix
if (url.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { // Only allow data: URLs when the policy permits them and the declared MIME is a // known image type, so non-image payloads cannot be smuggled in as an "image". if (DataImageUrisAllowed is false) return false; - return KnownImageMimeTypes.Any(m => url.StartsWith($"data:{m}", StringComparison.OrdinalIgnoreCase)); + var comma = url.IndexOf(','); + if (comma <= "data:".Length) return false; + + var metadata = url["data:".Length..comma]; + var semicolon = metadata.IndexOf(';'); + var contentType = semicolon >= 0 ? metadata[..semicolon] : metadata; + + return IsKnownImageMimeType(contentType); }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs` around lines 84 - 90, The data URL check in BitRichTextEditor.Media.cs is too permissive because it matches MIME prefixes instead of an exact declared type. Update the inline-image validation in the relevant data: URL branch to parse the MIME type the same way as IsKnownImageMimeType and require a proper data URL delimiter before accepting it, so values like data:image/pngfoo are rejected. Keep the fix localized to the URL validation logic that uses DataImageUrisAllowed and KnownImageMimeTypes.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts (2)
392-404: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRestore the saved editor selection before budgeting
_maxLength.Line 398 reads the live document selection before this path restores
editor._range. If a toolbar/custom action triggersinsertTextwhile focus is outside the editor, selected editor text is counted as0, so in-place replacements at the limit get blocked or over-truncated.Suggested fix
public static insertText(editor: any, text: string) { if (!editor || !text) return; // Honor the same _maxLength budget enforced by onBeforeInput/paste so programmatic // inserts (emoji picker, custom toolbar items) cannot push past the limit. const max = editor._maxLength; if (max != null) { + RichTextEditor.restoreSelection(editor); const sel = document.getSelection(); - const selected = (sel && !sel.isCollapsed) ? sel.toString().length : 0; + const selected = (sel && !sel.isCollapsed && sel.anchorNode && editor.contains(sel.anchorNode)) + ? sel.toString().length + : 0; const current = (editor.textContent || '').length; const remaining = Math.max(0, max - (current - selected)); if (remaining === 0) return;🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts` around lines 392 - 404, Restore the saved editor selection before applying the _maxLength budget in insertText so toolbar/custom insertions use the editor’s actual range instead of the live document selection. Update BitRichTextEditor.insertText to recover editor._range (or equivalent saved range state) before computing selected/current/remaining, then use that restored selection when calculating how much text can be inserted so in-place replacements at the limit are handled correctly.
561-577: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReject external selections before applying block direction.
restoreSelection()is best-effort. If it cannot reactivate an editor range, Line 565 falls back to whatever is currently selected in the document, and the walk at Lines 570-575 can setdiron non-editor DOM.Suggested fix
public static setBlockDirection(editor: any, dir: string) { + if (!editor) return; // Restore the editor's saved range so the direction is applied to the editor's // block rather than a selection left active in the toolbar/dialog. RichTextEditor.restoreSelection(editor); const sel = document.getSelection(); - if (!sel || sel.rangeCount === 0) { + if (!sel || sel.rangeCount === 0 || !sel.anchorNode || !editor.contains(sel.anchorNode)) { if (editor._dotNetRef) editor._dotNetRef.invokeMethodAsync('OnClientError', 'no-selection', 'Select a block to change its direction.'); return; }🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts` around lines 561 - 577, Reject any selection that is not inside the current editor before applying block direction in setBlockDirection. After restoreSelection(), verify the active selection’s anchor node belongs to the provided editor and stop early with OnClientError if it does not; only then walk up to the block and set the dir attribute so external DOM cannot be modified.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 102-113: The slash-command popup in BitRichTextEditor is using
listbox/option semantics even though it behaves like an immediate action menu,
not a selectable list. Update the BitRichTextEditor.razor markup around
bit-rte-slash and bit-rte-slash-list to use plain command/menu-style semantics
or a neutral container with buttons, and remove the role="listbox"/role="option"
pattern unless you also implement full listbox behavior in FilteredSlash(),
ApplySlashAsync(), and the keyboard handling.
- Around line 21-71: The open link, image, media, and find panels in
BitRichTextEditor can still be edited and trigger mutating actions after
ReadOnly becomes true. Update the panel rendering in BitRichTextEditor.razor to
respect ReadOnly by disabling the inputs/buttons or automatically closing these
panels when the editor switches to read-only, and make sure handlers like
ApplyLinkAsync, RemoveLinkAsync, ApplyImageUrlAsync, ApplyMediaAsync,
ReplaceCurrentAsync, and ReplaceAllAsync cannot run while ReadOnly is enabled.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 166-191: Command-mutating helpers in BitRichTextEditor still run
while source view is active, which can desync the hidden editor state from the
source buffer. Update ExecAsync, ExecBlockAsync, and ClearFormattingAsync to
gate on ControlsDisabled instead of only ReadOnly, and keep the existing editor
action calls (_js.BitRichTextEditorExec and _js.BitRichTextEditorExecBlock)
behind that shared check so all command mutations are blocked whenever ReadOnly
or _inSourceView is true.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 34-46: Update the source-view commit flow in
BitRichTextEditor.SourceView so `_inSourceView` and `_currentHtml` are only
changed after `BitRichTextEditorSetHtml` succeeds; right now `SetSourceHtml`/the
source-view exit path applies state before the interop bridge completes. Keep
the existing early-return for the unchanged sanitized HTML case, but for the
changed-content path await the JS call first and only then clear source-view
state, cache the sanitized HTML, and call `StateHasChanged` so the editor DOM
and bound value stay consistent if the bridge throws.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor`:
- Around line 256-260: The demo text for the RichTextEditor “Find & replace”
example mentions a find-next action that the UI does not provide. Update the
copy in BitRichTextEditorDemo.razor to match the actual toolbar behavior exposed
by BitRichTextEditor.razor, describing only the available replace, replace-all,
close, and optional case-sensitive toggle actions.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs`:
- Around line 84-90: The data URL check in BitRichTextEditor.Media.cs is too
permissive because it matches MIME prefixes instead of an exact declared type.
Update the inline-image validation in the relevant data: URL branch to parse the
MIME type the same way as IsKnownImageMimeType and require a proper data URL
delimiter before accepting it, so values like data:image/pngfoo are rejected.
Keep the fix localized to the URL validation logic that uses
DataImageUrisAllowed and KnownImageMimeTypes.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 392-404: Restore the saved editor selection before applying the
_maxLength budget in insertText so toolbar/custom insertions use the editor’s
actual range instead of the live document selection. Update
BitRichTextEditor.insertText to recover editor._range (or equivalent saved range
state) before computing selected/current/remaining, then use that restored
selection when calculating how much text can be inserted so in-place
replacements at the limit are handled correctly.
- Around line 561-577: Reject any selection that is not inside the current
editor before applying block direction in setBlockDirection. After
restoreSelection(), verify the active selection’s anchor node belongs to the
provided editor and stop early with OnClientError if it does not; only then walk
up to the block and set the dir attribute so external DOM cannot be modified.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 0b7cc37d-0608-4e5a-8b79-a67d1e654def
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 12
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts (1)
28-29: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winRemove or sanitize global inline styles.
styleis accepted for every allowed tag, but values are not sanitized. This keeps arbitrary pasted/source CSS in persisted content. Remove it fromDEFAULT_POLICYor enforce a narrow safe CSS allowlist before preserving the attribute.Minimal default-policy fix
- '*': ['style', 'class', 'dir'], + '*': ['class', 'dir'],Also applies to: 1233-1241
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts` around lines 28 - 29, The default rich text sanitization policy currently allows the global style attribute on every tag without restricting its contents, so update DEFAULT_POLICY in BitRichTextEditor to remove the broad style allowance or replace it with a narrow safe CSS allowlist. Make the change in the policy used by the editor’s sanitization flow so pasted or sourced content cannot persist arbitrary inline CSS, while keeping the existing allowedAttributes structure and related policy handling consistent.src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs (1)
41-41: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDo not allow arbitrary inline CSS in the default policy.
styleis globally allowed, but the sanitizer only checks the attribute name, not CSS properties/values. Pasted/source HTML can persist UI-overlay or external-resource CSS unless styles are removed by default or sanitized to a small editor-generated allowlist. This is the same unresolved policy issue mirrored in the TypeScript default policy.Suggested hardening
- ["*"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "style", "class", "dir" }, + ["*"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "class", "dir" },If editor-generated font/color formatting must keep inline styles, add a CSS property/value sanitizer before allowing
style.🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs` at line 41, The default rich text sanitization policy currently allows arbitrary inline style attributes, which can preserve unsafe CSS. Update BitRichTextEditorSanitizationPolicy so the default "*" attribute allowlist no longer permits unrestricted style, or only permits it after a strict CSS property/value sanitizer is applied. Keep the existing class and dir handling, and make the change in the policy definition that builds the default allowlist.
🧹 Nitpick comments (1)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs (1)
49-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd assertions for the new style/class hooks.
BitRichTextEditorClassStylesnow exposesGroup,Button,Source, andCount, but this suite still only checksRoot,Editor, andToolbar. A small follow-up test covering those new mappings would protect the newly added public API from silent markup regressions.🤖 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/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs` around lines 49 - 69, Add follow-up assertions in BitRichTextEditorShouldApplyClassesAndReadOnly to cover the newly exposed BitRichTextEditorClassStyles hooks for Group, Button, Source, and Count. Extend the existing BitRichTextEditor test setup to pass values for those properties and verify the rendered markup applies them to the corresponding RichTextEditor elements, alongside the existing Root, Editor, and Toolbar checks.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cs`:
- Around line 49-69: Block replace operations in the RichTextEditor find flow
when source view is active by checking ControlsDisabled in ReplaceCurrentAsync
and ReplaceAllAsync, not just ReadOnly or _findTerm. Update the
BitRichTextEditor.Find methods so they return early before calling
_js.BitRichTextEditorReplaceCurrent or _js.BitRichTextEditorReplaceAll whenever
the editor is in source-view mode, keeping the DOM and source text from
diverging.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cs`:
- Around line 24-52: The link mutation flow in ApplyLinkAsync and
RemoveLinkAsync ignores the source-view state and can update the hidden editor
instead of _sourceText. Update these paths to honor ControlsDisabled, following
the same pattern used elsewhere in BitRichTextEditor.Links.cs: when source view
is active, apply/remove link changes against the source text model instead of
calling the JS editor APIs, and otherwise keep the current editor-based
behavior.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs`:
- Around line 43-53: The image/color/font mutation handlers still update the
editor while source view is active, so they should be gated the same way as
ExecAsync. Update ApplyImageUrlAsync and the related mutation methods referenced
in the review to use ControlsDisabled (or an equivalent ReadOnly ||
_inSourceView check) before calling into _js, so these actions are blocked
whenever source view is active.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 74-84: The emoji and slash panels in BitRichTextEditor can still
trigger insertion after the editor switches to read-only, so add a ReadOnly gate
to both the UI and action handlers. Update the BitRichTextEditor.razor panel
rendering and related click/command handlers like InsertEmojiAsync and the
slash-menu actions so they are hidden, disabled, or no-op when ReadOnly is true,
including any already-open panel state. Ensure the emoji grid and slash panel
cannot invoke insert commands once read-only is enabled.
- Around line 334-336: The SourceGroup toggle in BitRichTextEditor currently
blocks all interaction when ReadOnly is true, which can trap the editor in
source view. Update the button logic so entering source mode is still prevented
by ReadOnly, but exiting source mode remains possible when _inSourceView is
already true. Adjust the disabled/onclick behavior in SourceGroup and
ToggleSourceViewAsync to distinguish between “enter” and “exit” actions, keeping
rendered-view recovery available after ReadOnly changes.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 11-14: `ToggleSourceViewAsync` currently returns immediately when
`ReadOnly` is true, which also prevents closing `_inSourceView` if the host
switches to read-only while source view is open. Update the guard in
`BitRichTextEditor.SourceView` so `ReadOnly` blocks only entering source view,
not exiting it; keep the existing toggle path for closing source view and use
the `_inSourceView` state in `ToggleSourceViewAsync` to distinguish the two
cases.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cs`:
- Around line 18-39: Update ApplyMediaAsync to also respect ControlsDisabled,
not just ReadOnly, so media insertion cannot mutate the editor DOM while source
view is active; add the same guard to the related rule insertion path referenced
by the other affected block. Use the existing ApplyMediaAsync flow and any
matching insert method in the RichTextEditor structured component to
short-circuit before calling the JS insertion helpers and raise the appropriate
error if needed.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cs`:
- Around line 76-83: The toolbar validation in BitRichTextEditor should also
reject duplicate custom item IDs, since OrderedToolbarIds() de-duplicates
case-insensitively while RenderCustomItem() uses the first match and can hide
later actions. Update the validation loop in the toolbar config checks to track
item.Id values case-insensitively and throw an ArgumentException when a
duplicate is found, alongside the existing blank Id and AriaLabel checks.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 1006-1010: The onDrop handler in BitRichTextEditor only processes
image files and lets non-image drops fall back to the browser default, so update
onDrop to intercept text/html and text/plain dataTransfer content as well. Reuse
the same sanitized insertion flow used by the paste path in BitRichTextEditor,
including sanitize() and max-length budgeting, so all dropped content is handled
consistently rather than inserted directly by contenteditable.
- Around line 377-382: The iframe `src` validation in `BitRichTextEditor` only
checks the host allowlist and still accepts non-HTTPS URLs. Update the `name ===
'src'` / `tag === 'iframe'` branch to also require the `https:` scheme and
verify the active URI policy before allowing the embed, using the existing
sanitization flow around the `src` attribute check.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor`:
- Around line 389-396: The RichTextEditor demo example is inconsistent because
the copy mentions both Styles and Classes, but the BitRichTextEditor sample only
demonstrates Styles. Update the BitRichTextEditorDemo.razor example by either
adding a Classes assignment alongside the existing Styles usage or revising the
surrounding description to mention only Styles, so the Example "Style & Class"
matches what users can see and copy.
- Around line 150-158: The RichTextEditor demo keeps showing a stale link error
because `linkError` is only set in `BitRichTextEditor`’s `OnError` handler and
never cleared on successful edits. Update the `BitRichTextEditorDemo.razor`
sample to use explicit `Value`/`ValueChanged` handling for `linkHtml` so the
content update path can reset `linkError` whenever the editor value changes
successfully. Keep the fix localized to the `BitRichTextEditor` usage and the
`linkError` state in this demo.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 28-29: The default rich text sanitization policy currently allows
the global style attribute on every tag without restricting its contents, so
update DEFAULT_POLICY in BitRichTextEditor to remove the broad style allowance
or replace it with a narrow safe CSS allowlist. Make the change in the policy
used by the editor’s sanitization flow so pasted or sourced content cannot
persist arbitrary inline CSS, while keeping the existing allowedAttributes
structure and related policy handling consistent.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs`:
- Line 41: The default rich text sanitization policy currently allows arbitrary
inline style attributes, which can preserve unsafe CSS. Update
BitRichTextEditorSanitizationPolicy so the default "*" attribute allowlist no
longer permits unrestricted style, or only permits it after a strict CSS
property/value sanitizer is applied. Keep the existing class and dir handling,
and make the change in the policy definition that builds the default allowlist.
---
Nitpick comments:
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs`:
- Around line 49-69: Add follow-up assertions in
BitRichTextEditorShouldApplyClassesAndReadOnly to cover the newly exposed
BitRichTextEditorClassStyles hooks for Group, Button, Source, and Count. Extend
the existing BitRichTextEditor test setup to pass values for those properties
and verify the rendered markup applies them to the corresponding RichTextEditor
elements, alongside the existing Root, Editor, and Toolbar checks.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a40fbf73-48d7-44bd-a398-6c28a48f3dcb
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cs`:
- Around line 40-46: The find flow in BitRichTextEditor.Find still hardcodes
user-facing strings, so route the error text and status labels through the
localizer instead of English literals. Update the logic around the find term
length check and the `_findCount` assignment in BitRichTextEditor.Find so
`"Search term is too long."`, `"No matches"`, and the match/replaced status text
are produced via `Label(...)` before calling `RaiseErrorAsync` or setting
`_findCount`; apply the same localization pattern to the related find/replace
paths mentioned in the comment, using the existing `IBitRichTextEditorLocalizer`
integration.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor`:
- Around line 21-92: The auxiliary panels in BitRichTextEditor.razor are still
rendered and interactive during source view because they only check ReadOnly, so
they can mutate the hidden editor DOM instead of the visible _sourceText. Update
the visibility and action gating around the link/image/media/find/emoji panels
and the find toggle in BitRichTextEditor to also respect ControlsDisabled, or
clear those panel states when source view is entered. Use the existing panel
state flags (_showLinkInput, _showImageInput, _showMediaInput, _showFind,
_showEmoji) and source-view/controls logic to keep these controls inactive while
source mode is active.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 280-287: The initial load and external update paths in
BitRichTextEditor currently sanitize HTML for rendering but do not push the
sanitized result back through the bound Value, so `@bind-Value` can still retain
unsafe content; update the OnAfterRender/initial-value flow and OnValueSet() so
that when _js.BitRichTextEditorSanitizeHtml changes the string, the component
assigns the sanitized HTML back to Value (via the existing binding/update
mechanism) before storing it in _currentHtml. Use the same
sanitize-then-propagate pattern in both places to keep the bound model and
rendered content in sync.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cs`:
- Around line 30-62: The _OnShortcut method in BitRichTextEditor.Shortcuts.cs is
returning true even when source view blocks execution because ExecAsync no-ops
via ControlsDisabled, which can incorrectly suppress the browser default. Update
_OnShortcut to detect the source-view/disabled state before calling ExecAsync
and return false when the shortcut is not actually handled, while keeping the
existing command lookup and unknown-command error handling intact.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cs`:
- Around line 13-16: The close flow in RichTextEditor source view still applies
and emits _sourceText even after ReadOnly becomes true, which violates the
read-only contract. Update the source-view exit path in
BitRichTextEditor.SourceView so that when ReadOnly is true on close it only
exits source view and skips sanitizing, assigning, and raising changes from
_sourceText. Keep the existing guard that allows leaving source view, but add a
ReadOnly check around the apply/commit logic in the same source-view close
method(s).
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cs`:
- Around line 81-90: The custom toolbar item validation in
BitRichTextEditor.Toolbar should also reject Id values that collide with
built-in toolbar group ids, not just blanks or duplicates within the custom
list. Update the validation flow around the items loop and OrderedToolbarIds()
integration so custom items cannot use reserved ids like history or image, and
throw an ArgumentException from the toolbar config validation when a collision
is detected. Use the existing BitRichTextEditor custom toolbar item checks in
the toolbar configuration path to keep the namespace for built-ins and custom
items distinct.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 623-627: `applySlashCommand()` is using
`RichTextEditor.currentBlock(editor)` before restoring the saved selection, so
the editor may lose focus and the slash block lookup can fail. Update
`BitRichTextEditor.applySlashCommand` to restore `editor._range` first, then
resolve the current block and remove the leading slash from that block’s text
before applying the command.
- Around line 355-376: The attribute sanitization in BitRichTextEditor currently
only strips attributes when a tag has an explicit entry in allowedAttrs, so
non-media tags like p and br can keep arbitrary attributes and let insertMedia()
wrapper markup leak into Value. Update the filtering inside the
tpl.content.querySelectorAll('*') loop to enforce a default deny policy for all
tags, keeping only safe/global attributes and the per-tag allowlist for media
tags such as iframe, video, audio, and source, while preserving the existing
policy.allowedTags and event-handler stripping logic.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs`:
- Around line 39-49: Remove the insecure default inline CSS permission from
BitRichTextEditorSanitizationPolicy by updating the AllowedAttributes setup in
the sanitization policy so the wildcard entry no longer includes style. Keep the
rest of the allowlist unchanged, and ensure the secure default still permits
only the intended attributes for tags like a, img, td, th, audio, video, and
source.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 53131195-2f5a-49d1-a0fe-d33f6bca9873
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
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
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 1008-1019: The MaxLength clamp in insertTransferContent is using
text.length, but the actual inserted value can be toInsert when HTML
paste/transfer data is present. Update the budgeting logic in
BitRichTextEditor.insertTransferContent to measure the final inserted content
(including HTML-sanitized or HTML-only cases) and truncate based on that value
rather than the plain-text payload. Keep the existing selection/remaining-length
calculation, but ensure the final toInsert content cannot exceed the remaining
budget before insertion.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs`:
- Around line 612-617: The sample validation code in
BitRichTextEditorDemo.razor.cs uses Regex without making
System.Text.RegularExpressions available, so the copied snippet won’t compile.
Update the Validate method to reference the regex type with its fully qualified
name, or add the missing using where example26CsharpCode is defined so the
snippet is self-contained.
- Around line 399-406: The validation in BitRichTextEditorDemo.Validate still
counts HTML entities and also overlaps with the existing [Required] check on
empty content. Update the Body length rule to work on normalized visible text by
stripping tags, decoding entities, and trimming before measuring, and skip the
minimum-length ValidationResult when nothing visible remains so empty bodies are
handled only by [Required].
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 49412e92-6d5e-4157-915e-b62a45189605
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cs`:
- Around line 56-59: The InsertEmojiAsync flow in BitRichTextEditor.Emoji.cs
still allows inserting into the live editor while source view is active, so
align it with the same guard used by the find/replace path. Update
InsertEmojiAsync to block insertion when ControlsDisabled is true in addition to
ReadOnly, and keep the _js.BitRichTextEditorInsertText call behind that combined
check so emoji insertion is skipped whenever source view controls are disabled.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 280-286: The initial-value and value-update paths in
BitRichTextEditor are only sanitizing when SanitizationPolicy is non-null, which
bypasses the bridge’s secure default allowlist when no custom policy is set.
Update the logic in BitRichTextEditor.razor.cs around the initial load and the
OnValueSet flow so BitRichTextEditorSanitizeHtml is invoked for any non-empty
HTML regardless of SanitizationPolicy, while still preserving any custom policy
behavior through the bridge. Ensure both the editor-rendered content and the
bound Value are sanitized under the default and custom cases.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 600-606: The roving focus list in enableToolbarRoving currently
includes disabled controls and label elements, which can trap keyboard
navigation on non-focusable items. Update the items() selector and any related
filtering in enableToolbarRoving so only enabled interactive controls are
included, and exclude disabled buttons/inputs/selects plus labels from the
roving tab order.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cs`:
- Around line 45-48: SetDirectionAsync currently only checks ReadOnly, so
block-direction changes can still run while controls are disabled and mutate the
hidden editor DOM in source view. Update SetDirectionAsync in
BitRichTextEditor.View to also guard on ControlsDisabled before calling
_js.BitRichTextEditorSetBlockDirection, matching the existing disabled-state
handling used elsewhere in the RichTextEditor component.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cs`:
- Line 7: The immutable upload contract in BitRichTextEditorImageUpload is
weakened by using a shared mutable byte[] for Content. Update the record to use
an immutable/read-only binary representation or defensively clone the buffer
when constructing and exposing it, and make sure any OnImageUpload usage treats
the payload as non-shared state so callers cannot mutate the stored content
after creation.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs`:
- Around line 396-408: The current validation in BitRichTextEditorDemo.razor.cs
only counts raw HTML in Validate and lets empty-looking markup pass through
[Required]; update the Body validation to also require non-whitespace visible
text after stripping tags and decoding entities, and keep the min-length check
based on that normalized text. Apply the same visible-text required behavior in
the sample snippet so it matches the model validation, using the existing
Validate method and Body property as the key locations.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 36373906-85e9-4c7c-95e4-71ae97c93cb7
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs (1)
126-130: 📐 Maintainability & Code Quality | 🔵 TrivialUse
ILoggerfor upload failures instead ofDebug.WriteLine.The UI message is safe now, but this catch path still drops the full exception in most deployed environments. Route
exto the component/library logger so failed uploads remain diagnosable outside local debugging.🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs` around lines 126 - 130, The upload failure catch path is still writing the exception only to Debug.WriteLine, so replace that with the component/library ILogger and log ex there while keeping the user-facing BitRichTextEditorError unchanged. Update the catch block in BitRichTextEditor.Media so the upload failure is recorded through the existing logging pipeline, using the same contextual message that includes the file name and exception details.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cs`:
- Around line 322-326: The OnValueSet flow in BitRichTextEditor is ignoring
external Value changes whenever _inSourceView is true, which leaves _sourceText
and _currentHtml out of sync. Update the OnValueSet method to handle incoming
Value changes even during source view, either by syncing _sourceText immediately
for external updates or by storing a pending external value to apply when source
editing ends, and make sure the editor state reflects the latest parent Value
rather than returning early.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 1086-1093: The shortcut fallback in BitRichTextEditor’s key
handling is too broad because it treats ctrl+b/i/u/z/y as owned even when Alt is
pressed, which can block AltGr/Ctrl+Alt input. Update the owned check in the
editor’s shortcut handler to exclude Alt-modified combinations from the built-in
fallback, while still allowing custom Alt combos through _shortcutKeys. Keep the
logic in the same shortcut-processing block so only non-Alt primary shortcuts
are preempted.
- Around line 1278-1287: In the RichTextEditor sanitization flow, the
`allowedAttributes` check in `BitRichTextEditor` currently skips filtering when
a custom policy omits `allowedAttributes`, letting non-event attributes through
on otherwise allowed tags. Update this branch so `policy.allowedAttributes`
defaults to a deny-all/empty allowlist when missing, while still honoring any
tag-specific and `'*'` entries when present, and keep the logic centered around
the existing attribute filtering block that uses `policy`, `allowedAttributes`,
and `el.removeAttribute`.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cs`:
- Around line 23-54: The BitRichTextEditorSanitizationPolicy.Default baseline is
missing the editor’s own iframe-based media output, so embeds are stripped on
re-sanitization. Update the Default property in
BitRichTextEditorSanitizationPolicy to either keep iframe media explicitly out
of the standard policy or include the exact iframe tag and required attributes
used by the media feature so supported embeds round-trip correctly. Use the
existing AllowedTags and AllowedAttributes dictionaries to align the policy with
the built-in editor output.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cs`:
- Around line 614-629: The validation sample is missing the DataAnnotations
namespace/import, so the shown FormModel snippet is not self-contained. Update
the example around FormModel and its Validate method to either include the
required using for System.ComponentModel.DataAnnotations in the displayed sample
or fully qualify Required, IValidatableObject, ValidationResult, and
ValidationContext so example26CsharpCode compiles when copied.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cs`:
- Around line 126-130: The upload failure catch path is still writing the
exception only to Debug.WriteLine, so replace that with the component/library
ILogger and log ex there while keeping the user-facing BitRichTextEditorError
unchanged. Update the catch block in BitRichTextEditor.Media so the upload
failure is recorded through the existing logging pipeline, using the same
contextual message that includes the file name and exception details.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8431c83c-6d57-4ebc-97b3-db17b642f49f
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cs (1)
6-6: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winType the policy contract explicitly.
Policyis the only opaque field in this setup DTO. Keeping it asobjecthides the interop payload shape and makes policy changes fail only at runtime. Since this PR already introduces a dedicated sanitization-policy type, prefer using that here too.♻️ Proposed fix
internal class BitRichTextEditorSetupOptions { public int Debounce { get; set; } - public object? Policy { get; set; } + public BitRichTextEditorSanitizationPolicy? Policy { get; set; } public bool HasUpload { get; set; } public bool PlainTextPaste { get; set; } public int? MaxLength { get; set; } public string[]? ShortcutKeys { get; 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cs` at line 6, The BitRichTextEditorSetupOptions.Policy property is still typed as an opaque object, which hides the interop contract. Update the Policy member in BitRichTextEditorSetupOptions to use the dedicated sanitization policy type introduced by this PR, so the setup DTO reflects the actual payload shape and policy changes are caught at compile time.
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cs`:
- Around line 46-48: The count text in RichTextEditor.Find still hardcodes
English word order/plural handling via interpolated strings, so replace the ad
hoc $"{count} ..." / $"{n} ..." logic with full localized format strings for
each case. Update the count-message assignment in the Find-related code paths
using the existing Label helper and localized templates so translators control
ordering and pluralization. Make the same fix for both affected count outputs
referenced in this class, not just the one in the current block.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss`:
- Around line 3-11: The root RichTextEditor container in BitRichTextEditor.scss
is clipping wide content, so horizontal scrolling must be enabled for the
editing surface. Update the .bit-rte styling and the related editor/table
wrapper rules referenced in the same stylesheet so wide tables can scroll on the
X axis instead of being hidden, while preserving the existing vertical behavior
and layout in the BitRichTextEditor component.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cs`:
- Around line 6-21: Table mutation commands in InsertTableAsync and TableOpAsync
still only check ReadOnly, so they can run while controls are disabled in source
view and mutate the hidden editor DOM. Update these methods to guard on
ControlsDisabled the same way the other command flows do, and keep the existing
ReadOnly behavior if needed. Use the InsertTableAsync and TableOpAsync methods
in BitRichTextEditor.Tables.cs as the fix points.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`:
- Around line 369-382: sanitizeMedia currently ignores custom attribute
allowlists after a tag is permitted, so media elements like iframe can keep
hard-coded attributes that the active policy did not allow. Update the attribute
filtering inside sanitizeMedia to respect the policy’s per-tag attribute
allowlist in addition to allowedTags, using the existing
allowedAttrs/globalAttrs logic so only attributes explicitly permitted by the
active sanitization contract are preserved.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cs`:
- Line 6: The BitRichTextEditorSetupOptions.Policy property is still typed as an
opaque object, which hides the interop contract. Update the Policy member in
BitRichTextEditorSetupOptions to use the dedicated sanitization policy type
introduced by this PR, so the setup DTO reflects the actual payload shape and
policy changes are caught at compile time.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: c08fcfe8-67b8-4f9a-8b7d-0a4c5ecb9dbc
📒 Files selected for processing (103)
src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Count.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Emoji.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Forms.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Links.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Media.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Sanitization.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Shortcuts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Slash.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.SourceView.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Structured.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Toolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.View.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorClassStyles.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorContentFacts.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorError.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorImageUpload.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSanitizationPolicy.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSelectionState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorSetupOptions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbar.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarConfig.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorToolbarItem.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/IBitRichTextEditorLocalizer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill-2.0.3.jssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.csssrc/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.csssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/RichTextEditor/BitRichTextEditorDemo.razor.scsssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Extras/RichTextEditor/BitRichTextEditorTests.cs
💤 Files with no reviewable changes (68)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/text.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/QuillModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/background.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/bubble.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/underline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/bold.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/break.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorTheme.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/snow.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/align.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/header.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/input.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/module.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/toolbar.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/size.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/table.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/image.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/inline.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/indent.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/selection.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Delta.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/AttributeMap.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/formula.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/scroll.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/script.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/theme.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uploader.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/font.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/parchment/parchment.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/clipboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/tableEmbed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.bubble-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/color.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/wwwroot/quilljs/quill.snow-2.0.3.css
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/video.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/Op.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/history.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/composition.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icons.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/link.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/italic.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/delta/OpIterator.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/editor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/container.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/block.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/code.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/tooltip.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditorModule.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/icon-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/strike.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/blockquote.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/syntax.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/quill.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/cursor.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/uiNode.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/scrollRectIntoView.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/utils/createRegistryWithFormats.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/logger.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/blots/embed.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/EventEmitter3/EventEmitter3.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/direction.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/ui/color-picker.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/themes/base.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/formats/list.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/modules/keyboard.d.ts
- src/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/@types/emitter.d.ts
| _findCount = count == 0 | ||
| ? Label("no-matches", "No matches") | ||
| : $"{count} {(count == 1 ? Label("match", "match") : Label("matches", "matches"))}"; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use full localized format strings for count messages.
$"{count} ..." and $"{n} ..." still bake in English word order/plural rules. This will produce awkward or incorrect text in many locales even with translated labels.
Also applies to: 73-74
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Find.cs`
around lines 46 - 48, The count text in RichTextEditor.Find still hardcodes
English word order/plural handling via interpolated strings, so replace the ad
hoc $"{count} ..." / $"{n} ..." logic with full localized format strings for
each case. Update the count-message assignment in the Find-related code paths
using the existing Label helper and localized templates so translators control
ordering and pluralization. Make the same fix for both affected count outputs
referenced in this class, not just the one in the current block.
| .bit-rte { | ||
| border: $shp-border-width $shp-border-style $clr-brd-pri; | ||
| border-radius: $shp-border-radius; | ||
| overflow: hidden; | ||
| background: $clr-bg-pri; | ||
| color: $clr-fg-pri; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Allow horizontal scrolling for wide tables.
The new table feature allows up to 50 columns, but the root editor clips overflow and the editing surface only scrolls on the Y axis. A wide table will extend past the right edge with no way to reach the hidden cells.
Suggested fix
.bit-rte-edt {
padding: spacing(1.7) spacing(2);
outline: none;
- overflow-y: auto;
+ overflow: auto;
line-height: 1.6;
color: $clr-fg-pri;
flex: 1;
position: relative;Also applies to: 232-239, 312-323
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.scss`
around lines 3 - 11, The root RichTextEditor container in BitRichTextEditor.scss
is clipping wide content, so horizontal scrolling must be enabled for the
editing surface. Update the .bit-rte styling and the related editor/table
wrapper rules referenced in the same stylesheet so wide tables can scroll on the
X axis instead of being hidden, while preserving the existing vertical behavior
and layout in the BitRichTextEditor component.
| private async Task InsertTableAsync(int rows, int cols) | ||
| { | ||
| if (ReadOnly) return; | ||
| if (rows < 1 || rows > 50 || cols < 1 || cols > 50) | ||
| { | ||
| await RaiseErrorAsync(new BitRichTextEditorError("invalid-table", | ||
| Label("invalid-table", "Tables must be between 1 and 50 rows/columns."))); | ||
| return; | ||
| } | ||
| await _js.BitRichTextEditorInsertTable(_editorRef, rows, cols); | ||
| } | ||
|
|
||
| private async Task TableOpAsync(string op) | ||
| { | ||
| if (ReadOnly) return; | ||
| await _js.BitRichTextEditorTableOp(_editorRef, op); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Guard table mutations with ControlsDisabled.
These paths still only check ReadOnly, so switching to source view can leave table insert/ops mutating the hidden editor DOM while the visible HTML source stays unchanged. The other command flows already moved to ControlsDisabled for this reason.
Suggested fix
private async Task InsertTableAsync(int rows, int cols)
{
- if (ReadOnly) return;
+ if (ControlsDisabled) return;
if (rows < 1 || rows > 50 || cols < 1 || cols > 50)
{
await RaiseErrorAsync(new BitRichTextEditorError("invalid-table",
Label("invalid-table", "Tables must be between 1 and 50 rows/columns.")));
return;
}
await _js.BitRichTextEditorInsertTable(_editorRef, rows, cols);
}
private async Task TableOpAsync(string op)
{
- if (ReadOnly) return;
+ if (ControlsDisabled) return;
await _js.BitRichTextEditorTableOp(_editorRef, op);
}📝 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.
| private async Task InsertTableAsync(int rows, int cols) | |
| { | |
| if (ReadOnly) return; | |
| if (rows < 1 || rows > 50 || cols < 1 || cols > 50) | |
| { | |
| await RaiseErrorAsync(new BitRichTextEditorError("invalid-table", | |
| Label("invalid-table", "Tables must be between 1 and 50 rows/columns."))); | |
| return; | |
| } | |
| await _js.BitRichTextEditorInsertTable(_editorRef, rows, cols); | |
| } | |
| private async Task TableOpAsync(string op) | |
| { | |
| if (ReadOnly) return; | |
| await _js.BitRichTextEditorTableOp(_editorRef, op); | |
| private async Task InsertTableAsync(int rows, int cols) | |
| { | |
| if (ControlsDisabled) return; | |
| if (rows < 1 || rows > 50 || cols < 1 || cols > 50) | |
| { | |
| await RaiseErrorAsync(new BitRichTextEditorError("invalid-table", | |
| Label("invalid-table", "Tables must be between 1 and 50 rows/columns."))); | |
| return; | |
| } | |
| await _js.BitRichTextEditorInsertTable(_editorRef, rows, cols); | |
| } | |
| private async Task TableOpAsync(string op) | |
| { | |
| if (ControlsDisabled) return; | |
| await _js.BitRichTextEditorTableOp(_editorRef, op); |
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.Tables.cs`
around lines 6 - 21, Table mutation commands in InsertTableAsync and
TableOpAsync still only check ReadOnly, so they can run while controls are
disabled in source view and mutate the hidden editor DOM. Update these methods
to guard on ControlsDisabled the same way the other command flows do, and keep
the existing ReadOnly behavior if needed. Use the InsertTableAsync and
TableOpAsync methods in BitRichTextEditor.Tables.cs as the fix points.
| // Honor the active sanitization policy first: media tags (notably iframe, which | ||
| // is opt-in) are only permitted when the policy allows them; otherwise setHtml() | ||
| // would strip them later, leaving inconsistent state. | ||
| if (policy && policy.allowedTags && !policy.allowedTags.includes(tag)) { | ||
| el.replaceWith(...Array.from(el.childNodes)); return; | ||
| } | ||
| for (const attr of Array.from(el.attributes)) { | ||
| const name = attr.name.toLowerCase(); | ||
| if (name.startsWith('on')) { el.removeAttribute(attr.name); continue; } | ||
| // Default deny: keep only the per-tag media allowlist or the safe global | ||
| // attributes; drop anything else regardless of which tag carries it. | ||
| const allowed = allowedAttrs[tag]; | ||
| const permitted = allowed ? allowed.has(name) : globalAttrs.has(name); | ||
| if (!permitted) { el.removeAttribute(attr.name); continue; } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Honor custom attribute allowlists in media sanitization.
sanitizeMedia only checks policy.allowedTags; once a host opts into iframe/media tags, this path still preserves the hard-coded media attributes even when the custom policy omitted them. That can emit Value that violates the active sanitization contract until a later setHtml() roundtrip strips it.
Proposed fix direction
if (policy && policy.allowedTags && !policy.allowedTags.includes(tag)) {
el.replaceWith(...Array.from(el.childNodes)); return;
}
+ const policyAttrs = policy?.allowedAttributes;
for (const attr of Array.from(el.attributes)) {
const name = attr.name.toLowerCase();
if (name.startsWith('on')) { el.removeAttribute(attr.name); continue; }
+ if (policyAttrs) {
+ const allowedByPolicy = [
+ ...(policyAttrs[tag] || []),
+ ...(policyAttrs['*'] || [])
+ ];
+ if (!allowedByPolicy.includes(name)) { el.removeAttribute(attr.name); continue; }
+ }📝 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.
| // Honor the active sanitization policy first: media tags (notably iframe, which | |
| // is opt-in) are only permitted when the policy allows them; otherwise setHtml() | |
| // would strip them later, leaving inconsistent state. | |
| if (policy && policy.allowedTags && !policy.allowedTags.includes(tag)) { | |
| el.replaceWith(...Array.from(el.childNodes)); return; | |
| } | |
| for (const attr of Array.from(el.attributes)) { | |
| const name = attr.name.toLowerCase(); | |
| if (name.startsWith('on')) { el.removeAttribute(attr.name); continue; } | |
| // Default deny: keep only the per-tag media allowlist or the safe global | |
| // attributes; drop anything else regardless of which tag carries it. | |
| const allowed = allowedAttrs[tag]; | |
| const permitted = allowed ? allowed.has(name) : globalAttrs.has(name); | |
| if (!permitted) { el.removeAttribute(attr.name); continue; } | |
| // Honor the active sanitization policy first: media tags (notably iframe, which | |
| // is opt-in) are only permitted when the policy allows them; otherwise setHtml() | |
| // would strip them later, leaving inconsistent state. | |
| if (policy && policy.allowedTags && !policy.allowedTags.includes(tag)) { | |
| el.replaceWith(...Array.from(el.childNodes)); return; | |
| } | |
| const policyAttrs = policy?.allowedAttributes; | |
| for (const attr of Array.from(el.attributes)) { | |
| const name = attr.name.toLowerCase(); | |
| if (name.startsWith('on')) { el.removeAttribute(attr.name); continue; } | |
| if (policyAttrs) { | |
| const allowedByPolicy = [ | |
| ...(policyAttrs[tag] || []), | |
| ...(policyAttrs['*'] || []) | |
| ]; | |
| if (!allowedByPolicy.includes(name)) { el.removeAttribute(attr.name); continue; } | |
| } | |
| // Default deny: keep only the per-tag media allowlist or the safe global | |
| // attributes; drop anything else regardless of which tag carries it. | |
| const allowed = allowedAttrs[tag]; | |
| const permitted = allowed ? allowed.has(name) : globalAttrs.has(name); | |
| if (!permitted) { el.removeAttribute(attr.name); continue; } |
🤖 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/BlazorUI/Bit.BlazorUI.Extras/Components/RichTextEditor/BitRichTextEditor.ts`
around lines 369 - 382, sanitizeMedia currently ignores custom attribute
allowlists after a tag is permitted, so media elements like iframe can keep
hard-coded attributes that the active policy did not allow. Update the attribute
filtering inside sanitizeMedia to respect the policy’s per-tag attribute
allowlist in addition to allowedTags, using the existing
allowedAttrs/globalAttrs logic so only attributes explicitly permitted by the
active sanitization contract are preserved.
closes #12505
Summary by CodeRabbit
SanitizationPolicy), optional persisted image uploads, and EditForm integration (ValueExpression).ShowCount/MaxLength).ReadOnlyis enabled.