v7.8.0: 📺 Standard Markdown for Embeds, Safe Iframe Capture, and a Cleaner HTML Round Trip
I am pleased to announce the release of officeParser v7.8.0! Embeds were the one construct in the Markdown dialect with no borrowed convention and the worst degrade: a YouTube video could only be written as an invented <div data-youtube-video> block that renders as an invisible empty box on GitHub, and a raw <iframe> was escaped into a wall of literal text. This release gives embeds a real, selectable Markdown form, adds a safe path for capturing untrusted iframes, and fixes an HTML round-trip whitespace bug.
Everything here follows the same rule as recent releases: no regression on any consumer. Every change is additive, a genuine bug fix, or non-standard becoming standard; where a default would move, the old behavior stays and is deprecated. The default embed output is byte-identical to 7.7.0.
✨ What's New
1. A Markdown form for embeds, selected by mdConfig.dialect.embeds
Choose how an embed node is written:
'html'(default): the<div data-youtube-video>/<iframe>single-line block this library has always emitted and re-reads.'directive': a remark-directive leaf,::youtube[Label]{id=… width=… align=…}/::embed[Label]{src=… …}, both parsed and generated. An editor round-trip form (GitHub renders it verbatim rather than as a player, so it is not a GitHub-interop format).'link': a plain[YouTube](url)/[Embed](url).'thumbnail': a YouTube-only clickable preview[](watch), the best GitHub degrade.
::youtube parses unconditionally (rendered from a validated id via a fixed template). ::embed carries an arbitrary src, so it is gated behind preserveIframes (the trust input) and stays literal text otherwise. Unknown ::names stay literal, with no catch-all.
2. Safe capture of untrusted iframes: htmlConfig.gatedEmbeds
Off by default. When on, a generic (non-YouTube) iframe embed is emitted as an inert <div data-embed-gated data-embed-src> placeholder that never auto-loads its src. An editor renders a click-to-load control from it, and HtmlParser reads it back to the same embed node. The src is scheme-checked on emit. The default output (a live <iframe>) is unchanged. Combined with the existing preserveIframes gate, untrusted input is never escaped-as-text and never auto-rendered.
3. Opt-in import of ambiguous "folk" forms: htmlParserConfig.embedFolkForms
Off by default. When on, a standalone Obsidian image whose URL is a YouTube link () and a clickable thumbnail-link ([](watch)) import as safe YouTube embeds. Off by default because auto-upgrading an image or link is a heuristic that could mangle a genuinely-intended image link. The unambiguous forms are always recognized regardless of this flag.
4. EmbedMetadata.label
The human label of a ::youtube[Label] / ::embed[Label] directive (and a gated embed's caption). It round-trips through the directive form, the generic gated data-embed-label, and the YouTube editor-HTML shape.
⚠️ Deprecated
fallbackToHtml.embeds (boolean). Use mdConfig.dialect.embeds instead, which also selects the 'directive' and 'thumbnail' forms. While dialect.embeds is unset the boolean is still honored (true maps to 'html', false to 'link'). It will be removed in the next major.
🔧 What's Fixed
1. Markdown and HTML now parse a YouTube iframe the same way
The Markdown parser read a YouTube <iframe> as a generic 'iframe' embed with no videoId, and only under preserveIframes, while the HTML parser read it as 'youtube' unconditionally. Both parsers now detect a YouTube src the same way, before the preserveIframes gate, so the same input yields the same 'youtube' embed. The youtube-via-iframe HTML path now also carries the iframe's width/height.
2. An inline link was fenced by blank lines on md → HTML
HtmlGenerator appended a readability blank line after every node, including inline text and link runs, so See this [video](url). emitted a paragraph with \n\n around the <a>, which reparsed as a stray space before the punctuation. The blank line is now added only after block-level nodes; inline runs concatenate directly. This is a whitespace-only change to generated HTML (semantically identical), and it makes the md → HTML → md round trip correct.
🛠 Getting Started
npm install officeparser@7.8.0🔗 Full Changelog: View v7.8.0 details
🔗 Documentation & Visualizer: officeparser.harshankur.com