Handle wiki style links

This commit is contained in:
2024-09-30 19:01:27 +02:00
parent 43d647c9ea
commit b64c13442b
8 changed files with 211 additions and 10 deletions

View File

@@ -19,6 +19,7 @@ import {
saveFileContent,
deleteFile,
getFileUrl,
lookupFileByName,
} from '../services/api';
const isImageFile = (filePath) => {
@@ -37,6 +38,7 @@ const MainContent = ({
onSave,
settings,
pullLatestChanges,
onLinkClick,
}) => {
const [activeTab, setActiveTab] = useState('source');
const { type: themeType } = useTheme();
@@ -212,6 +214,8 @@ const MainContent = ({
<MarkdownPreview
content={content}
baseUrl={window.API_BASE_URL}
onLinkClick={onLinkClick}
lookupFileByName={lookupFileByName}
/>
)}
</div>

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState, useEffect } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';
@@ -6,7 +6,69 @@ import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
import 'katex/dist/katex.min.css';
const MarkdownPreview = ({ content, baseUrl }) => {
const MarkdownPreview = ({
content,
baseUrl,
onLinkClick,
lookupFileByName,
}) => {
const [processedContent, setProcessedContent] = useState(content);
useEffect(() => {
const processContent = async (rawContent) => {
const regex = /(!?)\[\[(.*?)\]\]/g;
let result = rawContent;
const matches = [...rawContent.matchAll(regex)];
for (const match of matches) {
const [fullMatch, isImage, fileName] = match;
try {
const paths = await lookupFileByName(fileName);
if (paths && paths.length > 0) {
const filePath = paths[0];
if (isImage) {
result = result.replace(
fullMatch,
`![${fileName}](${baseUrl}/files/${filePath})`
);
} else {
// Use a valid URL format that React Markdown will recognize
result = result.replace(
fullMatch,
`[${fileName}](${baseUrl}/internal/${encodeURIComponent(
filePath
)})`
);
}
} else {
// Use a valid URL format for not found links
result = result.replace(
fullMatch,
`[${fileName}](${baseUrl}/notfound/${encodeURIComponent(
fileName
)})`
);
}
} catch (error) {
console.error('Error looking up file:', error);
result = result.replace(
fullMatch,
`[${fileName}](${baseUrl}/notfound/${encodeURIComponent(fileName)})`
);
}
}
return result;
};
processContent(content).then(setProcessedContent);
}, [content, baseUrl, lookupFileByName]);
const handleImageError = (event) => {
console.error('Failed to load image:', event.target.src);
event.target.alt = 'Failed to load image';
};
return (
<div className="markdown-preview">
<ReactMarkdown
@@ -30,17 +92,48 @@ const MarkdownPreview = ({ content, baseUrl }) => {
</code>
);
},
img({ src, alt, ...props }) {
// Check if the src is a relative path
if (src && !src.startsWith('http') && !src.startsWith('data:')) {
// Prepend the baseUrl to create an absolute path
src = `${baseUrl}/files/${src}`;
img: ({ src, alt, ...props }) => (
<img src={src} alt={alt} onError={handleImageError} {...props} />
),
a: ({ href, children }) => {
if (href.startsWith(`${baseUrl}/internal/`)) {
const filePath = decodeURIComponent(
href.replace(`${baseUrl}/internal/`, '')
);
return (
<a
href="#"
onClick={(e) => {
e.preventDefault();
onLinkClick(filePath);
}}
>
{children}
</a>
);
} else if (href.startsWith(`${baseUrl}/notfound/`)) {
const fileName = decodeURIComponent(
href.replace(`${baseUrl}/notfound/`, '')
);
return (
<a
href="#"
style={{ color: 'red', textDecoration: 'underline' }}
onClick={(e) => {
e.preventDefault();
onLinkClick(fileName);
}}
>
{children}
</a>
);
}
return <img src={src} alt={alt} {...props} />;
// Regular markdown link
return <a href={href}>{children}</a>;
},
}}
>
{content}
{processedContent}
</ReactMarkdown>
</div>
);