2022-07-28 07:57:39 +12:00
|
|
|
defmodule AshHqWeb.Helpers do
|
2022-08-07 11:22:58 +12:00
|
|
|
@moduledoc "Simple helpers for doc liveviews"
|
|
|
|
|
2022-09-13 11:36:28 +12:00
|
|
|
require Logger
|
|
|
|
|
|
|
|
alias AshHqWeb.DocRoutes
|
|
|
|
|
2022-07-28 07:57:39 +12:00
|
|
|
def latest_version(library) do
|
2022-10-31 13:58:34 +13:00
|
|
|
case library.versions do
|
|
|
|
[] ->
|
|
|
|
nil
|
|
|
|
|
|
|
|
versions ->
|
|
|
|
Enum.min(versions, &(Version.compare(&1.version, &2.version) != :lt))
|
|
|
|
end
|
2022-07-28 07:57:39 +12:00
|
|
|
end
|
2022-09-13 11:36:28 +12:00
|
|
|
|
|
|
|
def source_link(%AshHq.Docs.Module{file: file}, library, library_version) do
|
|
|
|
"https://github.com/ash-project/#{library.name}/tree/v#{library_version.version}/#{file}"
|
|
|
|
end
|
|
|
|
|
2022-09-30 05:56:07 +13:00
|
|
|
def source_link(%AshHq.Docs.MixTask{file: file}, library, library_version) do
|
|
|
|
"https://github.com/ash-project/#{library.name}/tree/v#{library_version.version}/#{file}"
|
|
|
|
end
|
|
|
|
|
2022-09-13 11:36:28 +12:00
|
|
|
def source_link(%AshHq.Docs.Function{file: file, line: line}, library, library_version) do
|
|
|
|
if line do
|
|
|
|
"https://github.com/ash-project/#{library.name}/tree/v#{library_version.version}/#{file}#L#{line}"
|
|
|
|
else
|
|
|
|
"https://github.com/ash-project/#{library.name}/tree/v#{library_version.version}/#{file}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def render_replacements(_, _, nil), do: ""
|
|
|
|
|
|
|
|
def render_replacements(libraries, selected_versions, docs) do
|
|
|
|
docs
|
|
|
|
|> render_links(libraries, selected_versions)
|
|
|
|
|> render_mix_deps(libraries, selected_versions)
|
|
|
|
end
|
|
|
|
|
|
|
|
defp render_mix_deps(docs, libraries, selected_versions) do
|
2022-10-31 13:58:34 +13:00
|
|
|
docs
|
|
|
|
|> String.replace(
|
|
|
|
~r/<code class="makeup elixir highlight">[\s\S]*?(?=<\/code>)/,
|
|
|
|
fn text ->
|
|
|
|
String.replace(text, ~r/{{mix_dep:.*}}/, fn text ->
|
|
|
|
try do
|
|
|
|
"{{mix_dep:" <> library = String.trim_trailing(text, "}}")
|
|
|
|
|
|
|
|
"#{render_mix_dep(libraries, library, selected_versions, text)}"
|
|
|
|
rescue
|
|
|
|
e ->
|
|
|
|
Logger.error(
|
|
|
|
"Invalid link #{Exception.format(:error, e)}\n#{Exception.format_stacktrace(__STACKTRACE__)}"
|
|
|
|
)
|
|
|
|
|
|
|
|
text
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
)
|
|
|
|
|> String.replace(~r/{{mix_dep:.*}}/, fn text ->
|
2022-09-13 11:36:28 +12:00
|
|
|
try do
|
|
|
|
"{{mix_dep:" <> library = String.trim_trailing(text, "}}")
|
|
|
|
|
|
|
|
"<pre><code>#{render_mix_dep(libraries, library, selected_versions, text)}</code></pre>"
|
|
|
|
rescue
|
|
|
|
e ->
|
|
|
|
Logger.error(
|
|
|
|
"Invalid link #{Exception.format(:error, e)}\n#{Exception.format_stacktrace(__STACKTRACE__)}"
|
|
|
|
)
|
|
|
|
|
|
|
|
text
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
defp render_mix_dep(libraries, library, selected_versions, source) do
|
|
|
|
library =
|
|
|
|
Enum.find(libraries, &(&1.name == library)) ||
|
|
|
|
raise "No such library in link: #{source}"
|
|
|
|
|
|
|
|
version =
|
|
|
|
if selected_versions[library.id] == "latest" do
|
|
|
|
AshHqWeb.Helpers.latest_version(library)
|
|
|
|
else
|
|
|
|
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
|
|
|
|
nil ->
|
2022-10-23 02:34:55 +13:00
|
|
|
AshHqWeb.Helpers.latest_version(library)
|
2022-09-13 11:36:28 +12:00
|
|
|
|
|
|
|
version ->
|
|
|
|
version
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
case Version.parse(version.version) do
|
|
|
|
{:ok, %Version{pre: pre, build: build}}
|
|
|
|
when not is_nil(pre) or not is_nil(build) ->
|
|
|
|
~s({:#{library.name}, "~> #{version.version}"})
|
|
|
|
|
|
|
|
{:ok, %Version{major: major, minor: minor, patch: 0}} ->
|
|
|
|
~s({:#{library.name}, "~> #{major}.#{minor}"})
|
|
|
|
|
|
|
|
{:ok, version} ->
|
|
|
|
~s({:#{library.name}, "~> #{version.version}"})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def render_links(docs, libraries, selected_versions) do
|
2022-10-31 13:58:34 +13:00
|
|
|
String.replace(docs, ~r/{{link:[^}]*}}/, fn text ->
|
2022-09-13 11:36:28 +12:00
|
|
|
try do
|
|
|
|
"{{link:" <> rest = String.trim_trailing(text, "}}")
|
|
|
|
[library, type, item | rest] = String.split(rest, ":")
|
|
|
|
render_link(libraries, selected_versions, library, type, item, text, rest)
|
|
|
|
rescue
|
|
|
|
e ->
|
|
|
|
Logger.error(
|
|
|
|
"Invalid link #{Exception.format(:error, e)}\n#{Exception.format_stacktrace(__STACKTRACE__)}"
|
|
|
|
)
|
|
|
|
|
|
|
|
text
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
defp render_link(libraries, selected_versions, library, type, item, source, rest) do
|
|
|
|
library =
|
|
|
|
Enum.find(libraries, &(&1.name == library)) ||
|
|
|
|
raise "No such library in link: #{source}"
|
|
|
|
|
|
|
|
version =
|
|
|
|
if selected_versions[library.id] in ["latest", nil, ""] do
|
2022-09-30 09:27:55 +13:00
|
|
|
AshHqWeb.Helpers.latest_version(library)
|
2022-09-13 11:36:28 +12:00
|
|
|
else
|
|
|
|
case Enum.find(library.versions, &(&1.id == selected_versions[library.id])) do
|
|
|
|
nil ->
|
|
|
|
nil
|
|
|
|
|
|
|
|
version ->
|
|
|
|
version
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if is_nil(version) do
|
2022-10-31 13:58:34 +13:00
|
|
|
raise "no version for library: #{library.name}"
|
2022-09-13 11:36:28 +12:00
|
|
|
else
|
|
|
|
case type do
|
|
|
|
"guide" ->
|
|
|
|
guide =
|
|
|
|
Enum.find(version.guides, &(&1.name == item)) ||
|
|
|
|
raise "No such guide in link: #{source}"
|
|
|
|
|
|
|
|
text = Enum.at(rest, 0) || item
|
|
|
|
|
|
|
|
"""
|
|
|
|
<a href="#{DocRoutes.doc_link(guide, selected_versions)}">#{text}</a>
|
|
|
|
"""
|
|
|
|
|
|
|
|
"dsl" ->
|
|
|
|
path =
|
|
|
|
item
|
2022-11-01 03:34:24 +13:00
|
|
|
|> String.trim_leading("/")
|
2022-09-13 11:36:28 +12:00
|
|
|
|> String.split(~r/[\/\.]/)
|
|
|
|
|
|
|
|
name =
|
|
|
|
path
|
|
|
|
|> Enum.join(".")
|
|
|
|
|
|
|
|
route = Enum.map_join(path, "/", &DocRoutes.sanitize_name/1)
|
|
|
|
|
|
|
|
"""
|
|
|
|
<a href="/docs/dsl/#{library.name}/#{version.version}/#{route}">#{name}</a>
|
|
|
|
"""
|
|
|
|
|
|
|
|
"option" ->
|
|
|
|
path =
|
|
|
|
item
|
2022-11-01 03:34:24 +13:00
|
|
|
|> String.trim_leading("/")
|
2022-09-13 11:36:28 +12:00
|
|
|
|> String.split(~r/[\/\.]/)
|
|
|
|
|
|
|
|
name = Enum.join(path, ".")
|
|
|
|
|
|
|
|
dsl_path = path |> :lists.droplast() |> Enum.map_join("/", &DocRoutes.sanitize_name/1)
|
2022-11-01 03:47:53 +13:00
|
|
|
anchor = dsl_path |> List.last() |> (DocRoutes.sanitize_name() / 1)
|
2022-09-13 11:36:28 +12:00
|
|
|
|
|
|
|
"""
|
|
|
|
<a href="/docs/dsl/#{library.name}/#{version.version}/#{dsl_path}##{anchor}">#{name}</a>
|
|
|
|
"""
|
|
|
|
|
|
|
|
"module" ->
|
|
|
|
"""
|
|
|
|
<a href="/docs/module/#{library.name}/#{version.version}/#{DocRoutes.sanitize_name(item)}">#{item}</a>
|
|
|
|
"""
|
|
|
|
|
|
|
|
"extension" ->
|
|
|
|
"""
|
|
|
|
<a href="/docs/dsl/#{library.name}/#{version.version}/#{DocRoutes.sanitize_name(item)}">#{item}</a>
|
|
|
|
"""
|
|
|
|
|
|
|
|
type ->
|
|
|
|
raise "unimplemented link type #{inspect(type)} in #{source}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-07-28 07:57:39 +12:00
|
|
|
end
|