summaryrefslogtreecommitdiff
diff options
from:
to:
context:
space:
mode:
authorGravatar Saya Andy <145215889+SayaAndy@users.noreply.github.com> 2025-10-17 19:28:37 +0700
committerGravatar GitHub <noreply@github.com> 2025-10-17 19:28:37 +0700
commitfa2d3009ed93c28e05758d52367b25fd6a04a2b7 (patch)
treec4a05a93b5b5a1c586f0ed8a9eea2ef2f90dd3c6
parent2e93141f1f53410d6c38122b918972581ec4aa8d (diff)
parent152bbebe8d2d0a07ab6958a74b5f53159c79e45f (diff)
downloadweb-fa2d3009ed93c28e05758d52367b25fd6a04a2b7.tar.gz
web-fa2d3009ed93c28e05758d52367b25fd6a04a2b7.zip
v0.9.0 (#10)v0.9.0
- [feat: implement new prototype gallery](https://github.com/SayaAndy/saya-today-web/commit/44fe2478478225450becb77ad5d273462c9b400a) (masonry + glightbox instead of lightgallery) - A simpler column gallery, expandable between 2 and 5 columns; - Allows highlighting images via tags; - A simpler lightbox layout with wider image, especially on mobile devices; - Displays tooltips; - [feat: adapted layouts for mobile/tablet devices](https://github.com/SayaAndy/saya-today-web/commit/d3ffefbd3d9de2378b564e4c6f965c03a5a06113) - [feat: switched most length units to absolute in layouts](https://github.com/SayaAndy/saya-today-web/commit/454e2f3cd84b6c0b02a0c2936a574d3d9c35c5a1) - [feat: use dvw/dvh instead of vw/vh](https://github.com/SayaAndy/saya-today-web/commit/e231d8a3074853fbdbae9b368976bd902a1428f7) - [feat: add onclick links in blog post links](https://github.com/SayaAndy/saya-today-web/commit/db174993127a8b2faf863a670fd6ce8ca8d7c1af) - feat: add href for any onclick links/icons - feat: use page-first layout for page titles (like "{page-header} // SAYA TODAY", not vice versa) - chore: rm any remains of old lightgallery - fix: map redefining
-rw-r--r--internal/glightbox/block.go32
-rw-r--r--internal/glightbox/extension.go (renamed from internal/lightgallery/extension.go)14
-rw-r--r--internal/glightbox/html_renderer.go188
-rw-r--r--internal/glightbox/parser.go (renamed from internal/lightgallery/parser.go)42
-rw-r--r--internal/lightgallery/block.go31
-rw-r--r--internal/lightgallery/html_renderer.go145
-rw-r--r--internal/router/api-v1-general-page-body.go2
-rw-r--r--internal/tailwind/link_renderer.go49
-rw-r--r--internal/tailwind/transformer.go33
-rw-r--r--internal/templatemanager/templatemanager.go4
-rw-r--r--locale/localization.en.yaml3
-rw-r--r--locale/localization.go6
-rw-r--r--locale/localization.ru.yaml3
-rw-r--r--main.go18
-rw-r--r--static/input.css412
-rw-r--r--views/index.html18
-rw-r--r--views/layouts/general-page.html63
-rw-r--r--views/pages/blog-catalogue.html40
-rw-r--r--views/pages/blog-page.html78
-rw-r--r--views/pages/global-map.html28
-rw-r--r--views/pages/home-page.html62
-rw-r--r--views/partials/blog-page-like-button.html6
-rw-r--r--views/partials/catalogue-blog-cards.html26
-rw-r--r--views/partials/general-page-body.html2
-rw-r--r--views/partials/general-page-footer.html8
-rw-r--r--views/partials/general-page-header.html12
26 files changed, 697 insertions, 628 deletions
diff --git a/internal/glightbox/block.go b/internal/glightbox/block.go
new file mode 100644
index 0000000..e53e67b
--- /dev/null
+++ b/internal/glightbox/block.go
@@ -0,0 +1,32 @@
+package glightbox
+
+import (
+ "time"
+
+ "github.com/yuin/goldmark/ast"
+)
+
+// GLightboxBlock represents a light gallery block in the AST
+type GLightboxBlock struct {
+ ast.BaseBlock
+ Images []GLightboxImage
+ Location *time.Location
+}
+
+type GLightboxImage struct {
+ URL string
+ Tags []string
+ Caption []byte
+}
+
+var KindGLightboxBlock = ast.NewNodeKind("GLightboxBlock")
+
+// Dump implements ast.Node.Dump
+func (n *GLightboxBlock) Dump(source []byte, level int) {
+ ast.DumpHelper(n, source, level, nil, nil)
+}
+
+// Kind implements ast.Node.Kind
+func (n *GLightboxBlock) Kind() ast.NodeKind {
+ return KindGLightboxBlock
+}
diff --git a/internal/lightgallery/extension.go b/internal/glightbox/extension.go
index 761dc05..7fd17b1 100644
--- a/internal/lightgallery/extension.go
+++ b/internal/glightbox/extension.go
@@ -1,4 +1,4 @@
-package lightgallery
+package glightbox
import (
"github.com/yuin/goldmark"
@@ -8,21 +8,21 @@ import (
)
// Extension that combines parser and renderer
-type LightGalleryExtension struct{}
+type GLightboxExtension struct{}
-func NewLightGalleryExtension() goldmark.Extender {
- return &LightGalleryExtension{}
+func NewGLightboxExtension() goldmark.Extender {
+ return &GLightboxExtension{}
}
-func (e *LightGalleryExtension) Extend(m goldmark.Markdown) {
+func (e *GLightboxExtension) Extend(m goldmark.Markdown) {
m.Parser().AddOptions(
parser.WithBlockParsers(
- util.Prioritized(NewLightGalleryParser(), 500),
+ util.Prioritized(NewGLightboxParser(), 500),
),
)
m.Renderer().AddOptions(
renderer.WithNodeRenderers(
- util.Prioritized(NewLightGalleryHTMLRenderer(), 500),
+ util.Prioritized(NewGLightboxHTMLRenderer(), 500),
),
)
}
diff --git a/internal/glightbox/html_renderer.go b/internal/glightbox/html_renderer.go
new file mode 100644
index 0000000..44fbd4c
--- /dev/null
+++ b/internal/glightbox/html_renderer.go
@@ -0,0 +1,188 @@
+package glightbox
+
+import (
+ "bytes"
+ "fmt"
+ "math/rand"
+ "regexp"
+ "strings"
+ "time"
+
+ "github.com/SayaAndy/saya-today-web/internal/tailwind"
+ "github.com/yuin/goldmark"
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/parser"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/util"
+)
+
+type GLightboxHTMLRenderer struct {
+ html.Config
+ md goldmark.Markdown
+ anchorMatchRe *regexp.Regexp
+}
+
+func NewGLightboxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
+ r := &GLightboxHTMLRenderer{
+ Config: html.NewConfig(),
+ md: goldmark.New(
+ goldmark.WithParserOptions(
+ parser.WithAutoHeadingID(),
+ parser.WithAttribute(),
+ ),
+ goldmark.WithRenderer(
+ renderer.NewRenderer(
+ renderer.WithNodeRenderers(
+ util.Prioritized(tailwind.NewCustomLinkRenderer(
+ html.WithUnsafe(), html.WithHardWraps(), html.WithXHTML(),
+ ), 50),
+ util.Prioritized(html.NewRenderer(
+ html.WithUnsafe(), html.WithHardWraps(), html.WithXHTML(),
+ ), 100),
+ ),
+ ),
+ ),
+ ),
+ }
+ for _, opt := range opts {
+ opt.SetHTMLOption(&r.Config)
+ }
+ r.anchorMatchRe = regexp.MustCompile(`(?s)<\s*a(\s+[^<]*)(href\s*=\s*["'].*?["'])\s*([^<]*)>(.*?)<\s*\/\s*a\s*>`)
+ return r
+}
+
+func (r *GLightboxHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
+ reg.Register(KindGLightboxBlock, r.renderGLightbox)
+}
+
+func (r *GLightboxHTMLRenderer) renderGLightbox(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if entering {
+ gallery := n.(*GLightboxBlock)
+
+ if len(gallery.Images) == 0 {
+ return ast.WalkContinue, nil
+ }
+
+ galleryID := generateDivId(8)
+
+ var elements []string
+ for i, img := range gallery.Images {
+ imageUrlSegments := strings.Split(img.URL, ".")
+ imageUrlWithoutExt := strings.Join(imageUrlSegments[:len(imageUrlSegments)-1], ".")
+ imageUrlParts := strings.Split(imageUrlWithoutExt, "/")
+ imageNameParts := strings.Split(imageUrlParts[len(imageUrlParts)-1], "-")
+
+ var captionBuf bytes.Buffer
+ captionHTML := img.Caption
+ if err := r.md.Convert(img.Caption, &captionBuf); err == nil {
+ captionHTML = captionBuf.Bytes()
+ captionHTML = bytes.TrimPrefix(captionHTML, []byte("<p>"))
+ captionHTML = bytes.TrimSuffix(captionHTML, []byte("</p>\n"))
+ captionHTML = bytes.TrimSuffix(captionHTML, []byte("</p>"))
+ }
+
+ dayDate, _ := time.Parse("20060102 150405", imageNameParts[len(imageNameParts)-2]+" "+imageNameParts[len(imageNameParts)-1])
+ dayDate = dayDate.In(gallery.Location)
+
+ glightboxDescId := ""
+ if len(captionHTML) != 0 {
+ glightboxDescId = fmt.Sprintf("glightbox-desc-%s-%d", galleryID, i)
+ }
+
+ dataDescriptionAttribute := ""
+ if glightboxDescId != "" {
+ dataDescriptionAttribute = fmt.Sprintf("data-description=\".%s\"", glightboxDescId)
+ }
+
+ tagClassList := make([]string, 0, len(img.Tags))
+ for _, tag := range img.Tags {
+ switch tag {
+ case "2x":
+ tagClassList = append(tagClassList, "grid-item-2x")
+ }
+ }
+
+ if len(img.Caption) > 0 {
+ tagClassList = append(tagClassList, "grid-tooltip")
+ }
+
+ anchorlessCaptionHTML := r.anchorMatchRe.ReplaceAll(captionHTML, []byte("<span class=\"linklike\" $1 $3>$4</span>"))
+
+ elements = append(elements, fmt.Sprintf(`
+ <a href="https://f003.backblazeb2.com/file/sayana-photos/full/%s" class="glightbox-%s grid-item %s grid-item-%s p-1"
+ data-gallery="gallery-%s" data-title="%s" %s>
+ <picture>
+ <source media="(width < 640px)" srcset="https://f003.backblazeb2.com/file/sayana-photos/webp-320p/%s.webp" />
+ <source media="(width < 1120px)" srcset="https://f003.backblazeb2.com/file/sayana-photos/webp-560p/%s.webp" />
+ <source media="(width < 1600px)" srcset="https://f003.backblazeb2.com/file/sayana-photos/webp-800p/%s.webp" />
+ <source media="(width < 2400px)" srcset="https://f003.backblazeb2.com/file/sayana-photos/webp-1200p/%s.webp" />
+ <source media="(width >= 2400px)" srcset="https://f003.backblazeb2.com/file/sayana-photos/webp-1600p/%s.webp" />
+ <img src="https://f003.backblazeb2.com/file/sayana-photos/webp-800p/%s.webp" />
+ </picture>
+ <span class="grid-tooltip-text"><p>%s</p></span>
+ <span class="grid-item-index">%d</span>
+ </a>`, img.URL, galleryID, strings.Join(tagClassList, " "), galleryID, galleryID, dayDate.Format("2006-01-02 15:04:05 -07:00"), dataDescriptionAttribute, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, anchorlessCaptionHTML, i+1))
+
+ if glightboxDescId != "" {
+ elements = append(elements, fmt.Sprintf(`
+ <div class="glightbox-desc rounded-4 %s">
+ <p>%s</p>
+ </div>`, glightboxDescId, captionHTML))
+ }
+ }
+
+ w.WriteString(fmt.Sprintf(`
+<div class="justify-content-center display-block m-1">
+ <hr class="border-t-3 border-dotted border-main-dark mt-1 mb-2 w-[80%%] ml-auto mr-auto">
+ <div class="grid masonry-grid-%s mx-auto">
+ <div class="grid-sizer grid-sizer-%s"></div>
+ %s
+ </div>
+ <hr class="border-t-3 border-dotted border-main-dark mt-1 mb-2 w-[80%%] ml-auto mr-auto">
+</div>`, galleryID, galleryID, strings.Join(elements, "\n")))
+
+ w.WriteString(fmt.Sprintf(`
+<script>
+ var lightbox_%s = GLightbox({
+ selector: '.glightbox-%s',
+ moreLength: 0
+ });
+
+ var msnry_%s = new Masonry('.masonry-grid-%s', {
+ itemSelector: '.grid-item-%s',
+ columnWidth: '.grid-sizer-%s',
+ percentPosition: true,
+ horizontalOrder: true
+ });
+
+ var imgLoad_%s_timer;
+ var imgLoad_%s = imagesLoaded('.masonry-grid-%s');
+
+ function initMasonryLayout_%s() {
+ clearTimeout(imgLoad_%s_timer);
+ imgLoad_%s_timer = setTimeout(() => msnry_%s.layout(), 500);
+ }
+
+ imgLoad_%s.on('progress', initMasonryLayout_%s);
+
+ document.addEventListener('popout', (e) => {
+ imgLoad_%s.off('progress', initMasonryLayout_%s);
+ initMasonryLayout_%s = null;
+ imgLoad_%s = null;
+ });
+</script>`, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID))
+ }
+
+ return ast.WalkContinue, nil
+}
+
+func generateDivId(length int) string {
+ const charset = "abcdefghijklmnopqrstuvwxyz"
+ seededRand := rand.New(rand.NewSource(time.Now().UnixNano())) // Seed with current time
+ b := make([]byte, length)
+ for i := range b {
+ b[i] = charset[seededRand.Intn(len(charset))]
+ }
+ return string(b)
+}
diff --git a/internal/lightgallery/parser.go b/internal/glightbox/parser.go
index daec797..6780090 100644
--- a/internal/lightgallery/parser.go
+++ b/internal/glightbox/parser.go
@@ -1,9 +1,10 @@
-package lightgallery
+package glightbox
import (
"bytes"
"log/slog"
"regexp"
+ "strings"
"time"
"github.com/yuin/goldmark/ast"
@@ -11,17 +12,17 @@ import (
"github.com/yuin/goldmark/text"
)
-type LightGalleryParser struct{}
+type GLightboxParser struct{}
-func NewLightGalleryParser() parser.BlockParser {
- return &LightGalleryParser{}
+func NewGLightboxParser() parser.BlockParser {
+ return &GLightboxParser{}
}
-func (p *LightGalleryParser) Trigger() []byte {
+func (p *GLightboxParser) Trigger() []byte {
return []byte{'{'}
}
-func (p *LightGalleryParser) Open(parent ast.Node, reader text.Reader, pc parser.Context) (ast.Node, parser.State) {
+func (p *GLightboxParser) Open(parent ast.Node, reader text.Reader, pc parser.Context) (ast.Node, parser.State) {
line, _ := reader.PeekLine()
if !bytes.HasPrefix(line, []byte("{Gallery:")) {
@@ -43,10 +44,10 @@ func (p *LightGalleryParser) Open(parent ast.Node, reader text.Reader, pc parser
return nil, parser.NoChildren
}
- return &LightGalleryBlock{Location: loc}, parser.NoChildren
+ return &GLightboxBlock{Location: loc}, parser.NoChildren
}
-func (p *LightGalleryParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State {
+func (p *GLightboxParser) Continue(node ast.Node, reader text.Reader, pc parser.Context) parser.State {
line, segment := reader.PeekLine()
if len(line) == 0 || segment.Len() == 0 {
return parser.Continue | parser.NoChildren
@@ -58,31 +59,42 @@ func (p *LightGalleryParser) Continue(node ast.Node, reader text.Reader, pc pars
return parser.Close
}
- gallery := node.(*LightGalleryBlock)
+ gallery := node.(*GLightboxBlock)
- parts := bytes.SplitN(trimmed, []byte{'|'}, 2)
+ parts := bytes.SplitN(trimmed, []byte{'|'}, 3)
url := bytes.TrimSpace(parts[0])
caption := make([]byte, 0)
- if len(parts) > 1 {
+ tagsRaw := ""
+ if len(parts) == 2 {
caption = bytes.TrimSpace(parts[1])
}
+ if len(parts) >= 3 {
+ tagsRaw = string(parts[1])
+ caption = bytes.TrimSpace(parts[2])
+ }
+
+ tags := strings.Split(tagsRaw, ",")
+ for i := range tags {
+ tags[i] = strings.TrimSpace(tags[i])
+ }
- gallery.Images = append(gallery.Images, LightGalleryImage{
+ gallery.Images = append(gallery.Images, GLightboxImage{
URL: string(url),
+ Tags: tags,
Caption: caption,
})
return parser.Continue | parser.NoChildren
}
-func (p *LightGalleryParser) Close(node ast.Node, reader text.Reader, pc parser.Context) {
+func (p *GLightboxParser) Close(node ast.Node, reader text.Reader, pc parser.Context) {
}
-func (p *LightGalleryParser) CanInterruptParagraph() bool {
+func (p *GLightboxParser) CanInterruptParagraph() bool {
return true
}
-func (p *LightGalleryParser) CanAcceptIndentedLine() bool {
+func (p *GLightboxParser) CanAcceptIndentedLine() bool {
return false
}
diff --git a/internal/lightgallery/block.go b/internal/lightgallery/block.go
deleted file mode 100644
index 8eb7c9e..0000000
--- a/internal/lightgallery/block.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package lightgallery
-
-import (
- "time"
-
- "github.com/yuin/goldmark/ast"
-)
-
-// LightGalleryBlock represents a light gallery block in the AST
-type LightGalleryBlock struct {
- ast.BaseBlock
- Images []LightGalleryImage
- Location *time.Location
-}
-
-type LightGalleryImage struct {
- URL string
- Caption []byte
-}
-
-var KindLightGalleryBlock = ast.NewNodeKind("LightGalleryBlock")
-
-// Dump implements ast.Node.Dump
-func (n *LightGalleryBlock) Dump(source []byte, level int) {
- ast.DumpHelper(n, source, level, nil, nil)
-}
-
-// Kind implements ast.Node.Kind
-func (n *LightGalleryBlock) Kind() ast.NodeKind {
- return KindLightGalleryBlock
-}
diff --git a/internal/lightgallery/html_renderer.go b/internal/lightgallery/html_renderer.go
deleted file mode 100644
index 8e184e0..0000000
--- a/internal/lightgallery/html_renderer.go
+++ /dev/null
@@ -1,145 +0,0 @@
-package lightgallery
-
-import (
- "bytes"
- "fmt"
- "math/rand"
- "strings"
- "time"
-
- "github.com/yuin/goldmark"
- "github.com/yuin/goldmark/ast"
- "github.com/yuin/goldmark/renderer"
- "github.com/yuin/goldmark/renderer/html"
- "github.com/yuin/goldmark/util"
-)
-
-type LightGalleryHTMLRenderer struct {
- html.Config
- md goldmark.Markdown
-}
-
-func NewLightGalleryHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
- r := &LightGalleryHTMLRenderer{
- Config: html.NewConfig(),
- md: goldmark.New(
- goldmark.WithRendererOptions(
- html.WithHardWraps(),
- html.WithXHTML(),
- ),
- ),
- }
- for _, opt := range opts {
- opt.SetHTMLOption(&r.Config)
- }
- return r
-}
-
-func (r *LightGalleryHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
- reg.Register(KindLightGalleryBlock, r.renderLightGallery)
-}
-
-func (r *LightGalleryHTMLRenderer) renderLightGallery(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
- if entering {
- gallery := n.(*LightGalleryBlock)
-
- if len(gallery.Images) == 0 {
- return ast.WalkContinue, nil
- }
-
- galleryID := generateDivId(8)
-
- w.WriteString(fmt.Sprintf(`
-<div class="justify-content-center display-block m-2">
- <hr class="border-t-4 border-dotted border-main-dark mt-[0.8vmin] mb-[0.8vmin] w-[80%%] ml-auto mr-auto">
- <div id="lg-%s" class="inline-gallery-container relative ml-auto mr-auto"></div>
- <hr class="border-t-4 border-dotted border-main-dark mt-[0.8vmin] mb-[0.8vmin] w-[80%%] ml-auto mr-auto">
-</div>`, galleryID))
-
- var dynamicElements []string
- for _, img := range gallery.Images {
- imageUrlSegments := strings.Split(img.URL, ".")
- imageUrlWithoutExt := strings.Join(imageUrlSegments[:len(imageUrlSegments)-1], ".")
- imageUrlParts := strings.Split(imageUrlWithoutExt, "/")
- imageNameParts := strings.Split(imageUrlParts[len(imageUrlParts)-1], "-")
-
- var captionBuf bytes.Buffer
- captionHTML := img.Caption
- if err := r.md.Convert(img.Caption, &captionBuf); err == nil {
- captionHTML = captionBuf.Bytes()
- captionHTML = bytes.TrimPrefix(captionHTML, []byte("<p>"))
- captionHTML = bytes.TrimSuffix(captionHTML, []byte("</p>\n"))
- captionHTML = bytes.TrimSuffix(captionHTML, []byte("</p>"))
- }
-
- dayDate, _ := time.Parse("20060102 150405", imageNameParts[len(imageNameParts)-2]+" "+imageNameParts[len(imageNameParts)-1])
- dayDate = dayDate.In(gallery.Location)
- dynamicElements = append(dynamicElements, fmt.Sprintf(`{
- src:
- "https://f003.backblazeb2.com/file/sayana-photos/full/%s",
- downloadUrl:
- "https://f003.backblazeb2.com/file/sayana-photos/full/%s",
- alt: "%s",
- responsive: "https://f003.backblazeb2.com/file/sayana-photos/webp-320p/%s.webp 384, https://f003.backblazeb2.com/file/sayana-photos/webp-560p/%s.webp 672, https://f003.backblazeb2.com/file/sayana-photos/webp-800p/%s.webp 960, https://f003.backblazeb2.com/file/sayana-photos/webp-1200p/%s.webp 1440, https://f003.backblazeb2.com/file/sayana-photos/webp-1600p/%s.webp 1920",
- thumb:
- "https://f003.backblazeb2.com/file/sayana-photos/webp-320p/%s.webp",
- subHtml: `+"`"+`<div class="flex flex-row light-gallery-captions">
- <p class="grow !text-[1vmax]/[1] text-left font-spectral text-main-dark">%s</p>
- <p class="!text-[1vmax]/[1] text-right font-spectral text-secondary">%s</p>
- </div>`+"`"+`
- }`, img.URL, img.URL, util.EscapeHTML(captionHTML), imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, captionHTML, dayDate.Format("2006-01-02 15:04:05 -07:00")))
- }
-
- w.WriteString(fmt.Sprintf(`
-<script>
-function createLightGallery%s() {
- const $lgContainer = document.getElementById('lg-%s');
- const config = {
- container: $lgContainer,
- dynamic: true,
- dynamicEl: [%s],
- width: "100%%",
- height: "50vmin",
- hash: false,
- closable: false,
- showMaximizeIcon: true,
- appendSubHtmlTo: ".lg-sub-html",
- isMobile: () => false,
- slideDelay: 0,
- plugins: [lgZoom, lgThumbnail],
- thumbWidth: calculateVmin(10),
- thumbHeight: "10vmin",
- thumbMargin: 4
- };
- const inlineGallery = lightGallery($lgContainer, config);
-
- setTimeout(() => {
- inlineGallery.openGallery();
- }, 200);
-
- galleryMap.set(inlineGallery, createLightGallery%s);
-}
-
-document.addEventListener('htmx:afterRequest', (e) => {
- if (e.detail.xhr.status == 404 || e.detail.successful != true) {
- return console.error(e);
- }
- if (e.detail.target.id == 'general-page-body') {
- createLightGallery%s();
- }
-}, {once: true});
-</script>`, galleryID, galleryID, strings.Join(dynamicElements, ","), galleryID, galleryID))
- }
-
- return ast.WalkContinue, nil
-}
-
-func generateDivId(length int) string {
- const charset = "abcdefghijklmnopqrstuvwxyz"
- seededRand := rand.New(rand.NewSource(time.Now().UnixNano())) // Seed with current time
- b := make([]byte, length)
- for i := range b {
- b[i] = charset[seededRand.Intn(len(charset))]
- }
- return string(b)
-}
diff --git a/internal/router/api-v1-general-page-body.go b/internal/router/api-v1-general-page-body.go
index b2fa268..c1a4a9f 100644
--- a/internal/router/api-v1-general-page-body.go
+++ b/internal/router/api-v1-general-page-body.go
@@ -136,6 +136,8 @@ func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []string,
values["MapLocationAreaMeters"] = areaError
values["Title"] = metadata.Title
values["ParsedMarkdown"] = template.HTML(parsedMarkdown)
+ values["PublishedDate"] = metadata.PublishedTime.Format("2006-01-02 15:04:05 -07:00")
+ values["ActionDate"] = metadata.ActionDate
additionalTemplates = append(additionalTemplates, "views/pages/blog-page.html")
diff --git a/internal/tailwind/link_renderer.go b/internal/tailwind/link_renderer.go
new file mode 100644
index 0000000..ff3d437
--- /dev/null
+++ b/internal/tailwind/link_renderer.go
@@ -0,0 +1,49 @@
+package tailwind
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/util"
+)
+
+type CustomLinkRenderer struct {
+ html.Config
+}
+
+func NewCustomLinkRenderer(opts ...html.Option) renderer.NodeRenderer {
+ r := &CustomLinkRenderer{
+ Config: html.NewConfig(),
+ }
+ for _, opt := range opts {
+ opt.SetHTMLOption(&r.Config)
+ }
+ return r
+}
+
+func (r *CustomLinkRenderer) renderLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.Link)
+ if entering {
+ _, _ = w.WriteString("<a href=\"")
+ if r.Unsafe || !html.IsDangerousURL(n.Destination) {
+ _, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
+ }
+ _, _ = w.WriteString(`"`)
+ if n.Title != nil {
+ _, _ = w.WriteString(` title="`)
+ _, _ = w.Write(util.EscapeHTML(n.Title))
+ _, _ = w.WriteString(`"`)
+ }
+ if n.Attributes() != nil {
+ html.RenderAttributes(w, n, nil)
+ }
+ _, _ = w.WriteString(">")
+ } else {
+ _, _ = w.WriteString("</a>")
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *CustomLinkRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
+ reg.Register(ast.KindLink, r.renderLink)
+}
diff --git a/internal/tailwind/transformer.go b/internal/tailwind/transformer.go
index 2f052b9..23ba1a3 100644
--- a/internal/tailwind/transformer.go
+++ b/internal/tailwind/transformer.go
@@ -1,6 +1,9 @@
package tailwind
import (
+ "bytes"
+ "fmt"
+
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
@@ -17,44 +20,48 @@ func (t *TailwindTransformer) Transform(node *ast.Document, reader text.Reader,
switch node := n.(type) {
case *ast.Heading:
classes := map[int]string{
- 1: "font-patua text-[2.5vmax] font-bold text-main-dark mb-[1.2vmin] tracking-[0.04vmin]",
- 2: "font-spectral text-[2vmax] font-bold text-main-dark mb-[0.8vmin] tracking-[0.04vmin]",
- 3: "font-spectral text-[1.5vmax] font-medium text-main-dark mb-[0.6vmin] tracking-[0.04vmin]",
- 4: "font-spectral text-[1.2vmax] font-medium text-main-medium mb-[0.4vmin] tracking-[0.04vmin]",
- 5: "font-spectral text-[1vmax] font-medium text-main-medium mb-[0.4vmin] italic tracking-[0.04vmin]",
- 6: "font-spectral text-[1vmax] font-medium text-secondary mb-[0.4vmin]",
+ 1: "font-patua text-4xl font-bold text-main-dark mb-3 tracking-[.0125rem]",
+ 2: "font-spectral text-3xl font-bold text-main-dark mb-1 tracking-[.0125rem]",
+ 3: "font-spectral text-2xl font-medium text-main-dark mb-0.8 tracking-[.0125rem]",
+ 4: "font-spectral text-xl font-medium text-main-medium mb-0.5 tracking-[.0125rem]",
+ 5: "font-spectral text-base font-medium text-main-medium mb-0.5 italic tracking-[.0125rem]",
+ 6: "font-spectral text-base font-medium text-secondary mb-0.5",
}
if class, ok := classes[node.Level]; ok {
node.SetAttribute([]byte("class"), []byte(class))
}
case *ast.Paragraph:
- node.SetAttribute([]byte("class"), []byte("text-[1vmax]/[2] font-spectral tracking-[0.04vmin] -indent-[2vmax] ml-[2vmax] mb-[1.6vmin]"))
+ node.SetAttribute([]byte("class"), []byte("text-base/[2] font-spectral tracking-[.0125rem] -indent-8 ml-4 mb-8"))
case *ast.List:
if node.IsOrdered() {
- node.SetAttribute([]byte("class"), []byte("list-decimal list-inside space-y-[0.8vmin] mb-[1.6vmin] pl-[2vmax]"))
+ node.SetAttribute([]byte("class"), []byte("list-decimal list-inside space-y-2 mb-4 pl-8"))
} else {
- node.SetAttribute([]byte("class"), []byte("list-disc list-inside space-y-[0.8vmin] mb-[1.6vmin] pl-[2vmax]"))
+ node.SetAttribute([]byte("class"), []byte("list-disc list-inside space-y-2 mb-4 pl-8"))
}
case *ast.ListItem:
- node.SetAttribute([]byte("class"), []byte("text-[1vmax]/[2] font-spectral tracking-[0.04vmin]"))
+ node.SetAttribute([]byte("class"), []byte("text-base/[2] font-spectral tracking-[.0125rem]"))
case *ast.Blockquote:
- node.SetAttribute([]byte("class"), []byte("border-l-[0.4vmin] border-main-medium bg-background-dark p-[0.8vmin] mb-[0.8vmin] italic"))
+ node.SetAttribute([]byte("class"), []byte("border-l-2 border-main-medium bg-background-dark p-1 mb-2 italic"))
case *ast.CodeSpan:
node.SetAttribute([]byte("class"), []byte("bg-background-dark"))
case *ast.CodeBlock, *ast.FencedCodeBlock:
- node.SetAttribute([]byte("class"), []byte("bg-background-dark p-[0.8vmin] rounded-lg overflow-x-auto mb-[1.6vmin]"))
+ node.SetAttribute([]byte("class"), []byte("bg-background-dark p-1 rounded-lg overflow-x-auto mb-4"))
case *ast.Link:
+ if bytes.HasPrefix(node.Destination, []byte{'.', '/'}) {
+ onclickAttr := fmt.Appendf(make([]byte, 0, 21+len(node.Destination)), "return changeUrl('%s');", node.Destination)
+ node.SetAttribute([]byte("onclick"), onclickAttr)
+ }
node.SetAttribute([]byte("class"), []byte("text-secondary hover:text-main-dark underline"))
case *ast.Image:
- node.SetAttribute([]byte("class"), []byte("max-w-full h-auto rounded-lg shadow-lg mb-[1.6vmin]"))
+ node.SetAttribute([]byte("class"), []byte("max-w-full h-auto rounded-lg shadow-lg mb-4"))
case *ast.Emphasis:
switch node.Level {
diff --git a/internal/templatemanager/templatemanager.go b/internal/templatemanager/templatemanager.go
index 4bf9a49..eebc297 100644
--- a/internal/templatemanager/templatemanager.go
+++ b/internal/templatemanager/templatemanager.go
@@ -37,7 +37,7 @@ func NewTemplateManager(templates ...TemplateManagerTemplates) (*TemplateManager
templateMap := make(map[string]templateManagerRender)
for _, tmplStruct := range templates {
- tmpl := template.New("").Funcs(templateFuncMap)
+ tmpl := template.New(tmplStruct.Name).Funcs(templateFuncMap)
tmpl, err := tmpl.ParseFiles(tmplStruct.Files...)
if err != nil {
return nil, err
@@ -84,7 +84,7 @@ func (tm *TemplateManager) Add(name string, files ...string) error {
return fmt.Errorf("you can't add template without any files")
}
- tmpl := template.New("").Funcs(templateFuncMap)
+ tmpl := template.New(name).Funcs(templateFuncMap)
tmpl, err := tmpl.ParseFiles(files...)
if err != nil {
diff --git a/locale/localization.en.yaml b/locale/localization.en.yaml
index 1b3654b..e93ab00 100644
--- a/locale/localization.en.yaml
+++ b/locale/localization.en.yaml
@@ -22,3 +22,6 @@ HomePage:
Hymn2: "We've been expecting you!"
Hymn3: 'You bring such joy in Sayasite!'
Hymn4: 'No matter where you roam, know our love is true!~'
+Metadata:
+ Published: 'Published'
+ Action: 'Took place on'
diff --git a/locale/localization.go b/locale/localization.go
index 088783f..7dbb554 100644
--- a/locale/localization.go
+++ b/locale/localization.go
@@ -12,6 +12,7 @@ type LocaleConfig struct {
BlogSearch BlogSearchConfig `yaml:"BlogSearch" json:"BlogSearch"`
GlobalMap GlobalMapConfig `yaml:"GlobalMap" json:"GlobalMap"`
HomePage HomePageConfig `yaml:"HomePage" json:"HomePage"`
+ Metadata MetadataConfig `yaml:"Metadata" json:"Metadata"`
}
type BlogSearchConfig struct {
@@ -43,6 +44,11 @@ type HomePageConfig struct {
Hymn4 string `yaml:"Hymn4" json:"Hymn4"`
}
+type MetadataConfig struct {
+ Action string `yaml:"Action" json:"Action"`
+ Published string `yaml:"Published" json:"Published"`
+}
+
func LoadConfig(path string, config *LocaleConfig) error {
fileBytes, err := os.ReadFile(path)
if err != nil {
diff --git a/locale/localization.ru.yaml b/locale/localization.ru.yaml
index 9d7084f..a1a9a6c 100644
--- a/locale/localization.ru.yaml
+++ b/locale/localization.ru.yaml
@@ -22,3 +22,6 @@ HomePage:
Hymn2: 'Мы Вас столько ждали!'
Hymn3: 'Столько радости от Вас на Саясайте!'
Hymn4: 'Где бы Вы не были, знайте, -- наша любовь крепка!'
+Metadata:
+ Published: 'Опубликовано'
+ Action: 'Время действия'
diff --git a/main.go b/main.go
index 20e90f4..a6a30b0 100644
--- a/main.go
+++ b/main.go
@@ -12,7 +12,7 @@ import (
"github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/internal/factgiver"
- "github.com/SayaAndy/saya-today-web/internal/lightgallery"
+ "github.com/SayaAndy/saya-today-web/internal/glightbox"
"github.com/SayaAndy/saya-today-web/internal/router"
"github.com/SayaAndy/saya-today-web/internal/tailwind"
"github.com/SayaAndy/saya-today-web/locale"
@@ -23,7 +23,9 @@ import (
"github.com/golang-migrate/migrate/v4/database/sqlite3"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/parser"
- gmhtml "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/util"
_ "github.com/golang-migrate/migrate/v4/source/file"
_ "github.com/mattn/go-sqlite3"
@@ -32,14 +34,20 @@ import (
var (
md = goldmark.New(
goldmark.WithExtensions(
- lightgallery.NewLightGalleryExtension(),
+ glightbox.NewGLightboxExtension(),
tailwind.NewTailwindExtension(),
),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
+ parser.WithAttribute(),
),
- goldmark.WithRendererOptions(
- gmhtml.WithXHTML(),
+ goldmark.WithRenderer(
+ renderer.NewRenderer(
+ renderer.WithNodeRenderers(
+ util.Prioritized(tailwind.NewCustomLinkRenderer(html.WithUnsafe(), html.WithXHTML()), 50),
+ util.Prioritized(html.NewRenderer(html.WithXHTML()), 100),
+ ),
+ ),
),
)
b2Client *b2.B2Client
diff --git a/static/input.css b/static/input.css
index 739bea7..a983460 100644
--- a/static/input.css
+++ b/static/input.css
@@ -3,6 +3,35 @@
@theme {
--font-spectral: Spectral, serif;
--font-patua: "Patua One", cursive;
+ --breakpoint-xs: 32rem;
+}
+
+html {
+ font-size: 12px;
+}
+
+@media screen and (width >= 640px) {
+ html {
+ font-size: 14px;
+ }
+}
+
+@media screen and (width >= 1200px) {
+ html {
+ font-size: 16px;
+ }
+}
+
+@media screen and (width >= 1920px) {
+ html {
+ font-size: 20px;
+ }
+}
+
+@media screen and (width >= 2560px) {
+ html {
+ font-size: 24px;
+ }
}
[data-theme="olive"] {
@@ -20,7 +49,7 @@
--leaflet-link-hover-color: var(--main-light-color);
--interlocked-hexagons-background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22%23ffffdb%22%2F%3E%3Cpath%20fill%3D%22%23777e63%22%20d%3D%22m33.64%200-.17.25h-33L4.3%206h33.07l4-6zm8.33%200-4.33%206.5h-33l3.83%205.75h33.06L49.7%200zm8.34%200-8.5%2012.75h-33l3.83%205.75H45.7L58.03%200zm8.33%200L45.97%2019h-33l3.83%205.75h33.06L66.36%200zm-8.5%2025.25L33.63%2050l3.86%205.8L54.03%2031h33l-3.83-5.75zm4.16%206.25L37.8%2056.25l3.87%205.8%2016.53-24.8h33l-3.84-5.75zm4.17%206.25L41.97%2062.5l3.86%205.8%2016.54-24.8h33l-3.84-5.75zM62.63%2044l-16.5%2024.75%203.87%205.8%2016.53-24.8h33L95.7%2044zM100%2050.45l-3.87%205.8%203.87%205.81v-11.6zM0%2050.46v11.6L12.5%2080.8l3.86-5.8zm95.83%206.25-3.87%205.8L100%2074.55v-11.6zm-4.17%206.24-3.86%205.8%2012.2%2018.3v-11.6zM0%2062.96v11.6l8.33%2012.49%203.86-5.8zm87.5%206.24L83.63%2075%20100%2099.54V87.96zM50%2075.45%2033.64%20100h7.72l12.5-18.75zm-50%200v11.6l4.16%206.24%203.87-5.8zm54.17%206.25L41.97%20100h7.73l8.33-12.5zm4.17%206.25L50.3%20100h7.73l4.17-6.25zM0%2087.95v11.59l3.86-5.8zm62.5%206.25-3.87%205.8h7.73z%22%2F%3E%3Cpath%20fill%3D%22%23a0a182%22%20d%3D%22M66.8.25%2062.97%206h33l4.03%206.05V.45l-.14-.2zM0%20.45v11.61L12.5%2030.8l3.86-5.8zM62.63%206.5l-3.83%205.75h33l8.2%2012.3v-11.6L95.7%206.5zm-4.16%206.25-3.84%205.75h33L100%2037.06v-11.6l-8.47-12.71zM0%2012.96v11.6l8.33%2012.49%203.86-5.8zM54.3%2019l-3.84%205.75h33L100%2049.55l.01-.01V37.96L87.36%2019zm-4.77%206.25H41.8L25.3%2050l16.66%2025-16.5%2024.75h7.74L49.7%2075%2033.03%2050zm-8.33%200h-7.74L16.96%2050l16.67%2025-16.5%2024.75h7.73L41.36%2075%2024.7%2050Zm-8.34%200h-7.73L8.63%2050%2025.3%2075%208.8%2099.75h7.73L33.03%2075%2016.36%2050zm-16.07%200L.3%2050l16.67%2025L.46%2099.75H8.2L24.7%2075%208.02%2050l16.5-24.75zM0%2025.46v11.6l4.16%206.24%203.87-5.8zm0%2012.5v11.58l3.86-5.79zm66.8%2012.29L50.3%2074.99l3.87%205.81%204.16%206.25%204.17%206.25%204.3%206.45h7.73L58.03%2075l16.5-24.75zm16.06%200h-7.73L58.63%2075l16.5%2024.75h7.73L66.36%2075zm.6%200L66.96%2075l16.5%2024.75h7.74L74.7%2075l16.5-24.75zm16.07%200H91.8L75.3%2075l16.5%2024.75h7.73L83.03%2075z%22%2F%3E%3C%2Fsvg%3E");
--interlocked-hexagons-background-repeat: repeat;
- --interlocked-hexagons-background-size: 10vh;
+ --interlocked-hexagons-background-size: 10dvh;
--squares-and-triangles-background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22%234a5139%22%2F%3E%3Cpath%20fill%3D%22%23b2b285%22%20d%3D%22M0%200v6.77L6.72%200zm8.91%200L0%208.96v3.86L12.83%200zm6.11%200L0%2015.06v3.87L18.9%200zm6.11%200L0%2021.12v3.92L25%200zM25%200l25%2024.99v-3.87L28.87%200zm25%2024.99%2025%2024.98L100%2025%2075%200zm-50%20.05v3.87l21.13%2021.12H25l-25-25zm25%2024.99h3.87L50%2028.9v-3.87zm0%200L0%2075l25%2025%2025-24.99zM50%2075l25-24.98h-3.87L50%2071.14v3.87zm0%200v3.87L71.13%20100H75L50%2075.01zm25%2025h3.87L100%2078.88v-3.87zm25-24.99v-3.87L78.87%2050.03H75L100%2075zM31.1%200%2050%2018.93v-3.87L34.98%200h-3.87zm6.07%200L50%2012.82V8.96L41.04%200zm6.1%200L50%206.77V0h-6.72zM25%202.19%202.14%2025.04H25zm0%2022.85v22.8l22.81-22.8zM75%203.92l21.13%2021.12L75%2046.16%2053.87%2025.04zm0%202.19L56.06%2025.04l18.89%2018.88%2018.94-18.88L75%206.1zm0%203.92%2015.07%2015L75%2040.06%2059.98%2025.04zm0%202.18L62.17%2025.04%2075%2037.86l12.83-12.82L75%2012.2zm0%203.82%208.96%209L75%2033.95%2066.04%2025zm0%202.24-6.72%206.77L75%2031.76l6.77-6.72h-.05zM0%2031.09v3.87l15.02%2015.07h3.87zm50%200L31.1%2050.03h3.88L50%2034.96V31.1zM0%2037.2v3.87l8.91%208.96h3.92zm50%200L37.17%2050.03h3.87L50%2041.07zM0%2043.3v6.73h6.72zm50%200-6.72%206.73H50zm0%206.73v6.71l6.72-6.71zm8.96%200L50%2058.93v3.92l12.83-12.82zm6.06%200L50%2065.03v3.88l18.94-18.88zm16.09%200L100%2068.9v-3.87l-15.02-15zm6.11%200L100%2062.85v-3.92l-8.91-8.9zm6.06%200%206.72%206.71v-6.71zM75%2052.2%2052.19%2075H75zM75%2075v22.8L97.81%2075zM25%2053.9l21.13%2021.12L25%2096.13%203.87%2075.01zm0%202.2L6.1%2074.95l18.95%2018.88%2018.9-18.88L25%2056.08zm0%203.9%2015.02%2015.01L25%2090.03%209.98%2075zm0%202.19L12.17%2075%2025%2087.84%2037.83%2075%2025%2062.2zm0%203.87L33.96%2075%2025%2083.97%2016.04%2075zm0%202.23-6.72%206.72L25%2081.73l6.72-6.72L25%2068.3zm25%2012.83v3.87L65.02%20100h3.87zm50%200L81.1%20100h3.88L100%2084.99zm-50%206.06v3.86l8.96%208.96h3.87zm50%200L87.22%20100h3.87l8.91-8.96zm-50%206.1V100h6.72zm50%200L93.28%20100H100z%22%2F%3E%3C%2Fsvg%3E");
--squares-and-triangles-background-repeat: repeat;
--squares-and-triangles-background-width-coef: 10;
@@ -42,7 +71,7 @@
--leaflet-link-hover-color: var(--main-light-color);
--interlocked-hexagons-background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22%23f5ede1%22%2F%3E%3Cpath%20fill%3D%22%239ab663%22%20d%3D%22m33.64%200-.17.25h-33L4.3%206h33.07l4-6zm8.33%200-4.33%206.5h-33l3.83%205.75h33.06L49.7%200zm8.34%200-8.5%2012.75h-33l3.83%205.75H45.7L58.03%200zm8.33%200L45.97%2019h-33l3.83%205.75h33.06L66.36%200zm-8.5%2025.25L33.63%2050l3.86%205.8L54.03%2031h33l-3.83-5.75zm4.16%206.25L37.8%2056.25l3.87%205.8%2016.53-24.8h33l-3.84-5.75zm4.17%206.25L41.97%2062.5l3.86%205.8%2016.54-24.8h33l-3.84-5.75zM62.63%2044l-16.5%2024.75%203.87%205.8%2016.53-24.8h33L95.7%2044zM100%2050.45l-3.87%205.8%203.87%205.81v-11.6zM0%2050.46v11.6L12.5%2080.8l3.86-5.8zm95.83%206.25-3.87%205.8L100%2074.55v-11.6zm-4.17%206.24-3.86%205.8%2012.2%2018.3v-11.6zM0%2062.96v11.6l8.33%2012.49%203.86-5.8zm87.5%206.24L83.63%2075%20100%2099.54V87.96zM50%2075.45%2033.64%20100h7.72l12.5-18.75zm-50%200v11.6l4.16%206.24%203.87-5.8zm54.17%206.25L41.97%20100h7.73l8.33-12.5zm4.17%206.25L50.3%20100h7.73l4.17-6.25zM0%2087.95v11.59l3.86-5.8zm62.5%206.25-3.87%205.8h7.73z%22%2F%3E%3Cpath%20fill%3D%22%23bbd095%22%20d%3D%22M66.8.25%2062.97%206h33l4.03%206.05V.45l-.14-.2zM0%20.45v11.61L12.5%2030.8l3.86-5.8zM62.63%206.5l-3.83%205.75h33l8.2%2012.3v-11.6L95.7%206.5zm-4.16%206.25-3.84%205.75h33L100%2037.06v-11.6l-8.47-12.71zM0%2012.96v11.6l8.33%2012.49%203.86-5.8zM54.3%2019l-3.84%205.75h33L100%2049.55l.01-.01V37.96L87.36%2019zm-4.77%206.25H41.8L25.3%2050l16.66%2025-16.5%2024.75h7.74L49.7%2075%2033.03%2050zm-8.33%200h-7.74L16.96%2050l16.67%2025-16.5%2024.75h7.73L41.36%2075%2024.7%2050Zm-8.34%200h-7.73L8.63%2050%2025.3%2075%208.8%2099.75h7.73L33.03%2075%2016.36%2050zm-16.07%200L.3%2050l16.67%2025L.46%2099.75H8.2L24.7%2075%208.02%2050l16.5-24.75zM0%2025.46v11.6l4.16%206.24%203.87-5.8zm0%2012.5v11.58l3.86-5.79zm66.8%2012.29L50.3%2074.99l3.87%205.81%204.16%206.25%204.17%206.25%204.3%206.45h7.73L58.03%2075l16.5-24.75zm16.06%200h-7.73L58.63%2075l16.5%2024.75h7.73L66.36%2075zm.6%200L66.96%2075l16.5%2024.75h7.74L74.7%2075l16.5-24.75zm16.07%200H91.8L75.3%2075l16.5%2024.75h7.73L83.03%2075z%22%2F%3E%3C%2Fsvg%3E");
--interlocked-hexagons-background-repeat: repeat;
- --interlocked-hexagons-background-size: 10vh;
+ --interlocked-hexagons-background-size: 10dvh;
--squares-and-triangles-background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22%23bbd095%22%2F%3E%3Cpath%20fill%3D%22%23f5ede1%22%20d%3D%22M0%200v6.77L6.72%200zm8.91%200L0%208.96v3.86L12.83%200zm6.11%200L0%2015.06v3.87L18.9%200zm6.11%200L0%2021.12v3.92L25%200zM25%200l25%2024.99v-3.87L28.87%200zm25%2024.99%2025%2024.98L100%2025%2075%200zm-50%20.05v3.87l21.13%2021.12H25l-25-25zm25%2024.99h3.87L50%2028.9v-3.87zm0%200L0%2075l25%2025%2025-24.99zM50%2075l25-24.98h-3.87L50%2071.14v3.87zm0%200v3.87L71.13%20100H75L50%2075.01zm25%2025h3.87L100%2078.88v-3.87zm25-24.99v-3.87L78.87%2050.03H75L100%2075zM31.1%200%2050%2018.93v-3.87L34.98%200h-3.87zm6.07%200L50%2012.82V8.96L41.04%200zm6.1%200L50%206.77V0h-6.72zM25%202.19%202.14%2025.04H25zm0%2022.85v22.8l22.81-22.8zM75%203.92l21.13%2021.12L75%2046.16%2053.87%2025.04zm0%202.19L56.06%2025.04l18.89%2018.88%2018.94-18.88L75%206.1zm0%203.92%2015.07%2015L75%2040.06%2059.98%2025.04zm0%202.18L62.17%2025.04%2075%2037.86l12.83-12.82L75%2012.2zm0%203.82%208.96%209L75%2033.95%2066.04%2025zm0%202.24-6.72%206.77L75%2031.76l6.77-6.72h-.05zM0%2031.09v3.87l15.02%2015.07h3.87zm50%200L31.1%2050.03h3.88L50%2034.96V31.1zM0%2037.2v3.87l8.91%208.96h3.92zm50%200L37.17%2050.03h3.87L50%2041.07zM0%2043.3v6.73h6.72zm50%200-6.72%206.73H50zm0%206.73v6.71l6.72-6.71zm8.96%200L50%2058.93v3.92l12.83-12.82zm6.06%200L50%2065.03v3.88l18.94-18.88zm16.09%200L100%2068.9v-3.87l-15.02-15zm6.11%200L100%2062.85v-3.92l-8.91-8.9zm6.06%200%206.72%206.71v-6.71zM75%2052.2%2052.19%2075H75zM75%2075v22.8L97.81%2075zM25%2053.9l21.13%2021.12L25%2096.13%203.87%2075.01zm0%202.2L6.1%2074.95l18.95%2018.88%2018.9-18.88L25%2056.08zm0%203.9%2015.02%2015.01L25%2090.03%209.98%2075zm0%202.19L12.17%2075%2025%2087.84%2037.83%2075%2025%2062.2zm0%203.87L33.96%2075%2025%2083.97%2016.04%2075zm0%202.23-6.72%206.72L25%2081.73l6.72-6.72L25%2068.3zm25%2012.83v3.87L65.02%20100h3.87zm50%200L81.1%20100h3.88L100%2084.99zm-50%206.06v3.86l8.96%208.96h3.87zm50%200L87.22%20100h3.87l8.91-8.96zm-50%206.1V100h6.72zm50%200L93.28%20100H100z%22%2F%3E%3C%2Fsvg%3E");
--squares-and-triangles-background-repeat: repeat;
--squares-and-triangles-background-width-coef: 10;
@@ -64,7 +93,7 @@
--leaflet-link-hover-color: var(--background-light-color);
--interlocked-hexagons-background: radial-gradient(33.5% 25% at 100% 82%, rgba(190, 227, 248, 0.2) 0%, rgba(197, 179, 246, 0.13) 33.33%, rgba(255, 0, 0, 0) 100%), radial-gradient(54% 25% at 55% 100%, rgba(190, 227, 248, 0.2) 0%, rgba(197, 179, 246, 0.13) 33.33%, rgba(255, 0, 0, 0) 100%), radial-gradient(37% 19.5% at 20% 100%, rgba(176, 220, 248, 0.3) 0%, rgba(197, 172, 247, 0.2) 33.33%, rgba(255, 0, 0, 0) 100%), radial-gradient(63% 34.5% at 66% 77%, rgba(190, 227, 248, 0.15) 0%, rgba(197, 179, 246, 0.1) 33.33%, rgba(255, 0, 0, 0) 100%), linear-gradient(0deg, #2f5883 0%, #2f4e7a 4.75%, #2e4472 9.5%, #2a3065 19%, #272e57 26.5%, #242b4b 34%, #1f2437 49%, #1c2030 57.75%, #1a1b29 66.5%, #13131b 84%);
--interlocked-hexagons-background-repeat: no-repeat;
- --interlocked-hexagons-background-size: 100vw 100vh;
+ --interlocked-hexagons-background-size: 100dvw 100dvh;
--squares-and-triangles-background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2260%22%20height%3D%2260%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22%2313131b%22%2F%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%23363645%22%20stroke-width%3D%22.5%22%20d%3D%22M10%2050H0m60-40H50m0%2040v10M10%200v10m21%2030v20m0-60v20m9%2010h20M0%2030h20m0%2010h20V20H20v10zM10%2010h40v40H10zM0%200h60v60H0z%22%2F%3E%3C%2Fsvg%3E");
--squares-and-triangles-background-repeat: repeat;
--squares-and-triangles-background-width-coef: 5;
@@ -93,12 +122,12 @@
--squares-and-triangles-background-height-coef: 15;
}
-a {
+a, .linklike {
color: var(--main-medium-color) !important;
text-decoration: underline;
}
-a:hover {
+a:hover, .linklike:hover {
color: var(--main-light-color) !important;
}
@@ -207,74 +236,35 @@ a:hover {
border-style: outset;
}
-.desktop-sidebar-custom {
- width: 5vw;
- background-size: calc(var(--squares-and-triangles-background-size) * 1vw);
-}
-
.bg-sidebar {
background-image: var(--squares-and-triangles-background);
background-repeat: var(--squares-and-triangles-background-repeat);
- background-size: calc(var(--squares-and-triangles-background-width-coef) * 1vw) calc(var(--squares-and-triangles-background-height-coef) * 1vw);
-}
-
-.mobile-topbar-custom {
- width: 90vw;
- height: 8%;
- background-size: calc(var(--squares-and-triangles-background-size) * 1.6vh);
- margin-left: 5vw;
-}
-
-body:has(.lg-container:not([class~="lg-inline"])) #sidebar {
- display: none !important;
+ background-size: calc(var(--squares-and-triangles-background-width-coef) * 1dvw) calc(var(--squares-and-triangles-background-height-coef) * 1dvw);
}
.logo-custom {
- width: 3.5vw;
- height: 20vw;
- font-size: 2.5vw;
- -webkit-text-stroke: 0.1vw var(--sidebar-stroke-color);
+ width: 3.5dvw;
+ height: 20dvw;
+ font-size: 2.5dvw;
+ -webkit-text-stroke: 0.1dvw var(--sidebar-stroke-color);
writing-mode: sideways-lr;
text-orientation: mixed;
display: block;
}
-.nav-icon-custom {
- font-size: 3vw !important;
- -webkit-text-stroke: 0.1vw var(--sidebar-stroke-color);
- width: 5vw;
- height: 5vw;
- align-content: center;
- text-align: center;
-}
-
-.nav-icon-custom:hover {
- font-size: 4vw;
-}
-
-.border-left-custom {
- width: 0.5vw;
- border-right: 0.3vh dashed var(--main-dark-color);
-}
-
-.border-right-custom {
- width: 0.5vw;
- border-left: 0.5vh dotted var(--main-dark-color);
-}
-
.inset-shadow {
- box-shadow: inset 0vh 1vh 1vh -1vh rgba(75, 81, 58, 0.5),
- inset 1vh 0vh 1vh -1vh rgba(75, 81, 58, 0.5),
- inset -1vh 0vh 1vh -1vh rgba(75, 81, 58, 0.5),
- inset 0vh -0.5vh rgba(75, 81, 58, 0.5);
+ box-shadow: inset 0dvh 1dvh 1dvh -1dvh rgba(75, 81, 58, 0.5),
+ inset 1dvh 0dvh 1dvh -1dvh rgba(75, 81, 58, 0.5),
+ inset -1dvh 0dvh 1dvh -1dvh rgba(75, 81, 58, 0.5),
+ inset 0dvh -0.5dvh rgba(75, 81, 58, 0.5);
}
.text-stroke-\(--sidebar-stroke-color\) {
-webkit-text-stroke-color: var(--sidebar-stroke-color);
}
-.text-stroke-\[0\.1vw\] {
- -webkit-text-stroke-width: 0.1vw;
+.text-stroke-\[0\.1dvw\] {
+ -webkit-text-stroke-width: 0.1dvw;
}
.theme-wheel {
@@ -337,143 +327,131 @@ body:has(.lg-container:not([class~="lg-inline"])) #sidebar {
transform: scale(1.1);
}
-.lg-backdrop {
- background-color: var(--background-light-color);
- opacity: 0.8 !important;
-}
-
-.lg-container:not([class~="lg-inline"]) .lg-outer {
- width: 90%;
- height: 90%;
- margin: 5vh 5vw;
-}
-
-.lg-thumb-outer {
- background-color: var(--background-light-color) !important;
- opacity: 0.8 !important;
+.grid-tooltip {
+ position: relative;
+ display: inline-block;
+ box-shadow: inset 0rem 0rem 0.5rem var(--main-light-color);
+ transition: box-shadow 0.5s ease-in-out;
}
-.lg-prev {
- background-color: var(--background-light-color);
- color: var(--main-dark-color);
+.grid-tooltip:hover {
+ box-shadow: none;
}
-.lg-next {
- background-color: var(--background-light-color);
- color: var(--main-dark-color);
-}
-
-.lg-counter {
+.grid-tooltip-text {
+ visibility: hidden;
+ opacity: 0;
+ transition: opacity 0.5s;
+ width: 100%;
+ top: 100%;
+ background-color: var(--background-dark-color);
color: var(--main-dark-color);
- font-family: 'Spectral';
- font-size: 1vmax;
- padding-top: 0;
- height: 1vmax;
-}
-
-.lg-container:not([class~="lg-inline"]) .lg-counter {
- font-size: 2vmax;
- height: 2vmax;
+ text-align: center;
+ padding: 0.25rem 0.25rem;
+ margin-top: 0.25rem;
+ border-radius: 0.5rem;
+ position: absolute;
+ z-index: 15;
}
-.lg-content {
- top: 2.5vmax !important;
- bottom: calc(10vmin + 5vmax) !important;
+.grid-tooltip:hover .grid-tooltip-text {
+ visibility: visible;
+ opacity: 1;
}
-.lg-outer[class~="lg-single-item"] .lg-content {
- bottom: 5vmax !important;
+.grid-tooltip-text::after {
+ content: " ";
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ margin-left: -0.25rem;
+ border-width: 0.25rem;
+ border-style: solid;
+ border-color: transparent transparent var(--background-dark-color) transparent;
}
-.lg-thumb-item {
- width: 10vmin !important;
- height: 10vmin !important;
+.grid-item, .grid-sizer {
+ position: relative;
+ display: inline-block;
+ width: 50%;
}
-.lg-container:not([class~="lg-inline"]) .lg-content {
- top: 4vmax !important;
+.grid-item-index {
+ visibility: visible;
+ opacity: 1;
+ transition: opacity 0.5s;
+ top: 0%;
+ left: 0%;
+ background-color: var(--main-light-color);
+ color: var(--background-dark-color);
+ text-align: center;
+ padding: 0.25rem 0.25rem;
+ position: absolute;
+ z-index: 14;
}
-.lg-toolbar .lg-icon,
-.lg-content .lg-icon {
- padding: 0 0.7vmax;
- font-size: 1.5vmax !important;
- height: 1.5vmax;
- width: auto;
- color: var(--main-dark-color);
+.grid-item:hover .grid-item-index {
+ visibility: hidden;
+ opacity: 0;
}
-.lg-container:not([class~="lg-inline"]) .lg-toolbar .lg-icon,
-.lg-container:not([class~="lg-inline"]) .lg-content .lg-icon {
- font-size: 3vmax !important;
- height: 3vmax;
+.grid-item-2x {
+ width: 100%;
}
-.lg-prev {
- left: 0 !important;
-}
+@media (width >= 32rem) {
+ .grid-item, .grid-sizer {
+ width: 33%;
+ }
-.lg-next {
- right: 0 !important;
+ .grid-item-2x {
+ width: 66%;
+ }
}
-.lg-toolbar .lg-icon:hover {
- color: var(--main-medium-color);
-}
+@media (width >= 40rem) {
+ .grid-item, .grid-sizer {
+ width: 25%;
+ }
-.lg-toolbar .lg-icon {
- font-size: 1.5vmax !important;
- color: var(--main-dark-color);
+ .grid-item-2x {
+ width: 50%;
+ }
}
-.lg-content .lg-icon:hover {
- color: var(--main-medium-color);
-}
+@media (width >= 48rem) {
+ .grid-item, .grid-sizer {
+ width: 20%;
+ }
-.lg-sub-html {
- padding: 0.7vmin 1.25vmin !important;
+ .grid-item-2x {
+ width: 40%;
+ }
}
-.inline-gallery-container {
- width: 80%;
- height: 70vmin;
+.goverlay {
+ background: color-mix(in srgb, var(--background-light-color) 50%, transparent) !important;
+ backdrop-filter: blur(1rem);
+ -webkit-backdrop-filter: blur(1rem);
}
-.light-gallery-captions {
- p {
- transform: translate3d(0, 0, 0px);
- transition-delay: 500ms;
- opacity: 1;
- }
+.glightbox-clean .gslide-description {
+ background: color-mix(in srgb, var(--background-dark-color) 50%, transparent) !important;
+ backdrop-filter: blur(1rem);
+ -webkit-backdrop-filter: blur(1rem);
}
-.lg-slide-progress {
- .light-gallery-captions {
- h4 {
- transform: translate3d(-60px, 0, 0px);
- }
-
- p {
- transform: translate3d(60px, 0, 0px);
- }
-
- h4,
- p {
- opacity: 0;
- }
- }
+.glightbox-clean .gslide-title {
+ font-family: var(--font-spectral) !important;
+ font-weight: 600 !important;
+ color: var(--main-light-color) !important;
}
-.lg-current {
- &.lg-slide-progress {
- .light-gallery-captions {
-
- h4,
- p {
- transition-delay: 0ms;
- }
- }
- }
+.glightbox-clean .gslide-desc {
+ font-size: 1rem !important;
+ font-family: var(--font-spectral) !important;
+ font-weight: 400;
+ color: var(--main-medium-color) !important;
}
.map-container .leaflet-container {
@@ -486,135 +464,115 @@ body[data-theme~="ram"] .leaflet-tile {
filter: invert(1) hue-rotate(190deg) contrast(1.1) brightness(1.2) !important;
}
-@media (min-aspect-ratio: 1.1/1) {
- .ar-gt-1\.1\:mr-\[1\.2vmin\] {
- margin-right: 1.2vmin;
+@media (min-aspect-ratio: 0.8/1) {
+ .ar-gt-0\.8\:mr-6 {
+ margin-right: 1.5rem;
}
- .ar-gt-1\.1\:w-fit {
+ .ar-gt-0\.8\:w-fit {
width: fit-content;
}
- .ar-gt-1\.1\:w-\[100vh\] {
- width: 100vh;
+ .ar-gt-0\.8\:w-\[100dvh\] {
+ width: 100dvh;
+ flex-basis: 100dvh;
}
- .ar-gt-1\.1\:min-w-fit {
+ .ar-gt-0\.8\:min-w-fit {
min-width: fit-content;
}
- .ar-gt-1\.1\:min-w-\[10vh\] {
- min-width: 10vh;
- }
-
- .ar-gt-1\.1\:max-w-\[20vh\] {
- max-width: 20vh;
+ .ar-gt-0\.8\:min-w-\[10dvh\] {
+ min-width: 10dvh;
}
- .ar-gt-1\.1\:max-w-\[100vh\] {
- max-width: 100vh;
+ .ar-gt-0\.8\:max-w-\[20dvh\] {
+ max-width: 20dvh;
}
- .ar-gt-1\.1\:items-center {
+ .ar-gt-0\.8\:items-center {
align-items: center;
}
}
-@media (max-aspect-ratio: 1.1/1) {
+@media (max-aspect-ratio: 0.8/1) {
.bg-sidebar {
- background-size: calc(var(--squares-and-triangles-background-width-coef) * 1.6vh) calc(var(--squares-and-triangles-background-height-coef) * 1.6vh);
+ background-size: calc(var(--squares-and-triangles-background-width-coef) * 1.6dvh) calc(var(--squares-and-triangles-background-height-coef) * 1.6dvh);
}
- .inline-gallery-container {
- width: 100%;
+ .ar-lt-0\.8\:bg-background-light {
+ background-color: var(--background-light-color);
}
.logo-custom {
display: none;
}
- .nav-icon-custom {
- font-size: 5vh !important;
- -webkit-text-stroke: 0.1vh var(--sidebar-stroke-color);
- width: 8vh;
- height: 8vh;
- align-content: center;
- text-align: center;
- }
-
- .nav-icon-custom:hover {
- font-size: 7vh;
- }
-
.bg-pattern-body {
- background-size: 10vh;
+ background-size: 10dvh;
}
- .ar-lt-1\.1\:grid {
+ .ar-lt-0\.8\:grid {
display: grid;
}
- .ar-lt-1\.1\:flex-col {
+ .ar-lt-0\.8\:flex-col {
flex-direction: column;
}
- .ar-lt-1\.1\:flex-row {
+ .ar-lt-0\.8\:flex-row {
flex-direction: row;
}
- .ar-lt-1\.1\:h-\[8vh\] {
- height: 8vh;
+ .ar-lt-0\.8\:h-\[8dvh\] {
+ height: 8dvh;
}
- .ar-lt-1\.1\:h-\[10vh\] {
- height: 10vh;
+ .ar-lt-0\.8\:h-\[10dvh\] {
+ height: 10dvh;
}
- .ar-lt-1\.1\:h-\[30vh\] {
- height: 30vh;
+ .ar-lt-0\.8\:h-\[30dvh\] {
+ height: 30dvh;
}
- .ar-lt-1\.1\:h-\[90vh\] {
- height: 90vh;
+ .ar-lt-0\.8\:h-\[90dvh\] {
+ height: 90dvh;
}
- .ar-lt-1\.1\:w-\[8vh\] {
- width: 8vh;
+ .ar-lt-0\.8\:w-\[8dvh\] {
+ width: 8dvh;
}
- .ar-lt-1\.1\:w-\[80\%\] {
+ .ar-lt-0\.8\:w-\[80\%\] {
width: 80%;
}
- .ar-lt-1\.1\:w-\[90vw\] {
- width: 90vw;
+ .ar-lt-0\.8\:w-\[90dvw\] {
+ width: 90dvw;
}
- .ar-lt-1\.1\:w-screen {
- width: 100vw;
+ .ar-lt-0\.8\:w-\[100dvw\] {
+ width: 100dvw;
}
- .ar-lt-1\.1\:max-h-\[25\%\] {
- max-height: 25%;
+ .ar-lt-0\.8\:max-h-\[30\%\] {
+ max-height: 30%;
}
- .ar-lt-1\.1\:max-h-\[80\%\] {
+ .ar-lt-0\.8\:max-h-\[80\%\] {
max-height: 80%;
}
- .ar-lt-1\.1\:max-h-\[calc\(100\%-25vh\)\] {
- max-height: calc(100% - 25vh);
- }
-
- .ar-lt-1\.1\:text-\[5vh\] {
- font-size: 5vh;
+ .ar-lt-0\.8\:max-h-\[92dvh\] {
+ max-height: 92dvh;
}
- .ar-lt-1\.1\:ml-\[5vw\] {
- margin-left: 5vw;
+ .ar-lt-0\.8\:text-\[5dvh\] {
+ font-size: 5dvh;
}
- .ar-lt-1\.1\:hidden {
+ .ar-lt-0\.8\:hidden {
display: none;
}
}
@@ -635,16 +593,6 @@ body[data-theme~="ram"] .leaflet-tile {
}
}
-@media (max-aspect-ratio: 0.4/1) {
- .ar-lt-0\.4\:w-\[100vw\] {
- width: 100vw;
- }
-
- .ar-lt-0\.4\:ml-0 {
- margin-left: 0;
- }
-}
-
.home-page-heart {
position: absolute;
color: var(--color-pink-700);
diff --git a/views/index.html b/views/index.html
index b52df94..2633894 100644
--- a/views/index.html
+++ b/views/index.html
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>SAYA TODAY // Заглавная</title>
+ <title>Choose Language // SAYA TODAY</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -12,8 +12,8 @@
<style>
.menu-outer-body {
border-radius: 10%;
- width: 40vh;
- height: 30vh;
+ width: 40dvh;
+ height: 30dvh;
}
.menu-inner-body {
@@ -35,8 +35,8 @@
}
.menu-outer-body {
- width: min(40vh, 100vw);
- height: 40vh;
+ width: min(40dvh, 100dvw);
+ height: 40dvh;
border-radius: 0;
}
@@ -56,7 +56,7 @@
</style>
</head>
-<body data-theme="night" class="font-spectral text-main-dark text-[1.5vmax] overflow-hidden bg-interlocked-hexagons h-screen flex flex-col">
+<body data-theme="night" class="font-spectral text-main-dark text-2xl overflow-hidden bg-interlocked-hexagons h-[100dvh] flex flex-col">
<div class="absolute star z-0">*</div>
<div class="absolute star z-0">*</div>
@@ -102,14 +102,14 @@
switchTheme(savedTheme);
</script>
- <div class="menu-outer-body p-4 z-1 bg-background-dark flex flex-col mx-auto my-auto opacity-70">
- <p class="font-patua mx-auto text-[2.5vmax] mt-[0.8vmin] mb-[0.8vmin]">saya.today</p>
+ <div class="menu-outer-body p-2 z-1 bg-background-dark flex flex-col mx-auto my-auto opacity-70">
+ <p class="font-patua mx-auto text-4xl mt-1 mb-2">saya.today</p>
<div class="menu-inner-body grow bg-background-light flex flex-adaptive mx-auto opacity-100">
{{- range .AvailableLanguages }}
<img onclick="location.href='/{{ .Name }}';" class="object-scale-down cursor-pointer flex-1 rounded-[20%] language-icon mx-auto my-auto relative" src="{{ .Flag }}" alt="{{ .Alt }}">
{{- end }}
</div>
- <p class="font-spectral mx-auto text-[1.5vmax] text-secondary mt-[0.8vmin] mb-[0.8vmin]">Choose your language</p>
+ <p class="font-spectral mx-auto text-2xl text-secondary mt-1 mb-2">Choose your language</p>
</div>
<script>
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index 60608f4..c320666 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -7,25 +7,34 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,200;1,300;1,400;1,500;1,600;1,700;1,800&family=Patua+One&display=swap" rel="stylesheet">
- <link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/css/lightgallery.min.css">
- <link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/css/lg-zoom.min.css">
- <link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/css/lg-thumbnail.min.css">
<link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet/1.9.4/leaflet.css">
+ <link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/glightbox/3.3.0/css/glightbox.min.css">
<link href="/output.css" rel="stylesheet">
</head>
-<body data-theme="ram" class="font-spectral text-main-dark overflow-hidden bg-interlocked-hexagons h-screen flex flex-row ar-lt-1.1:flex-col">
+<body data-theme="ram" class="font-spectral text-main-dark overflow-hidden bg-interlocked-hexagons h-[100dvh] flex flex-row ar-lt-0.8:flex-col">
+
+ <script>
+ let map = null;
+ </script>
<script>
function changeUrl(path, toAppend = false) {
const urlParams = new URLSearchParams(window.location.search);
const newPathname = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;
const newPath = toAppend ? `${newPathname}${path}` : `${path}`;
+
history.pushState({}, '', `${newPath}${urlParams.entries.length == 0 ? '' : '?' + urlParams.toString()}`);
+ if (location.pathname == "" || location.pathname == "/") {
+ return true;
+ }
window.dispatchEvent(new Event('popstate'));
+ return false;
};
</script>
+ <script src="https://f003.backblazeb2.com/file/sayana-static/libs/glightbox/3.3.0/js/glightbox.min.js"></script>
+
<script>
function sfc32(a, b, c, d) {
return function() {
@@ -161,15 +170,24 @@
const clientTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
</script>
- <div id="sidebar" class="bg-sidebar flex sticky flex-col ar-gt-1.1:items-center shadow-2xl z-20 w-[5vw] ar-lt-1.1:w-[90vw] ar-lt-0.4:w-[100vw] h-screen ar-lt-1.1:h-[8vh] ar-lt-1.1:ml-[5vw] ar-lt-0.4:ml-0">
- <div class="logo-custom ar-lt-1.1:hidden text-sidebar font-patua font-extrabold text-center relative z-20">
+ <div id="sidebar" class="bg-sidebar flex sticky flex-col ar-gt-0.8:items-center shadow-2xl z-20 w-[5dvw] ar-lt-0.8:w-[100dvw] h-[100dvh] ar-lt-0.8:h-[8dvh]">
+ <div class="logo-custom ar-lt-0.8:hidden text-sidebar font-patua font-extrabold text-center relative z-20">
saya.today
</div>
- <div class="text-[3vw] ar-lt-1.1:text-[5vh] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1vw] flex flex-col ar-lt-1.1:flex-row gap-0 relative z-20">
- <i onclick="changeUrl('/{{ .Lang }}');" class="fas fa-home w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
- <i onclick="changeUrl('/{{ .Lang }}/blog');" class="fas fa-search w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
- <i onclick="location.href='/{{ .Lang }}/map';" class="fas fa-map w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
- <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
+ <div class="text-[3dvw] ar-lt-0.8:text-[5dvh] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1dvw] flex flex-col ar-lt-0.8:flex-row gap-0 relative z-20">
+ <a href="/{{ .Lang }}" class="w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i onclick="return changeUrl('/{{ .Lang }}');" class="fas fa-home flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
+ <a href="/{{ .Lang }}/blog" class="w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i onclick="return changeUrl('/{{ .Lang }}/blog');" class="fas fa-search flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
+ <a href="/{{ .Lang }}/map" class="w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i class="fas fa-map flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
+ <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook flex w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i>
+ <a href="./" class="xs:!hidden w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i onclick="return changeUrl('/../', true);" class="fas fa-circle-left flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
</div>
<div class="theme-wheel" id="theme-wheel">
<div class="theme-icon" data-theme="olive"></div>
@@ -179,38 +197,37 @@
</div>
</div>
- <div class="bg-background-dark flex z-10 ar-lt-1.1:w-[90vw] ar-lt-0.4:w-[100vw] h-screen ar-lt-1.1:ml-[5vw] ar-lt-0.4:ml-0">
- <div class="pl-[0.5vw] bg-background-dark border-r-[0.4vmin] border-dashed border-main-dark"></div>
+ <div class="bg-background-dark flex z-10 w-[min(90dvw,100dvh)] grow-0 ar-lt-0.8:w-[100dvw] h-[100dvh] ar-lt-0.8:max-h-[92dvh]">
+ <div class="pl-[0.5dvw] bg-background-dark border-r-2 border-dashed border-main-dark"></div>
- <div class="ar-gt-1.1:w-[100vh] flex flex-col bg-background-dark relative pt-[1.6vmin] ml-[1.6vmin] pr-[1.6vmin]">
- <div id="general-page-header" class="flex flex-col"
+ <div class="max-h-100% flex flex-col grow bg-background-dark relative pt-4 ml-8 pr-4">
+ <div id="general-page-header" class="max-xs:hidden flex flex-col basis-8"
hx-get="/api/v1/general-page/header{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML">
</div>
<div id="general-page-header-trigger" hx-get="/api/v1/general-page/header{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="popstate from:window" hx-target="#general-page-header" hx-swap="innerHTML"></div>
- <hr class="border-t-4 border-dotted border-main-dark mb-[0.8vmin]">
+ <hr class="max-xs:hidden border-t-4 border-dotted border-main-dark mb-2">
- <div id="general-page-body" class="flex flex-col max-h-[calc(100%-7vmax)] ar-lt-1.1:max-h-[calc(100%-25vh)] grow"
+ <div id="general-page-body" class="flex flex-col grow overflow-y-auto"
hx-get="/api/v1/general-page/body{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML">
</div>
<div id="general-page-body-trigger" hx-get="/api/v1/general-page/body{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="popstate from:window" hx-target="#general-page-body" hx-swap="innerHTML"></div>
- <div id="general-page-footer" class="flex flex-row mt-[0.8vmin] mb-[0.4vmin]"
+ <div id="general-page-footer" class="flex flex-row basis-4 my-1"
hx-get="/api/v1/general-page/footer{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML">
</div>
<div id="general-page-footer-trigger" hx-get="/api/v1/general-page/footer{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="popstate from:window" hx-target="#general-page-footer" hx-swap="innerHTML"></div>
- <hr class="border-t-4 border-dotted border-main-dark mb-[0.8vmin]">
+ <hr class="border-t-4 border-dotted border-main-dark mb-2">
</div>
- <div class="pr-[0.5vw] bg-background-dark shadow-2xl border-l-[0.4vmin] border-dotted border-main-dark"></div>
+ <div class="pr-[0.5dvw] bg-background-dark shadow-2xl border-l-2 border-dotted border-main-dark"></div>
</div>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/htmx/2.0.6/htmx.min.js"></script>
- <script src="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/lightgallery.min.js"></script>
- <script src="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/plugins/lg-zoom.min.js"></script>
- <script src="https://f003.backblazeb2.com/file/sayana-static/libs/lightgallery/2.8.3/plugins/lg-thumbnail.min.js"></script>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet/1.9.4/leaflet.js"></script>
+ <script src="https://f003.backblazeb2.com/file/sayana-static/libs/imagesloaded/5.0.0/imagesloaded.pkgd.min.js"></script>
+ <script src="https://f003.backblazeb2.com/file/sayana-static/libs/masonry-layout/4.2.2/masonry.pkgd.min.js"></script>
<div id="general-page-bottom-embeds" class="flex"
hx-get="/api/v1/general-page/bottom-embeds{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML">
diff --git a/views/pages/blog-catalogue.html b/views/pages/blog-catalogue.html
index eccafd6..3845275 100644
--- a/views/pages/blog-catalogue.html
+++ b/views/pages/blog-catalogue.html
@@ -1,59 +1,59 @@
{{ define "body" }}
-<div class="flex flex-row ar-lt-1.1:flex-col text-[1vmax] h-[100%]">
+<div class="flex flex-row ar-lt-0.8:flex-col text-base h-[100%]">
<form hx-get="/api/v1/blog-search" hx-vals='{"lang": "{{ .Lang }}"}' hx-target=".blog-cards" hx-swap="innerHTML"
- class="tags-list ar-gt-1.1:min-w-[10vh] ar-gt-1.1:max-w-[20vh] ar-gt-1.1:w-fit ar-lt-1.1:w-[100%] ar-lt-1.1:max-h-[25%] flex shrink-0 flex-col ar-gt-1.1:mr-[1.2vmin]">
+ class="tags-list ar-gt-0.8:min-w-[10dvh] ar-gt-0.8:max-w-[20dvh] ar-gt-0.8:w-fit ar-lt-0.8:w-[100%] ar-lt-0.8:max-h-[30%] flex shrink-0 flex-col ar-gt-0.8:mr-6 bg-background-dark ar-lt-0.8:bg-background-light inset-shadow">
<div class="flex flex-col overflow-y-auto">
<fieldset>
<legend class="font-bold w-[100%] text-center">{{ .L.BlogSearch.TagsHeader }}</legend>
- <div class="flex flex-col ar-lt-1.1:grid grid-cols-5 grid-flow-row-dense">
- <div class="m-[0.4vmin]">
+ <div class="flex flex-col ar-lt-0.8:grid grid-cols-3 xs:grid-cols-4 sm:grid-cols-5 grid-flow-row-dense">
+ <div class="m-0.5">
<label class="font-bold"><input type="checkbox" id="tagsAllCheckbox" onclick="selectAll();"> {{ .L.BlogSearch.ChooseAllTags }}</label>
</div>
{{- range .Tags }}
- <div class="m-[0.4vmin]">
+ <div class="m-0.5">
<label><input type="checkbox" id="tag{{ .Name }}Checkbox" name="tags[]" value="{{ .Name }}" onclick="contextAll();" {{ if contains $.QueryTags .Name }}checked{{ end }}> {{ .Name }} <span class="text-secondary italic">{{ .Count }}</span></label>
</div>
{{- end }}
</div>
</fieldset>
- <fieldset class="mt-[0.8vmin]">
+ <fieldset class="mt-1">
<legend class="font-bold w-[100%] text-center">{{ .L.BlogSearch.OrderByHeader }}</legend>
- <div class="flex flex-col ar-lt-1.1:grid grid-cols-3 grid-rows-2 grid-flow-col">
- <div class="m-[0.4vmin]">
+ <div class="flex flex-col ar-lt-0.8:grid grid-cols-3 grid-rows-2 grid-flow-col">
+ <div class="m-0.5">
<label><input type="radio" id="sortTitleAsc" name="sort" value="titleAsc" {{ if eq .QuerySort "titleAsc" }}checked{{ end }}> {{ .L.BlogSearch.TitleOrdered }} <i class="fas fa-arrow-down-a-z"></i></label>
</div>
- <div class="m-[0.4vmin]">
+ <div class="m-0.5">
<label><input type="radio" id="sortTitleDesc" name="sort" value="titleDesc" {{ if eq .QuerySort "titleDesc" }}checked{{ end }}> {{ .L.BlogSearch.TitleOrdered }} <i class="fas fa-arrow-down-z-a"></i></label>
</div>
- <div class="m-[0.4vmin]">
+ <div class="m-0.5">
<label><input type="radio" id="sortActionDateAsc" name="sort" value="actionDateAsc" {{ if eq .QuerySort "actionDateAsc" }}checked{{ end }}> {{ .L.BlogSearch.ActionDateOrdered }} <i class="fas fa-arrow-down-1-9"></i></label>
</div>
- <div class="m-[0.4vmin]">
+ <div class="m-0.5">
<label><input type="radio" id="sortActionDateDesc" name="sort" value="actionDateDesc" {{ if eq .QuerySort "actionDateDesc" }}checked{{ end }}> {{ .L.BlogSearch.ActionDateOrdered }} <i class="fas fa-arrow-down-9-1"></i></label>
</div>
- <div class="m-[0.4vmin]">
+ <div class="m-0.5">
<label><input type="radio" id="sortPublicationDateAsc" name="sort" value="publicationDateAsc" {{ if eq .QuerySort "publicationDateAsc" }}checked{{ end }}> {{ .L.BlogSearch.PublicationDateOrdered }} <i class="fas fa-arrow-down-1-9"></i></label>
</div>
- <div class="m-[0.4vmin]">
+ <div class="m-0.5">
<label><input type="radio" id="sortPublicationDateDesc" name="sort" value="publicationDateDesc" {{ if eq .QuerySort "publicationDateDesc" }}checked{{ end }}> {{ .L.BlogSearch.PublicationDateOrdered }} <i class="fas fa-arrow-down-9-1"></i></label>
</div>
</div>
</fieldset>
</div>
- <hr class="border-t-[0.2vmax] border-dotted border-main-dark my-[0.4vmin]">
- <div class="flex flex-row grow bg-background-light my-[2vmin] p-[0.4vmin] rounded-[0.4vmin] justify-items-center">
- <i onclick="defaultSearchParams(); cleanHrefParams();" class="fas fa-rotate-left flex-1 text-center text-[1.5vmax] hover:bg-background-dark cursor-pointer transition-colors duration-300"></i>
- <div class="w-[0.5vmin] bg-background-dark grow-0"></div>
+ <hr class="border-t-2 border-dotted border-main-dark my-0.5">
+ <div class="flex flex-row bg-background-dark my-2 p-0.5 rounded-1 justify-items-center">
+ <i onclick="defaultSearchParams(); cleanHrefParams();" class="fas fa-rotate-left flex-1 text-center text-2xl hover:bg-background-light cursor-pointer transition-colors duration-300"></i>
+ <div class="w-1 bg-background-light grow-0"></div>
<button class="flex-1" type="submit">
- <i onclick="setHrefParams();" class="fas fa-magnifying-glass text-center text-[1.5vmax] hover:bg-background-dark cursor-pointer transition-colors duration-300"></i>
+ <i onclick="setHrefParams();" class="fas fa-magnifying-glass text-center text-2xl hover:bg-background-light cursor-pointer transition-colors duration-300"></i>
</button>
</div>
</form>
- <div class="w-[0.5vh] border-r-[0.3vh] border-dotted border-main-dark bg-background-dark"></div>
+ <div class="w-[0.5dvh] border-r-2 border-dotted border-main-dark bg-background-dark"></div>
<div hx-get="/api/v1/blog-search" hx-vals='js:{lang: "{{ .Lang }}", tz: clientTimeZone}' hx-target="this" hx-swap="innerHTML" hx-trigger="load" hx-include=".tags-list"
- class="blog-cards grow flex flex-col overflow-y-auto bg-background-light inset-shadow p-[2.4vmin]">
+ class="blog-cards grow flex flex-col overflow-y-auto bg-background-light inset-shadow p-6">
Loading...
</div>
</div>
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html
index 863b417..9704502 100644
--- a/views/pages/blog-page.html
+++ b/views/pages/blog-page.html
@@ -1,27 +1,14 @@
-{{ define "top-embeds" }}
-<script>
- let galleryMap = new Map();
- let map;
-
- window.addEventListener('popout', (e) => {
- map.remove();
- galleryMap.forEach((_, g, m) => {
- g.destroy();
- });
- galleryMap.clear();
- map = null;
- galleryMap = null;
- }, {once: true});
-</script>
-{{ end }}
-
{{ define "body" }}
-<div class="bg-background-light flex flex-col inset-shadow p-[2.4vmin] overflow-y-auto">
+<div class="bg-background-light flex flex-col inset-shadow px-8 py-4 overflow-y-auto">
+ <p class="xs:hidden font-spectral text-2xl font-bold italic text-main-dark tracking-[.0125rem] mb-1">{{ .Title }}</p>
+ <p class="xs:hidden grow text-lg font-spectral text-secondary">{{ .L.Metadata.Published }}: {{ .PublishedDate }}</p>
+ <p class="xs:hidden grow text-lg font-spectral text-secondary">{{ .L.Metadata.Action }}: {{ .ActionDate }}</p>
+ <hr class="xs:hidden border-t-2 border-dotted border-main-dark mt-1 mb-2 w-full ml-auto mr-auto">
{{ .ParsedMarkdown }}
{{- if .MapLocationX }}
- <hr class="border-t-4 border-dotted border-main-dark mt-[0.8vmin] mb-[0.8vmin] w-[80%] ml-auto mr-auto">
- <div id="map-container" class="relative p-[0.8vmin] flex-none ml-auto mr-auto w-[60%] ar-lt-1.1:w-[80%] h-[40vh] ar-lt-1.1:h-[30vh]"></div>
- <hr class="border-t-4 border-dotted border-main-dark mt-[0.8vmin] mb-[0.8vmin] w-[80%] ml-auto mr-auto">
+ <hr class="border-t-3 border-dotted border-main-dark mt-1 mb-2 w-[80%] ml-auto mr-auto">
+ <div id="map-container" class="relative p-1 flex-none ml-auto mr-auto w-[60%] ar-lt-0.8:w-[80%] h-[40dvh] ar-lt-0.8:h-[30dvh]"></div>
+ <hr class="border-t-3 border-dotted border-main-dark mt-1 mb-2 w-[80%] ml-auto mr-auto">
<script>
function initLocationMap(id, x, y, relativeErrorMeters = 0) {
@@ -48,16 +35,17 @@
.openPopup();
}
- document.addEventListener('htmx:afterRequest', (e) => {
- if (e.detail.target.id == 'general-page-body') {
- initLocationMap(
- 'map-container',
- {{ .MapLocationX }},
- {{ .MapLocationY }},
- {{ .MapLocationAreaMeters }}
- );
- }
- }, {once: true});
+ if (map) {
+ map.remove();
+ map = null;
+ }
+
+ setTimeout(() => initLocationMap(
+ 'map-container',
+ {{ .MapLocationX }},
+ {{ .MapLocationY }},
+ {{ .MapLocationAreaMeters }}
+ ), 1000);
</script>
{{- end }}
</div>
@@ -66,31 +54,3 @@
{{ define "footer" }}
<div hx-get="/api/v1/like" hx-target="this" hx-swap="outerHTML" hx-trigger="load"></div>
{{ end }}
-
-{{ define "bottom-embeds" }}
-<script>
- let galleryResizeTimeout;
-
- function resizeCb() {
- clearTimeout(galleryResizeTimeout);
- galleryResizeTimeout = setTimeout(() => {
- if (map !== undefined) {
- map.invalidateSize();
- }
- var oldGalleryMap = new Map(galleryMap);
- oldGalleryMap.forEach((createFunc, g, map) => {
- galleryMap.delete(g);
- g.destroy();
- createFunc();
- });
- }, 300);
- }
-
- window.addEventListener('resize', resizeCb);
-
- document.addEventListener('popout', (e) => {
- window.removeEventListener('resize', resizeCb);
- galleryResizeTimeout = null;
- });
-</script>
-{{ end }} \ No newline at end of file
diff --git a/views/pages/global-map.html b/views/pages/global-map.html
index a844e06..9b67514 100644
--- a/views/pages/global-map.html
+++ b/views/pages/global-map.html
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>SAYA TODAY // {{ .L.GlobalMap.Header }}</title>
+ <title>{{ .L.GlobalMap.Header }} // SAYA TODAY</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -15,7 +15,7 @@
<link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet.markercluster/1.4.1/MarkerCluster.Default.css">
</head>
-<body data-theme="ram" class="font-spectral text-main-dark overflow-hidden bg-interlocked-hexagons h-screen flex flex-row ar-lt-1.1:flex-col">
+<body data-theme="ram" class="font-spectral text-main-dark overflow-hidden bg-interlocked-hexagons h-[100dvh] flex flex-row ar-lt-0.8:flex-col">
<script>
function switchTheme(theme) {
@@ -40,15 +40,21 @@
const clientTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
</script>
- <div id="sidebar" class="bg-sidebar flex sticky flex-col ar-gt-1.1:items-center shadow-2xl z-20 w-[5vw] ar-lt-1.1:w-screen h-screen ar-lt-1.1:h-[8vh]">
- <div class="logo-custom ar-lt-1.1:hidden text-sidebar font-patua font-extrabold text-center relative z-20">
+ <div id="sidebar" class="bg-sidebar flex sticky flex-col ar-gt-0.8:items-center shadow-2xl z-20 w-[5dvw] ar-lt-0.8:w-[100dvw] h-[100dvh] ar-lt-0.8:h-[8dvh]">
+ <div class="logo-custom ar-lt-0.8:hidden text-sidebar font-patua font-extrabold text-center relative z-20">
saya.today
</div>
- <div class="text-[3vw] ar-lt-1.1:text-[5vh] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1vw] flex flex-col ar-lt-1.1:flex-row gap-0 relative z-20">
- <i onclick="location.href='/{{ .Lang }}';" class="fas fa-home w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
- <i onclick="location.href='/{{ .Lang }}/blog';" class="fas fa-search w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
- <i onclick="location.href='/{{ .Lang }}/map';" class="fas fa-map w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
- <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook w-[5vw] ar-lt-1.1:w-[8vh] h-[5vw] ar-lt-1.1:h-[8vh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 flex rounded-lg"></i>
+ <div class="text-[3dvw] ar-lt-0.8:text-[5dvh] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1dvw] flex flex-col ar-lt-0.8:flex-row gap-0 relative z-20">
+ <a href="/{{ .Lang }}" class="w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i class="fas fa-home flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
+ <a href="/{{ .Lang }}/blog" class="w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i class="fas fa-search flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
+ <a href="/{{ .Lang }}/map" class="w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh]">
+ <i class="fas fa-map flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
+ <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook flex w-[5dvw] ar-lt-0.8:w-[8dvh] h-[5dvw] ar-lt-0.8:h-[8dvh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i>
</div>
<div class="theme-wheel" id="theme-wheel">
<div class="theme-icon" data-theme="olive"></div>
@@ -58,7 +64,7 @@
</div>
</div>
- <div id="map-container" class="bg-background-dark flex z-10 w-[95vw] ar-lt-1.1:w-screen h-screen ar-lt-1.1:h-[92vh]"></div>
+ <div id="map-container" class="bg-background-dark flex z-10 w-[95dvw] ar-lt-0.8:w-[100dvw] h-[100dvh] ar-lt-0.8:h-[92dvh]"></div>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/htmx/2.0.6/htmx.min.js"></script>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet/1.9.4/leaflet.js"></script>
@@ -242,7 +248,7 @@
title: title,
}).bindPopup(`
<div class="flex flex-row justify-center justify-items-center">
- <img onclick="location.href='${link}';" class="cursor-pointer object-cover rounded-[10%] select-none w-[3vmax] h-[3vmax] mr-[0.5vmax]" src="https://f003.backblazeb2.com/file/sayana-photos/webp-320p/${thumbnail}.webp">
+ <img onclick="location.href='${link}';" class="cursor-pointer object-cover rounded-[10%] select-none w-12 h-12 mr-1" src="https://f003.backblazeb2.com/file/sayana-photos/webp-320p/${thumbnail}.webp">
<span><b><a href="${link}">${title}</a></b><br><a href="https://www.openstreetmap.org/#map=13/${x}/${y}">${x}, ${y}</a></span>
</div>`);
diff --git a/views/pages/home-page.html b/views/pages/home-page.html
index 6fd716b..95093a0 100644
--- a/views/pages/home-page.html
+++ b/views/pages/home-page.html
@@ -1,52 +1,52 @@
{{ define "body" }}
-<div class="bg-background-light flex flex-row ar-lt-0.6:flex-col w-full h-full inset-shadow overflow-y-auto text-[1vmax]/[2] tracking-[0.04vmin]">
- <div class="ar-gt-0.6:flex-3/5 justify-center content-start p-[5%]">
- <div class="flex flex-col justify-start items-start bg-background-dark mb-[2vmax]">
- <p class="text-[3vmax]/[2] tracking-[0.2vmin] uppercase w-full font-spectral italic text-left
- border-l-[0.4vmax] border-solid border-(--background-dark-color)
+<div class="bg-background-light flex flex-row ar-lt-0.6:flex-col w-full h-full inset-shadow overflow-y-auto text-base/[2] tracking-wide">
+ <div class="ar-gt-0.6:flex-3/5 justify-center content-start p-8">
+ <div class="flex flex-col justify-start items-start bg-background-dark mb-8">
+ <p class="text-3xl/[2] sm:text-4xl/[2] lg:text-5xl/[2] ml-4 tracking-widest uppercase w-full font-spectral italic text-left
+ border-l-1.5 border-solid border-(--background-dark-color)
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.Hymn1 }}</p>
- <hr class="w-full border-t-[0.2vmax] border-dotted border-main-dark mb-[0.8vmin]">
- <p class="text-[2vmax]/[2] -indent-[2vmax] ml-[2vmax] p-[0.4vmax]">{{ .L.HomePage.Hymn2 }}</p>
- <p class="text-[2vmax]/[2] -indent-[2vmax] ml-[2vmax] p-[0.4vmax]">{{ .L.HomePage.Hymn3 }}</p>
- <p class="text-[2vmax]/[2] -indent-[2vmax] ml-[2vmax] p-[0.4vmax]">{{ .L.HomePage.Hymn4 }}</p>
+ <hr class="w-full border-t-2 border-dotted border-main-dark mb-1">
+ <p class="text-xl/[2] sm:text-2xl/[2] lg:text-3xl/[2] -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn2 }}</p>
+ <p class="text-xl/[2] sm:text-2xl/[2] lg:text-3xl/[2] -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn3 }}</p>
+ <p class="text-xl/[2] sm:text-2xl/[2] lg:text-3xl/[2] -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn4 }}</p>
</div>
<div class="flex flex-col justify-center items-center">
- <p class="text-[2vmax] w-full font-spectral italic text-left
- border-l-[0.4vmax] border-solid border-(--background-dark-color)
+ <p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-spectral italic text-left
+ border-l-1.5 border-solid border-(--background-dark-color)
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.DidYouKnowThat }}</p>
- <hr class="w-full border-t-[0.2vmax] border-dotted border-main-dark mb-[0.8vmin]">
+ <hr class="w-full border-t-2 border-dotted border-main-dark mb-1">
<ul class="w-full text-left list-[circle]">
- <li class="ml-[2vmax] mb-[0.8vmin]">{{ index .FunFacts 0 }}</li>
- <li class="ml-[2vmax] mb-[0.8vmin]">{{ index .FunFacts 1 }}</li>
- <li class="ml-[2vmax]">{{ index .FunFacts 2 }}</li>
+ <li class="ml-4 mb-1">{{ index .FunFacts 0 }}</li>
+ <li class="ml-4 mb-1">{{ index .FunFacts 1 }}</li>
+ <li class="ml-4">{{ index .FunFacts 2 }}</li>
</ul>
</div>
</div>
- <div class="ar-gt-0.6:flex-2/5 justify-center content-start p-[5%]">
- <div class="flex flex-col justify-center items-start mb-[2vmax]">
- <p class="text-[2vmax] w-full font-spectral italic text-left
- border-l-[0.4vmax] border-solid border-(--background-dark-color)
+ <div class="ar-gt-0.6:flex-2/5 justify-center content-start p-8">
+ <div class="flex flex-col justify-center items-start mb-4">
+ <p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-spectral italic text-left
+ border-l-1.5 border-solid border-(--background-dark-color)
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.Contacts }}</p>
<a href="https://t.me/EarlInisMona">
- <i class="fa-brands fa-telegram w-[1vmax] h-[1vmax] mr-[0.4vmax]"></i>
+ <i class="fa-brands fa-telegram w-4 h-4 mr-1"></i>
<span class="font-bold">Telegram:</span>
<span>@EarlInisMona</span>
</a>
<a href="https://discord.com/users/356057270951346176">
- <i class="fa-brands fa-discord w-[1vmax] h-[1vmax] mr-[0.4vmax]"></i>
+ <i class="fa-brands fa-discord w-4 h-4 mr-1"></i>
<span class="font-bold">Discord:</span>
<span>montferrat</span>
</a>
<a href="mailto:saya.andy@posteo.com">
- <i class="fas fa-envelope w-[1vmax] h-[1vmax] mr-[0.4vmax]"></i>
+ <i class="fas fa-envelope w-4 h-4 mr-1"></i>
<span class="font-bold">E-mail:</span>
<span>saya.andy@posteo.com</span>
</a>
</div>
- <div class="flex relative aspect-square justify-center content-center mb-[2vmax]">
+ <div class="flex relative aspect-square justify-center content-center mb-4">
{{- range $_ := iterate .FilledHeartCount }}
<div class="home-page-heart z-50">♥</div>
{{- end }}
@@ -54,7 +54,7 @@
<div class="home-page-heart z-50">♡</div>
{{- end }}
<img src="https://f003.backblazeb2.com/file/sayana-static/home-page-gifs/{{ .GifName }}"
- class="home-page-gif z-49 -rotate-12 max-w-[70%] max-h-[70%] border-[1vmin] border-(--background-dark-color) border-inset">
+ class="home-page-gif z-49 -rotate-12 max-w-[70%] max-h-[70%] border-4 border-(--background-dark-color) border-inset">
</div>
<script>
@@ -100,20 +100,20 @@
</script>
<div class="flex flex-col justify-center items-center">
- <p class="text-[2vmax] w-full font-spectral italic text-left
- border-l-[0.4vmax] border-solid border-(--background-dark-color)
+ <p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-spectral italic text-left
+ border-l-1.5 border-solid border-(--background-dark-color)
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.SidebarDescription }}</p>
- <hr class="w-full border-t-[0.2vmax] border-dotted border-main-dark mb-[0.8vmin]">
+ <hr class="w-full border-t-2 border-dotted border-main-dark mb-1">
<div class="w-full grid grid-cols-[1fr_4fr] content-center items-center
[&>*:nth-child(4n+2)]:bg-(--background-medium-color) [&>*:nth-child(4n+3)]:bg-(--background-medium-color)" style="container-type: inline-size;">
<i class="fas fa-home w-full h-full text-[10cqi] content-center text-center text-main-dark"></i>
- <p class="p-[0.4vmax]">{{ .L.HomePage.HomePageDescription }}</p>
+ <p class="p-1">{{ .L.HomePage.HomePageDescription }}</p>
<i class="fas fa-search w-full h-full text-[10cqi] content-center text-center text-main-dark"></i>
- <p class="p-[0.4vmax]">{{ .L.HomePage.BlogSearchDescription }}</p>
+ <p class="p-1">{{ .L.HomePage.BlogSearchDescription }}</p>
<i class="fas fa-map w-full h-full text-[10cqi] content-center text-center text-main-dark"></i>
- <p class="p-[0.4vmax]">{{ .L.HomePage.MarkerMapDescription }}</p>
+ <p class="p-1">{{ .L.HomePage.MarkerMapDescription }}</p>
<i class="fas fa-swatchbook w-full h-full text-[10cqi] content-center text-center text-main-dark"></i>
- <p class="p-[0.4vmax]">{{ .L.HomePage.ThemeSwitchDescription }}</p>
+ <p class="p-1">{{ .L.HomePage.ThemeSwitchDescription }}</p>
</div>
</div>
</div>
diff --git a/views/partials/blog-page-like-button.html b/views/partials/blog-page-like-button.html
index a16e8c0..f23ef9d 100644
--- a/views/partials/blog-page-like-button.html
+++ b/views/partials/blog-page-like-button.html
@@ -1,6 +1,6 @@
<button
hx-put="/api/v1/like" hx-vals='{"like": {{ not .Liked }}}' hx-target="this" hx-swap="outerHTML" hx-trigger="click"
- class="text-[0.8vmax]/[0.9] font-spectral text-left px-[0.4vmax] py-[0.2vmax] {{ if .Liked }}bg-main-light hover:bg-main-medium text-background-dark border-inset{{ else }}bg-main-dark hover:bg-main-medium text-background-light border-outset{{ end }} cursor-pointer border-[0.2vmax] border-background-dark">
- <i class="fas fa-thumbs-up w-[0.8vmax] h-[0.8vmax]"></i>
- <span class="italic ml-[0.2vmax] text-background-light">({{ .LikedCount }})</span>
+ class="text-sm/[0.9] shrink-0 font-spectral text-left px-1 py-0.5 {{ if .Liked }}bg-main-light hover:bg-main-medium text-background-dark border-inset{{ else }}bg-main-dark hover:bg-main-medium text-background-light border-outset{{ end }} cursor-pointer border-2 border-background-dark">
+ <i class="fas fa-thumbs-up w-3 h-3"></i>
+ <span class="italic ml-0.5 text-background-light">({{ .LikedCount }})</span>
</button> \ No newline at end of file
diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html
index 37b3f57..5c3bb95 100644
--- a/views/partials/catalogue-blog-cards.html
+++ b/views/partials/catalogue-blog-cards.html
@@ -1,25 +1,27 @@
{{- range .BlogPages }}
-<hr class="first-of-type:hidden border-t-[0.3vh] my-[0.8vmin] border-dotted border-main-dark w-[80%] mx-auto">
-<div class="m-[0.4vmin] flex flex-row justify-center justify-items-center">
- <img onclick="changeUrl('{{ .ArticleLink }}');" class="cursor-pointer object-cover rounded-[10%] select-none w-[10vmin] h-[10vmin] aspect-square my-[0.4vmin] mr-[0.8vmin]" src="https://f003.backblazeb2.com/file/sayana-photos/webp-320p/{{ .Thumbnail }}.webp">
- <div class="grow my-[0.4vmin] mx-[0.8vmin] flex flex-col justify-center">
- <div class="flex flex-row gap-[5%] max-w-[100%]">
- <a onclick="changeUrl('{{ .ArticleLink }}');" class="flex-9/12 grow-0 block text-[1vmax] cursor-pointer">
+<hr class="first-of-type:hidden my-1 border-t-2 border-dotted border-main-dark">
+<div class="m-1 flex flex-row justify-center justify-items-center">
+ <a href="{{ .ArticleLink }}" class="w-24 h-24 basis-24 shrink-0 my-2.5 mr-2">
+ <img onclick="return changeUrl('{{ .ArticleLink }}');" class="w-full h-full aspect-square cursor-pointer object-cover rounded-lg select-none" src="https://f003.backblazeb2.com/file/sayana-photos/webp-320p/{{ .Thumbnail }}.webp">
+ </a>
+ <div class="grow my-0.5 mx-1 flex flex-col justify-center">
+ <div class="flex flex-row gap-2 max-w-[100%]">
+ <a href="{{ .ArticleLink }}" onclick="return changeUrl('{{ .ArticleLink }}');" class="grow text-base cursor-pointer">
<span class="font-extrabold">{{ .Title }}</span>
<span class="font-extrabold select-none text-secondary">//</span>
<span class="italic text-secondary">{{ .ActionDate }}</span>
</a>
- <p class="flex-3/12 grow-0 text-[1vmax] italic text-secondary text-right">{{ .PublishedTime }}</p>
+ <p class="basis-56 text-base italic text-secondary text-right">{{ .PublishedTime }}</p>
</div>
- <p class="text-[1vmax] text-main-dark">{{ .ShortDescription }}</p>
- <p class="text-[1vmax] text-secondary italic">
- <i class="fas fa-thumbs-up w-[1vmax] h-[1vmax]"></i>
+ <p class="text-base text-main-dark">{{ .ShortDescription }}</p>
+ <p class="text-base text-secondary italic">
+ <i class="fas fa-thumbs-up w-4 h-4"></i>
<span>{{ .LikeCount }}</span>
<span class="font-extrabold select-none">//</span>
- <i class="fas fa-eye w-[1vmax] h-[1vmax]"></i>
+ <i class="fas fa-eye w-4 h-4"></i>
<span>{{ .ViewCount }}</span>
</p>
- <p class="text-[1vmax] text-secondary">{{ $.L.TagsLabel }} {{ template "catalogue-blog-card-tags.html" . }}</p>
+ <p class="text-base text-secondary">{{ $.L.TagsLabel }} {{ template "catalogue-blog-card-tags.html" . }}</p>
</div>
</div>
{{- end }} \ No newline at end of file
diff --git a/views/partials/general-page-body.html b/views/partials/general-page-body.html
index 4686ea1..c3aa3eb 100644
--- a/views/partials/general-page-body.html
+++ b/views/partials/general-page-body.html
@@ -1,2 +1,2 @@
-<title>SAYA TODAY // {{ .Title }}</title>
+<title>{{ .Title }} // SAYA TODAY</title>
{{ block "body" . }}{{ end }} \ No newline at end of file
diff --git a/views/partials/general-page-footer.html b/views/partials/general-page-footer.html
index af6aec9..8979423 100644
--- a/views/partials/general-page-footer.html
+++ b/views/partials/general-page-footer.html
@@ -1,7 +1,7 @@
{{ block "footer" . }}{{ end }}
-<p class="grow content-center text-[1vmax]/[1] font-spectral italic text-right text-secondary mr-2">
+<p class="grow content-center text-base/[1] font-spectral italic text-right text-secondary mr-1">
All the photos on <a href="https://saya.today/">saya.today</a> are licensed under <a href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a> by <a href="https://t.me/EarlInisMona">Saya Andy</a> © {{ .PublishedYear }}
</p>
-<img class="max-w-[1vmax] max-h-[1vmax] self-center" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="CC">
-<img class="max-w-[1vmax] max-h-[1vmax] self-center" src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="BY">
-<img class="max-w-[1vmax] max-h-[1vmax] self-center" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg" alt="SA"> \ No newline at end of file
+<img class="max-w-4 max-h-4 self-center" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="CC">
+<img class="max-w-4 max-h-4 self-center" src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="BY">
+<img class="max-w-4 max-h-4 self-center" src="https://mirrors.creativecommons.org/presskit/icons/sa.svg" alt="SA"> \ No newline at end of file
diff --git a/views/partials/general-page-header.html b/views/partials/general-page-header.html
index 6cb87b7..e5488b4 100644
--- a/views/partials/general-page-header.html
+++ b/views/partials/general-page-header.html
@@ -1,8 +1,10 @@
<div {{ if .PublishedDate }} hx-get="/api/v1/tz" hx-vals='js:{timestamp: "{{ .PublishedDate }}", tz: clientTimeZone}' hx-target="#published-date" hx-swap="innerHTML" hx-trigger="load" {{ end }}
- class="flex flex-row mb-[0.4vmin]">
- <i onclick="changeUrl('/../', true);" class="fas fa-circle-left hover:bg-main-dark hover:bg-opacity-10 cursor-pointer transition-colors duration-300 rounded-md text-[2vmax] mt-auto mb-auto px-[0.8vmin]"></i>
- <p class="text-[2.5vmin] font-spectral italic font-extrabold select-none mt-auto pl-[0.8vmin] pr-[1.2vmin]">//</p>
- <p class="text-[2.5vmin] font-spectral italic text-left mt-auto">{{ .Title }}</p>
- <p id="published-date" class="grow text-[1.75vmin] font-spectral text-secondary text-right mt-auto">{{ .PublishedDate }}</p>
+ class="flex flex-row mb-2">
+ <a href="./" class="w-(--text-4xl) h-(--text-4xl) mx-1 my-auto">
+ <i onclick="return changeUrl('/../', true);" class="fas fa-circle-left hover:bg-main-dark hover:bg-opacity-10 cursor-pointer transition-colors duration-300 rounded-md text-4xl"></i>
+ </a>
+ <p class="text-4xl font-spectral italic font-extrabold select-none my-auto pl-3 pr-3">//</p>
+ <p class="text-4xl font-spectral italic text-left mt-auto">{{ .Title }}</p>
+ <p id="published-date" class="grow text-2xl font-spectral text-secondary text-right mt-auto">{{ .PublishedDate }}</p>
</div>
{{ block "header" . }}{{ end }}