Skip to content

[Feature]: Markdown import should keep image width and height #151

Description

@HMarzban

Problem statement

Settings → Import & export → Replace with a file reads Markdown and applies it with setContent. A line like:

![Three headings, three chatrooms, one page](/demo-assets/d1-idea.png)

becomes an image node with src and alt only. width and height stay empty.

The editor then paints the picture at IMAGE_LAYOUT_FALLBACK (320×240). On the desktop sheet that is about 39% of the 830px writing column, and it forces a 4:3 box onto 16:9 art.

This showed up while replacing /demo from PROPOSAL-demo/DEMO.md. The live local page stores every illustration at 830×467. The Markdown file cannot name that size, and the importer has no other place to read it from.

Alt works. ![alt](url) stores alt.

The italic line under the picture works. That is a following paragraph, not the image node.

The toolbar caption field does not. Common Markdown has no syntax for the node caption attribute. The local demo does not use that field (all 17 pictures have an empty caption). Out of scope here unless a later slice adds a Markdown convention for it.

HTML such as <img width="830" height="467"> is not a workaround today: the importer treats that tag as plain text.

Proposed solution

On Markdown import (and the Settings replace path that consumes it), an image with no width / height should land at a size that fills the writing column and keeps the picture's real aspect ratio.

A reader who imports DEMO.md should see the same column-width pictures they see on http://localhost:3000/demo, without dragging sixteen resize handles.

How we get the size is an implementation choice. Do not stamp a fixed 830×467 on every imported image: that squashes anything that is not 16:9.

Candidates to evaluate in the work, not to pick now:

  • After the image loads, commit naturalWidth / naturalHeight fitted to the editor column.
  • Teach the Markdown parse to keep width / height when the source can name them, if we add a syntax that marked actually emits.

Alternatives considered

  • Drag each picture to the sheet edge after import. Works. Does not scale.
  • Write Tiptap JSON through PATCH /content. Keeps size, video, audio, and embeds. Not the Settings Markdown path.
  • Change IMAGE_LAYOUT_FALLBACK to 830×467. That would resize every unsized picture in the product, including small ones.

Impact

Anyone who replaces a document from .md (the public demo, and later users). The demo page is the first document that needs this.

Acceptance criteria

  • Importing PROPOSAL-demo/DEMO.md through Settings → Replace with a file leaves each /demo-assets/dN-*.png filling the writing column, 16:9, not 320×240.
  • A Markdown image that is not 16:9 keeps its own aspect ratio. No global 830×467 stamp.
  • alt and the italic line under the picture still survive import.
  • A successful replace still does not throw. code + link on one run of text stays invalid; do not reintroduce [/path](/path).
  • Mobile: width: 100%; max-width: {width}px still shrinks with the column.

Related gaps (not this ticket)

Markdown import also turns uploaded video, uploaded audio, and the six embed URLs into links. The live /demo page holds real video / audio / provider nodes. File those as their own tasks when we pick them up.

Additional context

  • Fallback: extensions/extension-hypermultimedia IMAGE_LAYOUT_FALLBACK = { width: 320, height: 240 }.
  • Column: 56rem sheet minus 1px border and sm:p-8 each side = 830px.
  • Apply path: Settings applyStagededitor.commands.setContent(sanitizeJsonContent(...)). The conversion API already returned JSON; the editor then rejects or paints what it is given.
  • Repro file: PROPOSAL-demo/DEMO.md.

Checklist

  • I searched existing issues and discussions first.
  • This request is scoped to a concrete problem.
  • I included enough context for maintainers to evaluate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions