Skip to content

Preserve Substack widgets in markdown #64

Description

@MattFisher

When publish.py update overwrites a draft it replaces the entire body from Markdown, silently destroying any widgets inserted via the Substack editor. These widgets have no Markdown equivalent and should survive updates.

Widgets identified in a live draft:

Type Key attrs
polymarket eventSlug, marketSlug, fullEmbedUrl
button url, text, action, class
recipe id

Possible implementation

Represent widgets as HTML comment blocks containing the raw server JSON, e.g.:

<!-- widget
{"type": "polymarket", "attrs": {"eventSlug": "gpt-6-released-by", ...}}
-->

markdown-it passes HTML comments through as html_block tokens, so _render_block can detect and parse these without any plugin. The JSON is whatever publish.py inspect <id> returns for that node — the renderer inserts it verbatim, with no schema knowledge required. The block renders invisibly in Markdown previewers.

Alternatively, it may also be possible to store the widgets as normal json-formatted code blocks, and have the parser check the "type", but they would need to be distinguishable from code blocks that were intended to be published as code blocks.

Seamless sync via update

Rather than requiring manual inspect + copy-paste, cmd_update can keep the local file in sync automatically:

  1. Before uploading, fetch the existing draft and find any widget nodes not already present in the local Markdown file as <!-- widget ... --> blocks.
  2. Write missing widgets into the Markdown file.
  3. Render and upload the (now complete) Markdown.

Any widget added in the Substack editor is then written back into the local file on the next update run. The Markdown file stays in sync with the server and remains the source of truth for text content.

Image editing preservation

The Substack editor also lets authors set per-image properties (caption, alt text, alignment, full-width), as well as actually modify the image with a web-based editor, after a draft is created. A subsequent update currently stomps the changes because image nodes are rebuilt from scratch.

This is related to the widget problem and could be solved similarly — detect when a Markdown image URL matches an existing captionedImage src in the stored draft and merge editor-set attrs rather than replacing the node wholesale. It's worth investigating whether the editor saves image edits as a new upload or modifies the existing one, as that affects how src matching would work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions