63 lines
1.9 KiB
JavaScript
63 lines
1.9 KiB
JavaScript
// Fetch and render directory tree
|
|
const treeContainer = document.getElementById('tree');
|
|
const contentContainer = document.getElementById('content');
|
|
|
|
function fetchTree(relPath = '') {
|
|
fetch(`/api/tree?path=${encodeURIComponent(relPath)}`)
|
|
.then(r => r.json())
|
|
.then(data => renderTree(data, relPath))
|
|
.catch(err => console.error('Tree error', err));
|
|
}
|
|
|
|
function renderTree(items, parentPath) {
|
|
const ul = document.createElement('ul');
|
|
items.forEach(item => {
|
|
const li = document.createElement('li');
|
|
li.dataset.path = item.path;
|
|
const span = document.createElement('span');
|
|
span.textContent = item.name;
|
|
li.appendChild(span);
|
|
if (item.type === 'dir') {
|
|
li.classList.add('dir');
|
|
span.onclick = () => {
|
|
// Toggle expansion
|
|
if (li.dataset.loaded) {
|
|
const child = li.querySelector('ul');
|
|
if (child) child.style.display = child.style.display === 'none' ? 'block' : 'none';
|
|
} else {
|
|
fetchTree(item.path);
|
|
li.dataset.loaded = 'true';
|
|
}
|
|
};
|
|
} else if (item.type === 'file') {
|
|
li.classList.add('file');
|
|
span.onclick = () => loadMarkdown(item.path);
|
|
}
|
|
ul.appendChild(li);
|
|
});
|
|
// Append under the correct parent node
|
|
const parentLi = treeContainer.querySelector(`li[data-path="${parentPath.replace(/"/g,'\\"')}"]`);
|
|
if (parentLi) {
|
|
// If already has a child ul, replace it
|
|
const existing = parentLi.querySelector('ul');
|
|
if (existing) parentLi.replaceChild(ul, existing);
|
|
else parentLi.appendChild(ul);
|
|
} else {
|
|
// Root level
|
|
treeContainer.innerHTML = '';
|
|
treeContainer.appendChild(ul);
|
|
}
|
|
}
|
|
|
|
function loadMarkdown(relPath) {
|
|
fetch(`/api/md?path=${encodeURIComponent(relPath)}`)
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
contentContainer.innerHTML = data.html;
|
|
})
|
|
.catch(err => console.error('MD load error', err));
|
|
}
|
|
|
|
// Initial load of root directory
|
|
fetchTree();
|