obsidian/frontmatter-formatting
Rewrites a note’s YAML front matter by splicing its concrete syntax tree, so every region a change does not reach keeps the exact bytes its author wrote — comments and the whitespace inside them, quoting style, blank lines, indentation width, flow versus block collections, and folded and literal scalars.
Obsidian’s own processFrontMatter() parses the block to a plain object and re-stringifies the whole of it, so a callback that changes one key rewrites every other. Re-emitting the parsed document instead of the raw text does not fix that: five of the losses survive every emit option the yaml package offers. Splicing the CST does fix it, because an untouched token is never re-emitted at all — the library keeps each token’s original source text and CST.stringify concatenates it.
This module is DELIBERATELY not on the default path. It needs the yaml package’s CST API, which Obsidian does not hand to plugins through its module map — that map is obsidian, @codemirror/* and @lezer/* and nothing else — so the package cannot be marked external and lands in the consuming plugin’s main.js, about 100 KB of it. A plugin opts in by calling enableFrontmatterFormattingPreservation once, and only it pays.
Functions
Section titled “Functions”| Function | Description |
|---|---|
| enableFrontmatterFormattingPreservation | Registers this module’s engine as the front matter formatting preserver for every write this library performs. Call it once, from a plugin’s onloadImpl(). It takes effect for processFrontmatter(), applyFileChanges() and every other path that reaches setFrontmatter(), including the ones the calling plugin does not invoke itself. There is one preserver per realm, so two plugins that both call this simply agree. |
| preserveFrontmatterFormatting | Rewrites the front matter of a note, keeping the original bytes of everything the change does not reach. It is the engine enableFrontmatterFormattingPreservation registers, and can be called directly as well. null means “this one is not mine”: the block does not exist, the new front matter is empty (both are the parse-and-stringify path’s business, unchanged), or the splice could not be proved faithful. The proof is not hand-waved — the spliced block is re-parsed and compared against the value the parse-and-stringify path would have produced for the same input, and any difference returns null. That is what makes this strictly better than that path or identical to it, and never worse. |