Skip to content

fix: letterboxed, overflowing YouTube embeds on the public reader, paste to embed - #744

Merged
NagariaHussain merged 5 commits into
developfrom
fix/youtube-embed-layout
Aug 5, 2026
Merged

fix: letterboxed, overflowing YouTube embeds on the public reader, paste to embed#744
NagariaHussain merged 5 commits into
developfrom
fix/youtube-embed-layout

Conversation

@NagariaHussain

Copy link
Copy Markdown
Member

Problem

A YouTube embed renders with black bars top and bottom, sits flush-left, and overflows the text column.

Two causes:

  1. Stored markdown keeps whatever dimensions the author pasted from the share dialog — here width="800" height="473.33", a ratio of 1.690 rather than 16:9. YouTube pads its 16:9 video into the too-tall box, which is the black bars.
  2. Tailwind preflight leaves iframe out of the max-width: 100% rule it gives img/video, and there was no iframe CSS anywhere in the public reader. So 800px won and overflowed the 85ch article column.

The SPA editor and reader were already fine — they force 16:9 and ignore the stored attributes.

Solution

Impose our own box in #wiki-content: 100% width capped at 720px, centered, rounded, with an exact 16:9 aspect-ratio for video providers. Non-video embeds (Figma, Docs, gists) keep their authored height. IframeBlockView.vue takes the same 720px cap so the editor, the reader and a change-request preview agree.

Existing pages are untouched — the CSS overrides the stored attributes either way.

Also in here

  • YouTube embeds now use youtube-nocookie.com. No tracking cookies until the viewer presses play. Rehosting an existing embed URL preserves its ?si= share query, and a t=90 / t=1m30s on a watch link becomes ?start=90 instead of being dropped.
  • Pasting a YouTube link now embeds it. The iframe block has carried a nodePasteRule for provider URLs since the feature shipped, and it never ran: WikiEditor's handlePaste claims any plain-text-only clipboard as markdown and returns true, which tells ProseMirror not to apply its slice — and paste rules run on that slice. A URL copied from the address bar is exactly that payload, so it always landed as a bare link. It now stands aside for paste-alone embed URLs. A URL inside a sentence still stays text; a paste over a selection still becomes a link.

Tests

  • e2e/tests/public-embed-layout.spec.ts — measures the rendered box (720px cap, exact 16:9, centered). Confirmed failing at 800px with the CSS removed.
  • e2e/tests/iframe-embed.spec.ts — two paste-to-embed cases; the embed case was confirmed failing before the fix.
  • iframe-embed.test.js — nocookie rewrites, timestamp carry, and isEmbedUrlPaste statelessness (the lastIndex trap behind Link formatting broken #667).

Note on hiding YouTube's chrome

Not possible with player parameters any more: modestbranding has had no effect since 2023-08-15, showinfo was removed in 2018, and rel=0 only restricts related videos to the same channel. The only real option is a facade (own thumbnail + play button, iframe injected on click), which is deliberately not in this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XnyveABWeKpqoQ1CcG1qud

NagariaHussain and others added 5 commits August 5, 2026 21:09
Stored markdown keeps whatever width/height the author pasted from the
provider's share dialog, and Tailwind preflight leaves iframe out of the
max-width rule img/video get. So an 800x473 attribute pair won the layout:
the embed overflowed the article column and YouTube letterboxed the 16:9
video into the too-tall box with black bars.

Impose our own box in #wiki-content instead: 100% width capped at 720px,
centered, rounded, and an exact 16:9 aspect-ratio for video providers.
Non-video embeds (figma, docs, gists) keep their authored height.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XnyveABWeKpqoQ1CcG1qud
Match the public reader's 720px centered box so the same page doesn't
change shape between the editor, the readonly reader and a CR preview.
Documents, boards and sandboxes get 4:3 instead of a widescreen box that
wastes half its height on their own scrollbars.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XnyveABWeKpqoQ1CcG1qud
Every YouTube form (watch, shorts, youtu.be, an already-built embed URL)
now normalizes to youtube-nocookie.com, the privacy-enhanced host that
sets no tracking cookies until playback. Rehosting an existing embed URL
preserves its path and query so the share dialog's ?si= survives.

A `t=90` or `t=1m30s` on a watch/youtu.be link becomes `?start=90`
instead of being silently dropped.

Pasted embed HTML goes through the same normalizer as a pasted URL, so
the two entry points can't disagree on the host. Markdown already stored
on a page is parsed as-is and keeps whichever host it was written with.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XnyveABWeKpqoQ1CcG1qud
Pins the 720px cap, the exact 16:9 ratio and the centering. Verified it
fails (800px wide) with the main.css rules removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XnyveABWeKpqoQ1CcG1qud
The iframe block has always carried a nodePasteRule for provider URLs, but
it never ran. WikiEditor's handlePaste claims any plain-text-only clipboard
as markdown and returns true, which tells ProseMirror not to apply its
slice — and paste rules run on that slice. A URL copied from the address
bar is exactly a plain-text-only payload, so it always landed as a link.

Stand aside when the payload is nothing but an embeddable URL and let the
paste rule do its job. isEmbedUrlPaste() is built from the paste rule's own
pattern so the two can't drift, with a non-global copy of the regex: the
exported one carries lastIndex and would answer false on every other call.

Only paste-alone URLs embed; a link inside a sentence stays a link, and a
paste over a selection still goes to the link extension.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XnyveABWeKpqoQ1CcG1qud
@NagariaHussain
NagariaHussain force-pushed the fix/youtube-embed-layout branch from 1ecdb1b to d7a4462 Compare August 5, 2026 15:40
@NagariaHussain NagariaHussain changed the title Fix letterboxed, overflowing YouTube embeds on the public reader fix: letterboxed, overflowing YouTube embeds on the public reader Aug 5, 2026
@NagariaHussain NagariaHussain changed the title fix: letterboxed, overflowing YouTube embeds on the public reader fix: letterboxed, overflowing YouTube embeds on the public reader, paste to embed Aug 5, 2026
@NagariaHussain
NagariaHussain merged commit 05bc148 into develop Aug 5, 2026
7 checks passed
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.

1 participant