From 454e2f3cd84b6c0b02a0c2936a574d3d9c35c5a1 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Wed, 15 Oct 2025 02:43:04 +0700 Subject: feat: start switching to absolute length units in design --- internal/lightgallery/html_renderer.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'internal/lightgallery/html_renderer.go') diff --git a/internal/lightgallery/html_renderer.go b/internal/lightgallery/html_renderer.go index 8e184e0..f02b953 100644 --- a/internal/lightgallery/html_renderer.go +++ b/internal/lightgallery/html_renderer.go @@ -51,9 +51,9 @@ func (r *LightGalleryHTMLRenderer) renderLightGallery(w util.BufWriter, source [ w.WriteString(fmt.Sprintf(`
-
+
-
+
`, galleryID)) var dynamicElements []string @@ -84,8 +84,8 @@ func (r *LightGalleryHTMLRenderer) renderLightGallery(w util.BufWriter, source [ thumb: "https://f003.backblazeb2.com/file/sayana-photos/webp-320p/%s.webp", subHtml: `+"`"+``+"`"+` }`, img.URL, img.URL, util.EscapeHTML(captionHTML), imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, imageUrlWithoutExt, captionHTML, dayDate.Format("2006-01-02 15:04:05 -07:00"))) } -- cgit v1.3.1+13 From 739a4af71187e82fd58956e5ad36f0baefddf3c4 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Wed, 15 Oct 2025 18:14:59 +0700 Subject: feat: improve measurements in layout --- internal/lightgallery/html_renderer.go | 6 ++-- internal/tailwind/transformer.go | 24 +++++++------- views/index.html | 6 ++-- views/layouts/general-page.html | 8 ++--- views/pages/blog-catalogue.html | 26 ++++++++-------- views/pages/blog-page.html | 10 +++--- views/pages/global-map.html | 2 +- views/pages/home-page.html | 52 +++++++++++++++---------------- views/partials/blog-page-like-button.html | 4 +-- views/partials/catalogue-blog-cards.html | 12 +++---- views/partials/general-page-footer.html | 2 +- views/partials/general-page-header.html | 8 ++--- 12 files changed, 80 insertions(+), 80 deletions(-) (limited to 'internal/lightgallery/html_renderer.go') diff --git a/internal/lightgallery/html_renderer.go b/internal/lightgallery/html_renderer.go index f02b953..c2f785e 100644 --- a/internal/lightgallery/html_renderer.go +++ b/internal/lightgallery/html_renderer.go @@ -50,10 +50,10 @@ func (r *LightGalleryHTMLRenderer) renderLightGallery(w util.BufWriter, source [ galleryID := generateDivId(8) w.WriteString(fmt.Sprintf(` -
-
+
+
-
+
`, galleryID)) var dynamicElements []string diff --git a/internal/tailwind/transformer.go b/internal/tailwind/transformer.go index 4057ea4..f932533 100644 --- a/internal/tailwind/transformer.go +++ b/internal/tailwind/transformer.go @@ -17,44 +17,44 @@ 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-4xl font-bold text-main-dark mb-6 tracking-[.0125rem]", - 2: "font-spectral text-3xl font-bold text-main-dark mb-2 tracking-[.0125rem]", - 3: "font-spectral text-2xl font-medium text-main-dark mb-1.5 tracking-[.0125rem]", - 4: "font-spectral text-xl font-medium text-main-medium mb-1 tracking-[.0125rem]", - 5: "font-spectral text-base font-medium text-main-medium mb-1 italic tracking-[.0125rem]", - 6: "font-spectral text-base font-medium text-secondary mb-1", + 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-base/[2] font-spectral tracking-[.0125rem] -indent-8 ml-8 mb-8")) + 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-2 mb-8 pl-8")) + 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-2 mb-8 pl-8")) + 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-base/[2] font-spectral tracking-[.0125rem]")) case *ast.Blockquote: - node.SetAttribute([]byte("class"), []byte("border-l-1 border-main-medium bg-background-dark p-2 mb-2 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-2 rounded-lg overflow-x-auto mb-8")) + node.SetAttribute([]byte("class"), []byte("bg-background-dark p-1 rounded-lg overflow-x-auto mb-4")) case *ast.Link: 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-8")) + 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/views/index.html b/views/index.html index 666b9c6..c81d4b7 100644 --- a/views/index.html +++ b/views/index.html @@ -102,14 +102,14 @@ switchTheme(savedTheme); - -
-
+
+
-
+
+ class="blog-cards grow flex flex-col overflow-y-auto bg-background-light inset-shadow p-6"> Loading...
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html index cc00e1a..78a4b7f 100644 --- a/views/pages/blog-page.html +++ b/views/pages/blog-page.html @@ -16,12 +16,12 @@ {{ end }} {{ define "body" }} -
+
{{ .ParsedMarkdown }} {{- if .MapLocationX }} -
-
-
+
+
+
-{{ end }} \ No newline at end of file +{{ end }} diff --git a/views/pages/global-map.html b/views/pages/global-map.html index 330790b..7d730ea 100644 --- a/views/pages/global-map.html +++ b/views/pages/global-map.html @@ -242,7 +242,7 @@ title: title, }).bindPopup(` `); diff --git a/views/pages/home-page.html b/views/pages/home-page.html index 30f5ad0..9db6d23 100644 --- a/views/pages/home-page.html +++ b/views/pages/home-page.html @@ -1,52 +1,52 @@ {{ define "body" }} -
-
+
+
-

{{ .L.HomePage.Hymn1 }}

-
-

{{ .L.HomePage.Hymn2 }}

-

{{ .L.HomePage.Hymn3 }}

-

{{ .L.HomePage.Hymn4 }}

+
+

{{ .L.HomePage.Hymn2 }}

+

{{ .L.HomePage.Hymn3 }}

+

{{ .L.HomePage.Hymn4 }}

-

{{ .L.HomePage.DidYouKnowThat }}

-
+
    -
  • {{ index .FunFacts 0 }}
  • -
  • {{ index .FunFacts 1 }}
  • -
  • {{ index .FunFacts 2 }}
  • +
  • {{ index .FunFacts 0 }}
  • +
  • {{ index .FunFacts 1 }}
  • +
  • {{ index .FunFacts 2 }}
-
-
-

+

-
+
{{- range $_ := iterate .FilledHeartCount }}
{{- end }} @@ -54,7 +54,7 @@
{{- end }} + class="home-page-gif z-49 -rotate-12 max-w-[70%] max-h-[70%] border-4 border-(--background-dark-color) border-inset">
-

{{ .L.HomePage.SidebarDescription }}

-
+
-

{{ .L.HomePage.HomePageDescription }}

+

{{ .L.HomePage.HomePageDescription }}

-

{{ .L.HomePage.BlogSearchDescription }}

+

{{ .L.HomePage.BlogSearchDescription }}

-

{{ .L.HomePage.MarkerMapDescription }}

+

{{ .L.HomePage.MarkerMapDescription }}

-

{{ .L.HomePage.ThemeSwitchDescription }}

+

{{ .L.HomePage.ThemeSwitchDescription }}

diff --git a/views/partials/blog-page-like-button.html b/views/partials/blog-page-like-button.html index 1dfb5b8..f286471 100644 --- a/views/partials/blog-page-like-button.html +++ b/views/partials/blog-page-like-button.html @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html index f96e0f1..041f3c8 100644 --- a/views/partials/catalogue-blog-cards.html +++ b/views/partials/catalogue-blog-cards.html @@ -1,15 +1,15 @@ {{- range .BlogPages }} -
+
- -
-
- + +
+
+ {{ .Title }} // {{ .ActionDate }} -

{{ .PublishedTime }}

+

{{ .PublishedTime }}

{{ .ShortDescription }}

diff --git a/views/partials/general-page-footer.html b/views/partials/general-page-footer.html index c0774f6..8979423 100644 --- a/views/partials/general-page-footer.html +++ b/views/partials/general-page-footer.html @@ -1,5 +1,5 @@ {{ block "footer" . }}{{ end }} -

+

All the photos on saya.today are licensed under CC BY-SA 4.0 by Saya Andy © {{ .PublishedYear }}

CC diff --git a/views/partials/general-page-header.html b/views/partials/general-page-header.html index d13a6d8..115ab13 100644 --- a/views/partials/general-page-header.html +++ b/views/partials/general-page-header.html @@ -1,8 +1,8 @@
- -

//

-

{{ .Title }}

+ class="flex flex-row mb-2"> + +

//

+

{{ .Title }}

{{ .PublishedDate }}

{{ block "header" . }}{{ end }} -- cgit v1.3.1+13 From 44fe2478478225450becb77ad5d273462c9b400a Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Thu, 16 Oct 2025 12:23:00 +0700 Subject: feat: implement new prototype gallery --- internal/glightbox/block.go | 31 +++++++ internal/glightbox/extension.go | 28 +++++++ internal/glightbox/html_renderer.go | 134 ++++++++++++++++++++++++++++++ internal/glightbox/parser.go | 88 ++++++++++++++++++++ internal/lightgallery/block.go | 31 ------- internal/lightgallery/extension.go | 28 ------- internal/lightgallery/html_renderer.go | 145 -------------------------------- internal/lightgallery/parser.go | 88 -------------------- main.go | 4 +- static/input.css | 147 +++------------------------------ views/layouts/general-page.html | 11 ++- views/pages/blog-catalogue.html | 2 +- 12 files changed, 302 insertions(+), 435 deletions(-) create mode 100644 internal/glightbox/block.go create mode 100644 internal/glightbox/extension.go create mode 100644 internal/glightbox/html_renderer.go create mode 100644 internal/glightbox/parser.go delete mode 100644 internal/lightgallery/block.go delete mode 100644 internal/lightgallery/extension.go delete mode 100644 internal/lightgallery/html_renderer.go delete mode 100644 internal/lightgallery/parser.go (limited to 'internal/lightgallery/html_renderer.go') diff --git a/internal/glightbox/block.go b/internal/glightbox/block.go new file mode 100644 index 0000000..696f328 --- /dev/null +++ b/internal/glightbox/block.go @@ -0,0 +1,31 @@ +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 + 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/glightbox/extension.go b/internal/glightbox/extension.go new file mode 100644 index 0000000..7fd17b1 --- /dev/null +++ b/internal/glightbox/extension.go @@ -0,0 +1,28 @@ +package glightbox + +import ( + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/renderer" + "github.com/yuin/goldmark/util" +) + +// Extension that combines parser and renderer +type GLightboxExtension struct{} + +func NewGLightboxExtension() goldmark.Extender { + return &GLightboxExtension{} +} + +func (e *GLightboxExtension) Extend(m goldmark.Markdown) { + m.Parser().AddOptions( + parser.WithBlockParsers( + util.Prioritized(NewGLightboxParser(), 500), + ), + ) + m.Renderer().AddOptions( + renderer.WithNodeRenderers( + util.Prioritized(NewGLightboxHTMLRenderer(), 500), + ), + ) +} diff --git a/internal/glightbox/html_renderer.go b/internal/glightbox/html_renderer.go new file mode 100644 index 0000000..3b6a533 --- /dev/null +++ b/internal/glightbox/html_renderer.go @@ -0,0 +1,134 @@ +package glightbox + +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 GLightboxHTMLRenderer struct { + html.Config + md goldmark.Markdown +} + +func NewGLightboxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer { + r := &GLightboxHTMLRenderer{ + Config: html.NewConfig(), + md: goldmark.New( + goldmark.WithRendererOptions( + html.WithHardWraps(), + html.WithXHTML(), + ), + ), + } + for _, opt := range opts { + opt.SetHTMLOption(&r.Config) + } + 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("

")) + captionHTML = bytes.TrimSuffix(captionHTML, []byte("

\n")) + captionHTML = bytes.TrimSuffix(captionHTML, []byte("

")) + } + + 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) + } + + elements = append(elements, fmt.Sprintf(` + + webp thumbnail + `, img.URL, galleryID, galleryID, galleryID, dayDate.Format("2006-01-02 15:04:05 -07:00"), dataDescriptionAttribute, imageUrlWithoutExt)) + + if glightboxDescId != "" { + elements = append(elements, fmt.Sprintf(` +
+

%s

+
`, glightboxDescId, captionHTML)) + } + } + + w.WriteString(fmt.Sprintf(` +
+
+
+
+ %s +
+
+
`, galleryID, galleryID, strings.Join(elements, "\n"))) + + w.WriteString(fmt.Sprintf(` +`, 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/glightbox/parser.go b/internal/glightbox/parser.go new file mode 100644 index 0000000..ba3f22e --- /dev/null +++ b/internal/glightbox/parser.go @@ -0,0 +1,88 @@ +package glightbox + +import ( + "bytes" + "log/slog" + "regexp" + "time" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/text" +) + +type GLightboxParser struct{} + +func NewGLightboxParser() parser.BlockParser { + return &GLightboxParser{} +} + +func (p *GLightboxParser) Trigger() []byte { + return []byte{'{'} +} + +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:")) { + return nil, parser.NoChildren + } + + r := regexp.MustCompile(`^\{Gallery:([A-Za-z0-9\+\-/]+)\}$`) + + trimmed := bytes.TrimSpace(line) + parts := r.FindSubmatch(trimmed) + if len(parts) < 2 { + slog.Warn("invalid gallery header format", slog.String("line", string(trimmed)), slog.Int("submatch_count", len(parts))) + return nil, parser.NoChildren + } + + loc, err := time.LoadLocation(string(parts[1])) + if err != nil { + slog.Warn("invalid location specified for a gallery", slog.String("error", err.Error()), slog.String("line", string(trimmed)), slog.String("location", string(parts[1]))) + return nil, parser.NoChildren + } + + return &GLightboxBlock{Location: loc}, parser.NoChildren +} + +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 + } + + trimmed := bytes.TrimSpace(line) + if bytes.Equal(trimmed, []byte("{Gallery}")) || bytes.Equal(trimmed, []byte("{/Gallery}")) { + reader.AdvanceLine() + return parser.Close + } + + gallery := node.(*GLightboxBlock) + + parts := bytes.SplitN(trimmed, []byte{'|'}, 2) + url := bytes.TrimSpace(parts[0]) + + caption := make([]byte, 0) + if len(parts) > 1 { + caption = bytes.TrimSpace(parts[1]) + } + + gallery.Images = append(gallery.Images, GLightboxImage{ + URL: string(url), + Caption: caption, + }) + + return parser.Continue | parser.NoChildren +} + +func (p *GLightboxParser) Close(node ast.Node, reader text.Reader, pc parser.Context) { +} + +func (p *GLightboxParser) CanInterruptParagraph() bool { + return true +} + +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/extension.go b/internal/lightgallery/extension.go deleted file mode 100644 index 761dc05..0000000 --- a/internal/lightgallery/extension.go +++ /dev/null @@ -1,28 +0,0 @@ -package lightgallery - -import ( - "github.com/yuin/goldmark" - "github.com/yuin/goldmark/parser" - "github.com/yuin/goldmark/renderer" - "github.com/yuin/goldmark/util" -) - -// Extension that combines parser and renderer -type LightGalleryExtension struct{} - -func NewLightGalleryExtension() goldmark.Extender { - return &LightGalleryExtension{} -} - -func (e *LightGalleryExtension) Extend(m goldmark.Markdown) { - m.Parser().AddOptions( - parser.WithBlockParsers( - util.Prioritized(NewLightGalleryParser(), 500), - ), - ) - m.Renderer().AddOptions( - renderer.WithNodeRenderers( - util.Prioritized(NewLightGalleryHTMLRenderer(), 500), - ), - ) -} diff --git a/internal/lightgallery/html_renderer.go b/internal/lightgallery/html_renderer.go deleted file mode 100644 index c2f785e..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(` -
-
- -
-
`, 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("

")) - captionHTML = bytes.TrimSuffix(captionHTML, []byte("

\n")) - captionHTML = bytes.TrimSuffix(captionHTML, []byte("

")) - } - - 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: `+"`"+``+"`"+` - }`, 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(` -`, 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/lightgallery/parser.go b/internal/lightgallery/parser.go deleted file mode 100644 index daec797..0000000 --- a/internal/lightgallery/parser.go +++ /dev/null @@ -1,88 +0,0 @@ -package lightgallery - -import ( - "bytes" - "log/slog" - "regexp" - "time" - - "github.com/yuin/goldmark/ast" - "github.com/yuin/goldmark/parser" - "github.com/yuin/goldmark/text" -) - -type LightGalleryParser struct{} - -func NewLightGalleryParser() parser.BlockParser { - return &LightGalleryParser{} -} - -func (p *LightGalleryParser) Trigger() []byte { - return []byte{'{'} -} - -func (p *LightGalleryParser) Open(parent ast.Node, reader text.Reader, pc parser.Context) (ast.Node, parser.State) { - line, _ := reader.PeekLine() - - if !bytes.HasPrefix(line, []byte("{Gallery:")) { - return nil, parser.NoChildren - } - - r := regexp.MustCompile(`^\{Gallery:([A-Za-z0-9\+\-/]+)\}$`) - - trimmed := bytes.TrimSpace(line) - parts := r.FindSubmatch(trimmed) - if len(parts) < 2 { - slog.Warn("invalid gallery header format", slog.String("line", string(trimmed)), slog.Int("submatch_count", len(parts))) - return nil, parser.NoChildren - } - - loc, err := time.LoadLocation(string(parts[1])) - if err != nil { - slog.Warn("invalid location specified for a gallery", slog.String("error", err.Error()), slog.String("line", string(trimmed)), slog.String("location", string(parts[1]))) - return nil, parser.NoChildren - } - - return &LightGalleryBlock{Location: loc}, parser.NoChildren -} - -func (p *LightGalleryParser) 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 - } - - trimmed := bytes.TrimSpace(line) - if bytes.Equal(trimmed, []byte("{Gallery}")) || bytes.Equal(trimmed, []byte("{/Gallery}")) { - reader.AdvanceLine() - return parser.Close - } - - gallery := node.(*LightGalleryBlock) - - parts := bytes.SplitN(trimmed, []byte{'|'}, 2) - url := bytes.TrimSpace(parts[0]) - - caption := make([]byte, 0) - if len(parts) > 1 { - caption = bytes.TrimSpace(parts[1]) - } - - gallery.Images = append(gallery.Images, LightGalleryImage{ - URL: string(url), - Caption: caption, - }) - - return parser.Continue | parser.NoChildren -} - -func (p *LightGalleryParser) Close(node ast.Node, reader text.Reader, pc parser.Context) { -} - -func (p *LightGalleryParser) CanInterruptParagraph() bool { - return true -} - -func (p *LightGalleryParser) CanAcceptIndentedLine() bool { - return false -} diff --git a/main.go b/main.go index 20e90f4..53dbb74 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" @@ -32,7 +32,7 @@ import ( var ( md = goldmark.New( goldmark.WithExtensions( - lightgallery.NewLightGalleryExtension(), + glightbox.NewGLightboxExtension(), tailwind.NewTailwindExtension(), ), goldmark.WithParserOptions( diff --git a/static/input.css b/static/input.css index 51c3c30..36d17b2 100644 --- a/static/input.css +++ b/static/input.css @@ -247,10 +247,6 @@ a:hover { background-size: calc(var(--squares-and-triangles-background-width-coef) * 1vw) calc(var(--squares-and-triangles-background-height-coef) * 1vw); } -body:has(.lg-container:not([class~="lg-inline"])) #sidebar { - display: none !important; -} - .logo-custom { width: 3.5vw; height: 20vw; @@ -346,142 +342,25 @@ 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: 5dvh 5dvw; -} - -.lg-thumb-outer { - background-color: var(--background-light-color) !important; - opacity: 0.8 !important; -} - -.lg-prev { - background-color: var(--background-light-color); - color: var(--main-dark-color); -} - -.lg-next { - background-color: var(--background-light-color); - color: var(--main-dark-color); -} - -.lg-counter { - 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; -} - -.lg-content { - top: 2.5vmax !important; - bottom: calc(10vmin + 5vmax) !important; -} - -.lg-outer[class~="lg-single-item"] .lg-content { - bottom: 5vmax !important; -} - -.lg-thumb-item { - width: 10vmin !important; - height: 10vmin !important; -} - -.lg-container:not([class~="lg-inline"]) .lg-content { - top: 4vmax !important; -} - -.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); -} - -.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; -} - -.lg-prev { - left: 0 !important; -} - -.lg-next { - right: 0 !important; +.grid-item, .grid-sizer { + width: 50%; } -.lg-toolbar .lg-icon:hover { - color: var(--main-medium-color); -} - -.lg-toolbar .lg-icon { - font-size: 1.5vmax !important; - color: var(--main-dark-color); -} - -.lg-content .lg-icon:hover { - color: var(--main-medium-color); -} - -.lg-sub-html { - padding: 0.7vmin 1.25vmin !important; -} - -.inline-gallery-container { - width: 80%; - height: 70vmin; -} - -.light-gallery-captions { - p { - transform: translate3d(0, 0, 0px); - transition-delay: 500ms; - opacity: 1; +@media (width >= 32rem) { + .grid-item, .grid-sizer { + width: 33%; } } -.lg-slide-progress { - .light-gallery-captions { - h4 { - transform: translate3d(-60px, 0, 0px); - } - - p { - transform: translate3d(60px, 0, 0px); - } - - h4, - p { - opacity: 0; - } +@media (width >= 40rem) { + .grid-item, .grid-sizer { + width: 25%; } } -.lg-current { - &.lg-slide-progress { - .light-gallery-captions { - - h4, - p { - transition-delay: 0ms; - } - } +@media (width >= 48rem) { + .grid-item, .grid-sizer { + width: 20%; } } @@ -535,8 +414,8 @@ body[data-theme~="ram"] .leaflet-tile { background-size: calc(var(--squares-and-triangles-background-width-coef) * 1.6vh) calc(var(--squares-and-triangles-background-height-coef) * 1.6vh); } - .inline-gallery-container { - width: 100%; + .ar-lt-0\.8\:bg-background-light { + background-color: var(--background-light-color); } .logo-custom { diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index 5d84649..88c5de5 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -7,10 +7,8 @@ - - - + @@ -26,6 +24,8 @@ }; + + - - - + +
diff --git a/views/pages/blog-catalogue.html b/views/pages/blog-catalogue.html index faa6588..05a7bc5 100644 --- a/views/pages/blog-catalogue.html +++ b/views/pages/blog-catalogue.html @@ -1,7 +1,7 @@ {{ define "body" }}
+ 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">
{{ .L.BlogSearch.TagsHeader }} -- cgit v1.3.1+13