summaryrefslogtreecommitdiff
path: root/internal
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/b2/client.go121
-rw-r--r--internal/frontmatter/parser.go38
-rw-r--r--internal/lightgallery/block.go26
-rw-r--r--internal/lightgallery/extension.go28
-rw-r--r--internal/lightgallery/html_renderer.go137
-rw-r--r--internal/lightgallery/parser.go77
-rw-r--r--internal/tailwind/extension.go21
-rw-r--r--internal/tailwind/transformer.go72
8 files changed, 0 insertions, 520 deletions
diff --git a/internal/b2/client.go b/internal/b2/client.go
deleted file mode 100644
index f2b6cad..0000000
--- a/internal/b2/client.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package b2
-
-import (
- "context"
- "fmt"
- "strings"
- "time"
-
- "github.com/Backblaze/blazer/b2"
- "github.com/SayaAndy/saya-today-web/config"
- "github.com/SayaAndy/saya-today-web/internal/frontmatter"
-)
-
-type B2Client struct {
- prefix string
- bucket *b2.Bucket
- b2cl *b2.Client
-}
-
-func NewB2Client(cfg *config.B2Config) (*B2Client, error) {
- b2cl, err := b2.NewClient(context.Background(), cfg.KeyID, cfg.ApplicationKey)
- if err != nil {
- return nil, err
- }
-
- bucket, err := b2cl.Bucket(context.Background(), cfg.BucketName)
- if err != nil {
- return nil, err
- }
-
- return &B2Client{b2cl: b2cl, bucket: bucket, prefix: cfg.Prefix}, nil
-}
-
-type BlogPage struct {
- Link string
- Metadata *frontmatter.Metadata
-}
-
-func (c *B2Client) Scan() ([]*BlogPage, error) {
- filePaths := []*BlogPage{}
-
- iter := c.bucket.List(context.Background(), b2.ListPrefix(c.prefix))
-
- for iter.Next() {
- obj := iter.Object()
- if obj == nil {
- return nil, fmt.Errorf("failed to reference object in B2 bucket")
- }
-
- attrs, err := obj.Attrs(context.Background())
- if err != nil {
- return nil, fmt.Errorf("get attributes for object: %w", err)
- }
-
- if attrs.Status != b2.Uploaded {
- continue
- }
-
- if !strings.Contains(attrs.ContentType, "text/markdown") {
- continue
- }
-
- if _, ok := attrs.Info["title"]; !ok {
- continue
- }
-
- publishedTime, err := time.Parse(time.RFC3339, attrs.Info["published-time"])
- if err != nil {
- return nil, fmt.Errorf("failed to parse published time metadata field: %w", err)
- }
-
- linkParts := strings.Split(obj.Name(), ".")
-
- filePaths = append(filePaths, &BlogPage{
- Link: strings.Join(linkParts[:len(linkParts)-1], "."),
- Metadata: &frontmatter.Metadata{
- Title: attrs.Info["title"],
- ShortDescription: attrs.Info["short-description"],
- ActionDate: attrs.Info["action-date"],
- PublishedTime: publishedTime,
- Thumbnail: attrs.Info["thumbnail"],
- Tags: strings.Split(attrs.Info["tags"], ","),
- },
- })
- }
-
- if err := iter.Err(); err != nil {
- return nil, fmt.Errorf("iterate over B2 objects: %w", err)
- }
-
- return filePaths, nil
-}
-
-func (c *B2Client) ReadAll(path string) ([]byte, error) {
- obj := c.bucket.Object(c.prefix + path)
- if obj == nil {
- return nil, fmt.Errorf("failed to reference object in B2 bucket")
- }
- attrs, err := obj.Attrs(context.Background())
- if err != nil {
- return nil, fmt.Errorf("error getting attributes of an object: %w", err)
- }
-
- content := make([]byte, attrs.Size)
- reader := obj.NewReader(context.Background())
-
- if _, err = reader.Read(content); err != nil {
- return nil, fmt.Errorf("failed to read file content: %w", err)
- }
-
- return content, nil
-}
-
-func (c *B2Client) ReadFrontmatter(path string) (metadata *frontmatter.Metadata, markdown []byte, err error) {
- contentBytes, err := c.ReadAll(path)
- if err != nil {
- return nil, nil, fmt.Errorf("failed to read file for frontmatter parsing: %w", err)
- }
-
- return frontmatter.ParseFrontmatter(contentBytes)
-}
diff --git a/internal/frontmatter/parser.go b/internal/frontmatter/parser.go
deleted file mode 100644
index 1a521c0..0000000
--- a/internal/frontmatter/parser.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package frontmatter
-
-import (
- "fmt"
- "regexp"
- "time"
-
- "gopkg.in/yaml.v3"
-)
-
-type Metadata struct {
- Title string `yaml:"title"`
- ShortDescription string `yaml:"shortDescription"`
- ActionDate string `yaml:"actionDate"`
- PublishedTime time.Time `yaml:"publishedTime"`
- Thumbnail string `yaml:"thumbnail"`
- Tags []string `yaml:"tags"`
- Geolocation string `yaml:"geolocation"`
-}
-
-func ParseFrontmatter(content []byte) (metadata *Metadata, markdown []byte, err error) {
- frontmatterRegex := regexp.MustCompile(`^---\s*\r?\n([\s\S]*?)\r?\n---\s*\r?\n([\s\S]*)$`)
- matches := frontmatterRegex.FindSubmatch(content)
-
- if len(matches) != 3 {
- return nil, content, nil
- }
-
- yamlContent := matches[1]
- markdownContent := matches[2]
-
- metadata = &Metadata{}
- if err := yaml.Unmarshal([]byte(yamlContent), &metadata); err != nil {
- return nil, nil, fmt.Errorf("failed to parse YAML frontmatter: %w", err)
- }
-
- return metadata, markdownContent, nil
-}
diff --git a/internal/lightgallery/block.go b/internal/lightgallery/block.go
deleted file mode 100644
index dade2ea..0000000
--- a/internal/lightgallery/block.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package lightgallery
-
-import "github.com/yuin/goldmark/ast"
-
-// LightGalleryBlock represents a light gallery block in the AST
-type LightGalleryBlock struct {
- ast.BaseBlock
- Images []LightGalleryImage
-}
-
-type LightGalleryImage struct {
- URL string
- Caption string
-}
-
-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 bd73eac..0000000
--- a/internal/lightgallery/html_renderer.go
+++ /dev/null
@@ -1,137 +0,0 @@
-package lightgallery
-
-import (
- "fmt"
- "math/rand"
- "strings"
- "time"
-
- "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
-}
-
-func NewLightGalleryHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
- r := &LightGalleryHTMLRenderer{
- Config: html.NewConfig(),
- }
- 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(4)
-
- w.WriteString(fmt.Sprintf(`
-<div class="justify-content-center display-block m-2">
- <hr class="border-t-4 border-dotted border-main-dark mt-vmin0-8 mb-vmin0-8 w-p80 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-vmin0-8 mb-vmin0-8 w-p80 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], ".")
- imageNameParts := strings.Split(imageUrlWithoutExt, "-")
-
- dayDate, _ := time.Parse("20060102 150405", imageNameParts[len(imageNameParts)-2]+" "+imageNameParts[len(imageNameParts)-1])
- 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",
- sources: [{
- srcset: "https://f003.backblazeb2.com/file/sayana-photos/thumbnails/%s.webp",
- media: "(max-width: 800px)"
- }],
- thumb:
- "https://f003.backblazeb2.com/file/sayana-photos/thumbnails/%s.webp",
- subHtml: `+"`"+`<div class="flex flex-row light-gallery-captions">
- <p class="grow text-vmax1 text-left lh-0-9 font-spectral text-main-dark">%s</p>
- <p class="text-vmax1 text-right lh-0-9 font-spectral text-secondary">%s</p>
- </div>`+"`"+`
- }`, img.URL, img.URL, img.Caption, imageUrlWithoutExt, imageUrlWithoutExt, img.Caption, dayDate.Format("2006-01-02 15:04:05 -07:00")))
- }
-
- w.WriteString(fmt.Sprintf(`
-<script>
-function createLightLibrary%s() {
- const $lgContainer = document.getElementById('lg-%s');
- const inlineGallery = lightGallery($lgContainer, {
- 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: 160,
- thumbHeight: "10vmin",
- thumbMargin: 4
- });
-
- setTimeout(() => {
- inlineGallery.openGallery();
- }, 200);
-}
-
-document.addEventListener('DOMContentLoaded', createLightLibrary%s);
-
-let resizeTimer%s;
-window.addEventListener("resize", () => {
- clearTimeout(resizeTimer%s);
- resizeTimer%s = setTimeout(() => {
- const $lgContainer = document.getElementById('lg-%s');
- $lgContainer.innerHTML = "";
- createLightLibrary%s();
- }, 1000);
-});
-</script>`, galleryID, galleryID, strings.Join(dynamicElements, ","), galleryID, galleryID, galleryID, galleryID, galleryID, galleryID))
- }
-
- return ast.WalkContinue, nil
-}
-
-func escapeHTML(s string) string {
- s = strings.ReplaceAll(s, "&", "&amp;")
- s = strings.ReplaceAll(s, "<", "&lt;")
- s = strings.ReplaceAll(s, ">", "&gt;")
- s = strings.ReplaceAll(s, "\"", "&quot;")
- s = strings.ReplaceAll(s, "'", "&#39;")
- return s
-}
-
-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 0ce209c..0000000
--- a/internal/lightgallery/parser.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package lightgallery
-
-import (
- "bytes"
- "strings"
-
- "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
- }
-
- trimmed := bytes.TrimSpace(line)
- if !bytes.Equal(trimmed, []byte("{Gallery}")) {
- return nil, parser.NoChildren
- }
-
- return &LightGalleryBlock{}, 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.Close
- }
-
- trimmed := bytes.TrimSpace(line)
- if bytes.Equal(trimmed, []byte("{Gallery}")) {
- reader.AdvanceLine()
- return parser.Close
- }
-
- gallery := node.(*LightGalleryBlock)
- lineStr := string(trimmed)
-
- parts := strings.SplitN(lineStr, "|", 2)
- url := strings.TrimSpace(parts[0])
- caption := ""
-
- if len(parts) > 1 {
- caption = strings.TrimSpace(parts[1])
- }
-
- gallery.Images = append(gallery.Images, LightGalleryImage{
- URL: 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/internal/tailwind/extension.go b/internal/tailwind/extension.go
deleted file mode 100644
index c3254cc..0000000
--- a/internal/tailwind/extension.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package tailwind
-
-import (
- "github.com/yuin/goldmark"
- "github.com/yuin/goldmark/parser"
- "github.com/yuin/goldmark/util"
-)
-
-type TailwindExtension struct{}
-
-func NewTailwindExtension() goldmark.Extender {
- return &TailwindExtension{}
-}
-
-func (e *TailwindExtension) Extend(m goldmark.Markdown) {
- m.Parser().AddOptions(
- parser.WithASTTransformers(
- util.Prioritized(&TailwindTransformer{}, 500),
- ),
- )
-}
diff --git a/internal/tailwind/transformer.go b/internal/tailwind/transformer.go
deleted file mode 100644
index 51a33bc..0000000
--- a/internal/tailwind/transformer.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package tailwind
-
-import (
- "github.com/yuin/goldmark/ast"
- "github.com/yuin/goldmark/parser"
- "github.com/yuin/goldmark/text"
-)
-
-type TailwindTransformer struct{}
-
-func (t *TailwindTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
- ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
- if !entering {
- return ast.WalkContinue, nil
- }
-
- switch node := n.(type) {
- case *ast.Heading:
- classes := map[int]string{
- 1: "font-patua text-vmax2-5 font-bold text-main-dark mb-vmin1-2 ls-vmin0-04",
- 2: "font-spectral text-vmax2 font-bold text-main-dark mb-vmin0-8 ls-vmin0-04",
- 3: "font-spectral text-vmax1-5 font-medium text-main-dark mb-vmin0-6 ls-vmin0-04",
- 4: "font-spectral text-vmax1-2 font-medium text-main-medium mb-vmin0-4 ls-vmin0-04",
- 5: "font-spectral text-vmax1 font-medium text-main-medium mb-vmin0-4 italic ls-vmin0-04",
- 6: "font-spectral text-vmax1 font-medium text-secondary mb-vmin0-4",
- }
- if class, ok := classes[node.Level]; ok {
- node.SetAttribute([]byte("class"), []byte(class))
- }
-
- case *ast.Paragraph:
- node.SetAttribute([]byte("class"), []byte("text-vmax1 font-spectral lh-2 ls-vmin0-04 timl-vmax2 mb-vmin1-6"))
-
- case *ast.List:
- if node.IsOrdered() {
- node.SetAttribute([]byte("class"), []byte("list-decimal list-inside space-y-vmin0-8 mb-vmin1-6 pl-vmax2"))
- } else {
- node.SetAttribute([]byte("class"), []byte("list-disc list-inside space-y-vmin0-8 mb-vmin1-6 pl-vmax2"))
- }
-
- case *ast.ListItem:
- node.SetAttribute([]byte("class"), []byte("text-vmax1 font-spectral lh-2 ls-vmin0-04"))
-
- case *ast.Blockquote:
- node.SetAttribute([]byte("class"), []byte("border-l-vmin0-4 border-main-medium bg-background-dark p-vmin0-8 mb-vmin0-8 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-vmin0-8 rounded-lg overflow-x-auto mb-vmin1-6"))
-
- 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-vmin1-6"))
-
- case *ast.Emphasis:
- switch node.Level {
- case 1:
- node.SetAttribute([]byte("class"), []byte("italic"))
- case 2:
- node.SetAttribute([]byte("class"), []byte("font-bold"))
- case 3:
- node.SetAttribute([]byte("class"), []byte("italic font-bold"))
- }
- }
-
- return ast.WalkContinue, nil
- })
-}