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/parser.go | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 internal/glightbox/parser.go (limited to 'internal/glightbox/parser.go') 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 +} -- cgit v1.3.1+13 From c9a2858279d3d3bf48d752d5ad250303368f9ebd Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Fri, 17 Oct 2025 04:17:06 +0700 Subject: feat: add support for tags in gallery images feat: add 2x tag for an image in gallery feat: update layout of galleries while loading images (not just after) --- internal/glightbox/block.go | 1 + internal/glightbox/html_renderer.go | 31 +++++++++++++++++++++++++------ internal/glightbox/parser.go | 16 ++++++++++++++-- static/input.css | 16 ++++++++++++++++ views/pages/global-map.html | 2 +- 5 files changed, 57 insertions(+), 9 deletions(-) (limited to 'internal/glightbox/parser.go') diff --git a/internal/glightbox/block.go b/internal/glightbox/block.go index 696f328..e53e67b 100644 --- a/internal/glightbox/block.go +++ b/internal/glightbox/block.go @@ -15,6 +15,7 @@ type GLightboxBlock struct { type GLightboxImage struct { URL string + Tags []string Caption []byte } diff --git a/internal/glightbox/html_renderer.go b/internal/glightbox/html_renderer.go index 43d4790..3da98eb 100644 --- a/internal/glightbox/html_renderer.go +++ b/internal/glightbox/html_renderer.go @@ -78,11 +78,26 @@ func (r *GLightboxHTMLRenderer) renderGLightbox(w util.BufWriter, source []byte, 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") + } + } + elements = append(elements, fmt.Sprintf(` - - webp thumbnail - `, img.URL, galleryID, galleryID, galleryID, dayDate.Format("2006-01-02 15:04:05 -07:00"), dataDescriptionAttribute, imageUrlWithoutExt)) + + + + + + + + + `, 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)) if glightboxDescId != "" { elements = append(elements, fmt.Sprintf(` @@ -114,10 +129,14 @@ func (r *GLightboxHTMLRenderer) renderGLightbox(w util.BufWriter, source []byte, percentPosition: true }); - imagesLoaded('.masonry-grid-%s', function() { - msnry_%s.layout(); + var imgLoad_%s_timer; + var imgLoad_%s = imagesLoaded('.masonry-grid-%s', () => msnry_%s.layout()); + + imgLoad_%s.on('progress', function() { + clearTimeout(imgLoad_%s_timer); + imgLoad_%s_timer = setTimeout(() => msnry_%s.layout(), 500); }); -`, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID)) +`, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID, galleryID)) } return ast.WalkContinue, nil diff --git a/internal/glightbox/parser.go b/internal/glightbox/parser.go index ba3f22e..6780090 100644 --- a/internal/glightbox/parser.go +++ b/internal/glightbox/parser.go @@ -4,6 +4,7 @@ import ( "bytes" "log/slog" "regexp" + "strings" "time" "github.com/yuin/goldmark/ast" @@ -60,16 +61,27 @@ func (p *GLightboxParser) Continue(node ast.Node, reader text.Reader, pc parser. 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, GLightboxImage{ URL: string(url), + Tags: tags, Caption: caption, }) diff --git a/static/input.css b/static/input.css index d766049..8080d13 100644 --- a/static/input.css +++ b/static/input.css @@ -331,22 +331,38 @@ a:hover { width: 50%; } +.grid-item-2x { + width: 100%; +} + @media (width >= 32rem) { .grid-item, .grid-sizer { width: 33%; } + + .grid-item-2x { + width: 66%; + } } @media (width >= 40rem) { .grid-item, .grid-sizer { width: 25%; } + + .grid-item-2x { + width: 50%; + } } @media (width >= 48rem) { .grid-item, .grid-sizer { width: 20%; } + + .grid-item-2x { + width: 40%; + } } .map-container .leaflet-container { diff --git a/views/pages/global-map.html b/views/pages/global-map.html index d595e07..9b67514 100644 --- a/views/pages/global-map.html +++ b/views/pages/global-map.html @@ -3,7 +3,7 @@ - {{ .L.GlobalMap.Header }} // SAYA TODAY + {{ .L.GlobalMap.Header }} // SAYA TODAY -- cgit v1.3.1+13