rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1package gallery
2
3import (
4 "sort"
5 "strings"
6
7 "amadan.net/rastrillo/fiesta"
8)
9
10// formerRTL is the directory a theme's right-to-left twin had before
11// every page moved under a locale: <theme>/rtl/<page>, beside the
12// English <theme>/<page>. Those addresses were published, so they are
13// redirected rather than left to 404.
14const formerRTL = "rtl"
15
16// Redirects are the _redirects rules, for a tree rendered for mount,
17// that send each address the gallery had before its pages moved under
18// a locale to the page that is there now, with a 301:
19//
20// <theme>/ <theme>/en/
21// <theme>/index.html <theme>/en/
22// <theme>/<page>.html <theme>/en/<page>.html
23// <theme>/frames/<example>/<state> <theme>/en/frames/<example>/<state>
24// <theme>/rtl/... the same under <theme>/ar/
25//
26// An index goes to its directory, the address the edge serves it at,
27// since the edge sends .../index.html on to ./ and that would be a
28// second hop. The rules are written so that no source can match a
29// file of the tree, and no destination can match a source, so none
30// shadows a page and none leads to another: every file of today's tree
31// sits under <theme>/<locale>/ or assets/, and no locale is "frames",
32// "rtl", "index.html" or a page's name. So <theme>/rtl/:page can be one
33// rule, but an English page is named rule by rule: <theme>/:page would
34// also match <theme>/en, the English tree's own directory. The pages
35// named are the ones tree holds at <theme>/en/ in every theme, so each
36// destination is a page whatever the theme. The order is fixed, so the
37// same tree gives the same rules.
38func Redirects(mount string, tree map[string][]byte) []string {
39 m := cleanMount(mount)
40 en, ar := Locales[0], rtlLocale()
41 var out []string
42 rule := func(from, to string) { out = append(out, m+from+" "+m+to+" 301") }
43
44 themes := fiesta.ThemeNames()
45 for _, theme := range themes {
46 rule("/"+theme, "/"+theme+"/"+en+"/")
47 }
48 rule("/:theme/index.html", "/:theme/"+en+"/")
49 rule("/:theme/frames/:example/:state", "/:theme/"+en+"/frames/:example/:state")
50 for _, page := range everyThemesPages(tree, themes, en) {
51 rule("/:theme/"+page, "/:theme/"+en+"/"+page)
52 }
53
54 twin := "/:theme/" + formerRTL
55 rule(twin, "/:theme/"+ar+"/")
56 rule(twin+"/index.html", "/:theme/"+ar+"/")
57 rule(twin+"/frames/:example/:state", "/:theme/"+ar+"/frames/:example/:state")
58 rule(twin+"/:page", "/:theme/"+ar+"/:page")
59 return out
60}
61
62// rtlLocale is the locale that renders right to left, where the former
63// twins now live.
64func rtlLocale() string {
65 for _, l := range Locales {
66 if Dir(l) == "rtl" {
67 return l
68 }
69 }
70 panic("gallery: no locale renders right to left")
71}
72
73// everyThemesPages are the names of the HTML pages directly under
74// <theme>/<locale>/ for every theme, the index aside, sorted.
75func everyThemesPages(tree map[string][]byte, themes []string, locale string) []string {
76 count := map[string]int{}
77 for name := range tree {
78 for _, theme := range themes {
79 page, ok := strings.CutPrefix(name, theme+"/"+locale+"/")
80 if ok && !strings.Contains(page, "/") && strings.HasSuffix(page, ".html") && page != "index.html" {
81 count[page]++
82 }
83 }
84 }
85 var pages []string
86 for page, n := range count {
87 if n == len(themes) {
88 pages = append(pages, page)
89 }
90 }
91 sort.Strings(pages)
92 return pages
93}
94