Skip to content

Image widgets added inside a markdown widget field are not shown in preview #6785

@thecodemine

Description

@thecodemine

Describe the bug

No preview shown when adding an image in the markdown editor

To Reproduce

Steps to reproduce the behavior. For example:

  1. Go to 'markdown editor' (markdown widget)
  2. Click on 'add component' button
  3. Select 'Image'
  4. Choose an image to insert
  5. Add title and alt text for the image
  6. Note that no preview of the image is shown and warning shown in chrome developer tools. see below.
Chrome developer console shows the following warning
Sent invalid data to remark. Plugin: image. Value: ![alt text](/images/testing.jpg "testing"). Data: {"image":"/images/testing.jpg","alt":"alt text","title":"testing"}
(anonymous) @ netlify-cms-2.0.0.js:654
(anonymous) @ netlify-cms-2.0.0.js:646
e.exports @ netlify-cms-2.0.0.js:646
w.parse @ netlify-cms-2.0.0.js:639
O @ netlify-cms-2.0.0.js:54
t.markdownToHtml @ netlify-cms-2.0.0.js:54
render @ netlify-cms-2.0.0.js:658
Fa @ netlify-cms-2.0.0.js:188
Na @ netlify-cms-2.0.0.js:188
gs @ netlify-cms-2.0.0.js:188
ul @ netlify-cms-2.0.0.js:188
sl @ netlify-cms-2.0.0.js:188
Js @ netlify-cms-2.0.0.js:188
(anonymous) @ netlify-cms-2.0.0.js:188
t.unstable_runWithPriority @ netlify-cms-2.0.0.js:196
qi @ netlify-cms-2.0.0.js:188
Vi @ netlify-cms-2.0.0.js:188
$i @ netlify-cms-2.0.0.js:188
el @ netlify-cms-2.0.0.js:188
notify @ netlify-cms-2.0.0.js:28
notifyNestedSubs @ netlify-cms-2.0.0.js:28
i @ netlify-cms-2.0.0.js:28
v @ netlify-cms-2.0.0.js:48
(anonymous) @ netlify-cms-2.0.0.js:75
(anonymous) @ netlify-cms-2.0.0.js:220
n.<computed> @ netlify-cms-2.0.0.js:28
(anonymous) @ netlify-cms-2.0.0.js:280
onChange @ netlify-cms-2.0.0.js:280
onChange @ netlify-cms-2.0.0.js:298
(anonymous) @ netlify-cms-2.0.0.js:631
y @ netlify-cms-2.0.0.js:48
x @ netlify-cms-2.0.0.js:48
w @ netlify-cms-2.0.0.js:48
setTimeout (async)
b @ netlify-cms-2.0.0.js:48
k @ netlify-cms-2.0.0.js:48
(anonymous) @ netlify-cms-2.0.0.js:631
value @ netlify-cms-2.0.0.js:58
n @ netlify-cms-2.0.0.js:58
value @ netlify-cms-2.0.0.js:16
(anonymous) @ netlify-cms-2.0.0.js:16
Promise.then (async)
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
tt.setData @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
(anonymous) @ netlify-cms-2.0.0.js:16
Ve.withoutSaving @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
Ve.save @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
(anonymous) @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
Ge.select @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
(anonymous) @ netlify-cms-2.0.0.js:16
Ve.withoutMerging @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
Ge.snapshotSelection @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
deleteAtRange @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
deleteBackwardAtRange @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
deleteCharBackwardAtRange @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
_t.deleteCharBackward @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
t @ netlify-cms-2.0.0.js:16
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
r @ netlify-cms-2.0.0.js:16
onKeyDown @ netlify-cms-2.0.0.js:58
u @ netlify-cms-2.0.0.js:16
onKeyDown @ netlify-cms-2.0.0.js:58
u @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:16
value @ netlify-cms-2.0.0.js:58
onEvent @ netlify-cms-2.0.0.js:58
value @ netlify-cms-2.0.0.js:58
r.handlers.Re.reduce.e.<computed> @ netlify-cms-2.0.0.js:58
s @ netlify-cms-2.0.0.js:188
p @ netlify-cms-2.0.0.js:188
(anonymous) @ netlify-cms-2.0.0.js:188
v @ netlify-cms-2.0.0.js:188
at @ netlify-cms-2.0.0.js:188
it @ netlify-cms-2.0.0.js:188
st @ netlify-cms-2.0.0.js:188
pt @ netlify-cms-2.0.0.js:188
N @ netlify-cms-2.0.0.js:188
U @ netlify-cms-2.0.0.js:188
Zt @ netlify-cms-2.0.0.js:188
Xt @ netlify-cms-2.0.0.js:188
t.unstable_runWithPriority @ netlify-cms-2.0.0.js:196
qi @ netlify-cms-2.0.0.js:188
L @ netlify-cms-2.0.0.js:188
Yt @ netlify-cms-2.0.0.js:188

Expected behavior

images (image widgets) added inline should be shown in the preview

Screenshots

image

Applicable Versions:

  • Netlify CMS version: 2.10.192
  • Git provider: GitHub
  • OS: Pop!_OS 22.04 LTS
  • Browser version: Version 112.0.5615.165 (Official Build) (64-bit)
  • Node.JS version: v16.13.0

CMS configuration

config.yml
locale: 'sv'
publish_mode: editorial_workflow
display_url: https://redacted.com
backend:
  name: github
  repo: redacted/redacted.com
  branch: main # Branch to update (optional; defaults to master)
  base_url: https://redacted.com
  auth_endpoint: /api/auth
media_folder: src/images
public_folder: /images
collections:
  - name: 'config'
    label: 'konfiguration'
    files: 
      - name: 'contact_form'
        label: 'Kontakt formulär'
        file: 'src/_data/contact_form.json'
        widget: "object"
        fields: 
          - name: sv
            widget: list 
            fields: 
              - { name: subject, widget: string }
              - { name: email, widget: string }
          - name: en
            widget: list 
            fields: 
              - { name: subject, widget: string }
              - { name: email, widget: string }
          - name: default
            widget: list 
            fields: 
              - { name: subject, widget: string }
              - { name: email, widget: string } 
            
  - name: 'blog-swedish' 
    label: 'Blogginlägg (svenska)'
    folder: 'src/pages/_cms_content'
    create: true
    filter: {field: "language", value: "sv"}
    summary: '{{day}}/{{month}}/{{year}} {{hour}}:{{minute}} | {{title}}' # optional summary for a tree node, defaults to the inferred title field
    view_groups:
      - label: År
        field: date
        # groups items based on the value matched by the pattern
        pattern: \d{4}
    view_filters:
      - label: Utkast
        field: draft
        pattern: true
    slug: '{{slug}}'
    editor:
      preview: true
    nested:
      depth: 100 # max depth to show in the collection tree
      summary: '{{title}}' # optional summary for a tree node, defaults to the inferred title field
    fields:
      - { label: 'Language', name: 'language', widget: 'hidden', default: 'sv' }
      - { label: 'Datum', name: 'date', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ",  hint: 'Datum som visar när inlägget gjordes. Om datumet och tiden är i framtiden
    kommer inlägget att släppas ut på siten först vid den tiden.' }
      - { label: 'Utkast', name: 'draft', widget: 'boolean', default: true, hint: 'Inlägget kommer inte att visas på sidan även fast det är publicerat.' }
      - { label: 'Visa i flödet', name: 'show_in_flow', widget: 'boolean', default: true, hint: 'Inlägget visas i flödet på hemsidan.' }
      - { label: 'Visa som prioriterat tills', name: 'sticky_until', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ", hint: 'Inlägget visas högst upp i flödet på hemsidan tills denna tidpunkt.' }
      - { label: "Huvudbild", name: "image", widget: "image", required: false, choose_url: true, allow_multiple: false, hint: 'Bild som visas högst upp i inlägget och då det visas i flödet på hemsidan. Använd t.ex. **[Squoosh.app](http://squoosh.app)** för att se till att bilden är lagom stor innan du laddar upp den.' }
      - { label: 'Titel', name: 'title', widget: 'string', hint: 'Sidans titel som visas i inläggets intro och då det visas i flödet på sidan.' }
      - { label: 'Beskrivning', name: 'short_description', widget: 'string', required: false, hint: 'Kort beskrivning av inlägget då det visas i flödet på sidan.' }
      - { label: 'Sidinnehåll', name: 'body', widget: 'markdown', sanitize_preview: true, hint: 'Sidans innehåll, Se t.ex. **[markdown cheat-sheet](/markdown-cheat-sheet)** för exempel.' }
      - { label: "Taggar", name: "tags", widget: "list", required: false, hint: 'taggar som beskriver innehållet' }
    meta: { path: { widget: string, label: 'Path', index_file: 'index',  default: "/{{year}/{{month}}/{{}}"} }

  - name: 'blog-english' 
    label: 'Blogginlägg (engelska)'
    folder: 'src/pages/_cms_content/en'
    create: true
    filter: {field: "language", value: "en"}
    summary: '{{day}}/{{month}}/{{year}} {{hour}}:{{minute}} | {{title}}' # optional summary for a tree node, defaults to the inferred title field
    view_groups:
      - label: År
        field: date
        # groups items based on the value matched by the pattern
        pattern: \d{4}
    view_filters:
      - label: Utkast
        field: draft
        pattern: true
    slug: '{{slug}}'
    editor:
      preview: true
    nested:
      depth: 100 # max depth to show in the collection tree
      summary: '{{title}}' # optional summary for a tree node, defaults to the inferred title field
    fields:
      - { label: 'Language', name: 'language', widget: 'hidden', default: 'en' }
      - { label: 'Datum', name: 'date', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ",  hint: 'Datum som visar när inlägget gjordes. Om datumet och tiden är i framtiden
    kommer inlägget att släppas ut på siten först vid den tiden.' }
      - { label: 'Utkast', name: 'draft', widget: 'boolean', default: true, hint: 'Inlägget kommer inte att visas på sidan även fast det är publicerat.' }
      - { label: 'Visa i flödet', name: 'show_in_flow', widget: 'boolean', default: true, hint: 'Inlägget visas i flödet på hemsidan.' }
      - { label: 'Visa som prioriterat tills', name: 'sticky_until', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ", hint: 'Inlägget visas högst upp i flödet på hemsidan tills denna tidpunkt.' }
      - { label: "Huvudbild", name: "image", widget: "image", required: false, choose_url: true, allow_multiple: false, hint: 'Bild som visas högst upp i inlägget och då det visas i flödet på hemsidan. Använd t.ex. **[Squoosh.app](http://squoosh.app)** för att se till att bilden är lagom stor innan du laddar upp den.' }
      - { label: 'Titel', name: 'title', widget: 'string', hint: 'Sidans titel som visas i inläggets intro och då det visas i flödet på sidan.' }
      - { label: 'Beskrivning', name: 'short_description', widget: 'string', required: false, hint: 'Kort beskrivning av inlägget då det visas i flödet på sidan.' }
      - { label: 'Sidinnehåll', name: 'body', widget: 'markdown', sanitize_preview: true, hint: 'Sidans innehåll, Se t.ex. **[markdown cheat-sheet](/markdown-cheat-sheet)** för exempel.' }
      - { label: "Taggar", name: "tags", widget: "list", required: false, hint: 'taggar som beskriver innehållet' }

  - name: 'blog-german' 
    label: 'Blogginlägg (tyska)'
    folder: 'src/pages/_cms_content/de'
    create: true
    filter: {field: "language", value: "de"}
    summary: '{{day}}/{{month}}/{{year}} {{hour}}:{{minute}} | {{title}}' # optional summary for a tree node, defaults to the inferred title field
    view_groups:
      - label: År
        field: date
        # groups items based on the value matched by the pattern
        pattern: \d{4}
    view_filters:
      - label: Utkast
        field: draft
        pattern: true
    slug: '{{slug}}'
    editor:
      preview: true
    nested:
      depth: 100 # max depth to show in the collection tree
      summary: '{{title}}' # optional summary for a tree node, defaults to the inferred title field
    fields:
      - { label: 'Language', name: 'language', widget: 'hidden', default: 'de' }
      - { label: 'Datum', name: 'date', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ",  hint: 'Datum som visar när inlägget gjordes. Om datumet och tiden är i framtiden
    kommer inlägget att släppas ut på siten först vid den tiden.' }
      - { label: 'Utkast', name: 'draft', widget: 'boolean', default: true, hint: 'Inlägget kommer inte att visas på sidan även fast det är publicerat.' }
      - { label: 'Visa i flödet', name: 'show_in_flow', widget: 'boolean', default: true, hint: 'Inlägget visas i flödet på hemsidan.' }
      - { label: 'Visa som prioriterat tills', name: 'sticky_until', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ", hint: 'Inlägget visas högst upp i flödet på hemsidan tills denna tidpunkt.' }
      - { label: "Huvudbild", name: "image", widget: "image", required: false, choose_url: true, allow_multiple: false, hint: 'Bild som visas högst upp i inlägget och då det visas i flödet på hemsidan. Använd t.ex. **[Squoosh.app](http://squoosh.app)** för att se till att bilden är lagom stor innan du laddar upp den.' }
      - { label: 'Titel', name: 'title', widget: 'string', hint: 'Sidans titel som visas i inläggets intro och då det visas i flödet på sidan.' }
      - { label: 'Beskrivning', name: 'short_description', widget: 'string', required: false, hint: 'Kort beskrivning av inlägget då det visas i flödet på sidan.' }
      - { label: 'Sidinnehåll', name: 'body', widget: 'markdown', sanitize_preview: true, hint: 'Sidans innehåll, Se t.ex. **[markdown cheat-sheet](/markdown-cheat-sheet)** för exempel.' }
      - { label: "Taggar", name: "tags", widget: "list", required: false, hint: 'taggar som beskriver innehållet' }

  - name: 'blog-finnish' 
    label: 'Blogginlägg (finska)'
    folder: 'src/pages/_cms_content/fi'
    create: true
    filter: {field: "language", value: "fi"}
    summary: '{{day}}/{{month}}/{{year}} {{hour}}:{{minute}} | {{title}}' # optional summary for a tree node, defaults to the inferred title field
    view_groups:
      - label: År
        field: date
        # groups items based on the value matched by the pattern
        pattern: \d{4}
    view_filters:
      - label: Utkast
        field: draft
        pattern: true
    slug: '{{slug}}'
    editor:
      preview: true
    nested:
      depth: 100 # max depth to show in the collection tree
      summary: '{{title}}' # optional summary for a tree node, defaults to the inferred title field
    fields:
      - { label: 'Language', name: 'language', widget: 'hidden', default: 'fi' }
      - { label: 'Datum', name: 'date', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ",  hint: 'Datum som visar när inlägget gjordes. Om datumet och tiden är i framtiden
    kommer inlägget att släppas ut på siten först vid den tiden.' }
      - { label: 'Utkast', name: 'draft', widget: 'boolean', default: true, hint: 'Inlägget kommer inte att visas på sidan även fast det är publicerat.' }
      - { label: 'Visa i flödet', name: 'show_in_flow', widget: 'boolean', default: true, hint: 'Inlägget visas i flödet på hemsidan.' }
      - { label: 'Visa som prioriterat tills', name: 'sticky_until', widget: 'datetime', date_format: "DD.MM.YYYY", time_format: "HH:mm", format: "YYYY-MM-DDTHH:mmZ", hint: 'Inlägget visas högst upp i flödet på hemsidan tills denna tidpunkt.' }
      - { label: "Huvudbild", name: "image", widget: "image", required: false, choose_url: true, allow_multiple: false, hint: 'Bild som visas högst upp i inlägget och då det visas i flödet på hemsidan. Använd t.ex. **[Squoosh.app](http://squoosh.app)** för att se till att bilden är lagom stor innan du laddar upp den.' }
      - { label: 'Titel', name: 'title', widget: 'string', hint: 'Sidans titel som visas i inläggets intro och då det visas i flödet på sidan.' }
      - { label: 'Beskrivning', name: 'short_description', widget: 'string', required: false, hint: 'Kort beskrivning av inlägget då det visas i flödet på sidan.' }
      - { label: 'Sidinnehåll', name: 'body', widget: 'markdown', sanitize_preview: true, hint: 'Sidans innehåll, Se t.ex. **[markdown cheat-sheet](/markdown-cheat-sheet)** för exempel.' }
      - { label: "Taggar", name: "tags", widget: "list", required: false, hint: 'taggar som beskriver innehållet' }

Additional context

By modifying the markdown manually, after adding the image widget, you can force the image to show up in the preview (of course the image widget will no longer be shown in the rich text view)

before

There is no character before or after the image - and no image is in the preview

![alt text](/images/testing.jpg "testing")

after

There is a whitespace before the image (could be any character) -and image is shown in preview

 ![alt text](/images/testing.jpg "testing")

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions