Conversation
…perty in dependencies
…rom @demshy - Applied implementation from https://github.com/poslovnimediji/decap-cms/tree/widget-richtext - Based on PR decaporg#7162
e9f1eb6 to
a418dc0
Compare
… into widget-richtext
- pass voidCodeBlock to serializers - change elements for rendering paragraphs and headings
|
Tables are not rendered in rich text mode as they are in the markdown widget. Screen.Recording.2025-12-10.at.15.17.32.mov |
…and strikethrough
… into widget-richtext
* feat: add table preview in visual editor * fix: format
There was a problem hiding this comment.
Pull request overview
This PR introduces a new richtext widget package (based on Plate) and wires it into the app/preview pipeline as an experimental alternative to the existing markdown widget.
Changes:
- Added
decap-cms-widget-richtextpackage: control/editor UI, serializers (Markdown/HTML/Slate), and unit tests. - Integrated richtext widget into the app registry and preview context (passes
getEditorComponentsthrough preview). - Added/updated dev-test and Cypress e2e coverage to exercise richtext behavior.
Reviewed changes
Copilot reviewed 89 out of 91 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Switch TS module settings to NodeNext and add a path alias for decap-cms-ui-default. |
| packages/decap-cms-widget-richtext/webpack.config.js | Adds webpack config for the new widget package. |
| packages/decap-cms-widget-richtext/test-helpers/h.js | Slate hyperscript helper for serializer tests. |
| packages/decap-cms-widget-richtext/src/styles.js | Shared richtext editor styling primitives. |
| packages/decap-cms-widget-richtext/src/serializers/slateRemark.js | Slate→MDAST serializer port/adaptation. |
| packages/decap-cms-widget-richtext/src/serializers/remarkWrapHtml.js | Remark plugin to wrap top-level html nodes. |
| packages/decap-cms-widget-richtext/src/serializers/remarkStripTrailingBreaks.js | Remark plugin to remove trailing breaks. |
| packages/decap-cms-widget-richtext/src/serializers/remarkSquashReferences.js | Squashes link/image references to inline forms. |
| packages/decap-cms-widget-richtext/src/serializers/remarkSlate.js | MDAST→Slate serializer with mark/text normalization. |
| packages/decap-cms-widget-richtext/src/serializers/remarkShortcodes.js | Parses and stringifies editor-component shortcodes. |
| packages/decap-cms-widget-richtext/src/serializers/remarkRehypeShortcodes.js | Prepares shortcode previews for remark→rehype conversion. |
| packages/decap-cms-widget-richtext/src/serializers/remarkPaddedLinks.js | Fixes padded link text edge cases. |
| packages/decap-cms-widget-richtext/src/serializers/remarkImagesToText.js | Converts certain image nodes to text for shortcode matching. |
| packages/decap-cms-widget-richtext/src/serializers/remarkEscapeMarkdownEntities.js | Escapes markdown entities in non-markdown-aware text. |
| packages/decap-cms-widget-richtext/src/serializers/remarkAssertParents.js | Unwraps invalid MDAST nesting from pasted HTML. |
| packages/decap-cms-widget-richtext/src/serializers/remarkAllowHtmlEntities.js | Prevents HTML entity decoding during remark parsing. |
| packages/decap-cms-widget-richtext/src/serializers/rehypePaperEmoji.js | Replaces Paper emoji images with actual emoji chars. |
| packages/decap-cms-widget-richtext/src/serializers/regexHelper.js | Shared regex utilities for serializer plugins. |
| packages/decap-cms-widget-richtext/src/serializers/index.js | Serializer orchestration for markdown↔slate↔html. |
| packages/decap-cms-widget-richtext/src/serializers/tests/slate.spec.js | Slate serializer test suite. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkStripTrailingBreaks.spec.js | Tests for stripping trailing breaks. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkSlate.spec.js | Tests for mergeAdjacentTexts. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkShortcodes.spec.js | Tests for shortcode parsing/tokenization helpers. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkPlugins.spec.js | Verifies remark plugins are applied in pipelines. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkPaddedLinks.spec.js | Tests padded-link normalization. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkEscapeMarkdownEntities.spec.js | Tests markdown entity escaping. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkAssertParents.spec.js | Tests invalid-nesting unwrapping. |
| packages/decap-cms-widget-richtext/src/serializers/tests/remarkAllowHtmlEntities.spec.js | Tests entity decoding behavior. |
| packages/decap-cms-widget-richtext/src/serializers/tests/index.spec.js | Serializer integration tests with fixtures. |
| packages/decap-cms-widget-richtext/src/serializers/tests/commonmark.spec.js | CommonMark compliance suite (skipped). |
| packages/decap-cms-widget-richtext/src/serializers/tests/snapshots/remarkShortcodes.spec.js.snap | Jest snapshots for shortcode parsing tests. |
| packages/decap-cms-widget-richtext/src/serializers/tests/fixtures/duplicate_marks_github_issue_3280.md | Fixture for mark dedup regression. |
| packages/decap-cms-widget-richtext/src/schema.js | Widget config schema (buttons, modes, editor components). |
| packages/decap-cms-widget-richtext/src/index.js | Widget export/registration entrypoint. |
| packages/decap-cms-widget-richtext/src/tests/renderer.spec.js | Preview rendering tests for richtext widget output. |
| packages/decap-cms-widget-richtext/src/RichtextPreview.js | Preview component (markdown→html + optional sanitization). |
| packages/decap-cms-widget-richtext/src/RichtextControl/withProps.js | Helper to extend components with default props/ref forwarding. |
| packages/decap-cms-widget-richtext/src/RichtextControl/plugins/TablePlugin.js | Plate table element plugins. |
| packages/decap-cms-widget-richtext/src/RichtextControl/plugins/ShortcodePlugin.js | Plate shortcode (void element) plugin. |
| packages/decap-cms-widget-richtext/src/RichtextControl/plugins/ExtendedBlockquotePlugin.js | Custom blockquote behavior for Enter/Backspace. |
| packages/decap-cms-widget-richtext/src/RichtextControl/mergeMediaConfig.js | Merges media config into image editor components. |
| packages/decap-cms-widget-richtext/src/RichtextControl/linkHandler.js | Handles link insertion/removal via prompt + Plate APIs. |
| packages/decap-cms-widget-richtext/src/RichtextControl/editorContext.js | Context provider for editor control + editor components. |
| packages/decap-cms-widget-richtext/src/RichtextControl/defaultEmptyBlock.js | Creates default empty paragraph block. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/index.js | Toolbar barrel export. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/ToolbarButton.js | Toolbar button UI component. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/Toolbar.js | Main toolbar with marks/blocks/lists/components + mode toggle. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/MarkToolbarButton.js | Mark button glue for Plate toolbar hooks. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/ListToolbarButton.js | List button glue for Plate list hooks. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/LinkToolbarButton.js | Link button glue + prompt handler. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/HeadingToolbarButton.js | Heading dropdown selector + block toggling. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/EditorComponentsToolbarButton.js | Dropdown to insert editor-component shortcodes. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Toolbar/BlockquoteToolbarButton.js | Blockquote toggle button behavior. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Leaf/CodeLeaf.js | Code mark rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/TableRowElement.js | Table row rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/TableElement.js | Table rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/TableCellElement.js | Table cell rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/ShortcodeElement.js | Renders embedded editor components as void blocks with nested widget UI. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/ParagraphElement.js | Paragraph rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/ListElement.js | List/list-item rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/LinkElement.js | Link element rendering for Plate. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/HeadingElement.js | Heading rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/BlockquoteElement.js | Blockquote rendering. |
| packages/decap-cms-widget-richtext/src/RichtextControl/components/Editor.js | PlateContent wrapper/editor surface. |
| packages/decap-cms-widget-richtext/src/RichtextControl/tests/parser.spec.js | Markdown→Slate parser snapshot tests. |
| packages/decap-cms-widget-richtext/src/RichtextControl/tests/snapshots/parser.spec.js.snap | Snapshot output for parser tests. |
| packages/decap-cms-widget-richtext/src/RichtextControl/tests/VisualEditor.spec.js | Tests media config merging. |
| packages/decap-cms-widget-richtext/src/RichtextControl/VisualEditor.js | Plate-based visual editor implementation. |
| packages/decap-cms-widget-richtext/src/RichtextControl/RawEditor.js | “Raw markdown” mode editor implementation. |
| packages/decap-cms-widget-richtext/src/RichtextControl.js | Richtext widget control (mode switching, focus handling). |
| packages/decap-cms-widget-richtext/package.json | New package manifest for richtext widget. |
| packages/decap-cms-widget-richtext/README.md | Placeholder README. |
| packages/decap-cms-widget-object/src/ObjectPreview.js | Normalizes non-Immutable field prop to Immutable. |
| packages/decap-cms-widget-markdown/src/serializers/index.js | Adds debug logging to markdown widget serialization. |
| packages/decap-cms-widget-markdown/src/MarkdownControl/renderers.js | Adjusts table cell border styling. |
| packages/decap-cms-core/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js | Passes getEditorComponents into preview props. |
| packages/decap-cms-core/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js | Adds propTypes entry for getEditorComponents. |
| packages/decap-cms-app/src/extensions.js | Registers the new richtext widget in the app. |
| package.json | Adds eslint-import-resolver-exports dev dependency. |
| dev-test/index.html | Adds dev-test editor components and renders both richtext + markdown fields. |
| dev-test/config.yml | Switches dev-test body field to richtext and adds markdown comparison fields. |
| cypress/plugins/index.js | Adds a task to rewrite config to use richtext widget. |
| cypress/e2e/richtext_widget_marks_spec.js | E2E test for code mark + nested marks in richtext. |
| cypress/e2e/richtext_widget_link_spec.js | E2E tests for link creation + raw-mode output. |
| cypress/e2e/richtext_widget_hotkeys_spec.js | E2E tests for hotkeys in richtext. |
| cypress/e2e/richtext_widget_enter_spec.js | E2E tests for Enter behavior in richtext. |
| cypress/e2e/richtext_widget_code_block_spec.js | E2E test for code block insertion + raw output. |
| cypress/e2e/richtext_widget_backspace_spec.js | E2E tests for Backspace behavior in richtext. |
| .eslintrc.js | Adds exports resolver config for eslint-import-resolver-exports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/decap-cms-widget-richtext/src/RichtextControl/plugins/ExtendedBlockquotePlugin.js
Outdated
Show resolved
Hide resolved
yanthomasdev
left a comment
There was a problem hiding this comment.
This one is a really big PR, I've found a few things I am not sure about and I think there are a few things still TODO here. I left a few comments and suggestions based on what I found.
There's also conflicts with the branch I can't fix since I have no permission for some reason.
|
|
||
| const visualEditor = ( | ||
| <EditorProvider editorControl={editorControl} editorComponents={getEditorComponents()}> | ||
| <div className="cms-editor-visual" ref={this.processRef}> |
There was a problem hiding this comment.
this.processRef is not set so this will be undefined
There was a problem hiding this comment.
You're right, I removed it.
|
|
||
|  | ||
| `; | ||
| const html = await markdownToHtml(value); |
There was a problem hiding this comment.
If this is meant to test Markdown rendering, why is it being converted to HTML?
There was a problem hiding this comment.
The test are (almost) the same as on markdown widget to make sure it's backward-compatible. The preview component actially renders HTML instead of markdown, so a conversion must happen beforehand.
packages/decap-cms-widget-richtext/src/__tests__/renderer.spec.js
Outdated
Show resolved
Hide resolved
packages/decap-cms-widget-richtext/src/__tests__/renderer.spec.js
Outdated
Show resolved
Hide resolved
packages/decap-cms-widget-richtext/src/RichtextControl/components/Element/ListElement.js
Outdated
Show resolved
Hide resolved
packages/decap-cms-widget-richtext/src/RichtextControl/linkHandler.js
Outdated
Show resolved
Hide resolved
packages/decap-cms-widget-richtext/src/RichtextControl/VisualEditor.js
Outdated
Show resolved
Hide resolved
| function handleBlockClick() { | ||
| console.log('handleBlockClick'); | ||
| } |
There was a problem hiding this comment.
This part is still a TODO?
There was a problem hiding this comment.
It was a function in the markdown widget, but it's not needed here, so I removed it.
Co-authored-by: Yan <61414485+yanthomasdev@users.noreply.github.com>
Co-authored-by: Yan <61414485+yanthomasdev@users.noreply.github.com>
Summary
This is a work-in-progress PR that adds
richtext-widgetas a potential replacement for the markdown in one of the future releases. Discussion where I put some of my thoughts about this here: #6905Digging deeper, there might be another caveat that we haven't considered before - nesting block types (inside lists for example) might make the implementation much more difficult so I did not go down that road yet.
A very rough checklist:
I have copied serializers (and their tests) from the existing markdown widget and am updating them as I go. I copy the renderers one by one as I get to the plugin in question.
Once the basic implementation is done, I plan on going through the e2e tests and update what is needed on the code or tests side, depends on the specific situation.
Note that this is very much in progress but I'm happy of any feedback, especially from someone who dealt with Slate/Plate before.
Test plan
Checklist
Please add a
xinside each checkbox:A picture of a cute animal (not mandatory but encouraged)