view hg-web/src/index.js @ 207:58d9b64d8dca

Updated deployment script to include sqlite3
author MrJuneJune <me@mrjunejune.com>
date Sun, 15 Feb 2026 12:25:50 -0800
parents ffb764d2fcc5
children
line wrap: on
line source

const API_BASE = '/api/repo';

function getCurrentPath() {
  const params = new URLSearchParams(window.location.search);
  return params.get('path') || '';
}

function renderBreadcrumb(path) {
  const breadcrumb = document.getElementById('breadcrumb');
  if (!path) {
    breadcrumb.innerHTML = '<a href="/">Root</a>';
    return;
  }

  const parts = path.split('/').filter(p => p);
  let currentPath = '';
  let html = '<a href="/">Root</a>';

  parts.forEach((part, index) => {
    currentPath += (currentPath ? '/' : '') + part;
    html += ` <span>/</span> `;
    if (index === parts.length - 1) {
      html += `<span>${part}</span>`;
    } else {
      html += `<a href="?path=${encodeURIComponent(currentPath)}">${part}</a>`;
    }
  });

  breadcrumb.innerHTML = html;
}

function renderFiles(files, directories) {
  if (!files || files.length === 0) {
    fileList.style.display = 'none';
    emptyState.style.display = 'block';
    return;
  }

  emptyState.style.display = 'none';
  fileList.style.display = 'block';

  let html = '';
  directories.forEach(file => {
    const icon = '📁';
    const className = file.type;
    const href = `?path=${encodeURIComponent(file.abspath)}`;
    const target =  '';

    html += `
      <div class="file-item ${className}">
        <span class="icon">${icon}</span>
        <span class="name">
          <a href="${href}" ${target}>${file.basename}</a>
        </span>
      </div>
    `;
  });
  files.forEach(file => {
    const icon = '📄';
    const className = file.type;
    const href = `/api/repo/file?path=${encodeURIComponent(file.abspath)}`;
    const target = 'target="_blank"';

    html += `
      <div class="file-item ${className}">
        <span class="icon">${icon}</span>
        <span class="name">
          <a href="${href}" ${target}>${file.basename}</a>
        </span>
      </div>
    `;
  });

  fileList.innerHTML = html;
}

async function loadReadme(path) {
  const readmeSection = document.getElementById('readmeSection');
  const readmeContent = document.getElementById('readmeContent');

  try {
    const readmePath = path ? `${path}/README.md` : 'README.md';
    const response = await fetch(`/api/repo/readme?path=${encodeURIComponent(readmePath)}`);

    if (response.ok) {
      const markdown = await response.text();
      readmeSection.style.display = 'block';
      renderMarkdown(readmeContent, markdown);
    } else {
      readmeSection.style.display = 'none';
    }
  } catch (error) {
    readmeSection.style.display = 'none';
  }
}

async function loadDirectory(path) {
  try {
    const url = path ? `${API_BASE}/list?path=${encodeURIComponent(path)}` : `${API_BASE}/list`;
    const response = await fetch(url);
    const data = await response.json();

    if (data.error) {
      throw new Error(data.error);
    }

    const { files, directories } = data;

    renderBreadcrumb(path);
    renderFiles(files, directories);
    loadReadme(path);
  } catch (error) {
    console.error('Error loading directory:', error);
    document.getElementById('fileList').innerHTML = `
      <div class="error-message">Error loading directory: ${error.message}</div>
    `;
  }
}

window.addEventListener('popstate', (event) => {
  const path = event.state?.path || '';
  loadDirectory(path);
});

const currentPath = getCurrentPath();
loadDirectory(currentPath);