fix: letterboxed, overflowing YouTube embeds on the public reader, paste to embed - #744
Merged
Merged
Conversation
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
force-pushed
the
fix/youtube-embed-layout
branch
from
August 5, 2026 15:40
1ecdb1b to
d7a4462
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A YouTube embed renders with black bars top and bottom, sits flush-left, and overflows the text column.
Two causes:
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.iframeout of themax-width: 100%rule it givesimg/video, and there was no iframe CSS anywhere in the public reader. So800pxwon and overflowed the85charticle 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.vuetakes 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-nocookie.com. No tracking cookies until the viewer presses play. Rehosting an existing embed URL preserves its?si=share query, and at=90/t=1m30son a watch link becomes?start=90instead of being dropped.nodePasteRulefor provider URLs since the feature shipped, and it never ran:WikiEditor'shandlePasteclaims any plain-text-only clipboard as markdown and returnstrue, 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, andisEmbedUrlPastestatelessness (thelastIndextrap behind Link formatting broken #667).Note on hiding YouTube's chrome
Not possible with player parameters any more:
modestbrandinghas had no effect since 2023-08-15,showinfowas removed in 2018, andrel=0only 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