refactor(Blogex.LinkValidator): simplify dead code and naming

- Drop redundant :ok return in _validate_links/2 (blog.ex)
- Remove dead HTML link regex from extract_links/1 (body is raw markdown)
- Rename slug_slug_end/1 to slug_end/1
- Simplify parse_blog_link/1 to return {blog_id, slug}, removing
  parse_query_fragment/1 and dead case branches
This commit is contained in:
Firehose Bot
2026-05-07 13:24:11 +01:00
parent 1f0423841a
commit a83634da36
3 changed files with 27 additions and 67 deletions
+1 -5
View File
@@ -153,9 +153,7 @@ defmodule Blogex.Blog do
def _validate_links(posts, blog_id) do
Enum.each(posts, fn post ->
case Blogex.LinkValidator.validate_body(post.body, blog_id, post_id: post.id) do
:ok ->
:ok
:ok -> :ok
{:error, errors} ->
raise Blogex.LinkError,
blog: blog_id,
@@ -163,7 +161,5 @@ defmodule Blogex.Blog do
errors: errors
end
end)
:ok
end
end
+15 -51
View File
@@ -50,39 +50,27 @@ defmodule Blogex.LinkValidator do
`/blog/{engineering|releases}/{slug}`. External links and non-blog
internal links are ignored.
Handles both markdown link syntax `[text](url)` and HTML `<a href="url">`.
Handles markdown link syntax `[text](url)`.
## Examples
iex> extract_links("<p>[link](/blog/engineering/post)</p>")
iex> extract_links("[link](/blog/engineering/post)")
["/blog/engineering/post"]
iex> extract_links("<p><a href=\"/blog/engineering/post\">link</a></p>")
["/blog/engineering/post"]
iex> extract_links("<p>See [GitHub](https://github.com)</p>")
iex> extract_links("See [GitHub](https://github.com)")
[]
"""
@spec extract_links(String.t()) :: [String.t()]
def extract_links(body) when is_binary(body) do
markdown_links =
~r/\[([^\]]+)\]\(([^)]+)\)/
|> Regex.scan(body)
|> Enum.map(fn [_, _, path] -> path end)
html_links =
~r/<a\s+href=["']([^"']*)["']/i
|> Regex.scan(body)
|> Enum.map(fn [_, path] -> path end)
(markdown_links ++ html_links)
|> Enum.uniq()
~r/\[([^\]]+)\]\(([^)]+)\)/
|> Regex.scan(body)
|> Enum.map(fn [_, _, path] -> path end)
|> Enum.filter(&internal_blog_link?/1)
end
defp internal_blog_link?(path) do
case parse_blog_link(path) do
{_blog_id_str, _slug, _query, _fragment} -> true
{_, _} -> true
nil -> false
end
end
@@ -109,7 +97,7 @@ defmodule Blogex.LinkValidator do
nil ->
{:error, "not a blog link: #{link}"}
{blog_id_str, slug_part, _query, _fragment} ->
{blog_id_str, slug_part} ->
case Map.fetch(@valid_blog_ids, blog_id_str) do
{:ok, _blog_atom} -> validate_slug(slug_part)
:error -> {:error, "unknown blog ID: #{blog_id_str}"}
@@ -186,53 +174,29 @@ defmodule Blogex.LinkValidator do
end
end
# --- Private helpers ---
@doc false
@spec parse_blog_link(String.t()) ::
{String.t(), String.t(), String.t() | nil, String.t() | nil} | nil
@spec parse_blog_link(String.t()) :: {String.t(), String.t()} | nil
def parse_blog_link(path) do
# Parse /blog/{id}/{slug} with optional query string and/or fragment
with ["", "blog", blog_id, rest] <- String.split(path, "/", parts: 4),
{slug, query_fragment} <- String.split_at(rest, slug_slug_end(rest)),
{query, fragment} <- parse_query_fragment(query_fragment) do
case Map.fetch(@valid_blog_ids, blog_id) do
{:ok, _blog_atom} -> {blog_id, slug, query, fragment}
:error -> {blog_id, slug, query, fragment}
end
with ["", "blog", blog_id, rest] <- String.split(path, "/", parts: 4) do
slug = String.slice(rest, 0, slug_end(rest))
{blog_id, slug}
else
_ -> nil
end
end
@doc false
@spec slug_slug_end(String.t()) :: integer()
defp slug_slug_end(str) do
@spec slug_end(String.t()) :: integer()
defp slug_end(str) do
case String.split(str, ["?", "#"], parts: 2) do
[slug | _] -> String.length(slug)
_ -> String.length(str)
end
end
@doc false
@spec parse_query_fragment(String.t()) :: {String.t() | nil, String.t() | nil}
defp parse_query_fragment("") do
{nil, nil}
end
defp parse_query_fragment("?" <> query) do
case String.split(query, "#", parts: 2) do
[q, f] -> {q, f}
[q] -> {q, nil}
end
end
defp parse_query_fragment("#" <> fragment) do
{nil, fragment}
end
defp parse_query_fragment(_), do: {nil, nil}
@doc false
@spec validate_slug(String.t()) :: :ok | {:error, String.t()}
defp validate_slug(slug) when slug == "" do