diff --git a/src/renderer.js b/src/renderer.js
index 7dd1caf..50985f7 100644
--- a/src/renderer.js
+++ b/src/renderer.js
@@ -33,6 +33,39 @@ marked.use({
gfm: true
});
+// Footnotes support
+const markedFootnote = require('marked-footnote');
+marked.use(markedFootnote());
+
+// Admonitions support (:::note, :::warning, :::tip, :::danger, :::info)
+marked.use({
+ extensions: [{
+ name: 'admonition',
+ level: 'block',
+ start(src) { return src.match(/^:::(note|warning|tip|danger|info)/m)?.index; },
+ tokenizer(src) {
+ const match = src.match(/^:::(note|warning|tip|danger|info)\s*\n([\s\S]*?)^:::\s*$/m);
+ if (match) {
+ return {
+ type: 'admonition',
+ raw: match[0],
+ admonitionType: match[1],
+ text: match[2].trim()
+ };
+ }
+ },
+ renderer(token) {
+ const icons = { note: '\u2139', warning: '\u26A0', tip: '\uD83D\uDCA1', danger: '\uD83D\uDD34', info: '\u2139' };
+ const icon = icons[token.admonitionType] || '\u2139';
+ const inner = this.parser.parse(token.text);
+ return `
+
${icon} ${token.admonitionType.charAt(0).toUpperCase() + token.admonitionType.slice(1)}
+
${inner}
+
`;
+ }
+ }]
+});
+
// Tab Management
class TabManager {
constructor() {
@@ -337,7 +370,37 @@ class TabManager {
return;
}
const html = marked.parse(tab.content);
- const sanitizedHtml = DOMPurify.sanitize(html);
+ let sanitizedHtml = DOMPurify.sanitize(html);
+
+ // TOC generation
+ if (sanitizedHtml.includes('[[toc]]') || sanitizedHtml.includes('[TOC]')) {
+ const headingRegex = /]*>(.*?)<\/h[1-6]>/gi;
+ let tocMatch;
+ const toc = [];
+ const tempHtml = sanitizedHtml;
+ while ((tocMatch = headingRegex.exec(tempHtml)) !== null) {
+ const level = parseInt(tocMatch[1]);
+ const text = tocMatch[2].replace(/<[^>]+>/g, '');
+ const id = text.toLowerCase().replace(/[^\w]+/g, '-');
+ toc.push({ level, text, id });
+ }
+
+ if (toc.length > 0) {
+ const tocHtml = '';
+ sanitizedHtml = sanitizedHtml.replace(/\[\[toc\]\]|\[TOC\]/gi, tocHtml);
+
+ // Add IDs to headings for anchor links
+ toc.forEach(h => {
+ sanitizedHtml = sanitizedHtml.replace(
+ new RegExp(`(]*)>`, 'i'),
+ `$1 id="${h.id}">`
+ );
+ });
+ }
+ }
+
preview.innerHTML = sanitizedHtml;
// Render math expressions if KaTeX is available
diff --git a/src/styles.css b/src/styles.css
index bf107a0..a901a8a 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -4009,5 +4009,43 @@ body.theme-github .mermaid {
border-color: #e1e4e8;
}
+/* Task List Styles */
+.preview-content input[type="checkbox"] {
+ margin-right: 6px;
+ pointer-events: none;
+}
+.preview-content li.task-list-item {
+ list-style: none;
+ margin-left: -20px;
+}
+
+/* Admonition Styles */
+.admonition {
+ border-left: 4px solid;
+ border-radius: 4px;
+ padding: 12px 16px;
+ margin: 16px 0;
+}
+.admonition-title {
+ font-weight: 600;
+ margin-bottom: 8px;
+}
+.admonition-note, .admonition-info { border-color: #3b82f6; background: #eff6ff; }
+.admonition-warning { border-color: #f59e0b; background: #fffbeb; }
+.admonition-tip { border-color: #10b981; background: #ecfdf5; }
+.admonition-danger { border-color: #ef4444; background: #fef2f2; }
+
+/* TOC Styles */
+.toc { background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; padding: 16px; margin: 16px 0; }
+.toc h2 { font-size: 14px; margin-bottom: 8px; }
+.toc ul { list-style: none; padding: 0; }
+.toc li { padding: 2px 0; }
+.toc .toc-h1 { padding-left: 0; }
+.toc .toc-h2 { padding-left: 16px; }
+.toc .toc-h3 { padding-left: 32px; }
+.toc .toc-h4 { padding-left: 48px; }
+.toc a { color: #5661b3; text-decoration: none; }
+.toc a:hover { text-decoration: underline; }
+
/* Command Palette Styles */
/* Command Palette styles moved to styles-modern.css */