From 477ca7f4ac027573ca70f788aa293c42ee13c8c4 Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Wed, 2 Sep 2026 20:42:48 -0700 Subject: [PATCH] Match Splatoon 3 directory browser styling The initial Worker used a simplified renderer that omitted the established layout styles and folder/file icon markup. --- worker/index.js | 319 ++++++++++++++++++++++++++++++++++++++---- worker/index.spec.mjs | 4 + 2 files changed, 299 insertions(+), 24 deletions(-) diff --git a/worker/index.js b/worker/index.js index 37268fb..ddea0a4 100644 --- a/worker/index.js +++ b/worker/index.js @@ -155,7 +155,7 @@ function breadcrumbHtml(prefix) { let crumbs = ['assets']; for (let index = 0; index < parts.length; index++) { - crumbs.push(''); + crumbs.push(''); if (index === parts.length - 1) { crumbs.push(`${escapeHtml(parts[index])}`); } else { @@ -170,26 +170,29 @@ function breadcrumbHtml(prefix) { function renderListing(page) { let rows = []; if (page.prefix) { - rows.push(`
  • Parent directoryFolder
  • `); + rows.push(`
  • Name: Parent directory
  • `); } for (let directory of page.directories) { - rows.push(`
  • ${escapeHtml(directory.name)}Folder
  • `); + rows.push(`
  • Name: ${escapeHtml(directory.name)}Type: Folder
  • `); } for (let file of page.files) { - rows.push(`
  • ${escapeHtml(file.name)}${formatSize(file.size)}
  • `); + rows.push(`
  • Name: ${escapeHtml(file.name)}Last modified: Size: ${formatSize(file.size)}
  • `); } if (!rows.length) { - rows.push('
  • This directory is empty.
  • '); + rows.push('
  • This directory is empty.
  • '); } let jsonCursor = page.requestedCursor ? `&cursor=${encodeURIComponent(page.requestedCursor)}` : ''; let next = page.nextCursor - ? `` + ? `` : ''; let title = `Asset browser — ${page.pathname}`; let nonce = crypto.randomUUID().replaceAll('-', ''); + let folderCount = page.directories.length; + let fileCount = page.files.length; + let summary = `${folderCount} ${folderCount === 1 ? 'folder' : 'folders'} · ${fileCount} ${fileCount === 1 ? 'file' : 'files'}`; return { body: ` @@ -202,27 +205,295 @@ function renderListing(page) { ${escapeHtml(title)} -
    -
    ${page.directories.length} folders · ${page.files.length} files · JSON
    - -
    ${next}
    +
    +
    +
    + +
    ${summary}JSON
    +
    +
    +
    +
    NameLast modifiedSize
    +
      ${rows.join('')}
    +
    +
    + +
    `, diff --git a/worker/index.spec.mjs b/worker/index.spec.mjs index e76b096..c2df229 100644 --- a/worker/index.spec.mjs +++ b/worker/index.spec.mjs @@ -37,6 +37,10 @@ describe('R2 directory index', () => { expect(response.status).toBe(200); expect(response.headers.get('content-type')).toBe('text/html; charset=utf-8'); expect(response.headers.get('cache-control')).toBe('no-store'); + expect(html).toContain('
    '); + expect(html).toContain('class="entry-icon entry-icon--folder"'); + expect(html).toContain('class="entry-icon entry-icon--file"'); + expect(html).toContain('class="listing-header"'); expect(html).toContain('href="/data/locale/"'); expect(html).toContain('href="/data/schedules.json"'); expect(html).not.toContain('__directory');