Skip to main content

mix.exs

defmodule AshTypst.MixProject do
  use Mix.Project

  @version "0.3.0"
  @source_url "https://github.com/frankdugan3/ash_typst"

  def project do
    [
      app: :ash_typst,
      version: @version,
      elixir: "~> 1.20",
      elixirc_paths: elixirc_paths(Mix.env()),
      deps: deps(),
      description: "Precompiled NIFs and tooling to render Typst documents.",
      package: package(),
      docs: &docs/0,
      aliases: aliases()
    ]
  end

  defp docs do
    [
      main: "readme",
      source_url: @source_url,
      source_ref: "v#{@version}",
      extras: [
        {"README.md", title: "Home"},
        "CHANGELOG.md",
        {"documentation/dsls/DSL-AshTypst.Resource.md",
         search_data: Spark.Docs.search_data_for(AshTypst.Resource)},
        "documentation/topics/security/sensitive-data.md"
      ],
      groups_for_extras: [
        Topics: ~r"documentation/topics",
        Reference: ~r"documentation/dsls",
        "About AshTypst": ["CHANGELOG.md"]
      ],
      before_closing_head_tag: &before_closing_head_tag/1,
      before_closing_body_tag: &before_closing_body_tag/1,
      groups_for_modules: [
        Core: [
          AshTypst,
          AshTypst.Code,
          AshTypst.Context,
          AshTypst.Sigil,
          AshTypst.PathResolver,
          AshTypst.Document,
          AshTypst.Type.Document
        ],
        "Results & Diagnostics": [
          AshTypst.CompileResult,
          AshTypst.BundleResult,
          AshTypst.CompileError,
          AshTypst.Diagnostic,
          AshTypst.Span,
          AshTypst.TraceItem
        ],
        Resource: [
          AshTypst.Resource,
          AshTypst.Resource.Info,
          AshTypst.Resource.Render,
          AshTypst.Resource.Render.Read,
          AshTypst.Resource.Render.PdfOptions,
          AshTypst.Resource.Template
        ]
      ]
    ]
  end

  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  def cli do
    [
      preferred_envs: [
        check: :test,
        credo: :test,
        doctor: :test,
        "deps.audit": :test,
        "test.watch": :test
      ]
    ]
  end

  defp package do
    [
      links: %{
        "GitHub" => @source_url
      },
      licenses: ["MIT"],
      files: [
        "lib",
        "native/typst_nif/.cargo",
        "native/typst_nif/src",
        "native/typst_nif/Cargo*",
        "checksum-*.exs",
        ".formatter.exs",
        "mix.exs",
        "README.md",
        "CHANGELOG.md",
        "LICENSE.md"
      ]
    ]
  end

  def application do
    [
      extra_applications: [:logger]
    ]
  end

  defp deps do
    [
      {:ex_doc, ">= 0.0.0", only: [:dev, :test], runtime: false},
      {:ex_check, ">= 0.0.0", only: :test, runtime: false},
      {:credo, ">= 0.0.0", only: :test, runtime: false},
      {:doctor, ">= 0.0.0", only: :test, runtime: false},
      {:mix_audit, ">= 0.0.0", only: :test, runtime: false},
      {:mix_watch_docs, ">= 0.0.0", only: [:dev, :test], runtime: false},
      {:tzdata, "~> 1.1", only: :test},
      {:mix_test_watch, "~> 1.2", only: :test},
      {:git_ops, "~> 2.7", only: :dev},
      {:usage_rules, "~> 1.1", only: :dev},
      {:igniter, "~> 0.6", optional: true},
      {:rustler, "~> 0.35", optional: true},
      {:sourceror, "~> 1.7", optional: true},
      {:ash, "~> 3.0"},
      {:decimal, "~> 3.0"},
      {:rustler_precompiled, "~> 0.8"}
    ]
  end

  defp before_closing_head_tag(:html) do
    """
    <script defer src="https://cdn.jsdelivr.net/npm/mermaid@10.2.3/dist/mermaid.min.js"></script>
    """
  end

  defp before_closing_head_tag(:epub), do: ""

  defp before_closing_body_tag(:html) do
    """
    <script>
      let initialized = false;

      window.addEventListener("exdoc:loaded", () => {
        if (!initialized) {
          mermaid.initialize({
            startOnLoad: false,
            theme: document.body.className.includes("dark") ? "dark" : "default"
          });
          initialized = true;
        }

        let id = 0;
        for (const codeEl of document.querySelectorAll("pre code.mermaid")) {
          const preEl = codeEl.parentElement;
          const graphDefinition = codeEl.textContent;
          const graphEl = document.createElement("div");
          const graphId = "mermaid-graph-" + id++;
          mermaid.render(graphId, graphDefinition).then(({svg, bindFunctions}) => {
            graphEl.innerHTML = svg;
            bindFunctions?.(graphEl);
            preEl.insertAdjacentElement("afterend", graphEl);
            preEl.remove();
          });
        }
      });
    </script>
    """
  end

  defp before_closing_body_tag(:epub), do: ""

  defp aliases do
    [
      update: ["deps.update --all", "cmd --cd native/typst_nif cargo update --verbose"],
      "format.all": [
        "spark.formatter --extensions AshTypst.Resource",
        "cmd --cd native/typst_nif cargo fmt"
      ],
      outdated: ["hex.outdated", "cmd --cd native/typst_nif cargo update --locked --verbose"],
      setup: ["deps.get", "cmd --cd native/typst_nif cargo fetch"],
      docs: [
        "spark.cheat_sheets --extensions AshTypst.Resource",
        "docs",
        "spark.replace_doc_links"
      ],
      build: ["compile --force", "format.all", "docs"],
      "nif.checksum": ["rustler_precompiled.download AshTypst.NIF --all --print"],
      publish: ["nif.checksum", "hex.publish"]
    ]
  end
end