Has there been discussion about or interest in surfacing an API to access the Obsidian underlying markdown parser? What I have in mind for my use case is something like:
const result = await plugin.app.workspace.parse("Hello *world*");
console.log(result);
/**
[
{ text: "Hello ", type: "text"},
{ text: "world", type: "italics"},
]
*/
Obviously, the actual schema of the result array could resemble what Obsidian actually uses under the hood.
Up to this point, I have been using the recommendations found in Format your notes - Obsidian Help, but there are several undocumented nuances that could cause issues. For example, unlike the common mark spec, the string **Hello actually results in Hello bolded instead of rendering that full line as text. For these cases, it would simplify our use case immensely to be able to access the output of the parser directly.
Happy to expand on more if needed!
5 Likes
Yes it would be nice from the developers to give access to the parser and the grammar ! Especially if they use a parser-generator because that would make it really easy.
1 Like
I too am looking for this. Currently I use remark with some plugins, but the result is far from complete. For reference:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
// @ts-ignore: No type definitions available for this module
import remarkWikiLink from 'remark-wiki-link';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import { VFile } from 'vfile';
import { inspect } from 'unist-util-inspect';
describe('obsidian markdown parsing', () => {
it('parses a sample markdown text with remark-obsidian', async () => {
const sampleMarkdown = `
# Test Note
This is a [[link]] to another note.
![[embedded note]]
- [ ] Task 1
- [x] Task 2
> [!info] Callout
> This is a callout block
`.replace(/^[ \t]+/gm, '');
const file = new VFile(sampleMarkdown);
const result = unified().use(remarkParse).use(remarkGfm).use(remarkWikiLink).parse(file);
// shows syntax tree
console.log(inspect(result));
const root = result.children[0];
expect(result.children[0].type).toBe('heading');
});
});
Will print:
root[5] (1:1-13:1, 0-142)
ββ0 heading[1] (2:1-2:12, 1-12)
β β depth: 1
β ββ0 text "Test Note" (2:3-2:12, 3-12)
ββ1 paragraph[3] (4:1-4:36, 14-49)
β ββ0 text "This is a " (4:1-4:11, 14-24)
β ββ1 wikiLink "link" (4:11-4:19, 24-32)
β β data: {"alias":"link","permalink":"link","exists":false,"hName":"a","hProperties":{"className":"internal new","href":"#/page/link"},"hChildren":[{"type":"text","value":"link"}]}
β ββ2 text " to another note." (4:19-4:36, 32-49)
ββ2 paragraph[1] (6:1-6:19, 51-69)
β ββ0 text "![[embedded note]]" (6:1-6:19, 51-69)
ββ3 list[2] (8:1-9:13, 71-96)
β β ordered: false
β β start: null
β β spread: false
β ββ0 listItem[1] (8:1-8:13, 71-83)
β β β spread: false
β β β checked: false
β β ββ0 paragraph[1] (8:7-8:13, 77-83)
β β ββ0 text "Task 1" (8:7-8:13, 77-83)
β ββ1 listItem[1] (9:1-9:13, 84-96)
β β spread: false
β β checked: true
β ββ0 paragraph[1] (9:7-9:13, 90-96)
β ββ0 text "Task 2" (9:7-9:13, 90-96)
ββ4 blockquote[1] (11:1-12:26, 98-141)
ββ0 paragraph[1] (11:3-12:26, 100-141)
ββ0 text "[!info] Callout\nThis is a callout block" (11:3-12:26, 100-141)
1 Like
I have been maintaining a semi-popular text formatting plugin and have a feature request to do specific things before/after specific markdown features. You would think that Obsidianβs markdown parser would be accessible to plugin developers so we could, yβknow, support obsidian flavored markdown. Instead we are forced to add remark (different engine) as a dependency and 12 plugins, some of which are abandoned, to approximate the behavior of Obsidianβs markdown parser, which is a black box.
Exposing this API would make developing for Obsidian easier, cut the size of plugins shipping with remark, improve security by lessening the chance of a compromised dependency in abandoned plugins, and more.