All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m20s
Replace all 676 inline sexp() string calls across 7 services with render(component_name, **kwargs) calls backed by 46 external .sexpr component definition files (587 defcomps total). - Add render() function to shared/sexp/jinja_bridge.py - Add load_service_components() helper and update load_sexp_dir() for *.sexpr - Update parser keyword regex to support HTMX hx-on::event syntax - Convert remaining inline HTML in route files to render() calls - Add shared/sexp/templates/misc.sexp for cross-service utility components Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
4.9 KiB
Plaintext
90 lines
4.9 KiB
Plaintext
;; Blog card components
|
|
|
|
(defcomp ~blog-like-button (&key like-url hx-headers heart)
|
|
(div :class "absolute top-20 right-2 z-10 text-6xl md:text-4xl"
|
|
(button :hx-post like-url :hx-swap "outerHTML"
|
|
:hx-headers hx-headers :class "cursor-pointer" heart)))
|
|
|
|
(defcomp ~blog-draft-status (&key publish-requested timestamp)
|
|
(<> (div :class "flex justify-center gap-2 mt-1"
|
|
(span :class "inline-block px-2 py-0.5 rounded-full text-xs font-semibold bg-amber-100 text-amber-800" "Draft")
|
|
(when publish-requested (span :class "inline-block px-2 py-0.5 rounded-full text-xs font-semibold bg-blue-100 text-blue-800" "Publish requested")))
|
|
(when timestamp (p :class "text-sm text-stone-500" (str "Updated: " timestamp)))))
|
|
|
|
(defcomp ~blog-published-status (&key timestamp)
|
|
(p :class "text-sm text-stone-500" (str "Published: " timestamp)))
|
|
|
|
(defcomp ~blog-card (&key like-html href hx-select title status-html feature-image excerpt widget-html at-bar-html)
|
|
(article :class "border-b pb-6 last:border-b-0 relative"
|
|
(raw! like-html)
|
|
(a :href href :hx-get href :hx-target "#main-panel"
|
|
:hx-select hx-select :hx-swap "outerHTML" :hx-push-url "true"
|
|
:class "block rounded-xl bg-white shadow hover:shadow-md transition overflow-hidden"
|
|
(header :class "mb-2 text-center"
|
|
(h2 :class "text-4xl font-bold text-stone-900" title)
|
|
(raw! status-html))
|
|
(when feature-image (div :class "mb-4" (img :src feature-image :alt "" :class "rounded-lg w-full object-cover")))
|
|
(when excerpt (p :class "text-stone-700 text-lg leading-relaxed text-center" excerpt)))
|
|
(when widget-html (raw! widget-html))
|
|
(raw! at-bar-html)))
|
|
|
|
(defcomp ~blog-card-tile (&key href hx-select feature-image title status-html excerpt at-bar-html)
|
|
(article :class "relative"
|
|
(a :href href :hx-get href :hx-target "#main-panel"
|
|
:hx-select hx-select :hx-swap "outerHTML" :hx-push-url "true"
|
|
:class "block rounded-xl bg-white shadow hover:shadow-md transition overflow-hidden"
|
|
(when feature-image (div (img :src feature-image :alt "" :class "w-full aspect-video object-cover")))
|
|
(div :class "p-3 text-center"
|
|
(h2 :class "text-lg font-bold text-stone-900" title)
|
|
(raw! status-html)
|
|
(when excerpt (p :class "text-stone-700 text-sm leading-relaxed line-clamp-3 mt-1" excerpt))))
|
|
(raw! at-bar-html)))
|
|
|
|
(defcomp ~blog-tag-icon-image (&key src name)
|
|
(img :src src :alt name :class "h-4 w-4 rounded-full object-cover border border-stone-300 flex-shrink-0"))
|
|
|
|
(defcomp ~blog-tag-icon-initial (&key initial)
|
|
(div :class "h-4 w-4 rounded-full text-[8px] font-semibold flex items-center justify-center border border-stone-300 flex-shrink-0 bg-stone-200 text-stone-600" initial))
|
|
|
|
(defcomp ~blog-tag-li (&key icon-html name)
|
|
(li (a :class "flex items-center gap-1" (raw! icon-html)
|
|
(span :class "inline-block rounded-full bg-stone-100 text-stone-600 px-2 py-1 text-sm font-medium border border-stone-200" name))))
|
|
|
|
(defcomp ~blog-tag-bar (&key items-html)
|
|
(div :class "mt-4 flex items-center gap-2" (div "in")
|
|
(ul :class "flex flex-wrap gap-2 text-sm" (raw! items-html))))
|
|
|
|
(defcomp ~blog-author-with-image (&key image name)
|
|
(li :class "flex items-center gap-1"
|
|
(img :src image :alt name :class "h-5 w-5 rounded-full object-cover")
|
|
(span :class "text-stone-700" name)))
|
|
|
|
(defcomp ~blog-author-text (&key name)
|
|
(li :class "text-stone-700" name))
|
|
|
|
(defcomp ~blog-author-bar (&key items-html)
|
|
(div :class "mt-4 flex items-center gap-2" (div "by")
|
|
(ul :class "flex flex-wrap gap-2 text-sm" (raw! items-html))))
|
|
|
|
(defcomp ~blog-at-bar (&key tag-items-html author-items-html)
|
|
(div :class "flex flex-row justify-center gap-3"
|
|
(raw! tag-items-html) (div) (raw! author-items-html)))
|
|
|
|
(defcomp ~blog-page-badges (&key has-calendar has-market)
|
|
(div :class "flex justify-center gap-2 mt-2"
|
|
(when has-calendar (span :class "inline-block px-2 py-0.5 rounded-full text-xs font-semibold bg-blue-100 text-blue-800"
|
|
(i :class "fa fa-calendar mr-1") "Calendar"))
|
|
(when has-market (span :class "inline-block px-2 py-0.5 rounded-full text-xs font-semibold bg-green-100 text-green-800"
|
|
(i :class "fa fa-shopping-bag mr-1") "Market"))))
|
|
|
|
(defcomp ~blog-page-card (&key href hx-select title badges-html pub-html feature-image excerpt)
|
|
(article :class "border-b pb-6 last:border-b-0 relative"
|
|
(a :href href :hx-get href :hx-target "#main-panel"
|
|
:hx-select hx-select :hx-swap "outerHTML" :hx-push-url "true"
|
|
:class "block rounded-xl bg-white shadow hover:shadow-md transition overflow-hidden"
|
|
(header :class "mb-2 text-center"
|
|
(h2 :class "text-4xl font-bold text-stone-900" title)
|
|
(raw! badges-html) (raw! pub-html))
|
|
(when feature-image (div :class "mb-4" (img :src feature-image :alt "" :class "rounded-lg w-full object-cover")))
|
|
(when excerpt (p :class "text-stone-700 text-lg leading-relaxed text-center" excerpt)))))
|