diff options
Diffstat (limited to 'internal/lightgallery')
| -rw-r--r-- | internal/lightgallery/block.go | 31 | ||||
| -rw-r--r-- | internal/lightgallery/extension.go | 28 | ||||
| -rw-r--r-- | internal/lightgallery/html_renderer.go | 145 | ||||
| -rw-r--r-- | internal/lightgallery/parser.go | 88 |
4 files changed, 0 insertions, 292 deletions
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 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/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 -} |