feat: show recipe image thumbnail on index page
Build and Deploy / build-and-deploy (push) Successful in 1m43s
Build and Deploy / build-and-deploy (push) Successful in 1m43s
This commit is contained in:
+7
-4
@@ -175,9 +175,11 @@ page title content =
|
|||||||
, "textarea.roux-import-input { font-family: monospace; font-size: 0.85rem; resize: vertical; }"
|
, "textarea.roux-import-input { font-family: monospace; font-size: 0.85rem; resize: vertical; }"
|
||||||
, "/* Recipe list on index page */"
|
, "/* Recipe list on index page */"
|
||||||
, ".roux-recipes { list-style: none; padding: 0; }"
|
, ".roux-recipes { list-style: none; padding: 0; }"
|
||||||
, ".roux-recipes li { padding: 0.4rem 0; }"
|
, ".roux-recipes li { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.4rem 0; }"
|
||||||
, ".roux-recipes a { font-size: 1rem; display: block; color: var(--roux-text); }"
|
, ".roux-recipes li a { font-size: 1rem; display: block; color: var(--roux-text); }"
|
||||||
, ".roux-recipes a:hover { color: var(--roux-accent); }"
|
, ".roux-recipes li a:hover { color: var(--roux-accent); }"
|
||||||
|
, ".roux-index-thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 4px; flex-shrink: 0; margin-top: 0.1rem; }"
|
||||||
|
, ".roux-index-entry { min-width: 0; }"
|
||||||
, ".roux-letter-divider { font-family: \"Fraunces\", serif; font-size: 1.1rem; font-weight: 500; color: var(--roux-text); margin: 1.2rem 0 0.25rem; padding-bottom: 0.2rem; border-bottom: 0.5px solid rgba(61, 44, 30, 0.08); }"
|
, ".roux-letter-divider { font-family: \"Fraunces\", serif; font-size: 1.1rem; font-weight: 500; color: var(--roux-text); margin: 1.2rem 0 0.25rem; padding-bottom: 0.2rem; border-bottom: 0.5px solid rgba(61, 44, 30, 0.08); }"
|
||||||
, ".roux-recipe-meta { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.1rem; }"
|
, ".roux-recipe-meta { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.1rem; }"
|
||||||
, ".roux-recipe-meta .r-tag { font-size: 0.65rem; color: rgba(61, 44, 30, 0.5); letter-spacing: 0.02em; }"
|
, ".roux-recipe-meta .r-tag { font-size: 0.65rem; color: rgba(61, 44, 30, 0.5); letter-spacing: 0.02em; }"
|
||||||
@@ -312,7 +314,8 @@ searchJs =
|
|||||||
, " meta += '<span class=\\\'r-course\\\'>' + escapeHtml(r.course) + '</span>';"
|
, " meta += '<span class=\\\'r-course\\\'>' + escapeHtml(r.course) + '</span>';"
|
||||||
, " }"
|
, " }"
|
||||||
, " let metaHtml = meta ? '<div class=\\\'roux-recipe-meta\\\'>' + meta + '</div>' : '';"
|
, " let metaHtml = meta ? '<div class=\\\'roux-recipe-meta\\\'>' + meta + '</div>' : '';"
|
||||||
, " return '<li><a href=\\\"/recipes/' + encodeURIComponent(r.filename) + '\\\">' + escapeHtml(r.title) + '</a>' + metaHtml + '</li>';"
|
, " let imgHtml = r.image ? '<img class=\\\'roux-index-thumb\\\' src=\\\'' + escapeHtml(r.image) + '\\\' alt=\\\'\\\' loading=\\\'lazy\\\'>' : '';"
|
||||||
|
, " return '<li>' + imgHtml + '<div class=\\\'roux-index-entry\\\'><a href=\\\"/recipes/' + encodeURIComponent(r.filename) + '\\\">' + escapeHtml(r.title) + '</a>' + metaHtml + '</div></li>';"
|
||||||
, "}"
|
, "}"
|
||||||
, ""
|
, ""
|
||||||
, "function renderFlatList(items) {"
|
, "function renderFlatList(items) {"
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ data RecipeSearchEntry = RecipeSearchEntry
|
|||||||
{ rseTitle :: !Text
|
{ rseTitle :: !Text
|
||||||
, rseFilename :: !Text
|
, rseFilename :: !Text
|
||||||
, rseCourse :: !(Maybe Text)
|
, rseCourse :: !(Maybe Text)
|
||||||
|
, rseImage :: !(Maybe Text)
|
||||||
, rseTags :: ![Text]
|
, rseTags :: ![Text]
|
||||||
}
|
}
|
||||||
deriving stock (Eq, Show)
|
deriving stock (Eq, Show)
|
||||||
@@ -73,6 +74,7 @@ recipeSearchEntrySchema =
|
|||||||
#+ required "title" rseTitle text
|
#+ required "title" rseTitle text
|
||||||
#+ required "filename" rseFilename text
|
#+ required "filename" rseFilename text
|
||||||
#+ optionalNullable FC.EmitNull "course" rseCourse text
|
#+ optionalNullable FC.EmitNull "course" rseCourse text
|
||||||
|
#+ optionalNullable FC.EmitNull "image" rseImage text
|
||||||
#+ required "tags" rseTags (list text)
|
#+ required "tags" rseTags (list text)
|
||||||
|
|
||||||
{- | Convert a 'RecipeInfo' into a 'RecipeSearchEntry', extracting course and
|
{- | Convert a 'RecipeInfo' into a 'RecipeSearchEntry', extracting course and
|
||||||
@@ -80,16 +82,18 @@ recipeSearchEntrySchema =
|
|||||||
-}
|
-}
|
||||||
toSearchEntry :: RecipeInfo -> RecipeSearchEntry
|
toSearchEntry :: RecipeInfo -> RecipeSearchEntry
|
||||||
toSearchEntry info =
|
toSearchEntry info =
|
||||||
let (course, tags) = case riRecipe info of
|
let (course, image, tags) = case riRecipe info of
|
||||||
Right r ->
|
Right r ->
|
||||||
( metaCourse (recipeMetadata r)
|
( metaCourse (recipeMetadata r)
|
||||||
|
, metaImage (recipeMetadata r)
|
||||||
, metaTags (recipeMetadata r)
|
, metaTags (recipeMetadata r)
|
||||||
)
|
)
|
||||||
Left _ -> (Nothing, [])
|
Left _ -> (Nothing, Nothing, [])
|
||||||
in RecipeSearchEntry
|
in RecipeSearchEntry
|
||||||
{ rseTitle = riTitle info
|
{ rseTitle = riTitle info
|
||||||
, rseFilename = T.pack (riFilename info)
|
, rseFilename = T.pack (riFilename info)
|
||||||
, rseCourse = course
|
, rseCourse = course
|
||||||
|
, rseImage = image
|
||||||
, rseTags = tags
|
, rseTags = tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user