Refactor: Remove obsolete JavaScript managers and utilities

- Deleted NavigationManager, RecentPlotsManager, SearchManager, SortManager, StatsManager, ThemeManager, Utils, and ViewManager classes.
- Updated gallery builder to improve asset copying logic with a more efficient modification time check.
- Cleaned up gallery HTML template by removing subdirectory listing and embedding gallery data as JSON.
- Added CLAUDE.md for project documentation and guidelines.
This commit is contained in:
Kylian Schmidt
2026-05-06 08:34:40 +02:00
parent 6f0cf4521b
commit 6738c4ca69
44 changed files with 205 additions and 5239 deletions
+1 -8
View File
@@ -2,16 +2,9 @@
FOLDER TREE
======================================== */
.folder-tree {
background: var(--tree-bg);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
font-size: 0.85rem;
max-height: 350px;
overflow-y: auto;
transition: all 0.3s ease;
margin: 1rem 0;
}
.tree-item {
+65 -79
View File
@@ -9,20 +9,20 @@ export class NavigationManager {
const currentPath = window.location.pathname;
const pathParts = currentPath.split('/').filter(part => part !== '' && part !== 'index.html');
const breadcrumb = document.getElementById('breadcrumb');
if (!breadcrumb) return;
if (pathParts.length === 0) {
breadcrumb.innerHTML = '<span>🏠 Root</span>';
return;
}
let html = '<a href="/">🏠 Root</a>';
for (let i = 0; i < pathParts.length; i++) {
const part = pathParts[i];
html += '<span class="separator">/</span>';
if (i === pathParts.length - 1) {
html += `<span>${decodeURIComponent(part)}</span>`;
} else {
@@ -31,19 +31,35 @@ export class NavigationManager {
html += `<a href="${relativePath}">${decodeURIComponent(part)}</a>`;
}
}
breadcrumb.innerHTML = html;
}
/**
* Extract subdirs and item count from a parsed page document.
* Reads from the embedded #gallery-data JSON element.
*/
extractPageData(doc) {
const dataEl = doc.getElementById('gallery-data');
if (dataEl) {
try {
const data = JSON.parse(dataEl.textContent);
return { subdirs: data.subdirs || [], itemCount: data.item_count || 0 };
} catch {}
}
// Fallback for pages that pre-date the data element
return { subdirs: [], itemCount: doc.querySelectorAll('.grid-item').length };
}
/**
* Build and display the folder tree structure
*/
async buildFolderTree() {
const treeContainer = document.getElementById('folderTree');
const currentPath = window.location.pathname;
if (!treeContainer) return;
try {
const tree = await this.buildTreeRecursive(currentPath, 0, currentPath);
treeContainer.innerHTML = tree;
@@ -61,52 +77,41 @@ export class NavigationManager {
const indent = ' '.repeat(depth);
return `<div class="tree-item">${indent}└─ ...</div>`;
}
try {
const response = await fetch(path);
const htmlContent = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(htmlContent, 'text/html');
const subdirs = doc.querySelectorAll('h2 + ul li a');
const items = doc.querySelectorAll('.grid-item');
const { subdirs, itemCount } = this.extractPageData(doc);
const baseUrl = path.replace(/\/[^\/]*$/, '/');
// Check if this is an empty directory (only one subdirectory, no items)
if (items.length === 0 && subdirs.length === 1) {
const subdir = subdirs[0];
const href = subdir.getAttribute('href');
if (href) {
const baseUrl = path.replace(/\/[^\/]*$/, '/');
const subPath = baseUrl + href;
const collapsedPath = await this.getCollapsedPath(path, subPath);
return await this.buildCollapsedTreeItem(collapsedPath, depth, currentPath, maxDepth);
}
if (itemCount === 0 && subdirs.length === 1) {
const subPath = baseUrl + subdirs[0] + '/index.html';
const collapsedPath = await this.getCollapsedPath(path, subPath);
return await this.buildCollapsedTreeItem(collapsedPath, depth, currentPath, maxDepth);
}
// Normal directory processing
const indent = ' '.repeat(depth);
const folderName = path.split('/').filter(p => p !== '' && p !== 'index.html').pop() || 'Gallery';
const totalItems = items.length + subdirs.length;
const totalItems = itemCount + subdirs.length;
const arrow = depth === 0 ? '' : '└─ ';
let html = '';
if (path === currentPath) {
html += `<div class="tree-item">${indent}${arrow}📁 <span class="tree-current">${folderName}</span> (${totalItems} items)</div>`;
} else {
html += `<div class="tree-item">${indent}${arrow}📁 <a href="${path}" class="tree-link">${folderName}</a> (${totalItems} items)</div>`;
}
for (let i = 0; i < subdirs.length; i++) {
const subdir = subdirs[i];
const href = subdir.getAttribute('href');
if (href) {
const baseUrl = path.replace(/\/[^\/]*$/, '/');
const subPath = baseUrl + href;
html += await this.buildTreeRecursive(subPath, depth + 1, currentPath, maxDepth);
}
for (const subdir of subdirs) {
const subPath = baseUrl + subdir + '/index.html';
html += await this.buildTreeRecursive(subPath, depth + 1, currentPath, maxDepth);
}
return html;
} catch (error) {
const indent = ' '.repeat(depth);
@@ -122,41 +127,30 @@ export class NavigationManager {
async getCollapsedPath(startPath, currentPath) {
const pathSegments = [];
let path = startPath;
while (true) {
try {
const response = await fetch(path);
const htmlContent = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(htmlContent, 'text/html');
const subdirs = doc.querySelectorAll('h2 + ul li a');
const items = doc.querySelectorAll('.grid-item');
const { subdirs, itemCount } = this.extractPageData(doc);
const folderName = path.split('/').filter(p => p !== '' && p !== 'index.html').pop() || 'Gallery';
pathSegments.push({ name: folderName, path: path });
if (items.length > 0 || subdirs.length !== 1) {
break;
}
const subdir = subdirs[0];
const href = subdir.getAttribute('href');
if (href) {
const baseUrl = path.replace(/\/[^\/]*$/, '/');
path = baseUrl + href;
} else {
if (itemCount > 0 || subdirs.length !== 1) {
break;
}
const baseUrl = path.replace(/\/[^\/]*$/, '/');
path = baseUrl + subdirs[0] + '/index.html';
} catch (error) {
break;
}
}
return {
segments: pathSegments,
finalPath: path
};
return { segments: pathSegments, finalPath: path };
}
/**
@@ -165,10 +159,10 @@ export class NavigationManager {
async buildCollapsedTreeItem(collapsedPath, depth, currentPath, maxDepth) {
const indent = ' '.repeat(depth);
const arrow = depth === 0 ? '' : '└─ ';
const displayName = collapsedPath.segments.map(seg => seg.name).join(' / ');
const finalPath = collapsedPath.finalPath;
let totalItems = 0;
let subdirs = [];
try {
@@ -176,33 +170,25 @@ export class NavigationManager {
const htmlContent = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(htmlContent, 'text/html');
const subdirElements = doc.querySelectorAll('h2 + ul li a');
const items = doc.querySelectorAll('.grid-item');
totalItems = items.length + subdirElements.length;
subdirs = Array.from(subdirElements);
} catch (error) {
// Handle error case
}
const data = this.extractPageData(doc);
totalItems = data.itemCount + data.subdirs.length;
subdirs = data.subdirs;
} catch (error) {}
let html = '';
if (finalPath === currentPath) {
html += `<div class="tree-item">${indent}${arrow}📁 <span class="tree-current">${displayName}</span> (${totalItems} items)</div>`;
} else {
html += `<div class="tree-item">${indent}${arrow}📁 <a href="${finalPath}" class="tree-link">${displayName}</a> (${totalItems} items)</div>`;
}
for (let i = 0; i < subdirs.length; i++) {
const subdir = subdirs[i];
const href = subdir.getAttribute('href');
if (href) {
const baseUrl = finalPath.replace(/\/[^\/]*$/, '/');
const subPath = baseUrl + href;
html += await this.buildTreeRecursive(subPath, depth + 1, currentPath, maxDepth);
}
const baseUrl = finalPath.replace(/\/[^\/]*$/, '/');
for (const subdir of subdirs) {
const subPath = baseUrl + subdir + '/index.html';
html += await this.buildTreeRecursive(subPath, depth + 1, currentPath, maxDepth);
}
return html;
}
}