Current section
Files
Jump to
Current section
Files
mix.exs
defmodule Visualize.MixProject do
use Mix.Project
# The version between releases carries `-dev`, so no commit claims to be the release it
# merely follows. `~/Projects/claude-tools/release.exs` moves this attribute — it edits
# `@version`, not an inline `version:` — and RELEASING.md describes the lifecycle.
@version "0.2.25"
def project do
[
app: :visualize,
version: @version,
elixir: "~> 1.19",
start_permanent: Mix.env() == :prod,
elixirc_paths: elixirc_paths(Mix.env()),
name: "Visualize",
description:
"Server-side SVG and canvas visualization for Phoenix LiveView, in the shape of D3.",
# The public home (#516): GitLab push-mirrors main and the tags here.
source_url: "https://github.com/dcoai/Visualize",
package: package(),
docs: docs(),
aliases: [
"vis.verify": &verify_models/1,
# Every gate CI runs, in CI's order; see scripts/check.exs.
"vis.check": ["cmd elixir scripts/check.exs"]
],
test_coverage: [summary: [threshold: 0]],
deps: deps()
]
end
# Only `lib/` reaches a consumer. `audit/` holds the surface scanner and its mix tasks
# (dev and test); `test/support` compiles for tests alone.
defp elixirc_paths(:test), do: ["lib", "audit", "specs", "test/support"]
defp elixirc_paths(:dev), do: ["lib", "audit", "specs"]
defp elixirc_paths(_), do: ["lib"]
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:nx, "~> 0.9", optional: true},
# `Visualize.Chart.to_json/1` and `from_json/1` (spec/14 §11): optional like Nx, so a
# consumer without Jason builds silently and the two functions return an error value.
{:jason, "~> 1.4", optional: true},
# `Data.Table.rows/1` (spec/08 §6) reads Explorer frames, and anything else that
# implements `Table.Reader`, through the protocol. The package is the protocol and
# two impls, optional like Nx: without it lists, column maps and tensors still work
# and a struct source raises at the call (D-52).
{:table, "~> 0.1.2", optional: true},
# Explorer frames in the `Data.Table` tests only; scripts/consumer_check.exs proves
# neither Explorer nor `Table.Reader` reaches a consumer.
{:explorer, "~> 0.12", only: :test},
# A time zone database for the zoned time scale's tests (spec/03 §7.5, #447). The library
# reads the host's `Calendar.TimeZoneDatabase` and takes no tz dependency (D-115); the
# tests configure this one in test/test_helper.exs. `only:` is load-bearing: test deps
# are not transitive, and scripts/consumer_check.exs proves `Tz` never reaches a consumer.
{:tz, "~> 0.28", only: :test},
# The LiveView components (spec/10 §2-3) compile only when `Phoenix.Component` is
# loaded. `optional:` is load-bearing, and `only:` would not do: Mix prunes the code
# path to a dependency's declared deps while compiling it, so a guard over an
# undeclared Phoenix never fires in a host. A host without LiveView never fetches it;
# scripts/consumer_check.exs proves that on every pipeline (D-45).
{:phoenix_live_view, "~> 1.0", optional: true},
# `mix vis.surface` (spec/12 §2): the source-scan primitives and the golden renderer
# shared with extc and extla. `only:` is load-bearing: dev/test deps are not transitive,
# so nothing here reaches a consumer of visualize.
{:surfex, "~> 0.6.2", only: [:dev, :test], runtime: false},
{:ex_doc, "~> 0.34", only: :dev, runtime: false},
# Property tests over the scale protocol (spec/03 §1.3; test/visualize/scale/).
{:stream_data, "~> 1.4", only: [:dev, :test]},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
# `mix vis.verify` (spec/12 §5): the model of the force simulation. Pinned by tag, with
# the lock entry committed, so CI and every workstation build the same extla (#441).
{:extla, extla_source() ++ [only: [:dev, :test], runtime: false]}
]
end
# A local extla checkout is an explicit opt-in (`EXTLA_PATH=../extla`), never inferred
# from a sibling directory: that is how an unannounced rename reached the build.
defp extla_source do
case System.get_env("EXTLA_PATH") do
nil -> [git: "git@gitlab.conet.yarina.org:dco-tek/extla.git", tag: "v0.4.0"]
path -> [path: path]
end
end
# Every model, checked one at a time. `Mix.Task.rerun/2`, not a list alias: Mix remembers
# a task by name and silently skips it the second time.
@models ~w(Visualize.Specs.ForceSimulation)
defp verify_models(_args), do: Enum.each(@models, &Mix.Task.rerun("extla.check", [&1]))
# The guides ship with the package, as hexdocs extras a reader starts from. The
# specification, the surface golden and the changelog ship with it too: they are
# the contract a consumer holds the library to, and the record of what an upgrade brings,
# not internal documentation. RELEASING.md is deliberately absent — it is a maintainer
# document, and nothing that ships may link to a file that does not.
defp package do
[
files:
~w(lib guides spec mix.exs README.md LICENSE CHANGELOG.md usage-rules.md API_SURFACE.md .formatter.exs),
licenses: ["MIT"],
links: %{
"GitHub" => "https://github.com/dcoai/Visualize",
"Changelog" => "https://hexdocs.pm/visualize/changelog.html"
}
]
end
# The references the specification makes on purpose to functions that are internal
# (behaviour callbacks; the family modules behind `Geo.Projection` and `CanvasBinary`; the
# one module that calls the resvg binary, spec/09 §9) or that the decisions log
# records as removed or as never having existed (D-2, D-13).
@internal_prefixes [
"Visualize.Backend.SVG.",
"Visualize.Backend.Canvas.",
"Visualize.Backend.CanvasBinary.SVG.",
"Visualize.Backend.CanvasBinary.PathEncoder.",
"Visualize.Backend.CanvasBinary.Opcodes.",
"Visualize.Render.Raster"
]
@recorded_absent [
"Visualize.Geo.Projection.family/1",
"Visualize.Render.with_backend/2",
"Visualize.Scale.scale/2",
"Visualize.Scale.color/0",
"Visualize.Scale.scheme/2"
]
@doc false
def internal_reference?(reference) do
reference in @recorded_absent or
Enum.any?(@internal_prefixes, &String.starts_with?(reference, &1))
end
# `spec/README.md` gets an explicit filename: two README.md extras otherwise collide.
defp docs do
[
main: "readme",
# The tag of the version being documented, which the mirror carries: a "View source"
# link opens the code that was published, not main.
source_ref: "v#{@version}",
# The specification refers, on purpose, to internal functions (behaviour callbacks and
# the family modules behind `Geo.Projection` and `CanvasBinary`) and to functions the
# decisions log records as removed or as called by code that has never run (D-2, D-13).
# Those references are the document's content, not broken links.
skip_code_autolink_to: &__MODULE__.internal_reference?/1,
extras:
[
"README.md",
# The guides, in reading order, ahead of the reference material: where a newcomer
# starts, then the declarative layer, then the one-page summary.
"guides/getting_started.md",
"guides/liveview.md",
"guides/designing_charts.md",
"guides/cheatsheet.cheatmd",
"usage-rules.md",
# The changelog ships in `files:`, so the README's Installation section links it
# as the reference for moving a pinned tag. A link from a shipping document has
# to resolve in the published docs too, which means being an extra.
"CHANGELOG.md",
{"spec/README.md", filename: "specification", title: "Specification index"}
| Path.wildcard("spec/[0-9]*.md")
] ++ ["API_SURFACE.md"],
# ExDoc lists ungrouped extras first, so the README alone stays ungrouped and the
# guides follow it, ahead of the reference documents.
groups_for_extras: [
Guides: ~r"guides/",
Reference: ["usage-rules.md", "CHANGELOG.md"],
Specification: ~r"spec/",
Conformance: ["API_SURFACE.md"]
],
groups_for_modules: [
Facade: [Visualize],
"Declarative chart": ~r"Visualize\.Chart",
Scales: ~r"Visualize\.Scale",
Shapes: ~r"Visualize\.Shape",
"Axes and formatting": [Visualize.Axis, Visualize.Format],
Layouts: ~r"Visualize\.Layout",
Geo: [~r"Visualize\.Geo", Visualize.Polygon, ~r"Visualize\.Contour"],
Utilities: [
Visualize.Color,
Visualize.Interpolate,
Visualize.Ease,
Visualize.Random,
Visualize.Data,
Visualize.Data.Table
],
"IR and rendering": [
~r"Visualize\.IR",
~r"Visualize\.Backend",
Visualize.Render,
Visualize.Incremental,
Visualize.Benchmark
],
"SVG elements": ~r"Visualize\.SVG",
LiveView: [~r"Visualize\.Components", ~r"Visualize\.Hooks"]
]
]
end
end