fix(templ): stop emitting literal { expr } text into attributes and body classes
Release / build-and-push (push) Successful in 3m31s
Release / build-and-push (push) Successful in 3m31s
templ does not interpolate { expr } inside quoted attribute values — the
braces ship as literal text (AGENTS.md gotcha #1). Swept every templ
source for the pattern and fixed all of it:
Body theme classes: 22 page bodies rendered class="theme-{ user.Theme }"
literally, so every page first-painted the :root default (Tokyo Night)
and flashed when main.js applied the real theme. All now render
class={ "theme-" + user.Theme } server-side.
Attribute interpolations (26 across 8 files):
- api_explorer: initAPIExplorerDoc path/body/response and the Copy
Request/Response buttons (invalid JS, silently dead)
- collections: book-selection :checked/@change/@click ids and four
hx-get search URLs (collection_id={ collection.ID })
- conflicts: Resolve button id
- devices: Kobo sync-url/auth-token element ids (copy lookups only
worked because the id and the lookup were the same literal)
- unlinked_books: search-matches/manual-link clicks and container ids
- queue: status/priority badge classes never matched their CSS
- dashboard: Restore-section tooltip text
- collection_rules/collections: collection icon color
Free text goes through the new templates.JSONArg (json.Marshal) —
templ.JSONString in this templ version returns (string, error) and
cannot compose in attribute expressions; uuids via device.ID.String().
Includes regen-only drift from running templ generate (error-path
normalization) on files with no source change.
This commit is contained in:
1 parent
d5bb874651
commit
b89eac22e3
58 files changed
+4473
-3618
No files matched your search
+10
-10
@@ -25,7 +25,7 @@ templ Collection(user User, collections []CollectionData, errorMessage string) {
|
||||
<link href="/static/style.css" rel="stylesheet"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg"/>
|
||||
</head>
|
||||
<body x-data="collections" x-init="initCollectionsPage()" class="theme-{ user.Theme }">
|
||||
<body x-data="collections" x-init="initCollectionsPage()" class={ "theme-" + user.Theme }>
|
||||
@Header(user, "/collections")
|
||||
<div id="modal-container"></div>
|
||||
<div class="mx-auto container px-4 sm:px-6 lg:px-8 py-8">
|
||||
@@ -140,7 +140,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
<link href="/static/style.css" rel="stylesheet"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg"/>
|
||||
</head>
|
||||
<body x-data="collections" x-init="initCollectionsPage()" class="theme-{ user.Theme }">
|
||||
<body x-data="collections" x-init="initCollectionsPage()" class={ "theme-" + user.Theme }>
|
||||
@Header(user, "/collections")
|
||||
@LibrarySwitcher(libData, libraryID, "")
|
||||
<div class="mx-auto container px-4 sm:px-6 lg:px-8 py-8">
|
||||
@@ -150,7 +150,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
<span>Back to Collections</span>
|
||||
</a>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="grid place-items-center h-14 w-14 rounded-2xl text-3xl" style="background-color: var(--accent-muted); color: { collection.Color }">{ collection.Icon }</div>
|
||||
<div class="grid place-items-center h-14 w-14 rounded-2xl text-3xl" style={ "background-color: var(--accent-muted); color: " + collection.Color }>{ collection.Icon }</div>
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold tracking-tight flex items-center gap-2" style="color: var(--text-primary)">
|
||||
{ collection.Name }
|
||||
@@ -222,8 +222,8 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
<input
|
||||
type="checkbox"
|
||||
class="w-5 h-5"
|
||||
:checked="selectedBooks.includes('{ book.MediaItemID }')"
|
||||
@change="toggleSelection('{ book.MediaItemID }')"
|
||||
:checked={ "selectedBooks.includes(" + JSONArg(book.MediaItemID) + ")" }
|
||||
@change={ "toggleSelection(" + JSONArg(book.MediaItemID) + ")" }
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
@@ -262,7 +262,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
if !collection.IsSystem && !collection.IsSmart {
|
||||
<div class="mt-3 pt-3 border-t" style="border-color: var(--border);">
|
||||
<button
|
||||
@click="requestRemoveBook('{ book.MediaItemID }')"
|
||||
@click={ "requestRemoveBook(" + JSONArg(book.MediaItemID) + ")" }
|
||||
class="btn btn-secondary w-full"
|
||||
>
|
||||
@Icon("trash", "h-4 w-4")
|
||||
@@ -321,7 +321,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
name="q"
|
||||
placeholder="Search books..."
|
||||
class="input"
|
||||
hx-get="/api/media-items/search?show_checkbox=true&collection_id={ collection.ID }"
|
||||
hx-get={ "/api/media-items/search?show_checkbox=true&collection_id=" + collection.ID }
|
||||
hx-target="#book-picker-grid"
|
||||
hx-trigger="keyup changed delay:300ms"
|
||||
hx-include="#book-picker-filters"
|
||||
@@ -333,7 +333,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
name="author_filter"
|
||||
placeholder="Author"
|
||||
class="input"
|
||||
hx-get="/api/media-items/search?show_checkbox=true&collection_id={ collection.ID }"
|
||||
hx-get={ "/api/media-items/search?show_checkbox=true&collection_id=" + collection.ID }
|
||||
hx-target="#book-picker-grid"
|
||||
hx-trigger="change"
|
||||
hx-include="#book-picker-filters"
|
||||
@@ -345,7 +345,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
name="genre_filter"
|
||||
placeholder="Genre"
|
||||
class="input"
|
||||
hx-get="/api/media-items/search?show_checkbox=true&collection_id={ collection.ID }"
|
||||
hx-get={ "/api/media-items/search?show_checkbox=true&collection_id=" + collection.ID }
|
||||
hx-target="#book-picker-grid"
|
||||
hx-trigger="change"
|
||||
hx-include="#book-picker-filters"
|
||||
@@ -365,7 +365,7 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
||||
<div
|
||||
id="book-picker-grid"
|
||||
class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 p-4 max-h-96 overflow-y-auto"
|
||||
hx-get="/api/media-items/search?show_checkbox=true&collection_id={ collection.ID }"
|
||||
hx-get={ "/api/media-items/search?show_checkbox=true&collection_id=" + collection.ID }
|
||||
hx-trigger="loadBooks"
|
||||
hx-include="#book-picker-filters"
|
||||
>
|
||||
|
||||
Reference in new issue
Block a user