Skip to content

feat(markdown): add toMarkdown to limel-markdown - #4300

Draft
civing wants to merge 1 commit into
mainfrom
feat/markdown-to-markdown
Draft

civing wants to merge 1 commit into
mainfrom
feat/markdown-to-markdown

Conversation

@civing

@civing civing commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude on behalf of Civing

@coderabbitai summary

Closes #4301. Part of Lundalogik/crm-insights-and-intelligence#392.

What

limel-markdown gains a toMarkdown() method: its value with every whitelisted custom element replaced by the markdown that element stands for, for targets that cannot render the element — a paste into another application, say.

An element opts in by implementing the new MarkdownRepresentable interface (toMarkdown(): Promise<string>). The viewer detects the method on the rendered instances by duck typing, so it imports nothing from any consumer, and only whitelisted elements are ever asked — they are the only custom elements the sanitizer lets into the DOM, and the whitelist is checked explicitly as well.

Why

The AI Assist copy action puts the answer's markdown on the clipboard. Custom elements in it — <limebb-object-chip limetype="person" objectid="1234"> — come out as raw markup in plain text and are stripped entirely from the rich flavour. The rendered chip already knows the person's name and URL; this lets the copy path ask it. The consumers (building-blocks for the chip, crm-components for the copy handler) follow in their own PRs once this is released.

The rich text editor's serializer, which writes the tag itself so its markdown round-trips, is unchanged: that is the storage form, this is the export form.

How

  • substituteCustomElements(source, root, whitelist) pairs each written occurrence of a whitelisted tag with the rendered elements of that tag, by order, and splices in what each returns. Three written forms are recognised (self-closing, open through closing tag, open alone). When a tag's written and rendered counts disagree, every occurrence of that tag is removed rather than risk pairing wrongly. Elements without the method contribute their light-DOM text when written with a closing tag and nothing otherwise, since without one the parser nests the following text inside the element and it is already in the source.
  • textChanged() keeps its render as a promise so toMarkdown() can wait for the elements to exist before asking them.
  • 13 spec tests on the substitution rules; 3 browser e2e tests with a custom element defined in the page.

Review:

  • Commits are atomic
  • Commits have the correct type for the changes made
  • Commits with breaking changes are marked as such (none — purely additive, the interface is @alpha)

Browsers tested:

(Check any that applies, it's ok to leave boxes unchecked if testing something didn't seem relevant.)

Windows:

  • Chrome
  • Edge
  • Firefox

Linux:

  • Chrome
  • Firefox

macOS:

  • Chrome (headless Chromium via the e2e suite)
  • Firefox
  • Safari

Mobile:

  • Chrome on Android
  • iOS

🤖 Generated with Claude Code

limel-markdown gains a toMarkdown() method that returns its value
with every whitelisted custom element replaced by what its rendered
instance reports through the new MarkdownRepresentable interface, for
targets that cannot render the element — a paste into another
application, say. Today such an element is stripped from any HTML
made of the markdown and left as raw markup in the plain text.

Occurrences in the source are paired with rendered elements by tag
name and order; when the counts disagree for a tag, every occurrence
of it is dropped rather than risk attaching one element's
representation to another. Elements without the method contribute
their light-DOM text when written with a closing tag, and nothing
otherwise, since without one the parser nests the following text
inside the element and it is already in the source.

The render started by a value change is now kept as a promise so the
method can wait for the elements to exist before asking them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

Documentation has been published to https://lundalogik.github.io/lime-elements/versions/PR-4300/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

limel-markdown can export its content as markdown for targets that cannot render custom elements

1 participant