diff --git a/Makefile b/Makefile index 1282622..754b53b 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,27 @@ -# coffee — build & publish helpers (wasm .bnp workflow) +# coffee — 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 coffee-.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 coffee-.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 := coffee 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..eef4aca --- /dev/null +++ b/blocks/blocks.yaml @@ -0,0 +1,42 @@ +# Coffee theme block definitions (codeless .bnp, WO-WZ-021). +# Keys are fully qualified (coffee:) 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 attributes and the master_pages.json references. +blocks: + - key: coffee:menu_board + title: Menu Board + description: Kraft-paper menu with sections of items (espresso, filter, pastry, ...) + category: content + schema: menu_board.schema.json + template: menu_board.ninjatpl + - key: coffee:hours_strip + title: Hours Strip + description: Weekly hours strip listing each day's opening hours. + category: content + schema: hours_strip.schema.json + template: hours_strip.ninjatpl + - key: coffee:location_card + title: Location Card + description: Address card with optional static map image and doodled pin overlay. + category: content + schema: location_card.schema.json + template: location_card.ninjatpl + - key: coffee:featured_pour + title: Featured Pour + description: Hero card for a featured coffee, tea or pastry with tasting notes and price. + category: content + schema: featured_pour.schema.json + template: featured_pour.ninjatpl + - key: coffee:footer + title: Footer + description: Torn-edge footer with optional location summary and newsletter caption. + category: layout + schema: footer.schema.json + template: footer.ninjatpl + - key: coffee:doodle_divider + title: Doodle Divider + description: Hand-drawn divider in one of four motifs (beans, croissant, cup, leaf). + category: layout + schema: doodle_divider.schema.json + template: doodle_divider.ninjatpl diff --git a/blocks/doodle_divider.ninjatpl b/blocks/doodle_divider.ninjatpl new file mode 100644 index 0000000..a97a2d0 --- /dev/null +++ b/blocks/doodle_divider.ninjatpl @@ -0,0 +1,39 @@ +
+ {% if motif == "croissant" %} + + {% elif motif == "cup" %} + + {% elif motif == "leaf" %} + + {% else %} + + {% endif %} +
diff --git a/schemas/doodle_divider.schema.json b/blocks/doodle_divider.schema.json similarity index 100% rename from schemas/doodle_divider.schema.json rename to blocks/doodle_divider.schema.json diff --git a/blocks/featured_pour.ninjatpl b/blocks/featured_pour.ninjatpl new file mode 100644 index 0000000..eda009d --- /dev/null +++ b/blocks/featured_pour.ninjatpl @@ -0,0 +1,15 @@ +
+
+ + Featured + +
+ {% if image %}{{ name }}{% else %}
Add a hero image
{% endif %} +
+
+ {% if name %}

{{ name }}

{% else %}

Featured pour

{% endif %} + {% if tasting %}
{{ tasting|safe }}
{% endif %} + {% if price %}
{{ price }}
{% endif %} +
+
+
diff --git a/schemas/featured_pour.schema.json b/blocks/featured_pour.schema.json similarity index 100% rename from schemas/featured_pour.schema.json rename to blocks/featured_pour.schema.json diff --git a/blocks/footer.ninjatpl b/blocks/footer.ninjatpl new file mode 100644 index 0000000..694152c --- /dev/null +++ b/blocks/footer.ninjatpl @@ -0,0 +1,28 @@ +
+
+
+

Hello there

+

Pull up a seat. Pastries from 7, coffee until late.

+
+ {% if showLocation != "false" and showLocation != false %} +
+

Visit

+
42 Roastery Lane +City, State 9000
+
+ {% endif %} +
+

Stay in touch

+ {% if newsletterText %}

{{ newsletterText }}

{% else %}

Slow notes from the bar. Brew tips, seasonal pours, no spam.

{% endif %} +
+ + + +
+
+
+
+ © Coffee theme — kraft paper edition. + Hand-drawn with care. +
+
diff --git a/schemas/footer.schema.json b/blocks/footer.schema.json similarity index 100% rename from schemas/footer.schema.json rename to blocks/footer.schema.json diff --git a/blocks/hours_strip.ninjatpl b/blocks/hours_strip.ninjatpl new file mode 100644 index 0000000..23e6439 --- /dev/null +++ b/blocks/hours_strip.ninjatpl @@ -0,0 +1,11 @@ + diff --git a/schemas/hours_strip.schema.json b/blocks/hours_strip.schema.json similarity index 100% rename from schemas/hours_strip.schema.json rename to blocks/hours_strip.schema.json diff --git a/blocks/location_card.ninjatpl b/blocks/location_card.ninjatpl new file mode 100644 index 0000000..f61f3b6 --- /dev/null +++ b/blocks/location_card.ninjatpl @@ -0,0 +1,18 @@ +
+
+
+ {% if mapImage %}Map of our location{% else %}
Map preview
{% endif %} + +
+
+

+ Find us +

+ {% if address %}
{{ address }}
{% else %}

Add an address to render the location card.

{% endif %} + {% if directionsUrl %}Directions{% endif %} +
+
+
diff --git a/schemas/location_card.schema.json b/blocks/location_card.schema.json similarity index 100% rename from schemas/location_card.schema.json rename to blocks/location_card.schema.json diff --git a/blocks/menu_board.ninjatpl b/blocks/menu_board.ninjatpl new file mode 100644 index 0000000..718b34d --- /dev/null +++ b/blocks/menu_board.ninjatpl @@ -0,0 +1,26 @@ +
+
+

+ {{ title|default:"Menu" }} +

+ {% if not sections %}

Add a section to get started.

{% endif %} + {% for section in sections %} +
+ {% if section.name %}

{{ section.name }}

{% endif %} + {% if not section.items %}

No items yet.

{% endif %} +
    + {% for item in section.items %} +
  • +
    +
    {{ item.name }}
    + {% if item.note %}
    {{ item.note }}
    {% endif %} + {% if item.allergens %}
    Allergens: {{ item.allergens }}
    {% endif %} +
    + {% if item.price %}
    {{ item.price }}
    {% endif %} +
  • + {% endfor %} +
+
+ {% endfor %} +
+
diff --git a/schemas/menu_board.schema.json b/blocks/menu_board.schema.json similarity index 100% rename from schemas/menu_board.schema.json rename to blocks/menu_board.schema.json diff --git a/button_override.go b/button_override.go deleted file mode 100644 index 79e1a70..0000000 --- a/button_override.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "bytes" - "context" -) - -// CoffeeButtonBlock renders a button with the kraft-tag override styling. -// Content shape: {"text": "Click me", "url": "...", "variant": "primary|secondary"} -func CoffeeButtonBlock(ctx context.Context, content map[string]any) string { - text := getString(content, "text") - url := getString(content, "url") - variant := getString(content, "variant") - - var buf bytes.Buffer - _ = coffeeButtonComponent(text, url, variant).Render(ctx, &buf) - return buf.String() -} diff --git a/button_override.templ b/button_override.templ deleted file mode 100644 index 989d0ee..0000000 --- a/button_override.templ +++ /dev/null @@ -1,23 +0,0 @@ -package main - -// coffeeButtonVariantClass appends a variant-specific tone to the kraft-tag. -func coffeeButtonVariantClass(variant string) string { - switch variant { - case "secondary": - return "bg-secondary text-secondary-foreground" - case "destructive": - return "bg-destructive text-destructive-foreground" - default: - return "" - } -} - -// coffeeButtonComponent renders a button or link styled like a kraft tag with -// a slight rotation on hover. -templ coffeeButtonComponent(text, url, variant string) { - if url != "" { - { text } - } else { - - } -} diff --git a/button_override_templ.go b/button_override_templ.go deleted file mode 100644 index f35945b..0000000 --- a/button_override_templ.go +++ /dev/null @@ -1,136 +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" - -// coffeeButtonVariantClass appends a variant-specific tone to the kraft-tag. -func coffeeButtonVariantClass(variant string) string { - switch variant { - case "secondary": - return "bg-secondary text-secondary-foreground" - case "destructive": - return "bg-destructive text-destructive-foreground" - default: - return "" - } -} - -// coffeeButtonComponent renders a button or link styled like a kraft tag with -// a slight rotation on hover. -func coffeeButtonComponent(text, url, 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) - if url != "" { - var templ_7745c5c3_Var2 = []any{"kraft-tag", coffeeButtonVariantClass(variant)} - 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_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(text) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 19, 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, 4, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - var templ_7745c5c3_Var6 = []any{"kraft-tag", coffeeButtonVariantClass(variant)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, 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/doodle_divider.go b/doodle_divider.go deleted file mode 100644 index 68c91d4..0000000 --- a/doodle_divider.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// DoodleDividerBlockMeta defines metadata for the doodle_divider block. -var DoodleDividerBlockMeta = blocks.BlockMeta{ - Key: "doodle_divider", - Title: "Doodle Divider", - Description: "Hand-drawn divider in one of four motifs (beans, croissant, cup, leaf)", - Source: "coffee", -} - -// DoodleDividerBlock renders an inline SVG divider based on the motif. -// Content shape: {"motif": "beans"} where motif is one of beans/croissant/cup/leaf. -func DoodleDividerBlock(ctx context.Context, content map[string]any) string { - motif := getString(content, "motif") - switch motif { - case "beans", "croissant", "cup", "leaf": - // allowed - default: - motif = "beans" - } - - var buf bytes.Buffer - _ = doodleDividerComponent(motif).Render(ctx, &buf) - return buf.String() -} diff --git a/doodle_divider.templ b/doodle_divider.templ deleted file mode 100644 index 80b64a1..0000000 --- a/doodle_divider.templ +++ /dev/null @@ -1,47 +0,0 @@ -package main - -// doodleDividerComponent renders an inline SVG divider whose motif is -// selected by the editor. Each motif draws a distinct hand-drawn shape so -// they look visibly different even at thumbnail size. -templ doodleDividerComponent(motif string) { -
- switch motif { - case "croissant": - - case "cup": - - case "leaf": - - default: - - } -
-} diff --git a/doodle_divider_templ.go b/doodle_divider_templ.go deleted file mode 100644 index 0f35547..0000000 --- a/doodle_divider_templ.go +++ /dev/null @@ -1,82 +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" - -// doodleDividerComponent renders an inline SVG divider whose motif is -// selected by the editor. Each motif draws a distinct hand-drawn shape so -// they look visibly different even at thumbnail size. -func doodleDividerComponent(motif 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 - } - switch motif { - case "croissant": - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case "cup": - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case "leaf": - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - default: - 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/email_wrapper.templ b/email_wrapper.templ deleted file mode 100644 index cc578d3..0000000 --- a/email_wrapper.templ +++ /dev/null @@ -1,204 +0,0 @@ -package main - -import ( - "bytes" - "context" - "fmt" - - "git.dev.alexdunmow.com/block/core/templates" -) - -// CoffeeEmailWrapper renders a single-column 560px cream-and-espresso wrapper -// for transactional and newsletter emails. Table-only layout so it survives -// Outlook; doodle divider rendered inline as SVG so it survives email -// clients that strip styles. -func CoffeeEmailWrapper(body string, emailCtx templates.EmailContext) string { - var buf bytes.Buffer - _ = coffeeEmailTemplate(emailCtx, body).Render(context.Background(), &buf) - return buf.String() -} - -templ coffeeEmailTemplate(emailCtx templates.EmailContext, body string) { - - - - - - - - { emailCtx.SiteSettings.SiteName } - - - - if emailCtx.PreviewText != "" { -
- { emailCtx.PreviewText } -
- } - - - - -
- - - - - - - - - - - - - - -
- - -} - -// Coffee email color helpers — cream paper background, espresso ink, terracotta accent. -// EmailColors carries the resolved theme palette; we use Primary for the -// accent fallback because EmailColors has no dedicated Accent field. -func coffeeBgColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Background != "" { - return emailCtx.Colors.Background - } - return "#f4ece1" -} - -func coffeeCardColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Card != "" { - return emailCtx.Colors.Card - } - return "#ece1d0" -} - -func coffeeFgColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Foreground != "" { - return emailCtx.Colors.Foreground - } - return "#3d2a1a" -} - -func coffeePrimaryColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Primary != "" { - return emailCtx.Colors.Primary - } - return "#8a4a23" -} - -// coffeeAccentColor reuses Primary when no dedicated accent is in scope — -// EmailColors does not expose Accent; the resolved palette still applies via -// Primary which the CMS sets per-email. -func coffeeAccentColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Primary != "" { - return emailCtx.Colors.Primary - } - return "#c95b2f" -} - -func coffeeMutedFgColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.MutedForeground != "" { - return emailCtx.Colors.MutedForeground - } - return "#6b5440" -} - -func coffeeBorderColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Border != "" { - return emailCtx.Colors.Border - } - return "#c9b69e" -} diff --git a/email_wrapper_templ.go b/email_wrapper_templ.go deleted file mode 100644 index a53abbb..0000000 --- a/email_wrapper_templ.go +++ /dev/null @@ -1,432 +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 ( - "bytes" - "context" - "fmt" - - "git.dev.alexdunmow.com/block/core/templates" -) - -// CoffeeEmailWrapper renders a single-column 560px cream-and-espresso wrapper -// for transactional and newsletter emails. Table-only layout so it survives -// Outlook; doodle divider rendered inline as SVG so it survives email -// clients that strip styles. -func CoffeeEmailWrapper(body string, emailCtx templates.EmailContext) string { - var buf bytes.Buffer - _ = coffeeEmailTemplate(emailCtx, body).Render(context.Background(), &buf) - return buf.String() -} - -func coffeeEmailTemplate(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: 29, 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: 75, Col: 27} - } - _, 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.LogoURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"")") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else if emailCtx.SiteSettings.SiteName != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, 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: 88, Col: 43} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) - 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(body).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 - } - if emailCtx.SiteSettings.SiteName != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var16 string - templ_7745c5c3_Var16, 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: 120, Col: 46} - } - _, 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, 23, "

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

Pull up a seat. Pastries from 7, coffee until late.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if emailCtx.SiteSettings.SiteURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var19 string - templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(emailCtx.SiteSettings.SiteURL) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 127, Col: 46} - } - _, 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, 28, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if emailCtx.UnsubscribeURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "

Unsubscribe

") - 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 - } - return nil - }) -} - -// Coffee email color helpers — cream paper background, espresso ink, terracotta accent. -// EmailColors carries the resolved theme palette; we use Primary for the -// accent fallback because EmailColors has no dedicated Accent field. -func coffeeBgColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Background != "" { - return emailCtx.Colors.Background - } - return "#f4ece1" -} - -func coffeeCardColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Card != "" { - return emailCtx.Colors.Card - } - return "#ece1d0" -} - -func coffeeFgColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Foreground != "" { - return emailCtx.Colors.Foreground - } - return "#3d2a1a" -} - -func coffeePrimaryColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Primary != "" { - return emailCtx.Colors.Primary - } - return "#8a4a23" -} - -// coffeeAccentColor reuses Primary when no dedicated accent is in scope — -// EmailColors does not expose Accent; the resolved palette still applies via -// Primary which the CMS sets per-email. -func coffeeAccentColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Primary != "" { - return emailCtx.Colors.Primary - } - return "#c95b2f" -} - -func coffeeMutedFgColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.MutedForeground != "" { - return emailCtx.Colors.MutedForeground - } - return "#6b5440" -} - -func coffeeBorderColor(emailCtx templates.EmailContext) string { - if emailCtx.Colors.Border != "" { - return emailCtx.Colors.Border - } - return "#c9b69e" -} - -var _ = templruntime.GeneratedTemplate diff --git a/embed.go b/embed.go deleted file mode 100644 index d160f4e..0000000 --- a/embed.go +++ /dev/null @@ -1,66 +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. -func Assets() fs.FS { - sub, _ := fs.Sub(assetsFS, "assets") - return sub -} - -// Schemas returns the embedded schemas filesystem. -func Schemas() fs.FS { - sub, _ := fs.Sub(schemasFS, "schemas") - return sub -} - -// AssetsHandler returns an http.Handler that serves the embedded assets. -func AssetsHandler() http.Handler { - return http.FileServer(http.FS(Assets())) -} - -// ThemePresets returns the embedded theme presets JSON. -func ThemePresets() []byte { - return presetsData -} - -// BundledFonts returns the embedded fonts manifest JSON. -// Coffee ships fonts.json = [] per FONTS.md wave-1 policy; recommended fonts -// (Fraunces, Inter, JetBrains Mono) are documented in RECOMMENDED_FONTS.md. -func BundledFonts() []byte { - return fontsData -} - -// ThemeCSSManifest returns the additional CSS that Tailwind should include -// when this theme is active (paper texture, torn-edge mask, kraft-tag button, -// drop-cap, font-family variable fallbacks). -func ThemeCSSManifest() *plugin.CSSManifest { - css, err := assetsFS.ReadFile("assets/style.css") - if err != nil { - return &plugin.CSSManifest{} - } - return &plugin.CSSManifest{ - InputCSSAppend: string(css), - } -} diff --git a/featured_pour.go b/featured_pour.go deleted file mode 100644 index 2d8a701..0000000 --- a/featured_pour.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// FeaturedPourBlockMeta defines metadata for the featured_pour block. -var FeaturedPourBlockMeta = blocks.BlockMeta{ - Key: "featured_pour", - Title: "Featured Pour", - Description: "Hero card for a featured coffee, tea or pastry with tasting notes and price", - Source: "coffee", -} - -// FeaturedPourBlock renders a featured pour card. -// Content shape: {"name": "...", "tasting": "...rich text...", "image": "...", "price": "..."} -func FeaturedPourBlock(ctx context.Context, content map[string]any) string { - data := FeaturedPourData{ - Name: getString(content, "name"), - Tasting: getString(content, "tasting"), - Image: getString(content, "image"), - Price: getString(content, "price"), - } - - var buf bytes.Buffer - _ = featuredPourComponent(data).Render(ctx, &buf) - return buf.String() -} - -// FeaturedPourData holds the data for the component. -type FeaturedPourData struct { - Name string - Tasting string - Image string - Price string -} diff --git a/featured_pour.templ b/featured_pour.templ deleted file mode 100644 index 107edc5..0000000 --- a/featured_pour.templ +++ /dev/null @@ -1,36 +0,0 @@ -package main - -// featuredPourComponent renders the featured pour hero card. -templ featuredPourComponent(data FeaturedPourData) { -
-
- - Featured - -
- if data.Image != "" { - { - } else { -
- Add a hero image -
- } -
-
- if data.Name != "" { -

{ data.Name }

- } else { -

Featured pour

- } - if data.Tasting != "" { -
- @templ.Raw(data.Tasting) -
- } - if data.Price != "" { -
{ data.Price }
- } -
-
-
-} diff --git a/featured_pour_templ.go b/featured_pour_templ.go deleted file mode 100644 index 57b00b1..0000000 --- a/featured_pour_templ.go +++ /dev/null @@ -1,143 +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" - -// featuredPourComponent renders the featured pour hero card. -func featuredPourComponent(data FeaturedPourData) 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, "
Featured
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Image != "" { - 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, "
Add a hero image
") - 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 data.Name != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.Name) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `featured_pour.templ`, Line: 21, Col: 65} - } - _, 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 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

Featured pour

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if data.Tasting != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(data.Tasting).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 - } - } - if data.Price != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Price) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `featured_pour.templ`, Line: 31, Col: 57} - } - _, 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, 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 - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/footer.go b/footer.go deleted file mode 100644 index 2053f54..0000000 --- a/footer.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// FooterBlockMeta defines metadata for the Coffee footer block. -var FooterBlockMeta = blocks.BlockMeta{ - Key: "footer", - Title: "Footer", - Description: "Torn-edge footer with optional location summary and newsletter caption", - Source: "coffee", -} - -// FooterBlock renders the coffee footer. -// Content shape: {"showLocation": "true", "newsletterText": "..."} -func FooterBlock(ctx context.Context, content map[string]any) string { - data := FooterData{ - ShowLocation: getBool(content, "showLocation", true), - NewsletterText: getString(content, "newsletterText"), - } - - var buf bytes.Buffer - _ = footerComponent(data).Render(ctx, &buf) - return buf.String() -} - -// FooterData holds the data for the footer component. -type FooterData struct { - ShowLocation bool - NewsletterText string -} diff --git a/footer.templ b/footer.templ deleted file mode 100644 index 59c42cf..0000000 --- a/footer.templ +++ /dev/null @@ -1,37 +0,0 @@ -package main - -// footerComponent renders the kraft-paper footer with a torn top edge. -templ footerComponent(data FooterData) { -
-
-
-

Hello there

-

Pull up a seat. Pastries from 7, coffee until late.

-
- if data.ShowLocation { -
-

Visit

-
42 Roastery Lane -City, State 9000
-
- } -
-

Stay in touch

- if data.NewsletterText != "" { -

{ data.NewsletterText }

- } else { -

Slow notes from the bar. Brew tips, seasonal pours, no spam.

- } -
- - - -
-
-
-
- © Coffee theme — kraft paper edition. - Hand-drawn with care. -
-
-} diff --git a/footer_templ.go b/footer_templ.go deleted file mode 100644 index d052dc2..0000000 --- a/footer_templ.go +++ /dev/null @@ -1,79 +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" - -// footerComponent renders the kraft-paper footer with a torn top edge. -func footerComponent(data FooterData) 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, "

Hello there

Pull up a seat. Pastries from 7, coffee until late.

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

Visit

42 Roastery Lane City, State 9000
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

Stay in touch

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

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.NewsletterText) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer.templ`, Line: 21, Col: 72} - } - _, 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 - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "

Slow notes from the bar. Brew tips, seasonal pours, no spam.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
© Coffee theme — kraft paper edition. Hand-drawn with care.
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/go.mod b/go.mod deleted file mode 100644 index b3604c6..0000000 --- a/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module git.dev.alexdunmow.com/block/themes/coffee - -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 f7155b4..0000000 --- a/heading_override.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "bytes" - "context" - "strconv" -) - -// CoffeeHeadingBlock renders a heading with Coffee styling. -// Content shape: {"text": "...", "level": 1-6, "textClass": "..."} -func CoffeeHeadingBlock(ctx context.Context, content map[string]any) string { - text := getString(content, "text") - textClass := getString(content, "textClass") - level := parseHeadingLevel(content) - - var buf bytes.Buffer - _ = coffeeHeadingComponent(level, text, textClass).Render(ctx, &buf) - return buf.String() -} - -// parseHeadingLevel parses the heading level, defaulting to 2. -func parseHeadingLevel(content map[string]any) int { - if level, ok := content["level"].(float64); ok { - l := int(level) - if l >= 1 && l <= 6 { - return l - } - } - if level, ok := content["level"].(int); ok { - if level >= 1 && level <= 6 { - return level - } - } - if level, ok := content["level"].(string); ok { - if l, err := strconv.Atoi(level); 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 fd171f5..0000000 --- a/heading_override.templ +++ /dev/null @@ -1,48 +0,0 @@ -package main - -// coffeeHeadingBaseClass returns base Tailwind classes for each heading level. -func coffeeHeadingBaseClass(level int) string { - switch level { - case 1: - return "coffee-display text-5xl leading-tight" - case 2: - return "coffee-display text-3xl italic" - case 3: - return "coffee-display text-2xl" - case 4: - return "coffee-display text-xl" - case 5: - return "coffee-display text-lg" - case 6: - return "coffee-display text-base" - default: - return "coffee-display text-3xl" - } -} - -// coffeeHeadingComponent renders a heading with Coffee display styling and an -// optional doodle underline for h2+ levels. -templ coffeeHeadingComponent(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 aaea7e1..0000000 --- a/heading_override_templ.go +++ /dev/null @@ -1,312 +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" - -// coffeeHeadingBaseClass returns base Tailwind classes for each heading level. -func coffeeHeadingBaseClass(level int) string { - switch level { - case 1: - return "coffee-display text-5xl leading-tight" - case 2: - return "coffee-display text-3xl italic" - case 3: - return "coffee-display text-2xl" - case 4: - return "coffee-display text-xl" - case 5: - return "coffee-display text-lg" - case 6: - return "coffee-display text-base" - default: - return "coffee-display text-3xl" - } -} - -// coffeeHeadingComponent renders a heading with Coffee display styling and an -// optional doodle underline for h2+ levels. -func coffeeHeadingComponent(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{coffeeHeadingBaseClass(1), "text-primary", 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: 28, Col: 76} - } - _, 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{coffeeHeadingBaseClass(2), "text-primary", 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: 31, Col: 48} - } - _, 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{coffeeHeadingBaseClass(3), "text-primary", 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: 35, Col: 48} - } - _, 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{coffeeHeadingBaseClass(4), "text-primary", 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: 38, Col: 76} - } - _, 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{coffeeHeadingBaseClass(5), "text-primary", 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: 40, Col: 76} - } - _, 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{coffeeHeadingBaseClass(6), "text-primary", 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: 42, Col: 76} - } - _, 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{coffeeHeadingBaseClass(2), "text-primary", 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: 45, Col: 48} - } - _, 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 d936603..0000000 --- a/helpers.go +++ /dev/null @@ -1,91 +0,0 @@ -package main - -import ( - "strings" - "time" -) - -// getString extracts a string value from content map. -func getString(content map[string]any, key string) string { - if v, ok := content[key].(string); ok { - return v - } - return "" -} - -// getBool extracts a bool value from content map (handles string forms). -func getBool(content map[string]any, key string, defaultVal bool) bool { - if v, ok := content[key].(bool); ok { - return v - } - if v, ok := content[key].(string); ok { - switch strings.ToLower(v) { - case "true", "yes", "1": - return true - case "false", "no", "0": - return false - } - } - return defaultVal -} - -// getSlice extracts a slice of maps from content. -func getSlice(content map[string]any, key string) []map[string]any { - if v, ok := content[key].([]any); ok { - result := make([]map[string]any, 0, len(v)) - for _, item := range v { - if m, ok := item.(map[string]any); ok { - result = append(result, m) - } - } - return result - } - return nil -} - -// shortDayName returns the three-letter weekday abbreviation for "today" in -// the server's local time zone. Used by hours_strip to flag today's row -// server-side (no JS). -func shortDayName(now time.Time) string { - switch now.Weekday() { - case time.Monday: - return "Mon" - case time.Tuesday: - return "Tue" - case time.Wednesday: - return "Wed" - case time.Thursday: - return "Thu" - case time.Friday: - return "Fri" - case time.Saturday: - return "Sat" - case time.Sunday: - return "Sun" - } - return "" -} - -// normaliseDay accepts a free-form day string and returns the matching short -// name. This lets editors enter "Monday", "mon", or "Mon" and still get a -// reliable comparison against today. -func normaliseDay(day string) string { - d := strings.ToLower(strings.TrimSpace(day)) - switch { - case strings.HasPrefix(d, "mon"): - return "Mon" - case strings.HasPrefix(d, "tue"): - return "Tue" - case strings.HasPrefix(d, "wed"): - return "Wed" - case strings.HasPrefix(d, "thu"): - return "Thu" - case strings.HasPrefix(d, "fri"): - return "Fri" - case strings.HasPrefix(d, "sat"): - return "Sat" - case strings.HasPrefix(d, "sun"): - return "Sun" - } - return strings.TrimSpace(day) -} diff --git a/hours_strip.go b/hours_strip.go deleted file mode 100644 index c0c68ea..0000000 --- a/hours_strip.go +++ /dev/null @@ -1,73 +0,0 @@ -package main - -import ( - "bytes" - "context" - "time" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// HoursStripBlockMeta defines metadata for the hours_strip block. -var HoursStripBlockMeta = blocks.BlockMeta{ - Key: "hours_strip", - Title: "Hours Strip", - Description: "Weekly hours strip with today's row server-side highlighted", - Source: "coffee", -} - -// HoursStripBlock renders a weekly hours strip. -// Content shape: -// -// { -// "todayLabel": "Today", -// "hours": [ -// {"day": "Mon", "open": "7:00", "close": "15:00"}, ... -// ] -// } -// -// The "today" row is detected server-side by comparing each row's day to the -// current local weekday — no JS required. -func HoursStripBlock(ctx context.Context, content map[string]any) string { - todayLabel := getString(content, "todayLabel") - if todayLabel == "" { - todayLabel = "Today" - } - - today := shortDayName(time.Now()) - - rawHours := getSlice(content, "hours") - var rows []HoursRow - for _, h := range rawHours { - day := normaliseDay(getString(h, "day")) - rows = append(rows, HoursRow{ - Day: day, - Open: getString(h, "open"), - Close: getString(h, "close"), - IsToday: day != "" && day == today, - }) - } - - data := HoursStripData{ - TodayLabel: todayLabel, - Rows: rows, - } - - var buf bytes.Buffer - _ = hoursStripComponent(data).Render(ctx, &buf) - return buf.String() -} - -// HoursStripData contains data for the hours strip component. -type HoursStripData struct { - TodayLabel string - Rows []HoursRow -} - -// HoursRow represents one weekday's hours. -type HoursRow struct { - Day string - Open string - Close string - IsToday bool -} diff --git a/hours_strip.templ b/hours_strip.templ deleted file mode 100644 index 4a8407f..0000000 --- a/hours_strip.templ +++ /dev/null @@ -1,35 +0,0 @@ -package main - -// hoursStripComponent renders the hours strip with the today row highlighted. -templ hoursStripComponent(data HoursStripData) { - -} - -// todayClass returns the highlight class when this row is today's. -func todayClass(isToday bool) string { - if isToday { - return "coffee-hours-today is-today today" - } - return "" -} diff --git a/hours_strip_templ.go b/hours_strip_templ.go deleted file mode 100644 index 48b2814..0000000 --- a/hours_strip_templ.go +++ /dev/null @@ -1,152 +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" - -// hoursStripComponent renders the hours strip with the today row highlighted. -func hoursStripComponent(data HoursStripData) 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 - }) -} - -// todayClass returns the highlight class when this row is today's. -func todayClass(isToday bool) string { - if isToday { - return "coffee-hours-today is-today today" - } - return "" -} - -var _ = templruntime.GeneratedTemplate diff --git a/image_override.go b/image_override.go deleted file mode 100644 index 0cd5c22..0000000 --- a/image_override.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "bytes" - "context" -) - -// CoffeeImageBlock renders an image with the torn-edge frame and optional -// handwritten caption. -// Content shape: {"src": "...", "alt": "...", "caption": "..."} -func CoffeeImageBlock(ctx context.Context, content map[string]any) string { - src := getString(content, "src") - alt := getString(content, "alt") - caption := getString(content, "caption") - - var buf bytes.Buffer - _ = coffeeImageComponent(src, alt, caption).Render(ctx, &buf) - return buf.String() -} diff --git a/image_override.templ b/image_override.templ deleted file mode 100644 index 0190fd8..0000000 --- a/image_override.templ +++ /dev/null @@ -1,20 +0,0 @@ -package main - -// coffeeImageComponent renders an image with the torn-edge frame and an -// optional caption styled like a handwritten note. -templ coffeeImageComponent(src, alt, caption string) { -
-
- if src != "" { - { - } else { -
- Add an image to render the torn-edge frame. -
- } -
- if caption != "" { -
{ caption }
- } -
-} diff --git a/image_override_templ.go b/image_override_templ.go deleted file mode 100644 index 7577b45..0000000 --- a/image_override_templ.go +++ /dev/null @@ -1,106 +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" - -// coffeeImageComponent renders an image with the torn-edge frame and an -// optional caption styled like a handwritten note. -func coffeeImageComponent(src, alt, caption 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 - } - if src != "" { - 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, "
Add an image to render the torn-edge frame.
") - 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 caption != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(caption) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `image_override.templ`, Line: 17, Col: 101} - } - _, 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 - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/location_card.go b/location_card.go deleted file mode 100644 index d6e11a9..0000000 --- a/location_card.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// LocationCardBlockMeta defines metadata for the location_card block. -var LocationCardBlockMeta = blocks.BlockMeta{ - Key: "location_card", - Title: "Location Card", - Description: "Address card with optional static map image and doodled pin overlay", - Source: "coffee", -} - -// LocationCardBlock renders a location card. -// Content shape: {"address": "...", "mapImage": "...", "directionsUrl": "..."} -func LocationCardBlock(ctx context.Context, content map[string]any) string { - data := LocationCardData{ - Address: getString(content, "address"), - MapImage: getString(content, "mapImage"), - DirectionsURL: getString(content, "directionsUrl"), - } - - var buf bytes.Buffer - _ = locationCardComponent(data).Render(ctx, &buf) - return buf.String() -} - -// LocationCardData holds the data the template needs. -type LocationCardData struct { - Address string - MapImage string - DirectionsURL string -} diff --git a/location_card.templ b/location_card.templ deleted file mode 100644 index b4b8254..0000000 --- a/location_card.templ +++ /dev/null @@ -1,35 +0,0 @@ -package main - -// locationCardComponent renders a location card with doodled pin overlay. -templ locationCardComponent(data LocationCardData) { -
-
-
- if data.MapImage != "" { - Map of our location - } else { -
- Map preview -
- } - -
-
-

- Find us -

- if data.Address != "" { -
{ data.Address }
- } else { -

Add an address to render the location card.

- } - if data.DirectionsURL != "" { - Directions - } -
-
-
-} diff --git a/location_card_templ.go b/location_card_templ.go deleted file mode 100644 index dfdbdae..0000000 --- a/location_card_templ.go +++ /dev/null @@ -1,116 +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" - -// locationCardComponent renders a location card with doodled pin overlay. -func locationCardComponent(data LocationCardData) 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.MapImage != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"Map ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
Map preview
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

Find us

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if data.Address != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.Address) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `location_card.templ`, Line: 25, Col: 95} - } - _, 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, 7, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "

Add an address to render the location card.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if data.DirectionsURL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "Directions") - 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 - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/main.go b/main.go deleted file mode 100644 index 1e24bd9..0000000 --- a/main.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build wasip1 - -// Package main compiles the coffee 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..afe2102 --- /dev/null +++ b/manifest.yaml @@ -0,0 +1,195 @@ +# Coffee theme — codeless .bnp manifest (WO-WZ-021 Phase B1). +# 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: coffee + title: Coffee + description: "Warm, hand-crafted theme for cafes, bakeries, and slow-craft makers" + +page_templates: + - system: coffee + key: default + title: Default + description: "Header + main + footer with warm paper background" + slots: [header, main, footer] + - system: coffee + key: landing + title: Landing + description: "Hero pour + featured menu, big imagery" + slots: [hero, menu, story, cta, footer] + - system: coffee + key: article + title: Article + description: "Narrow narrative column for journal / recipes" + slots: [header, main, footer] + - system: coffee + key: full-width + title: Full Width + description: "Edge-to-edge gallery / interior shots" + slots: [header, main, footer] + +template_overrides: + - { template: coffee, block: heading } + - { template: coffee, block: text } + - { template: coffee, block: button } + - { template: coffee, block: image } + +email_wrappers: + - coffee + +css: + input_css_append: | + /* Coffee theme styles + * + * Uses the 19 shadcn-style HSL token CSS variables (--background, + * --foreground, --primary, --accent, --border, --muted, --card, ...) via + * `hsl(var(--token))`. Font families are resolved through the BlockNinja font + * variables (--font-heading, --font-body, --font-mono) with fallback stacks + * derived from the spec §3 typography list. + */ + + /* --- Font-family fallbacks --------------------------------------------- + * + * Templates use the variable form; the second argument is the fallback the + * site shows before the admin assigns fonts via the typography picker. + */ + :root { + --coffee-heading-fallback: "Fraunces", "Playfair Display", Georgia, "Times New Roman", serif; + --coffee-body-fallback: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --coffee-mono-fallback: "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace; + } + + /* --- Paper grain background -------------------------------------------- + * + * Inline SVG noise overlay applied as the body background. Keeps file size + * tiny and palette-neutral so it works with all three presets. + */ + body.coffee-paper { + background-color: hsl(var(--background)); + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'%3E%3Cfilter id='paper-grain'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.18 0 0 0 0 0.13 0 0 0 0 0.09 0 0 0 0.07 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23paper-grain)'/%3E%3C/svg%3E"); + background-repeat: repeat; + } + + /* --- Headings ----------------------------------------------------------- */ + .coffee-display { + font-family: var(--font-heading, var(--coffee-heading-fallback)); + font-feature-settings: "liga" 1, "dlig" 1; + letter-spacing: -0.01em; + } + + .coffee-body { + font-family: var(--font-body, var(--coffee-body-fallback)); + line-height: 1.65; + } + + .coffee-mono { + font-family: var(--font-mono, var(--coffee-mono-fallback)); + } + + /* --- Doodle underline (heading override) -------------------------------- */ + .coffee-doodle-underline { + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 12' preserveAspectRatio='none'%3E%3Cpath d='M2 8 Q 20 2 40 7 T 80 6 T 118 7' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' opacity='0.55'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: 100% 0.5em; + padding-bottom: 0.18em; + } + + /* --- Drop-cap (text override / article body) ---------------------------- */ + .coffee-dropcap > p:first-of-type::first-letter { + font-family: var(--font-heading, var(--coffee-heading-fallback)); + font-size: 4em; + line-height: 0.85; + float: left; + padding: 0.05em 0.12em 0 0; + color: hsl(var(--primary)); + } + + /* --- Kraft-tag button --------------------------------------------------- */ + .kraft-tag { + position: relative; + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.55rem 1.1rem; + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); + border: 1px solid hsl(var(--border)); + border-radius: 0.25rem; + font-family: var(--font-body, var(--coffee-body-fallback)); + font-weight: 500; + letter-spacing: 0.02em; + box-shadow: 0 1px 0 hsl(var(--border)); + transition: transform 120ms ease, box-shadow 120ms ease; + cursor: pointer; + } + + .kraft-tag:hover { + transform: rotate(-1.2deg); + box-shadow: 0 2px 0 hsl(var(--border)); + } + + .kraft-tag:focus-visible { + outline: 2px solid hsl(var(--ring)); + outline-offset: 3px; + } + + /* --- Torn-edge utility -------------------------------------------------- */ + .coffee-torn-top { + -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"); + mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-size: 100% 100%; + mask-size: 100% 100%; + } + + .coffee-torn-bottom { + -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E"); + mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E"); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + -webkit-mask-size: 100% 100%; + mask-size: 100% 100%; + } + + /* --- Coffee surfaces ---------------------------------------------------- */ + .coffee-card { + background-color: hsl(var(--card)); + color: hsl(var(--card-foreground)); + border: 1px solid hsl(var(--border)); + border-radius: 0.5rem; + } + + .coffee-frame { + border: 1px solid hsl(var(--border)); + background-color: hsl(var(--card)); + } + + .coffee-pencil-rule { + border-color: hsl(var(--border)); + border-style: solid; + } + + /* --- Today highlight ---------------------------------------------------- */ + .coffee-hours-today { + background-color: hsl(var(--accent) / 0.15); + color: hsl(var(--accent-foreground)); + border-left: 3px solid hsl(var(--accent)); + padding-left: 0.75rem; + } + + /* --- Price typography --------------------------------------------------- */ + .coffee-price { + font-family: var(--font-mono, var(--coffee-mono-fallback)); + font-variant-numeric: tabular-nums; + color: hsl(var(--accent)); + } + + /* --- Doodle pin overlay for location card ------------------------------- */ + .coffee-pin { + color: hsl(var(--accent)); + } diff --git a/master_pages.go b/master_pages.go deleted file mode 100644 index da02aae..0000000 --- a/master_pages.go +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import "git.dev.alexdunmow.com/block/core/plugin" - -// DefaultMasterPages returns the default master pages the Coffee theme seeds. -// Spec §7. Two masters: default-master (default + article templates) and -// landing-master (landing template only). -func DefaultMasterPages() []plugin.MasterPageDefinition { - return []plugin.MasterPageDefinition{ - { - Key: "coffee:default-master", - Title: "Coffee Default Master", - PageTemplates: []string{"default", "article"}, - Blocks: []plugin.MasterPageBlock{ - { - BlockKey: "navbar", - Title: "Main Navigation", - Content: map[string]any{"menuName": "main"}, - Slot: "header", - SortOrder: 0, - }, - { - BlockKey: "coffee:hours_strip", - Title: "Hours Strip", - Content: map[string]any{"todayLabel": "Today"}, - Slot: "header", - SortOrder: 1, - }, - { - BlockKey: "slot", - Title: "Main Content", - Content: map[string]any{"slotName": "main", "placeholder": "Pour something in here"}, - Slot: "main", - SortOrder: 0, - }, - { - BlockKey: "coffee:footer", - Title: "Site Footer", - Content: map[string]any{"showLocation": true}, - Slot: "footer", - SortOrder: 0, - }, - }, - }, - { - Key: "coffee:landing-master", - Title: "Coffee Landing Master", - PageTemplates: []string{"landing"}, - Blocks: []plugin.MasterPageBlock{ - { - BlockKey: "navbar", - Title: "Main Navigation", - Content: map[string]any{"menuName": "main"}, - Slot: "header", - SortOrder: 0, - }, - { - BlockKey: "slot", - Title: "Hero Slot", - Content: map[string]any{"slotName": "hero", "placeholder": "Drop a hero block"}, - Slot: "hero", - SortOrder: 0, - }, - { - BlockKey: "coffee:featured_pour", - Title: "Featured Pour", - Content: map[string]any{}, - Slot: "menu", - SortOrder: 0, - }, - { - BlockKey: "slot", - Title: "Story Slot", - Content: map[string]any{"slotName": "story", "placeholder": "Tell the story"}, - Slot: "story", - SortOrder: 0, - }, - { - BlockKey: "coffee:location_card", - Title: "Location Card", - Content: map[string]any{}, - Slot: "cta", - SortOrder: 0, - }, - { - BlockKey: "coffee:footer", - Title: "Site Footer", - Content: map[string]any{"showLocation": true}, - Slot: "footer", - SortOrder: 0, - }, - }, - }, - } -} diff --git a/master_pages.json b/master_pages.json new file mode 100644 index 0000000..74349ff --- /dev/null +++ b/master_pages.json @@ -0,0 +1,26 @@ +[ + { + "key": "coffee:default-master", + "title": "Coffee Default Master", + "page_templates": ["default", "article"], + "blocks": [ + { "block_key": "navbar", "title": "Main Navigation", "content": { "menuName": "main" }, "slot": "header", "sort_order": 0 }, + { "block_key": "coffee:hours_strip", "title": "Hours Strip", "content": { "todayLabel": "Today" }, "slot": "header", "sort_order": 1 }, + { "block_key": "slot", "title": "Main Content", "content": { "slotName": "main", "placeholder": "Pour something in here" }, "slot": "main", "sort_order": 0 }, + { "block_key": "coffee:footer", "title": "Site Footer", "content": { "showLocation": true }, "slot": "footer", "sort_order": 0 } + ] + }, + { + "key": "coffee:landing-master", + "title": "Coffee Landing Master", + "page_templates": ["landing"], + "blocks": [ + { "block_key": "navbar", "title": "Main Navigation", "content": { "menuName": "main" }, "slot": "header", "sort_order": 0 }, + { "block_key": "slot", "title": "Hero Slot", "content": { "slotName": "hero", "placeholder": "Drop a hero block" }, "slot": "hero", "sort_order": 0 }, + { "block_key": "coffee:featured_pour", "title": "Featured Pour", "content": {}, "slot": "menu", "sort_order": 0 }, + { "block_key": "slot", "title": "Story Slot", "content": { "slotName": "story", "placeholder": "Tell the story" }, "slot": "story", "sort_order": 0 }, + { "block_key": "coffee:location_card", "title": "Location Card", "content": {}, "slot": "cta", "sort_order": 0 }, + { "block_key": "coffee:footer", "title": "Site Footer", "content": { "showLocation": true }, "slot": "footer", "sort_order": 0 } + ] + } +] diff --git a/menu_board.go b/menu_board.go deleted file mode 100644 index eda2458..0000000 --- a/menu_board.go +++ /dev/null @@ -1,82 +0,0 @@ -package main - -import ( - "bytes" - "context" - - "git.dev.alexdunmow.com/block/core/blocks" -) - -// MenuBoardBlockMeta defines metadata for the menu_board block. -var MenuBoardBlockMeta = blocks.BlockMeta{ - Key: "menu_board", - Title: "Menu Board", - Description: "Kraft-paper menu with sections of items (espresso, filter, pastry, ...)", - Source: "coffee", -} - -// MenuBoardBlock renders a sectioned menu card. -// Content shape: -// -// { -// "title": "Menu", -// "sections": [ -// {"name": "Espresso", "items": [ -// {"name": "Flat White", "price": "5.50", "note": "...", "allergens": "..."} -// ]} -// ] -// } -func MenuBoardBlock(ctx context.Context, content map[string]any) string { - title := getString(content, "title") - if title == "" { - title = "Menu" - } - - rawSections := getSlice(content, "sections") - var sections []MenuSection - for _, s := range rawSections { - rawItems := getSlice(s, "items") - var items []MenuItem - for _, it := range rawItems { - items = append(items, MenuItem{ - Name: getString(it, "name"), - Price: getString(it, "price"), - Note: getString(it, "note"), - Allergens: getString(it, "allergens"), - }) - } - sections = append(sections, MenuSection{ - Name: getString(s, "name"), - Items: items, - }) - } - - data := MenuBoardData{ - Title: title, - Sections: sections, - } - - var buf bytes.Buffer - _ = menuBoardComponent(data).Render(ctx, &buf) - return buf.String() -} - -// MenuBoardData contains data for the menu board component. -type MenuBoardData struct { - Title string - Sections []MenuSection -} - -// MenuSection groups a list of items under a heading. -type MenuSection struct { - Name string - Items []MenuItem -} - -// MenuItem represents a single menu line. -type MenuItem struct { - Name string - Price string - Note string - Allergens string -} diff --git a/menu_board.templ b/menu_board.templ deleted file mode 100644 index 9a373c6..0000000 --- a/menu_board.templ +++ /dev/null @@ -1,54 +0,0 @@ -package main - -// menuBoardComponent renders a Coffee-styled menu board. -templ menuBoardComponent(data MenuBoardData) { -
-
- if data.Title != "" { -

- { data.Title } -

- } - if len(data.Sections) == 0 { -

Add a section to get started.

- } - for sIdx, section := range data.Sections { -
- if section.Name != "" { -

{ section.Name }

- } - if len(section.Items) == 0 { -

No items yet.

- } -
    - for _, item := range section.Items { -
  • -
    -
    { item.Name }
    - if item.Note != "" { -
    { item.Note }
    - } - if item.Allergens != "" { -
    Allergens: { item.Allergens }
    - } -
    - if item.Price != "" { -
    { item.Price }
    - } -
  • - } -
-
- } -
-
-} - -// menuSectionClass returns the CSS class for a section, leaving the first -// section without a top margin and adding spacing between later sections. -func menuSectionClass(idx int) string { - if idx == 0 { - return "mb-6" - } - return "mt-8 mb-6" -} diff --git a/menu_board_templ.go b/menu_board_templ.go deleted file mode 100644 index 7d9ec4b..0000000 --- a/menu_board_templ.go +++ /dev/null @@ -1,220 +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" - -// menuBoardComponent renders a Coffee-styled menu board. -func menuBoardComponent(data MenuBoardData) 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.Title != "" { - 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(data.Title) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `menu_board.templ`, Line: 9, Col: 55} - } - _, 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 - } - } - if len(data.Sections) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

Add a section to get started.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - for sIdx, section := range data.Sections { - var templ_7745c5c3_Var3 = []any{menuSectionClass(sIdx)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...) - 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 section.Name != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(section.Name) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `menu_board.templ`, Line: 18, Col: 73} - } - _, 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, 8, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if len(section.Items) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

No items yet.

") - 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 - } - for _, item := range section.Items { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
  • ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `menu_board.templ`, Line: 27, Col: 73} - } - _, 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, 12, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if item.Note != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.Note) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `menu_board.templ`, Line: 29, Col: 76} - } - _, 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, 14, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if item.Allergens != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
    Allergens: ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(item.Allergens) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `menu_board.templ`, Line: 32, Col: 99} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - 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 = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if item.Price != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(item.Price) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `menu_board.templ`, Line: 36, Col: 81} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) - 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 - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
  • ") - 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 = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// menuSectionClass returns the CSS class for a section, leaving the first -// section without a top margin and adding spacing between later sections. -func menuSectionClass(idx int) string { - if idx == 0 { - return "mb-6" - } - return "mt-8 mb-6" -} - -var _ = templruntime.GeneratedTemplate diff --git a/plugin.mod b/plugin.mod index 8de0a9c..99a6283 100644 --- a/plugin.mod +++ b/plugin.mod @@ -2,11 +2,8 @@ name = "coffee" display_name = "Coffee" scope = "@themes" -version = "0.1.2" +version = "0.2.0" description = "Warm, hand-crafted theme for cafes, bakeries, and slow-craft makers — kraft paper, doodle illustrations, and roasted browns." kind = "theme" categories = ["templates"] tags = ["warm", "hospitality", "cafe", "bakery", "food", "handcraft", "organic", "artisan", "menu"] - -[compatibility] -block_core = ">=0.15.0 <0.16.0" diff --git a/register.go b/register.go deleted file mode 100644 index 7519d30..0000000 --- a/register.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( - "context" - - "github.com/a-h/templ" - - "git.dev.alexdunmow.com/block/core/blocks" - "git.dev.alexdunmow.com/block/core/templates" -) - -// wrap adapts a templ-returning render function to templates.TemplateFunc. -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 is the plugin entry point that wires Coffee's system template, -// page templates, blocks, overrides, and email wrapper. -func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error { - // 1. System template ---------------------------------------------------- - tr.RegisterSystemTemplate(templates.SystemTemplateMeta{ - Key: "coffee", - Title: "Coffee", - Description: "Warm, hand-crafted theme for cafes, bakeries, and slow-craft makers", - }) - - // 2. Page templates ----------------------------------------------------- - if err := tr.RegisterPageTemplate("coffee", templates.PageTemplateMeta{ - Key: "default", - Title: "Default", - Description: "Header + main + footer with warm paper background", - Slots: []string{"header", "main", "footer"}, - }, wrap(RenderCoffee)); err != nil { - return err - } - - if err := tr.RegisterPageTemplate("coffee", templates.PageTemplateMeta{ - Key: "landing", - Title: "Landing", - Description: "Hero pour + featured menu, big imagery", - Slots: []string{"hero", "menu", "story", "cta", "footer"}, - }, wrap(RenderCoffeeLanding)); err != nil { - return err - } - - if err := tr.RegisterPageTemplate("coffee", templates.PageTemplateMeta{ - Key: "article", - Title: "Article", - Description: "Narrow narrative column for journal / recipes", - Slots: []string{"header", "main", "footer"}, - }, wrap(RenderCoffeeArticle)); err != nil { - return err - } - - if err := tr.RegisterPageTemplate("coffee", templates.PageTemplateMeta{ - Key: "full-width", - Title: "Full Width", - Description: "Edge-to-edge gallery / interior shots", - Slots: []string{"header", "main", "footer"}, - }, wrap(RenderCoffeeFullWidth)); err != nil { - return err - } - - // 3. Schemas — MUST be loaded BEFORE br.Register -------------------------- - if err := br.LoadSchemasFromFS(Schemas()); err != nil { - return err - } - - // 4. Theme-specific blocks (registered unqualified; addressed as coffee:) - br.Register(MenuBoardBlockMeta, MenuBoardBlock) - br.Register(HoursStripBlockMeta, HoursStripBlock) - br.Register(LocationCardBlockMeta, LocationCardBlock) - br.Register(FeaturedPourBlockMeta, FeaturedPourBlock) - br.Register(FooterBlockMeta, FooterBlock) - br.Register(DoodleDividerBlockMeta, DoodleDividerBlock) - - // 5. Built-in block overrides — only active when Coffee is the system template - br.RegisterTemplateOverride("coffee", "heading", CoffeeHeadingBlock) - br.RegisterTemplateOverride("coffee", "text", CoffeeTextBlock) - br.RegisterTemplateOverride("coffee", "button", CoffeeButtonBlock) - br.RegisterTemplateOverride("coffee", "image", CoffeeImageBlock) - - // 6. Email wrapper ------------------------------------------------------ - tr.RegisterEmailWrapper("coffee", CoffeeEmailWrapper) - - return nil -} diff --git a/registration.go b/registration.go deleted file mode 100644 index 4e4067a..0000000 --- a/registration.go +++ /dev/null @@ -1,25 +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 Coffee theme. -var Registration = plugin.PluginRegistration{ - Name: "coffee", - 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 8770a12..0000000 --- a/template.templ +++ /dev/null @@ -1,257 +0,0 @@ -package main - -import ( - "context" - - "git.dev.alexdunmow.com/block/core/templates/bn" -) - -// PageData carries everything the Coffee page templates need to render. -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 parseCoffeePageData(doc map[string]any) PageData { - title := "Untitled" - if t, ok := doc["title"].(string); ok { - title = t - } - - slots := make(map[string]string) - if s, ok := doc["slots"].(map[string]string); ok { - slots = s - } - - 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 - } - - themeMode := "light" - if tm, ok := doc["theme_mode"].(string); ok && tm != "" { - themeMode = tm - } - - siteSettings := bn.ParseSiteSettings(doc) - pageMeta := bn.ParsePageMeta(doc) - engagementConfig := bn.ParseEngagementConfig(doc) - - return PageData{ - Title: title, - Slots: slots, - ThemeMode: themeMode, - ThemeCSS: themeCSS, - SiteSettings: siteSettings, - PageMeta: pageMeta, - StructuredData: structuredData, - CSSHash: cssHash, - PageviewNonce: pageviewNonce, - EngagementConfig: engagementConfig, - } -} - -// Default page template (header / main / footer) -templ Coffee(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/coffee/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 { -
-

Pour something in here.

-
- } -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// Landing page template with hero / menu / story / cta / footer slots. -templ CoffeeLanding(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/coffee/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["menu"]) -
-
-
-
- @templ.Raw(data.Slots["story"]) -
-
-
-
- @templ.Raw(data.Slots["cta"]) -
-
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// Article page template — narrow narrative column for journal / recipes. -templ CoffeeArticle(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/coffee/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 { -
-

Write something honest here.

-
- } -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// Full-width page template — edge-to-edge gallery / interior shots. -templ CoffeeFullWidth(data PageData) { - - - @bn.Head(bn.HeadData{ - Title: data.Title, - Settings: data.SiteSettings, - PageMeta: data.PageMeta, - ThemeMode: data.ThemeMode, - ThemeCSS: data.ThemeCSS, - PluginStyles: []string{"/templates/coffee/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 { -
-

Add a gallery, a wide photo, a confession.

-
- } -
-
- @templ.Raw(data.Slots["footer"]) -
- @bn.BodyEnd(data.SiteSettings) - - -} - -// RenderCoffee is the default page renderer. -func RenderCoffee(ctx context.Context, doc map[string]any) templ.Component { - return Coffee(parseCoffeePageData(doc)) -} - -// RenderCoffeeLanding renders the landing page template. -func RenderCoffeeLanding(ctx context.Context, doc map[string]any) templ.Component { - return CoffeeLanding(parseCoffeePageData(doc)) -} - -// RenderCoffeeArticle renders the article page template. -func RenderCoffeeArticle(ctx context.Context, doc map[string]any) templ.Component { - return CoffeeArticle(parseCoffeePageData(doc)) -} - -// RenderCoffeeFullWidth renders the full-width page template. -func RenderCoffeeFullWidth(ctx context.Context, doc map[string]any) templ.Component { - return CoffeeFullWidth(parseCoffeePageData(doc)) -} diff --git a/template_templ.go b/template_templ.go deleted file mode 100644 index 2059289..0000000 --- a/template_templ.go +++ /dev/null @@ -1,506 +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 carries everything the Coffee page templates need to render. -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 parseCoffeePageData(doc map[string]any) PageData { - title := "Untitled" - if t, ok := doc["title"].(string); ok { - title = t - } - - slots := make(map[string]string) - if s, ok := doc["slots"].(map[string]string); ok { - slots = s - } - - 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 - } - - themeMode := "light" - if tm, ok := doc["theme_mode"].(string); ok && tm != "" { - themeMode = tm - } - - siteSettings := bn.ParseSiteSettings(doc) - pageMeta := bn.ParsePageMeta(doc) - engagementConfig := bn.ParseEngagementConfig(doc) - - return PageData{ - Title: title, - Slots: slots, - ThemeMode: themeMode, - ThemeCSS: themeCSS, - SiteSettings: siteSettings, - PageMeta: pageMeta, - StructuredData: structuredData, - CSSHash: cssHash, - PageviewNonce: pageviewNonce, - EngagementConfig: engagementConfig, - } -} - -// Default page template (header / main / footer) -func Coffee(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/coffee/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, "

Pour something in here.

") - 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 with hero / menu / story / cta / footer slots. -func CoffeeLanding(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/coffee/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["menu"]).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 - } - templ_7745c5c3_Err = templ.Raw(data.Slots["story"]).Render(ctx, templ_7745c5c3_Buffer) - 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 = 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, 15, "
") - 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, 16, "
") - 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, 17, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// Article page template — narrow narrative column for journal / recipes. -func CoffeeArticle(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, 18, "") - 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/coffee/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, 19, "") - 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, 20, "
") - 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, 21, "
") - 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, 22, "
") - 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, 23, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "

Write something honest here.

") - 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 - } - 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, 26, "
") - 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, 27, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// Full-width page template — edge-to-edge gallery / interior shots. -func CoffeeFullWidth(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, 28, "") - 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/coffee/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, 29, "") - 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, 30, "
") - 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, 31, "
") - 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, 32, "

Add a gallery, a wide photo, a confession.

") - 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["footer"]).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 - } - 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, 35, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -// RenderCoffee is the default page renderer. -func RenderCoffee(ctx context.Context, doc map[string]any) templ.Component { - return Coffee(parseCoffeePageData(doc)) -} - -// RenderCoffeeLanding renders the landing page template. -func RenderCoffeeLanding(ctx context.Context, doc map[string]any) templ.Component { - return CoffeeLanding(parseCoffeePageData(doc)) -} - -// RenderCoffeeArticle renders the article page template. -func RenderCoffeeArticle(ctx context.Context, doc map[string]any) templ.Component { - return CoffeeArticle(parseCoffeePageData(doc)) -} - -// RenderCoffeeFullWidth renders the full-width page template. -func RenderCoffeeFullWidth(ctx context.Context, doc map[string]any) templ.Component { - return CoffeeFullWidth(parseCoffeePageData(doc)) -} - -var _ = templruntime.GeneratedTemplate diff --git a/templates/coffee/article.ninjatpl b/templates/coffee/article.ninjatpl new file mode 100644 index 0000000..9214286 --- /dev/null +++ b/templates/coffee/article.ninjatpl @@ -0,0 +1,15 @@ + + +{{ head_html|safe }} + + {{ admin_banner_html|safe }} +
+
{{ slots.header|safe }}
+
+
+ {% if slots.main %}
{{ slots.main|safe }}
{% else %}

Write something honest here.

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

Pour something in here.

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

Add a gallery, a wide photo, a confession.

{% endif %} +
+
{{ slots.footer|safe }}
+ {{ body_end_html|safe }} + + diff --git a/templates/coffee/landing.ninjatpl b/templates/coffee/landing.ninjatpl new file mode 100644 index 0000000..3e19c1b --- /dev/null +++ b/templates/coffee/landing.ninjatpl @@ -0,0 +1,19 @@ + + +{{ head_html|safe }} + + {{ admin_banner_html|safe }} +
{{ slots.hero|safe }}
+
+
{{ slots.menu|safe }}
+
+
+
{{ slots.story|safe }}
+
+
+
{{ slots.cta|safe }}
+
+
{{ slots.footer|safe }}
+ {{ body_end_html|safe }} + + diff --git a/templates/email/coffee.ninjatpl b/templates/email/coffee.ninjatpl new file mode 100644 index 0000000..5bb7449 --- /dev/null +++ b/templates/email/coffee.ninjatpl @@ -0,0 +1,99 @@ + + + + + + + + {{ site_name }} + + + + {% if preview_text %}
{{ preview_text }}
{% endif %} + + + + +
+ + + + + + + + + + + + + + +
+ + diff --git a/templates/overrides/coffee/button.ninjatpl b/templates/overrides/coffee/button.ninjatpl new file mode 100644 index 0000000..5747e56 --- /dev/null +++ b/templates/overrides/coffee/button.ninjatpl @@ -0,0 +1 @@ +{% if url %}{{ text }}{% else %}{% endif %} diff --git a/templates/overrides/coffee/heading.ninjatpl b/templates/overrides/coffee/heading.ninjatpl new file mode 100644 index 0000000..c1e1f92 --- /dev/null +++ b/templates/overrides/coffee/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/coffee/image.ninjatpl b/templates/overrides/coffee/image.ninjatpl new file mode 100644 index 0000000..1040ab1 --- /dev/null +++ b/templates/overrides/coffee/image.ninjatpl @@ -0,0 +1,6 @@ +
+
+ {% if src %}{{ alt }}{% else %}
Add an image to render the torn-edge frame.
{% endif %} +
+ {% if caption %}
{{ caption }}
{% endif %} +
diff --git a/templates/overrides/coffee/text.ninjatpl b/templates/overrides/coffee/text.ninjatpl new file mode 100644 index 0000000..a6a268a --- /dev/null +++ b/templates/overrides/coffee/text.ninjatpl @@ -0,0 +1 @@ +
{{ text|safe }}
diff --git a/text_override.go b/text_override.go deleted file mode 100644 index 78dde08..0000000 --- a/text_override.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "bytes" - "context" -) - -// CoffeeTextBlock renders rich text with Coffee body styling and the optional -// drop-cap utility on the first paragraph. -func CoffeeTextBlock(ctx context.Context, content map[string]any) string { - text := getString(content, "text") - class := getString(content, "class") - - var buf bytes.Buffer - _ = coffeeTextComponent(text, class).Render(ctx, &buf) - return buf.String() -} diff --git a/text_override.templ b/text_override.templ deleted file mode 100644 index 5ec33cb..0000000 --- a/text_override.templ +++ /dev/null @@ -1,8 +0,0 @@ -package main - -// coffeeTextComponent renders text with a longer measure and drop-cap utility. -templ coffeeTextComponent(text, class string) { -
- @templ.Raw(text) -
-} diff --git a/text_override_templ.go b/text_override_templ.go deleted file mode 100644 index bce7539..0000000 --- a/text_override_templ.go +++ /dev/null @@ -1,67 +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" - -// coffeeTextComponent renders text with a longer measure and drop-cap utility. -func coffeeTextComponent(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{"coffee-body coffee-dropcap prose max-w-prose text-foreground", 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