Skip to content

Commit 2be7e37

Browse files
gjulivangjulivan
authored andcommitted
chore: update events icons warnings dialogs preview
1 parent a781546 commit 2be7e37

22 files changed

Lines changed: 2625 additions & 2310 deletions

File tree

packages/pluggableWidgets/rich-text-web/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1616

1717
### Fixed
1818

19+
- We fixed Tiptap duplicate extension warnings for `link`, `textStyle`, `underline`, and `textDirection` by properly configuring StarterKit, removing redundant extension registrations in TextColorClass, memoizing the extensions array to prevent re-registration on component re-renders, and disabling the core TextDirection extension that conflicts with our custom implementation.
20+
21+
- We fixed an issue where empty editor content was saving as `<p></p>` instead of an empty string, which incorrectly passed required field validation. Empty content now correctly saves as `""`, ensuring proper validation behavior. Note: This is a breaking change for forms that were relying on the incorrect behavior - required RichText fields will now correctly reject empty content.
22+
1923
- We fixed an issue where the editor pasting back the whole sentence instead of the single copied word
2024

2125
### Changed

packages/pluggableWidgets/rich-text-web/e2e/RichText.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,40 @@ test.describe("RichText", () => {
166166
`richTextDialogInsidePopupEdit.png`
167167
);
168168
});
169+
170+
test("empty content persists as empty string, not <p></p>", async ({ page }) => {
171+
await page.goto("/");
172+
await waitForMendixApp(page);
173+
await page.click("text=Generate Data");
174+
await page.goto("/p/basic");
175+
await waitForMendixApp(page);
176+
177+
// Find the first editable rich text editor
178+
const editor = page.locator(".mx-name-richText1 .tiptap");
179+
await editor.scrollIntoViewIfNeeded();
180+
await expect(editor).toBeVisible();
181+
182+
// Click into the editor and clear all content
183+
await editor.click();
184+
await page.keyboard.press("Control+A");
185+
await page.keyboard.press("Backspace");
186+
187+
// Blur the editor to trigger save
188+
await page.keyboard.press("Tab");
189+
await page.waitForTimeout(500);
190+
191+
// The editor should now be empty (visual check)
192+
const textContent = await editor.textContent();
193+
expect(textContent?.trim() || "").toBe("");
194+
195+
// Reload the page to verify persistence
196+
await page.reload();
197+
await waitForMendixApp(page);
198+
199+
// The editor should still be empty after reload
200+
const reloadedEditor = page.locator(".mx-name-richText1 .tiptap");
201+
await expect(reloadedEditor).toBeVisible();
202+
const reloadedContent = await reloadedEditor.textContent();
203+
expect(reloadedContent?.trim() || "").toBe("");
204+
});
169205
});
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Normalize Empty Content
2+
3+
**Status:** Proposed
4+
**Type:** Bug Fix
5+
**Impact:** Breaking (Validation behavior)
6+
**Effort:** ~3.5 hours
7+
8+
## Quick Summary
9+
10+
Fix the rich text editor to save empty content as `""` instead of `<p></p>`, ensuring correct validation and consistent data representation.
11+
12+
## Problem
13+
14+
When users delete all content, the editor currently saves `<p></p>` to the database. This breaks:
15+
16+
- Required field validation (incorrectly passes)
17+
- Empty checks (`if (value)` returns true)
18+
- Data consistency (semantically empty ≠ empty string)
19+
20+
## Solution
21+
22+
Use Tiptap's `editor.isEmpty` property to return `""` when content is empty, and normalize comparison logic to treat `""` and `<p></p>` as equivalent.
23+
24+
## Files
25+
26+
- [`proposal.md`](./proposal.md) - Problem statement, scope, and impact
27+
- [`design.md`](./design.md) - Technical design, decisions, and architecture
28+
- [`tasks.md`](./tasks.md) - Implementation checklist and effort estimate
29+
30+
## Key Decisions
31+
32+
1. **Trust Tiptap's isEmpty** - Use built-in check, no custom logic
33+
2. **Normalize at persistence** - Convert to `""` when saving, not loading
34+
3. **Lazy migration** - Existing `<p></p>` records normalize on next edit
35+
4. **No version bump** - This Tiptap version is unreleased
36+
37+
## Changes Required
38+
39+
### Editor.tsx (line 237-240)
40+
41+
```typescript
42+
// Before:
43+
const html = editor.getHTML();
44+
45+
// After:
46+
const html = editor.isEmpty ? "" : editor.getHTML();
47+
```
48+
49+
### EditorWrapper.tsx (line 48-60)
50+
51+
```typescript
52+
// Add normalization in comparison:
53+
const normalizeEmpty = (val?: string) => (!val || val === "<p></p>" ? "" : val);
54+
55+
const current = normalizeEmpty(stringAttribute.value);
56+
const incoming = normalizeEmpty(html);
57+
if (current !== incoming) {
58+
stringAttribute.setValue(incoming);
59+
}
60+
```
61+
62+
## Testing
63+
64+
- ✓ Unit tests for empty content behavior
65+
- ✓ E2E test for persistence
66+
- ✓ Manual validation testing
67+
68+
## Breaking Change
69+
70+
**Required field validation will now correctly reject empty content.**
71+
72+
Previously: `<p></p>` passed validation ❌
73+
After fix: `""` fails validation ✓
74+
75+
This is desired behavior (bug fix), but may affect existing forms.
76+
77+
## Next Steps
78+
79+
1. Review proposal and design
80+
2. Approve or request changes
81+
3. Implement following tasks.md
82+
4. Test thoroughly
83+
5. Update CHANGELOG
84+
6. Merge to main branch

0 commit comments

Comments
 (0)