From e578f1278f570ab5e41b9907cd7b2a820193f124 Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 10 Sep 2026 15:51:14 +1000 Subject: [PATCH] fix(loader): index.md article slug = folder name; skip subject-root index.md --- app/src/content.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/src/content.go b/app/src/content.go index df2d860..3c663c0 100644 --- a/app/src/content.go +++ b/app/src/content.go @@ -180,6 +180,12 @@ func (c *Content) loadSubject(slug string) (*Subject, error) { // (skips _prefixed dirs/files: config, templates). Supports both flat // subjects//.md and folder-per-article subjects///.md. func (c *Content) loadFilesUnder(dir string, out *[]*Article) error { + return c.loadFilesUnderDepth(dir, out, 0) +} + +// loadFilesUnderDepth: depth 0 = collection/subject root (skip index.md as it's the +// subject's own index), depth 1+ = article folders (index.md IS the article). +func (c *Content) loadFilesUnderDepth(dir string, out *[]*Article, depth int) error { entries, err := os.ReadDir(dir) if err != nil { return err @@ -189,17 +195,21 @@ func (c *Content) loadFilesUnder(dir string, out *[]*Article) error { if e.IsDir() { // recurse one level (article folder) — skip hidden/_ folders (e.g. _attachments) if !strings.HasPrefix(name, "_") { - c.loadFilesUnder(path.Join(dir, name), out) + c.loadFilesUnderDepth(path.Join(dir, name), out, depth + 1) } continue } if !strings.HasSuffix(name, ".md") { continue } - // skip _ files (config, templates) BUT _index.md is the real article in a folder + // skip _ files (config, templates) — but index.md/_index.md in a folder is the article if strings.HasPrefix(name, "_") && name != "_index.md" { continue } + // at the subject/collection root (depth 0), index.md = the subject's own index — skip + if depth == 0 && (name == "index.md" || name == "_index.md") { + continue + } if a, err := c.loadFile(path.Join(dir, name)); err == nil { // unpublished articles are drafts — load, then hide from all listings *out = append(*out, a) @@ -338,15 +348,16 @@ func parseFrontMatter(text string) (FrontMatter, string, bool) { } // slugOf derives a slug from a file path: dir/file.md -> file +// slugOf derives a slug from a file path: dir/index.md -> folder name (Decap nested), +// otherwise dir/file.md -> file base. func slugOf(full string) string { base := path.Base(full) base = strings.TrimSuffix(base, ".md") - // article files are now /_index.md — the slug is the folder name. - if base == "_index" { + // article files are now /index.md (Decap nested) — slug is the folder name. + if base == "_index" || base == "index" { dir := path.Dir(full) base = path.Base(dir) } - // lowercase for URL-friendly slugs return strings.ToLower(base) }