Skip to content

fix(custom-class): preserve HTML structure in multiline selections (#594)#595

Merged
kolkov merged 1 commit intomainfrom
fix/594-custom-class-multiline
Jan 30, 2026
Merged

fix(custom-class): preserve HTML structure in multiline selections (#594)#595
kolkov merged 1 commit intomainfrom
fix/594-custom-class-multiline

Conversation

@kolkov
Copy link
Owner

@kolkov kolkov commented Jan 30, 2026

Summary

Fixes #594 - When applying custom class, multiline blocks were converted to single line, losing all HTML structure (paragraphs, fonts, lists, etc.).

Root Cause

The createCustomClass() method used sel.toString() which returns plain text only, stripping all HTML structure.

Solution

Implemented an enterprise-level solution with smart block/inline detection:

  • New mode option for CustomClass interface:

    • 'inline' - Wrap selection in single element (legacy behavior)
    • 'block' - Apply class to each block element in selection
    • 'auto' (default) - Smart detection based on selection span
  • DOM Range API with extractContents() + insertNode() pattern instead of sel.toString()

  • TreeWalker-based block detection for finding P, DIV, H1-H6, LI, etc.

  • Toggle behavior in block mode - removes class if already present

Example Usage

customClasses: [
  { name: 'Red Text', class: 'redText' },  // Uses 'auto' by default
  { name: 'Block Highlight', class: 'highlight', mode: 'block' },
  { name: 'Inline Style', class: 'inline', mode: 'inline' }
]

Changes

  • config.ts - Extended CustomClass interface with mode option
  • angular-editor.service.ts - New implementation of createCustomClass() with helper methods
  • angular-editor.service.spec.ts - Added 6 comprehensive unit tests

Test Plan

  • TypeScript compilation passes
  • Library builds successfully (ng-packagr)
  • All 19 unit tests pass (13 existing + 6 new)
  • Manual testing in demo app

Before/After

Before (broken):

<!-- Input -->
<p>First</p><p>Second</p><p>Third</p>

<!-- After applying class - WRONG -->
<span class="redText">First&#10;Second&#10;Third</span>

After (fixed):

<!-- Input -->
<p>First</p><p>Second</p><p>Third</p>

<!-- After applying class with mode: 'block' - CORRECT -->
<p class="redText">First</p><p class="redText">Second</p><p class="redText">Third</p>

)

- Add 'mode' option to CustomClass: 'inline', 'block', 'auto' (default)
- Implement smart block detection using DOM Range API and TreeWalker
- Use extractContents + insertNode pattern instead of sel.toString()
- Add toggle behavior for block mode (remove class if already present)
- Add comprehensive unit tests for createCustomClass (6 new tests)

Fixes #594
@kolkov kolkov force-pushed the fix/594-custom-class-multiline branch from 665dbb9 to e0f8b44 Compare January 30, 2026 02:14
@kolkov kolkov merged commit e796670 into main Jan 30, 2026
@kolkov kolkov deleted the fix/594-custom-class-multiline branch January 30, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When apply custom class, multiline blocks are converted to single line

1 participant