diff hg-web/src/index.js @ 135:ffb764d2fcc5

[HgWeb] Updated hg web so it works
author June Park <parkjune1995@gmail.com>
date Fri, 09 Jan 2026 11:17:20 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hg-web/src/index.js	Fri Jan 09 11:17:20 2026 -0800
@@ -0,0 +1,126 @@
+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);