Skip to content

Workflow fire: convert Block Editor HTML/Markdown to ProseMirror JSON on save (server-side) #36002

Description

@fmontes

Description

Today, when content is created or updated through the workflow fire endpoints (/api/v1/workflow/actions/**/fire, firemultipart, bulk fire), a Story Block (Block Editor) field value is stored in the database exactly as sent. If a client sends HTML or Markdown instead of a Tiptap/ProseMirror JSON document, dotCMS persists that raw string. The conversion to the proper ProseMirror object only happens later, client-side, when a human opens the contentlet in the editor and re-saves it.

This is a problem for non-interactive/automated content creation (AI agents via the MCP server, headless imports, migrations): the content looks broken to any consumer that reads the field as ProseMirror JSON (GraphQL, REST, SDK renderers) until a person manually opens and re-saves each contentlet.

What we want

On the workflow fire path, when a Story Block field's incoming value is HTML or Markdown (not already a valid Tiptap JSON document), the backend should convert it to a Tiptap/ProseMirror JSON object server-side and store that, so no human editor round-trip is required.

Why this is now feasible

PR #35728 (issue #35727) adds com.dotcms.tiptap.TiptapMarkdown, a bidirectional Tiptap-JSON ⇄ Markdown converter at the Java level — including the Markdown → Tiptap JSON direction (via commonmark-java). This provides the conversion primitive needed to do the transform during content save. This issue is about wiring that converter into the fire/save path.

Related work

Depends on #35728 being merged (or its TiptapMarkdown converter being available).

Acceptance Criteria

  • On the workflow fire endpoints, a Story Block field value supplied as Markdown is converted to a valid Tiptap/ProseMirror JSON document and stored as such.
  • The same applies to a value supplied as HTML.
  • A value that is already valid Tiptap/ProseMirror JSON is detected and stored unchanged (no double-conversion).
  • After firing with Markdown/HTML, the field reads back as structured ProseMirror JSON via GraphQL/REST/SDK without any human opening and re-saving the contentlet.
  • Conversion never throws on unknown/extended nodes or marks (consistent with the graceful-degradation behavior in feat(tiptap): convert Story Block content to Markdown (#35727) #35728).
  • Covered by tests (Markdown→stored-JSON and HTML→stored-JSON through the fire endpoint).

Priority

Medium

Additional Context

Once this lands, the MCP server's existing guidance (telling agents to send HTML/Markdown for Block Editor fields) becomes fully correct with no human follow-up step. The fire endpoints already document that Block Editor fields accept HTML/Markdown.

Metadata

Metadata

Assignees

No fields configured for Feature.

Projects

Status
New

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions