Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Entries for unreleased work are not written here directly. Each issue drops a
fragment in [`changelog.d/`](changelog.d/README.md); the fragments are assembled
fragment in [`changelog.d/`](https://github.com/riddler/statifier-ui/blob/v0.10.1/changelog.d/README.md); the fragments are assembled
into a version section at release. See that README for the format and for when a
change warrants an entry at all.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ The vocabulary that stream can carry is closed and published:
string the format defines. It is the handle to hold and diff across upgrades -
a consumer still ignores types it does not know, but a diff of that list is
how it notices a new one. See the note on pinning the vocabulary in
[ADR-0005](docs/adr/0005-language-neutral-trace-wire-format.md).
[ADR-0005](https://github.com/riddler/statifier-ui/blob/v0.10.1/docs/adr/0005-language-neutral-trace-wire-format.md).

## Checking expressions

Expand Down
26 changes: 21 additions & 5 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ defmodule StatifierUI.MixProject do
defp elixirc_paths(_env), do: ["lib"]

# Hexdocs configuration. These paths are read off the publisher's disk at
# `mix docs` time and need no entry in package()'s files: list - the docs
# tarball hexdocs hosts is built separately from the package tarball
# `mix deps.get` fetches.
# `mix docs` time - the docs tarball hexdocs hosts is built separately from
# the package tarball `mix deps.get` fetches. A guide the README links to
# relatively is also in package()'s files: list, for hex.pm's README page.
defp docs do
[
name: "StatifierUI",
Expand Down Expand Up @@ -69,8 +69,24 @@ defmodule StatifierUI.MixProject do
# `assets` is here because ADR-0009 makes it public API: the JavaScript
# ships as source and the host's bundler compiles it, so a tarball without
# it is a package whose documented hook cannot be imported.
# `test/packaging_test.exs` holds this list against the ADRs.
files: ~w(lib assets mix.exs README.md LICENSE CHANGELOG.md),
# The docs/ guides are here because hex.pm renders the README from this
# tarball, so a README relative link answers 404 there unless its target
# ships; each is also an extra, so the same link works on HexDocs.
# `test/packaging_test.exs` holds this list against the ADRs and the
# README's relative links.
files: ~w(
lib
assets
mix.exs
README.md
LICENSE
CHANGELOG.md
docs/architecture.md
docs/ops-embedding.md
docs/fixture-bundles.md
docs/wire-format.md
docs/telemetry.md
),
links: %{
"GitHub" => @source_url,
"Changelog" => "#{@source_url}/blob/main/CHANGELOG.md"
Expand Down
37 changes: 37 additions & 0 deletions test/packaging_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,41 @@ defmodule StatifierUI.PackagingTest do
assert {"assets", "ADR-0009 (JavaScript ships as source)"} in @published_by_adr
end
end

describe "README relative links" do
# hex.pm renders the README from the package tarball, so a relative link
# there resolves inside the tarball and answers 404 unless the target
# ships; HexDocs rewrites a relative link only when the target is an
# extra. One relative link works on GitHub, HexDocs and hex.pm alike only
# when its target is in both lists. A file that is in neither (an ADR,
# for one) is linked by absolute GitHub URL instead.
test "every relative link target is in package files: and in extras" do
config = Mix.Project.config()
files = config[:package][:files]
extras = Enum.map(config[:docs][:extras], &extra_path/1)

targets = readme_relative_targets()
assert targets != [], "found no relative links in README.md; the scan is broken"

for target <- targets do
assert target in extras,
"README.md links #{target} relatively, but it is not in docs() extras: #{inspect(extras)}"

assert Enum.any?(files, &(target == &1 or String.starts_with?(target, &1 <> "/"))),
"README.md links #{target} relatively, but package() files: does not ship it: #{inspect(files)}"
end
end
end

defp readme_relative_targets do
~r/\]\(([^)\s]+)\)/
|> Regex.scan(File.read!("README.md"), capture: :all_but_first)
|> List.flatten()
|> Enum.reject(&String.match?(&1, ~r{^(https?:|mailto:|#)}))
|> Enum.map(&(&1 |> String.split("#") |> hd()))
|> Enum.uniq()
end

defp extra_path({path, _opts}), do: to_string(path)
defp extra_path(path), do: to_string(path)
end
Loading