Ferrite v0.3.1 adds AST support for embedded video syntax in markdown. Parsing runs as a post-processing pass after comrak conversion and wikilink extraction. Rendering (wry WebView overlay + thumbnail fallback) is a separate follow-up — see task 8 / future video-embed-rendering.md.
| Form | Example | AST result |
|---|---|---|
| Braced | {{video https://youtube.com/watch?v=abc}} |
VideoEmbed (YouTube if allowlisted) |
| Bare URL | Paragraph containing only a YouTube/youtu.be URL | VideoEmbed (YouTube only) |
Bare non-YouTube URLs stay normal paragraphs. Braced non-YouTube URLs become VideoEmbed with trusted: false (no WebView path).
| File | Purpose |
|---|---|
src/markdown/parser.rs |
VideoProvider, VideoEmbedInfo, MarkdownNodeType::VideoEmbed |
src/markdown/video_embed.rs |
URL parsing, allowlist, extract_video_embeds() post-pass |
src/markdown/widgets.rs |
serialize_node round-trip via source_text |
pub enum VideoProvider { YouTube, Unknown }
pub struct VideoEmbedInfo {
pub provider: VideoProvider,
pub video_id: Option<String>, // YouTube ID when provider is YouTube
pub url: String, // Normalized http/https URL
pub trusted: bool, // Allowlisted domain → WebView-eligible
pub source_text: String, // Original markdown (round-trip preserved)
}
// MarkdownNodeType variant:
VideoEmbed(VideoEmbedInfo)Called from parse_markdown_with_options() after extract_wikilinks():
- Walk block-level children recursively.
- For each
Paragraph, trytry_parse_video_paragraph(). - On match, replace paragraph with a leaf
VideoEmbednode (same line span).
- Parsed with the
urlcrate; onlyhttp/httpsaccepted. - Trusted hosts (WebView allowlist):
youtube.com,www.youtube.com,m.youtube.com,music.youtube.com,youtu.be,www.youtu.be. - YouTube ID extraction:
watch?v=,youtu.be/<id>,/embed/,/shorts/,/v/.
Public helper for downstream rendering:
pub fn parse_video_embed_url(raw_url: &str) -> Option<VideoEmbedInfo>Re-exported from crate::markdown.
VideoEmbedInfo.source_textstores the exact paragraph source.MarkdownNode::text_content()returnssource_textfor embed nodes.widgets::serialize_nodewritessource_textunchanged — raw/rendered switches do not rewrite markdown.
- No arbitrary iframe URLs on the trusted path — domain allowlist gates
trusted: true. - Non-allowlisted braced URLs parse as
VideoEmbedbuttrusted: false(thumbnail/text fallback only when rendering lands). javascript:and other schemes rejected at parse time (Nonefrom URL parser path).
Unit tests in src/markdown/video_embed.rs (#[cfg(test)]):
- Braced YouTube watch + youtu.be URLs
- Bare YouTube paragraph
- Non-YouTube bare URL stays paragraph
- Braced Vimeo → untrusted embed
- Mixed paragraph text + URL stays paragraph
Run (when test harness compiles):
cargo test video_embed- PRD §5.3 — prd-v0.3.1.md
- GitHub #119