Skip to content
This repository was archived by the owner on Jun 26, 2025. It is now read-only.

Commit fbce149

Browse files
committed
feat: add README modal for snippet details with Markdown rendering
1 parent 4db4e15 commit fbce149

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

main.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Plugin, Notice, Modal, App} from "obsidian";
1+
import {Plugin, Notice, Modal, App, MarkdownRenderer} from "obsidian";
22

33
interface Snippet {
44
id: string;
@@ -240,6 +240,29 @@ class CssSnippetStoreModal extends Modal {
240240

241241
card.createDiv({ cls: 'snippet-store-button-wrapper' });
242242

243+
card.addEventListener('click', async (event) => {
244+
// Prevent click events on buttons inside the card from triggering README modal
245+
if ((event.target as HTMLElement).tagName.toLowerCase() === 'button') return;
246+
247+
const readmeUrl = `https://raw.githubusercontent.com/${snippet.repo}/refs/heads/main/${snippet.folder}/README.md`;
248+
try {
249+
if (await isOnline()) {
250+
const response = await fetchWithTimeout(readmeUrl);
251+
if (!response.ok) {
252+
new Notice(`Could not fetch README: ${response.statusText}`);
253+
return;
254+
}
255+
const readme = await response.text();
256+
new SnippetReadmeModal(this.app, snippet, readme).open();
257+
} else {
258+
new Notice("No Internet connection...");
259+
}
260+
} catch (error) {
261+
console.error(error);
262+
new Notice(`Error fetching README: ${error.message}`);
263+
}
264+
});
265+
243266
// Now update just the button based on snippet state
244267
this.updateSnippetCard(snippet);
245268
});
@@ -320,4 +343,67 @@ export async function isOnline(timeout = 3000): Promise<boolean> {
320343
} catch (e) {
321344
return false;
322345
}
346+
}
347+
348+
class SnippetReadmeModal extends Modal {
349+
constructor(
350+
app: App,
351+
private snippet: Snippet,
352+
private readmeContent: string
353+
) {
354+
super(app);
355+
}
356+
357+
async onOpen() {
358+
const { contentEl } = this;
359+
contentEl.empty();
360+
contentEl.addClass("snippet-readme-modal");
361+
this.modalEl.style.width = "80vw";
362+
this.modalEl.style.height = "80vh";
363+
364+
// Title
365+
contentEl.createEl("h2", {
366+
text: `${this.snippet.name} – README`,
367+
});
368+
369+
// Rewrite relative image paths to absolute GitHub raw URLs
370+
const adjustedContent = this.rewriteRelativeMediaPaths(this.readmeContent);
371+
372+
// Markdown container
373+
const markdownContainer = contentEl.createDiv();
374+
markdownContainer.style.overflowY = "auto";
375+
markdownContainer.style.maxHeight = "65vh";
376+
markdownContainer.style.padding = "1rem";
377+
markdownContainer.style.backgroundColor = "var(--background-secondary)";
378+
markdownContainer.style.borderRadius = "8px";
379+
380+
// Render Markdown using Obsidian's renderer
381+
await MarkdownRenderer.renderMarkdown(
382+
adjustedContent,
383+
markdownContainer,
384+
"",
385+
this
386+
);
387+
388+
markdownContainer.querySelectorAll("img").forEach((img) => {
389+
img.style.maxWidth = "100%";
390+
img.style.height = "auto";
391+
img.style.display = "block";
392+
img.style.margin = "1rem auto"; // Optional: center images
393+
});
394+
}
395+
396+
onClose() {
397+
this.contentEl.empty();
398+
}
399+
400+
private rewriteRelativeMediaPaths(content: string): string {
401+
const base = `https://raw.githubusercontent.com/${this.snippet.repo}/refs/heads/main/${this.snippet.folder}/`;
402+
403+
// Regex to match image/video markdown with relative path
404+
return content.replace(/!\[([^\]]*)\]\((\.\/[^)]+)\)/g, (match, alt, relPath) => {
405+
const url = base + relPath.replace("./", "");
406+
return `![${alt}](${url})`;
407+
});
408+
}
323409
}

0 commit comments

Comments
 (0)