feat: convert to codeless .bnp — templates + manifest, Go/templ deleted (WO-WZ-021)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b32e3f143a
commit
8ea1477d37
40
Makefile
40
Makefile
@ -1,26 +1,27 @@
|
|||||||
# cyberpunk — build & publish helpers (wasm .bnp workflow)
|
# cyberpunk — build & publish helpers (CODELESS .bnp workflow, WO-WZ-021)
|
||||||
#
|
#
|
||||||
# The theme compiles to a wasip1 reactor-mode wasm module packed into a .bnp
|
# This theme is a CODELESS .bnp: pure declaration the host runs — blocks
|
||||||
# artifact (`ninja plugin build`). The legacy .so path is retired (WO-WZ-015):
|
# (blocks/blocks.yaml + .ninjatpl), page/system templates, template overrides,
|
||||||
# the CMS is wasm-native and can no longer load .so plugins. Distribution is
|
# an email wrapper, master pages, presets, fonts and CSS in manifest.yaml. No
|
||||||
# publish-to-registry -> InstallFromRegistry (hot-load, no restart).
|
# 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:
|
# Usage:
|
||||||
# make build # compile wasm + pack cyberpunk-<version>.bnp
|
# make build # pack cyberpunk-<version>.bnp (codeless — no wasm)
|
||||||
# make verify # validate the built .bnp (layout/abi/name/size)
|
# make verify # validate the built .bnp (loader-identical checks)
|
||||||
# make archive-check # prove a clean `git archive HEAD` compiles to wasm
|
# make archive-check # prove a clean `git archive HEAD` still builds codeless
|
||||||
# make publish # ninja plugin publish --bnp (to the active registry)
|
# make publish # ninja plugin publish --bnp (to the active registry)
|
||||||
# make templ # regenerate templ Go files
|
|
||||||
# make clean # remove build artefacts
|
# make clean # remove build artefacts
|
||||||
|
|
||||||
.PHONY: build verify archive-check publish templ clean help
|
.PHONY: build verify archive-check publish clean help
|
||||||
|
|
||||||
PLUGIN_NAME := cyberpunk
|
PLUGIN_NAME := cyberpunk
|
||||||
NINJA := ninja
|
NINJA := ninja
|
||||||
BNP := $(PLUGIN_NAME)-$(shell grep '^version' plugin.mod | sed 's/.*"\(.*\)"/\1/').bnp
|
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,
|
# Pack the codeless .bnp (manifest.pb synthesized from plugin.mod + manifest.yaml
|
||||||
# tar.zst of plugin.wasm + plugin.mod + manifest.pb + schemas/ + assets/).
|
# + blocks/ + templates/; no wasm compile, no DESCRIBE probe).
|
||||||
build:
|
build:
|
||||||
$(NINJA) plugin build --dir .
|
$(NINJA) plugin build --dir .
|
||||||
|
|
||||||
@ -28,12 +29,12 @@ build:
|
|||||||
verify:
|
verify:
|
||||||
$(NINJA) plugin verify $(BNP)
|
$(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:
|
archive-check:
|
||||||
@T=$$(mktemp -d /tmp/archive-check-$(PLUGIN_NAME).XXXXXX) && \
|
@T=$$(mktemp -d /tmp/archive-check-$(PLUGIN_NAME).XXXXXX) && \
|
||||||
trap 'rm -rf "$$T"' EXIT && \
|
trap 'rm -rf "$$T"' EXIT && \
|
||||||
git archive HEAD | tar -x -C "$$T" && \
|
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"
|
echo "archive-check OK"
|
||||||
|
|
||||||
# Publish the prebuilt .bnp to the active registry.
|
# Publish the prebuilt .bnp to the active registry.
|
||||||
@ -41,19 +42,14 @@ archive-check:
|
|||||||
publish: build
|
publish: build
|
||||||
$(NINJA) plugin publish --bnp $(BNP)
|
$(NINJA) plugin publish --bnp $(BNP)
|
||||||
|
|
||||||
# Regenerate templ Go files locally.
|
|
||||||
templ:
|
|
||||||
templ generate
|
|
||||||
|
|
||||||
# Remove build artefacts.
|
# Remove build artefacts.
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PLUGIN_NAME)-*.bnp $(PLUGIN_NAME).so plugin.wasm
|
rm -f $(PLUGIN_NAME)-*.bnp plugin.wasm
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "Targets:"
|
@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 " 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 " publish Publish the .bnp to the active registry"
|
||||||
@echo " templ Regenerate templ Go files"
|
|
||||||
@echo " clean Remove build artefacts"
|
@echo " clean Remove build artefacts"
|
||||||
|
|||||||
48
blocks/blocks.yaml
Normal file
48
blocks/blocks.yaml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Cyberpunk theme block definitions (codeless .bnp, WO-WZ-021).
|
||||||
|
# Keys are fully qualified (cyberpunk:<key>) 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: cyberpunk:hero_glitch
|
||||||
|
title: Glitch Hero
|
||||||
|
description: RGB-split H1, neon CTA, optional scanline overlay toggle.
|
||||||
|
category: layout
|
||||||
|
schema: hero_glitch.schema.json
|
||||||
|
template: hero_glitch.ninjatpl
|
||||||
|
- key: cyberpunk:cta_terminal
|
||||||
|
title: Terminal CTA
|
||||||
|
description: Faux $ prompt with blinking caret and copy button.
|
||||||
|
category: layout
|
||||||
|
schema: cta_terminal.schema.json
|
||||||
|
template: cta_terminal.ninjatpl
|
||||||
|
- key: cyberpunk:navbar_terminal
|
||||||
|
title: Terminal Navbar
|
||||||
|
description: Mono-spaced navbar with $ command prefix and optional status dot.
|
||||||
|
category: navigation
|
||||||
|
schema: navbar_terminal.schema.json
|
||||||
|
template: navbar_terminal.ninjatpl
|
||||||
|
- key: cyberpunk:footer_grid
|
||||||
|
title: Grid Footer
|
||||||
|
description: Mono columns, build-hash + uptime status pill.
|
||||||
|
category: navigation
|
||||||
|
schema: footer_grid.schema.json
|
||||||
|
template: footer_grid.ninjatpl
|
||||||
|
- key: cyberpunk:feature_card_neon
|
||||||
|
title: Neon Feature Card
|
||||||
|
description: Single feature card with per-card neon edge glow (magenta/cyan/lime).
|
||||||
|
category: layout
|
||||||
|
schema: feature_card_neon.schema.json
|
||||||
|
template: feature_card_neon.ninjatpl
|
||||||
|
- key: cyberpunk:stats_glow
|
||||||
|
title: Glow Stats
|
||||||
|
description: Big mono numerals with neon accent underline.
|
||||||
|
category: display
|
||||||
|
schema: stats_glow.schema.json
|
||||||
|
template: stats_glow.ninjatpl
|
||||||
|
- key: cyberpunk:code_neon
|
||||||
|
title: Code Block
|
||||||
|
description: Server-rendered code block with neon edge and optional copy button.
|
||||||
|
category: content
|
||||||
|
schema: code_neon.schema.json
|
||||||
|
template: code_neon.ninjatpl
|
||||||
1
blocks/code_neon.ninjatpl
Normal file
1
blocks/code_neon.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<figure data-block="cyberpunk:code_neon" class="cyberpunk-code w-full my-6 rounded-lg overflow-hidden neon-edge-magenta" style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground));"><figcaption class="flex items-center justify-between px-4 py-2 cyberpunk-mono text-xs uppercase tracking-widest" style="background-color: hsl(var(--secondary)); color: hsl(var(--muted-foreground));"><span>{{ language|default:'text' }}</span>{% if copy != false and copy != "false" and copy != "off" and copy != "no" and copy != "0" and copy != "" %} <button type="button" class="cyberpunk-code-copy cyberpunk-mono uppercase tracking-widest px-2 py-1 rounded" style="border: 1px solid hsl(var(--border)); color: hsl(var(--accent));" data-copy="{{ code }}">COPY</button>{% endif %}</figcaption><pre class="cyberpunk-mono overflow-x-auto p-4 text-sm leading-relaxed" style="background-color: hsl(var(--background)); color: hsl(var(--foreground)); font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);"><code class="language-{{ language|default:'text' }}">{{ code }}</code></pre></figure>
|
||||||
1
blocks/cta_terminal.ninjatpl
Normal file
1
blocks/cta_terminal.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section data-block="cyberpunk:cta_terminal" class="cyberpunk-cta-terminal w-full py-16" style="background-color: hsl(var(--card));"><div class="max-w-4xl mx-auto px-4"><div class="cyberpunk-mono rounded-lg p-6 md:p-8 flex flex-col md:flex-row items-stretch md:items-center gap-4" style="background-color: hsl(var(--background)); border: 1px dashed hsl(var(--primary));"><div class="flex-1 flex items-center gap-2 text-base md:text-lg overflow-hidden"><span aria-hidden="true" style="color: hsl(var(--accent));">$</span> <code class="cyberpunk-mono whitespace-pre-wrap break-all" style="color: hsl(var(--foreground));" data-caret-blink>{{ prompt|default:'$ npm i your-thing' }}</code> <span aria-hidden="true" class="caret-blink" data-caret-blink style="color: hsl(var(--primary));">▍</span></div>{% if button|default:'Copy' %}<a href="{{ href|default:'#' }}" class="cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center justify-center gap-2 px-4 py-2 rounded-md font-semibold uppercase tracking-wider" style="background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));"{% if copyable != false and copyable != "false" and copyable != "off" and copyable != "no" and copyable != "0" and copyable != "" %} data-copy="{{ prompt|default:'$ npm i your-thing' }}"{% endif %}>{{ button|default:'Copy' }}</a>{% endif %}</div></div></section>
|
||||||
1
blocks/feature_card_neon.ninjatpl
Normal file
1
blocks/feature_card_neon.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<article data-block="cyberpunk:feature_card_neon" data-accent="{% if accent == "cyan" %}cyan{% elif accent == "lime" %}lime{% else %}magenta{% endif %}" class="cyberpunk-feature-card p-6 rounded-lg h-full flex flex-col gap-4 {% if accent == "cyan" %}neon-edge-cyan{% elif accent == "lime" %}neon-edge-lime{% else %}neon-edge-magenta{% endif %}" style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border));">{% if icon %}<div class="cyberpunk-feature-icon w-10 h-10 flex items-center justify-center rounded-md" style="background-color: hsl(var(--secondary));"><img src="{{ icon }}" alt="" class="w-6 h-6" onerror="this.style.display='none'"></div>{% endif %}<h3 class="cyberpunk-feature-title text-lg font-semibold" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ title|default:'Feature' }}</h3>{% if body %}<div class="cyberpunk-feature-body text-sm leading-relaxed" style="color: hsl(var(--muted-foreground));">{{ body|safe }}</div>{% endif %}</article>
|
||||||
1
blocks/footer_grid.ninjatpl
Normal file
1
blocks/footer_grid.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<div data-block="cyberpunk:footer_grid" class="cyberpunk-footer w-full" style="background-color: hsl(var(--card)); color: hsl(var(--muted-foreground));"><div class="max-w-6xl mx-auto px-4 py-12">{% if columns %}<div class="grid gap-8 mb-10 cyberpunk-mono text-sm {% if columns|length == 2 %}grid-cols-1 sm:grid-cols-2{% elif columns|length == 3 %}grid-cols-1 sm:grid-cols-2 lg:grid-cols-3{% elif columns|length >= 4 %}grid-cols-1 sm:grid-cols-2 lg:grid-cols-4{% else %}grid-cols-1{% endif %}">{% for col in columns %}<div>{% if col.title %}<p class="cyberpunk-mono uppercase tracking-widest text-xs mb-4" style="color: hsl(var(--accent));">{{ col.title }}</p>{% endif %}{% if col.links %}<ul class="space-y-2">{% for link in col.links %}<li><a href="{{ link.href|default:'#' }}" class="cyberpunk-footer-link hover:underline" style="color: hsl(var(--foreground));">{{ link.label }}</a></li>{% endfor %}</ul>{% endif %}</div>{% endfor %}</div>{% else %}<p class="cyberpunk-mono mb-6 text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">// add columns to populate this grid</p>{% endif %}<div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-3 pt-6" style="border-top: 1px dashed hsl(var(--border));"><p class="cyberpunk-mono text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">BUILD <span style="color: hsl(var(--foreground));">{{ buildHash|default:'dev' }}</span></p>{% if showStatus != false and showStatus != "false" and showStatus != "off" and showStatus != "no" and showStatus != "0" and showStatus != "" %}<span class="cyberpunk-status-pill cyberpunk-mono inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs uppercase tracking-widest" style="border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));"><span aria-hidden="true" class="cyberpunk-status-dot inline-block w-2 h-2 rounded-full" style="background-color: hsl(var(--accent)); box-shadow: 0 0 6px hsl(var(--accent));"></span> OK</span>{% endif %}</div></div></div>
|
||||||
1
blocks/hero_glitch.ninjatpl
Normal file
1
blocks/hero_glitch.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section data-block="cyberpunk:hero_glitch" class="cyberpunk-hero relative w-full overflow-hidden py-24 md:py-32" style="background-color: hsl(var(--background));">{% if scanlines != false and scanlines != "false" and scanlines != "off" and scanlines != "no" and scanlines != "0" and scanlines != "" %}<div aria-hidden="true" class="scanlines pointer-events-none absolute inset-0" data-scanlines-local></div>{% endif %}<div class="relative z-10 max-w-5xl mx-auto px-4 text-center">{% if eyebrow %}<p class="cyberpunk-eyebrow cyberpunk-mono inline-block px-3 py-1 mb-6 text-xs uppercase tracking-[0.35em]" style="color: hsl(var(--accent)); border: 1px dashed hsl(var(--accent));">{{ eyebrow }}</p>{% endif %}<h1 class="glitch cyberpunk-display text-5xl md:text-7xl font-bold leading-[1.05] tracking-tight mb-8" data-text="{{ headline|default:'// hero headline' }}" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ headline|default:'// hero headline' }}</h1>{% if sub %}<p class="cyberpunk-sub mx-auto max-w-2xl text-lg md:text-xl mb-10" style="color: hsl(var(--muted-foreground));">{{ sub }}</p>{% endif %}<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">{% if cta.label %}<a href="{{ cta.href|default:'#' }}" class="cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center gap-2 px-6 py-3 rounded-md font-semibold uppercase tracking-wider" style="background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));"><span>{{ cta.label }}</span> <span aria-hidden="true" class="caret-blink">_</span></a>{% endif %}{% if secondaryCta.label %}<a href="{{ secondaryCta.href|default:'#' }}" class="cyberpunk-btn-ghost cyberpunk-mono inline-flex items-center gap-2 px-6 py-3 rounded-md font-semibold uppercase tracking-wider" style="border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));"><span>{{ secondaryCta.label }}</span></a>{% endif %}</div></div></section>
|
||||||
1
blocks/navbar_terminal.ninjatpl
Normal file
1
blocks/navbar_terminal.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<nav data-block="cyberpunk:navbar_terminal" class="cyberpunk-navbar w-full" style="background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));"><div class="max-w-6xl mx-auto px-4 py-3 flex items-center justify-between gap-4"><div class="flex items-center gap-3 min-w-0">{% if statusDot != false and statusDot != "false" and statusDot != "off" and statusDot != "no" and statusDot != "0" and statusDot != "" %}<span aria-hidden="true" class="cyberpunk-status-dot inline-block w-2 h-2 rounded-full" style="background-color: hsl(var(--accent)); box-shadow: 0 0 8px hsl(var(--accent));"></span>{% endif %}<span class="cyberpunk-mono text-sm" style="color: hsl(var(--accent));">{{ commandPrefix|default:'~/' }}</span> <span class="cyberpunk-mono text-sm truncate" style="color: hsl(var(--foreground));">{{ menuName|default:'main' }}</span> <span aria-hidden="true" class="caret-blink cyberpunk-mono text-sm" style="color: hsl(var(--primary));">_</span></div><button type="button" aria-expanded="false" aria-controls="cyberpunk-navbar-links" class="cyberpunk-navbar-toggle md:hidden inline-flex items-center justify-center px-3 py-2 rounded-md cyberpunk-mono uppercase text-xs tracking-widest" style="border: 1px solid hsl(var(--border)); color: hsl(var(--foreground));" data-cyberpunk-navbar-toggle>MENU</button><ul id="cyberpunk-navbar-links" class="cyberpunk-navbar-links hidden md:flex items-center gap-6 cyberpunk-mono text-sm uppercase tracking-widest" style="color: hsl(var(--muted-foreground));" data-menu-name="{{ menuName|default:'main' }}"><li class="cyberpunk-navbar-hint" style="color: hsl(var(--muted-foreground));">// menu items resolve at runtime</li></ul></div></nav>
|
||||||
1
blocks/stats_glow.ninjatpl
Normal file
1
blocks/stats_glow.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<section data-block="cyberpunk:stats_glow" class="cyberpunk-stats w-full py-16" style="background-color: hsl(var(--background));"><div class="max-w-6xl mx-auto px-4">{% if items %}<div class="grid gap-8 text-center {% if items|length == 2 %}grid-cols-1 sm:grid-cols-2{% elif items|length == 3 %}grid-cols-1 sm:grid-cols-3{% elif items|length >= 4 %}grid-cols-1 sm:grid-cols-2 lg:grid-cols-4{% else %}grid-cols-1{% endif %}">{% for stat in items %}<div class="cyberpunk-stat-cell"><div class="cyberpunk-mono cyberpunk-stat-number text-5xl md:text-6xl font-bold tracking-tight" style="color: hsl(var(--foreground)); font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);"><span>{{ stat.value }}</span>{% if stat.suffix %} <span style="color: hsl(var(--primary));">{{ stat.suffix }}</span>{% endif %}</div><div class="cyberpunk-stat-underline mx-auto mt-2 mb-3 h-px w-12" style="background-color: hsl(var(--accent));"></div><div class="cyberpunk-mono cyberpunk-stat-label text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">{{ stat.label }}</div></div>{% endfor %}</div>{% else %}<div class="text-center cyberpunk-mono text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">// add items to render stats</div>{% endif %}</div></section>
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CyberpunkButtonBlock renders the built-in button with cyberpunk styling:
|
|
||||||
// terminal-cursor caret suffix, RGB-split hover via the .rgb-split class,
|
|
||||||
// mono label and uppercase tracking.
|
|
||||||
func CyberpunkButtonBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
label := getStringWithDefault(content, "label", "Button")
|
|
||||||
href := safeHref(getString(content, "href"))
|
|
||||||
variant := getStringWithDefault(content, "variant", "primary")
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = cyberpunkButtonComponent(label, href, variant).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// cyberpunkButtonComponent renders the override for the built-in button block.
|
|
||||||
// Primary buttons get .rgb-split for the chromatic-aberration hover.
|
|
||||||
// Secondary / ghost variants use the accent/border tokens.
|
|
||||||
templ cyberpunkButtonComponent(label, href, variant string) {
|
|
||||||
switch variant {
|
|
||||||
case "secondary":
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(href) }
|
|
||||||
class="cyberpunk-btn cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider"
|
|
||||||
style="background-color: hsl(var(--secondary)); color: hsl(var(--secondary-foreground));"
|
|
||||||
>
|
|
||||||
<span>{ label }</span>
|
|
||||||
<span aria-hidden="true" class="caret-blink">_</span>
|
|
||||||
</a>
|
|
||||||
case "ghost":
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(href) }
|
|
||||||
class="cyberpunk-btn-ghost cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider"
|
|
||||||
style="border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));"
|
|
||||||
>
|
|
||||||
<span>{ label }</span>
|
|
||||||
<span aria-hidden="true" class="caret-blink">_</span>
|
|
||||||
</a>
|
|
||||||
default:
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(href) }
|
|
||||||
class="cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider"
|
|
||||||
style="background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));"
|
|
||||||
>
|
|
||||||
<span>{ label }</span>
|
|
||||||
<span aria-hidden="true" class="caret-blink">_</span>
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,134 +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"
|
|
||||||
|
|
||||||
// cyberpunkButtonComponent renders the override for the built-in button block.
|
|
||||||
// Primary buttons get .rgb-split for the chromatic-aberration hover.
|
|
||||||
// Secondary / ghost variants use the accent/border tokens.
|
|
||||||
func cyberpunkButtonComponent(label, href, 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)
|
|
||||||
switch variant {
|
|
||||||
case "secondary":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(href))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 10, Col: 30}
|
|
||||||
}
|
|
||||||
_, 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, "\" class=\"cyberpunk-btn cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider\" style=\"background-color: hsl(var(--secondary)); color: hsl(var(--secondary-foreground));\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 14, Col: 17}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <span aria-hidden=\"true\" class=\"caret-blink\">_</span></a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case "ghost":
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(href))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 19, Col: 30}
|
|
||||||
}
|
|
||||||
_, 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, "\" class=\"cyberpunk-btn-ghost cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider\" style=\"border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 23, Col: 17}
|
|
||||||
}
|
|
||||||
_, 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, 6, "</span> <span aria-hidden=\"true\" class=\"caret-blink\">_</span></a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(href))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 28, Col: 30}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" class=\"cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider\" style=\"background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button_override.templ`, Line: 32, Col: 17}
|
|
||||||
}
|
|
||||||
_, 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, 9, "</span> <span aria-hidden=\"true\" class=\"caret-blink\">_</span></a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CyberpunkCardBlock renders the built-in card with a dashed neon border-image
|
|
||||||
// and hover-lift / chromatic-aberration shadow.
|
|
||||||
func CyberpunkCardBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
title := getString(content, "title")
|
|
||||||
body := getString(content, "body")
|
|
||||||
href := getString(content, "href")
|
|
||||||
media := getString(content, "media")
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = cyberpunkCardComponent(title, body, href, media).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// cyberpunkCardComponent renders the override for the built-in card block:
|
|
||||||
// dashed neon border, hover-lift with chromatic-aberration shadow.
|
|
||||||
templ cyberpunkCardComponent(title, body, href, media string) {
|
|
||||||
if href != "" {
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(safeHref(href)) }
|
|
||||||
class="cyberpunk-card neon-edge-magenta block p-6 rounded-lg h-full transition-transform hover:-translate-y-0.5"
|
|
||||||
style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px dashed hsl(var(--primary));"
|
|
||||||
>
|
|
||||||
@cyberpunkCardInner(title, body, media)
|
|
||||||
</a>
|
|
||||||
} else {
|
|
||||||
<article
|
|
||||||
class="cyberpunk-card neon-edge-magenta block p-6 rounded-lg h-full"
|
|
||||||
style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px dashed hsl(var(--primary));"
|
|
||||||
>
|
|
||||||
@cyberpunkCardInner(title, body, media)
|
|
||||||
</article>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cyberpunkCardInner renders the shared card body markup.
|
|
||||||
templ cyberpunkCardInner(title, body, media string) {
|
|
||||||
if media != "" {
|
|
||||||
<img
|
|
||||||
src={ media }
|
|
||||||
alt=""
|
|
||||||
class="cyberpunk-card-media w-full h-40 object-cover rounded mb-4"
|
|
||||||
onerror="this.style.display='none'"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
if title != "" {
|
|
||||||
<h3 class="cyberpunk-card-title text-lg font-semibold mb-2" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">
|
|
||||||
{ title }
|
|
||||||
</h3>
|
|
||||||
}
|
|
||||||
if body != "" {
|
|
||||||
<div class="cyberpunk-card-body text-sm leading-relaxed" style="color: hsl(var(--muted-foreground));">
|
|
||||||
@templ.Raw(body)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,156 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// cyberpunkCardComponent renders the override for the built-in card block:
|
|
||||||
// dashed neon border, hover-lift with chromatic-aberration shadow.
|
|
||||||
func cyberpunkCardComponent(title, body, href, media 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 href != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(safeHref(href)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `card_override.templ`, Line: 8, Col: 39}
|
|
||||||
}
|
|
||||||
_, 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, "\" class=\"cyberpunk-card neon-edge-magenta block p-6 rounded-lg h-full transition-transform hover:-translate-y-0.5\" style=\"background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px dashed hsl(var(--primary));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = cyberpunkCardInner(title, body, media).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<article class=\"cyberpunk-card neon-edge-magenta block p-6 rounded-lg h-full\" style=\"background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px dashed hsl(var(--primary));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = cyberpunkCardInner(title, body, media).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</article>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// cyberpunkCardInner renders the shared card body markup.
|
|
||||||
func cyberpunkCardInner(title, body, media 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_Var3 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var3 == nil {
|
|
||||||
templ_7745c5c3_Var3 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
if media != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<img src=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(media)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `card_override.templ`, Line: 28, Col: 14}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" alt=\"\" class=\"cyberpunk-card-media w-full h-40 object-cover rounded mb-4\" onerror=\"this.style.display='none'\"> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if title != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<h3 class=\"cyberpunk-card-title text-lg font-semibold mb-2\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `card_override.templ`, Line: 36, Col: 10}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</h3>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if body != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"cyberpunk-card-body text-sm leading-relaxed\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
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, 11, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
39
code_neon.go
39
code_neon.go
@ -1,39 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CodeNeonMeta defines metadata for the cyberpunk:code_neon block.
|
|
||||||
var CodeNeonMeta = blocks.BlockMeta{
|
|
||||||
Key: "code_neon",
|
|
||||||
Title: "Code Block",
|
|
||||||
Description: "Server-rendered code block with neon edge and optional copy button",
|
|
||||||
Category: blocks.CategoryContent,
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeNeonData is the typed view of the code_neon content map.
|
|
||||||
type CodeNeonData struct {
|
|
||||||
Language string
|
|
||||||
Code string
|
|
||||||
Copy bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeNeonBlock renders the code_neon block.
|
|
||||||
//
|
|
||||||
// Content shape:
|
|
||||||
// {language:"bash"|"go"|..., code, copy: bool|"on"|"off"}
|
|
||||||
func CodeNeonBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := CodeNeonData{
|
|
||||||
Language: getStringWithDefault(content, "language", "text"),
|
|
||||||
Code: getString(content, "code"),
|
|
||||||
Copy: getBool(content, "copy", true),
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = codeNeonComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// codeNeonComponent renders the cyberpunk:code_neon block.
|
|
||||||
templ codeNeonComponent(data CodeNeonData) {
|
|
||||||
<figure
|
|
||||||
data-block="cyberpunk:code_neon"
|
|
||||||
class="cyberpunk-code w-full my-6 rounded-lg overflow-hidden neon-edge-magenta"
|
|
||||||
style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground));"
|
|
||||||
>
|
|
||||||
<figcaption class="flex items-center justify-between px-4 py-2 cyberpunk-mono text-xs uppercase tracking-widest" style="background-color: hsl(var(--secondary)); color: hsl(var(--muted-foreground));">
|
|
||||||
<span>{ data.Language }</span>
|
|
||||||
if data.Copy {
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="cyberpunk-code-copy cyberpunk-mono uppercase tracking-widest px-2 py-1 rounded"
|
|
||||||
style="border: 1px solid hsl(var(--border)); color: hsl(var(--accent));"
|
|
||||||
data-copy={ data.Code }
|
|
||||||
>
|
|
||||||
COPY
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</figcaption>
|
|
||||||
<pre class="cyberpunk-mono overflow-x-auto p-4 text-sm leading-relaxed" style="background-color: hsl(var(--background)); color: hsl(var(--foreground)); font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);"><code class={ "language-" + data.Language }>{ data.Code }</code></pre>
|
|
||||||
</figure>
|
|
||||||
}
|
|
||||||
@ -1,112 +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"
|
|
||||||
|
|
||||||
// codeNeonComponent renders the cyberpunk:code_neon block.
|
|
||||||
func codeNeonComponent(data CodeNeonData) 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, "<figure data-block=\"cyberpunk:code_neon\" class=\"cyberpunk-code w-full my-6 rounded-lg overflow-hidden neon-edge-magenta\" style=\"background-color: hsl(var(--card)); color: hsl(var(--card-foreground));\"><figcaption class=\"flex items-center justify-between px-4 py-2 cyberpunk-mono text-xs uppercase tracking-widest\" style=\"background-color: hsl(var(--secondary)); color: hsl(var(--muted-foreground));\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Language)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `code_neon.templ`, Line: 11, Col: 24}
|
|
||||||
}
|
|
||||||
_, 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, "</span> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Copy {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<button type=\"button\" class=\"cyberpunk-code-copy cyberpunk-mono uppercase tracking-widest px-2 py-1 rounded\" style=\"border: 1px solid hsl(var(--border)); color: hsl(var(--accent));\" data-copy=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Code)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `code_neon.templ`, Line: 17, Col: 26}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">COPY</button>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</figcaption><pre class=\"cyberpunk-mono overflow-x-auto p-4 text-sm leading-relaxed\" style=\"background-color: hsl(var(--background)); color: hsl(var(--foreground)); font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 = []any{"language-" + data.Language}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<code class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var4).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `code_neon.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(data.Code)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `code_neon.templ`, Line: 23, Col: 284}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</code></pre></figure>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CTATerminalMeta defines metadata for the cyberpunk:cta_terminal block.
|
|
||||||
var CTATerminalMeta = blocks.BlockMeta{
|
|
||||||
Key: "cta_terminal",
|
|
||||||
Title: "Terminal CTA",
|
|
||||||
Description: "Faux $ prompt with blinking caret and copy button",
|
|
||||||
Category: blocks.CategoryLayout,
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// CTATerminalData is the typed view of the cta_terminal content map.
|
|
||||||
type CTATerminalData struct {
|
|
||||||
Prompt string
|
|
||||||
Button string
|
|
||||||
Href string
|
|
||||||
Copyable bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// CTATerminalBlock renders the cta_terminal block.
|
|
||||||
//
|
|
||||||
// Content shape:
|
|
||||||
// {prompt, button, href, copyable: bool|"true"|"false"}
|
|
||||||
func CTATerminalBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := CTATerminalData{
|
|
||||||
Prompt: getStringWithDefault(content, "prompt", "$ npm i your-thing"),
|
|
||||||
Button: getStringWithDefault(content, "button", "Copy"),
|
|
||||||
Href: getString(content, "href"),
|
|
||||||
Copyable: getBool(content, "copyable", true),
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = ctaTerminalComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// ctaTerminalComponent renders the cyberpunk:cta_terminal block as a faux terminal prompt.
|
|
||||||
templ ctaTerminalComponent(data CTATerminalData) {
|
|
||||||
<section
|
|
||||||
data-block="cyberpunk:cta_terminal"
|
|
||||||
class="cyberpunk-cta-terminal w-full py-16"
|
|
||||||
style="background-color: hsl(var(--card));"
|
|
||||||
>
|
|
||||||
<div class="max-w-4xl mx-auto px-4">
|
|
||||||
<div
|
|
||||||
class="cyberpunk-mono rounded-lg p-6 md:p-8 flex flex-col md:flex-row items-stretch md:items-center gap-4"
|
|
||||||
style="background-color: hsl(var(--background)); border: 1px dashed hsl(var(--primary));"
|
|
||||||
>
|
|
||||||
<div class="flex-1 flex items-center gap-2 text-base md:text-lg overflow-hidden">
|
|
||||||
<span aria-hidden="true" style="color: hsl(var(--accent));">$</span>
|
|
||||||
<code class="cyberpunk-mono whitespace-pre-wrap break-all" style="color: hsl(var(--foreground));" data-caret-blink>
|
|
||||||
{ data.Prompt }
|
|
||||||
</code>
|
|
||||||
<span aria-hidden="true" class="caret-blink" data-caret-blink style="color: hsl(var(--primary));">▍</span>
|
|
||||||
</div>
|
|
||||||
if data.Button != "" {
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(safeHref(data.Href)) }
|
|
||||||
class="cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center justify-center gap-2 px-4 py-2 rounded-md font-semibold uppercase tracking-wider"
|
|
||||||
style="background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));"
|
|
||||||
if data.Copyable {
|
|
||||||
data-copy={ data.Prompt }
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{ data.Button }
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
@ -1,113 +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"
|
|
||||||
|
|
||||||
// ctaTerminalComponent renders the cyberpunk:cta_terminal block as a faux terminal prompt.
|
|
||||||
func ctaTerminalComponent(data CTATerminalData) 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, "<section data-block=\"cyberpunk:cta_terminal\" class=\"cyberpunk-cta-terminal w-full py-16\" style=\"background-color: hsl(var(--card));\"><div class=\"max-w-4xl mx-auto px-4\"><div class=\"cyberpunk-mono rounded-lg p-6 md:p-8 flex flex-col md:flex-row items-stretch md:items-center gap-4\" style=\"background-color: hsl(var(--background)); border: 1px dashed hsl(var(--primary));\"><div class=\"flex-1 flex items-center gap-2 text-base md:text-lg overflow-hidden\"><span aria-hidden=\"true\" style=\"color: hsl(var(--accent));\">$</span> <code class=\"cyberpunk-mono whitespace-pre-wrap break-all\" style=\"color: hsl(var(--foreground));\" data-caret-blink>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Prompt)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cta_terminal.templ`, Line: 18, Col: 19}
|
|
||||||
}
|
|
||||||
_, 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, "</code> <span aria-hidden=\"true\" class=\"caret-blink\" data-caret-blink style=\"color: hsl(var(--primary));\">▍</span></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Button != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(safeHref(data.Href)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cta_terminal.templ`, Line: 24, Col: 47}
|
|
||||||
}
|
|
||||||
_, 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, 4, "\" class=\"cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center justify-center gap-2 px-4 py-2 rounded-md font-semibold uppercase tracking-wider\" style=\"background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Copyable {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " data-copy=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Prompt)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cta_terminal.templ`, Line: 28, Col: 30}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, ">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Button)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `cta_terminal.templ`, Line: 31, Col: 19}
|
|
||||||
}
|
|
||||||
_, 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, "</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div></div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CyberpunkEmailWrapper is the registered cyberpunk:email_wrapper.
|
|
||||||
// It produces a dark email with a mono preheader, magenta hairline divider,
|
|
||||||
// and a literal "[esc] unsubscribe" link per UAT §10.
|
|
||||||
//
|
|
||||||
// UAT §10 mandates `body { background:#0a0a12 }`. That literal hex lives in the
|
|
||||||
// <style> head block (a <style> element is not a `style=` attribute and so does
|
|
||||||
// not trip the no-inline-hex-style rule). All other colour values use hsl()
|
|
||||||
// notation, which most modern mail clients render fine.
|
|
||||||
func CyberpunkEmailWrapper(body string, emailCtx templates.EmailContext) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = cyberpunkEmailTemplate(emailCtx, body).Render(context.Background(), &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// cyberpunkEmailTemplate is the Cyberpunk-branded HTML email shell.
|
|
||||||
templ cyberpunkEmailTemplate(emailCtx templates.EmailContext, body string) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
||||||
<meta name="x-apple-disable-message-reformatting"/>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
|
||||||
<title>{ emailCtx.SiteSettings.SiteName }</title>
|
|
||||||
<style type="text/css">
|
|
||||||
body { background:#0a0a12; margin:0; padding:0; color: hsl(260 25% 92%); }
|
|
||||||
table, td { mso-table-lspace:0pt; mso-table-rspace:0pt; }
|
|
||||||
a { color: inherit; }
|
|
||||||
.cyberpunk-preheader { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
|
||||||
.cyberpunk-divider { border-top:1px solid hsl(320 100% 60%); }
|
|
||||||
@media only screen and (max-width: 620px) {
|
|
||||||
.email-container { width:100% !important; max-width:100% !important; }
|
|
||||||
.content-padding { padding-left:24px !important; padding-right:24px !important; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body bgcolor="#0a0a12" style="margin:0;padding:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;">
|
|
||||||
if emailCtx.PreviewText != "" {
|
|
||||||
<div class="cyberpunk-preheader" style="display:none;max-height:0;overflow:hidden;mso-hide:all;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;">
|
|
||||||
$ from: { emailCtx.SiteSettings.SiteName } — { emailCtx.PreviewText }
|
|
||||||
</div>
|
|
||||||
} else {
|
|
||||||
<div class="cyberpunk-preheader" style="display:none;max-height:0;overflow:hidden;mso-hide:all;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;">
|
|
||||||
$ from: { emailCtx.SiteSettings.SiteName }
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#0a0a12">
|
|
||||||
<tr>
|
|
||||||
<td align="center" style="padding:48px 12px;">
|
|
||||||
<table role="presentation" class="email-container" width="600" cellpadding="0" cellspacing="0" border="0" bgcolor="#101020" style="max-width:600px;border:1px solid hsl(258 28% 20%);">
|
|
||||||
<tr>
|
|
||||||
<td class="content-padding" align="center" style="padding:32px 40px;border-bottom:1px solid hsl(320 100% 60%);">
|
|
||||||
<div class="cyberpunk-preheader" style="font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size:12px;letter-spacing:0.2em;text-transform:uppercase;">
|
|
||||||
$ from: { emailCtx.SiteSettings.SiteName }
|
|
||||||
</div>
|
|
||||||
if emailCtx.SiteSettings.LogoURL != "" {
|
|
||||||
<img src={ emailCtx.SiteSettings.LogoURL } alt={ emailCtx.SiteSettings.SiteName } style="margin-top:12px;max-height:48px;width:auto;display:inline-block;"/>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="content-padding" style="padding:40px 48px;font-size:16px;line-height:1.7;">
|
|
||||||
@templ.Raw(body)
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="cyberpunk-divider" height="1" style="border-top:1px solid hsl(320 100% 60%);font-size:0;line-height:0;"> </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="content-padding" align="center" style="padding:24px 48px 40px;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size:12px;letter-spacing:0.15em;text-transform:uppercase;">
|
|
||||||
if emailCtx.SiteSettings.SiteURL != "" {
|
|
||||||
<p style="margin:0 0 12px;">
|
|
||||||
<a href={ templ.SafeURL(emailCtx.SiteSettings.SiteURL) } style="text-decoration:none;">
|
|
||||||
{ emailCtx.SiteSettings.SiteURL }
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
if emailCtx.UnsubscribeURL != "" {
|
|
||||||
<p style="margin:0;">
|
|
||||||
<a href={ templ.SafeURL(emailCtx.UnsubscribeURL) } style="text-decoration:none;">[esc] unsubscribe</a>
|
|
||||||
</p>
|
|
||||||
} else {
|
|
||||||
<p style="margin:0;">[esc] unsubscribe</p>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
@ -1,246 +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"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CyberpunkEmailWrapper is the registered cyberpunk:email_wrapper.
|
|
||||||
// It produces a dark email with a mono preheader, magenta hairline divider,
|
|
||||||
// and a literal "[esc] unsubscribe" link per UAT §10.
|
|
||||||
//
|
|
||||||
// UAT §10 mandates `body { background:#0a0a12 }`. That literal hex lives in the
|
|
||||||
// <style> head block (a <style> element is not a `style=` attribute and so does
|
|
||||||
// not trip the no-inline-hex-style rule). All other colour values use hsl()
|
|
||||||
// notation, which most modern mail clients render fine.
|
|
||||||
func CyberpunkEmailWrapper(body string, emailCtx templates.EmailContext) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = cyberpunkEmailTemplate(emailCtx, body).Render(context.Background(), &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// cyberpunkEmailTemplate is the Cyberpunk-branded HTML email shell.
|
|
||||||
func cyberpunkEmailTemplate(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, "<!doctype html><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><meta name=\"x-apple-disable-message-reformatting\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><title>")
|
|
||||||
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: 33, 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, "</title><style type=\"text/css\">\n\t\t\t\tbody { background:#0a0a12; margin:0; padding:0; color: hsl(260 25% 92%); }\n\t\t\t\ttable, td { mso-table-lspace:0pt; mso-table-rspace:0pt; }\n\t\t\t\ta { color: inherit; }\n\t\t\t\t.cyberpunk-preheader { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }\n\t\t\t\t.cyberpunk-divider { border-top:1px solid hsl(320 100% 60%); }\n\t\t\t\t@media only screen and (max-width: 620px) {\n\t\t\t\t\t.email-container { width:100% !important; max-width:100% !important; }\n\t\t\t\t\t.content-padding { padding-left:24px !important; padding-right:24px !important; }\n\t\t\t\t}\n\t\t\t</style></head><body bgcolor=\"#0a0a12\" style=\"margin:0;padding:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.PreviewText != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"cyberpunk-preheader\" style=\"display:none;max-height:0;overflow:hidden;mso-hide:all;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\">$ from: ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, 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: 49, Col: 45}
|
|
||||||
}
|
|
||||||
_, 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, 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: 49, Col: 74}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"cyberpunk-preheader\" style=\"display:none;max-height:0;overflow:hidden;mso-hide:all;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\">$ from: ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, 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: 53, Col: 45}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" bgcolor=\"#0a0a12\"><tr><td align=\"center\" style=\"padding:48px 12px;\"><table role=\"presentation\" class=\"email-container\" width=\"600\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" bgcolor=\"#101020\" style=\"max-width:600px;border:1px solid hsl(258 28% 20%);\"><tr><td class=\"content-padding\" align=\"center\" style=\"padding:32px 40px;border-bottom:1px solid hsl(320 100% 60%);\"><div class=\"cyberpunk-preheader\" style=\"font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size:12px;letter-spacing:0.2em;text-transform:uppercase;\">$ from: ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, 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: 63, Col: 50}
|
|
||||||
}
|
|
||||||
_, 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, 9, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.SiteSettings.LogoURL != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<img src=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(emailCtx.SiteSettings.LogoURL)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 66, Col: 50}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" alt=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(emailCtx.SiteSettings.SiteName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 66, Col: 89}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" style=\"margin-top:12px;max-height:48px;width:auto;display:inline-block;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</td></tr><tr><td class=\"content-padding\" style=\"padding:40px 48px;font-size:16px;line-height:1.7;\">")
|
|
||||||
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, 14, "</td></tr><tr><td class=\"cyberpunk-divider\" height=\"1\" style=\"border-top:1px solid hsl(320 100% 60%);font-size:0;line-height:0;\"> </td></tr><tr><td class=\"content-padding\" align=\"center\" style=\"padding:24px 48px 40px;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size:12px;letter-spacing:0.15em;text-transform:uppercase;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if emailCtx.SiteSettings.SiteURL != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<p style=\"margin:0 0 12px;\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(emailCtx.SiteSettings.SiteURL))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 82, Col: 65}
|
|
||||||
}
|
|
||||||
_, 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, 16, "\" style=\"text-decoration:none;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var10 string
|
|
||||||
templ_7745c5c3_Var10, 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: 83, Col: 43}
|
|
||||||
}
|
|
||||||
_, 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, 17, "</a></p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if emailCtx.UnsubscribeURL != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<p style=\"margin:0;\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(emailCtx.UnsubscribeURL))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `email_wrapper.templ`, Line: 89, Col: 59}
|
|
||||||
}
|
|
||||||
_, 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, 19, "\" style=\"text-decoration:none;\">[esc] unsubscribe</a></p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<p style=\"margin:0;\">[esc] unsubscribe</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</td></tr></table></td></tr></table></body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
60
embed.go
60
embed.go
@ -1,60 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/plugin"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed assets/*
|
|
||||||
var assetsFS embed.FS
|
|
||||||
|
|
||||||
//go:embed schemas/*
|
|
||||||
var schemasFS embed.FS
|
|
||||||
|
|
||||||
//go:embed presets.json
|
|
||||||
var presetsData []byte
|
|
||||||
|
|
||||||
//go:embed fonts.json
|
|
||||||
var fontsData []byte
|
|
||||||
|
|
||||||
//go:embed plugin.mod
|
|
||||||
var pluginModBytes []byte
|
|
||||||
|
|
||||||
// Assets returns the embedded assets filesystem (rooted at "assets/").
|
|
||||||
func Assets() fs.FS {
|
|
||||||
sub, _ := fs.Sub(assetsFS, "assets")
|
|
||||||
return sub
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schemas returns the embedded schemas filesystem (rooted at "schemas/").
|
|
||||||
func Schemas() fs.FS {
|
|
||||||
sub, _ := fs.Sub(schemasFS, "schemas")
|
|
||||||
return sub
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssetsHandler returns an http.Handler that serves the embedded assets at /templates/cyberpunk/...
|
|
||||||
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.
|
|
||||||
func BundledFonts() []byte { return fontsData }
|
|
||||||
|
|
||||||
// ThemeCSSManifest exposes the theme's custom CSS (scanlines, glitch, neon-edge,
|
|
||||||
// caret-blink keyframes, font-family fallbacks) to the host Tailwind input so the
|
|
||||||
// utilities survive prod purging.
|
|
||||||
func ThemeCSSManifest() *plugin.CSSManifest {
|
|
||||||
css, err := assetsFS.ReadFile("assets/css/cyberpunk.css")
|
|
||||||
if err != nil {
|
|
||||||
return &plugin.CSSManifest{}
|
|
||||||
}
|
|
||||||
return &plugin.CSSManifest{
|
|
||||||
InputCSSAppend: string(css),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FeatureCardNeonMeta defines metadata for the cyberpunk:feature_card_neon block.
|
|
||||||
var FeatureCardNeonMeta = blocks.BlockMeta{
|
|
||||||
Key: "feature_card_neon",
|
|
||||||
Title: "Neon Feature Card",
|
|
||||||
Description: "Single feature card with per-card neon edge glow (magenta/cyan/lime)",
|
|
||||||
Category: blocks.CategoryLayout,
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeatureCardNeonData is the typed view of the feature_card_neon content map.
|
|
||||||
type FeatureCardNeonData struct {
|
|
||||||
Icon string
|
|
||||||
Title string
|
|
||||||
Body string
|
|
||||||
Accent string
|
|
||||||
}
|
|
||||||
|
|
||||||
// FeatureCardNeonBlock renders the feature_card_neon block.
|
|
||||||
//
|
|
||||||
// Content shape:
|
|
||||||
// {icon, title, body, accent:"magenta"|"cyan"|"lime"}
|
|
||||||
func FeatureCardNeonBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := FeatureCardNeonData{
|
|
||||||
Icon: getString(content, "icon"),
|
|
||||||
Title: getStringWithDefault(content, "title", "Feature"),
|
|
||||||
Body: getString(content, "body"),
|
|
||||||
Accent: parseAccent(getString(content, "accent")),
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = featureCardNeonComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseAccent normalises the accent value to one of the three known accents.
|
|
||||||
func parseAccent(v string) string {
|
|
||||||
switch v {
|
|
||||||
case "magenta", "cyan", "lime":
|
|
||||||
return v
|
|
||||||
default:
|
|
||||||
return "magenta"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// neonEdgeClass returns the per-accent neon-edge utility class.
|
|
||||||
func neonEdgeClass(accent string) string {
|
|
||||||
switch accent {
|
|
||||||
case "cyan":
|
|
||||||
return "neon-edge-cyan"
|
|
||||||
case "lime":
|
|
||||||
return "neon-edge-lime"
|
|
||||||
default:
|
|
||||||
return "neon-edge-magenta"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// featureCardNeonComponent renders the cyberpunk:feature_card_neon block.
|
|
||||||
templ featureCardNeonComponent(data FeatureCardNeonData) {
|
|
||||||
<article
|
|
||||||
data-block="cyberpunk:feature_card_neon"
|
|
||||||
data-accent={ data.Accent }
|
|
||||||
class={ "cyberpunk-feature-card p-6 rounded-lg h-full flex flex-col gap-4", neonEdgeClass(data.Accent) }
|
|
||||||
style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border));"
|
|
||||||
>
|
|
||||||
if data.Icon != "" {
|
|
||||||
<div class="cyberpunk-feature-icon w-10 h-10 flex items-center justify-center rounded-md" style="background-color: hsl(var(--secondary));">
|
|
||||||
<img src={ data.Icon } alt="" class="w-6 h-6" onerror="this.style.display='none'"/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<h3 class="cyberpunk-feature-title text-lg font-semibold" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">
|
|
||||||
{ data.Title }
|
|
||||||
</h3>
|
|
||||||
if data.Body != "" {
|
|
||||||
<div class="cyberpunk-feature-body text-sm leading-relaxed" style="color: hsl(var(--muted-foreground));">
|
|
||||||
@templ.Raw(data.Body)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</article>
|
|
||||||
}
|
|
||||||
@ -1,138 +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"
|
|
||||||
|
|
||||||
// neonEdgeClass returns the per-accent neon-edge utility class.
|
|
||||||
func neonEdgeClass(accent string) string {
|
|
||||||
switch accent {
|
|
||||||
case "cyan":
|
|
||||||
return "neon-edge-cyan"
|
|
||||||
case "lime":
|
|
||||||
return "neon-edge-lime"
|
|
||||||
default:
|
|
||||||
return "neon-edge-magenta"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// featureCardNeonComponent renders the cyberpunk:feature_card_neon block.
|
|
||||||
func featureCardNeonComponent(data FeatureCardNeonData) 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{"cyberpunk-feature-card p-6 rounded-lg h-full flex flex-col gap-4", neonEdgeClass(data.Accent)}
|
|
||||||
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, "<article data-block=\"cyberpunk:feature_card_neon\" data-accent=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Accent)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `feature_card_neon.templ`, Line: 19, Col: 27}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `feature_card_neon.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" style=\"background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Icon != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"cyberpunk-feature-icon w-10 h-10 flex items-center justify-center rounded-md\" style=\"background-color: hsl(var(--secondary));\"><img src=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Icon)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `feature_card_neon.templ`, Line: 25, Col: 24}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" alt=\"\" class=\"w-6 h-6\" onerror=\"this.style.display='none'\"></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<h3 class=\"cyberpunk-feature-title text-lg font-semibold\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(data.Title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `feature_card_neon.templ`, Line: 29, Col: 15}
|
|
||||||
}
|
|
||||||
_, 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, 7, "</h3>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Body != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"cyberpunk-feature-body text-sm leading-relaxed\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Body).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</article>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FooterGridMeta defines metadata for the cyberpunk:footer_grid block.
|
|
||||||
var FooterGridMeta = blocks.BlockMeta{
|
|
||||||
Key: "footer_grid",
|
|
||||||
Title: "Grid Footer",
|
|
||||||
Description: "Mono columns, build-hash + uptime status pill",
|
|
||||||
Category: blocks.CategoryNavigation,
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// FooterColumn is one column of footer links.
|
|
||||||
type FooterColumn struct {
|
|
||||||
Title string
|
|
||||||
Links []Link
|
|
||||||
}
|
|
||||||
|
|
||||||
// FooterGridData is the typed view of the footer_grid content map.
|
|
||||||
type FooterGridData struct {
|
|
||||||
ShowStatus bool
|
|
||||||
BuildHash string
|
|
||||||
Columns []FooterColumn
|
|
||||||
}
|
|
||||||
|
|
||||||
// FooterGridBlock renders the footer_grid block.
|
|
||||||
//
|
|
||||||
// Content shape:
|
|
||||||
// {showStatus, buildHash, columns:[{title, links:[{label, href}]}]}
|
|
||||||
func FooterGridBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
cols := getSlice(content, "columns")
|
|
||||||
columns := make([]FooterColumn, 0, len(cols))
|
|
||||||
for _, col := range cols {
|
|
||||||
linkObjs := getSlice(col, "links")
|
|
||||||
links := make([]Link, 0, len(linkObjs))
|
|
||||||
for _, l := range linkObjs {
|
|
||||||
links = append(links, Link{
|
|
||||||
Label: getString(l, "label"),
|
|
||||||
Href: getString(l, "href"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
columns = append(columns, FooterColumn{
|
|
||||||
Title: getString(col, "title"),
|
|
||||||
Links: links,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data := FooterGridData{
|
|
||||||
ShowStatus: getBool(content, "showStatus", true),
|
|
||||||
BuildHash: getStringWithDefault(content, "buildHash", "dev"),
|
|
||||||
Columns: columns,
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = footerGridComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// footerGridColumns returns a tailwind grid-column class for n columns.
|
|
||||||
func footerGridColumns(n int) string {
|
|
||||||
switch n {
|
|
||||||
case 0, 1:
|
|
||||||
return "grid-cols-1"
|
|
||||||
case 2:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2"
|
|
||||||
case 3:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"
|
|
||||||
default:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// footerGridComponent renders the cyberpunk:footer_grid block.
|
|
||||||
templ footerGridComponent(data FooterGridData) {
|
|
||||||
<div
|
|
||||||
data-block="cyberpunk:footer_grid"
|
|
||||||
class="cyberpunk-footer w-full"
|
|
||||||
style="background-color: hsl(var(--card)); color: hsl(var(--muted-foreground));"
|
|
||||||
>
|
|
||||||
<div class="max-w-6xl mx-auto px-4 py-12">
|
|
||||||
if len(data.Columns) > 0 {
|
|
||||||
<div class={ "grid gap-8 mb-10 cyberpunk-mono text-sm", footerGridColumns(len(data.Columns)) }>
|
|
||||||
for _, col := range data.Columns {
|
|
||||||
<div>
|
|
||||||
if col.Title != "" {
|
|
||||||
<p class="cyberpunk-mono uppercase tracking-widest text-xs mb-4" style="color: hsl(var(--accent));">
|
|
||||||
{ col.Title }
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
if len(col.Links) > 0 {
|
|
||||||
<ul class="space-y-2">
|
|
||||||
for _, link := range col.Links {
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(safeHref(link.Href)) }
|
|
||||||
class="cyberpunk-footer-link hover:underline"
|
|
||||||
style="color: hsl(var(--foreground));"
|
|
||||||
>
|
|
||||||
{ link.Label }
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
} else {
|
|
||||||
<p class="cyberpunk-mono mb-6 text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">
|
|
||||||
{ "// add columns to populate this grid" }
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
<div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-3 pt-6" style="border-top: 1px dashed hsl(var(--border));">
|
|
||||||
<p class="cyberpunk-mono text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">
|
|
||||||
BUILD <span style="color: hsl(var(--foreground));">{ data.BuildHash }</span>
|
|
||||||
</p>
|
|
||||||
if data.ShowStatus {
|
|
||||||
<span
|
|
||||||
class="cyberpunk-status-pill cyberpunk-mono inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs uppercase tracking-widest"
|
|
||||||
style="border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
class="cyberpunk-status-dot inline-block w-2 h-2 rounded-full"
|
|
||||||
style="background-color: hsl(var(--accent)); box-shadow: 0 0 6px hsl(var(--accent));"
|
|
||||||
></span>
|
|
||||||
OK
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@ -1,199 +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"
|
|
||||||
|
|
||||||
// footerGridColumns returns a tailwind grid-column class for n columns.
|
|
||||||
func footerGridColumns(n int) string {
|
|
||||||
switch n {
|
|
||||||
case 0, 1:
|
|
||||||
return "grid-cols-1"
|
|
||||||
case 2:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2"
|
|
||||||
case 3:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"
|
|
||||||
default:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// footerGridComponent renders the cyberpunk:footer_grid block.
|
|
||||||
func footerGridComponent(data FooterGridData) 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, "<div data-block=\"cyberpunk:footer_grid\" class=\"cyberpunk-footer w-full\" style=\"background-color: hsl(var(--card)); color: hsl(var(--muted-foreground));\"><div class=\"max-w-6xl mx-auto px-4 py-12\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if len(data.Columns) > 0 {
|
|
||||||
var templ_7745c5c3_Var2 = []any{"grid gap-8 mb-10 cyberpunk-mono text-sm", footerGridColumns(len(data.Columns))}
|
|
||||||
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, 2, "<div class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_grid.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, col := range data.Columns {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if col.Title != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<p class=\"cyberpunk-mono uppercase tracking-widest text-xs mb-4\" style=\"color: hsl(var(--accent));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(col.Title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_grid.templ`, Line: 31, Col: 20}
|
|
||||||
}
|
|
||||||
_, 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, 6, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(col.Links) > 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<ul class=\"space-y-2\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, link := range col.Links {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<li><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(safeHref(link.Href)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_grid.templ`, Line: 39, Col: 53}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" class=\"cyberpunk-footer-link hover:underline\" style=\"color: hsl(var(--foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(link.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_grid.templ`, Line: 43, Col: 24}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</a></li>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</ul>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<p class=\"cyberpunk-mono mb-6 text-xs uppercase tracking-widest\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs("// add columns to populate this grid")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_grid.templ`, Line: 54, Col: 45}
|
|
||||||
}
|
|
||||||
_, 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, 15, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"flex flex-col md:flex-row items-start md:items-center justify-between gap-3 pt-6\" style=\"border-top: 1px dashed hsl(var(--border));\"><p class=\"cyberpunk-mono text-xs uppercase tracking-widest\" style=\"color: hsl(var(--muted-foreground));\">BUILD <span style=\"color: hsl(var(--foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(data.BuildHash)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `footer_grid.templ`, Line: 59, Col: 72}
|
|
||||||
}
|
|
||||||
_, 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, 17, "</span></p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.ShowStatus {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<span class=\"cyberpunk-status-pill cyberpunk-mono inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs uppercase tracking-widest\" style=\"border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));\"><span aria-hidden=\"true\" class=\"cyberpunk-status-dot inline-block w-2 h-2 rounded-full\" style=\"background-color: hsl(var(--accent)); box-shadow: 0 0 6px hsl(var(--accent));\"></span> OK</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div></div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
20
go.mod
20
go.mod
@ -1,20 +0,0 @@
|
|||||||
module git.dev.alexdunmow.com/block/themes/cyberpunk
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
|
||||||
46
go.sum
46
go.sum
@ -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=
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CyberpunkHeadingBlock renders the built-in heading block with cyberpunk styling.
|
|
||||||
// H1/H2 get the glitch text-shadow (magenta + cyan offsets); smaller levels get
|
|
||||||
// mono small-caps eyebrow class.
|
|
||||||
func CyberpunkHeadingBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
text := getString(content, "text")
|
|
||||||
textClass := getString(content, "textClass")
|
|
||||||
level := parseHeadingLevel(content)
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = cyberpunkHeadingComponent(level, text, textClass).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// cyberpunkHeadingBaseClass returns default Tailwind classes for each heading level.
|
|
||||||
func cyberpunkHeadingBaseClass(level int) string {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
return "text-4xl md:text-5xl font-bold tracking-tight"
|
|
||||||
case 2:
|
|
||||||
return "text-3xl md:text-4xl font-semibold tracking-tight"
|
|
||||||
case 3:
|
|
||||||
return "text-2xl font-semibold"
|
|
||||||
case 4:
|
|
||||||
return "text-xl font-semibold"
|
|
||||||
case 5:
|
|
||||||
return "text-lg font-medium"
|
|
||||||
case 6:
|
|
||||||
return "text-base font-medium"
|
|
||||||
default:
|
|
||||||
return "text-3xl font-semibold tracking-tight"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cyberpunkHeadingComponent renders the override for the built-in heading block.
|
|
||||||
// H1 and H2 get the .glitch class which gives them the RGB-split text-shadow.
|
|
||||||
// H3-H6 get the mono small-caps eyebrow class.
|
|
||||||
templ cyberpunkHeadingComponent(level int, text, textClass string) {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
<h1
|
|
||||||
class={ "cyberpunk-display glitch", cyberpunkHeadingBaseClass(1), textClass }
|
|
||||||
data-text={ text }
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h1>
|
|
||||||
case 2:
|
|
||||||
<h2
|
|
||||||
class={ "cyberpunk-display glitch", cyberpunkHeadingBaseClass(2), textClass }
|
|
||||||
data-text={ text }
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h2>
|
|
||||||
case 3:
|
|
||||||
<h3
|
|
||||||
class={ "cyberpunk-display", cyberpunkHeadingBaseClass(3), textClass }
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h3>
|
|
||||||
case 4:
|
|
||||||
<h4
|
|
||||||
class={ "cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest", cyberpunkHeadingBaseClass(4), textClass }
|
|
||||||
style="color: hsl(var(--accent));"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h4>
|
|
||||||
case 5:
|
|
||||||
<h5
|
|
||||||
class={ "cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest", cyberpunkHeadingBaseClass(5), textClass }
|
|
||||||
style="color: hsl(var(--accent));"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h5>
|
|
||||||
case 6:
|
|
||||||
<h6
|
|
||||||
class={ "cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest", cyberpunkHeadingBaseClass(6), textClass }
|
|
||||||
style="color: hsl(var(--accent));"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h6>
|
|
||||||
default:
|
|
||||||
<h2
|
|
||||||
class={ "cyberpunk-display glitch", cyberpunkHeadingBaseClass(2), textClass }
|
|
||||||
data-text={ text }
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);"
|
|
||||||
>
|
|
||||||
{ text }
|
|
||||||
</h2>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,352 +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"
|
|
||||||
|
|
||||||
// cyberpunkHeadingBaseClass returns default Tailwind classes for each heading level.
|
|
||||||
func cyberpunkHeadingBaseClass(level int) string {
|
|
||||||
switch level {
|
|
||||||
case 1:
|
|
||||||
return "text-4xl md:text-5xl font-bold tracking-tight"
|
|
||||||
case 2:
|
|
||||||
return "text-3xl md:text-4xl font-semibold tracking-tight"
|
|
||||||
case 3:
|
|
||||||
return "text-2xl font-semibold"
|
|
||||||
case 4:
|
|
||||||
return "text-xl font-semibold"
|
|
||||||
case 5:
|
|
||||||
return "text-lg font-medium"
|
|
||||||
case 6:
|
|
||||||
return "text-base font-medium"
|
|
||||||
default:
|
|
||||||
return "text-3xl font-semibold tracking-tight"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cyberpunkHeadingComponent renders the override for the built-in heading block.
|
|
||||||
// H1 and H2 get the .glitch class which gives them the RGB-split text-shadow.
|
|
||||||
// H3-H6 get the mono small-caps eyebrow class.
|
|
||||||
func cyberpunkHeadingComponent(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{"cyberpunk-display glitch", cyberpunkHeadingBaseClass(1), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<h1 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" data-text=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 31, Col: 20}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
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: `heading_override.templ`, Line: 34, Col: 10}
|
|
||||||
}
|
|
||||||
_, 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, "</h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
var templ_7745c5c3_Var6 = []any{"cyberpunk-display glitch", cyberpunkHeadingBaseClass(2), textClass}
|
|
||||||
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, "<h2 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var6).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" data-text=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.ResolveAttributeValue(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 39, Col: 20}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 string
|
|
||||||
templ_7745c5c3_Var9, 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: 10}
|
|
||||||
}
|
|
||||||
_, 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, 8, "</h2>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
var templ_7745c5c3_Var10 = []any{"cyberpunk-display", cyberpunkHeadingBaseClass(3), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<h3 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 string
|
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var10).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var12 string
|
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 49, Col: 10}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</h3>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
var templ_7745c5c3_Var13 = []any{"cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest", cyberpunkHeadingBaseClass(4), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var13...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<h4 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var14 string
|
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var13).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\" style=\"color: hsl(var(--accent));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var15 string
|
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 56, Col: 10}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</h4>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 5:
|
|
||||||
var templ_7745c5c3_Var16 = []any{"cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest", cyberpunkHeadingBaseClass(5), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<h5 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var17 string
|
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var16).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\" style=\"color: hsl(var(--accent));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var18 string
|
|
||||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 63, Col: 10}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</h5>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
case 6:
|
|
||||||
var templ_7745c5c3_Var19 = []any{"cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest", cyberpunkHeadingBaseClass(6), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var19...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<h6 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var20 string
|
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var19).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" style=\"color: hsl(var(--accent));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var21 string
|
|
||||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 70, Col: 10}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</h6>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
var templ_7745c5c3_Var22 = []any{"cyberpunk-display glitch", cyberpunkHeadingBaseClass(2), textClass}
|
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var22...)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<h2 class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var23 string
|
|
||||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var22).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var23)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" data-text=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var24 string
|
|
||||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.ResolveAttributeValue(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 75, Col: 20}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var25 string
|
|
||||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `heading_override.templ`, Line: 78, Col: 10}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</h2>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
102
helpers.go
102
helpers.go
@ -1,102 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "strconv"
|
|
||||||
|
|
||||||
// getString extracts a string value from a content map. Returns "" on miss/wrong-type.
|
|
||||||
func getString(content map[string]any, key string) string {
|
|
||||||
if v, ok := content[key].(string); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStringWithDefault is like getString but returns dflt if the key is missing or non-string.
|
|
||||||
func getStringWithDefault(content map[string]any, key, dflt string) string {
|
|
||||||
if v, ok := content[key].(string); ok && v != "" {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return dflt
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBool extracts a boolean value from a content map. Accepts bool, "true"/"false",
|
|
||||||
// "on"/"off", "yes"/"no", and numerics. Returns dflt when missing or unparsable.
|
|
||||||
func getBool(content map[string]any, key string, dflt bool) bool {
|
|
||||||
switch v := content[key].(type) {
|
|
||||||
case bool:
|
|
||||||
return v
|
|
||||||
case string:
|
|
||||||
switch v {
|
|
||||||
case "true", "on", "yes", "1":
|
|
||||||
return true
|
|
||||||
case "false", "off", "no", "0", "":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case float64:
|
|
||||||
return v != 0
|
|
||||||
case int:
|
|
||||||
return v != 0
|
|
||||||
}
|
|
||||||
return dflt
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSlice extracts a slice of object-shaped entries from a content map.
|
|
||||||
func getSlice(content map[string]any, key string) []map[string]any {
|
|
||||||
v, ok := content[key].([]any)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := make([]map[string]any, 0, len(v))
|
|
||||||
for _, item := range v {
|
|
||||||
if m, ok := item.(map[string]any); ok {
|
|
||||||
out = append(out, m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// getLink reads a {label, href} link object. Tolerates string values
|
|
||||||
// (interpreted as href, label = href) and missing keys.
|
|
||||||
func getLink(content map[string]any, key string) Link {
|
|
||||||
v := content[key]
|
|
||||||
switch x := v.(type) {
|
|
||||||
case map[string]any:
|
|
||||||
return Link{Label: getString(x, "label"), Href: getString(x, "href")}
|
|
||||||
case string:
|
|
||||||
return Link{Label: x, Href: x}
|
|
||||||
}
|
|
||||||
return Link{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link is a {label, href} pair used by hero / nav / footer blocks.
|
|
||||||
type Link struct {
|
|
||||||
Label string
|
|
||||||
Href string
|
|
||||||
}
|
|
||||||
|
|
||||||
// safeHref returns "#" when href is empty so templ.SafeURL never receives "".
|
|
||||||
func safeHref(href string) string {
|
|
||||||
if href == "" {
|
|
||||||
return "#"
|
|
||||||
}
|
|
||||||
return href
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseHeadingLevel parses a 1..6 heading level. Defaults to 2 for safety.
|
|
||||||
func parseHeadingLevel(content map[string]any) int {
|
|
||||||
switch v := content["level"].(type) {
|
|
||||||
case float64:
|
|
||||||
l := int(v)
|
|
||||||
if l >= 1 && l <= 6 {
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
case int:
|
|
||||||
if v >= 1 && v <= 6 {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
case string:
|
|
||||||
if l, err := strconv.Atoi(v); err == nil && l >= 1 && l <= 6 {
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HeroGlitchMeta defines metadata for the cyberpunk glitch hero block.
|
|
||||||
var HeroGlitchMeta = blocks.BlockMeta{
|
|
||||||
Key: "hero_glitch",
|
|
||||||
Title: "Glitch Hero",
|
|
||||||
Description: "RGB-split H1, neon CTA, optional scanline overlay toggle",
|
|
||||||
Category: blocks.CategoryLayout,
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeroGlitchData is the typed view of the hero_glitch content map.
|
|
||||||
type HeroGlitchData struct {
|
|
||||||
Eyebrow string
|
|
||||||
Headline string
|
|
||||||
Sub string
|
|
||||||
CTA Link
|
|
||||||
SecondaryCTA Link
|
|
||||||
Scanlines bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeroGlitchBlock renders the hero_glitch block.
|
|
||||||
//
|
|
||||||
// Content shape (matches schemas/hero_glitch.schema.json):
|
|
||||||
// {eyebrow, headline, sub, cta:{label,href}, secondaryCta:{label,href}, scanlines:"on"|"off"}
|
|
||||||
func HeroGlitchBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := HeroGlitchData{
|
|
||||||
Eyebrow: getString(content, "eyebrow"),
|
|
||||||
Headline: getStringWithDefault(content, "headline", "// hero headline"),
|
|
||||||
Sub: getString(content, "sub"),
|
|
||||||
CTA: getLink(content, "cta"),
|
|
||||||
SecondaryCTA: getLink(content, "secondaryCta"),
|
|
||||||
Scanlines: parseScanlines(content),
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = heroGlitchComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseScanlines(content map[string]any) bool {
|
|
||||||
if v, ok := content["scanlines"].(string); ok {
|
|
||||||
return v == "on" || v == "true"
|
|
||||||
}
|
|
||||||
if v, ok := content["scanlines"].(bool); ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// heroGlitchComponent renders the cyberpunk:hero_glitch block with an RGB-split H1.
|
|
||||||
templ heroGlitchComponent(data HeroGlitchData) {
|
|
||||||
<section
|
|
||||||
data-block="cyberpunk:hero_glitch"
|
|
||||||
class="cyberpunk-hero relative w-full overflow-hidden py-24 md:py-32"
|
|
||||||
style="background-color: hsl(var(--background));"
|
|
||||||
>
|
|
||||||
if data.Scanlines {
|
|
||||||
<div aria-hidden="true" class="scanlines pointer-events-none absolute inset-0" data-scanlines-local></div>
|
|
||||||
}
|
|
||||||
<div class="relative z-10 max-w-5xl mx-auto px-4 text-center">
|
|
||||||
if data.Eyebrow != "" {
|
|
||||||
<p class="cyberpunk-eyebrow cyberpunk-mono inline-block px-3 py-1 mb-6 text-xs uppercase tracking-[0.35em]" style="color: hsl(var(--accent)); border: 1px dashed hsl(var(--accent));">
|
|
||||||
{ data.Eyebrow }
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
<h1
|
|
||||||
class="glitch cyberpunk-display text-5xl md:text-7xl font-bold leading-[1.05] tracking-tight mb-8"
|
|
||||||
data-text={ data.Headline }
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);"
|
|
||||||
>
|
|
||||||
{ data.Headline }
|
|
||||||
</h1>
|
|
||||||
if data.Sub != "" {
|
|
||||||
<p class="cyberpunk-sub mx-auto max-w-2xl text-lg md:text-xl mb-10" style="color: hsl(var(--muted-foreground));">
|
|
||||||
{ data.Sub }
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
|
||||||
if data.CTA.Label != "" {
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(safeHref(data.CTA.Href)) }
|
|
||||||
class="cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center gap-2 px-6 py-3 rounded-md font-semibold uppercase tracking-wider"
|
|
||||||
style="background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));"
|
|
||||||
>
|
|
||||||
<span>{ data.CTA.Label }</span>
|
|
||||||
<span aria-hidden="true" class="caret-blink">_</span>
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
if data.SecondaryCTA.Label != "" {
|
|
||||||
<a
|
|
||||||
href={ templ.SafeURL(safeHref(data.SecondaryCTA.Href)) }
|
|
||||||
class="cyberpunk-btn-ghost cyberpunk-mono inline-flex items-center gap-2 px-6 py-3 rounded-md font-semibold uppercase tracking-wider"
|
|
||||||
style="border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));"
|
|
||||||
>
|
|
||||||
<span>{ data.SecondaryCTA.Label }</span>
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
@ -1,191 +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"
|
|
||||||
|
|
||||||
// heroGlitchComponent renders the cyberpunk:hero_glitch block with an RGB-split H1.
|
|
||||||
func heroGlitchComponent(data HeroGlitchData) 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, "<section data-block=\"cyberpunk:hero_glitch\" class=\"cyberpunk-hero relative w-full overflow-hidden py-24 md:py-32\" style=\"background-color: hsl(var(--background));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Scanlines {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div aria-hidden=\"true\" class=\"scanlines pointer-events-none absolute inset-0\" data-scanlines-local></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"relative z-10 max-w-5xl mx-auto px-4 text-center\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Eyebrow != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<p class=\"cyberpunk-eyebrow cyberpunk-mono inline-block px-3 py-1 mb-6 text-xs uppercase tracking-[0.35em]\" style=\"color: hsl(var(--accent)); border: 1px dashed hsl(var(--accent));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.Eyebrow)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 16, Col: 19}
|
|
||||||
}
|
|
||||||
_, 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, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<h1 class=\"glitch cyberpunk-display text-5xl md:text-7xl font-bold leading-[1.05] tracking-tight mb-8\" data-text=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Headline)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 21, Col: 29}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" style=\"color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.Headline)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 24, Col: 19}
|
|
||||||
}
|
|
||||||
_, 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, "</h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.Sub != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<p class=\"cyberpunk-sub mx-auto max-w-2xl text-lg md:text-xl mb-10\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Sub)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 28, Col: 15}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"flex flex-col sm:flex-row gap-4 justify-center items-center\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.CTA.Label != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(safeHref(data.CTA.Href)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 34, Col: 51}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\" class=\"cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center gap-2 px-6 py-3 rounded-md font-semibold uppercase tracking-wider\" style=\"background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(data.CTA.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 38, Col: 28}
|
|
||||||
}
|
|
||||||
_, 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, "</span> <span aria-hidden=\"true\" class=\"caret-blink\">_</span></a> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if data.SecondaryCTA.Label != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(safeHref(data.SecondaryCTA.Href)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 44, Col: 60}
|
|
||||||
}
|
|
||||||
_, 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, "\" class=\"cyberpunk-btn-ghost cyberpunk-mono inline-flex items-center gap-2 px-6 py-3 rounded-md font-semibold uppercase tracking-wider\" style=\"border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 string
|
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(data.SecondaryCTA.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `hero_glitch.templ`, Line: 48, Col: 37}
|
|
||||||
}
|
|
||||||
_, 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, 17, "</span></a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</div></div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
17
main.go
17
main.go
@ -1,17 +0,0 @@
|
|||||||
//go:build wasip1
|
|
||||||
|
|
||||||
// Package main compiles the cyberpunk 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
|
|
||||||
277
manifest.yaml
Normal file
277
manifest.yaml
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
# Cyberpunk theme — codeless .bnp manifest (WO-WZ-021 Phase B).
|
||||||
|
# Synthesized into manifest.pb by `ninja plugin build` (no plugin.wasm).
|
||||||
|
theme_presets: presets.json
|
||||||
|
bundled_fonts: fonts.json
|
||||||
|
master_pages: master_pages.json
|
||||||
|
|
||||||
|
system_templates:
|
||||||
|
- key: cyberpunk
|
||||||
|
title: Cyberpunk
|
||||||
|
description: "Neon-on-black BlockNinja theme with glitch motifs, monospace accents, and magenta/cyan/lime tri-accent palette for SaaS, dev tools, and crypto."
|
||||||
|
|
||||||
|
page_templates:
|
||||||
|
- system: cyberpunk
|
||||||
|
key: default
|
||||||
|
title: Default
|
||||||
|
description: "Standard dark page with scanline overlay, sticky terminal-style header"
|
||||||
|
slots: [header, main, footer]
|
||||||
|
- system: cyberpunk
|
||||||
|
key: landing
|
||||||
|
title: Landing
|
||||||
|
description: "Hero with glitch H1, neon CTA, feature grid, social proof, footer"
|
||||||
|
slots: [hero, features, cta, footer]
|
||||||
|
- system: cyberpunk
|
||||||
|
key: article
|
||||||
|
title: Article
|
||||||
|
description: "Mono-metadata header, prose column, code-friendly aside"
|
||||||
|
slots: [header, main, aside, footer]
|
||||||
|
- system: cyberpunk
|
||||||
|
key: full-width
|
||||||
|
title: Full Width
|
||||||
|
description: "Edge-to-edge dashboard / showcase layout, no max-width"
|
||||||
|
slots: [header, main, footer]
|
||||||
|
|
||||||
|
template_overrides:
|
||||||
|
- { template: cyberpunk, block: heading }
|
||||||
|
- { template: cyberpunk, block: text }
|
||||||
|
- { template: cyberpunk, block: button }
|
||||||
|
- { template: cyberpunk, block: card }
|
||||||
|
|
||||||
|
email_wrappers:
|
||||||
|
- cyberpunk
|
||||||
|
|
||||||
|
css:
|
||||||
|
input_css_append: |
|
||||||
|
/* ============================================================
|
||||||
|
Cyberpunk — Neon-on-black BlockNinja theme
|
||||||
|
Scanlines / glitch / RGB-split / caret-blink / neon-edge utilities.
|
||||||
|
All colours consume the host shadcn HSL tokens via hsl(var(--token)).
|
||||||
|
No hardcoded hex / rgb / named colours.
|
||||||
|
============================================================ */
|
||||||
|
|
||||||
|
/* --- Typography fallbacks --------------------------------- */
|
||||||
|
|
||||||
|
.cyberpunk-body {
|
||||||
|
font-family: var(--font-body, "Inter", system-ui, -apple-system, "Segoe UI", sans-serif);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cyberpunk-mono,
|
||||||
|
.cyberpunk-mono *,
|
||||||
|
.cyberpunk-mono code,
|
||||||
|
pre.cyberpunk-mono,
|
||||||
|
code.cyberpunk-mono {
|
||||||
|
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cyberpunk-display {
|
||||||
|
font-family: var(--font-heading, "Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif);
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cyberpunk-prose,
|
||||||
|
.cyberpunk-prose p,
|
||||||
|
.cyberpunk-prose li {
|
||||||
|
font-family: var(--font-body, "Inter", system-ui, sans-serif);
|
||||||
|
line-height: 1.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cyberpunk-prose code {
|
||||||
|
color: hsl(var(--accent));
|
||||||
|
background-color: hsl(var(--muted));
|
||||||
|
padding: 0.125rem 0.375rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Scanlines -------------------------------------------- */
|
||||||
|
|
||||||
|
.scanlines {
|
||||||
|
opacity: 0.04;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
hsl(var(--foreground)) 0px,
|
||||||
|
hsl(var(--foreground)) 1px,
|
||||||
|
transparent 1px,
|
||||||
|
transparent 3px
|
||||||
|
);
|
||||||
|
background-size: 100% 3px;
|
||||||
|
animation: scanline-drift 6s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes scanline-drift {
|
||||||
|
0% { background-position: 0 0; }
|
||||||
|
100% { background-position: 0 3px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Glitch (RGB-split text-shadow) on H1/H2 -------------- */
|
||||||
|
|
||||||
|
.glitch {
|
||||||
|
position: relative;
|
||||||
|
text-shadow:
|
||||||
|
-2px 0 hsl(var(--primary)),
|
||||||
|
2px 0 hsl(var(--accent));
|
||||||
|
animation: glitch-x 3.6s steps(1, end) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glitch-x {
|
||||||
|
0%, 92%, 100% {
|
||||||
|
text-shadow:
|
||||||
|
-2px 0 hsl(var(--primary)),
|
||||||
|
2px 0 hsl(var(--accent));
|
||||||
|
}
|
||||||
|
93% {
|
||||||
|
text-shadow:
|
||||||
|
-3px 0 hsl(var(--primary)),
|
||||||
|
3px 0 hsl(var(--accent)),
|
||||||
|
0 1px hsl(var(--accent));
|
||||||
|
}
|
||||||
|
95% {
|
||||||
|
text-shadow:
|
||||||
|
-1px 0 hsl(var(--accent)),
|
||||||
|
4px 0 hsl(var(--primary));
|
||||||
|
}
|
||||||
|
97% {
|
||||||
|
text-shadow:
|
||||||
|
-2px 0 hsl(var(--primary)),
|
||||||
|
2px 0 hsl(var(--accent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- RGB-split hover/focus/active on primary buttons ------ */
|
||||||
|
|
||||||
|
.rgb-split {
|
||||||
|
transition: transform 120ms ease, box-shadow 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rgb-split:hover,
|
||||||
|
.rgb-split:focus-visible {
|
||||||
|
box-shadow:
|
||||||
|
-2px 0 0 hsl(var(--primary)),
|
||||||
|
2px 0 0 hsl(var(--accent));
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Touch tap-flash fallback (iOS strips :hover after touchend) */
|
||||||
|
.cyberpunk-btn:active,
|
||||||
|
.rgb-split:active,
|
||||||
|
button.cyberpunk-btn:active {
|
||||||
|
box-shadow:
|
||||||
|
-2px 0 0 hsl(var(--primary)),
|
||||||
|
2px 0 0 hsl(var(--accent));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* :focus-visible ring uses the ring token, not browser default */
|
||||||
|
.cyberpunk-btn:focus-visible,
|
||||||
|
.cyberpunk-btn-ghost:focus-visible,
|
||||||
|
button:focus-visible,
|
||||||
|
a:focus-visible {
|
||||||
|
outline: 2px solid hsl(var(--ring));
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Caret blink ------------------------------------------ */
|
||||||
|
|
||||||
|
.caret-blink {
|
||||||
|
display: inline-block;
|
||||||
|
animation: caret 1.05s steps(2, end) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes caret {
|
||||||
|
0%, 50% { opacity: 1; }
|
||||||
|
51%, 100% { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Neon edge utilities (magenta / cyan / lime) ---------- */
|
||||||
|
|
||||||
|
.neon-edge-magenta {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px hsl(var(--primary) / 0.4),
|
||||||
|
0 0 18px hsl(var(--primary) / 0.25);
|
||||||
|
transition: box-shadow 180ms ease, transform 180ms ease;
|
||||||
|
}
|
||||||
|
.neon-edge-magenta:hover,
|
||||||
|
.neon-edge-magenta:focus-within {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px hsl(var(--primary) / 0.85),
|
||||||
|
0 0 28px hsl(var(--primary) / 0.45);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.neon-edge-cyan {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px hsl(var(--accent) / 0.4),
|
||||||
|
0 0 18px hsl(var(--accent) / 0.25);
|
||||||
|
transition: box-shadow 180ms ease, transform 180ms ease;
|
||||||
|
}
|
||||||
|
.neon-edge-cyan:hover,
|
||||||
|
.neon-edge-cyan:focus-within {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px hsl(var(--accent) / 0.85),
|
||||||
|
0 0 28px hsl(var(--accent) / 0.45);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.neon-edge-lime {
|
||||||
|
/* Lime accent is the toxic-bloom primary; magenta-noir uses the primary
|
||||||
|
token. We reuse --ring as a third neon channel so this utility renders
|
||||||
|
visibly across all three presets. */
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px hsl(var(--ring) / 0.4),
|
||||||
|
0 0 18px hsl(var(--ring) / 0.25);
|
||||||
|
transition: box-shadow 180ms ease, transform 180ms ease;
|
||||||
|
}
|
||||||
|
.neon-edge-lime:hover,
|
||||||
|
.neon-edge-lime:focus-within {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 1px hsl(var(--ring) / 0.85),
|
||||||
|
0 0 28px hsl(var(--ring) / 0.45);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Card override dashed border --------------------------- */
|
||||||
|
|
||||||
|
.cyberpunk-card {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Status pill / dot animation -------------------------- */
|
||||||
|
|
||||||
|
.cyberpunk-status-dot {
|
||||||
|
animation: cyberpunk-pulse 2.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cyberpunk-pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.4; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Reduced motion: disable glitch, caret, scanline ------ */
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.glitch,
|
||||||
|
.caret-blink,
|
||||||
|
.scanlines,
|
||||||
|
.cyberpunk-status-dot {
|
||||||
|
animation: none !important;
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
.glitch {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
.scanlines {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.rgb-split:hover,
|
||||||
|
.rgb-split:focus-visible {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- High-contrast: kill scanlines ------------------------ */
|
||||||
|
|
||||||
|
@media (prefers-contrast: more) {
|
||||||
|
.scanlines {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
master_pages.json
Normal file
33
master_pages.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"key": "cyberpunk:default-master",
|
||||||
|
"title": "Cyberpunk Default Master",
|
||||||
|
"page_templates": ["default", "article"],
|
||||||
|
"blocks": [
|
||||||
|
{ "block_key": "cyberpunk:navbar_terminal", "title": "Top Nav", "content": { "menuName": "main", "commandPrefix": "~/" }, "slot": "header", "sort_order": 0 },
|
||||||
|
{ "block_key": "slot", "title": "Main Slot", "content": { "slotName": "main", "placeholder": "// content" }, "slot": "main", "sort_order": 0 },
|
||||||
|
{ "block_key": "cyberpunk:footer_grid", "title": "Site Footer", "content": { "showStatus": true, "buildHash": "auto" }, "slot": "footer", "sort_order": 0 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "cyberpunk:landing-master",
|
||||||
|
"title": "Cyberpunk Landing Master",
|
||||||
|
"page_templates": ["landing"],
|
||||||
|
"blocks": [
|
||||||
|
{ "block_key": "cyberpunk:hero_glitch", "title": "Glitch Hero", "content": { "eyebrow": "NEW", "headline": "Ship like it's 2049", "cta": { "label": "Get the SDK", "href": "#" } }, "slot": "hero", "sort_order": 0 },
|
||||||
|
{ "block_key": "slot", "title": "Features Slot", "content": { "slotName": "features" }, "slot": "features", "sort_order": 0 },
|
||||||
|
{ "block_key": "cyberpunk:cta_terminal", "title": "CTA Strip", "content": { "prompt": "$ npm i your-thing", "button": "Copy" }, "slot": "cta", "sort_order": 0 },
|
||||||
|
{ "block_key": "cyberpunk:footer_grid", "title": "Site Footer", "content": { "showStatus": true }, "slot": "footer", "sort_order": 0 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "cyberpunk:full-master",
|
||||||
|
"title": "Cyberpunk Full Master",
|
||||||
|
"page_templates": ["full-width"],
|
||||||
|
"blocks": [
|
||||||
|
{ "block_key": "cyberpunk:navbar_terminal", "title": "Top Nav", "content": { "menuName": "main" }, "slot": "header", "sort_order": 0 },
|
||||||
|
{ "block_key": "slot", "title": "Main Slot", "content": { "slotName": "main" }, "slot": "main", "sort_order": 0 },
|
||||||
|
{ "block_key": "cyberpunk:footer_grid", "title": "Site Footer", "content": { "showStatus": false }, "slot": "footer", "sort_order": 0 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NavbarTerminalMeta defines metadata for the cyberpunk:navbar_terminal block.
|
|
||||||
var NavbarTerminalMeta = blocks.BlockMeta{
|
|
||||||
Key: "navbar_terminal",
|
|
||||||
Title: "Terminal Navbar",
|
|
||||||
Description: "Mono-spaced navbar with $ command prefix and optional status dot",
|
|
||||||
Category: blocks.CategoryNavigation,
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// NavbarTerminalData is the typed view of the navbar_terminal content map.
|
|
||||||
type NavbarTerminalData struct {
|
|
||||||
MenuName string
|
|
||||||
CommandPrefix string
|
|
||||||
StatusDot bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NavbarTerminalBlock renders the navbar_terminal block.
|
|
||||||
//
|
|
||||||
// Content shape:
|
|
||||||
// {menuName, commandPrefix, statusDot:"on"|"off"|bool}
|
|
||||||
//
|
|
||||||
// menuName is the slug of a CMS-managed menu; the actual <ul> items are
|
|
||||||
// resolved by the host menu lookup. This block emits the chrome wrapper plus a
|
|
||||||
// data-menu-name hook the host renderer reads at runtime.
|
|
||||||
func NavbarTerminalBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
data := NavbarTerminalData{
|
|
||||||
MenuName: getStringWithDefault(content, "menuName", "main"),
|
|
||||||
CommandPrefix: getStringWithDefault(content, "commandPrefix", "~/"),
|
|
||||||
StatusDot: getBool(content, "statusDot", true),
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = navbarTerminalComponent(data).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// navbarTerminalComponent renders the cyberpunk:navbar_terminal block.
|
|
||||||
// At ≤768px the link list collapses behind an aria-expanded toggle button.
|
|
||||||
templ navbarTerminalComponent(data NavbarTerminalData) {
|
|
||||||
<nav
|
|
||||||
data-block="cyberpunk:navbar_terminal"
|
|
||||||
class="cyberpunk-navbar w-full"
|
|
||||||
style="background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));"
|
|
||||||
>
|
|
||||||
<div class="max-w-6xl mx-auto px-4 py-3 flex items-center justify-between gap-4">
|
|
||||||
<div class="flex items-center gap-3 min-w-0">
|
|
||||||
if data.StatusDot {
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
class="cyberpunk-status-dot inline-block w-2 h-2 rounded-full"
|
|
||||||
style="background-color: hsl(var(--accent)); box-shadow: 0 0 8px hsl(var(--accent));"
|
|
||||||
></span>
|
|
||||||
}
|
|
||||||
<span class="cyberpunk-mono text-sm" style="color: hsl(var(--accent));">
|
|
||||||
{ data.CommandPrefix }
|
|
||||||
</span>
|
|
||||||
<span class="cyberpunk-mono text-sm truncate" style="color: hsl(var(--foreground));">
|
|
||||||
{ data.MenuName }
|
|
||||||
</span>
|
|
||||||
<span aria-hidden="true" class="caret-blink cyberpunk-mono text-sm" style="color: hsl(var(--primary));">_</span>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-controls="cyberpunk-navbar-links"
|
|
||||||
class="cyberpunk-navbar-toggle md:hidden inline-flex items-center justify-center px-3 py-2 rounded-md cyberpunk-mono uppercase text-xs tracking-widest"
|
|
||||||
style="border: 1px solid hsl(var(--border)); color: hsl(var(--foreground));"
|
|
||||||
data-cyberpunk-navbar-toggle
|
|
||||||
>
|
|
||||||
MENU
|
|
||||||
</button>
|
|
||||||
<ul
|
|
||||||
id="cyberpunk-navbar-links"
|
|
||||||
class="cyberpunk-navbar-links hidden md:flex items-center gap-6 cyberpunk-mono text-sm uppercase tracking-widest"
|
|
||||||
style="color: hsl(var(--muted-foreground));"
|
|
||||||
data-menu-name={ data.MenuName }
|
|
||||||
>
|
|
||||||
<li class="cyberpunk-navbar-hint" style="color: hsl(var(--muted-foreground));">
|
|
||||||
{ "// menu items resolve at runtime" }
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
}
|
|
||||||
@ -1,104 +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"
|
|
||||||
|
|
||||||
// navbarTerminalComponent renders the cyberpunk:navbar_terminal block.
|
|
||||||
// At ≤768px the link list collapses behind an aria-expanded toggle button.
|
|
||||||
func navbarTerminalComponent(data NavbarTerminalData) 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, "<nav data-block=\"cyberpunk:navbar_terminal\" class=\"cyberpunk-navbar w-full\" style=\"background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));\"><div class=\"max-w-6xl mx-auto px-4 py-3 flex items-center justify-between gap-4\"><div class=\"flex items-center gap-3 min-w-0\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if data.StatusDot {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<span aria-hidden=\"true\" class=\"cyberpunk-status-dot inline-block w-2 h-2 rounded-full\" style=\"background-color: hsl(var(--accent)); box-shadow: 0 0 8px hsl(var(--accent));\"></span> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<span class=\"cyberpunk-mono text-sm\" style=\"color: hsl(var(--accent));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.CommandPrefix)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar_terminal.templ`, Line: 21, Col: 25}
|
|
||||||
}
|
|
||||||
_, 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, 4, "</span> <span class=\"cyberpunk-mono text-sm truncate\" style=\"color: hsl(var(--foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.MenuName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar_terminal.templ`, Line: 24, Col: 20}
|
|
||||||
}
|
|
||||||
_, 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, 5, "</span> <span aria-hidden=\"true\" class=\"caret-blink cyberpunk-mono text-sm\" style=\"color: hsl(var(--primary));\">_</span></div><button type=\"button\" aria-expanded=\"false\" aria-controls=\"cyberpunk-navbar-links\" class=\"cyberpunk-navbar-toggle md:hidden inline-flex items-center justify-center px-3 py-2 rounded-md cyberpunk-mono uppercase text-xs tracking-widest\" style=\"border: 1px solid hsl(var(--border)); color: hsl(var(--foreground));\" data-cyberpunk-navbar-toggle>MENU</button><ul id=\"cyberpunk-navbar-links\" class=\"cyberpunk-navbar-links hidden md:flex items-center gap-6 cyberpunk-mono text-sm uppercase tracking-widest\" style=\"color: hsl(var(--muted-foreground));\" data-menu-name=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.MenuName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar_terminal.templ`, Line: 42, Col: 34}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\"><li class=\"cyberpunk-navbar-hint\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs("// menu items resolve at runtime")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `navbar_terminal.templ`, Line: 45, Col: 41}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</li></ul></div></nav>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@ -2,11 +2,8 @@
|
|||||||
name = "cyberpunk"
|
name = "cyberpunk"
|
||||||
display_name = "Cyberpunk"
|
display_name = "Cyberpunk"
|
||||||
scope = "@themes"
|
scope = "@themes"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
description = "Neon-on-black BlockNinja theme with glitch motifs, monospace accents, and magenta/cyan/lime tri-accent palette for SaaS, dev tools, and crypto."
|
description = "Neon-on-black BlockNinja theme with glitch motifs, monospace accents, and magenta/cyan/lime tri-accent palette for SaaS, dev tools, and crypto."
|
||||||
kind = "theme"
|
kind = "theme"
|
||||||
categories = ["templates"]
|
categories = ["templates"]
|
||||||
tags = ["dark", "neon", "glitch", "monospace", "saas", "developer", "tech", "crypto", "fintech"]
|
tags = ["dark", "neon", "glitch", "monospace", "saas", "developer", "tech", "crypto", "fintech"]
|
||||||
|
|
||||||
[compatibility]
|
|
||||||
block_core = ">=0.15.0 <0.16.0"
|
|
||||||
|
|||||||
190
register.go
190
register.go
@ -1,190 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/a-h/templ"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
"git.dev.alexdunmow.com/block/core/plugin"
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// wrap adapts a templ-returning render function to templates.TemplateFunc.
|
|
||||||
// templ.Component already implements templates.HTMLComponent via Render.
|
|
||||||
func wrap(f func(ctx context.Context, doc map[string]any) templ.Component) templates.TemplateFunc {
|
|
||||||
return func(ctx context.Context, doc map[string]any) templates.HTMLComponent {
|
|
||||||
return f(ctx, doc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register is the plugin entry point that registers the Cyberpunk system template,
|
|
||||||
// page templates, theme-owned blocks, built-in overrides, and the email wrapper.
|
|
||||||
func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error {
|
|
||||||
// 1. System template metadata.
|
|
||||||
tr.RegisterSystemTemplate(templates.SystemTemplateMeta{
|
|
||||||
Key: "cyberpunk",
|
|
||||||
Title: "Cyberpunk",
|
|
||||||
Description: "Neon-on-black BlockNinja theme with glitch motifs, monospace accents, and magenta/cyan/lime tri-accent palette for SaaS, dev tools, and crypto.",
|
|
||||||
})
|
|
||||||
|
|
||||||
// 2. Page templates — slot lists match docs/works/cyberpunk.md byte-for-byte.
|
|
||||||
if err := tr.RegisterPageTemplate("cyberpunk", templates.PageTemplateMeta{
|
|
||||||
Key: "default",
|
|
||||||
Title: "Default",
|
|
||||||
Description: "Standard dark page with scanline overlay, sticky terminal-style header",
|
|
||||||
Slots: []string{"header", "main", "footer"},
|
|
||||||
}, wrap(RenderCyberpunk)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("cyberpunk", templates.PageTemplateMeta{
|
|
||||||
Key: "landing",
|
|
||||||
Title: "Landing",
|
|
||||||
Description: "Hero with glitch H1, neon CTA, feature grid, social proof, footer",
|
|
||||||
Slots: []string{"hero", "features", "cta", "footer"},
|
|
||||||
}, wrap(RenderCyberpunkLanding)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("cyberpunk", templates.PageTemplateMeta{
|
|
||||||
Key: "article",
|
|
||||||
Title: "Article",
|
|
||||||
Description: "Mono-metadata header, prose column, code-friendly aside",
|
|
||||||
Slots: []string{"header", "main", "aside", "footer"},
|
|
||||||
}, wrap(RenderCyberpunkArticle)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tr.RegisterPageTemplate("cyberpunk", templates.PageTemplateMeta{
|
|
||||||
Key: "full-width",
|
|
||||||
Title: "Full Width",
|
|
||||||
Description: "Edge-to-edge dashboard / showcase layout, no max-width",
|
|
||||||
Slots: []string{"header", "main", "footer"},
|
|
||||||
}, wrap(RenderCyberpunkFullWidth)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Load block schemas BEFORE registering any blocks.
|
|
||||||
if err := br.LoadSchemasFromFS(Schemas()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Theme-owned blocks (seven, per spec section "Blocks to build").
|
|
||||||
br.Register(HeroGlitchMeta, HeroGlitchBlock)
|
|
||||||
br.Register(CTATerminalMeta, CTATerminalBlock)
|
|
||||||
br.Register(NavbarTerminalMeta, NavbarTerminalBlock)
|
|
||||||
br.Register(FooterGridMeta, FooterGridBlock)
|
|
||||||
br.Register(FeatureCardNeonMeta, FeatureCardNeonBlock)
|
|
||||||
br.Register(StatsGlowMeta, StatsGlowBlock)
|
|
||||||
br.Register(CodeNeonMeta, CodeNeonBlock)
|
|
||||||
|
|
||||||
// 5. Built-in block overrides — applied only when this theme is active.
|
|
||||||
br.RegisterTemplateOverride("cyberpunk", "heading", CyberpunkHeadingBlock)
|
|
||||||
br.RegisterTemplateOverride("cyberpunk", "text", CyberpunkTextBlock)
|
|
||||||
br.RegisterTemplateOverride("cyberpunk", "button", CyberpunkButtonBlock)
|
|
||||||
br.RegisterTemplateOverride("cyberpunk", "card", CyberpunkCardBlock)
|
|
||||||
|
|
||||||
// 6. Email wrapper.
|
|
||||||
tr.RegisterEmailWrapper("cyberpunk", CyberpunkEmailWrapper)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultMasterPages returns the three master pages Cyberpunk seeds on first load.
|
|
||||||
// Spec table — section "Master pages" — drives keys, blocks, slots and sort orders.
|
|
||||||
func DefaultMasterPages() []plugin.MasterPageDefinition {
|
|
||||||
return []plugin.MasterPageDefinition{
|
|
||||||
{
|
|
||||||
Key: "cyberpunk:default-master",
|
|
||||||
Title: "Cyberpunk Default Master",
|
|
||||||
PageTemplates: []string{"default", "article"},
|
|
||||||
Blocks: []plugin.MasterPageBlock{
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:navbar_terminal",
|
|
||||||
Title: "Top Nav",
|
|
||||||
Content: map[string]any{"menuName": "main", "commandPrefix": "~/"},
|
|
||||||
Slot: "header",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "slot",
|
|
||||||
Title: "Main Slot",
|
|
||||||
Content: map[string]any{"slotName": "main", "placeholder": "// content"},
|
|
||||||
Slot: "main",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:footer_grid",
|
|
||||||
Title: "Site Footer",
|
|
||||||
Content: map[string]any{"showStatus": true, "buildHash": "auto"},
|
|
||||||
Slot: "footer",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "cyberpunk:landing-master",
|
|
||||||
Title: "Cyberpunk Landing Master",
|
|
||||||
PageTemplates: []string{"landing"},
|
|
||||||
Blocks: []plugin.MasterPageBlock{
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:hero_glitch",
|
|
||||||
Title: "Glitch Hero",
|
|
||||||
Content: map[string]any{"eyebrow": "NEW", "headline": "Ship like it's 2049", "cta": map[string]any{"label": "Get the SDK", "href": "#"}},
|
|
||||||
Slot: "hero",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "slot",
|
|
||||||
Title: "Features Slot",
|
|
||||||
Content: map[string]any{"slotName": "features"},
|
|
||||||
Slot: "features",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:cta_terminal",
|
|
||||||
Title: "CTA Strip",
|
|
||||||
Content: map[string]any{"prompt": "$ npm i your-thing", "button": "Copy"},
|
|
||||||
Slot: "cta",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:footer_grid",
|
|
||||||
Title: "Site Footer",
|
|
||||||
Content: map[string]any{"showStatus": true},
|
|
||||||
Slot: "footer",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "cyberpunk:full-master",
|
|
||||||
Title: "Cyberpunk Full Master",
|
|
||||||
PageTemplates: []string{"full-width"},
|
|
||||||
Blocks: []plugin.MasterPageBlock{
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:navbar_terminal",
|
|
||||||
Title: "Top Nav",
|
|
||||||
Content: map[string]any{"menuName": "main"},
|
|
||||||
Slot: "header",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "slot",
|
|
||||||
Title: "Main Slot",
|
|
||||||
Content: map[string]any{"slotName": "main"},
|
|
||||||
Slot: "main",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BlockKey: "cyberpunk:footer_grid",
|
|
||||||
Title: "Site Footer",
|
|
||||||
Content: map[string]any{"showStatus": false},
|
|
||||||
Slot: "footer",
|
|
||||||
SortOrder: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
"git.dev.alexdunmow.com/block/core/plugin"
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Registration is the compile-time plugin registration for the Cyberpunk theme.
|
|
||||||
var Registration = plugin.PluginRegistration{
|
|
||||||
Name: "cyberpunk",
|
|
||||||
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() },
|
|
||||||
RequiredIconPacks: plugin.ParseRequiredIconPacks(pluginModBytes),
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/blocks"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StatsGlowMeta defines metadata for the cyberpunk:stats_glow block.
|
|
||||||
var StatsGlowMeta = blocks.BlockMeta{
|
|
||||||
Key: "stats_glow",
|
|
||||||
Title: "Glow Stats",
|
|
||||||
Description: "Big mono numerals with neon accent underline",
|
|
||||||
Category: "display",
|
|
||||||
Source: "cyberpunk",
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatGlowItem is one stat in the grid.
|
|
||||||
type StatGlowItem struct {
|
|
||||||
Value string
|
|
||||||
Label string
|
|
||||||
Suffix string
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatsGlowBlock renders the stats_glow block.
|
|
||||||
//
|
|
||||||
// Content shape:
|
|
||||||
// {items:[{value, label, suffix}]}
|
|
||||||
func StatsGlowBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
raw := getSlice(content, "items")
|
|
||||||
items := make([]StatGlowItem, 0, len(raw))
|
|
||||||
for _, item := range raw {
|
|
||||||
items = append(items, StatGlowItem{
|
|
||||||
Value: getString(item, "value"),
|
|
||||||
Label: getString(item, "label"),
|
|
||||||
Suffix: getString(item, "suffix"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = statsGlowComponent(items).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// statsGridColumns returns the tailwind grid-column class for n stats.
|
|
||||||
func statsGridColumns(n int) string {
|
|
||||||
switch n {
|
|
||||||
case 0, 1:
|
|
||||||
return "grid-cols-1"
|
|
||||||
case 2:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2"
|
|
||||||
case 3:
|
|
||||||
return "grid-cols-1 sm:grid-cols-3"
|
|
||||||
default:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// statsGlowComponent renders the cyberpunk:stats_glow block.
|
|
||||||
templ statsGlowComponent(items []StatGlowItem) {
|
|
||||||
<section
|
|
||||||
data-block="cyberpunk:stats_glow"
|
|
||||||
class="cyberpunk-stats w-full py-16"
|
|
||||||
style="background-color: hsl(var(--background));"
|
|
||||||
>
|
|
||||||
<div class="max-w-6xl mx-auto px-4">
|
|
||||||
if len(items) == 0 {
|
|
||||||
<div class="text-center cyberpunk-mono text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">
|
|
||||||
{ "// add items to render stats" }
|
|
||||||
</div>
|
|
||||||
} else {
|
|
||||||
<div class={ "grid gap-8 text-center", statsGridColumns(len(items)) }>
|
|
||||||
for _, stat := range items {
|
|
||||||
<div class="cyberpunk-stat-cell">
|
|
||||||
<div
|
|
||||||
class="cyberpunk-mono cyberpunk-stat-number text-5xl md:text-6xl font-bold tracking-tight"
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);"
|
|
||||||
>
|
|
||||||
<span>{ stat.Value }</span>
|
|
||||||
if stat.Suffix != "" {
|
|
||||||
<span style="color: hsl(var(--primary));">{ stat.Suffix }</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="cyberpunk-stat-underline mx-auto mt-2 mb-3 h-px w-12" style="background-color: hsl(var(--accent));"></div>
|
|
||||||
<div class="cyberpunk-mono cyberpunk-stat-label text-xs uppercase tracking-widest" style="color: hsl(var(--muted-foreground));">
|
|
||||||
{ stat.Label }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
@ -1,160 +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"
|
|
||||||
|
|
||||||
// statsGridColumns returns the tailwind grid-column class for n stats.
|
|
||||||
func statsGridColumns(n int) string {
|
|
||||||
switch n {
|
|
||||||
case 0, 1:
|
|
||||||
return "grid-cols-1"
|
|
||||||
case 2:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2"
|
|
||||||
case 3:
|
|
||||||
return "grid-cols-1 sm:grid-cols-3"
|
|
||||||
default:
|
|
||||||
return "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// statsGlowComponent renders the cyberpunk:stats_glow block.
|
|
||||||
func statsGlowComponent(items []StatGlowItem) 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, "<section data-block=\"cyberpunk:stats_glow\" class=\"cyberpunk-stats w-full py-16\" style=\"background-color: hsl(var(--background));\"><div class=\"max-w-6xl mx-auto px-4\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if len(items) == 0 {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"text-center cyberpunk-mono text-xs uppercase tracking-widest\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("// add items to render stats")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `stats_glow.templ`, Line: 27, Col: 37}
|
|
||||||
}
|
|
||||||
_, 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, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var templ_7745c5c3_Var3 = []any{"grid gap-8 text-center", statsGridColumns(len(items))}
|
|
||||||
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, 4, "<div class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var3).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `stats_glow.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, stat := range items {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"cyberpunk-stat-cell\"><div class=\"cyberpunk-mono cyberpunk-stat-number text-5xl md:text-6xl font-bold tracking-tight\" style=\"color: hsl(var(--foreground)); font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);\"><span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(stat.Value)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `stats_glow.templ`, Line: 37, Col: 26}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if stat.Suffix != "" {
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<span style=\"color: hsl(var(--primary));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(stat.Suffix)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `stats_glow.templ`, Line: 39, Col: 64}
|
|
||||||
}
|
|
||||||
_, 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, 9, "</span>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div><div class=\"cyberpunk-stat-underline mx-auto mt-2 mb-3 h-px w-12\" style=\"background-color: hsl(var(--accent));\"></div><div class=\"cyberpunk-mono cyberpunk-stat-label text-xs uppercase tracking-widest\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(stat.Label)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `stats_glow.templ`, Line: 44, Col: 20}
|
|
||||||
}
|
|
||||||
_, 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, 11, "</div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></section>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
237
template.templ
237
template.templ
@ -1,237 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.dev.alexdunmow.com/block/core/templates/bn"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PageData carries the rendered slots and assorted page chrome data passed
|
|
||||||
// from the CMS into a Cyberpunk page template.
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseCyberpunkPageData converts the loose doc map the renderer is handed into a typed PageData.
|
|
||||||
func parseCyberpunkPageData(doc map[string]any) PageData {
|
|
||||||
title := "Untitled"
|
|
||||||
if t, ok := doc["title"].(string); ok && t != "" {
|
|
||||||
title = t
|
|
||||||
}
|
|
||||||
|
|
||||||
slots := map[string]string{}
|
|
||||||
if s, ok := doc["slots"].(map[string]string); ok {
|
|
||||||
slots = s
|
|
||||||
}
|
|
||||||
|
|
||||||
themeCSS, _ := doc["theme_css"].(string)
|
|
||||||
structuredData, _ := doc["structured_data"].(string)
|
|
||||||
cssHash, _ := doc["css_hash"].(string)
|
|
||||||
pageviewNonce, _ := doc["pageview_nonce"].(string)
|
|
||||||
|
|
||||||
themeMode := "dark"
|
|
||||||
if tm, ok := doc["theme_mode"].(string); ok && tm != "" {
|
|
||||||
themeMode = tm
|
|
||||||
}
|
|
||||||
|
|
||||||
return PageData{
|
|
||||||
Title: title,
|
|
||||||
Slots: slots,
|
|
||||||
ThemeMode: themeMode,
|
|
||||||
ThemeCSS: themeCSS,
|
|
||||||
SiteSettings: bn.ParseSiteSettings(doc),
|
|
||||||
PageMeta: bn.ParsePageMeta(doc),
|
|
||||||
StructuredData: structuredData,
|
|
||||||
CSSHash: cssHash,
|
|
||||||
PageviewNonce: pageviewNonce,
|
|
||||||
EngagementConfig: bn.ParseEngagementConfig(doc),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanlineOverlay renders the global scanline overlay element (fixed, pointer-events: none).
|
|
||||||
templ scanlineOverlay() {
|
|
||||||
<div aria-hidden="true" class="scanlines pointer-events-none fixed inset-0 z-50" data-cyberpunk-scanlines></div>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cyberpunk renders the default page template.
|
|
||||||
templ Cyberpunk(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="dark">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: []string{"/templates/cyberpunk/css/cyberpunk.css"},
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
@scanlineOverlay()
|
|
||||||
<header class="cyberpunk-chrome w-full sticky top-0 z-40" style="background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</header>
|
|
||||||
<main class="flex-grow w-full max-w-6xl mx-auto px-4 py-12">
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
@templ.Raw(main)
|
|
||||||
} else {
|
|
||||||
<div class="py-20 text-center cyberpunk-empty" style="color: hsl(var(--muted-foreground));">
|
|
||||||
<p class="cyberpunk-mono">No content blocks assigned to this page.</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</main>
|
|
||||||
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// CyberpunkLanding renders the marketing landing template with hero/features/cta/footer slots.
|
|
||||||
templ CyberpunkLanding(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="dark">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: []string{"/templates/cyberpunk/css/cyberpunk.css"},
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
@scanlineOverlay()
|
|
||||||
<section class="w-full">
|
|
||||||
@templ.Raw(data.Slots["hero"])
|
|
||||||
</section>
|
|
||||||
<section class="w-full max-w-6xl mx-auto px-4 py-16">
|
|
||||||
@templ.Raw(data.Slots["features"])
|
|
||||||
</section>
|
|
||||||
<section class="w-full">
|
|
||||||
@templ.Raw(data.Slots["cta"])
|
|
||||||
</section>
|
|
||||||
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// CyberpunkArticle renders the article template with mono-metadata header and a code-friendly aside.
|
|
||||||
templ CyberpunkArticle(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="dark">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: []string{"/templates/cyberpunk/css/cyberpunk.css"},
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
@scanlineOverlay()
|
|
||||||
<header class="w-full" style="border-bottom: 1px solid hsl(var(--border));">
|
|
||||||
<div class="max-w-4xl mx-auto px-4 py-6 cyberpunk-mono text-xs uppercase tracking-widest">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<main class="flex-grow w-full max-w-4xl mx-auto px-4 py-12 grid gap-10 lg:grid-cols-[1fr_240px]">
|
|
||||||
<article class="cyberpunk-prose prose prose-invert max-w-none">
|
|
||||||
@templ.Raw(data.Slots["main"])
|
|
||||||
</article>
|
|
||||||
<aside class="cyberpunk-aside cyberpunk-mono text-sm" style="color: hsl(var(--muted-foreground));">
|
|
||||||
@templ.Raw(data.Slots["aside"])
|
|
||||||
</aside>
|
|
||||||
</main>
|
|
||||||
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// CyberpunkFullWidth renders the edge-to-edge template (no max-width clamping on main).
|
|
||||||
templ CyberpunkFullWidth(data PageData) {
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="dark">
|
|
||||||
@bn.Head(bn.HeadData{
|
|
||||||
Title: data.Title,
|
|
||||||
Settings: data.SiteSettings,
|
|
||||||
PageMeta: data.PageMeta,
|
|
||||||
ThemeMode: data.ThemeMode,
|
|
||||||
ThemeCSS: data.ThemeCSS,
|
|
||||||
PluginStyles: []string{"/templates/cyberpunk/css/cyberpunk.css"},
|
|
||||||
StructuredData: data.StructuredData,
|
|
||||||
CSSHash: data.CSSHash,
|
|
||||||
PageviewNonce: data.PageviewNonce,
|
|
||||||
EngagementConfig: data.EngagementConfig,
|
|
||||||
})
|
|
||||||
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
|
||||||
@bn.AdminBypassBanner(data.SiteSettings)
|
|
||||||
@scanlineOverlay()
|
|
||||||
<header class="cyberpunk-chrome w-full sticky top-0 z-40" style="background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));">
|
|
||||||
@templ.Raw(data.Slots["header"])
|
|
||||||
</header>
|
|
||||||
<main class="flex-grow w-full">
|
|
||||||
if main, ok := data.Slots["main"]; ok && main != "" {
|
|
||||||
@templ.Raw(main)
|
|
||||||
} else {
|
|
||||||
<div class="py-20 text-center cyberpunk-mono" style="color: hsl(var(--muted-foreground));">
|
|
||||||
<p>No content blocks assigned to this page.</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</main>
|
|
||||||
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">
|
|
||||||
@templ.Raw(data.Slots["footer"])
|
|
||||||
</footer>
|
|
||||||
@bn.BodyEnd(data.SiteSettings)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunk renders the default Cyberpunk page template.
|
|
||||||
func RenderCyberpunk(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return Cyberpunk(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunkLanding renders the Cyberpunk landing page template.
|
|
||||||
func RenderCyberpunkLanding(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return CyberpunkLanding(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunkArticle renders the Cyberpunk article page template.
|
|
||||||
func RenderCyberpunkArticle(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return CyberpunkArticle(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunkFullWidth renders the Cyberpunk full-width page template.
|
|
||||||
func RenderCyberpunkFullWidth(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return CyberpunkFullWidth(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
@ -1,520 +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 the rendered slots and assorted page chrome data passed
|
|
||||||
// from the CMS into a Cyberpunk page template.
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseCyberpunkPageData converts the loose doc map the renderer is handed into a typed PageData.
|
|
||||||
func parseCyberpunkPageData(doc map[string]any) PageData {
|
|
||||||
title := "Untitled"
|
|
||||||
if t, ok := doc["title"].(string); ok && t != "" {
|
|
||||||
title = t
|
|
||||||
}
|
|
||||||
|
|
||||||
slots := map[string]string{}
|
|
||||||
if s, ok := doc["slots"].(map[string]string); ok {
|
|
||||||
slots = s
|
|
||||||
}
|
|
||||||
|
|
||||||
themeCSS, _ := doc["theme_css"].(string)
|
|
||||||
structuredData, _ := doc["structured_data"].(string)
|
|
||||||
cssHash, _ := doc["css_hash"].(string)
|
|
||||||
pageviewNonce, _ := doc["pageview_nonce"].(string)
|
|
||||||
|
|
||||||
themeMode := "dark"
|
|
||||||
if tm, ok := doc["theme_mode"].(string); ok && tm != "" {
|
|
||||||
themeMode = tm
|
|
||||||
}
|
|
||||||
|
|
||||||
return PageData{
|
|
||||||
Title: title,
|
|
||||||
Slots: slots,
|
|
||||||
ThemeMode: themeMode,
|
|
||||||
ThemeCSS: themeCSS,
|
|
||||||
SiteSettings: bn.ParseSiteSettings(doc),
|
|
||||||
PageMeta: bn.ParsePageMeta(doc),
|
|
||||||
StructuredData: structuredData,
|
|
||||||
CSSHash: cssHash,
|
|
||||||
PageviewNonce: pageviewNonce,
|
|
||||||
EngagementConfig: bn.ParseEngagementConfig(doc),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanlineOverlay renders the global scanline overlay element (fixed, pointer-events: none).
|
|
||||||
func scanlineOverlay() 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, "<div aria-hidden=\"true\" class=\"scanlines pointer-events-none fixed inset-0 z-50\" data-cyberpunk-scanlines></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cyberpunk renders the default page template.
|
|
||||||
func Cyberpunk(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, 2, "<!doctype html><html lang=\"en\" class=\"dark\">")
|
|
||||||
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/cyberpunk/css/cyberpunk.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, 3, "<body class=\"cyberpunk-body min-h-screen flex flex-col antialiased\" style=\"background-color: hsl(var(--background)); color: hsl(var(--foreground));\">")
|
|
||||||
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 = scanlineOverlay().Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<header class=\"cyberpunk-chrome w-full sticky top-0 z-40\" style=\"background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));\">")
|
|
||||||
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, 5, "</header><main class=\"flex-grow w-full max-w-6xl mx-auto px-4 py-12\">")
|
|
||||||
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, 6, "<div class=\"py-20 text-center cyberpunk-empty\" style=\"color: hsl(var(--muted-foreground));\"><p class=\"cyberpunk-mono\">No content blocks assigned to this page.</p></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</main><footer class=\"w-full mt-auto\" style=\"border-top: 1px solid hsl(var(--border));\">")
|
|
||||||
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, 8, "</footer>")
|
|
||||||
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, 9, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CyberpunkLanding renders the marketing landing template with hero/features/cta/footer slots.
|
|
||||||
func CyberpunkLanding(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, 10, "<!doctype html><html lang=\"en\" class=\"dark\">")
|
|
||||||
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/cyberpunk/css/cyberpunk.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, 11, "<body class=\"cyberpunk-body min-h-screen flex flex-col antialiased\" style=\"background-color: hsl(var(--background)); color: hsl(var(--foreground));\">")
|
|
||||||
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 = scanlineOverlay().Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<section class=\"w-full\">")
|
|
||||||
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, 13, "</section><section class=\"w-full max-w-6xl mx-auto px-4 py-16\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["features"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</section><section class=\"w-full\">")
|
|
||||||
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, "</section><footer class=\"w-full mt-auto\" style=\"border-top: 1px solid hsl(var(--border));\">")
|
|
||||||
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, "</footer>")
|
|
||||||
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, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CyberpunkArticle renders the article template with mono-metadata header and a code-friendly aside.
|
|
||||||
func CyberpunkArticle(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, 18, "<!doctype html><html lang=\"en\" class=\"dark\">")
|
|
||||||
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/cyberpunk/css/cyberpunk.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, "<body class=\"cyberpunk-body min-h-screen flex flex-col antialiased\" style=\"background-color: hsl(var(--background)); color: hsl(var(--foreground));\">")
|
|
||||||
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 = scanlineOverlay().Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<header class=\"w-full\" style=\"border-bottom: 1px solid hsl(var(--border));\"><div class=\"max-w-4xl mx-auto px-4 py-6 cyberpunk-mono text-xs uppercase tracking-widest\">")
|
|
||||||
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, "</div></header><main class=\"flex-grow w-full max-w-4xl mx-auto px-4 py-12 grid gap-10 lg:grid-cols-[1fr_240px]\"><article class=\"cyberpunk-prose prose prose-invert max-w-none\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["main"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</article><aside class=\"cyberpunk-aside cyberpunk-mono text-sm\" style=\"color: hsl(var(--muted-foreground));\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ.Raw(data.Slots["aside"]).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</aside></main><footer class=\"w-full mt-auto\" style=\"border-top: 1px solid hsl(var(--border));\">")
|
|
||||||
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, 24, "</footer>")
|
|
||||||
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, 25, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CyberpunkFullWidth renders the edge-to-edge template (no max-width clamping on main).
|
|
||||||
func CyberpunkFullWidth(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_Var5 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var5 == nil {
|
|
||||||
templ_7745c5c3_Var5 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<!doctype html><html lang=\"en\" class=\"dark\">")
|
|
||||||
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/cyberpunk/css/cyberpunk.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, 27, "<body class=\"cyberpunk-body min-h-screen flex flex-col antialiased\" style=\"background-color: hsl(var(--background)); color: hsl(var(--foreground));\">")
|
|
||||||
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 = scanlineOverlay().Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<header class=\"cyberpunk-chrome w-full sticky top-0 z-40\" style=\"background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));\">")
|
|
||||||
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, 29, "</header><main class=\"flex-grow w-full\">")
|
|
||||||
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, 30, "<div class=\"py-20 text-center cyberpunk-mono\" style=\"color: hsl(var(--muted-foreground));\"><p>No content blocks assigned to this page.</p></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</main><footer class=\"w-full mt-auto\" style=\"border-top: 1px solid hsl(var(--border));\">")
|
|
||||||
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, 32, "</footer>")
|
|
||||||
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, 33, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunk renders the default Cyberpunk page template.
|
|
||||||
func RenderCyberpunk(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return Cyberpunk(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunkLanding renders the Cyberpunk landing page template.
|
|
||||||
func RenderCyberpunkLanding(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return CyberpunkLanding(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunkArticle renders the Cyberpunk article page template.
|
|
||||||
func RenderCyberpunkArticle(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return CyberpunkArticle(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderCyberpunkFullWidth renders the Cyberpunk full-width page template.
|
|
||||||
func RenderCyberpunkFullWidth(ctx context.Context, doc map[string]any) templ.Component {
|
|
||||||
return CyberpunkFullWidth(parseCyberpunkPageData(doc))
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
12
templates/cyberpunk/article.ninjatpl
Normal file
12
templates/cyberpunk/article.ninjatpl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<div aria-hidden="true" class="scanlines pointer-events-none fixed inset-0 z-50" data-cyberpunk-scanlines></div>
|
||||||
|
<header class="w-full" style="border-bottom: 1px solid hsl(var(--border));"><div class="max-w-4xl mx-auto px-4 py-6 cyberpunk-mono text-xs uppercase tracking-widest">{{ slots.header|safe }}</div></header>
|
||||||
|
<main class="flex-grow w-full max-w-4xl mx-auto px-4 py-12 grid gap-10 lg:grid-cols-[1fr_240px]"><article class="cyberpunk-prose prose prose-invert max-w-none">{{ slots.main|safe }}</article><aside class="cyberpunk-aside cyberpunk-mono text-sm" style="color: hsl(var(--muted-foreground));">{{ slots.aside|safe }}</aside></main>
|
||||||
|
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
12
templates/cyberpunk/default.ninjatpl
Normal file
12
templates/cyberpunk/default.ninjatpl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<div aria-hidden="true" class="scanlines pointer-events-none fixed inset-0 z-50" data-cyberpunk-scanlines></div>
|
||||||
|
<header class="cyberpunk-chrome w-full sticky top-0 z-40" style="background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));">{{ slots.header|safe }}</header>
|
||||||
|
<main class="flex-grow w-full max-w-6xl mx-auto px-4 py-12">{% if slots.main %}{{ slots.main|safe }}{% else %}<div class="py-20 text-center cyberpunk-empty" style="color: hsl(var(--muted-foreground));"><p class="cyberpunk-mono">No content blocks assigned to this page.</p></div>{% endif %}</main>
|
||||||
|
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
12
templates/cyberpunk/full-width.ninjatpl
Normal file
12
templates/cyberpunk/full-width.ninjatpl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<div aria-hidden="true" class="scanlines pointer-events-none fixed inset-0 z-50" data-cyberpunk-scanlines></div>
|
||||||
|
<header class="cyberpunk-chrome w-full sticky top-0 z-40" style="background-color: hsl(var(--background) / 0.85); border-bottom: 1px solid hsl(var(--border));">{{ slots.header|safe }}</header>
|
||||||
|
<main class="flex-grow w-full">{% if slots.main %}{{ slots.main|safe }}{% else %}<div class="py-20 text-center cyberpunk-mono" style="color: hsl(var(--muted-foreground));"><p>No content blocks assigned to this page.</p></div>{% endif %}</main>
|
||||||
|
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
templates/cyberpunk/landing.ninjatpl
Normal file
13
templates/cyberpunk/landing.ninjatpl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
{{ head_html|safe }}
|
||||||
|
<body class="cyberpunk-body min-h-screen flex flex-col antialiased" style="background-color: hsl(var(--background)); color: hsl(var(--foreground));">
|
||||||
|
{{ admin_banner_html|safe }}
|
||||||
|
<div aria-hidden="true" class="scanlines pointer-events-none fixed inset-0 z-50" data-cyberpunk-scanlines></div>
|
||||||
|
<section class="w-full">{{ slots.hero|safe }}</section>
|
||||||
|
<section class="w-full max-w-6xl mx-auto px-4 py-16">{{ slots.features|safe }}</section>
|
||||||
|
<section class="w-full">{{ slots.cta|safe }}</section>
|
||||||
|
<footer class="w-full mt-auto" style="border-top: 1px solid hsl(var(--border));">{{ slots.footer|safe }}</footer>
|
||||||
|
{{ body_end_html|safe }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
50
templates/email/cyberpunk.ninjatpl
Normal file
50
templates/email/cyberpunk.ninjatpl
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="x-apple-disable-message-reformatting">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<title>{{ site_name }}</title>
|
||||||
|
<style type="text/css">
|
||||||
|
body { background:#0a0a12; margin:0; padding:0; color: hsl(260 25% 92%); }
|
||||||
|
table, td { mso-table-lspace:0pt; mso-table-rspace:0pt; }
|
||||||
|
a { color: inherit; }
|
||||||
|
.cyberpunk-preheader { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
||||||
|
.cyberpunk-divider { border-top:1px solid hsl(320 100% 60%); }
|
||||||
|
@media only screen and (max-width: 620px) {
|
||||||
|
.email-container { width:100% !important; max-width:100% !important; }
|
||||||
|
.content-padding { padding-left:24px !important; padding-right:24px !important; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#0a0a12" style="margin:0;padding:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;">
|
||||||
|
{% if preview_text %}<div class="cyberpunk-preheader" style="display:none;max-height:0;overflow:hidden;mso-hide:all;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;">$ from: {{ site_name }} — {{ preview_text }}</div>{% else %}<div class="cyberpunk-preheader" style="display:none;max-height:0;overflow:hidden;mso-hide:all;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;">$ from: {{ site_name }}</div>{% endif %}
|
||||||
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#0a0a12">
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding:48px 12px;">
|
||||||
|
<table role="presentation" class="email-container" width="600" cellpadding="0" cellspacing="0" border="0" bgcolor="#101020" style="max-width:600px;border:1px solid hsl(258 28% 20%);">
|
||||||
|
<tr>
|
||||||
|
<td class="content-padding" align="center" style="padding:32px 40px;border-bottom:1px solid hsl(320 100% 60%);">
|
||||||
|
<div class="cyberpunk-preheader" style="font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size:12px;letter-spacing:0.2em;text-transform:uppercase;">$ from: {{ site_name }}</div>
|
||||||
|
{% if logo_url %}<img src="{{ logo_url }}" alt="{{ site_name }}" style="margin-top:12px;max-height:48px;width:auto;display:inline-block;">{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-padding" style="padding:40px 48px;font-size:16px;line-height:1.7;">{{ body|safe }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="cyberpunk-divider" height="1" style="border-top:1px solid hsl(320 100% 60%);font-size:0;line-height:0;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content-padding" align="center" style="padding:24px 48px 40px;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size:12px;letter-spacing:0.15em;text-transform:uppercase;">
|
||||||
|
{% if site_url %}<p style="margin:0 0 12px;"><a href="{{ site_url }}" style="text-decoration:none;">{{ site_url }}</a></p>{% endif %}
|
||||||
|
{% if unsubscribe_url %}<p style="margin:0;"><a href="{{ unsubscribe_url }}" style="text-decoration:none;">[esc] unsubscribe</a></p>{% else %}<p style="margin:0;">[esc] unsubscribe</p>{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
templates/overrides/cyberpunk/button.ninjatpl
Normal file
1
templates/overrides/cyberpunk/button.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% if variant == "secondary" %}<a href="{{ href|default:'#' }}" class="cyberpunk-btn cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider" style="background-color: hsl(var(--secondary)); color: hsl(var(--secondary-foreground));"><span>{{ label|default:'Button' }}</span> <span aria-hidden="true" class="caret-blink">_</span></a>{% elif variant == "ghost" %}<a href="{{ href|default:'#' }}" class="cyberpunk-btn-ghost cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider" style="border: 1px solid hsl(var(--accent)); color: hsl(var(--accent));"><span>{{ label|default:'Button' }}</span> <span aria-hidden="true" class="caret-blink">_</span></a>{% else %}<a href="{{ href|default:'#' }}" class="cyberpunk-btn rgb-split cyberpunk-mono inline-flex items-center gap-2 px-5 py-2.5 rounded-md font-semibold uppercase tracking-wider" style="background-color: hsl(var(--primary)); color: hsl(var(--primary-foreground));"><span>{{ label|default:'Button' }}</span> <span aria-hidden="true" class="caret-blink">_</span></a>{% endif %}
|
||||||
1
templates/overrides/cyberpunk/card.ninjatpl
Normal file
1
templates/overrides/cyberpunk/card.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% if href %}<a href="{{ href|default:'#' }}" class="cyberpunk-card neon-edge-magenta block p-6 rounded-lg h-full transition-transform hover:-translate-y-0.5" style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px dashed hsl(var(--primary));">{% if media %}<img src="{{ media }}" alt="" class="cyberpunk-card-media w-full h-40 object-cover rounded mb-4" onerror="this.style.display='none'">{% endif %}{% if title %}<h3 class="cyberpunk-card-title text-lg font-semibold mb-2" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ title }}</h3>{% endif %}{% if body %}<div class="cyberpunk-card-body text-sm leading-relaxed" style="color: hsl(var(--muted-foreground));">{{ body|safe }}</div>{% endif %}</a>{% else %}<article class="cyberpunk-card neon-edge-magenta block p-6 rounded-lg h-full" style="background-color: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px dashed hsl(var(--primary));">{% if media %}<img src="{{ media }}" alt="" class="cyberpunk-card-media w-full h-40 object-cover rounded mb-4" onerror="this.style.display='none'">{% endif %}{% if title %}<h3 class="cyberpunk-card-title text-lg font-semibold mb-2" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ title }}</h3>{% endif %}{% if body %}<div class="cyberpunk-card-body text-sm leading-relaxed" style="color: hsl(var(--muted-foreground));">{{ body|safe }}</div>{% endif %}</article>{% endif %}
|
||||||
1
templates/overrides/cyberpunk/heading.ninjatpl
Normal file
1
templates/overrides/cyberpunk/heading.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% if level|integer == 1 %}<h1 class="cyberpunk-display glitch text-4xl md:text-5xl font-bold tracking-tight {{ textClass }}" data-text="{{ text }}" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ text }}</h1>{% elif level|integer == 2 %}<h2 class="cyberpunk-display glitch text-3xl md:text-4xl font-semibold tracking-tight {{ textClass }}" data-text="{{ text }}" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ text }}</h2>{% elif level|integer == 3 %}<h3 class="cyberpunk-display text-2xl font-semibold {{ textClass }}" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ text }}</h3>{% elif level|integer == 4 %}<h4 class="cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest text-xl font-semibold {{ textClass }}" style="color: hsl(var(--accent));">{{ text }}</h4>{% elif level|integer == 5 %}<h5 class="cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest text-lg font-medium {{ textClass }}" style="color: hsl(var(--accent));">{{ text }}</h5>{% elif level|integer == 6 %}<h6 class="cyberpunk-eyebrow cyberpunk-mono uppercase tracking-widest text-base font-medium {{ textClass }}" style="color: hsl(var(--accent));">{{ text }}</h6>{% else %}<h2 class="cyberpunk-display glitch text-3xl md:text-4xl font-semibold tracking-tight {{ textClass }}" data-text="{{ text }}" style="color: hsl(var(--foreground)); font-family: var(--font-heading, 'Space Grotesk', system-ui, sans-serif);">{{ text }}</h2>{% endif %}
|
||||||
1
templates/overrides/cyberpunk/text.ninjatpl
Normal file
1
templates/overrides/cyberpunk/text.ninjatpl
Normal file
@ -0,0 +1 @@
|
|||||||
|
<div class="cyberpunk-prose prose prose-invert max-w-none leading-relaxed {{ class }}" style="color: hsl(var(--foreground)); font-family: var(--font-body, 'Inter', system-ui, sans-serif);">{{ text|safe }}</div>
|
||||||
@ -1,16 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CyberpunkTextBlock renders the built-in text block with cyberpunk styling:
|
|
||||||
// scanline-friendly leading and accent-coloured <code> inline spans.
|
|
||||||
func CyberpunkTextBlock(ctx context.Context, content map[string]any) string {
|
|
||||||
text := getString(content, "text")
|
|
||||||
class := getString(content, "class")
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_ = cyberpunkTextComponent(text, class).Render(ctx, &buf)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// cyberpunkTextComponent renders the override for the built-in text block:
|
|
||||||
// shadcn `prose` invert with cyberpunk leading and accent inline code.
|
|
||||||
templ cyberpunkTextComponent(text, class string) {
|
|
||||||
<div
|
|
||||||
class={ "cyberpunk-prose prose prose-invert max-w-none leading-relaxed", class }
|
|
||||||
style="color: hsl(var(--foreground)); font-family: var(--font-body, 'Inter', system-ui, sans-serif);"
|
|
||||||
>
|
|
||||||
@templ.Raw(text)
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1020
|
|
||||||
package main
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
// cyberpunkTextComponent renders the override for the built-in text block:
|
|
||||||
// shadcn `prose` invert with cyberpunk leading and accent inline code.
|
|
||||||
func cyberpunkTextComponent(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{"cyberpunk-prose prose prose-invert max-w-none leading-relaxed", 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, "<div class=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `text_override.templ`, Line: 1, Col: 0}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" style=\"color: hsl(var(--foreground)); font-family: var(--font-body, 'Inter', system-ui, sans-serif);\">")
|
|
||||||
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, "</div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
Loading…
x
Reference in New Issue
Block a user