Packages

Analyze, transform, and render Figma files from Elixir

Current section

Files

Jump to
figler mix.exs
Raw

mix.exs

defmodule Figler.MixProject do
use Mix.Project
@version "0.1.0-beta.1"
@source_url "https://github.com/open-pencil/figler"
def project do
[
app: :figler,
version: @version,
elixir: "~> 1.19",
start_permanent: Mix.env() == :prod,
description: "Analyze, transform, and render Figma files from Elixir",
elixirc_paths: elixirc_paths(Mix.env()),
aliases: aliases(),
dialyzer: [plt_add_apps: [:mix], flags: [:no_opaque]],
package: package(),
docs: docs(),
deps: deps()
]
end
def cli do
[preferred_envs: [ci: :test]]
end
def application do
[extra_applications: [:logger]]
end
defp elixirc_paths(:test), do: ["lib", "codegen"]
defp elixirc_paths(_env), do: ["lib"]
defp aliases do
[
ci: [
"compile --warnings-as-errors",
"kiwi.gen.check",
"rustq.gen --check",
"format --check-formatted",
"rust.fmt --check",
"rust.check",
"rust.clippy",
"test",
"credo --strict",
"dialyzer --plt",
"dialyzer",
"ex_dna --max-clones 0",
"reach.check --arch --smells"
],
"kiwi.gen.check": &kiwi_gen_check/1,
"native.gen": "rustq.gen",
"native.gen.check": "rustq.gen --check",
"rust.fmt": &rust_fmt/1,
"rust.check": &rust_check/1,
"rust.clippy": &rust_clippy/1
]
end
defp kiwi_gen_check(_args) do
Mix.Task.run("loadpaths")
schema_path = "priv/schema/fig.kiwi"
generated_dir = "lib/generated"
tmp_dir =
Path.join(System.tmp_dir!(), "figler-kiwi-gen-check-#{System.unique_integer([:positive])}")
try do
schema_path
|> File.read!()
|> KiwiCodec.FileGenerator.generate_files!(module_prefix: Figler.Schema, out: tmp_dir)
compare_generated_files!(tmp_dir, generated_dir)
after
File.rm_rf!(tmp_dir)
end
end
defp compare_generated_files!(expected_dir, actual_dir) do
expected_files = relative_files(expected_dir)
actual_files = relative_files(actual_dir)
missing = expected_files -- actual_files
extra = actual_files -- expected_files
changed =
Enum.filter(
expected_files -- missing,
&generated_file_changed?(expected_dir, actual_dir, &1)
)
case {missing, extra, changed} do
{[], [], []} ->
Mix.shell().info("Fresh Kiwi schema modules: #{actual_dir}")
_stale ->
Mix.raise("""
Stale Kiwi schema modules in #{actual_dir}.
Missing files: #{inspect(missing)}
Extra files: #{inspect(extra)}
Changed files: #{inspect(changed)}
Run:
mix kiwi.gen priv/schema/fig.kiwi --module-prefix Figler.Schema --out #{actual_dir}
""")
end
end
defp generated_file_changed?(expected_dir, actual_dir, relative_path) do
expected_path = Path.join(expected_dir, relative_path)
actual_path = Path.join(actual_dir, relative_path)
formatted_file!(expected_path) != formatted_file!(actual_path)
end
defp formatted_file!(path) do
path
|> File.read!()
|> Code.format_string!(file: path)
|> IO.iodata_to_binary()
end
defp relative_files(dir) do
dir
|> Path.join("**/*")
|> Path.wildcard()
|> Enum.reject(&File.dir?/1)
|> Enum.map(&Path.relative_to(&1, dir))
|> Enum.sort()
end
defp rust_fmt(args) do
rust_cmd(["fmt", "--manifest-path", "native/Cargo.toml"] ++ args)
end
defp rust_check(_args) do
rust_cmd(["check", "--manifest-path", "native/Cargo.toml"])
end
defp rust_clippy(_args) do
rust_cmd([
"clippy",
"--manifest-path",
"native/Cargo.toml",
"--",
"-D",
"warnings"
])
end
defp rust_cmd(args) do
{_, status} = System.cmd("cargo", args, into: IO.stream(), stderr_to_stdout: true)
if status != 0 do
Mix.raise("cargo #{Enum.join(args, " ")} failed")
end
end
defp deps do
[
kiwi_codec_dep(),
rustq_dep(),
json_codec_dep(),
{:ezstd, "~> 1.2"},
{:rustler, "~> 0.38"},
{:skia, "~> 0.3.7", optional: true},
{:reach, "~> 2.6", only: [:dev, :test], runtime: false},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
{:ex_dna, "~> 1.5", only: [:dev, :test], runtime: false},
{:ex_slop, "~> 0.4", only: [:dev, :test], runtime: false},
{:ex_doc, "~> 0.34", only: [:dev, :test], runtime: false}
]
end
defp kiwi_codec_dep do
{:kiwi_codec, "~> 0.3.1"}
end
defp rustq_dep do
{:rustq, "~> 1.0.0-rc.3", only: [:dev, :test], runtime: false}
end
defp json_codec_dep do
{:json_codec, "~> 0.1.0"}
end
defp package do
[
licenses: ["MIT"],
links: %{"GitHub" => @source_url},
files:
runtime_files() ++
[
"native/Cargo.toml",
"native/Cargo.lock",
"native/src",
"priv/schema",
"guides",
"mix.exs",
"README.md",
"CHANGELOG.md",
"LICENSE*"
]
]
end
defp runtime_files do
"lib/**/*.ex"
|> Path.wildcard()
|> Enum.reject(&String.starts_with?(&1, "lib/mix/"))
end
defp docs do
[
main: "readme",
extras: [
"README.md",
"CHANGELOG.md",
"guides/introduction/getting-started.md",
"guides/introduction/why-figler.md",
"guides/querying/querying-scenes.md",
"guides/querying/effective-graphs.md",
"guides/querying/transforming-files.md",
"guides/querying/schema-and-codecs.md",
"guides/rendering/headless-rendering.md",
"guides/rendering/rendering-support.md",
"guides/rendering/rendering-warnings.md",
"guides/rendering/fonts.md",
"guides/production/performance-and-safety.md",
"guides/production/native-builds.md",
"guides/production/compatibility.md",
"guides/reference/errors-and-options.md"
],
groups_for_extras: [
Introduction: ~r/guides\/introduction\//,
"Analysis and Transformation": ~r/guides\/querying\//,
Rendering: ~r/guides\/rendering\//,
Production: ~r/guides\/production\//,
Reference: ~r/guides\/reference\//
],
filter_modules: &public_doc_module?/2,
groups_for_modules: docs_groups_for_modules(),
source_ref: "v#{@version}",
source_url: @source_url
]
end
defp public_doc_module?(module, _metadata) do
name = Atom.to_string(module)
name not in [
"Elixir.Figler.Render.Projection",
"Elixir.Figler.Scene.Input",
"Elixir.Figler.Scene.Projection",
"Elixir.Figler.Scene.Query",
"Elixir.Figler.Scene.Tree"
] and
not Enum.any?(
[
"Elixir.Figler.Codegen",
"Elixir.Figler.Native",
"Elixir.Figler.Render.Skia",
"Elixir.Mix.Tasks.Figler."
],
&String.starts_with?(name, &1)
)
end
defp docs_groups_for_modules do
[
Core: [Figler, Figler.Container, Figler.Sparse],
"Generated schema": [~r/^Figler\.Schema/],
Errors: [Figler.Error, Figler.OptionError],
"Scene graph": [~r/^Figler\.Scene\.Graph(\.Options)?$/],
"Scene graph diagnostics": [~r/^Figler\.Scene\.Graph\.(Oracle|Profile)(\.|$)/],
"Scene graph internals": [
~r/^Figler\.Scene\.Graph\.(Build|Component|Diff|GUID|Nodes|Patch|Provenance|Seed|Symbol)(\.|$)/
],
Documents: [Figler.Document, Figler.Document.Page],
"Scene queries": [~r/^Figler\.Scene(\.|$)/],
Rendering: [~r/^Figler\.Render(\.|$)/]
]
end
end