diff --git a/src/lib/components/ZettelEditor.svelte b/src/lib/components/ZettelEditor.svelte
index 1ca01bc..869030f 100644
--- a/src/lib/components/ZettelEditor.svelte
+++ b/src/lib/components/ZettelEditor.svelte
@@ -23,7 +23,7 @@
} from "$lib/utils/asciidoc_publication_parser";
import { getNdkContext } from "$lib/ndk";
import Asciidoctor from "asciidoctor";
- import { extractWikiLinks } from "$lib/utils/wiki_links";
+ import { extractWikiLinks, renderWikiLinksToHtml } from "$lib/utils/wiki_links";
// Initialize Asciidoctor processor
const asciidoctor = Asciidoctor();
@@ -218,7 +218,8 @@
event = findEventByDTag(publicationResult.contentEvents, node.dTag, node.eventKind);
}
- const tags = event?.tags.filter((t: string[]) => t[0] === "t") || [];
+ // Extract all tags (t for hashtags, w for wiki links)
+ const tags = event?.tags || [];
// Extract the title from the title tag
const titleTag = event?.tags.find((t: string[]) => t[0] === "title");
@@ -722,18 +723,18 @@
fontWeight: "500",
fontStyle: "italic",
},
- // Wiki links
+ // Wiki links - using theme primary colors (leather tones)
".cm-wiki-link-auto": {
- color: "#8B5CF6", // violet-500 for [[term]] (auto)
+ color: "var(--color-primary-700)", // [[term]] (auto) - medium leather
fontWeight: "500",
- backgroundColor: "rgba(139, 92, 246, 0.1)",
+ backgroundColor: "color-mix(in srgb, var(--color-primary-700) 10%, transparent)",
padding: "2px 4px",
borderRadius: "3px",
},
".cm-wiki-link-ref": {
- color: "#06B6D4", // cyan-500 for [[w:term]] (reference)
+ color: "var(--color-primary-800)", // [[w:term]] (reference) - darker leather
fontWeight: "500",
- backgroundColor: "rgba(6, 182, 212, 0.1)",
+ backgroundColor: "color-mix(in srgb, var(--color-primary-800) 10%, transparent)",
padding: "2px 4px",
borderRadius: "3px",
},
@@ -1026,10 +1027,11 @@
- {@const tTags = section.tags?.filter((tag) => tag[0] === 't') || []}
- {@const wTags = section.tags?.filter((tag) => tag[0] === 'w') || []}
+ {#if section.tags && section.tags.length > 0}
+ {@const tTags = section.tags.filter((tag) => tag[0] === 't')}
+ {@const wTags = section.tags.filter((tag) => tag[0] === 'w')}
- {#if tTags.length > 0 || wTags.length > 0}
+ {#if tTags.length > 0 || wTags.length > 0}
{#if tTags.length > 0}
@@ -1049,7 +1051,7 @@
{#each wTags as tag}
🔗 {tag[2] || tag[1]}
@@ -1058,6 +1060,7 @@
{/if}
+ {/if}
{/if}
{:else}
@@ -1087,10 +1090,11 @@
- {@const tTags = section.tags?.filter((tag) => tag[0] === 't') || []}
- {@const wTags = section.tags?.filter((tag) => tag[0] === 'w') || []}
+ {#if section.tags && section.tags.length > 0}
+ {@const tTags = section.tags.filter((tag) => tag[0] === 't')}
+ {@const wTags = section.tags.filter((tag) => tag[0] === 'w')}
- {#if tTags.length > 0 || wTags.length > 0}
+ {#if tTags.length > 0 || wTags.length > 0}
{#if tTags.length > 0}
@@ -1110,15 +1114,16 @@
{#each wTags as tag}
🔗 {tag[2] || tag[1]}
{/each}
-
{/if}
+ {/if}
{/if}
@@ -1127,25 +1132,37 @@
class="prose prose-sm dark:prose-invert max-w-none mt-4"
>
{@html (() => {
+ // Extract wiki links and replace with placeholders BEFORE Asciidoctor
+ const wikiLinks = extractWikiLinks(section.content);
+ let contentWithPlaceholders = section.content;
+ const placeholders = new Map();
+
+ wikiLinks.forEach((link, index) => {
+ // Use a placeholder inside a passthrough macro - Asciidoctor will strip pass:[...] and leave the inner text
+ const innerPlaceholder = `WIKILINK${index}PLACEHOLDER`;
+ const placeholder = `pass:[${innerPlaceholder}]`;
+ placeholders.set(innerPlaceholder, link); // Store by inner placeholder (what will remain after Asciidoctor)
+ contentWithPlaceholders = contentWithPlaceholders.replace(link.fullMatch, placeholder);
+ });
+
// Check if content contains nested headers
- const hasNestedHeaders = section.content.includes('\n===') || section.content.includes('\n====');
-
+ const hasNestedHeaders = contentWithPlaceholders.includes('\n===') || contentWithPlaceholders.includes('\n====');
+
+ let rendered;
if (hasNestedHeaders) {
// For proper nested header parsing, we need full document context
// Create a complete AsciiDoc document structure
// Important: Ensure proper level sequence for nested headers
- const fullDoc = `= Temporary Document\n\n${"=".repeat(section.level)} ${section.title}\n\n${section.content}`;
-
-
- const rendered = asciidoctor.convert(fullDoc, {
+ const fullDoc = `= Temporary Document\n\n${"=".repeat(section.level)} ${section.title}\n\n${contentWithPlaceholders}`;
+
+ rendered = asciidoctor.convert(fullDoc, {
standalone: false,
attributes: {
showtitle: false,
sectids: false,
},
});
-
-
+
// Extract just the content we want (remove the temporary structure)
// Find the section we care about
const sectionStart = rendered.indexOf(`');
if (sectionEnd !== -1) {
- const extracted = afterHeader.substring(0, sectionEnd);
- return extracted;
+ rendered = afterHeader.substring(0, sectionEnd);
}
}
}
- return rendered;
} else {
// Simple content without nested headers
- return asciidoctor.convert(section.content, {
+ rendered = asciidoctor.convert(contentWithPlaceholders, {
standalone: false,
attributes: {
showtitle: false,
@@ -1173,6 +1188,32 @@
},
});
}
+
+ // Replace placeholders with actual wiki link HTML
+ // Use a global regex to catch all occurrences (Asciidoctor might have duplicated them)
+ placeholders.forEach((link, placeholder) => {
+ const className =
+ link.type === 'auto'
+ ? 'wiki-link wiki-link-auto'
+ : link.type === 'w'
+ ? 'wiki-link wiki-link-ref'
+ : 'wiki-link wiki-link-def';
+
+ const title =
+ link.type === 'w'
+ ? 'Wiki reference (mentions this concept)'
+ : link.type === 'd'
+ ? 'Wiki definition (defines this concept)'
+ : 'Wiki link (searches both references and definitions)';
+
+ const html = `${link.displayText}`;
+
+ // Use global replace to handle all occurrences
+ const regex = new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
+ rendered = rendered.replace(regex, html);
+ });
+
+ return rendered;
})()}
{/if}
@@ -1567,3 +1608,43 @@ Understanding the nature of knowledge...
{/if}
+
+