diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 2c6dc55..c7cb3c8 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -1,150 +1,148 @@
-# Copilot Instructions for Notes App
+# NoteX Copilot Instructions
-## Project Architecture
+## Project Overview
+NoteX is a local-first, markdown-based note-taking app built with Tauri v2 (Rust backend + Vue 3 frontend). Notes are stored in SQLite and support cloud sync via custom database paths (OneDrive, Google Drive, etc.).
-This is a **Tauri v2 + Vue 3 + Vite** desktop application using a monorepo structure managed by Bun workspaces.
+## Architecture
-### Repository Structure
-- **Root**: Monorepo managed with Bun workspaces (`bun.lock`, `package.json`)
-- **`desktop/`**: The Tauri application workspace
- - Frontend: Vue 3 SFCs with `
@@ -53,6 +117,7 @@ const handleKeydown = (e: KeyboardEvent) => {
v-model="input"
@input="handleInput"
@keydown="handleKeydown"
+ @paste="handlePaste"
:placeholder="placeholder"
:disabled="disabled"
:autofocus="autofocus"
diff --git a/desktop/src/utils/markdown.ts b/desktop/src/utils/markdown.ts
index 7c98f03..320b6c5 100644
--- a/desktop/src/utils/markdown.ts
+++ b/desktop/src/utils/markdown.ts
@@ -1,7 +1,18 @@
import { marked } from 'marked';
import { createHighlighter } from 'shiki';
+import { invoke } from '@tauri-apps/api/core';
+import { convertFileSrc } from '@tauri-apps/api/core';
let highlighter: any = null;
+let databaseDirectory: string | null = null;
+
+// Get the database directory for resolving image paths
+async function getDatabaseDirectory(): Promise {
+ if (!databaseDirectory) {
+ databaseDirectory = await invoke('get_database_directory_cmd');
+ }
+ return databaseDirectory;
+}
// Initialize Shiki highlighter with both light and dark themes
async function initHighlighter() {
@@ -39,6 +50,41 @@ renderer.link = function (token: any) {
return `${text}`;
};
+// Custom image renderer to handle local image paths
+renderer.image = function (token: any) {
+ const { href, title, text } = token;
+
+ // Check if the href is a relative path starting with assets/images/
+ if (href.startsWith('assets/images/')) {
+ // Convert to absolute path and use Tauri's convertFileSrc
+ if (databaseDirectory) {
+ // Normalize path separators to forward slashes
+ const normalizedDbDir = databaseDirectory.replace(/\\/g, '/');
+ // Ensure there's a separator between directory and relative path
+ const absolutePath = normalizedDbDir.endsWith('/')
+ ? `${normalizedDbDir}${href}`
+ : `${normalizedDbDir}/${href}`;
+
+ const src = convertFileSrc(absolutePath);
+ const titleAttr = title ? ` title="${title}"` : '';
+ const alt = text || '';
+
+ console.log('Image path conversion:', {
+ href,
+ databaseDirectory,
+ absolutePath,
+ src,
+ });
+ return `
`;
+ }
+ }
+
+ // For absolute URLs or other paths, render normally
+ const titleAttr = title ? ` title="${title}"` : '';
+ const alt = text || '';
+ return `
`;
+};
+
renderer.code = function (token: any) {
const { text: code, lang: language } = token;
@@ -138,8 +184,9 @@ initHighlighter();
// Export the render function
export async function renderMarkdown(content: string): Promise {
- // Ensure highlighter is ready
+ // Ensure highlighter is ready and database directory is loaded
await initHighlighter();
+ await getDatabaseDirectory();
return marked.parse(content) as string;
}