bigwolfe commited on
Commit
7f96410
·
1 Parent(s): 044ec7f

wikilinks and graph working

Browse files
frontend/src/components/NoteViewer.tsx CHANGED
@@ -35,6 +35,21 @@ export function NoteViewer({
35
  [onWikilinkClick]
36
  );
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  const formatDate = (dateString: string) => {
39
  return new Date(dateString).toLocaleDateString('en-US', {
40
  year: 'numeric',
@@ -72,12 +87,17 @@ export function NoteViewer({
72
 
73
  {/* Content */}
74
  <ScrollArea className="flex-1 p-6">
 
 
 
 
75
  <div className="prose prose-slate dark:prose-invert max-w-none">
76
  <ReactMarkdown
77
  remarkPlugins={[remarkGfm]}
78
  components={markdownComponents}
 
79
  >
80
- {note.body}
81
  </ReactMarkdown>
82
  </div>
83
 
 
35
  [onWikilinkClick]
36
  );
37
 
38
+ // Pre-process markdown to convert wikilinks to standard links
39
+ // [[Link]] -> [Link](wikilink:Link)
40
+ // [[Link|Alias]] -> [Alias](wikilink:Link)
41
+ const processedBody = useMemo(() => {
42
+ if (!note.body) return '';
43
+ const processed = note.body.replace(/\[\[([^\]]+)\]\]/g, (match, content) => {
44
+ const [link, alias] = content.split('|');
45
+ const displayText = alias || link;
46
+ const href = `wikilink:${encodeURIComponent(link)}`;
47
+ return `[${displayText}](${href})`;
48
+ });
49
+ // console.log('Processed Body:', processed);
50
+ return processed;
51
+ }, [note.body]);
52
+
53
  const formatDate = (dateString: string) => {
54
  return new Date(dateString).toLocaleDateString('en-US', {
55
  year: 'numeric',
 
87
 
88
  {/* Content */}
89
  <ScrollArea className="flex-1 p-6">
90
+ {/* Debug: Verify processed output */}
91
+ {/* <pre className="text-xs text-muted-foreground mb-4 whitespace-pre-wrap bg-muted p-2 rounded">
92
+ {processedBody}
93
+ </pre> */}
94
  <div className="prose prose-slate dark:prose-invert max-w-none">
95
  <ReactMarkdown
96
  remarkPlugins={[remarkGfm]}
97
  components={markdownComponents}
98
+ urlTransform={(url) => url} // Allow all protocols including wikilink:
99
  >
100
+ {processedBody}
101
  </ReactMarkdown>
102
  </div>
103
 
frontend/src/lib/markdown.tsx CHANGED
@@ -17,27 +17,13 @@ export function createWikilinkComponent(
17
  onWikilinkClick?: (linkText: string) => void
18
  ): Components {
19
  return {
20
- // Override the text renderer to handle wikilinks
21
- text: ({ children }: any) => {
22
- const value = String(children || '');
23
- const parts: React.ReactNode[] = [];
24
- const pattern = /\[\[([^\]]+)\]\]/g;
25
- let lastIndex = 0;
26
- let match;
27
- let key = 0;
28
-
29
- while ((match = pattern.exec(value)) !== null) {
30
- // Add text before the wikilink
31
- if (match.index > lastIndex) {
32
- parts.push(value.slice(lastIndex, match.index));
33
- }
34
-
35
- // Add the wikilink as a clickable element
36
- const linkText = match[1];
37
- parts.push(
38
  <span
39
- key={key++}
40
- className="wikilink cursor-pointer text-primary hover:underline"
41
  onClick={(e) => {
42
  e.preventDefault();
43
  onWikilinkClick?.(linkText);
@@ -50,47 +36,13 @@ export function createWikilinkComponent(
50
  onWikilinkClick?.(linkText);
51
  }
52
  }}
 
53
  >
54
- [[{linkText}]]
55
- </span>
56
- );
57
-
58
- lastIndex = pattern.lastIndex;
59
- }
60
-
61
- // Add remaining text
62
- if (lastIndex < value.length) {
63
- parts.push(value.slice(lastIndex));
64
- }
65
-
66
- return parts.length > 0 ? <>{parts}</> : value;
67
- },
68
-
69
- // Style code blocks
70
- code: ({ className, children, ...props }) => {
71
- const match = /language-(\w+)/.exec(className || '');
72
- const isInline = !match;
73
-
74
- if (isInline) {
75
- return (
76
- <code className="bg-muted px-1.5 py-0.5 rounded text-sm font-mono" {...props}>
77
  {children}
78
- </code>
79
  );
80
  }
81
 
82
- return (
83
- <code
84
- className={`${className} block bg-muted p-4 rounded-lg overflow-x-auto text-sm font-mono`}
85
- {...props}
86
- >
87
- {children}
88
- </code>
89
- );
90
- },
91
-
92
- // Style links
93
- a: ({ href, children, ...props }) => {
94
  const isExternal = href?.startsWith('http');
95
  return (
96
  <a
 
17
  onWikilinkClick?: (linkText: string) => void
18
  ): Components {
19
  return {
20
+ // Style links
21
+ a: ({ href, children, ...props }) => {
22
+ if (href?.startsWith('wikilink:')) {
23
+ const linkText = decodeURIComponent(href.replace('wikilink:', ''));
24
+ return (
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  <span
26
+ className="wikilink cursor-pointer text-primary hover:underline font-medium text-blue-500 dark:text-blue-400"
 
27
  onClick={(e) => {
28
  e.preventDefault();
29
  onWikilinkClick?.(linkText);
 
36
  onWikilinkClick?.(linkText);
37
  }
38
  }}
39
+ title={`Go to ${linkText}`}
40
  >
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  {children}
42
+ </span>
43
  );
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  const isExternal = href?.startsWith('http');
47
  return (
48
  <a
frontend/src/pages/MainApp.tsx CHANGED
@@ -126,6 +126,7 @@ export function MainApp() {
126
  // Handle wikilink clicks
127
  const handleWikilinkClick = async (linkText: string) => {
128
  const slug = normalizeSlug(linkText);
 
129
 
130
  // Try to find exact match first
131
  let targetNote = notes.find(
@@ -136,11 +137,13 @@ export function MainApp() {
136
  if (!targetNote) {
137
  targetNote = notes.find((note) => {
138
  const pathSlug = normalizeSlug(note.note_path.replace(/\.md$/, ''));
 
139
  return pathSlug.endsWith(slug);
140
  });
141
  }
142
 
143
  if (targetNote) {
 
144
  setSelectedPath(targetNote.note_path);
145
  } else {
146
  // TODO: Show "Create note" dialog
 
126
  // Handle wikilink clicks
127
  const handleWikilinkClick = async (linkText: string) => {
128
  const slug = normalizeSlug(linkText);
129
+ console.log(`[Wikilink] Clicked: "${linkText}", Slug: "${slug}"`);
130
 
131
  // Try to find exact match first
132
  let targetNote = notes.find(
 
137
  if (!targetNote) {
138
  targetNote = notes.find((note) => {
139
  const pathSlug = normalizeSlug(note.note_path.replace(/\.md$/, ''));
140
+ // console.log(`Checking path: ${note.note_path}, Slug: ${pathSlug}`);
141
  return pathSlug.endsWith(slug);
142
  });
143
  }
144
 
145
  if (targetNote) {
146
+ console.log(`[Wikilink] Found target: ${targetNote.note_path}`);
147
  setSelectedPath(targetNote.note_path);
148
  } else {
149
  // TODO: Show "Create note" dialog