dotCMS / dotCMS/core

Block Editor: Add a caption field to image properties

Open
#37,496 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotCMS: Block Editor Team : Scout Type : Task
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Description

Add a caption field to the image properties dialog in the Block Editor (libs/new-block-editor), persist it as a new attribute on the dotImage node, and render it as a <figcaption> across every renderer.

Today the dialog exposes three fields — Image URL (src), Tooltip (title) and Alt text (alt). There is no way to attach a visible caption to an image. title is the browser tooltip and must stay that way; the caption is a distinct, visible piece of content.

Current state (verified)
  • Dialog template: core-web/libs/new-block-editor/src/lib/editor/components/image-popover/image-popover.component.html — three controls, all bound to form.controls.{src,title,alt}.
  • Node: core-web/libs/new-block-editor/src/lib/editor/extensions/nodes/image.extension.tsDotImage already serializes to <figure> in both renderHTML() and addNodeView(), so <figcaption> has a natural place to live.
  • VTL renderer: dotCMS/src/main/webapp/WEB-INF/velocity/static/storyblock/dotImage.vtl — already emits a <figure> wrapper.
Design decision

A new caption node attribute, rendered as <figcaption> inside the existing <figure>. title keeps its current meaning (tooltip). No fallback from title to caption — they are independent fields.

Files in scope
File Change
.../components/image-popover/image-popover.component.html Add the Caption input
.../components/image-popover/image-popover.component.ts Add caption to the form group; read/write the node attr
.../extensions/nodes/image.extension.ts Add caption attribute with parseHTML / renderHTML; emit <figcaption> in renderHTML() and addNodeView()
dotCMS/src/main/webapp/WEB-INF/messages/Language.properties New keys: ...field.caption.label, ...field.caption.hint, ...field.caption.placeholder
dotCMS/src/main/webapp/WEB-INF/velocity/static/storyblock/dotImage.vtl Emit <figcaption> when caption is set
dotCMS/src/main/java/com/dotcms/tiptap/TiptapHtml.java Emit <figcaption>
dotCMS/src/main/java/com/dotcms/tiptap/TiptapMarkdown.java Emit the caption in Markdown output
core-web/libs/sdk/react/.../blocks/Image.tsx Render <figcaption>
core-web/libs/sdk/vue/.../blocks/DotImage.vue Render <figcaption>
core-web/libs/sdk/angular/.../blocks/image.component.ts Render <figcaption>
core-web/libs/sdk/angular/.../dotcms-block-editor-renderer-native.component.html Render <figcaption>
core-web/libs/sdk/types/src/lib/components/block-editor-renderer/internal.ts Add caption to the image attrs type

Acceptance Criteria

Editor — happy path

  • The image properties dialog shows a "Caption" text input below Alt text
  • Typing a caption and clicking Save persists it as the caption attribute on the dotImage node
  • A saved caption appears as visible text directly below the image in the editor canvas
  • Reopening the dialog on an image with a caption pre-populates the Caption input with the stored value
  • Clearing the Caption input and saving removes the caption text and the <figcaption> element from the image

Editor — field independence

  • Setting a caption does not change the title (tooltip) attribute
  • Setting a tooltip does not change the caption attribute
  • The Caption input is optional — saving with it empty succeeds and src remains the only required field

Persistence & round-trip

  • The stored contentlet JSON contains caption in the dotImage node's attrs
  • Copying an image with a caption and pasting it elsewhere in the document preserves the caption
  • parseHTML reads a caption back from a <figure><img><figcaption>…</figcaption></figure> structure

Renderers

  • VTL (dotImage.vtl) renders <figcaption> with the caption text when caption is set
  • VTL renders no <figcaption> element when caption is unset, empty, or the literal string "null"
  • React SDK block renderer renders <figcaption> with the caption text
  • Vue SDK block renderer renders <figcaption> with the caption text
  • Angular SDK block renderer (image.component.ts) renders <figcaption> with the caption text
  • Angular SDK native/semantic renderer renders <figcaption> with the caption text
  • TiptapHtml server-side HTML output includes the <figcaption>
  • TiptapMarkdown output includes the caption text

Layout interaction

  • A captioned image with textWrap set keeps the image-wrap-* figure class and the caption stays inside the wrapped figure
  • A captioned image with textAlign set keeps the image-align-* figure class
  • A captioned image wrapped in a link renders the <figcaption> outside the <a>, not inside it

Backward compatibility

  • Existing stored images with no caption attribute render exactly as they do today — no <figcaption>, no layout shift

Escaping

  • A caption containing <, >, &, or " is HTML-escaped in every renderer and does not inject markup

Tests

  • Unit specs in libs/new-block-editor/ cover the dialog field, node attribute round-trip, and <figcaption> serialization
  • SDK renderer specs updated for React, Vue, and both Angular renderers

Priority

Medium

Additional Context

  • Scope is libs/new-block-editor only. The legacy libs/block-editor is not in scope.
  • Related: the image resize ticket (#37495) touches the same node and the same renderer set — coordinate to avoid conflicting edits to image.extension.ts and dotImage.vtl.
  • Related: the message-key audit ticket (#37497) fixes the Tooltip field's misleading "Add a caption…" placeholder. That fix and this feature must land consistently — the tooltip placeholder must not say "caption" once a real Caption field exists.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the image popover files and image.extension.ts under core-web/libs/new-block-editor, then trace the existing figure output in dotImage.vtl. Review the listed Java and SDK renderer files and their existing unit specs. Done means caption is persisted, parsed, escaped, and rendered consistently across all listed renderers without changing tooltip behavior or unc captioned images.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, java, react, typescript
Domain
backend, content, frontend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.