Add autocompletion for wiki links

This commit is contained in:
2025-11-11 21:56:18 +01:00
parent 0579b8d0e5
commit 2e7bd88a57
13 changed files with 538 additions and 107 deletions

View File

@@ -1,5 +1,17 @@
import { API_BASE_URL } from '@/types/api';
import { IMAGE_EXTENSIONS } from '@/types/models';
import { IMAGE_EXTENSIONS, type FileNode } from '@/types/models';
/**
* Represents a flattened file for searching and autocompletion
*/
export interface FlatFile {
name: string; // "meeting-notes.md"
path: string; // "work/2024/meeting-notes.md"
displayPath: string; // "work/2024/meeting-notes"
nameWithoutExt: string; // "meeting-notes"
parentFolder: string; // "work/2024"
isImage: boolean;
}
/**
* Checks if the given file path has an image extension.
@@ -15,3 +27,65 @@ export const getFileUrl = (workspaceName: string, filePath: string) => {
workspaceName
)}/files/content?file_path=${encodeURIComponent(filePath)}`;
};
/**
* Recursively flattens FileNode tree into searchable array
* Precomputes display strings and metadata for performance
*
* @param nodes - Array of FileNode from the file tree
* @param showHiddenFiles - Whether to include hidden files (files/folders starting with .)
* @returns Array of FlatFile objects ready for searching
*/
export function flattenFileTree(nodes: FileNode[], showHiddenFiles = false): FlatFile[] {
const result: FlatFile[] = [];
function traverse(node: FileNode) {
// Skip hidden files and folders if showHiddenFiles is false
// Hidden files/folders are those that start with a dot (.)
if (!showHiddenFiles && node.name.startsWith('.')) {
return;
}
// Only process files, not folders (folders have children)
if (!node.children) {
const name = node.name;
const path = node.path;
const isImage = isImageFile(path);
// Remove extension for display (except for images)
let nameWithoutExt = name;
let displayPath = path;
if (name.endsWith('.md')) {
nameWithoutExt = name.slice(0, -3);
displayPath = path.slice(0, -3);
}
// Get parent folder path
const lastSlashIndex = path.lastIndexOf('/');
const parentFolder = lastSlashIndex > 0 ? path.slice(0, lastSlashIndex) : '';
result.push({
name,
path,
displayPath,
nameWithoutExt,
parentFolder,
isImage,
});
}
// Recursively process children
if (node.children) {
for (const child of node.children) {
traverse(child);
}
}
}
for (const node of nodes) {
traverse(node);
}
return result;
}