11import { MarkdownSourceContentAdapter } from "./markdown_source.js" ;
2+ import { MarkdownRenderer , htmlToMarkdown , Component } from 'obsidian' ;
23
4+ /**
5+ * @class ObsidianMarkdownSourceContentAdapter
6+ * @extends MarkdownSourceContentAdapter
7+ * @description
8+ * An adapter for Obsidian markdown files that can optionally render
9+ * the file content to HTML and convert it back to markdown to capture
10+ * dynamic transformations (e.g. Dataview).
11+ */
312export class ObsidianMarkdownSourceContentAdapter extends MarkdownSourceContentAdapter {
13+ /**
14+ * Returns the frontmatter metadata from Obsidian's metadataCache.
15+ * @async
16+ * @returns {Promise<Object> } Frontmatter data if available, otherwise undefined.
17+ */
418 async get_metadata ( ) {
519 const app = this . item . env . main . app ;
6- const { frontmatter} = app . metadataCache . getFileCache ( this . item . file ) ;
20+ const { frontmatter } = app . metadataCache . getFileCache ( this . item . file ) || { } ;
721 return frontmatter ;
822 }
23+
24+ /**
25+ * Reads the file content. If opts.render_output is true, attempts to use
26+ * Obsidian's MarkdownRenderer to render the file to HTML, then convert it
27+ * back to markdown via htmlToMarkdown.
28+ * @async
29+ * @param {Object } [opts={}] - Options for reading.
30+ * @param {boolean } [opts.render_output=false] - If true, render MD -> HTML -> MD.
31+ * @returns {Promise<string> } The file content (possibly rendered).
32+ */
33+ async read ( opts = { } ) {
34+ const content = await super . read ( opts ) ;
35+ if ( ! opts . render_output ) {
36+ return content ;
37+ }
38+
39+ // Attempt dynamic rendering
40+ const app = this . item . env . main . app ;
41+ if ( ! app || ! MarkdownRenderer || ! htmlToMarkdown ) {
42+ console . warn ( 'Obsidian environment not found; cannot render markdown.' ) ;
43+ return content ;
44+ }
45+
46+ // Render to HTML
47+ const container = document . createElement ( 'div' ) ;
48+ // Obsidian's signature: renderMarkdown(markdown, container, sourcePath, plugin)
49+ await MarkdownRenderer . render ( app , content , container , this . item . path , new Component ( ) ) ;
50+
51+ // wait for container to stop changing
52+ let last_html = container . innerHTML ;
53+ const max_wait = 10000 ;
54+ let wait_time = 0 ;
55+ while ( last_html !== container . innerHTML || last_html . includes ( 'Loading...' ) ) {
56+ console . log ( 'waiting for markdown to render' ) ;
57+ await new Promise ( resolve => setTimeout ( resolve , 200 ) ) ;
58+ last_html = container . innerHTML ;
59+ wait_time += 200 ;
60+ if ( wait_time > max_wait ) {
61+ console . warn ( 'ObsidianMarkdownSourceContentAdapter: Timeout waiting for markdown to render.' ) ;
62+ break ;
63+ }
64+ }
65+
66+ // Convert HTML back to MD
67+ const newMd = htmlToMarkdown ( container ) ;
68+ console . log ( 'newMd' , newMd ) ;
69+ return newMd ;
70+ }
971}
1072
1173export default {
1274 collection : null , // No collection adapter needed for markdown sources
1375 item : ObsidianMarkdownSourceContentAdapter
14- } ;
76+ } ;
0 commit comments