diff --git a/Makefile b/Makefile index a319b2a..2e0ac29 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,27 @@ -# y2k — build & publish helpers (wasm .bnp workflow) +# y2k — build & publish helpers (CODELESS .bnp workflow, WO-WZ-021) # -# The theme compiles to a wasip1 reactor-mode wasm module packed into a .bnp -# artifact (`ninja plugin build`). The legacy .so path is retired (WO-WZ-015): -# the CMS is wasm-native and can no longer load .so plugins. Distribution is -# publish-to-registry -> InstallFromRegistry (hot-load, no restart). +# This theme is a CODELESS .bnp: pure declaration the host runs — blocks +# (blocks/blocks.yaml + .ninjatpl), page/system templates, template overrides, +# an email wrapper, master pages, presets, fonts and CSS in manifest.yaml. No +# Go, no templ, no plugin.wasm, no block/core dependency. `ninja plugin build` +# classifies the repo as codeless (no Go at the root) and packs the artifact +# with manifest.pb (codeless: true) and NO plugin.wasm. # # Usage: -# make build # compile wasm + pack y2k-.bnp -# make verify # validate the built .bnp (layout/abi/name/size) -# make archive-check # prove a clean `git archive HEAD` compiles to wasm +# make build # pack y2k-.bnp (codeless — no wasm) +# make verify # validate the built .bnp (loader-identical checks) +# make archive-check # prove a clean `git archive HEAD` still builds codeless # make publish # ninja plugin publish --bnp (to the active registry) -# make templ # regenerate templ Go files # make clean # remove build artefacts -.PHONY: build verify archive-check publish templ clean help +.PHONY: build verify archive-check publish clean help PLUGIN_NAME := y2k NINJA := ninja BNP := $(PLUGIN_NAME)-$(shell grep '^version' plugin.mod | sed 's/.*"\(.*\)"/\1/').bnp -# Compile to wasm and pack the .bnp (GOOS=wasip1 GOARCH=wasm, DESCRIBE probe, -# tar.zst of plugin.wasm + plugin.mod + manifest.pb + schemas/ + assets/). +# Pack the codeless .bnp (manifest.pb synthesized from plugin.mod + manifest.yaml +# + blocks/ + templates/; no wasm compile, no DESCRIBE probe). build: $(NINJA) plugin build --dir . @@ -28,12 +29,12 @@ build: verify: $(NINJA) plugin verify $(BNP) -# Prove a clean `git archive HEAD` (what publish ships) compiles to wasm. +# Prove a clean `git archive HEAD` (what publish ships) still packs codeless. archive-check: @T=$$(mktemp -d /tmp/archive-check-$(PLUGIN_NAME).XXXXXX) && \ trap 'rm -rf "$$T"' EXIT && \ git archive HEAD | tar -x -C "$$T" && \ - cd "$$T" && GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o "$$T/check.wasm" . && \ + cd "$$T" && $(NINJA) plugin build --dir . && \ echo "archive-check OK" # Publish the prebuilt .bnp to the active registry. @@ -41,19 +42,14 @@ archive-check: publish: build $(NINJA) plugin publish --bnp $(BNP) -# Regenerate templ Go files locally. -templ: - templ generate - # Remove build artefacts. clean: - rm -f $(PLUGIN_NAME)-*.bnp $(PLUGIN_NAME).so plugin.wasm + rm -f $(PLUGIN_NAME)-*.bnp plugin.wasm help: @echo "Targets:" - @echo " build Compile wasm + pack the .bnp" + @echo " build Pack the codeless .bnp (no wasm)" @echo " verify Validate the built .bnp (loader-identical checks)" - @echo " archive-check Prove a clean git archive HEAD compiles to wasm" + @echo " archive-check Prove a clean git archive HEAD packs codeless" @echo " publish Publish the .bnp to the active registry" - @echo " templ Regenerate templ Go files" @echo " clean Remove build artefacts" diff --git a/blocks/blocks.yaml b/blocks/blocks.yaml new file mode 100644 index 0000000..40f8232 --- /dev/null +++ b/blocks/blocks.yaml @@ -0,0 +1,66 @@ +# Y2K theme block definitions (codeless .bnp, WO-WZ-021). +# Keys are fully qualified (y2k:) because the codeless loader registers +# definitions verbatim — there is no PluginBlockRegistry prefixing in the +# codeless path (unlike the wasm/templ path). The qualified keys match the +# hardcoded data-block-key attributes and the master_pages.json references. +blocks: + - key: y2k:chrome_navbar + title: Chrome Navbar + description: Beveled chrome navigation bar with hover sparkle. + category: navigation + schema: chrome_navbar.schema.json + template: chrome_navbar.ninjatpl + - key: y2k:metaball_hero + title: Metaball Hero + description: SVG metaballs on a gradient mesh canvas with headline + CTA. + category: layout + schema: metaball_hero.schema.json + template: metaball_hero.ninjatpl + - key: y2k:waveform_player + title: Waveform Player + description: Soundcloud-style audio player with a canvas waveform. + category: content + schema: waveform_player.schema.json + template: waveform_player.ninjatpl + - key: y2k:marquee + title: Marquee Ticker + description: Scrolling text marquee with chrome edges; pauses on hover. + category: layout + schema: marquee.schema.json + template: marquee.ninjatpl + - key: y2k:tracklist + title: Tracklist + description: Tabular tracklist styled like a CD jewel case insert. + category: content + schema: tracklist.schema.json + template: tracklist.ninjatpl + - key: y2k:merch_card + title: Merch Card + description: Plastic-bevel product card with a corner sticker badge. + category: content + schema: merch_card.schema.json + template: merch_card.ninjatpl + - key: y2k:webring_badge + title: Webring Badge + description: Canonical 88x31 webring button row with prev/next/ring links. + category: navigation + schema: webring_badge.schema.json + template: webring_badge.ninjatpl + - key: y2k:glitter_divider + title: Glitter Divider + description: Animated sparkle horizontal rule. + category: layout + schema: glitter_divider.schema.json + template: glitter_divider.ninjatpl + - key: y2k:footer_chrome + title: Chrome Footer + description: Beveled chrome footer strip with optional webring and copyright. + category: layout + schema: footer_chrome.schema.json + template: footer_chrome.ninjatpl + - key: y2k:nft_gallery + title: NFT Gallery + description: Holographic-foil hover gallery for NFT items (presentational only). + category: content + schema: nft_gallery.schema.json + template: nft_gallery.ninjatpl diff --git a/blocks/chrome_navbar.ninjatpl b/blocks/chrome_navbar.ninjatpl new file mode 100644 index 0000000..89e7fbe --- /dev/null +++ b/blocks/chrome_navbar.ninjatpl @@ -0,0 +1,12 @@ + diff --git a/schemas/chrome_navbar.schema.json b/blocks/chrome_navbar.schema.json similarity index 100% rename from schemas/chrome_navbar.schema.json rename to blocks/chrome_navbar.schema.json diff --git a/blocks/footer_chrome.ninjatpl b/blocks/footer_chrome.ninjatpl new file mode 100644 index 0000000..3bb6d7d --- /dev/null +++ b/blocks/footer_chrome.ninjatpl @@ -0,0 +1,7 @@ +
+
+ {% if menuName %}{% endif %} + {% if showWebring != "no" and showWebring != false %}{% endif %} + {% if copyright %}{{ copyright }}{% endif %} +
+
diff --git a/schemas/footer_chrome.schema.json b/blocks/footer_chrome.schema.json similarity index 100% rename from schemas/footer_chrome.schema.json rename to blocks/footer_chrome.schema.json diff --git a/blocks/glitter_divider.ninjatpl b/blocks/glitter_divider.ninjatpl new file mode 100644 index 0000000..b1dc853 --- /dev/null +++ b/blocks/glitter_divider.ninjatpl @@ -0,0 +1,6 @@ + + diff --git a/schemas/glitter_divider.schema.json b/blocks/glitter_divider.schema.json similarity index 100% rename from schemas/glitter_divider.schema.json rename to blocks/glitter_divider.schema.json diff --git a/blocks/marquee.ninjatpl b/blocks/marquee.ninjatpl new file mode 100644 index 0000000..8847274 --- /dev/null +++ b/blocks/marquee.ninjatpl @@ -0,0 +1,5 @@ +
+
+ {% if items %}{% for item in items %}*{{ item }}{% endfor %}{% for item in items %}{% endfor %}{% else %}*now playing*new drop friday*subscribe to the zine{% endif %} +
+
diff --git a/schemas/marquee.schema.json b/blocks/marquee.schema.json similarity index 100% rename from schemas/marquee.schema.json rename to blocks/marquee.schema.json diff --git a/blocks/merch_card.ninjatpl b/blocks/merch_card.ninjatpl new file mode 100644 index 0000000..129e6f2 --- /dev/null +++ b/blocks/merch_card.ninjatpl @@ -0,0 +1,13 @@ +
+ {% if sticker %}{% if sticker == "sold-out" %}sold out{% else %}{{ sticker }}{% endif %}{% endif %} +
+ {% if image %}{{ title }}{% else %}
no image
{% endif %} +
+
+

{{ title|default:"untitled" }}

+
+ {{ price|default:"$--" }} + {% if buyHref %}buy{% endif %} +
+
+
diff --git a/schemas/merch_card.schema.json b/blocks/merch_card.schema.json similarity index 100% rename from schemas/merch_card.schema.json rename to blocks/merch_card.schema.json diff --git a/blocks/metaball_hero.ninjatpl b/blocks/metaball_hero.ninjatpl new file mode 100644 index 0000000..d75f7f5 --- /dev/null +++ b/blocks/metaball_hero.ninjatpl @@ -0,0 +1,32 @@ +
+ +
+
+

{{ headline|default:"new EP out now" }}

+ {% if sub %}

{{ sub }}

{% endif %} + {% if ctaLabel %}{{ ctaLabel }}{% endif %} +
+
+
diff --git a/schemas/metaball_hero.schema.json b/blocks/metaball_hero.schema.json similarity index 100% rename from schemas/metaball_hero.schema.json rename to blocks/metaball_hero.schema.json diff --git a/blocks/nft_gallery.ninjatpl b/blocks/nft_gallery.ninjatpl new file mode 100644 index 0000000..f3077b5 --- /dev/null +++ b/blocks/nft_gallery.ninjatpl @@ -0,0 +1,9 @@ +
+ {% if not items %}

No items yet.

{% else %}{% endif %} +
diff --git a/schemas/nft_gallery.schema.json b/blocks/nft_gallery.schema.json similarity index 100% rename from schemas/nft_gallery.schema.json rename to blocks/nft_gallery.schema.json diff --git a/blocks/tracklist.ninjatpl b/blocks/tracklist.ninjatpl new file mode 100644 index 0000000..b5432d5 --- /dev/null +++ b/blocks/tracklist.ninjatpl @@ -0,0 +1,8 @@ +
+
tracklist
+ {% if not tracks %}

No tracks yet.

{% else %}
    {% for track in tracks %}
  1. + {{ forloop.Counter }} + {% if track.url %}{{ track.title|default:"untitled track" }}{% else %}{{ track.title|default:"untitled track" }}{% endif %} + {{ track.duration|default:"--:--" }} +
  2. {% endfor %}
{% endif %} +
diff --git a/schemas/tracklist.schema.json b/blocks/tracklist.schema.json similarity index 100% rename from schemas/tracklist.schema.json rename to blocks/tracklist.schema.json diff --git a/blocks/waveform_player.ninjatpl b/blocks/waveform_player.ninjatpl new file mode 100644 index 0000000..ce2b81e --- /dev/null +++ b/blocks/waveform_player.ninjatpl @@ -0,0 +1,13 @@ +{% if audioUrl or trackTitle %}
+
+ {% if coverImage %}{{ trackTitle }}{% else %}{% endif %} +
+
+
+ {{ trackTitle|default:"untitled track" }} + {% if artist %}{{ artist }}{% endif %} +
+ + {% if audioUrl %}{% else %}

No audio source configured.

{% endif %} +
+
{% endif %} diff --git a/schemas/waveform_player.schema.json b/blocks/waveform_player.schema.json similarity index 100% rename from schemas/waveform_player.schema.json rename to blocks/waveform_player.schema.json diff --git a/blocks/webring_badge.ninjatpl b/blocks/webring_badge.ninjatpl new file mode 100644 index 0000000..3b92e98 --- /dev/null +++ b/blocks/webring_badge.ninjatpl @@ -0,0 +1,5 @@ + diff --git a/schemas/webring_badge.schema.json b/blocks/webring_badge.schema.json similarity index 100% rename from schemas/webring_badge.schema.json rename to blocks/webring_badge.schema.json diff --git a/button_override.go b/button_override.go deleted file mode 100644 index 01c07ea..0000000 --- a/button_override.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "bytes" - "context" -) - -// Y2KButtonBlock applies the plastic-bevel styling to the built-in button. -// Content: {text, url, variant, class} -func Y2KButtonBlock(ctx context.Context, content map[string]any) string { - data := Y2KButtonData{ - Text: getStringOr(content, "text", "button"), - URL: getStringOr(content, "url", "#"), - Variant: getStringOr(content, "variant", "primary"), - Class: getString(content, "class"), - } - var buf bytes.Buffer - _ = y2kButtonComponent(data).Render(ctx, &buf) - return buf.String() -} - -// Y2KButtonData is the typed shape for the templ component. -type Y2KButtonData struct { - Text string - URL string - Variant string - Class string -} diff --git a/button_override.templ b/button_override.templ deleted file mode 100644 index 04cc458..0000000 --- a/button_override.templ +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// y2kButtonComponent renders the plastic-bevel button. The 3D bevel + inset -// active state are owned by .y2k-button in css.go (UAT 13.9). -templ y2kButtonComponent(data Y2KButtonData) { - - { data.Text } - -} diff --git a/button_override_templ.go b/button_override_templ.go deleted file mode 100644 index 260b56b..0000000 --- a/button_override_templ.go +++ /dev/null @@ -1,99 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// y2kButtonComponent renders the plastic-bevel button. The 3D bevel + inset -// active state are owned by .y2k-button in css.go (UAT 13.9). -func y2kButtonComponent(data Y2KButtonData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var2 = []any{"y2k-button", data.Class} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(data.Text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 7, Col: 13} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/chrome_navbar.go b/chrome_navbar.go deleted file mode 100644 index 1dfb7c0..0000000 --- a/chrome_navbar.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// ChromeNavbarBlockMeta declares the y2k chrome navbar. -var ChromeNavbarBlockMeta = blocks.BlockMeta{ - Key: "chrome_navbar", - Title: "Chrome Navbar", - Description: "Beveled chrome navigation bar with hover sparkle.", - Source: "y2k", - Category: blocks.CategoryNavigation, -} - -// ChromeNavbarBlock renders the navbar. -// Content: {menuName, logoText, logoImage} -func ChromeNavbarBlock(ctx context.Context, content map[string]any) string { - data := ChromeNavbarData{ - MenuName: getStringOr(content, "menuName", "main"), - LogoText: getString(content, "logoText"), - LogoImage: getString(content, "logoImage"), - } - var buf bytes.Buffer - _ = chromeNavbarComponent(data).Render(ctx, &buf) - return buf.String() -} - -// ChromeNavbarData is the typed shape for the templ component. -type ChromeNavbarData struct { - MenuName string - LogoText string - LogoImage string -} diff --git a/chrome_navbar.templ b/chrome_navbar.templ deleted file mode 100644 index 4d1bf56..0000000 --- a/chrome_navbar.templ +++ /dev/null @@ -1,38 +0,0 @@ -package main - -// chromeNavbarComponent renders the beveled chrome navbar. The menu itself is -// hydrated client-side by the CMS; this block only owns the chrome shell and -// brand area. -templ chromeNavbarComponent(data ChromeNavbarData) { - -} - -func defaultLogoText(s string) string { - if s == "" { - return "y2k.fm" - } - return s -} diff --git a/chrome_navbar_templ.go b/chrome_navbar_templ.go deleted file mode 100644 index d63c0ed..0000000 --- a/chrome_navbar_templ.go +++ /dev/null @@ -1,169 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// chromeNavbarComponent renders the beveled chrome navbar. The menu itself is -// hydrated client-side by the CMS; this block only owns the chrome shell and -// brand area. -func chromeNavbarComponent(data ChromeNavbarData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func defaultLogoText(s string) string { - if s == "" { - return "y2k.fm" - } - return s -} - -var _ = templruntime.GeneratedTemplate diff --git a/css.go b/css.go deleted file mode 100644 index dcc4c37..0000000 --- a/css.go +++ /dev/null @@ -1,228 +0,0 @@ -package main - -// y2kInputCSS is appended to the host Tailwind input. It declares the chrome -// gradient stops, mesh anchors, bevel shadows, marquee/sparkle/metaball -// keyframes, and the utility classes those keyframes drive. Every colour is -// expressed through theme HSL custom properties (no hardcoded hex/rgb). -const y2kInputCSS = ` -/* === y2k theme — chrome/bevel/mesh tokens === */ -:root { - --chrome-1: 280 30% 95%; - --chrome-2: 200 40% 75%; - --chrome-3: 320 60% 60%; - --chrome-4: 280 40% 25%; - --mesh-a: 320 95% 58%; - --mesh-b: 185 90% 60%; - --mesh-c: 60 95% 70%; - --bevel-light: 0 0% 100%; - --bevel-dark: 280 60% 12%; -} -.dark { - --chrome-1: 280 30% 30%; - --chrome-2: 200 40% 45%; - --chrome-3: 320 60% 50%; - --chrome-4: 280 40% 10%; - --mesh-a: 320 100% 65%; - --mesh-b: 185 95% 55%; - --mesh-c: 60 100% 65%; - --bevel-light: 0 0% 100%; - --bevel-dark: 280 80% 4%; -} - -/* === keyframes === */ -@keyframes marquee-x { - from { transform: translate3d(0, 0, 0); } - to { transform: translate3d(-50%, 0, 0); } -} -@keyframes sparkle { - 0%, 100% { opacity: 0; transform: scale(0.5) rotate(0deg); } - 50% { opacity: 1; transform: scale(1) rotate(180deg); } -} -@keyframes metaball-morph { - 0%, 100% { d: path("M 50 100 a 50 50 0 1 1 100 0 a 50 50 0 1 1 -100 0"); } - 50% { d: path("M 40 95 a 60 55 0 1 1 120 5 a 55 60 0 1 1 -120 -5"); } -} - -/* === chrome surface utilities === */ -.y2k-chrome-bg { - background-image: - linear-gradient(180deg, - hsl(var(--chrome-1)) 0%, - hsl(var(--chrome-2)) 35%, - hsl(var(--chrome-3)) 70%, - hsl(var(--chrome-4)) 100%); -} -.y2k-mesh-bg { - background-image: - radial-gradient(at 20% 20%, hsl(var(--mesh-a) / 0.85) 0%, transparent 55%), - radial-gradient(at 80% 30%, hsl(var(--mesh-b) / 0.80) 0%, transparent 55%), - radial-gradient(at 50% 80%, hsl(var(--mesh-c) / 0.70) 0%, transparent 55%), - linear-gradient(135deg, hsl(var(--background)) 0%, hsl(var(--card)) 100%); -} -.y2k-bevel { - border: 2px solid hsl(var(--border)); - box-shadow: - inset 0 1px 0 hsl(var(--bevel-light) / 0.85), - inset 0 -2px 0 hsl(var(--bevel-dark) / 0.35), - 0 2px 6px hsl(var(--bevel-dark) / 0.30); -} -.y2k-bevel:active { - box-shadow: - inset 0 2px 4px hsl(var(--bevel-dark) / 0.45), - inset 0 -1px 0 hsl(var(--bevel-light) / 0.40); -} -.y2k-glow { - box-shadow: 0 0 24px hsl(var(--primary) / 0.45); -} - -/* === marquee === */ -.y2k-marquee { - overflow: hidden; - position: relative; - border-top: 2px solid hsl(var(--border)); - border-bottom: 2px solid hsl(var(--border)); -} -.y2k-marquee-track { - display: inline-flex; - gap: 3rem; - white-space: nowrap; - animation-name: marquee-x; - animation-timing-function: linear; - animation-iteration-count: infinite; -} -.y2k-marquee-track[data-speed="slow"] { animation-duration: 60s; } -.y2k-marquee-track[data-speed="medium"] { animation-duration: 30s; } -.y2k-marquee-track[data-speed="fast"] { animation-duration: 12s; } -.y2k-marquee:hover .y2k-marquee-track, -.y2k-marquee:focus-within .y2k-marquee-track { - animation-play-state: paused; -} - -/* === sparkle decoration === */ -.y2k-sparkle { - pointer-events: none; - animation: sparkle 1.6s ease-in-out infinite; -} - -/* === metaball morph === */ -.y2k-metaball { - animation: metaball-morph 6s ease-in-out infinite; -} - -/* === webring 88x31 badge === */ -.y2k-webring-badge { - display: inline-block; - width: 88px; - height: 31px; - line-height: 31px; - text-align: center; - font-size: 11px; - letter-spacing: 0.05em; - text-transform: uppercase; - border: 1px solid hsl(var(--border)); - background-image: linear-gradient(180deg, hsl(var(--chrome-1)) 0%, hsl(var(--chrome-3)) 100%); - color: hsl(var(--primaryForeground)); - text-decoration: none; - box-shadow: inset 0 1px 0 hsl(var(--bevel-light) / 0.6); -} - -/* === holographic foil for NFT gallery === */ -.y2k-foil { - position: relative; - isolation: isolate; -} -.y2k-foil::after { - content: ""; - position: absolute; - inset: 0; - pointer-events: none; - opacity: 0; - transition: opacity 220ms ease; - background-image: conic-gradient( - from 0deg, - hsl(var(--mesh-a) / 0.45), - hsl(var(--mesh-b) / 0.45), - hsl(var(--mesh-c) / 0.45), - hsl(var(--mesh-a) / 0.45) - ); - mix-blend-mode: color-dodge; - filter: hue-rotate(0deg); -} -.y2k-foil:hover::after, -.y2k-foil:focus-within::after { - opacity: 1; - filter: hue-rotate(45deg); -} - -/* === plastic button override === */ -.y2k-button { - display: inline-flex; - align-items: center; - gap: 0.5rem; - padding: 0.65rem 1.25rem; - font-weight: 600; - border: 2px solid hsl(var(--border)); - border-radius: 0.625rem; - background-image: linear-gradient(180deg, - hsl(var(--primary) / 0.95) 0%, - hsl(var(--primary)) 50%, - hsl(var(--primary) / 0.85) 100%); - color: hsl(var(--primaryForeground)); - box-shadow: - inset 0 1px 0 hsl(var(--bevel-light) / 0.7), - inset 0 -2px 0 hsl(var(--bevel-dark) / 0.3), - 0 2px 6px hsl(var(--bevel-dark) / 0.25); - transition: transform 90ms ease, box-shadow 90ms ease; -} -.y2k-button:hover { transform: translateY(-1px); } -.y2k-button:active { - transform: translateY(1px); - box-shadow: - inset 0 2px 4px hsl(var(--bevel-dark) / 0.45), - inset 0 -1px 0 hsl(var(--bevel-light) / 0.30); -} -.y2k-button:focus-visible { - outline: 2px solid hsl(var(--ring)); - outline-offset: 2px; -} - -/* === image chrome frame === */ -.y2k-image-frame { - border-radius: 0.625rem; - border: 2px solid hsl(var(--border)); - box-shadow: - inset 0 1px 0 hsl(var(--bevel-light) / 0.5), - 0 4px 14px hsl(var(--bevel-dark) / 0.35); -} - -/* === heading chrome stroke === */ -.y2k-heading { - font-family: var(--font-heading, "Stretch Pro", "VT323", "Courier New", monospace); - letter-spacing: 0.04em; - text-shadow: - 0 1px 0 hsl(var(--bevel-light) / 0.65), - 0 2px 0 hsl(var(--bevel-dark) / 0.35), - 0 6px 22px hsl(var(--primary) / 0.45); -} - -/* === text holographic link underline === */ -.y2k-text a { - background-image: linear-gradient(90deg, - hsl(var(--mesh-a)), - hsl(var(--mesh-b)), - hsl(var(--mesh-c))); - background-size: 100% 2px; - background-repeat: no-repeat; - background-position: 0 100%; - text-decoration: none; -} - -/* === reduced motion overrides === */ -@media (prefers-reduced-motion: reduce) { - .y2k-marquee-track, - .y2k-sparkle, - .y2k-metaball { - animation: none !important; - } -} -` diff --git a/email_wrapper.go b/email_wrapper.go deleted file mode 100644 index 2383d96..0000000 --- a/email_wrapper.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/templates" -) - -// Y2KEmailWrapper wraps body content in a Y2K-branded email shell: -// -// - Centred 600px chrome-bordered card on a near-black background. -// - Magenta-to-teal gradient header bar. -// - Inter Tight body (with system fallback). -// - Plain marquee pill footer. -// -// All colours are sourced from emailCtx.Colors when present, falling back to -// HSL token-equivalent hex values that match the chrome-dream dark preset. -func Y2KEmailWrapper(body string, emailCtx templates.EmailContext) string { - var buf bytes.Buffer - _ = y2kEmailTemplate(emailCtx, body).Render(context.Background(), &buf) - return buf.String() -} - -// Resolved palette per render — these helpers translate the preset HSL triples -// to email-safe hex via theme tokens, with fallbacks aligned to the -// chrome-dream dark preset. - -func y2kEmailBg(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Background != "" { - return emailCtx.Colors.Background - } - return "#0c0820" // chrome-dream dark background equivalent -} - -func y2kEmailCard(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Card != "" { - return emailCtx.Colors.Card - } - return "#150f2a" -} - -func y2kEmailFg(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Foreground != "" { - return emailCtx.Colors.Foreground - } - return "#f4e8fa" -} - -func y2kEmailMuted(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Muted != "" { - return emailCtx.Colors.Muted - } - return "#1f1740" -} - -func y2kEmailMutedFg(emailCtx templates.EmailContext) string { - if emailCtx.Colors.MutedForeground != "" { - return emailCtx.Colors.MutedForeground - } - return "#b9a8d3" -} - -func y2kEmailBorder(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Border != "" { - return emailCtx.Colors.Border - } - return "#4d2b6f" -} - -func y2kEmailPrimary(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Primary != "" { - return emailCtx.Colors.Primary - } - return "#ff4dd2" -} - -func y2kEmailSecondary(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Secondary != "" { - return emailCtx.Colors.Secondary - } - return "#4ddff0" -} diff --git a/email_wrapper.templ b/email_wrapper.templ deleted file mode 100644 index 7ebf5c9..0000000 --- a/email_wrapper.templ +++ /dev/null @@ -1,88 +0,0 @@ -package main - -import ( - "fmt" - - "git.dev.alexdunmow.com/block/core/templates" -) - -// y2kEmailTemplate is the Y2K-branded email shell. -templ y2kEmailTemplate(emailCtx templates.EmailContext, body string) { - - - - - - - - { emailCtx.SiteSettings.SiteName } - - - - if emailCtx.PreviewText != "" { -
{ emailCtx.PreviewText }
- } - - - - -
- - - - - - - - - - - - - - -
- - -} diff --git a/email_wrapper_templ.go b/email_wrapper_templ.go deleted file mode 100644 index 92cea7a..0000000 --- a/email_wrapper_templ.go +++ /dev/null @@ -1,251 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import ( - "fmt" - - "git.dev.alexdunmow.com/block/core/templates" -) - -// y2kEmailTemplate is the Y2K-branded email shell. -func y2kEmailTemplate(emailCtx templates.EmailContext, body string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteName) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 18, Col: 42} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if emailCtx.PreviewText != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.PreviewText) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 33, Col: 95} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if emailCtx.SiteSettings.SiteName != "" { - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteName) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 51, Col: 42} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "y2k.fm") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(body).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
* now playing * new drop friday * subscribe to the zine *
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if emailCtx.UnsubscribeURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "

unsubscribe

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/embed.go b/embed.go deleted file mode 100644 index d3d9676..0000000 --- a/embed.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -import ( - "embed" - "io/fs" - "net/http" - - "git.dev.alexdunmow.com/block/core/plugin" -) - -//go:embed assets/* -var assetsFS embed.FS - -//go:embed schemas/* -var schemasFS embed.FS - -//go:embed presets.json -var presetsData []byte - -//go:embed fonts.json -var fontsData []byte - -//go:embed plugin.mod -var pluginModBytes []byte - -// Assets returns the embedded assets filesystem rooted at assets/. -func Assets() fs.FS { - sub, _ := fs.Sub(assetsFS, "assets") - return sub -} - -// Schemas returns the embedded schemas filesystem rooted at schemas/. -func Schemas() fs.FS { - sub, _ := fs.Sub(schemasFS, "schemas") - return sub -} - -// AssetsHandler serves embedded asset files at /templates/y2k/... -func AssetsHandler() http.Handler { - return http.FileServer(http.FS(Assets())) -} - -// ThemePresets returns the raw presets.json bytes. -func ThemePresets() []byte { return presetsData } - -// BundledFonts returns the raw fonts.json bytes. -func BundledFonts() []byte { return fontsData } - -// ThemeCSSManifest returns the theme's CSS manifest. Y2K injects keyframes -// (marquee-x, sparkle, metaball-morph) and chrome/bevel utility classes that -// Tailwind alone cannot express, plus CSS custom properties (--chrome-1..4, -// --mesh-a/b/c, --bevel-light/dark) into the host Tailwind input. -func ThemeCSSManifest() *plugin.CSSManifest { - return &plugin.CSSManifest{ - InputCSSAppend: y2kInputCSS, - } -} diff --git a/footer_chrome.go b/footer_chrome.go deleted file mode 100644 index 3405996..0000000 --- a/footer_chrome.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// FooterChromeBlockMeta declares the chrome footer block. -var FooterChromeBlockMeta = blocks.BlockMeta{ - Key: "footer_chrome", - Title: "Chrome Footer", - Description: "Beveled chrome footer strip with optional webring and copyright.", - Source: "y2k", - Category: blocks.CategoryLayout, -} - -// FooterChromeBlock renders the footer. -// Content: {menuName, showWebring, copyright} -func FooterChromeBlock(ctx context.Context, content map[string]any) string { - // showWebring is stored as either bool (legacy/master-page seed) or string - // ("yes" | "no") from the schema's select editor. - show := true - switch v := content["showWebring"].(type) { - case bool: - show = v - case string: - show = v != "no" - } - data := FooterChromeData{ - MenuName: getString(content, "menuName"), - ShowWebring: show, - Copyright: getString(content, "copyright"), - } - var buf bytes.Buffer - _ = footerChromeComponent(data).Render(ctx, &buf) - return buf.String() -} - -// FooterChromeData is the typed shape for the templ component. -type FooterChromeData struct { - MenuName string - ShowWebring bool - Copyright string -} diff --git a/footer_chrome.templ b/footer_chrome.templ deleted file mode 100644 index a474c93..0000000 --- a/footer_chrome.templ +++ /dev/null @@ -1,24 +0,0 @@ -package main - -// footerChromeComponent renders the bottom chrome strip with optional webring. -templ footerChromeComponent(data FooterChromeData) { -
-
- if data.MenuName != "" { - - } - if data.ShowWebring { -
- prev - ring - next -
- } - if data.Copyright != "" { - { data.Copyright } - } -
-
-} diff --git a/footer_chrome_templ.go b/footer_chrome_templ.go deleted file mode 100644 index d240936..0000000 --- a/footer_chrome_templ.go +++ /dev/null @@ -1,102 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// footerChromeComponent renders the bottom chrome strip with optional webring. -func footerChromeComponent(data FooterChromeData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.MenuName != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if data.ShowWebring { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if data.Copyright != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.Copyright) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_chrome.templ`, Line: 20, Col: 64} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/glitter_divider.go b/glitter_divider.go deleted file mode 100644 index e2b2383..0000000 --- a/glitter_divider.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// GlitterDividerBlockMeta declares the animated sparkle divider. -var GlitterDividerBlockMeta = blocks.BlockMeta{ - Key: "glitter_divider", - Title: "Glitter Divider", - Description: "Animated sparkle horizontal rule.", - Source: "y2k", - Category: blocks.CategoryLayout, -} - -// GlitterDividerBlock renders the divider. -// Content: {variant} -func GlitterDividerBlock(ctx context.Context, content map[string]any) string { - variant := getStringOr(content, "variant", "sparkle") - var buf bytes.Buffer - _ = glitterDividerComponent(variant).Render(ctx, &buf) - return buf.String() -} diff --git a/glitter_divider.templ b/glitter_divider.templ deleted file mode 100644 index 3e43029..0000000 --- a/glitter_divider.templ +++ /dev/null @@ -1,25 +0,0 @@ -package main - -// glitterDividerComponent renders a sparkle hr. The glyph used per variant is -// inert (decorative) — the divider itself carries role="separator". -templ glitterDividerComponent(variant string) { - - -} - -func glitterGlyph(v string) string { - switch v { - case "stars": - return "*" - case "hearts": - return "<3" - case "chrome": - return "~" - default: - return "*" - } -} diff --git a/glitter_divider_templ.go b/glitter_divider_templ.go deleted file mode 100644 index b1b90f7..0000000 --- a/glitter_divider_templ.go +++ /dev/null @@ -1,107 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// glitterDividerComponent renders a sparkle hr. The glyph used per variant is -// inert (decorative) — the divider itself carries role="separator". -func glitterDividerComponent(variant string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(glitterGlyph(variant)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `glitter_divider.templ`, Line: 8, Col: 51} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(glitterGlyph(variant)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `glitter_divider.templ`, Line: 9, Col: 82} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(glitterGlyph(variant)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `glitter_divider.templ`, Line: 10, Col: 82} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func glitterGlyph(v string) string { - switch v { - case "stars": - return "*" - case "hearts": - return "<3" - case "chrome": - return "~" - default: - return "*" - } -} - -var _ = templruntime.GeneratedTemplate diff --git a/go.mod b/go.mod deleted file mode 100644 index ae84f19..0000000 --- a/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module git.dev.alexdunmow.com/block/themes/y2k - -go 1.26.4 - -require ( - git.dev.alexdunmow.com/block/core v0.15.2 - github.com/a-h/templ v0.3.1020 -) - -require ( - connectrpc.com/connect v1.20.0 // indirect - github.com/BurntSushi/toml v1.6.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.9.2 // indirect - golang.org/x/mod v0.34.0 // indirect - golang.org/x/text v0.36.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index ebd3d11..0000000 --- a/go.sum +++ /dev/null @@ -1,46 +0,0 @@ -connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ= -connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4= -git.dev.alexdunmow.com/block/core v0.15.2 h1:qTjJxa1pClxwehkdTxXiJDpHQLr5DoXBUCa40QRO0L8= -git.dev.alexdunmow.com/block/core v0.15.2/go.mod h1:A+mgA9oeWoPhXruv4Mjpywwl2A9B5I3cKzlJjalBdlE= -github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= -github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw= -github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= -github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tetratelabs/wazero v1.12.0 h1:DuWcpNu/FzgEXgGBDp8J1Spc+CWOvvtvVyjKlaZopYU= -github.com/tetratelabs/wazero v1.12.0/go.mod h1:LvKtzl2RqO4gyF27BiXU+nKAjcV8f38U+kP/q2vgxh0= -golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= -golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/heading_override.go b/heading_override.go deleted file mode 100644 index 87348e0..0000000 --- a/heading_override.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "bytes" - "context" - "strconv" -) - -// Y2KHeadingBlock applies the chrome-stroke heading styling to the built-in -// heading block when the y2k theme is active. -// Content: {text, level, textClass} -func Y2KHeadingBlock(ctx context.Context, content map[string]any) string { - text := getString(content, "text") - textClass := getString(content, "textClass") - level := parseHeadingLevel(content) - var buf bytes.Buffer - _ = y2kHeadingComponent(level, text, textClass).Render(ctx, &buf) - return buf.String() -} - -// parseHeadingLevel reads "level" from the content map, accepting float64 -// (JSON), int (Go), or numeric strings. Returns 2 as a safe default. -func parseHeadingLevel(content map[string]any) int { - if v, ok := content["level"].(float64); ok { - l := int(v) - if l >= 1 && l <= 6 { - return l - } - } - if v, ok := content["level"].(int); ok && v >= 1 && v <= 6 { - return v - } - if v, ok := content["level"].(string); ok { - if l, err := strconv.Atoi(v); err == nil && l >= 1 && l <= 6 { - return l - } - } - return 2 -} diff --git a/heading_override.templ b/heading_override.templ deleted file mode 100644 index af47451..0000000 --- a/heading_override.templ +++ /dev/null @@ -1,41 +0,0 @@ -package main - -// y2kHeadingBaseClass returns the per-level Tailwind sizing classes. -func y2kHeadingBaseClass(level int) string { - switch level { - case 1: - return "text-5xl md:text-6xl" - case 2: - return "text-3xl md:text-4xl" - case 3: - return "text-2xl" - case 4: - return "text-xl" - case 5: - return "text-lg" - case 6: - return "text-base" - default: - return "text-3xl md:text-4xl" - } -} - -// y2kHeadingComponent renders a heading with chrome stroke + drop shadow. -templ y2kHeadingComponent(level int, text, textClass string) { - switch level { - case 1: -

{ text }

- case 2: -

{ text }

- case 3: -

{ text }

- case 4: -

{ text }

- case 5: -
{ text }
- case 6: -
{ text }
- default: -

{ text }

- } -} diff --git a/heading_override_templ.go b/heading_override_templ.go deleted file mode 100644 index 4956f5e..0000000 --- a/heading_override_templ.go +++ /dev/null @@ -1,311 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// y2kHeadingBaseClass returns the per-level Tailwind sizing classes. -func y2kHeadingBaseClass(level int) string { - switch level { - case 1: - return "text-5xl md:text-6xl" - case 2: - return "text-3xl md:text-4xl" - case 3: - return "text-2xl" - case 4: - return "text-xl" - case 5: - return "text-lg" - case 6: - return "text-base" - default: - return "text-3xl md:text-4xl" - } -} - -// y2kHeadingComponent renders a heading with chrome stroke + drop shadow. -func y2kHeadingComponent(level int, text, textClass string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - switch level { - case 1: - var templ_7745c5c3_Var2 = []any{"y2k-heading font-bold text-foreground", y2kHeadingBaseClass(1), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 27, Col: 98} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case 2: - var templ_7745c5c3_Var5 = []any{"y2k-heading font-bold text-foreground", y2kHeadingBaseClass(2), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 29, Col: 98} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case 3: - var templ_7745c5c3_Var8 = []any{"y2k-heading font-semibold text-foreground", y2kHeadingBaseClass(3), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var10 string - templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 31, Col: 102} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case 4: - var templ_7745c5c3_Var11 = []any{"y2k-heading font-semibold text-foreground", y2kHeadingBaseClass(4), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var11...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var13 string - templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 33, Col: 102} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case 5: - var templ_7745c5c3_Var14 = []any{"y2k-heading font-semibold text-foreground", y2kHeadingBaseClass(5), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var16 string - templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 35, Col: 102} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case 6: - var templ_7745c5c3_Var17 = []any{"y2k-heading font-semibold text-foreground", y2kHeadingBaseClass(6), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var17...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var19 string - templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 37, Col: 102} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - default: - var templ_7745c5c3_Var20 = []any{"y2k-heading font-bold text-foreground", y2kHeadingBaseClass(2), textClass} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var22 string - templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 39, Col: 98} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/helpers.go b/helpers.go deleted file mode 100644 index 600154d..0000000 --- a/helpers.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -// getString safely extracts a string value from a content map. -func getString(content map[string]any, key string) string { - if v, ok := content[key].(string); ok { - return v - } - return "" -} - -// getStringOr returns the string value for key or the default when missing/empty. -func getStringOr(content map[string]any, key, dflt string) string { - if v := getString(content, key); v != "" { - return v - } - return dflt -} - - -// getStringSlice extracts a []string from a JSON array of strings. -func getStringSlice(content map[string]any, key string) []string { - raw, ok := content[key].([]any) - if !ok { - return nil - } - out := make([]string, 0, len(raw)) - for _, item := range raw { - if s, ok := item.(string); ok { - out = append(out, s) - } - } - return out -} - -// getSlice extracts a []map[string]any from a JSON array of objects. -func getSlice(content map[string]any, key string) []map[string]any { - raw, ok := content[key].([]any) - if !ok { - return nil - } - out := make([]map[string]any, 0, len(raw)) - for _, item := range raw { - if m, ok := item.(map[string]any); ok { - out = append(out, m) - } - } - return out -} diff --git a/image_override.go b/image_override.go deleted file mode 100644 index 3e703a4..0000000 --- a/image_override.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "bytes" - "context" -) - -// Y2KImageBlock applies the chrome-bordered image frame to the built-in -// image block. -// Content: {url, alt, caption, class} -func Y2KImageBlock(ctx context.Context, content map[string]any) string { - data := Y2KImageData{ - URL: getString(content, "url"), - Alt: getString(content, "alt"), - Caption: getString(content, "caption"), - Class: getString(content, "class"), - } - if data.URL == "" { - return "" - } - var buf bytes.Buffer - _ = y2kImageComponent(data).Render(ctx, &buf) - return buf.String() -} - -// Y2KImageData is the typed shape for the templ component. -type Y2KImageData struct { - URL string - Alt string - Caption string - Class string -} diff --git a/image_override.templ b/image_override.templ deleted file mode 100644 index 59cde06..0000000 --- a/image_override.templ +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// y2kImageComponent wraps an image in the chrome y2k-image-frame. -templ y2kImageComponent(data Y2KImageData) { -
- { - if data.Caption != "" { -
{ data.Caption }
- } -
-} diff --git a/image_override_templ.go b/image_override_templ.go deleted file mode 100644 index 9137557..0000000 --- a/image_override_templ.go +++ /dev/null @@ -1,108 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// y2kImageComponent wraps an image in the chrome y2k-image-frame. -func y2kImageComponent(data Y2KImageData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var2 = []any{"my-4", data.Class} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
\"") ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Caption != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(data.Caption) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `image_override.templ`, Line: 8, Col: 84} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/main.go b/main.go deleted file mode 100644 index 5d965aa..0000000 --- a/main.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build wasip1 - -// Package main compiles the y2k theme to a wasip1 reactor-mode wasm guest -// (WO-WZ-015). The .so build path is retired; `ninja plugin build` produces the -// .bnp artifact the registry serves. -// -// Reactor mode: the host runs `_initialize` once per pooled instance, which -// runs this init func (hence wasmguest.Serve) before any bn_invoke. Serve is -// non-blocking; all theme work then arrives over the ABI hook calls. main is -// never called. -package main - -import "git.dev.alexdunmow.com/block/core/plugin/wasmguest" - -func init() { wasmguest.Serve(Registration) } - -func main() {} // never called — reactor mode diff --git a/manifest.yaml b/manifest.yaml new file mode 100644 index 0000000..36b6b6e --- /dev/null +++ b/manifest.yaml @@ -0,0 +1,264 @@ +# Y2K theme — codeless .bnp manifest (WO-WZ-021 Phase B). +# Synthesized into manifest.pb by `ninja plugin build` (no plugin.wasm). +theme_presets: presets.json +bundled_fonts: fonts.json +master_pages: master_pages.json + +system_templates: + - key: y2k + title: Y2K + description: "Liquid-chrome Y2K revival theme for indie musicians, zines, and merch shops." + +page_templates: + - system: y2k + key: default + title: Default + description: "Chrome navbar + content + footer." + slots: [header, main, footer] + - system: y2k + key: landing + title: Landing + description: "Hero metaball + marquee + CTAs." + slots: [hero, marquee, main, cta, footer] + - system: y2k + key: article + title: Article / Zine Page + description: "Narrow column with sidebar tracklist." + slots: [header, main, aside, footer] + - system: y2k + key: full-width + title: Full Width + description: "Edge-to-edge gradient mesh canvas." + slots: [header, main, footer] + +template_overrides: + - { template: y2k, block: heading } + - { template: y2k, block: text } + - { template: y2k, block: button } + - { template: y2k, block: image } + +email_wrappers: + - y2k + +css: + input_css_append: | + /* === y2k theme — chrome/bevel/mesh tokens === */ + :root { + --chrome-1: 280 30% 95%; + --chrome-2: 200 40% 75%; + --chrome-3: 320 60% 60%; + --chrome-4: 280 40% 25%; + --mesh-a: 320 95% 58%; + --mesh-b: 185 90% 60%; + --mesh-c: 60 95% 70%; + --bevel-light: 0 0% 100%; + --bevel-dark: 280 60% 12%; + } + .dark { + --chrome-1: 280 30% 30%; + --chrome-2: 200 40% 45%; + --chrome-3: 320 60% 50%; + --chrome-4: 280 40% 10%; + --mesh-a: 320 100% 65%; + --mesh-b: 185 95% 55%; + --mesh-c: 60 100% 65%; + --bevel-light: 0 0% 100%; + --bevel-dark: 280 80% 4%; + } + + /* === keyframes === */ + @keyframes marquee-x { + from { transform: translate3d(0, 0, 0); } + to { transform: translate3d(-50%, 0, 0); } + } + @keyframes sparkle { + 0%, 100% { opacity: 0; transform: scale(0.5) rotate(0deg); } + 50% { opacity: 1; transform: scale(1) rotate(180deg); } + } + @keyframes metaball-morph { + 0%, 100% { d: path("M 50 100 a 50 50 0 1 1 100 0 a 50 50 0 1 1 -100 0"); } + 50% { d: path("M 40 95 a 60 55 0 1 1 120 5 a 55 60 0 1 1 -120 -5"); } + } + + /* === chrome surface utilities === */ + .y2k-chrome-bg { + background-image: + linear-gradient(180deg, + hsl(var(--chrome-1)) 0%, + hsl(var(--chrome-2)) 35%, + hsl(var(--chrome-3)) 70%, + hsl(var(--chrome-4)) 100%); + } + .y2k-mesh-bg { + background-image: + radial-gradient(at 20% 20%, hsl(var(--mesh-a) / 0.85) 0%, transparent 55%), + radial-gradient(at 80% 30%, hsl(var(--mesh-b) / 0.80) 0%, transparent 55%), + radial-gradient(at 50% 80%, hsl(var(--mesh-c) / 0.70) 0%, transparent 55%), + linear-gradient(135deg, hsl(var(--background)) 0%, hsl(var(--card)) 100%); + } + .y2k-bevel { + border: 2px solid hsl(var(--border)); + box-shadow: + inset 0 1px 0 hsl(var(--bevel-light) / 0.85), + inset 0 -2px 0 hsl(var(--bevel-dark) / 0.35), + 0 2px 6px hsl(var(--bevel-dark) / 0.30); + } + .y2k-bevel:active { + box-shadow: + inset 0 2px 4px hsl(var(--bevel-dark) / 0.45), + inset 0 -1px 0 hsl(var(--bevel-light) / 0.40); + } + .y2k-glow { + box-shadow: 0 0 24px hsl(var(--primary) / 0.45); + } + + /* === marquee === */ + .y2k-marquee { + overflow: hidden; + position: relative; + border-top: 2px solid hsl(var(--border)); + border-bottom: 2px solid hsl(var(--border)); + } + .y2k-marquee-track { + display: inline-flex; + gap: 3rem; + white-space: nowrap; + animation-name: marquee-x; + animation-timing-function: linear; + animation-iteration-count: infinite; + } + .y2k-marquee-track[data-speed="slow"] { animation-duration: 60s; } + .y2k-marquee-track[data-speed="medium"] { animation-duration: 30s; } + .y2k-marquee-track[data-speed="fast"] { animation-duration: 12s; } + .y2k-marquee:hover .y2k-marquee-track, + .y2k-marquee:focus-within .y2k-marquee-track { + animation-play-state: paused; + } + + /* === sparkle decoration === */ + .y2k-sparkle { + pointer-events: none; + animation: sparkle 1.6s ease-in-out infinite; + } + + /* === metaball morph === */ + .y2k-metaball { + animation: metaball-morph 6s ease-in-out infinite; + } + + /* === webring 88x31 badge === */ + .y2k-webring-badge { + display: inline-block; + width: 88px; + height: 31px; + line-height: 31px; + text-align: center; + font-size: 11px; + letter-spacing: 0.05em; + text-transform: uppercase; + border: 1px solid hsl(var(--border)); + background-image: linear-gradient(180deg, hsl(var(--chrome-1)) 0%, hsl(var(--chrome-3)) 100%); + color: hsl(var(--primaryForeground)); + text-decoration: none; + box-shadow: inset 0 1px 0 hsl(var(--bevel-light) / 0.6); + } + + /* === holographic foil for NFT gallery === */ + .y2k-foil { + position: relative; + isolation: isolate; + } + .y2k-foil::after { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + opacity: 0; + transition: opacity 220ms ease; + background-image: conic-gradient( + from 0deg, + hsl(var(--mesh-a) / 0.45), + hsl(var(--mesh-b) / 0.45), + hsl(var(--mesh-c) / 0.45), + hsl(var(--mesh-a) / 0.45) + ); + mix-blend-mode: color-dodge; + filter: hue-rotate(0deg); + } + .y2k-foil:hover::after, + .y2k-foil:focus-within::after { + opacity: 1; + filter: hue-rotate(45deg); + } + + /* === plastic button override === */ + .y2k-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.65rem 1.25rem; + font-weight: 600; + border: 2px solid hsl(var(--border)); + border-radius: 0.625rem; + background-image: linear-gradient(180deg, + hsl(var(--primary) / 0.95) 0%, + hsl(var(--primary)) 50%, + hsl(var(--primary) / 0.85) 100%); + color: hsl(var(--primaryForeground)); + box-shadow: + inset 0 1px 0 hsl(var(--bevel-light) / 0.7), + inset 0 -2px 0 hsl(var(--bevel-dark) / 0.3), + 0 2px 6px hsl(var(--bevel-dark) / 0.25); + transition: transform 90ms ease, box-shadow 90ms ease; + } + .y2k-button:hover { transform: translateY(-1px); } + .y2k-button:active { + transform: translateY(1px); + box-shadow: + inset 0 2px 4px hsl(var(--bevel-dark) / 0.45), + inset 0 -1px 0 hsl(var(--bevel-light) / 0.30); + } + .y2k-button:focus-visible { + outline: 2px solid hsl(var(--ring)); + outline-offset: 2px; + } + + /* === image chrome frame === */ + .y2k-image-frame { + border-radius: 0.625rem; + border: 2px solid hsl(var(--border)); + box-shadow: + inset 0 1px 0 hsl(var(--bevel-light) / 0.5), + 0 4px 14px hsl(var(--bevel-dark) / 0.35); + } + + /* === heading chrome stroke === */ + .y2k-heading { + font-family: var(--font-heading, "Stretch Pro", "VT323", "Courier New", monospace); + letter-spacing: 0.04em; + text-shadow: + 0 1px 0 hsl(var(--bevel-light) / 0.65), + 0 2px 0 hsl(var(--bevel-dark) / 0.35), + 0 6px 22px hsl(var(--primary) / 0.45); + } + + /* === text holographic link underline === */ + .y2k-text a { + background-image: linear-gradient(90deg, + hsl(var(--mesh-a)), + hsl(var(--mesh-b)), + hsl(var(--mesh-c))); + background-size: 100% 2px; + background-repeat: no-repeat; + background-position: 0 100%; + text-decoration: none; + } + + /* === reduced motion overrides === */ + @media (prefers-reduced-motion: reduce) { + .y2k-marquee-track, + .y2k-sparkle, + .y2k-metaball { + animation: none !important; + } + } diff --git a/marquee.go b/marquee.go deleted file mode 100644 index cb0a1e9..0000000 --- a/marquee.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// MarqueeBlockMeta declares the marquee ticker block. -var MarqueeBlockMeta = blocks.BlockMeta{ - Key: "marquee", - Title: "Marquee Ticker", - Description: "Scrolling text marquee with chrome edges; pauses on hover.", - Source: "y2k", - Category: blocks.CategoryLayout, -} - -// MarqueeBlock renders the marquee. -// Content: {items[], speed, direction} -func MarqueeBlock(ctx context.Context, content map[string]any) string { - data := MarqueeData{ - Items: getStringSlice(content, "items"), - Speed: getStringOr(content, "speed", "medium"), - Direction: getStringOr(content, "direction", "left"), - } - if len(data.Items) == 0 { - data.Items = []string{"now playing", "new drop friday", "subscribe to the zine"} - } - var buf bytes.Buffer - _ = marqueeComponent(data).Render(ctx, &buf) - return buf.String() -} - -// MarqueeData is the typed shape for the templ component. -type MarqueeData struct { - Items []string - Speed string - Direction string -} diff --git a/marquee.templ b/marquee.templ deleted file mode 100644 index e96ce51..0000000 --- a/marquee.templ +++ /dev/null @@ -1,29 +0,0 @@ -package main - -// marqueeComponent renders a horizontally scrolling marquee. The track is -// duplicated so the CSS keyframes can loop seamlessly. Speed is keyed off the -// data-speed attribute which the y2k stylesheet maps to a duration. -templ marqueeComponent(data MarqueeData) { -
-
- for _, item := range data.Items { - - * - { item } - - } - for _, item := range data.Items { - - } -
-
-} diff --git a/marquee_templ.go b/marquee_templ.go deleted file mode 100644 index 2717c73..0000000 --- a/marquee_templ.go +++ /dev/null @@ -1,111 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// marqueeComponent renders a horizontally scrolling marquee. The track is -// duplicated so the CSS keyframes can loop seamlessly. Speed is keyed off the -// data-speed attribute which the y2k stylesheet maps to a duration. -func marqueeComponent(data MarqueeData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - for _, item := range data.Items { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "* ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(item) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `marquee.templ`, Line: 18, Col: 11} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - for _, item := range data.Items { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "* ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(item) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `marquee.templ`, Line: 24, Col: 11} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/master_pages.json b/master_pages.json new file mode 100644 index 0000000..3a8f761 --- /dev/null +++ b/master_pages.json @@ -0,0 +1,24 @@ +[ + { + "key": "y2k:default-master", + "title": "Y2K Default Master", + "page_templates": ["default", "article"], + "blocks": [ + { "block_key": "y2k:chrome_navbar", "title": "Chrome Navbar", "content": { "menuName": "main", "logoText": "y2k.fm" }, "slot": "header", "sort_order": 0 }, + { "block_key": "y2k:marquee", "title": "Top Marquee", "content": { "items": ["new drop friday", "listen on bandcamp", "subscribe to the zine"], "speed": "medium" }, "slot": "header", "sort_order": 1 }, + { "block_key": "slot", "title": "Main Slot", "content": { "slotName": "main" }, "slot": "main", "sort_order": 0 }, + { "block_key": "y2k:footer_chrome", "title": "Chrome Footer", "content": { "showWebring": true, "copyright": "(c) y2k.fm" }, "slot": "footer", "sort_order": 0 } + ] + }, + { + "key": "y2k:landing-master", + "title": "Y2K Landing Master", + "page_templates": ["landing", "full-width"], + "blocks": [ + { "block_key": "y2k:metaball_hero", "title": "Metaball Hero", "content": { "headline": "new EP out now", "sub": "liquid chrome dreams", "ctaLabel": "listen" }, "slot": "hero", "sort_order": 0 }, + { "block_key": "y2k:marquee", "title": "Marquee", "content": { "items": ["* new * new * new"], "speed": "fast" }, "slot": "marquee", "sort_order": 0 }, + { "block_key": "slot", "title": "Main Slot", "content": { "slotName": "main" }, "slot": "main", "sort_order": 0 }, + { "block_key": "y2k:footer_chrome", "title": "Chrome Footer", "content": { "showWebring": true }, "slot": "footer", "sort_order": 0 } + ] + } +] diff --git a/merch_card.go b/merch_card.go deleted file mode 100644 index d3eb362..0000000 --- a/merch_card.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// MerchCardBlockMeta declares the merch product card block. -var MerchCardBlockMeta = blocks.BlockMeta{ - Key: "merch_card", - Title: "Merch Card", - Description: "Plastic-bevel product card with a corner sticker badge.", - Source: "y2k", - Category: blocks.CategoryContent, -} - -// MerchCardBlock renders the merch card. -// Content: {title, price, image, buyHref, sticker} -func MerchCardBlock(ctx context.Context, content map[string]any) string { - data := MerchCardData{ - Title: getString(content, "title"), - Price: getString(content, "price"), - Image: getString(content, "image"), - BuyHref: getString(content, "buyHref"), - Sticker: getString(content, "sticker"), - } - var buf bytes.Buffer - _ = merchCardComponent(data).Render(ctx, &buf) - return buf.String() -} - -// MerchCardData is the typed shape for the templ component. -type MerchCardData struct { - Title string - Price string - Image string - BuyHref string - Sticker string -} diff --git a/merch_card.templ b/merch_card.templ deleted file mode 100644 index 31563f0..0000000 --- a/merch_card.templ +++ /dev/null @@ -1,52 +0,0 @@ -package main - -// merchCardComponent renders a single merch card. The card class is applied -// to a grid container managed by the page; this block stays self-contained. -templ merchCardComponent(data MerchCardData) { -
- if data.Sticker != "" { - { stickerLabel(data.Sticker) } - } -
- if data.Image != "" { - { - } else { -
- no image -
- } -
-
-

{ titleOr(data.Title) }

-
- { priceOr(data.Price) } - if data.BuyHref != "" { - buy - } -
-
-
-} - -func stickerLabel(s string) string { - switch s { - case "sold-out": - return "sold out" - default: - return s - } -} - -func titleOr(s string) string { - if s == "" { - return "untitled" - } - return s -} - -func priceOr(s string) string { - if s == "" { - return "$--" - } - return s -} diff --git a/merch_card_templ.go b/merch_card_templ.go deleted file mode 100644 index 4a6d4ac..0000000 --- a/merch_card_templ.go +++ /dev/null @@ -1,178 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// merchCardComponent renders a single merch card. The card class is applied -// to a grid container managed by the page; this block stays self-contained. -func merchCardComponent(data MerchCardData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Sticker != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(stickerLabel(data.Sticker)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `merch_card.templ`, Line: 8, Col: 118} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Image != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\"")") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
no image
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(titleOr(data.Title)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `merch_card.templ`, Line: 20, Col: 72} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(priceOr(data.Price)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `merch_card.templ`, Line: 22, Col: 65} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.BuyHref != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "buy") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func stickerLabel(s string) string { - switch s { - case "sold-out": - return "sold out" - default: - return s - } -} - -func titleOr(s string) string { - if s == "" { - return "untitled" - } - return s -} - -func priceOr(s string) string { - if s == "" { - return "$--" - } - return s -} - -var _ = templruntime.GeneratedTemplate diff --git a/metaball_hero.go b/metaball_hero.go deleted file mode 100644 index c9c5603..0000000 --- a/metaball_hero.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// MetaballHeroBlockMeta declares the metaball hero block. -var MetaballHeroBlockMeta = blocks.BlockMeta{ - Key: "metaball_hero", - Title: "Metaball Hero", - Description: "SVG metaballs on a gradient mesh canvas with headline + CTA.", - Source: "y2k", - Category: blocks.CategoryLayout, -} - -// MetaballHeroBlock renders the metaball hero. -// Content: {headline, sub, ctaLabel, ctaHref, bgPreset} -func MetaballHeroBlock(ctx context.Context, content map[string]any) string { - data := MetaballHeroData{ - Headline: getString(content, "headline"), - Sub: getString(content, "sub"), - CTALabel: getString(content, "ctaLabel"), - CTAHref: getString(content, "ctaHref"), - BgPreset: getStringOr(content, "bgPreset", "magenta-teal"), - } - var buf bytes.Buffer - _ = metaballHeroComponent(data).Render(ctx, &buf) - return buf.String() -} - -// MetaballHeroData is the typed shape for the templ component. -type MetaballHeroData struct { - Headline string - Sub string - CTALabel string - CTAHref string - BgPreset string -} diff --git a/metaball_hero.templ b/metaball_hero.templ deleted file mode 100644 index de01966..0000000 --- a/metaball_hero.templ +++ /dev/null @@ -1,64 +0,0 @@ -package main - -// metaballHeroComponent renders the headline + CTA on a gradient mesh with -// SVG metaballs (Gaussian-blur + threshold filter technique). -templ metaballHeroComponent(data MetaballHeroData) { -
- -
-
-

- { headlineOrDefault(data.Headline) } -

- if data.Sub != "" { -

{ data.Sub }

- } - if data.CTALabel != "" { - - { data.CTALabel } - - } -
-
-
-} - -func headlineOrDefault(s string) string { - if s == "" { - return "new EP out now" - } - return s -} - -func ctaHrefOr(s string) string { - if s == "" { - return "#" - } - return s -} diff --git a/metaball_hero_templ.go b/metaball_hero_templ.go deleted file mode 100644 index ad93754..0000000 --- a/metaball_hero_templ.go +++ /dev/null @@ -1,137 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// metaballHeroComponent renders the headline + CTA on a gradient mesh with -// SVG metaballs (Gaussian-blur + threshold filter technique). -func metaballHeroComponent(data MetaballHeroData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(headlineOrDefault(data.Headline)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `metaball_hero.templ`, Line: 37, Col: 39} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Sub != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.Sub) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `metaball_hero.templ`, Line: 40, Col: 74} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if data.CTALabel != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(data.CTALabel) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `metaball_hero.templ`, Line: 44, Col: 21} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func headlineOrDefault(s string) string { - if s == "" { - return "new EP out now" - } - return s -} - -func ctaHrefOr(s string) string { - if s == "" { - return "#" - } - return s -} - -var _ = templruntime.GeneratedTemplate diff --git a/nft_gallery.go b/nft_gallery.go deleted file mode 100644 index 41f1a44..0000000 --- a/nft_gallery.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// NFTGalleryBlockMeta declares the holographic-foil NFT gallery block. -// Presentational only - no signing UX in v0.1 per spec open question. -var NFTGalleryBlockMeta = blocks.BlockMeta{ - Key: "nft_gallery", - Title: "NFT Gallery", - Description: "Holographic-foil hover gallery for NFT items (presentational only).", - Source: "y2k", - Category: blocks.CategoryContent, -} - -// NFTGalleryBlock renders the gallery. -// Content: {items[{title, image, chain, href}]} -func NFTGalleryBlock(ctx context.Context, content map[string]any) string { - raw := getSlice(content, "items") - items := make([]NFTItem, 0, len(raw)) - for _, r := range raw { - items = append(items, NFTItem{ - Title: getString(r, "title"), - Image: getString(r, "image"), - Chain: getString(r, "chain"), - Href: getString(r, "href"), - }) - } - var buf bytes.Buffer - _ = nftGalleryComponent(NFTGalleryData{Items: items}).Render(ctx, &buf) - return buf.String() -} - -// NFTGalleryData is the typed shape for the templ component. -type NFTGalleryData struct { - Items []NFTItem -} - -// NFTItem is a single gallery card. -type NFTItem struct { - Title string - Image string - Chain string - Href string -} diff --git a/nft_gallery.templ b/nft_gallery.templ deleted file mode 100644 index a1c401b..0000000 --- a/nft_gallery.templ +++ /dev/null @@ -1,33 +0,0 @@ -package main - -// nftGalleryComponent renders a grid of foil-on-hover NFT cards. -templ nftGalleryComponent(data NFTGalleryData) { -
- if len(data.Items) == 0 { -

No items yet.

- } else { - - } -
-} diff --git a/nft_gallery_templ.go b/nft_gallery_templ.go deleted file mode 100644 index 1345673..0000000 --- a/nft_gallery_templ.go +++ /dev/null @@ -1,156 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// nftGalleryComponent renders a grid of foil-on-hover NFT cards. -func nftGalleryComponent(data NFTGalleryData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if len(data.Items) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "

No items yet.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - for _, item := range data.Items { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if item.Image != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\"")") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
no image
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(titleOr(item.Title)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `nft_gallery.templ`, Line: 23, Col: 65} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if item.Chain != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(item.Chain) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `nft_gallery.templ`, Line: 25, Col: 90} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/plugin.mod b/plugin.mod index cebb1b6..69cb004 100644 --- a/plugin.mod +++ b/plugin.mod @@ -2,11 +2,8 @@ name = "y2k" display_name = "Y2K" scope = "@themes" -version = "0.1.2" +version = "0.2.0" description = "Liquid-chrome Y2K revival theme for indie musicians, zines, and merch shops. Gradient mesh backgrounds, plastic-bevel buttons, marquee text, waveform blocks." kind = "theme" categories = ["templates"] tags = ["retro", "chrome", "vaporwave", "pastel", "music", "creator", "nostalgia", "web3"] - -[compatibility] -block_core = ">=0.15.0 <0.16.0" diff --git a/register.go b/register.go deleted file mode 100644 index 8ba5a89..0000000 --- a/register.go +++ /dev/null @@ -1,173 +0,0 @@ -package main - -import ( - "context" - - "github.com/a-h/templ" - - "git.dev.alexdunmow.com/block/core/blocks" - "git.dev.alexdunmow.com/block/core/plugin" - "git.dev.alexdunmow.com/block/core/templates" -) - -// wrap adapts a templ-returning render function to templates.TemplateFunc. -// templ.Component already implements templates.HTMLComponent via Render. -func wrap(f func(ctx context.Context, doc map[string]any) templ.Component) templates.TemplateFunc { - return func(ctx context.Context, doc map[string]any) templates.HTMLComponent { - return f(ctx, doc) - } -} - -// Register registers the y2k system template, its four page templates, all -// theme-specific blocks, the four built-in overrides, and the email wrapper. -// -// Call order: page templates can be registered any time, but schemas MUST load -// before any block Register call. -func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error { - // 1. System template - tr.RegisterSystemTemplate(templates.SystemTemplateMeta{ - Key: "y2k", - Title: "Y2K", - Description: "Liquid-chrome Y2K revival theme for indie musicians, zines, and merch shops.", - }) - - // 2. Page templates (slots match the spec verbatim) - if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{ - Key: "default", - Title: "Default", - Description: "Chrome navbar + content + footer.", - Slots: []string{"header", "main", "footer"}, - }, wrap(RenderY2K)); err != nil { - return err - } - if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{ - Key: "landing", - Title: "Landing", - Description: "Hero metaball + marquee + CTAs.", - Slots: []string{"hero", "marquee", "main", "cta", "footer"}, - }, wrap(RenderY2KLanding)); err != nil { - return err - } - if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{ - Key: "article", - Title: "Article / Zine Page", - Description: "Narrow column with sidebar tracklist.", - Slots: []string{"header", "main", "aside", "footer"}, - }, wrap(RenderY2KArticle)); err != nil { - return err - } - if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{ - Key: "full-width", - Title: "Full Width", - Description: "Edge-to-edge gradient mesh canvas.", - Slots: []string{"header", "main", "footer"}, - }, wrap(RenderY2KFullWidth)); err != nil { - return err - } - - // 3. Schemas first — must precede br.Register so they bind. - if err := br.LoadSchemasFromFS(Schemas()); err != nil { - return err - } - - // 4. Theme-specific blocks (10 total per spec §11). - br.Register(ChromeNavbarBlockMeta, ChromeNavbarBlock) - br.Register(MetaballHeroBlockMeta, MetaballHeroBlock) - br.Register(WaveformPlayerBlockMeta, WaveformPlayerBlock) - br.Register(MarqueeBlockMeta, MarqueeBlock) - br.Register(TracklistBlockMeta, TracklistBlock) - br.Register(MerchCardBlockMeta, MerchCardBlock) - br.Register(WebringBadgeBlockMeta, WebringBadgeBlock) - br.Register(GlitterDividerBlockMeta, GlitterDividerBlock) - br.Register(FooterChromeBlockMeta, FooterChromeBlock) - br.Register(NFTGalleryBlockMeta, NFTGalleryBlock) - - // 5. Built-in overrides (only apply when y2k is the active theme). - br.RegisterTemplateOverride("y2k", "heading", Y2KHeadingBlock) - br.RegisterTemplateOverride("y2k", "text", Y2KTextBlock) - br.RegisterTemplateOverride("y2k", "button", Y2KButtonBlock) - br.RegisterTemplateOverride("y2k", "image", Y2KImageBlock) - - // 6. Email wrapper for branded transactional mail. - tr.RegisterEmailWrapper("y2k", Y2KEmailWrapper) - - return nil -} - -// DefaultMasterPages returns the master pages that y2k seeds on first load. -// Block keys reference theme-owned blocks as "y2k:"; the built-in slot -// block uses {"slotName":"main"} per CLAUDE.md. -func DefaultMasterPages() []plugin.MasterPageDefinition { - return []plugin.MasterPageDefinition{ - { - Key: "y2k:default-master", - Title: "Y2K Default Master", - PageTemplates: []string{"default", "article"}, - Blocks: []plugin.MasterPageBlock{ - { - BlockKey: "y2k:chrome_navbar", - Title: "Chrome Navbar", - Content: map[string]any{"menuName": "main", "logoText": "y2k.fm"}, - Slot: "header", - SortOrder: 0, - }, - { - BlockKey: "y2k:marquee", - Title: "Top Marquee", - Content: map[string]any{"items": []any{"new drop friday", "listen on bandcamp", "subscribe to the zine"}, "speed": "medium"}, - Slot: "header", - SortOrder: 1, - }, - { - BlockKey: "slot", - Title: "Main Slot", - Content: map[string]any{"slotName": "main"}, - Slot: "main", - SortOrder: 0, - }, - { - BlockKey: "y2k:footer_chrome", - Title: "Chrome Footer", - Content: map[string]any{"showWebring": true, "copyright": "(c) y2k.fm"}, - Slot: "footer", - SortOrder: 0, - }, - }, - }, - { - Key: "y2k:landing-master", - Title: "Y2K Landing Master", - PageTemplates: []string{"landing", "full-width"}, - Blocks: []plugin.MasterPageBlock{ - { - BlockKey: "y2k:metaball_hero", - Title: "Metaball Hero", - Content: map[string]any{"headline": "new EP out now", "sub": "liquid chrome dreams", "ctaLabel": "listen"}, - Slot: "hero", - SortOrder: 0, - }, - { - BlockKey: "y2k:marquee", - Title: "Marquee", - Content: map[string]any{"items": []any{"* new * new * new"}, "speed": "fast"}, - Slot: "marquee", - SortOrder: 0, - }, - { - BlockKey: "slot", - Title: "Main Slot", - Content: map[string]any{"slotName": "main"}, - Slot: "main", - SortOrder: 0, - }, - { - BlockKey: "y2k:footer_chrome", - Title: "Chrome Footer", - Content: map[string]any{"showWebring": true}, - Slot: "footer", - SortOrder: 0, - }, - }, - }, - } -} diff --git a/registration.go b/registration.go deleted file mode 100644 index 4f10fd7..0000000 --- a/registration.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "io/fs" - "net/http" - - "git.dev.alexdunmow.com/block/core/blocks" - "git.dev.alexdunmow.com/block/core/plugin" - "git.dev.alexdunmow.com/block/core/templates" -) - -// Registration is the compile-time plugin registration for the Y2K theme. -// The CMS plugin loader looks up this exported symbol after dlopen. -var Registration = plugin.PluginRegistration{ - Name: "y2k", - Version: plugin.ParseModVersion(pluginModBytes), - Register: func(tr templates.TemplateRegistry, br blocks.BlockRegistry) error { - return Register(tr, br) - }, - Assets: func() http.Handler { return AssetsHandler() }, - Schemas: func() fs.FS { return Schemas() }, - ThemePresets: func() []byte { return ThemePresets() }, - BundledFonts: func() []byte { return BundledFonts() }, - MasterPages: func() []plugin.MasterPageDefinition { return DefaultMasterPages() }, - CSSManifest: func() *plugin.CSSManifest { return ThemeCSSManifest() }, -} diff --git a/template.templ b/template.templ deleted file mode 100644 index 5f5aeb4..0000000 --- a/template.templ +++ /dev/null @@ -1,244 +0,0 @@ -package main - -import ( - "context" - - "git.dev.alexdunmow.com/block/core/templates/bn" -) - -// PageData is the per-render shape used by every y2k page template. -// It mirrors gotham's shape so the bn.Head/bn.BodyEnd helpers can be reused. -type PageData struct { - Title string - Slots map[string]string - ThemeMode string - ThemeCSS string - SiteSettings bn.SiteSettingsData - PageMeta bn.PageMeta - StructuredData string - CSSHash string - PageviewNonce string - EngagementConfig bn.EngagementConfig -} - -func parseY2KPageData(doc map[string]any) PageData { - title := "Untitled" - if t, ok := doc["title"].(string); ok { - title = t - } - slots := map[string]string{} - if s, ok := doc["slots"].(map[string]string); ok { - slots = s - } - themeMode := "light" - if tm, ok := doc["theme_mode"].(string); ok && tm != "" { - themeMode = tm - } - themeCSS := "" - if tc, ok := doc["theme_css"].(string); ok { - themeCSS = tc - } - structuredData := "" - if sd, ok := doc["structured_data"].(string); ok { - structuredData = sd - } - cssHash := "" - if ch, ok := doc["css_hash"].(string); ok { - cssHash = ch - } - pageviewNonce := "" - if pn, ok := doc["pageview_nonce"].(string); ok { - pageviewNonce = pn - } - return PageData{ - Title: title, - Slots: slots, - ThemeMode: themeMode, - ThemeCSS: themeCSS, - SiteSettings: bn.ParseSiteSettings(doc), - PageMeta: bn.ParsePageMeta(doc), - StructuredData: structuredData, - CSSHash: cssHash, - PageviewNonce: pageviewNonce, - EngagementConfig: bn.ParseEngagementConfig(doc), - } -} - -// === Default page template === -templ Y2KDefault(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }) - - @bn.AdminBypassBanner(data.SiteSettings) -
- @templ.Raw(data.Slots["header"]) -
-
- if main, ok := data.Slots["main"]; ok && main != "" { - @templ.Raw(main) - } else { -
-

No content blocks assigned to this page.

-
- } -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// === Landing page template === -templ Y2KLanding(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }) - - @bn.AdminBypassBanner(data.SiteSettings) -
- @templ.Raw(data.Slots["hero"]) -
-
- @templ.Raw(data.Slots["marquee"]) -
-
- if main, ok := data.Slots["main"]; ok && main != "" { -
- @templ.Raw(main) -
- } -
-
- @templ.Raw(data.Slots["cta"]) -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// === Article / Zine page template === -templ Y2KArticle(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }) - - @bn.AdminBypassBanner(data.SiteSettings) -
- @templ.Raw(data.Slots["header"]) -
-
-
- if main, ok := data.Slots["main"]; ok && main != "" { -
- @templ.Raw(main) -
- } else { -
-

No content blocks assigned to this page.

-
- } -
- -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// === Full-width page template === -templ Y2KFullWidth(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }) - - @bn.AdminBypassBanner(data.SiteSettings) -
- @templ.Raw(data.Slots["header"]) -
-
- if main, ok := data.Slots["main"]; ok && main != "" { - @templ.Raw(main) - } else { -
-

No content blocks assigned to this page.

-
- } -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -func RenderY2K(ctx context.Context, doc map[string]any) templ.Component { - return Y2KDefault(parseY2KPageData(doc)) -} - -func RenderY2KLanding(ctx context.Context, doc map[string]any) templ.Component { - return Y2KLanding(parseY2KPageData(doc)) -} - -func RenderY2KArticle(ctx context.Context, doc map[string]any) templ.Component { - return Y2KArticle(parseY2KPageData(doc)) -} - -func RenderY2KFullWidth(ctx context.Context, doc map[string]any) templ.Component { - return Y2KFullWidth(parseY2KPageData(doc)) -} diff --git a/template_templ.go b/template_templ.go deleted file mode 100644 index 21d91b9..0000000 --- a/template_templ.go +++ /dev/null @@ -1,510 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import ( - "context" - - "git.dev.alexdunmow.com/block/core/templates/bn" -) - -// PageData is the per-render shape used by every y2k page template. -// It mirrors gotham's shape so the bn.Head/bn.BodyEnd helpers can be reused. -type PageData struct { - Title string - Slots map[string]string - ThemeMode string - ThemeCSS string - SiteSettings bn.SiteSettingsData - PageMeta bn.PageMeta - StructuredData string - CSSHash string - PageviewNonce string - EngagementConfig bn.EngagementConfig -} - -func parseY2KPageData(doc map[string]any) PageData { - title := "Untitled" - if t, ok := doc["title"].(string); ok { - title = t - } - slots := map[string]string{} - if s, ok := doc["slots"].(map[string]string); ok { - slots = s - } - themeMode := "light" - if tm, ok := doc["theme_mode"].(string); ok && tm != "" { - themeMode = tm - } - themeCSS := "" - if tc, ok := doc["theme_css"].(string); ok { - themeCSS = tc - } - structuredData := "" - if sd, ok := doc["structured_data"].(string); ok { - structuredData = sd - } - cssHash := "" - if ch, ok := doc["css_hash"].(string); ok { - cssHash = ch - } - pageviewNonce := "" - if pn, ok := doc["pageview_nonce"].(string); ok { - pageviewNonce = pn - } - return PageData{ - Title: title, - Slots: slots, - ThemeMode: themeMode, - ThemeCSS: themeCSS, - SiteSettings: bn.ParseSiteSettings(doc), - PageMeta: bn.ParsePageMeta(doc), - StructuredData: structuredData, - CSSHash: cssHash, - PageviewNonce: pageviewNonce, - EngagementConfig: bn.ParseEngagementConfig(doc), - } -} - -// === Default page template === -func Y2KDefault(data PageData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if main, ok := data.Slots["main"]; ok && main != "" { - templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

No content blocks assigned to this page.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// === Landing page template === -func Y2KLanding(data PageData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var2 := templ.GetChildren(ctx) - if templ_7745c5c3_Var2 == nil { - templ_7745c5c3_Var2 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["hero"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["marquee"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if main, ok := data.Slots["main"]; ok && main != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["cta"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// === Article / Zine page template === -func Y2KArticle(data PageData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templ.GetChildren(ctx) - if templ_7745c5c3_Var3 == nil { - templ_7745c5c3_Var3 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if main, ok := data.Slots["main"]; ok && main != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "

No content blocks assigned to this page.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// === Full-width page template === -func Y2KFullWidth(data PageData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var4 := templ.GetChildren(ctx) - if templ_7745c5c3_Var4 == nil { - templ_7745c5c3_Var4 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/y2k/style.css"}, - StructuredData: data.StructuredData, - CSSHash: data.CSSHash, - PageviewNonce: data.PageviewNonce, - EngagementConfig: data.EngagementConfig, - }).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.AdminBypassBanner(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["header"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if main, ok := data.Slots["main"]; ok && main != "" { - templ_7745c5c3_Err = templ.Raw(main).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "

No content blocks assigned to this page.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Slots["footer"]).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = bn.BodyEnd(data.SiteSettings).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func RenderY2K(ctx context.Context, doc map[string]any) templ.Component { - return Y2KDefault(parseY2KPageData(doc)) -} - -func RenderY2KLanding(ctx context.Context, doc map[string]any) templ.Component { - return Y2KLanding(parseY2KPageData(doc)) -} - -func RenderY2KArticle(ctx context.Context, doc map[string]any) templ.Component { - return Y2KArticle(parseY2KPageData(doc)) -} - -func RenderY2KFullWidth(ctx context.Context, doc map[string]any) templ.Component { - return Y2KFullWidth(parseY2KPageData(doc)) -} - -var _ = templruntime.GeneratedTemplate diff --git a/templates/email/y2k.ninjatpl b/templates/email/y2k.ninjatpl new file mode 100644 index 0000000..8f139ca --- /dev/null +++ b/templates/email/y2k.ninjatpl @@ -0,0 +1,53 @@ + + + + + + + + {{ site_name }} + + + + {% if preview_text %}
{{ preview_text }}
{% endif %} + + + + +
+ + + + + + + + + + + + + + +
+ + diff --git a/templates/overrides/y2k/button.ninjatpl b/templates/overrides/y2k/button.ninjatpl new file mode 100644 index 0000000..61b7004 --- /dev/null +++ b/templates/overrides/y2k/button.ninjatpl @@ -0,0 +1 @@ +{{ text|default:"button" }} diff --git a/templates/overrides/y2k/heading.ninjatpl b/templates/overrides/y2k/heading.ninjatpl new file mode 100644 index 0000000..06b1470 --- /dev/null +++ b/templates/overrides/y2k/heading.ninjatpl @@ -0,0 +1 @@ +{% if level|integer == 1 %}

{{ text }}

{% elif level|integer == 3 %}

{{ text }}

{% elif level|integer == 4 %}

{{ text }}

{% elif level|integer == 5 %}
{{ text }}
{% elif level|integer == 6 %}
{{ text }}
{% else %}

{{ text }}

{% endif %} diff --git a/templates/overrides/y2k/image.ninjatpl b/templates/overrides/y2k/image.ninjatpl new file mode 100644 index 0000000..eef295d --- /dev/null +++ b/templates/overrides/y2k/image.ninjatpl @@ -0,0 +1 @@ +{% if url %}
{{ alt }}{% if caption %}
{{ caption }}
{% endif %}
{% endif %} diff --git a/templates/overrides/y2k/text.ninjatpl b/templates/overrides/y2k/text.ninjatpl new file mode 100644 index 0000000..adf7858 --- /dev/null +++ b/templates/overrides/y2k/text.ninjatpl @@ -0,0 +1 @@ +
{{ text|safe }}
diff --git a/templates/y2k/article.ninjatpl b/templates/y2k/article.ninjatpl new file mode 100644 index 0000000..e6fc052 --- /dev/null +++ b/templates/y2k/article.ninjatpl @@ -0,0 +1,22 @@ + + +{{ head_html|safe }} + + {{ admin_banner_html|safe }} +
+ {{ slots.header|safe }} +
+
+
+ {% if slots.main %}
{{ slots.main|safe }}
{% else %}

No content blocks assigned to this page.

{% endif %} +
+ +
+
+ {{ slots.footer|safe }} +
+ {{ body_end_html|safe }} + + diff --git a/templates/y2k/default.ninjatpl b/templates/y2k/default.ninjatpl new file mode 100644 index 0000000..ed6617a --- /dev/null +++ b/templates/y2k/default.ninjatpl @@ -0,0 +1,17 @@ + + +{{ head_html|safe }} + + {{ admin_banner_html|safe }} +
+ {{ slots.header|safe }} +
+
+ {% if slots.main %}{{ slots.main|safe }}{% else %}

No content blocks assigned to this page.

{% endif %} +
+
+ {{ slots.footer|safe }} +
+ {{ body_end_html|safe }} + + diff --git a/templates/y2k/full-width.ninjatpl b/templates/y2k/full-width.ninjatpl new file mode 100644 index 0000000..3d1222b --- /dev/null +++ b/templates/y2k/full-width.ninjatpl @@ -0,0 +1,17 @@ + + +{{ head_html|safe }} + + {{ admin_banner_html|safe }} +
+ {{ slots.header|safe }} +
+
+ {% if slots.main %}{{ slots.main|safe }}{% else %}

No content blocks assigned to this page.

{% endif %} +
+
+ {{ slots.footer|safe }} +
+ {{ body_end_html|safe }} + + diff --git a/templates/y2k/landing.ninjatpl b/templates/y2k/landing.ninjatpl new file mode 100644 index 0000000..d53f13e --- /dev/null +++ b/templates/y2k/landing.ninjatpl @@ -0,0 +1,23 @@ + + +{{ head_html|safe }} + + {{ admin_banner_html|safe }} +
+ {{ slots.hero|safe }} +
+
+ {{ slots.marquee|safe }} +
+
+ {% if slots.main %}
{{ slots.main|safe }}
{% endif %} +
+
+ {{ slots.cta|safe }} +
+
+ {{ slots.footer|safe }} +
+ {{ body_end_html|safe }} + + diff --git a/text_override.go b/text_override.go deleted file mode 100644 index 44475d4..0000000 --- a/text_override.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "bytes" - "context" -) - -// Y2KTextBlock applies the holographic link underline to the built-in text -// block when the y2k theme is active. -// Content: {text, class} -func Y2KTextBlock(ctx context.Context, content map[string]any) string { - text := getString(content, "text") - class := getString(content, "class") - var buf bytes.Buffer - _ = y2kTextComponent(text, class).Render(ctx, &buf) - return buf.String() -} diff --git a/text_override.templ b/text_override.templ deleted file mode 100644 index 2cf9385..0000000 --- a/text_override.templ +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// y2kTextComponent wraps prose in the y2k-text container so links pick up the -// holographic underline gradient. -templ y2kTextComponent(text, class string) { -
- @templ.Raw(text) -
-} diff --git a/text_override_templ.go b/text_override_templ.go deleted file mode 100644 index 753ceaf..0000000 --- a/text_override_templ.go +++ /dev/null @@ -1,68 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// y2kTextComponent wraps prose in the y2k-text container so links pick up the -// holographic underline gradient. -func y2kTextComponent(text, class string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var2 = []any{"y2k-text prose max-w-none", class} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(text).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/tracklist.go b/tracklist.go deleted file mode 100644 index e9676a8..0000000 --- a/tracklist.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// TracklistBlockMeta declares the CD-jewel-case tracklist block. -var TracklistBlockMeta = blocks.BlockMeta{ - Key: "tracklist", - Title: "Tracklist", - Description: "Tabular tracklist styled like a CD jewel case insert.", - Source: "y2k", - Category: blocks.CategoryContent, -} - -// TracklistBlock renders the tracklist. -// Content: {tracks[{title, duration, url}]} -func TracklistBlock(ctx context.Context, content map[string]any) string { - raw := getSlice(content, "tracks") - tracks := make([]TrackRow, 0, len(raw)) - for _, r := range raw { - tracks = append(tracks, TrackRow{ - Title: getString(r, "title"), - Duration: getString(r, "duration"), - URL: getString(r, "url"), - }) - } - var buf bytes.Buffer - _ = tracklistComponent(TracklistData{Tracks: tracks}).Render(ctx, &buf) - return buf.String() -} - -// TracklistData is the typed shape for the templ component. -type TracklistData struct { - Tracks []TrackRow -} - -// TrackRow is a single tracklist row. -type TrackRow struct { - Title string - Duration string - URL string -} diff --git a/tracklist.templ b/tracklist.templ deleted file mode 100644 index 83b7982..0000000 --- a/tracklist.templ +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import "strconv" - -// tracklistComponent renders the track table. Rows wrap on small screens so -// duration is never dropped (UAT 7.6). -templ tracklistComponent(data TracklistData) { -
-
- tracklist -
- if len(data.Tracks) == 0 { -

No tracks yet.

- } else { -
    - for i, t := range data.Tracks { -
  1. - { strconv.Itoa(i + 1) } - - if t.URL != "" { - { trackTitleOr(t.Title) } - } else { - { trackTitleOr(t.Title) } - } - - { durationOrDash(t.Duration) } -
  2. - } -
- } -
-} - -func durationOrDash(s string) string { - if s == "" { - return "--:--" - } - return s -} diff --git a/tracklist_templ.go b/tracklist_templ.go deleted file mode 100644 index 0132fdd..0000000 --- a/tracklist_templ.go +++ /dev/null @@ -1,148 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "strconv" - -// tracklistComponent renders the track table. Rows wrap on small screens so -// duration is never dropped (UAT 7.6). -func tracklistComponent(data TracklistData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
tracklist
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if len(data.Tracks) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "

No tracks yet.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - for i, t := range data.Tracks { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
  1. ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(i + 1)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `tracklist.templ`, Line: 18, Col: 97} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if t.URL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(trackTitleOr(t.Title)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `tracklist.templ`, Line: 21, Col: 88} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(trackTitleOr(t.Title)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `tracklist.templ`, Line: 23, Col: 31} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(durationOrDash(t.Duration)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `tracklist.templ`, Line: 26, Col: 109} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
  2. ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func durationOrDash(s string) string { - if s == "" { - return "--:--" - } - return s -} - -var _ = templruntime.GeneratedTemplate diff --git a/waveform_player.go b/waveform_player.go deleted file mode 100644 index 1a32e20..0000000 --- a/waveform_player.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// WaveformPlayerBlockMeta declares the waveform audio player block. -var WaveformPlayerBlockMeta = blocks.BlockMeta{ - Key: "waveform_player", - Title: "Waveform Player", - Description: "Soundcloud-style audio player with a canvas waveform.", - Source: "y2k", - Category: blocks.CategoryContent, -} - -// WaveformPlayerBlock renders the audio block. -// Content: {trackTitle, audioUrl, artist, coverImage} -func WaveformPlayerBlock(ctx context.Context, content map[string]any) string { - data := WaveformPlayerData{ - TrackTitle: getString(content, "trackTitle"), - AudioURL: getString(content, "audioUrl"), - Artist: getString(content, "artist"), - CoverImage: getString(content, "coverImage"), - } - if data.AudioURL == "" && data.TrackTitle == "" { - return "" - } - var buf bytes.Buffer - _ = waveformPlayerComponent(data).Render(ctx, &buf) - return buf.String() -} - -// WaveformPlayerData is the typed shape for the templ component. -type WaveformPlayerData struct { - TrackTitle string - AudioURL string - Artist string - CoverImage string -} diff --git a/waveform_player.templ b/waveform_player.templ deleted file mode 100644 index 302575e..0000000 --- a/waveform_player.templ +++ /dev/null @@ -1,49 +0,0 @@ -package main - -// waveformPlayerComponent renders a Soundcloud-style horizontal player. The -// canvas waveform is filled client-side from the audio source using WebAudio -// peak decode (v0.1 strategy noted in the spec's open questions). -templ waveformPlayerComponent(data WaveformPlayerData) { -
-
- if data.CoverImage != "" { - { - } else { - - } -
-
-
- { trackTitleOr(data.TrackTitle) } - if data.Artist != "" { - { data.Artist } - } -
- - if data.AudioURL != "" { - - } else { -

No audio source configured.

- } -
-
-} - -func trackTitleOr(s string) string { - if s == "" { - return "untitled track" - } - return s -} diff --git a/waveform_player_templ.go b/waveform_player_templ.go deleted file mode 100644 index 076478d..0000000 --- a/waveform_player_templ.go +++ /dev/null @@ -1,168 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// waveformPlayerComponent renders a Soundcloud-style horizontal player. The -// canvas waveform is filled client-side from the audio source using WebAudio -// peak decode (v0.1 strategy noted in the spec's open questions). -func waveformPlayerComponent(data WaveformPlayerData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.CoverImage != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"")") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(trackTitleOr(data.TrackTitle)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `waveform_player.templ`, Line: 22, Col: 96} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Artist != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Artist) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `waveform_player.templ`, Line: 24, Col: 96} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.AudioURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "

No audio source configured.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func trackTitleOr(s string) string { - if s == "" { - return "untitled track" - } - return s -} - -var _ = templruntime.GeneratedTemplate diff --git a/webring_badge.go b/webring_badge.go deleted file mode 100644 index c27355b..0000000 --- a/webring_badge.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// WebringBadgeBlockMeta declares the canonical 88x31 webring badge row. -var WebringBadgeBlockMeta = blocks.BlockMeta{ - Key: "webring_badge", - Title: "Webring Badge", - Description: "Canonical 88x31 webring button row with prev/next/ring links.", - Source: "y2k", - Category: blocks.CategoryNavigation, -} - -// WebringBadgeBlock renders the badge row. -// Content: {prevHref, nextHref, ringName} -func WebringBadgeBlock(ctx context.Context, content map[string]any) string { - data := WebringBadgeData{ - PrevHref: getString(content, "prevHref"), - NextHref: getString(content, "nextHref"), - RingName: getStringOr(content, "ringName", "the y2k.fm ring"), - } - var buf bytes.Buffer - _ = webringBadgeComponent(data).Render(ctx, &buf) - return buf.String() -} - -// WebringBadgeData is the typed shape for the templ component. -type WebringBadgeData struct { - PrevHref string - NextHref string - RingName string -} diff --git a/webring_badge.templ b/webring_badge.templ deleted file mode 100644 index 812dc45..0000000 --- a/webring_badge.templ +++ /dev/null @@ -1,18 +0,0 @@ -package main - -// webringBadgeComponent renders the prev/ring/next badge triplet at the -// canonical 88x31 button size. -templ webringBadgeComponent(data WebringBadgeData) { - -} - -func orHash(s string) string { - if s == "" { - return "#" - } - return s -} diff --git a/webring_badge_templ.go b/webring_badge_templ.go deleted file mode 100644 index bb8a0cd..0000000 --- a/webring_badge_templ.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.1020 -package main - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// webringBadgeComponent renders the prev/ring/next badge triplet at the -// canonical 88x31 button size. -func webringBadgeComponent(data WebringBadgeData) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func orHash(s string) string { - if s == "" { - return "#" - } - return s -} - -var _ = templruntime.GeneratedTemplate