Improve HTML for robot consumtion (#24)

* Fix icalendar validation errors

* Add RSS feed to documents

* Add stuff to meta: opengraph, canonical

* Add SEO robots meta elements

* Fix correct page titles

* Add more semantics to HTML

* Remove breadcrumbs from templates

* Render breadcrumbs in layout

Each controller should provide their own breadcrumb
trail as a list of tuples, where each tuple is the
pair of a slugified key and a human readable label.

Example:

[{"blog", "Webblogg"}]
[{"blog", "Webblogg"}, "2024", "2024"]

* Add CSS util class to show content only to screen readers

* Load interactive event map only on events page

* Decrease home logo size

* Use correct HTML element for time

* Improve Home page HTML semantics

* Add Person RFDa to footer

* Add RDFa to articles: annual, item, articles

* Enrich links semantics using RDFa

* Enrich Page semantics using RDFa

* Enrich Album semantics using RFDa

* Enrich Event semantics with RDFa
This commit is contained in:
Anders Englöf Ytterström 2024-10-16 15:40:53 +02:00 committed by GitHub
parent ef937ca0eb
commit 57e935ec00
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 648 additions and 520 deletions

View file

@ -81,6 +81,11 @@ section {
} }
} }
.sr-only {
position: absolute;
left: -999em;
}
.flx { .flx {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View file

@ -43,16 +43,30 @@ defmodule Mse25.Directus do
end end
def get_album(externalId) do def get_album(externalId) do
get_item( case get_item(
:albums, :albums,
externalId, externalId,
[ [
"*", "*",
"songs.title", "songs.title",
"songs.artist.name" "songs.artist.name"
] ]
|> Enum.join(",") |> Enum.join(",")
) ) do
{:ok,
data = %{
"album" => album,
"year" => year,
"songs" => [%{"artist" => %{"name" => artist}} | _]
}} ->
{:ok,
data
|> Map.put("artist", artist)
|> Map.put("summary", "#{artist} - #{album} (#{to_string(year)})")}
not_found ->
not_found
end
end end
def get_albums!(options \\ []) do def get_albums!(options \\ []) do
@ -120,6 +134,7 @@ defmodule Mse25.Directus do
"fields=" <> "fields=" <>
Enum.join( Enum.join(
[ [
"id",
"title", "title",
"lead", "lead",
"slug", "slug",
@ -128,6 +143,7 @@ defmodule Mse25.Directus do
"started_at", "started_at",
"ended_at", "ended_at",
"contents", "contents",
"date_created",
"bands.artists_id.name", "bands.artists_id.name",
"mia.artists_id.name", "mia.artists_id.name",
"location.*" "location.*"

View file

@ -1,11 +1,4 @@
defmodule Mse25.EventHelpers do defmodule Mse25.EventHelpers do
def bandlist(bands) do
bands
|> Enum.map(fn b -> b["artists_id"]["name"] end)
|> Enum.join(", ")
|> String.replace(~r/, ([^,]+?)$/, " och \\1")
end
def hilights?(%{"bands" => bands, "category" => category}) do def hilights?(%{"bands" => bands, "category" => category}) do
_festival_band?(bands, category) _festival_band?(bands, category)
end end
@ -30,4 +23,18 @@ defmodule Mse25.EventHelpers do
def _festival_band?(_b, _c) do def _festival_band?(_b, _c) do
false false
end end
def bandlist(bands) do
bands
|> Enum.map(fn b -> b["artists_id"]["name"] end)
|> Enum.join(", ")
|> String.replace(~r/, ([^,]+?)$/, " och \\1")
end
def rdfa_bandlist(bands) do
bands
|> Enum.map(fn b -> "<span property=\"performer\">#{b["artists_id"]["name"]}</span>" end)
|> Enum.join(", ")
|> String.replace(~r/, ([^,]+?)$/, " och \\1")
end
end end

View file

@ -1,14 +1,114 @@
defmodule Mse25Web.Layouts do defmodule Mse25Web.Layouts do
@moduledoc """
This module holds different layouts used by your application.
See the `layouts` directory for all templates available.
The "root" layout is a skeleton rendered as part of the
application router. The "app" layout is set as the default
layout on both `use Mse25Web, :controller` and
`use Mse25Web, :live_view`.
"""
use Mse25Web, :html use Mse25Web, :html
@url "https://madr.se"
@list_views ["webblogg", "delningar", "evenemang"]
embed_templates "layouts/*" embed_templates "layouts/*"
def canonical(%{year: _, conn: %{path_info: path}}) do
~s"""
<link rel="canonical" href="#{@url}/#{Enum.join(path, "/")}" />
"""
end
def canonical(_) do
""
end
def opengraph(%{heading: title, lead: lead, conn: %{path_info: path}}) do
~s"""
<meta property="og:title" content="#{title}" />
<meta property="og:description" content="#{lead}" />
<meta property="og:type" content="event" />
<meta property="og:url" content="#{@url}/#{Enum.join(path, "/")}" />
<meta property="og:site_name" content="madr.se" />
"""
end
def opengraph(%{heading: title, conn: %{path_info: path}}) do
~s"""
<meta property="og:title" content="#{title}" />
<meta property="og:type" content="article" />
<meta property="og:url" content="#{@url}/#{Enum.join(path, "/")}" />
<meta property="og:site_name" content="madr.se" />
"""
end
def opengraph(%{page_title: title, conn: %{path_info: path}}) do
~s"""
<meta property="og:title" content="#{title}" />
<meta property="og:type" content="page" />
<meta property="og:url" content="#{@url}/#{Enum.join(path, "/")}" />
<meta property="og:site_name" content="madr.se" />
"""
end
def robots(%{conn: %{path_info: [first | []]}}) do
case Integer.parse(first) do
:error ->
case Enum.member?(@list_views, first) do
true ->
~s"""
<meta name="robots" content="noindex,follow" />
"""
false ->
~s"""
<meta name="robots" content="index,follow" />
"""
end
{_i, _d} ->
~s"""
<meta name="robots" content="noindex,follow" />
"""
end
end
def robots(%{conn: %{path_info: [_p, _c]}}) do
~s"""
<meta name="robots" content="index,follow" />
"""
end
def robots(_) do
~s"""
<meta name="robots" content="noindex,follow" />
"""
end
def breadcrumbs(nodes) do
breadcrumbs([], "", 1, nodes)
end
def breadcrumbs(seen, _path, _index, []) do
Enum.reverse(seen)
end
def breadcrumbs(seen, path, index, [{slug, name} | nodes]) do
breadcrumbs(
[{index + 1, {path <> "/" <> to_string(slug), name}} | seen],
path <> "/" <> to_string(slug),
index + 1,
nodes
)
end
def breadcrumbs(seen, path, index, [{slug, name, custom_prefix} | nodes]) do
breadcrumbs(
[{index + 1, {custom_prefix <> "/" <> to_string(slug), name}} | seen],
path <> "/" <> to_string(slug),
index + 1,
nodes
)
end
def show_interactive_event_map?(assigns) do
Map.has_key?(assigns, :events)
end
def show_footer?(%{heading: "Kolofon"}), do: false
def show_footer?(%{}), do: true
end end

View file

@ -1,3 +1,39 @@
<main> <a href="#content" class="skiplink">Hoppa till innehållet</a>
<nav role="menu">
<div>
<span class="sr-only">Du är här:</span>
<span class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
<span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/" rel="home">
<span itemprop="name">madr.se</span>
</a>
<meta itemprop="position" content="1" />
</span>
<%= for {index, {parent_slug, parent_name}} <- breadcrumbs(@breadcrumbs) do %>
<span class="sr-only">&gt;</span>
<span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href={parent_slug}>
<span itemprop="name"><%= parent_name %></span>
</a>
<meta itemprop="position" content={index} />
</span>
<% end %>
</span>
</div>
</nav>
<main id="content" role="main">
<%= @inner_content %> <%= @inner_content %>
</main> </main>
<%= if show_footer?(assigns) do %>
<footer role="contentinfo">
<p vocab="https://schema.org/" typeof="Person">
<a href="https://madr.se" property="url">madr.se</a>
är <span property="name">Anders Englöf Ytterström</span>s hemsida. Anders är <span property="jobTitle">webbutvecklare</span>, linuxentusiast, ljudtekniker och hårdrockare, bosatt i <span
property="address"
typeof="PostalAddress"
><span property="addressLocality">Borlänge</span> (<span property="addressRegion">Dalarna</span>)</span>.
Läs <a href="/colophon">kolofonen</a>.
</p>
</footer>
<% end %>

View file

@ -4,12 +4,25 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<meta name="csrf-token" content={get_csrf_token()} /> <meta name="csrf-token" content={get_csrf_token()} />
<title><%= assigns[:page_title] || "Anders Englöf Ytterström" %> | madr.se</title> <title><%= assigns.page_title || "Anders Englöf Ytterström" %> | madr.se</title>
<link rel="stylesheet" href={~p"/assets/app.css"} /> <link rel="stylesheet" href={~p"/assets/app.css"} />
<link
href="/prenumerera.xml"
type="application/rss+xml"
rel="alternate"
title="madr.se: inlägg, evenemang, delningar"
/>
<%= canonical(assigns) |> raw %>
<%= opengraph(assigns) |> raw %>
<%= robots(assigns) |> raw %>
</head> </head>
<body class="bg-white"> <body>
<%= @inner_content %> <%= @inner_content %>
<script src={~p"/assets/app.js"}> <script src={~p"/assets/app.js"}>
</script> </script>
<%= if show_interactive_event_map?(assigns) do %>
<script src="/event-map.js">
</script>
<% end %>
</body> </body>
</html> </html>

View file

@ -19,10 +19,12 @@ defmodule Mse25Web.FeedController do
conn |> put_resp_content_type("text/calendar"), conn |> put_resp_content_type("text/calendar"),
Directus.get_events!(upcoming: true, limit: 9999) Directus.get_events!(upcoming: true, limit: 9999)
|> Enum.map(fn %{ |> Enum.map(fn %{
"id" => id,
"title" => title, "title" => title,
"lead" => lead, "lead" => lead,
"started_at" => starts_at, "started_at" => starts_at,
"ended_at" => ends_at, "ended_at" => ends_at,
"date_created" => created_at,
"location" => %{ "location" => %{
"name" => venue, "name" => venue,
"address" => region, "address" => region,
@ -32,6 +34,7 @@ defmodule Mse25Web.FeedController do
} }
} -> } ->
%{ %{
id: id,
title: title, title: title,
lead: lead, lead: lead,
region: region, region: region,
@ -39,6 +42,8 @@ defmodule Mse25Web.FeedController do
latitude: lat, latitude: lat,
longitude: lng, longitude: lng,
all_day?: true, all_day?: true,
updated_at: created_at |> String.slice(0..18) |> String.replace(~r/[-:]/, ""),
created_at: created_at |> String.slice(0..18) |> String.replace(~r/[-:]/, ""),
starts_at: String.replace(starts_at, "-", ""), starts_at: String.replace(starts_at, "-", ""),
ends_at: String.replace(ends_at, "-", "") ends_at: String.replace(ends_at, "-", "")
} }

View file

@ -23,14 +23,31 @@ defmodule Mse25Web.FeedView do
~s""" ~s"""
BEGIN:VCALENDAR BEGIN:VCALENDAR
VERSION:2.0 VERSION:2.0
PRODID:-//https://madr.se//kommande-evenemang PRODID:-//https://madr.se//kommande-evenemang.ics//SE
CALSCALE:GREGORIAN
X-ORIGINAL-URL:https://madr.se
X-WR-CALDESC: Kommande evenemang, madr.se
METHOD:PUBLISH METHOD:PUBLISH
#{upcoming |> Enum.map(fn %{title: title, starts_at: starts_at, ends_at: ends_at, longitude: longitude, latitude: latitude, lead: lead, venue: venue, region: region} -> ~s""" REFRESH-INTERVAL;VALUE=DURATION:PT1H
X-Robots-Tag:noindex
X-PUBLISHED-TTL:PT1H
BEGIN:VTIMEZONE
TZID:CEST
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:20000630T000000
END:STANDARD
END:VTIMEZONE
#{upcoming |> Enum.map(fn %{id: id, title: title, created_at: created_at, starts_at: starts_at, ends_at: ends_at, longitude: longitude, latitude: latitude, lead: lead, venue: venue, region: region} -> ~s"""
BEGIN:VEVENT BEGIN:VEVENT
UID:#{title}.#{starts_at}@madr.se UID:#{starts_at}.#{id}@madr.se
DTSTAMP:#{starts_at}T000000 DTSTAMP:#{created_at}
DTSTART;VALUE=DATE:#{starts_at} CREATED:#{created_at}
DTEND;VALUE=DATE:#{ends_at} LAST-MODIFIED:#{created_at}
DTSTART;TZID=CEST:#{starts_at}T060606
DTEND;TZID=CEST:#{ends_at}T060606
SUMMARY:#{title} SUMMARY:#{title}
DESCRIPTION:#{lead} DESCRIPTION:#{lead}
LOCATION:#{venue}\, #{region} LOCATION:#{venue}\, #{region}

View file

@ -73,6 +73,7 @@ defmodule Mse25Web.ItemController do
do: [ do: [
year: year, year: year,
page_title: "Innehåll från " <> to_string(year), page_title: "Innehåll från " <> to_string(year),
breadcrumbs: [{year, year}],
timeline: timeline, timeline: timeline,
brutal_legends_count: Map.get(counts, :albums, 0), brutal_legends_count: Map.get(counts, :albums, 0),
article_count: Map.get(counts, :articles, 0), article_count: Map.get(counts, :articles, 0),
@ -86,8 +87,11 @@ defmodule Mse25Web.ItemController do
"pubDate" => published_at, "pubDate" => published_at,
"date_updated" => updated_at "date_updated" => updated_at
}) do }) do
year = String.slice(published_at, 0..3)
[ [
page_title: heading, page_title: heading,
breadcrumbs: [{"webblogg", "Webblogg"}, {year, year, ""}],
heading: heading, heading: heading,
contents: Earmark.as_html!(contents), contents: Earmark.as_html!(contents),
published_at: published_at, published_at: published_at,
@ -96,7 +100,7 @@ defmodule Mse25Web.ItemController do
nil -> published_at nil -> published_at
ua -> String.slice(ua, 0..9) ua -> String.slice(ua, 0..9)
end, end,
year: String.slice(published_at, 0..3) year: year
] ]
end end
@ -104,22 +108,28 @@ defmodule Mse25Web.ItemController do
"title" => heading, "title" => heading,
"contents" => contents, "contents" => contents,
"started_at" => started_at, "started_at" => started_at,
"ended_at" => ended_at,
"lead" => lead, "lead" => lead,
"poster" => poster, "poster" => poster,
"bands" => bands, "bands" => bands,
"mia" => mia, "mia" => mia,
"category" => category "category" => category
}) do }) do
year = String.slice(started_at, 0..3)
[ [
page_title: heading, page_title: heading,
breadcrumbs: [{"evenemang", "Evenemang"}, {year, year, ""}],
heading: heading, heading: heading,
contents: Earmark.as_html!(contents), contents: Earmark.as_html!(contents),
lead: lead, lead: lead,
year: String.slice(started_at, 0..3), year: year,
poster: poster, poster: poster,
bands: bands, bands: bands,
mia: mia, mia: mia,
category: category category: category,
started_at: started_at,
ended_at: ended_at
] ]
end end
@ -131,14 +141,17 @@ defmodule Mse25Web.ItemController do
"source" => url, "source" => url,
"h1" => title "h1" => title
}) do }) do
year = String.slice(published_at, 0..3)
[ [
page_title: heading, page_title: heading,
breadcrumbs: [{"delningar", "Delningar"}, {year, year, ""}],
heading: heading, heading: heading,
contents: Earmark.as_html!(contents), contents: Earmark.as_html!(contents),
published_at: published_at, published_at: published_at,
url: url, url: url,
title: title, title: title,
year: String.slice(published_at, 0..3), year: year,
updated_at: updated_at:
case updated_at do case updated_at do
nil -> published_at nil -> published_at
@ -153,6 +166,8 @@ defmodule Mse25Web.ItemController do
"date_updated" => updated_at "date_updated" => updated_at
}) do }) do
[ [
page_title: heading,
breadcrumbs: [],
heading: heading, heading: heading,
contents: Earmark.as_html!(contents), contents: Earmark.as_html!(contents),
updated_at: String.slice(updated_at, 0..9) updated_at: String.slice(updated_at, 0..9)
@ -166,18 +181,24 @@ defmodule Mse25Web.ItemController do
"cover" => cover, "cover" => cover,
"purchased_at" => purchased_at, "purchased_at" => purchased_at,
"externalId" => count, "externalId" => count,
"songs" => songs "songs" => songs,
"summary" => summary,
"artist" => artist
}) do }) do
purchase_year = String.slice(purchased_at, 0..3)
[ [
page_title: summary,
breadcrumbs: [{purchase_year, purchase_year}],
count: count, count: count,
page_title: album,
album: album, album: album,
cover: cover, cover: cover,
year: to_string(year), year: to_string(year),
purchase_year: String.slice(purchased_at, 0..3), purchase_year: purchase_year,
contents: Earmark.as_html!(contents), contents: Earmark.as_html!(contents),
songs: Enum.map(songs, fn %{"title" => name} -> "\"" <> name <> "\"" end), songs: Enum.map(songs, fn %{"title" => name} -> "\"" <> name <> "\"" end),
artist: List.first(songs) |> Map.get("artist") |> Map.get("name") artist: artist,
summary: summary
] ]
end end
end end

View file

@ -1,21 +1,7 @@
<article class="article"> <article class="album" vocab="https://schema.org/" typeof="MusicAlbum Review">
<header> <h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList"> <%= @summary %>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> </h1>
<a href="/" rel="home">
<span itemprop="name">madr.se</span>
</a>
<meta itemprop="position" content="1" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href={"/" <> @purchase_year}>
<span itemprop="name"><%= @purchase_year %></span>
</a>
<meta itemprop="position" content="2" />
</li>
</ol>
<h1><%= @artist <> " - " <> @album <> " (" <> @year <> ")" %></h1>
</header>
<p> <p>
Som jag tidigare skrivit om har jag ett roligt projekt pågående: att äga alla låtar i spelet Brütal Legend äldre än 1990 på vinyl, där det är möjligt. Som jag tidigare skrivit om har jag ett roligt projekt pågående: att äga alla låtar i spelet Brütal Legend äldre än 1990 på vinyl, där det är möjligt.
@ -23,18 +9,23 @@
<div class="brutal-legend"> <div class="brutal-legend">
<p> <p>
#<%= @count %>: <%= @artist %> - <%= csl(@songs) %>, från <%= @album %> (<%= @year %>) #<%= @count %>: <span property="byArtist"><%= @artist %></span>
- <%= csl(@songs) %>, från <span property="name"><%= @album %></span>
(<span property="copyrightYear"><%= @year %></span>)
</p> </p>
<%= if @cover do %> <%= if @cover do %>
<img <img
src={"https://n.madr.se/assets/" <> @cover <> "?key=rectangular"} property="image"
src={"https://n.madr.se/assets/" <> @cover <> "?key=cover"}
alt="Skivomslag" alt="Skivomslag"
loading="lazy" loading="lazy"
height="75" height="333"
width="75" width="333"
/> />
<% end %> <% end %>
</div> </div>
<%= raw(@contents) %> <div property="reviewBody">
<%= raw(@contents) %>
</div>
</article> </article>

View file

@ -1,108 +1,107 @@
<header> <h1><%= @page_title %></h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList"> <ul>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> <li><a href={"/" <> to_string(@year - 1)}>Tillbaka till <%= @year - 1 %></a></li>
<a href="/" rel="home"> <li><a href={"/" <> to_string(@year + 1)}>Framåt till <%= @year + 1 %></a></li>
<span itemprop="name">madr.se</span> </ul>
</a> <ul>
<meta itemprop="position" content="1" /> <%= if @link_count > 0 do %>
<li><%= @link_count %> länkar värda att uppmärksamma och kommentera</li>
<% end %>
<%= if @article_count > 0 do %>
<li><%= @article_count %> inlägg i webbloggen</li>
<% end %>
<%= if @event_count > 0 do %>
<li><%= @event_count %> besökta evenemang</li>
<% end %>
<%= if @brutal_legends_count > 0 do %>
<li>
<%= @brutal_legends_count %>
<%= if @brutal_legends_count == 1 do %>
köpt vinylskiva
<% else %>
köpta vinylskivor
<% end %>
till Brütal Legend-samlingen
</li> </li>
</ol> <% end %>
<h1><%= @page_title %></h1> </ul>
<ul> <%= for {month, items} <- @timeline do %>
<li><a href={"/" <> to_string(@year - 1)}>Tillbaka till <%= @year - 1 %></a></li> <section id={"m" <> month}>
<li><a href={"/" <> to_string(@year + 1)}>Framåt till <%= @year + 1 %></a></li> <h2><%= month_name(month) <> ", " <> to_string(@year) %></h2>
</ul> <%= for item = %{t: t} <- items do %>
<ul> <%= if t == :articles do %>
<%= if @link_count > 0 do %> <article class="article" vocab="https://schema.org/" typeof="Article">
<li><%= @link_count %> länkar värda att uppmärksamma och kommentera</li> <h3 property="name">
<% end %> <a href={"/" <> item["slug"]}>
<%= if @article_count > 0 do %>
<li><%= @article_count %> inlägg i webbloggen</li>
<% end %>
<%= if @event_count > 0 do %>
<li><%= @event_count %> besökta evenemang</li>
<% end %>
<%= if @brutal_legends_count > 0 do %>
<li>
<%= @brutal_legends_count %>
<%= if @brutal_legends_count == 1 do %>
köpt vinylskiva
<% else %>
köpta vinylskivor
<% end %>
till Brütal Legend-samlingen
</li>
<% end %>
</ul>
<%= for {month, items} <- @timeline do %>
<section id={"m" <> month}>
<h2><%= month_name(month) <> ", " <> to_string(@year) %></h2>
<%= for item = %{t: t} <- items do %>
<article>
<%= if t == :articles do %>
<h3>
<a href={"/" <> item["slug"]}>
<%= item["title"] %>
</a>
</h3>
<% end %>
<%= if t == :events do %>
<h3>
<a href={"/" <> item["slug"]}>
<%= item["title"] %>
</a>
</h3>
<p><%= item["lead"] %></p>
<%= if item["poster"] do %>
<img
src={ "https://n.madr.se/assets/" <> item["poster"] <> "?key=poster"}
loading="lazy"
alt="Affisch"
width="200"
/>
<% end %>
<% end %>
<%= if t == :links do %>
<h3>
<%= item["title"] %> <%= item["title"] %>
</h3>
<p><%= raw(Earmark.as_html!(item["contents"])) %></p>
Källa:
<a href={"/" <> item["source"]}>
<%= item["h1"] %>
</a> </a>
<% end %> </h3>
<%= if t == :albums do %> <time property="datePublished"><%= item["pubDate"] %></time>
<h3> </article>
<%= item["artist"] <> <% end %>
" - " <> item["album"] <> " (" <> to_string(item["year"]) <> ")" %> <%= if t == :events do %>
<a <article class="event" vocab="https://schema.org/" typeof="Event">
class="permalink" <h3>
href={"/" <> to_string(@year) <> "/brutal-legend-" <> item["externalId"]} <a property="name" href={"/" <> item["slug"]}>
> <%= item["title"] %>
# </a>
</a> </h3>
</h3> <p property="description"><%= item["lead"] %></p>
<%= if item["contents"] do %> <%= if item["poster"] do %>
<p><%= raw(Earmark.as_html!(item["contents"])) %></p> <img
<% end %> property="thumbnail"
<ul> src={ "https://n.madr.se/assets/" <> item["poster"] <> "?key=poster"}
<%= for song <- item["songs"] do %> loading="lazy"
<li><%= song["artist"]["name"] <> " - " <> song["title"] %></li> alt="Affisch"
<% end %> width="200"
</ul> />
<%= if item["cover"] do %>
<img
src={"https://n.madr.se/assets/" <> item["cover"] <> "?key=rectangular"}
alt="Skivomslag"
loading="lazy"
height="75"
width="75"
/>
<% end %>
<% end %> <% end %>
</article> </article>
<% end %> <% end %>
</section> <%= if t == :links do %>
<% end %> <article vocab="https://schema.org/" typeof="WebContent Review" class="bookmark">
</header> <h3>
<span property="name"><%= item["title"] %></span>
<a class="permalink" href={"/" <> item["slug"]} title="Permalänk">#</a>
</h3>
<div property="reviewBody">
<%= item["contents"] |> Earmark.as_html!() |> raw %>
</div>
<div class="source">
Källa: <a href={item["source"]} rel="external"><%= item["h1"] %></a>
</div>
</article>
<% end %>
<%= if t == :albums do %>
<article class="album" vocab="https://schema.org/" typeof="MusicAlbum">
<h3>
<span property="byArtist"><%= @artist %></span>
- <%= csl(@songs) %>, från <span property="name"><%= @album %></span>
(<span property="copyrightYear"><%= @year %></span>)
<a
class="permalink"
href={"/" <> to_string(@year) <> "/brutal-legend-" <> item["externalId"]}
>
#
</a>
</h3>
<ul>
<%= for song <- item["songs"] do %>
<li><%= song["artist"]["name"] <> " - " <> song["title"] %></li>
<% end %>
</ul>
<%= if item["cover"] do %>
<img
property="thumbnail"
src={"https://n.madr.se/assets/" <> item["cover"] <> "?key=rectangular"}
alt="Skivomslag"
loading="lazy"
height="75"
width="75"
/>
<% end %>
</article>
<% end %>
<% end %>
</section>
<% end %>

View file

@ -1,33 +1,15 @@
<article class="article"> <article class="article" vocab="https://schema.org/" typeof="Article">
<header> <h1 property="name"><%= @heading %></h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/" rel="home">
<span itemprop="name">madr.se</span>
</a>
<meta itemprop="position" content="1" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/webblogg">
<span itemprop="name">Webblogg</span>
</a>
<meta itemprop="position" content="2" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href={"/" <> @year}>
<span itemprop="name"><%= @year %></span>
</a>
<meta itemprop="position" content="3" />
</li>
</ol>
<h1><%= @heading %></h1>
</header>
<%= raw(@contents) %> <div property="articleBody">
<%= raw(@contents) %>
</div>
<footer> <footer>
<p> <p>
Publicerad <%= @published_at %> <br />och senast uppdaterad <%= @updated_at %> Publicerad <time property="datePublished"><%= @published_at %></time>
av <span property="publisher">Anders Englöf Ytterström</span>, <br /> senast uppdaterad
<time property="dateModified"><%= @updated_at %></time>
</p> </p>
</footer> </footer>
</article> </article>

View file

@ -1,45 +1,38 @@
<article class="article"> <article class="event" vocab="https://schema.org/" typeof="Event Review">
<header> <h1 property="name"><%= @heading %></h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/" rel="home">
<span itemprop="name">madr.se</span>
</a>
<meta itemprop="position" content="1" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/evenemang">
<span itemprop="name">Evenemang</span>
</a>
<meta itemprop="position" content="2" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href={"/" <> @year}>
<span itemprop="name"><%= @year %></span>
</a>
<meta itemprop="position" content="3" />
</li>
</ol>
<h1><%= @heading %></h1>
</header>
<ul> <ul>
<li><%= @lead %></li> <li property="description"><%= @lead %></li>
<li class="sr-only">
<span property="startDate"><%= @started_at %></span><span property="endDate"><%= @ended_at %></span>
</li>
<%= if opening_acts?(%{"bands" => @bands, "category" => @category}) do %> <%= if opening_acts?(%{"bands" => @bands, "category" => @category}) do %>
<li>Huvudakt: <%= @bands |> List.first() |> Map.get("artists_id") |> Map.get("name") %></li> <li>
<li>Förband: <%= @bands |> Enum.drop(1) |> bandlist() %></li> Huvudakt:
<span property="performer">
<%= @bands |> List.first() |> Map.get("artists_id") |> Map.get("name") %>
</span>
</li>
<li>Förband: <%= @bands |> Enum.drop(1) |> rdfa_bandlist() |> raw %></li>
<% end %> <% end %>
<%= if hilights?(%{"bands" => @bands, "category" => @category}) do %> <%= if hilights?(%{"bands" => @bands, "category" => @category}) do %>
<li>Personliga höjdpunkter: <%= @bands |> bandlist() %></li> <li>Personliga höjdpunkter: <%= @bands |> rdfa_bandlist() |> raw %></li>
<% end %> <% end %>
<%= if missed?(%{"mia" => @mia, "category" => @category}) do %> <%= if missed?(%{"mia" => @mia, "category" => @category}) do %>
<li>Band jag missade: <%= @mia |> bandlist() %></li> <li>Band jag missade: <%= @mia |> bandlist() %></li>
<% end %> <% end %>
</ul> </ul>
<%= raw(@contents) %> <div property="reviewBody">
<%= raw(@contents) %>
</div>
<%= if @poster do %> <%= if @poster do %>
<img src={"https://n.madr.se/assets/" <> @poster} alt="affisch" loading="lazy" /> <img
property="image"
src={"https://n.madr.se/assets/" <> @poster <> "?key=poster"}
alt="affisch"
loading="lazy"
/>
<% end %> <% end %>
</article> </article>

View file

@ -1,35 +1,16 @@
<article class="article"> <article vocab="https://schema.org/" typeof="WebContent Review" class="bookmark">
<header> <h1 property="name"><%= @heading %></h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList"> <div property="reviewBody">
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> <%= raw(@contents) %>
<a href="/" rel="home"> </div>
<span itemprop="name">madr.se</span> <div class="source">
</a> Källa: <a href={@url} property="url"><span property="headline"><%= @title %></span></a>
<meta itemprop="position" content="1" /> </div>
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/delningar">
<span itemprop="name">Delningar</span>
</a>
<meta itemprop="position" content="2" />
</li>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href={"/" <> @year}>
<span itemprop="name"><%= @year %></span>
</a>
<meta itemprop="position" content="3" />
</li>
</ol>
<h1><%= @heading %></h1>
</header>
<%= raw(@contents) %>
<p>
Källa: <a href={@url} rel="external"><%= @title %></a>
</p>
<footer> <footer>
<p> <p>
Publicerad <%= @published_at %> <br />och senast uppdaterad <%= @updated_at %> Publicerad <time property="datePublished archivedAt"><%= @published_at %></time>
av <span property="author">Anders Englöf Ytterström</span>,<br />Senast uppdaterad
<time property="dateModified"><%= @updated_at %></time>
</p> </p>
</footer> </footer>
</article> </article>

View file

@ -1,19 +1,13 @@
<article> <article class="article" vocab="https://schema.org/" typeof="Article">
<header> <h1 property="name"><%= @heading %></h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/" rel="home">
<span itemprop="name">madr.se</span>
</a>
<meta itemprop="position" content="1" />
</li>
</ol>
<h1><%= @heading %></h1>
</header>
<%= raw(@contents) %> <div property="articleBody">
<%= raw(@contents) %>
</div>
<footer> <footer>
<p>Senast uppdaterad <%= @updated_at %></p> <p>
Senast uppdaterad <time property="dateModified"><%= @updated_at %></time>
</p>
</footer> </footer>
</article> </article>

View file

@ -38,6 +38,7 @@ defmodule Mse25Web.PageController do
render(conn, :search, render(conn, :search,
q: query, q: query,
breadcrumbs: [],
page_title: scount <> " sökresultat för \"" <> query <> "\"", page_title: scount <> " sökresultat för \"" <> query <> "\"",
results: results results: results
) )
@ -48,19 +49,20 @@ defmodule Mse25Web.PageController do
end end
def articles(conn, params) do def articles(conn, params) do
articles = {articles, page_title} =
case params do case params do
%{"q" => query_string} -> %{"q" => query_string} ->
Directus.get_articles!(limit: @almost_infinity, query: query_string) {Directus.get_articles!(limit: @almost_infinity, query: query_string),
"Webblogg: \"#{query_string}\""}
_ -> _ ->
Directus.get_articles!(limit: @almost_infinity) {Directus.get_articles!(limit: @almost_infinity), "Webblogg"}
end end
|> group_annually
render(conn, :articles, render(conn, :articles,
page_title: "Webblogg", page_title: page_title,
articles: articles, breadcrumbs: [{"webblogg", "Webblogg"}],
articles: group_annually(articles),
q: params["q"], q: params["q"],
nosearch?: params["q"] == nil or params["q"] == "" nosearch?: params["q"] == nil or params["q"] == ""
) )
@ -81,6 +83,8 @@ defmodule Mse25Web.PageController do
render(conn, :events, render(conn, :events,
page_title: title, page_title: title,
breadcrumbs: [],
show_interactive_event_map?: true,
contents: Earmark.as_html!(contents), contents: Earmark.as_html!(contents),
events: events, events: events,
q: params["q"], q: params["q"],
@ -93,6 +97,7 @@ defmodule Mse25Web.PageController do
render(conn, :links, render(conn, :links,
page_title: "Delningar", page_title: "Delningar",
breadcrumbs: [],
links: links links: links
) )
end end

View file

@ -1,49 +1,41 @@
<header> <h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList"> <%= @page_title %>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> </h1>
<a href="/" rel="home"> <p>
<span itemprop="name">madr.se</span> Inlägg skrivna sedan 2006.
</a> <%= if @nosearch? do %>
<meta itemprop="position" content="1" /> Gå direkt till:
</li>
</ol>
<h1>Webblogg</h1>
<p>
Inlägg skrivna sedan 2006.
<%= if @nosearch? do %>
Gå direkt till:
<% end %>
</p>
<ul class="months">
<%= for {year, articles} <- @articles do %>
<li>
<a href={"#y" <> year}><%= year %></a> (<%= Enum.count(articles) %>)
</li>
<% end %>
</ul>
<form method="get" action="/webblogg">
<p>
<%= if @nosearch? do %>
Eller
<% end %>
<label for="q">sök innehåll</label>:
<input type="search" value={@q} name="q" id="q" size="7" />
<button>Sök</button>
</p>
</form>
<%= for {year, articles} <- @articles do %>
<section id={"y" <> year}>
<h2 class="sticky"><%= year %></h2>
<div class="articles">
<%= for article <- articles do %>
<article>
<h2>
<a href={"/" <> article["slug"]}><%= article["title"] %></a>
</h2>
<date><%= article["pubDate"] %></date>
</article>
<% end %>
</div>
</section>
<% end %> <% end %>
</header> </p>
<ul class="months">
<%= for {year, articles} <- @articles do %>
<li>
<a href={"#y" <> year}><%= year %></a> (<%= Enum.count(articles) %>)
</li>
<% end %>
</ul>
<form method="get" action="/webblogg">
<p>
<%= if @nosearch? do %>
Eller
<% end %>
<label for="q">sök innehåll</label>:
<input type="search" value={@q} name="q" id="q" size="7" />
<button>Sök</button>
</p>
</form>
<%= for {year, articles} <- @articles do %>
<section id={"y" <> year}>
<h2 class="sticky"><%= year %></h2>
<div class="articles">
<%= for article <- articles do %>
<article class="article" vocab="https://schema.org/" typeof="Article">
<h2 property="name">
<a href={"/" <> article["slug"]}><%= article["title"] %></a>
</h2>
<time><%= article["pubDate"] %></time>
</article>
<% end %>
</div>
</section>
<% end %>

View file

@ -1,14 +1,5 @@
<header> <h1><%= @page_title %></h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a href="/" rel="home">
<span itemprop="name">madr.se</span>
</a>
<meta itemprop="position" content="1" />
</li>
</ol>
<h1><%= @page_title %></h1>
</header>
<%= raw(@contents) %> <%= raw(@contents) %>
<section id="map"> <section id="map">
<h2>Geografisk utspridning</h2> <h2>Geografisk utspridning</h2>
@ -43,14 +34,14 @@
<h2 class="sticky"><%= year %></h2> <h2 class="sticky"><%= year %></h2>
<div class="events"> <div class="events">
<%= for event <- events do %> <%= for event <- events do %>
<article> <article class="event" vocab="https://schema.org/" typeof="Event">
<h2> <h2>
<a href={"/" <> event["slug"]}><%= event["title"] %></a> <a property="name" href={"/" <> event["slug"]}><%= event["title"] %></a>
</h2> </h2>
<p><%= event["lead"] %></p> <p property="description"><%= event["lead"] %></p>
<%= if hilights?(event) do %> <%= if hilights?(event) do %>
<p> <p>
Personliga höjdpunkter: <%= bandlist(event["bands"]) %> Personliga höjdpunkter: <%= rdfa_bandlist(event["bands"]) |> raw %>
</p> </p>
<% end %> <% end %>
<%= if missed?(event) do %> <%= if missed?(event) do %>
@ -60,13 +51,14 @@
<% end %> <% end %>
<%= if opening_acts?(event) do %> <%= if opening_acts?(event) do %>
<p> <p>
Förband: <%= event["bands"] |> Enum.drop(1) |> bandlist() %> Förband: <%= event["bands"] |> Enum.drop(1) |> rdfa_bandlist() |> raw %>
</p> </p>
<% end %> <% end %>
<%= if event["poster"] do %> <%= if event["poster"] do %>
<img <img
property="thumbnail"
loading="lazy" loading="lazy"
src={"https://n.madr.se/assets/" <> event["poster"]} src={"https://n.madr.se/assets/" <> event["poster"] <> "?key=poster"}
alt="affisch" alt="affisch"
width="150" width="150"
/> />
@ -76,5 +68,3 @@
</div> </div>
</section> </section>
<% end %> <% end %>
<script src="/event-map.js">
</script>

View file

@ -1,72 +1,72 @@
<main class="landing"> <main class="landing">
<img src={~p"/images/aey.svg"} width="300" alt="Anders Englöf Ytterström" /> <img src={~p"/images/aey.svg"} width="120" alt="Anders Englöf Ytterström" />
<form metod="get" action="/sok"> <form metod="get" action="/sok">
<label for="q">Sök innehåll</label>: <input size="9" type="search" id="q" name="q" /> <label for="q">Sök innehåll</label>: <input size="9" type="search" id="q" name="q" />
<button>Sök</button> <button>Sök</button>
</form> </form>
<div class="tree"> <div class="tree">
<div> <article class="article">
Senast skrivet (<date><%= @recent_article["pubDate"] %></date>):<br /> Senast skrivet (<time><%= @recent_article["pubDate"] %></time>):<br />
<a href={"/" <> @recent_article["slug"]}> <a href={"/" <> @recent_article["slug"]}>
<%= @recent_article["title"] %> <%= @recent_article["title"] %>
</a> </a>
</div> </article>
<div> <article class="article">
Dessförinnan (<date><%= @older_article["pubDate"] %></date>):<br /> Dessförinnan (<time><%= @older_article["pubDate"] %></time>):<br />
<a href={"/" <> @older_article["slug"]}> <a href={"/" <> @older_article["slug"]}>
<%= @older_article["title"] %> <%= @older_article["title"] %>
</a> </a>
</div> </article>
<div> <article class="page">
<a href="/webblogg">Webbloggen</a> <a href="/webblogg">Webbloggen</a>
</div> </article>
<%= for event <- @upcoming do %> <%= for event <- @upcoming do %>
<div> <article class="event">
Kommande: <a href={event["slug"]}><%= event["title"] %><br /><%= event["lead"] %></a> Kommande: <a href={event["slug"]}><%= event["title"] %><br /><%= event["lead"] %></a>
</div> </article>
<% end %> <% end %>
<%= for event <- @recent_event do %> <%= for event <- @recent_event do %>
<div> <article class="event">
Upplevt: <a href={event["slug"]}><%= event["title"] %><br /><%= event["lead"] %></a> Upplevt: <a href={event["slug"]}><%= event["title"] %><br /><%= event["lead"] %></a>
</div> </article>
<% end %> <% end %>
<div> <article class="feed events page">
<a href="/evenemang">Evenemangstidslinje</a> <a href="/evenemang">Evenemangstidslinje</a>
</div> </article>
<div> <article class="feed ics">
<a href="/kommande-evenemang.ics">Kommande evenemang</a> (vcalendar) <a href="/kommande-evenemang.ics">Kommande evenemang</a> (vcalendar)
</div> </article>
<div> <article class="feed links">
<a href="/delningar"> <a href="/delningar">
Delningar Delningar
</a> </a>
</div> </article>
<%= for legend <- @brutal_legends do %> <%= for legend <- @brutal_legends do %>
<div> <article class="album">
Införskaffat (<%= legend["purchased_at"] %>):<br /> Införskaffat (<%= legend["purchased_at"] %>):<br />
<a href={"/" <> legend["purchase_year"] <> "/brutal-legend-" <> legend["externalId"]}> <a href={"/" <> legend["purchase_year"] <> "/brutal-legend-" <> legend["externalId"]}>
<%= legend["artist"] %> - <%= legend["album"] %> (<%= legend["year"] %>) <%= legend["artist"] %> - <%= legend["album"] %> (<%= legend["year"] %>)
</a> </a>
</div> </article>
<% end %> <% end %>
<div> <article class="page">
<a href="/vad-jag-gor"> <a href="/vad-jag-gor">
Vad jag gör Vad jag gör
</a> </a>
</div> </article>
<div> <article class="page">
Mer om: Mer om:
<a href="/om"> <a href="/om">
Anders, 39, Hårdrockare Anders, 39, Hårdrockare
</a> </a>
</div> </article>
<div> <article class="feed rss">
<a href="/prenumerera.xml">Prenumerera</a> (RSS 2.0) <a href="/prenumerera.xml">Prenumerera</a> (RSS 2.0)
</div> </article>
<div> <article class="page meta">
<a href="/colophon"> <a href="/colophon">
Kontakt &amp; Kolofon Kontakt &amp; Kolofon
</a> </a>
</div> </article>
</div> </div>
</main> </main>

View file

@ -1,73 +1,65 @@
<header> <h1>Delningar</h1>
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList"> <p>
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> Länkar som är värda att uppmärksammas och lämna åsikt om.
<a href="/" rel="home"> </p>
<span itemprop="name">madr.se</span> <%= for {date, links} <- @links do %>
</a> <section id={"d" <> date}>
<meta itemprop="position" content="1" /> <div class="links">
</li> <h2>
</ol> <%= date
<h1>Delningar</h1> |> Date.from_iso8601!()
<p> |> Calendar.strftime(
Länkar som är värda att uppmärksammas och lämna åsikt om. "%A, %d %B %Y",
</p> month_names: fn m ->
<%= for {date, links} <- @links do %> Enum.at(
<section id={"d" <> date}> [
<div class="links"> "januari",
<h2> "februari",
<%= date "mars",
|> Date.from_iso8601!() "april",
|> Calendar.strftime( "maj",
"%A, %d %B %Y", "juni",
month_names: fn m -> "juli",
Enum.at( "augusti",
[ "september",
"januari", "oktober",
"februari", "november",
"mars", "december"
"april", ],
"maj", m - 1
"juni", )
"juli", end,
"augusti", day_of_week_names: fn d ->
"september", Enum.at(
"oktober", [
"november", "måndag",
"december" "tisdag",
], "onsdag",
m - 1 "torsdag",
) "fredag",
end, "lördag",
day_of_week_names: fn d -> "söndag"
Enum.at( ],
[ d - 1
"måndag", )
"tisdag", end
"onsdag", )
"torsdag", |> String.replace(~r/ 0/, " ") %>
"fredag", </h2>
"lördag", <%= for link <- links do %>
"söndag" <article vocab="https://schema.org/" typeof="WebContent Review" class="bookmark">
], <h3>
d - 1 <span property="name"><%= link["title"] %></span>
) <a class="permalink" href={"/" <> link["slug"]} title="Permalänk">#</a>
end </h3>
) <div property="reviewBody">
|> String.replace(~r/ 0/, " ") %>
</h2>
<%= for link <- links do %>
<article>
<h3>
<%= link["title"] %>
<a class="permalink" href={"/" <> link["slug"]} title="Permalänk">#</a>
</h3>
<%= link["contents"] |> Earmark.as_html!() |> raw %> <%= link["contents"] |> Earmark.as_html!() |> raw %>
<div class="source"> </div>
Källa: <a href={link["source"]} rel="external"><%= link["h1"] %></a> <div class="source">
</div> Källa: <a href={link["source"]} rel="external"><%= link["h1"] %></a>
</article> </div>
<% end %> </article>
</div> <% end %>
</section> </div>
<% end %> </section>
</header> <% end %>

View file

@ -1,82 +1,71 @@
<header> <form metod="get" action="/sok">
<ol class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList"> <label for="q">Sök innehåll</label>: <input size="9" type="search" id="q" name="q" value={@q} />
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> <button>Sök</button>
<a href="/" rel="home"> </form>
<span itemprop="name">madr.se</span> <h1><%= @page_title %></h1>
</a> <%= for item = %{t: t} <- @results do %>
<meta itemprop="position" content="1" /> <article>
</li> <%= if t == :articles do %>
</ol> <h3>
<form metod="get" action="/sok"> <a href={"/" <> item["slug"]}>
<label for="q">Sök innehåll</label>:
<input size="9" type="search" id="q" name="q" value={@q} />
<button>Sök</button>
</form>
<h1><%= @page_title %></h1>
<%= for item = %{t: t} <- @results do %>
<article>
<%= if t == :articles do %>
<h3>
<a href={"/" <> item["slug"]}>
<%= item["title"] %>
</a>
</h3>
<% end %>
<%= if t == :events do %>
<h3>
<a href={"/" <> item["slug"]}>
<%= item["title"] %>
</a>
</h3>
<p><%= item["lead"] %></p>
<%= if item["poster"] do %>
<img
src={ "https://n.madr.se/assets/" <> item["poster"] <> "?key=poster"}
loading="lazy"
alt="Affisch"
width="200"
/>
<% end %>
<% end %>
<%= if t == :links do %>
<h3>
<%= item["title"] %> <%= item["title"] %>
</h3>
<p><%= raw(Earmark.as_html!(item["contents"])) %></p>
Källa:
<a href={"/" <> item["source"]}>
<%= item["h1"] %>
</a> </a>
</h3>
<% end %>
<%= if t == :events do %>
<h3>
<a href={"/" <> item["slug"]}>
<%= item["title"] %>
</a>
</h3>
<p><%= item["lead"] %></p>
<%= if item["poster"] do %>
<img
src={ "https://n.madr.se/assets/" <> item["poster"] <> "?key=poster"}
loading="lazy"
alt="Affisch"
width="200"
/>
<% end %> <% end %>
<%= if t == :albums do %> <% end %>
<h3> <%= if t == :links do %>
<%= item["artist"] <> <h3>
" - " <> item["album"] <> " (" <> to_string(item["year"]) <> ")" %> <%= item["title"] %>
<a </h3>
class="permalink" <p><%= raw(Earmark.as_html!(item["contents"])) %></p>
href={"/" <> to_string(@year) <> "/brutal-legend-" <> item["externalId"]} Källa:
> <a href={"/" <> item["source"]}>
# <%= item["h1"] %>
</a> </a>
</h3> <% end %>
<%= if item["contents"] do %> <%= if t == :albums do %>
<p><%= raw(Earmark.as_html!(item["contents"])) %></p> <h3>
<% end %> <%= item["artist"] <>
<ul> " - " <> item["album"] <> " (" <> to_string(item["year"]) <> ")" %>
<%= for song <- item["songs"] do %> <a
<li><%= song["artist"]["name"] <> " - " <> song["title"] %></li> class="permalink"
<% end %> href={"/" <> to_string(@year) <> "/brutal-legend-" <> item["externalId"]}
</ul> >
<%= if item["cover"] do %> #
<img </a>
src={"https://n.madr.se/assets/" <> item["cover"] <> "?key=rectangular"} </h3>
alt="Skivomslag" <%= if item["contents"] do %>
loading="lazy" <p><%= raw(Earmark.as_html!(item["contents"])) %></p>
height="75"
width="75"
/>
<% end %>
<% end %> <% end %>
</article> <ul>
<% end %> <%= for song <- item["songs"] do %>
</header> <li><%= song["artist"]["name"] <> " - " <> song["title"] %></li>
<% end %>
</ul>
<%= if item["cover"] do %>
<img
src={"https://n.madr.se/assets/" <> item["cover"] <> "?key=rectangular"}
alt="Skivomslag"
loading="lazy"
height="75"
width="75"
/>
<% end %>
<% end %>
</article>
<% end %>