From 7ac3e5516b0c6eeb003235e4a6066ed47ef6b3a9 Mon Sep 17 00:00:00 2001 From: Andrew Vogel Date: Mon, 3 Mar 2025 12:43:02 -0500 Subject: [PATCH 1/2] fix: adjust html markup so that it's parsed nicely by safari's reader mode * rework html markup by removing extra section tag and replacing h1 with header * fixes css that was broken by changes to structure * add structured data so browser can infer things like markup, type, title, and author --- assets/css/components.css | 64 ++++++++----- assets/js/like.js | 2 +- lib/tilex_web/templates/shared/post.html.eex | 92 +++++++++---------- test/features/visitor_searches_posts_test.exs | 2 +- test/features/visitor_views_channel_test.exs | 4 +- .../features/visitor_visits_homepage_test.exs | 2 +- test/support/pages/post_show_page.ex | 4 +- 7 files changed, 91 insertions(+), 79 deletions(-) diff --git a/assets/css/components.css b/assets/css/components.css index cf6687771..8c347fc64 100644 --- a/assets/css/components.css +++ b/assets/css/components.css @@ -47,9 +47,15 @@ nav.pagination a:hover { } .post { display: flex; - align-items: flex-start; + flex-direction: column; + margin: 0 auto; margin-bottom: 3vw; - justify-content: center; + min-width: 35rem; + max-width: 60%; + background: rgb(251, 253, 254); + border: 0.2rem solid rgb(255, 255, 255); + box-shadow: 5px 5px 7px var(--navy-light); + box-sizing: border-box; } .post:after { content: ""; @@ -62,37 +68,34 @@ nav.pagination a:hover { @media screen and (max-width: 480px) { .post { display: block; - padding: 0 1rem; + margin: 1rem; } } .post.draft { opacity: 0.8; } -.post section { - flex: 0 1 auto; - box-sizing: border-box; - min-width: 35rem; - max-width: 60%; - background: rgb(251, 253, 254); - border: 0.2rem solid rgb(255, 255, 255); - box-shadow: 5px 5px 7px var(--navy-light); -} @media screen and (max-width: 480px) { - .post section { + .post { max-width: none; min-width: 0; } } -.post .post__content { +.post.post__content { overflow: auto; - padding: 4vw; + padding-top: 4vw; + + header, footer, .copy, a.twitter-share-button { + padding: 0 4vw; + } } -.post .post__content h1:first-of-type a { +.post.post__content header:first-of-type a { + font-family: var(--primary-typeface); + font-weight: bold; color: inherit; display: block; transition: color 0.1s; } -.post .post__content h1:first-of-type a:hover { +.post.post__content header:first-of-type a:hover { color: var(--red); } .post footer { @@ -125,6 +128,9 @@ nav.pagination a:hover { .post footer a:hover { text-decoration: underline; } +.post aside { + padding-top: 4vw; +} .post aside ul { display: flex; width: 100%; @@ -341,15 +347,25 @@ form input[type='submit']:active, form button[type='submit']:active, form input[ font-size: 0.85em; } } -.copy h1, .copy h2, .copy h3, .copy p, .copy ul, .copy ol { - margin: 0 0 1.2em 0; +.post.post__content header, .copy { + h1, h2, h3, h4, h5, p, ul, ol { + margin: 0 0 1.2em 0; + } + header:first-type-of a { + margin: 0 0 1.2em 0; + } } @media screen and (max-width: 480px) { - .copy h1, .copy h2, .copy h3, .copy p, .copy ul, .copy ol { - margin-bottom: 0.7em; - } -} -.copy h1 { + .post.post__content header, .copy { + h1, h2, h3, h4, h5, p, ul, ol { + margin-bottom: 0.7em; + } + header:first-type-of a { + margin-bottom: 0.7em; + } + } +} +.copy h1, .post.post__content header:first-of-type a { font-size: 1.6em; } .copy h2, .copy h3 { diff --git a/assets/js/like.js b/assets/js/like.js index 41057ad56..bf9498e0a 100644 --- a/assets/js/like.js +++ b/assets/js/like.js @@ -71,5 +71,5 @@ $(function(){ new LikeButton(this); }); - $('header').attr('data-likes-loaded', 'true') + $('header.site_head').attr('data-likes-loaded', 'true') }); diff --git a/lib/tilex_web/templates/shared/post.html.eex b/lib/tilex_web/templates/shared/post.html.eex index b03e6d2b9..ac253abe9 100644 --- a/lib/tilex_web/templates/shared/post.html.eex +++ b/lib/tilex_web/templates/shared/post.html.eex @@ -1,55 +1,51 @@ -
-
-
-

- <%= link(@post.title, to: Routes.post_path(@conn, :show, @post)) %> -

- <%= raw Tilex.Markdown.to_html(@post.body) %> +
+
+

<%= link(@post.title, to: Routes.post_path(@conn, :show, @post)) %>

+
- <%= if assigns[:twitter_shareable] && Mix.env != :test do %> - - <% end %> +
+ <%= raw Tilex.Markdown.to_html(@post.body) %> +
+ + <%= if assigns[:twitter_shareable] && Mix.env != :test do %> + + <% end %> -
- -
+
+ <%= link(@post.developer.username, to: Routes.developer_path(@conn, :show, @post.developer), itemprop: "author") %> + -
+ -
+ + +
diff --git a/test/features/visitor_searches_posts_test.exs b/test/features/visitor_searches_posts_test.exs index f41eb8352..c6a882388 100644 --- a/test/features/visitor_searches_posts_test.exs +++ b/test/features/visitor_searches_posts_test.exs @@ -64,6 +64,6 @@ defmodule VisiorSearchesPosts do end defp get_first_post_on_page_title(session) do - get_text(session, "#home > article:first-child h1 a") + get_text(session, "#home > article:first-child header a") end end diff --git a/test/features/visitor_views_channel_test.exs b/test/features/visitor_views_channel_test.exs index ec03a8a8a..df1494922 100644 --- a/test/features/visitor_views_channel_test.exs +++ b/test/features/visitor_views_channel_test.exs @@ -42,10 +42,10 @@ defmodule Features.VisitorViewsChannelTest do |> assert_has(Query.css("article.post", count: 5)) |> assert_has(Query.css("nav.pagination", visible: true)) |> visit("/smalltalk?page=2") - |> assert_has(Query.css("h1", text: "Title1", visible: true)) + |> assert_has(Query.css("article header a", text: "Title1", visible: true)) |> assert_has(Query.css("article.post", count: 1)) |> visit("/smalltalk") - |> assert_has(Query.css("h1", text: "Title5", visible: true)) + |> assert_has(Query.css("article header a", text: "Title5", visible: true)) |> assert_has(Query.css("article.post", count: 5)) end end diff --git a/test/features/visitor_visits_homepage_test.exs b/test/features/visitor_visits_homepage_test.exs index e1191baf0..a3490fc76 100644 --- a/test/features/visitor_visits_homepage_test.exs +++ b/test/features/visitor_visits_homepage_test.exs @@ -35,7 +35,7 @@ defmodule VisitorVisitsHomepageTest do Element.text(find(session, Query.css(selector))) end - post_header = element_text.(session, "article h1") + post_header = element_text.(session, "article header a") post_body = element_text.(session, "article") post_footer = element_text.(session, ".post aside") diff --git a/test/support/pages/post_show_page.ex b/test/support/pages/post_show_page.ex index 24b9de306..d9c92d140 100644 --- a/test/support/pages/post_show_page.ex +++ b/test/support/pages/post_show_page.ex @@ -10,7 +10,7 @@ defmodule Tilex.Integration.Pages.PostShowPage do |> Browser.find(Query.css("article.post")) session - |> Browser.find(Query.css("h1", text: title)) + |> Browser.find(Query.css("header a", text: title)) session end @@ -29,7 +29,7 @@ defmodule Tilex.Integration.Pages.PostShowPage do expected_likes_count = attrs |> Map.fetch!(:likes_count) |> to_string() session - |> Browser.find(Query.css(".post h1", text: expected_title)) + |> Browser.find(Query.css(".post header a", text: expected_title)) session |> Browser.find(Query.css(".post .copy", text: expected_body)) From e0de631ee493cbebea4cf96a7e62929ab3e2c5ad Mon Sep 17 00:00:00 2001 From: Andrew Vogel Date: Sun, 4 May 2025 13:46:26 -0400 Subject: [PATCH 2/2] chore: update esbuild version for nested css support --- assets/css/components.css | 6 +++--- config/config.exs | 2 +- mix.lock | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/css/components.css b/assets/css/components.css index 8c347fc64..644e1f8d5 100644 --- a/assets/css/components.css +++ b/assets/css/components.css @@ -84,7 +84,7 @@ nav.pagination a:hover { overflow: auto; padding-top: 4vw; - header, footer, .copy, a.twitter-share-button { + :is(header, footer), .copy, a.twitter-share-button { padding: 0 4vw; } } @@ -348,7 +348,7 @@ form input[type='submit']:active, form button[type='submit']:active, form input[ } } .post.post__content header, .copy { - h1, h2, h3, h4, h5, p, ul, ol { + :is(h1, h2, h3, h4, h5, p, ul, ol) { margin: 0 0 1.2em 0; } header:first-type-of a { @@ -357,7 +357,7 @@ form input[type='submit']:active, form button[type='submit']:active, form input[ } @media screen and (max-width: 480px) { .post.post__content header, .copy { - h1, h2, h3, h4, h5, p, ul, ol { + :is(h1, h2, h3, h4, h5, p, ul, ol) { margin-bottom: 0.7em; } header:first-type-of a { diff --git a/config/config.exs b/config/config.exs index 56658113c..fbfddeca2 100644 --- a/config/config.exs +++ b/config/config.exs @@ -34,7 +34,7 @@ config :swoosh, :api_client, false # Configure esbuild (the version is required) config :esbuild, - version: "0.14.29", + version: "0.18.6", default: [ args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), diff --git a/mix.lock b/mix.lock index 5aed5a521..3600a8234 100644 --- a/mix.lock +++ b/mix.lock @@ -18,7 +18,7 @@ "earmark": {:hex, :earmark, "1.4.47", "7e7596b84fe4ebeb8751e14cbaeaf4d7a0237708f2ce43630cfd9065551f94ca", [:mix], [], "hexpm", "3e96bebea2c2d95f3b346a7ff22285bc68a99fbabdad9b655aa9c6be06c698f8"}, "ecto": {:hex, :ecto, "3.12.3", "1a9111560731f6c3606924c81c870a68a34c819f6d4f03822f370ea31a582208", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9efd91506ae722f95e48dc49e70d0cb632ede3b7a23896252a60a14ac6d59165"}, "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, - "esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"}, + "esbuild": {:hex, :esbuild, "0.9.0", "f043eeaca4932ca8e16e5429aebd90f7766f31ac160a25cbd9befe84f2bc068f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b415027f71d5ab57ef2be844b2a10d0c1b5a492d431727f43937adce22ba45ae"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},