External links in post bodies now open in a new tab and show a box-with-arrow marker icon, so readers can tell at a glance which links leave the site. - blogex: new Blogex.ExternalLinks.rewrite/1 marks up anchors with http(s) hrefs at compile time with target="_blank", rel="noopener" and class="blogex-external" (idempotent, merges into existing class/rel values, leaves relative, mailto: and #anchor links alone) - blogex: Post.build/3 applies the rewrite, so every blog gets it - app: CSS in .blogex-post-body draws the marker via a mask so it inherits the link colour; empty ::after content stays invisible to screen readers - make test now also runs the blogex suite; it is currently red with 3 pre-existing blog_integration_test failures caused by the vacuous link validator (parked yak link-validator-never-sees-compiled-html-...)
103 lines
2.8 KiB
Elixir
103 lines
2.8 KiB
Elixir
defmodule Blogex.PostTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
alias Blogex.Post
|
|
|
|
describe "build/3" do
|
|
test "extracts date from filename path" do
|
|
post = Post.build("anything/2026/03-10-my-slug.md", valid_attrs(), "<p>body</p>")
|
|
|
|
assert post.date == ~D[2026-03-10]
|
|
end
|
|
|
|
test "extracts slug from filename" do
|
|
post = Post.build("anything/2026/01-05-cool-feature.md", valid_attrs(), "<p>body</p>")
|
|
|
|
assert post.id == "cool-feature"
|
|
end
|
|
|
|
test "preserves slug with multiple hyphens" do
|
|
post = Post.build("x/2026/06-01-my-multi-part-slug.md", valid_attrs(), "<p>x</p>")
|
|
|
|
assert post.id == "my-multi-part-slug"
|
|
end
|
|
|
|
test "merges frontmatter attributes into struct" do
|
|
attrs = %{
|
|
title: "Custom Title",
|
|
author: "Specific Author",
|
|
description: "Custom desc",
|
|
tags: ~w(alpha beta)
|
|
}
|
|
|
|
post = Post.build("x/2026/01-01-x.md", attrs, "<p>x</p>")
|
|
|
|
assert post.title == "Custom Title"
|
|
assert post.author == "Specific Author"
|
|
assert post.tags == ["alpha", "beta"]
|
|
end
|
|
|
|
test "stores rendered HTML body" do
|
|
html = "<h1>Hello</h1><p>World</p>"
|
|
|
|
post = Post.build("x/2026/01-01-x.md", valid_attrs(), html)
|
|
|
|
assert post.body == html
|
|
end
|
|
|
|
test "adds target, rel and marker class to external links in stored body" do
|
|
html = ~s(<p>See <a href="https://en.wikipedia.org/wiki/Blog">Wikipedia</a></p>)
|
|
|
|
post = Post.build("x/2026/01-01-x.md", valid_attrs(), html)
|
|
|
|
assert post.body =~
|
|
~s(<a href="https://en.wikipedia.org/wiki/Blog" target="_blank" rel="noopener" class="blogex-external">Wikipedia</a>)
|
|
end
|
|
|
|
test "leaves internal links in stored body untouched" do
|
|
html = ~s(<p>See <a href="/blog/engineering/swim-the-test">Swim the Test</a></p>)
|
|
|
|
post = Post.build("x/2026/01-01-x.md", valid_attrs(), html)
|
|
|
|
assert post.body == html
|
|
end
|
|
|
|
test "defaults published to true" do
|
|
post = Post.build("x/2026/01-01-x.md", valid_attrs(), "<p>x</p>")
|
|
|
|
assert post.published == true
|
|
end
|
|
|
|
test "allows overriding published to false" do
|
|
attrs = Map.put(valid_attrs(), :published, false)
|
|
|
|
post = Post.build("x/2026/01-01-x.md", attrs, "<p>x</p>")
|
|
|
|
assert post.published == false
|
|
end
|
|
|
|
test "preserves image from frontmatter" do
|
|
attrs = Map.put(valid_attrs(), :image, "/images/cover.png")
|
|
|
|
post = Post.build("x/2026/01-01-x.md", attrs, "<p>x</p>")
|
|
|
|
assert post.image == "/images/cover.png"
|
|
end
|
|
|
|
test "defaults image to nil when not in frontmatter" do
|
|
post = Post.build("x/2026/01-01-x.md", valid_attrs(), "<p>x</p>")
|
|
|
|
assert post.image == nil
|
|
end
|
|
end
|
|
|
|
defp valid_attrs do
|
|
%{
|
|
title: "Title",
|
|
author: "Author",
|
|
description: "Desc",
|
|
tags: ["tag"]
|
|
}
|
|
end
|
|
end
|