Skip to content

Add MarkdownEmbedPreview component + preview pane (CS-11673, CS-11674)#5303

Open
FadhlanR wants to merge 3 commits into
mainfrom
cs-11673-cs-11674-markdown-embed-preview-pane
Open

Add MarkdownEmbedPreview component + preview pane (CS-11673, CS-11674)#5303
FadhlanR wants to merge 3 commits into
mainfrom
cs-11673-cs-11674-markdown-embed-preview-pane

Conversation

@FadhlanR

@FadhlanR FadhlanR commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Builds the reusable markdown-embed preview and its right-hand preview pane — the companion the combined chooser modal (CS-11675) will compose later. Per discussion, CS-11674 (always-on W×H inputs with smart variant matching) is combined into this branch.

Cards/files embed in markdown via BFM directives (:card[URL] inline / ::card[URL | size] block). This lets a user pick a target, choose how it renders, toggle inline vs block, and get the correctly-serialized BFM.

What's here

  • MarkdownEmbedPreview (markdown-embed-chooser/preview/index.gts) — pure render component. Given a resolved CardDef/FileDef, a @format, and (for fitted) a @sizeSpec, it renders via CardRenderer. Fitted sizing reuses bfmBlockFormatAndSize, so the preview footprint matches the live markdown renderer byte-for-byte. @kind controls inline/block placement, not the render format. With @showSurroundingText it renders the embed inside skeleton document text so you can see how it sits in a real doc — an inline embed flows within the paragraph, a block embed breaks to its own line. A shared inner Embed component keeps the bare and in-context paths from duplicating the inline/block markup.
  • MarkdownEmbedPreviewPane (markdown-embed-chooser/pane.gts) — format dropdown at the top (Atom / Embedded / each Fitted variant / Custom), a live preview, and a footer with the Inline/Block toggle, the W×H inputs (for Fitted/Custom, placed right after the toggle), and a dynamic "Insert as …" CTA that fires @onInsert(bfm). Format and placement are independent — every format is selectable in both inline and block, and the preview tracks the true format × placement.
  • runtime-common/bfm-card-references.tsserializeBfmSizeSpec (inverse of parseBfmSizeSpec) and serializeBfmRef, the single source of truth for BFM directive syntax. base/markdown-helpers.ts delegates to it so file refs (:file[…]) serialize too. The pane declares its intent uniformly ({ kind, size }) and lets this serializer decide what each placement carries.
  • templates/host-freestyle.gts — provides the full CardContext so the Freestyle preview usages actually render cards/files (CardRenderer consumes it via @consume).
  • Freestyle demos for both components (registered as MarkdownEmbedChooser::Preview / ::Pane), plus unit + integration tests.

Serialization

Today serializeBfmRef drops the size for inline (inline is atom-only in the current BFM grammar):

Choice Inline (today) Block
Atom :card[URL] ::card[URL | atom]
Embedded :card[URL] ::card[URL | embedded]
Fitted variant :card[URL] ::card[URL | tall-tile]
Custom W×H :card[URL] ::card[URL | w:300 h:200]

Files use the file keyword. The preview already shows the selected format in both placements; the inline column collapses to a size-less :card[URL] only because BFM's serializer/grammar doesn't yet carry a spec for inline.

Follow-up: CS-11704

Making inline carry a format/size is a BFM-grammar change tracked in CS-11704 ("BFM: support all formats in both inline and block reference directives"). When it lands, the inline column above becomes :card[URL | <spec>] with no change to this chooser — it already passes the size through serializeBfmRef.

Notes for reviewers

  • Scope: standalone pane + Freestyle only — real chooser composition is deferred to the combined modal (CS-11675). The CTA only emits the BFM via @onInsert; cursor insertion is a later ticket.
  • Deviation: uses the inline-style fitted path (shared with production rendered-markdown) instead of FittedCardContainer, because it covers custom W×H + % widths uniformly and guarantees parity with the live renderer.
  • Verification: eslint, ember-template-lint, and ember-tsc are clean for the touched files; the markdown-embed integration suite passes locally against the dev stack (14 tests, 37 assertions).

Screen Recording

Screen.Recording.2026-06-23.at.19.15.11.mov

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files      1 suites   2h 1m 19s ⏱️
3 200 tests 3 185 ✅ 15 💤 0 ❌
3 219 runs  3 204 ✅ 15 💤 0 ❌

Results for commit f6ac9e3.

Realm Server Test Results

    1 files  ±0      1 suites  ±0   12m 3s ⏱️ - 1m 2s
1 742 tests ±0  1 742 ✅ ±0  0 💤 ±0  0 ❌ ±0 
1 835 runs  ±0  1 835 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit f6ac9e3. ± Comparison against earlier commit 6700fe0.

FadhlanR and others added 2 commits June 23, 2026 14:00
Build the reusable markdown-embed preview and its right-hand preview pane,
the companion the combined chooser modal will compose later.

- MarkdownEmbedPreview: renders a resolved card/file in a given format/size
  via CardRenderer; fitted sizing reuses bfmBlockFormatAndSize so the preview
  footprint matches the live markdown renderer. @kind controls inline/block
  placement, not the render format.
- Preview pane: format dropdown (Atom / Embedded / each Fitted variant /
  Custom), always-on W×H inputs for Fitted with smart bidirectional variant
  matching, Inline/Block toggle (Block disabled while Atom is selected), and a
  dynamic "Insert as ..." CTA that emits the serialized BFM via @onInsert.
- runtime-common: add serializeBfmSizeSpec (inverse of parseBfmSizeSpec) and
  serializeBfmRef as the single source of truth for BFM directive syntax;
  base markdown-helpers delegate to it so file refs serialize too.
- Freestyle demos for both components plus unit and integration tests.

Combines CS-11674 (W×H inputs) into this branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ment decoupling

- host-freestyle: provide CardContext so previewed cards/files actually render
  (CardRenderer consumes it; the freestyle route only had the Get* contexts).
- Pane layout: move the format dropdown to the top; place the W×H inputs after
  the Inline/Block toggle in the footer.
- MarkdownEmbedPreview: add opt-in @showSurroundingText that renders the embed
  inside skeleton document text (inline flows in the paragraph, block breaks to
  its own line); extract a shared Embed component so the bare and in-context
  paths don't duplicate the inline/block markup.
- Decouple format from placement: every format is selectable in both inline and
  block, and the preview tracks the true format × placement. The pane declares
  intent (kind + size) uniformly to serializeBfmRef; whether inline carries the
  size is owned by BFM's serializer and handled in CS-11704.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@FadhlanR FadhlanR force-pushed the cs-11673-cs-11674-markdown-embed-preview-pane branch from ae62c77 to 6700fe0 Compare June 23, 2026 12:09
The provided CardContext assigned the raw card-resource `getCard`, which
isn't assignable to CardContext.getCard's `getCard<CardDef>` type — ember-tsc
flagged TS2322. Cast through `GetCardType` and reference `this.getCard` in the
context, mirroring how `templates/index.gts` provides it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@FadhlanR FadhlanR marked this pull request as ready for review June 23, 2026 13:38
@FadhlanR FadhlanR requested a review from a team June 23, 2026 13:39
@habdelra habdelra requested a review from Copilot June 23, 2026 13:39

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f6ac9e3e88

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +167 to +168
case 'atom':
return 'atom';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don’t emit unsupported block atom directives

When the default Atom option is switched to Block, this returns atom as the size specifier, so the CTA emits ::card[url | atom]. I checked the current BFM reader path: parseBfmSizeSpec does not accept atom, and block rendering falls back to embedded when no recognized data-boxel-bfm-format is produced, so users who insert from this state see an embedded card despite the preview/CTA saying Atom. Until the grammar/renderer supports block atom, this state should either serialize to a supported directive or be disabled.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a reusable markdown-embed preview component and a companion right-hand preview pane for configuring BFM card/file embed directives, plus shared BFM serialization helpers so host + base realm emit consistent directive syntax.

Changes:

  • Introduces MarkdownEmbedPreview (pure render) and MarkdownEmbedPreviewPane (format/placement/size controls + “Insert as …” emitting serialized BFM).
  • Centralizes BFM directive serialization in runtime-common (serializeBfmSizeSpec, serializeBfmRef) and updates base-realm markdown helpers to delegate to it.
  • Adds Freestyle demos and new unit/integration tests for BFM serialization + preview/pane behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/runtime-common/bfm-card-references.ts Adds BFM size + reference serializers to centralize directive output.
packages/host/tests/unit/bfm-card-references-test.ts Adds unit coverage for new serializer helpers.
packages/host/tests/integration/components/markdown-embed-preview-test.gts Adds integration coverage for preview rendering across formats/placement.
packages/host/tests/integration/components/markdown-embed-preview-pane-test.gts Adds integration coverage for pane controls and emitted BFM strings.
packages/host/app/templates/host-freestyle.gts Provides full CardContext so Freestyle demos can render via CardRenderer.
packages/host/app/components/markdown-embed-chooser/preview/usage.gts Freestyle usage/demo for MarkdownEmbedPreview.
packages/host/app/components/markdown-embed-chooser/preview/index.gts New preview component implementation (format + placement + optional fitted sizing).
packages/host/app/components/markdown-embed-chooser/pane.gts New preview-pane component (dropdown, toggle, W×H inputs, emits serialized BFM).
packages/host/app/components/markdown-embed-chooser/pane-usage.gts Freestyle usage/demo for MarkdownEmbedPreviewPane.
packages/base/markdown-helpers.ts Delegates embed directive construction to serializeBfmRef for consistent syntax.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +165 to +170
private get sizeSpecifier(): string | undefined {
switch (this.category) {
case 'atom':
return 'atom';
case 'embedded':
return 'embedded';
Comment on lines +40 to +42
matching), an Inline/Block toggle (Block is disabled while Atom is
selected, since atom has no block form), and a dynamic "Insert as …"
CTA. The CTA fires
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.

2 participants