5.7 KiB
Arcology Link Routers
- Shared Functions in the
Arcology.KeyMaps
module map in to and out of "site keys" and domains. - "local" router
Routing differs between local development and production deployment, and may diverge further in the future. Consider this page, with the ARCOLOGY_KEY
value arcology/links
. In each environment this value should map one-to-one with a URL. In local development, the domain will be localhost
and the path will be /arcology/links
. In production, the domain will be (probably) arcology.garden
and the path will be /links
, and I will have multiple domains in the same Garden "namespace", a single org-roam directory.
The router has to perform these tasks:
- rewrite an HTML url from the org-mode file to the
ARCOLOGY_KEY
. add_site_colors
andurl_for_arcology_key
in Arcology.Sitemap- domain_to_site and build_site_key in ArcologyWeb.Router
Some of these are actually going to be the same in both environments, but it seems really smart to have all the mapping between Sites be in one module in another file is the right idea. Handful of modules. Base, Prod, Dev, swapped in based on the Config? it's actually probably just stuff in config yikes.
Shared Functions in the Arcology.KeyMaps
module map in to and out of "site keys" and domains.
It contains code that's used in other places but is related to domain-to-site mapping. Eventually sites could be an implementation of a struct which implements a protocol that these functions call against. I'm going to need to do a bunch of stuff in the Arcology configuration for this to work in production, anyways…
defmodule Arcology.KeyMaps do
def domain_to_site_map do
%{
"arcology.garden" => %{site: "garden"},
"lionsrear.com" => %{site: "lionsrear"},
"cce.arcology.garden" => %{site: "cce"},
"doc.arcology.garden" => %{site: "doc"},
"localhost" => %{site: "local", local_wiki: true},
}
end
def site_colors_map do
%{
"cce" => "#707231",
"arcology" => "#82796C",
"lionsrear" => "#7e5c41",
"garden" => "#CC6960",
"doc" => "#67b4f8",
}
end
def domain_to_site(host), do: Map.get(domain_to_site_map(), host, %{site: "unknown"})
def site_key_to_color(site_key), do: Map.get(site_colors_map(), site_key, "#FFFFFF")
end
"local" router
The local router allows for routing under a single domain, probably localhost
for development purposes. This router lets you pass as the URL path an ARCOLOGY_KEY
value, and needs to generate HTML links that work the same way.
defmodule Arcology.LinkRouter.Local do
require Logger
<<normalize_urls>>
def url_for_arcology_key(key) do
"/#{key}.html"
end
end
Normalizing HTML URLs
The arcology should route all internal URLs, rewriting any which are not exposed via ARCOLOGY_KEY
to the 404 page. the URLs which are roam:
prefixed are dangling links in my Knowledge Base, they otherwise would be rewritten to a real page and those are turned in to a broken link. I'd like to include some statistics for these at some point so I can have some awareness of the pages people are interested in, but that's not important right now.
@doc "Rewrite the HTML anchors in the passed binary from org links to local-routing HTML links"
def normalize_urls(input_html) when is_binary(input_html) do
intermediate = Regex.replace(
~r/<a href="([0-9a-zA-Z_\- \/]+.org)">/,
input_html,
&normalize_org_url(&1, &2)
)
Regex.replace(
~r/<a href="(roam:[0-9a-zA-Z_\- \/,.!?]+)">roam:/,
intermediate,
&normalize_roam_url(&1, &2)
)
end
defp normalize_roam_url(_match, page) do
~s(<a href="/arcology/404.html" class="dead-link">)
end
defp normalize_org_url(_match, page) do
# arc_dir = Application.get_env(:arcology, :env)[:arcology_directory]
key = Arcology.Roam.Keyword.from_file(page|>IO.inspect, "ARCOLOGY_KEY")
cond do
key == nil ->
Logger.warn("could not load key for #{page}")
~s(<a href="/arcology/404.html" class="dead-link">)
true ->
~s(<a href="/#{key}.html">)
end
end
@doc "This is for tests, ignore the man behind the curtain"
def test_normalize(page), do: normalize_org_url(nil, page)
normalize_url/2
is called by the Regex.replace
in normalize_urls/1
, the second argument is all we care about, it comes out of the capture in the expression, and is the string of the relative file-name in all likelihood; this is not really consistent and it is something that I need to resolve in my org-roam and org-mode configurations. This is going to have a lot of data-validity issues, and I kind-of wish that it was easier to quickly get an Arcology.Roam.Link from this page
variable to get to a Arcology.Roam.Keyword.
defmodule ArcologyPageTestRewriteLocal do
use ExUnit.Case
setup do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(Arcology.Repo)
end
test 'valid link with valid key' do
assert Arcology.LinkRouter.Local.test_normalize("arcology_page.org") == ~s(<a href="/arcology/page.html">)
assert Arcology.LinkRouter.Local.test_normalize("link_routers.org") == ~s(<a href="/arcology/links.html">)
end
test 'URLs not in the arcology-db get a dead-link class' do
assert Arcology.LinkRouter.Local.test_normalize("Private.org") =~ "dead-link"
end
end