Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-24 - HTML Directory Listing Semantic Navigation & Decorative Icons
**Learning:** When generating raw HTML pages (like directory listings), unicode icons (e.g., &#128193; for folders, &#x21B0; for parent dir) are announced poorly by screen readers. Furthermore, a bare `<ul>` lacks semantic context. Wrapping the list in `<nav>`, the page in `<main>`, and specifically using `<span aria-hidden="true">`, while adding descriptive `aria-label`s on the links, significantly improves the structural understanding and voice announcements for keyboard/screen reader users.
**Action:** Always wrap decorative or visually symbolic unicode characters in `<span aria-hidden="true">`, wrap primary navigation in a `<nav>` element, and explicitly provide `aria-label`s for links where visual icons substitute context.
16 changes: 11 additions & 5 deletions src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,11 @@ fun process_dir(curr_dir: File){
${css}
</head>
<body>
<h1>${curr_dir.getName().escapeHtml()}</h1>
<ul>
<li><a style="display:block; width:100%" href="./.." aria-label="์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™">&#x21B0; ..</a></li>
<main>
<h1>${curr_dir.getName().escapeHtml()}</h1>
<nav aria-label="ํŒŒ์ผ ํƒ์ƒ‰">
<ul>
<li><a style="display:block; width:100%" href="./.." aria-label="์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™"><span aria-hidden="true">&#x21B0;</span> ..</a></li>
"""

val index_middle = fun():String{
Expand All @@ -131,15 +133,19 @@ fun process_dir(curr_dir: File){
dir_files.forEach {
val isLinkedDirectory = it.isDirectory() && !java.nio.file.Files.isSymbolicLink(it.toPath())
if((it.getName() !in exclude) && (isLinkedDirectory || !it.isDirectory())) {
l += """ <li><a style="display:block; width:100%" href="${if (isLinkedDirectory) { "./${it.getName().urlEncodePath()}/" } else { "./${it.getName().urlEncodePath()}" }}">${if (isLinkedDirectory) { "&#128193;" } else { "&rtrif;" }} ${it.getName().escapeHtml()}</a></li>"""+"\n"
val ariaLabel = if (isLinkedDirectory) { "aria-label=\"${it.getName().escapeHtml()} ๋””๋ ‰ํ† ๋ฆฌ\"" } else { "aria-label=\"${it.getName().escapeHtml()} ํŒŒ์ผ\"" }
val icon = if (isLinkedDirectory) { "<span aria-hidden=\"true\">&#128193;</span>" } else { "<span aria-hidden=\"true\">&rtrif;</span>" }
l += """ <li><a style="display:block; width:100%" href="${if (isLinkedDirectory) { "./${it.getName().urlEncodePath()}/" } else { "./${it.getName().urlEncodePath()}" }}" $ariaLabel>$icon ${it.getName().escapeHtml()}</a></li>"""+"\n"
}
}

return l;
}

val index_bottom="""
</ul>
</ul>
</nav>
</main>
</body>
</html>
"""
Expand Down
11 changes: 9 additions & 2 deletions src/test/kotlin/html4tree/MainTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ class MainTest {
go(tempDir.absolutePath, -1)
val indexFile = File(tempDir, "index.html")
assertTrue(indexFile.exists())
assertTrue(indexFile.readText().contains("<html lang=\"ko\">"))
val htmlContent = indexFile.readText()
assertTrue(htmlContent.contains("<html lang=\"ko\">"))
assertTrue(htmlContent.contains("<main>"))
assertTrue(htmlContent.contains("<nav aria-label=\"ํŒŒ์ผ ํƒ์ƒ‰\">"))
assertTrue(htmlContent.contains("<span aria-hidden=\"true\">&#x21B0;</span>"))
}

@Test
Expand Down Expand Up @@ -113,7 +117,10 @@ class MainTest {
assertTrue(htmlContent.contains("aria-label=\"์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™\""))
assertTrue(htmlContent.contains("file1.txt"))
assertTrue(htmlContent.contains("subdir/"))
assertTrue(htmlContent.contains("&#128193;"))
assertTrue(htmlContent.contains("<span aria-hidden=\"true\">&#128193;</span>"))
assertTrue(htmlContent.contains("<span aria-hidden=\"true\">&rtrif;</span>"))
assertTrue(htmlContent.contains("aria-label=\"subdir ๋””๋ ‰ํ† ๋ฆฌ\""))
assertTrue(htmlContent.contains("aria-label=\"file1.txt ํŒŒ์ผ\""))
assertFalse(htmlContent.contains("test.ignore"))
}

Expand Down