** DONE Potential Markdown Data Loss When You Will Move Away from Obsidian :blog:pim:standards: CLOSED: [2026-04-08 Wed 23:11] :PROPERTIES: :ID: 2026-04-08-obsidian-md-portability :CREATED: [2026-04-08 Wed 23:04] :END: :LOGBOOK: - State "DONE" from "TODO" [2026-04-08 Wed 23:11] :END: This report is extending [[id:2025-05-10-Markdown-disaster][my general be-careful-with-Markdown article]] because users of Obsidian in particular do seem to ignore warnings about potential conversion loss for their future tool switch when Obsidian does not meet their requirements any more or is not available any longer - as so many closed source tools did before. This is a report generated by Claude.ai Opus 4.6 on [2026-04-08 Wed] for the prompt: #+BEGIN_QUOTE Please do generate a report on Markdown issues that will or may arise when a person moves away data from Obsidian. In general, Markdown has many different flavors and tools like Obsidian or Obsidian add-ons introduce new syntax elements that are not understood by other tools such as pandoc. In this example, I would suggest to convert Obsidian files to HTML that we do have a concrete target syntax example which is a valid choice for that experiment. Suggest a different format if you do have good arguments for a different target format. Do differ between standard Obsidian Markdown syntax elements (the focus) and popular addons (to get likely issues when not just sticking to the default elements). Add syntax examples for each case with the Markdown source (Markdown blocks) and the HTML result (HTML blocks) so that it is visible in what respect syntax information got lost or not handled properly as you would like to expect for a perfect data conversion. Also add a list of dynamic Obsidian features that are not available outside of Obsidian automatically when you are re-using the Markdown files elsewhere such as node visualizations and such. Bonus is when you can also come up with a list of Obsidian Markdown elements that are not part of the CommonMark syntax element list. #+END_QUOTE So if you do use Obsidian and find something here which is not accurate or changed over time, I would ask you to leave a comment so that I might fix that error. *I did not check all those findings myself* and LLMs like Claude may hallucinate here or there. The LLM output follows now: *** 1. Introduction [[https://obsidian.md/][Obsidian]] stores notes as plain [[https://en.wikipedia.org/wiki/Markdown][Markdown]] files --- but "plain" is misleading. Obsidian uses what it calls *Obsidian Flavored Markdown*, a combination of CommonMark, GitHub Flavored Markdown (GFM), and a set of proprietary syntax extensions. On top of that, the Obsidian plugin ecosystem introduces further non-standard syntax that only renders inside Obsidian itself. This report documents the specific syntax elements that cause problems when you try to move your Obsidian vault to another tool or convert files to HTML (or another format). Each section provides the *Obsidian Markdown source*, the *expected ideal HTML output*, and the *actual output* you would typically get from a standard converter like [[https://pandoc.org/][pandoc]]. **** Why HTML as the target format? HTML is a good test target because: - It is a well-defined, standards-based format with no ambiguity. - Pandoc (the most common Markdown-to-anything converter) supports it natively. - It makes information loss immediately visible --- you can see what rendered and what didn't. - Most other target formats (PDF, DOCX, EPUB) go through an HTML-like intermediate step anyway. That said, if your goal is long-term archival rather than conversion testing, *HTML with embedded CSS* or *EPUB* are both strong choices. If you want to stay in the Markdown ecosystem but on a more standardized footing, converting to *strict CommonMark* (stripping Obsidian extensions) is another valid path --- though you will lose features. *** 2. Standard Obsidian Syntax: What Breaks These are features built into Obsidian core --- no plugins required. **** 2.1 Wikilinks (Internal Links) Obsidian's signature feature. Wikilinks use double-bracket syntax to link notes by name, without requiring a file path or extension. *Markdown source:* #+begin_src markdown See [[My Other Note]] for details. Link with alias: [[My Other Note|click here]] Link to heading: [[My Other Note#Section Two]] Link to block: [[My Other Note#^abc123]] #+end_src *Expected ideal HTML:* #+begin_src html
See My Other Note for details.
Link with alias: click here
Link to heading: Section Two
Link to block: abc123
#+end_src *Actual pandoc output (default settings):* #+begin_src htmlSee [[My Other Note]] for details.
Link with alias: [[My Other Note|click here]]
Link to heading: [[My Other Note#Section Two]]
Link to block: [[My Other Note#^abc123]]
#+end_src *What went wrong:* Pandoc does not recognize wikilinks by default. The double brackets appear as literal text. Pandoc 3.0+ added =wikilinks_title_after_pipe= and =wikilinks_title_before_pipe= extensions, but they still do not handle image wikilinks, block references (=^id=), or vault-relative path resolution. **** 2.2 Embeds (Transclusion) Obsidian can embed the content of another note, a section of a note, or media files inline. *Markdown source:* #+begin_src markdown ![[Meeting Notes]] ![[Meeting Notes#Decisions]] ![[Meeting Notes#^block-ref]] ![[photo.png]] ![[photo.png|300]] ![[document.pdf]] ![[recording.mp3]] #+end_src *Expected ideal HTML:* #+begin_src html
#+end_src
*Actual pandoc output:*
#+begin_src html
![[Meeting Notes]]
![[Meeting Notes#Decisions]]
![[Meeting Notes#^block-ref]]
![[photo.png]]
![[photo.png|300]]
![[document.pdf]]
![[recording.mp3]]
#+end_src *What went wrong:* Pandoc treats all embeds syntax elements as literal text. Note transclusion is an inherently dynamic, Obsidian-specific feature --- no static converter resolves it. Image embeds with the wikilink syntax and the =|width= size hint are also not recognized. Even with pandoc's wikilink extensions enabled, image wikilinks remain unprocessed. **** 2.3 Block References and Block IDs Obsidian allows you to assign an ID to any paragraph or list item, then link or embed that specific block from elsewhere. *Markdown source:* #+begin_src markdown This is an important conclusion. ^my-conclusion - Item A - Item B - Item C ^my-list Link to the block: [[Note#^my-conclusion]] #+end_src *Expected ideal HTML:* #+begin_src htmlThis is an important conclusion.
Link to the block: my-conclusion
#+end_src *Actual pandoc output:* #+begin_src htmlThis is an important conclusion. ^my-conclusion
^my-list
Link to the block: [[Note#^my-conclusion]]
#+end_src *What went wrong:* The =^block-id= markers are rendered as literal text. They are not converted to HTML =id= attributes. The linking syntax also fails because wikilinks are not recognized. **** 2.4 Callouts Obsidian extends blockquote syntax with a type marker to create styled callout boxes. *Markdown source:* #+begin_src markdown > [!warning] Be careful > This action cannot be undone. > [!tip]+ Expand me > This is expanded by default. > [!faq]- Collapsed section > Hidden until the user clicks. > [!note] > A plain note callout without custom title. #+end_src *Expected ideal HTML:* #+begin_src htmlThis action cannot be undone.
This is expanded by default.
Hidden until the user clicks.
A plain note callout without custom title.
[!warning] Be careful This action cannot be undone.
[!tip]+ Expand me This is expanded by default.
[!faq]- Collapsed section Hidden until the user clicks.
#+end_src *What went wrong:* Pandoc renders these as ordinary blockquotes. The =[!type]= marker, the custom title, and the collapsible modifiers all appear as literal text inside the quote. The semantic meaning (warning vs.Β tip vs.Β note), the visual styling, and the interactive collapse/expand behavior are entirely lost. **** 2.5 Highlight Syntax Obsidian supports ===text=== for highlighted (marked) text. *Markdown source:* #+begin_src markdown This is ==highlighted text== in a sentence. #+end_src *Expected ideal HTML:* #+begin_src html[!note] A plain note callout without custom title.
This is highlighted text in a sentence.
#+end_src *Actual pandoc output (default Markdown reader):* #+begin_src htmlThis is ==highlighted text== in a sentence.
#+end_src *Workaround:* Pandoc's =markdown+mark= extension does support this, but it must be explicitly enabled: =pandoc -f markdown+mark=. Without it, the ==== delimiters appear literally. **** 2.6 Comments (Obsidian-Specific) Obsidian uses =%%= to delimit comments that are invisible in reading/preview mode but present in the source. *Markdown source:* #+begin_src markdown Visible text. %% This is a private comment that should not appear in output. %% More visible text. Inline comment: some text %% hidden note %% continues here. #+end_src *Expected ideal HTML:* #+begin_src htmlVisible text.
More visible text.
Inline comment: some text continues here.
#+end_src *Actual pandoc output:* #+begin_src htmlVisible text.
%% This is a private comment that should not appear in output. %%
More visible text.
Inline comment: some text %% hidden note %% continues here.
#+end_src *What went wrong:* The =%%= comment syntax is completely Obsidian-specific. Pandoc and every other Markdown processor treats =%%= as literal text, exposing your private annotations in the output. **** 2.7 YAML Frontmatter / Properties Obsidian uses YAML frontmatter for metadata (title, tags, aliases, dates, custom fields). This is also used by other tools, so support varies. *Markdown source:* #+begin_src markdown --- title: Project Status tags: - project - quarterly aliases: - Q3 Status - Project Update cssclasses: - wide-page date: 2025-06-15 --- # Project Status Content begins here. #+end_src *Expected ideal HTML:* #+begin_src htmlContent begins here.
#+end_src *Actual pandoc output:* #+begin_src htmlContent begins here.
#+end_src *Status:* Pandoc handles standard YAML frontmatter well --- it strips it from output and can use fields like =title= and =date=. However, Obsidian-specific fields like =aliases=, =cssclasses=, and nested tag structures have no meaning outside Obsidian and are silently discarded. This is not a rendering failure, but it is *metadata loss* --- your aliases and custom properties vanish. **** 2.8 Tags (Inline) Obsidian supports inline tags with =#= and nested tags with =/=. *Markdown source:* #+begin_src markdown This note is about #machine-learning and specifically #ml/transformers. Nested tags like #project/alpha/phase-2 are common. #+end_src *Expected ideal HTML:* #+begin_src htmlThis note is about #machine-learning and specifically #ml/transformers.
Nested tags like #project/alpha/phase-2 are common.
#+end_src *Actual pandoc output:* #+begin_src htmlThis note is about #machine-learning and specifically #ml/transformers.
Nested tags like #project/alpha/phase-2 are common.
#+end_src *What went wrong:* Inline tags survive as plain text (which is acceptable for readability), but their semantic meaning as navigable, filterable tags is entirely lost. The hierarchical tag structure (=ml/transformers= as a child of =ml=) has no equivalent in HTML. **** 2.9 Math / LaTeX Obsidian supports inline and block LaTeX math via =$...$= and =$$...$$=, using MathJax/KaTeX. *Markdown source:* #+begin_src markdown Inline math: $E = mc^2$ Block math: $$ \int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2} $$ #+end_src *Expected ideal HTML (with MathJax):* #+begin_src htmlInline math: \(E = mc^2\)
\[\int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}\]
#+end_src *Actual pandoc output:* #+begin_src htmlInline math: E = mc2
#+end_src *Status:* Pandoc handles math reasonably well with =--mathjax= or =--katex= flags. Without those flags, it attempts to render math as plain HTML, which works for simple expressions but breaks for complex LaTeX. The key issue is that you *must* explicitly configure your converter for math support --- it is not automatic. **** 2.10 Mermaid Diagrams Obsidian renders Mermaid diagram code blocks natively. *Markdown source:* #+begin_src markdown ```mermaid graph LR A[Start] --> B{Decision} B -->|Yes| C[Action] B -->|No| D[End] ``` #+end_src *Expected ideal HTML:* #+begin_src htmlgraph LR
A[Start] --> B{Decision}
B -->|Yes| C[Action]
B -->|No| D[End]
#+end_src
*What went wrong:* Pandoc outputs the Mermaid code as a regular code
block. Without a post-processing step that adds the Mermaid JavaScript
library and changes the tag structure, you get raw diagram source code
instead of a rendered diagram.
**** 2.11 Footnotes
Obsidian supports standard footnote syntax --- this is actually
well-supported.
*Markdown source:*
#+begin_src markdown
This claim needs a source[^1].
[^1]: Smith, J. (2024). *Important Research*. Journal of Examples.
#+end_src
*Expected ideal HTML:*
#+begin_src html
This claim needs a source1.
Smith, J. (2024). Important Research. Journal of Examples.β©οΈ
#+end_src
*Actual pandoc output:*
#+begin_src html
| File | Created | Tags |
|---|---|---|
| Note A | 2025-01-15 | #project |
TABLE file.ctime AS "Created", file.tags AS "Tags"
FROM #project
SORT file.ctime DESC
dv.table(["Name", "Status"],
dv.pages("#task")
.map(p => [p.file.link, p.status])
)
Inline query: = this.file.name
Created: 2025-06-15
Author: My Note Title
Previous: 2025-06-14
Created: <% tp.date.now("YYYY-MM-DD") %>
Author: <% tp.file.title %>
Previous: <% tp.date.now("YYYY-MM-DD", -1) %>
<%* if (tp.file.tags.includes("#meeting")) { %>
<%* } %>
#+end_src *What went wrong:* Templater expressions are escaped as literal text. If you export a note /before/ Templater has processed it (e.g., a template file rather than a rendered note), the raw template syntax appears in the output. If Templater already ran and replaced the expressions with values, there is no issue --- the note contains plain Markdown. **** 3.3 Tasks Plugin Extended Syntax The Tasks plugin extends standard checkbox syntax with dates, priorities, and recurrence. *Markdown source:* #+begin_src markdown - [ ] Review PR #42 π 2025-06-20 β« - [x] Deploy hotfix β 2025-06-14 π 2025-06-15 - [ ] Weekly standup π every Monday π 2025-06-17 - [ ] Write documentation β³ 2025-06-18 β 2025-06-10 #+end_src *Expected ideal HTML:* #+begin_src htmlContent here.
With a colored background.
Content here.
note: These are speaker notes not visible to the audience.
With a colored background.
#+end_src *What went wrong:* The =---= separators become =