defmodule Shadix.Generator do
@moduledoc """
Pure helpers for the Shadix generator tooling.
Provides namespace rewriting, default namespace derivation, and default
target directory derivation. Kept separate from Mix tasks so it is
unit-testable without invoking Mix machinery.
"""
@doc """
Rewrites canonical `Shadix.*` module references in `source` to use `namespace`
as the new base.
Three ordered replacements are applied:
1. `Shadix.Components` → `namespace`
2. `Shadix.Cn` → `namespace <> ".Cn"`
3. `Shadix.Form` → `namespace <> ".Form"`
The order matters: `Shadix.Components` is replaced first so the substring
`Shadix.Cn` is never accidentally matched inside a `Shadix.Components.*` name.
iex> Shadix.Generator.rewrite_namespace("import Shadix.Cn", "Demo.UI")
"import Demo.UI.Cn"
"""
@spec rewrite_namespace(String.t(), String.t()) :: String.t()
def rewrite_namespace(source, namespace) do
source
|> String.replace("Shadix.Components", namespace)
|> String.replace("Shadix.Cn", namespace <> ".Cn")
|> String.replace("Shadix.Form", namespace <> ".Form")
end
@doc """
Returns the default target namespace for the current Mix project.
Derived as `<CamelizedApp>Web.Components.UI`.
iex> Shadix.Generator.default_namespace()
"ShadixWeb.Components.UI"
"""
@spec default_namespace() :: String.t()
def default_namespace do
app = Mix.Project.config()[:app]
Macro.camelize(to_string(app)) <> "Web.Components.UI"
end
@doc """
Returns the default target directory for a given namespace.
Derived as `lib/<underscored_namespace>`.
iex> Shadix.Generator.default_dir("MyAppWeb.Components.UI")
"lib/my_app_web/components/ui"
"""
@spec default_dir(String.t()) :: String.t()
def default_dir(namespace) do
underscored = Macro.underscore(namespace)
"lib/#{underscored}"
end
end