There are 2 comments.
 
 
XWiki Platform / cid:jira-generated-image-avatar-182a34a6-7d15-4b2d-9c4d-c45fb6c40a02 XWIKI-24281 Open

WYSIWYG editor causes content loss in computed fields when adding a macro

 
View issue   ·   Add comment
 

2 comments

 
cid:jira-generated-image-avatar-b8651452-73a3-497c-8ac8-88ac1fb550a8 Vincent Massol on 27/Apr/26 14:12
 

According to CC:

Bug Summary (XWIKI-24281) 63,972 tokens
When editing a page that has a class with computed fields, adding a macro via the WYSIWYG editor (CKEditor) causes the content of the computed field to disappear. 32% used
$0.00 spent
Root Cause: XWIKI-23043 — "Provide validation and UI for group of macro parameters belonging to same feature"
LSP
The regression was introduced by XWIKI-23043, specifically through these commits: • jdtls xwiki-platform-core/xwiki-
┌─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ platform-oldcore
│Commit │Date │Description │
├─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ ▼ Todo
│0b8eff16718 │Jun 20, 2025 │Initial PR (#4187) — Major refactor of macro parameter handling │ [✓] Understand the bug: WYSIWYG
├─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ editor causes content loss in
│63a86e309f1 │Jun 25, 2025 │Changed nested editables conversion from widget HTML serialization to per-editable getData() │ computed fields when adding a
├─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ macro
│ae5a0f19f2d │Jun 26, 2025 │Macro quick action no longer pre-inserts macro before modal closes │ [✓] Search for related commits in
└─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ CKEditor module that could cause
the regression
This landed in XWiki 17.5.0 (the regression boundary is between 17.4.0 and 17.5.0). [✓] Find the specific commit and
Jira issue that introduced the
Mechanism of the Regression regression
[•] Propose a fix plan
The bug occurs through the following chain:

1. cleanupEditables was added (plugin.js:814-821): When updating a macro widget, this method removes inplace editable DOM elements from the widget if showInlineEditableParameters is true (which is the default). This happens before widget.setData(data).

2. The xwiki-refresh server round-trip (plugin.js:391-416): After macro insertion, ALL editor content is sent to the server for a rendering round-trip: editor.getData() → server converts HTML→wiki syntax→HTML → editor.setData(html).

3. Computed fields have no storage (ComputedFieldClass.java:132-136): fromString() returns null, and displayHidden() is empty. The computed field content shown in the editor is the rendered output of a script, not stored wiki content.

4. The content loss happens during the refresh round-trip: When the editor content (which includes the rendered computed field HTML) goes through editor.getData() → server conversion → editor.setData(), the server re-renders everything. The computed field's rendered
output is treated as regular wiki syntax content, and if it doesn't cleanly round-trip through the HTML→wiki→HTML conversion, the content is lost or replaced with empty/different content.

Key Files

  • xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-macro/plugin.js — cleanupEditables (line 814), xwiki-refresh command (line 391), insertOrUpdateMacroWidget (line 737)
  • xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-source/plugin.js — convertHTML server round-trip
  • xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/objects/classes/ComputedFieldClass.java — displayEdit calls displayView, displayHidden is empty

Fix plan:

Fix Plan editor causes content loss in
computed fields when adding a
Option A (Targeted fix — recommended): Protect computed field content during the xwiki-refresh round-trip. macro
[✓] Search for related commits in
1. Identify computed field boundaries in the editor HTML: When the editor is used on a page with computed fields, the computed field content is rendered inside specific DOM elements (typically within form field containers). Add data attributes or markers to identify CKEditor module that could cause
computed field content during editing. the regression
[✓] Find the specific commit and
2. Preserve computed field content during refresh: In the xwiki-refresh command (plugin.js:391-416), before calling editor.getData(), save the computed field content. After editor.setData(html), restore the saved computed field content, preventing the server round- Jira issue that introduced the
trip from overwriting it. regression
[•] Propose a fix plan
3. Alternative approach: Instead of modifying the refresh command, make the downcast function aware of computed fields so it can preserve them during the getData() → server → setData() cycle. This could be done by wrapping computed field content in special markers
that survive the round-trip.

Option B (Minimal fix): Skip the xwiki-refresh for computed fields.

1. In insertOrUpdateMacroWidget (plugin.js:808-811), the xwiki-refresh command is triggered with a setTimeout. Before this refresh, check if the editor content includes computed field areas. If so, either skip the refresh or handle it differently for those areas.

2. The computed field content could be marked with CSS classes or data attributes by ComputedFieldClass.displayEdit() so the JS can detect and preserve it.

Option C (Server-side fix): Ensure the HTML converter handles computed field output correctly.

1. Modify the CKEditor.HTMLConverter or the underlying rendering pipeline to properly handle the HTML output of computed fields during the HTML→wiki→HTML round-trip. This would ensure the content survives the conversion.

Recommended Approach

Option A is recommended because:

  • It addresses the root cause (content loss during round-trip) directly in the CKEditor plugin
  • It doesn't require changes to the rendering pipeline or server-side code
  • It's consistent with how nested editables are already handled (their content is preserved during refresh)

The fix should:
1. Add a marker (e.g., data-xwiki-computed-field) to the computed field's rendered HTML in ComputedFieldClass.displayEdit()
2. In the xwiki-refresh command, extract and preserve the marked content before the server round-trip
3. After editor.setData(), restore the preserved computed field content

Verification

To bisect and confirm: compare behavior between tags xwiki-platform-17.4.0 (before XWIKI-23043) and xwiki-platform-17.5.0 (after). The regression should be reproducible starting from 17.5.0.

 
cid:jira-generated-image-avatar-b8651452-73a3-497c-8ac8-88ac1fb550a8 Vincent Massol on 27/Apr/26 14:13
 
According to CC:

{
quote noformat }
    Bug Summary (XWIKI-24281)
                     63,972 tokens                    
    
                    
     When editing a page that has a class with computed fields, adding a macro via the WYSIWYG editor (CKEditor) causes the content of the computed field to disappear.                      32% used                    
                     $0.00 spent                    
                    
                    
     Root Cause: XWIKI-23043 — "Provide validation and UI for group of macro parameters belonging to same feature"                    
                     LSP                    
                    
     The regression was introduced by XWIKI-23043, specifically through these commits:                     • jdtls xwiki-platform-core/xwiki-      
     ┌─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐      platform-oldcore                    
     │Commit                     │Date                     │Description                     │                    
     ├─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤    ▼ Todo                    
     │0b8eff16718                     │Jun 20, 2025                     │Initial PR (#4187) — Major refactor of macro parameter handling                     │    [✓] Understand the bug: WYSIWYG         
     ├─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤        editor causes content loss in       
     │63a86e309f1                     │Jun 25, 2025                     │Changed nested editables conversion from widget HTML serialization to per-editable getData()                     │        computed fields when adding a       
     ├─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤        macro                    
     │ae5a0f19f2d                     │Jun 26, 2025                     │Macro quick action no longer pre-inserts macro before modal closes                     │    [✓] Search for related commits in       
     └─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘        CKEditor module that could cause    
                     the regression                    
     This landed in XWiki 17.5.0 (the regression boundary is between 17.4.0 and 17.5.0).                     [✓] Find the specific commit and        
                     Jira issue that introduced the      
     Mechanism of the Regression                     regression                    
                     [•] Propose a fix plan                  
     The bug occurs through the following chain:                    
                    
     1. cleanupEditables was added (plugin.js:814-821): When updating a macro widget, this method removes inplace editable DOM elements from the widget if showInlineEditableParameters is true (which is the default). This happens before widget.setData(data).                    
                    
     2. The xwiki-refresh server round-trip (plugin.js:391-416): After macro insertion, ALL editor content is sent to the server for a rendering round-trip: editor.getData() → server converts HTML→wiki syntax→HTML → editor.setData(html).                    
                    
     3. Computed fields have no storage (ComputedFieldClass.java:132-136): fromString() returns null, and displayHidden() is empty. The computed field content shown in the editor is the rendered output of a script, not stored wiki content.                    
                    
     4. The content loss happens during the refresh round-trip: When the editor content (which includes the rendered computed field HTML) goes through editor.getData() → server conversion → editor.setData(), the server re-renders everything. The computed field's rendered                    
     output is treated as regular wiki syntax content, and if it doesn't cleanly round-trip through the HTML→wiki→HTML conversion, the content is lost or replaced with empty/different content.                    
                    
     Key Files                    
                    
     - xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-macro/plugin.js — cleanupEditables (line 814), xwiki-refresh command (line 391), insertOrUpdateMacroWidget (line 737)                    
     - xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-source/plugin.js — convertHTML server round-trip                    
     - xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/objects/classes/ComputedFieldClass.java — displayEdit calls displayView, displayHidden is empty                    
{
quote noformat }

Fix plan:

{
quote noformat }
Fix Plan                     editor causes content loss in       
                     computed fields when adding a       
     Option A (Targeted fix — recommended): Protect computed field content during the xwiki-refresh round-trip.                     macro                    
                     [✓] Search for related commits in       
     1. Identify computed field boundaries in the editor HTML: When the editor is used on a page with computed fields, the computed field content is rendered inside specific DOM elements (typically within form field containers). Add data attributes or markers to identify         CKEditor module that could cause    
     computed field content during editing.                     the regression                    
                     [✓] Find the specific commit and        
     2. Preserve computed field content during refresh: In the xwiki-refresh command (plugin.js:391-416), before calling editor.getData(), save the computed field content. After editor.setData(html), restore the saved computed field content, preventing the server round-          Jira issue that introduced the      
     trip from overwriting it.                     regression                    
                     [•] Propose a fix plan                  
     3. Alternative approach: Instead of modifying the refresh command, make the downcast function aware of computed fields so it can preserve them during the getData() → server → setData() cycle. This could be done by wrapping computed field content in special markers                    
     that survive the round-trip.                    
                    
     Option B (Minimal fix): Skip the xwiki-refresh for computed fields.                    
                    
     1. In insertOrUpdateMacroWidget (plugin.js:808-811), the xwiki-refresh command is triggered with a setTimeout. Before this refresh, check if the editor content includes computed field areas. If so, either skip the refresh or handle it differently for those areas.                    
                    
     2. The computed field content could be marked with CSS classes or data attributes by ComputedFieldClass.displayEdit() so the JS can detect and preserve it.                    
                    
     Option C (Server-side fix): Ensure the HTML converter handles computed field output correctly.                    
                    
     1. Modify the CKEditor.HTMLConverter or the underlying rendering pipeline to properly handle the HTML output of computed fields during the HTML→wiki→HTML round-trip. This would ensure the content survives the conversion.                    
                    
     Recommended Approach                    
                    
     Option A is recommended because:                    
     - It addresses the root cause (content loss during round-trip) directly in the CKEditor plugin                    
     - It doesn't require changes to the rendering pipeline or server-side code                    
     - It's consistent with how nested editables are already handled (their content is preserved during refresh)                    
                    
     The fix should:                    
     1. Add a marker (e.g., data-xwiki-computed-field) to the computed field's rendered HTML in ComputedFieldClass.displayEdit()                    
     2. In the xwiki-refresh command, extract and preserve the marked content before the server round-trip                    
     3. After editor.setData(), restore the preserved computed field content                    
                    
     Verification                    
                    
     To bisect and confirm: compare behavior between tags xwiki-platform-17.4.0 (before XWIKI-23043) and xwiki-platform-17.5.0 (after). The regression should be reproducible starting from 17.5.0.                    
{
quote noformat }