feat: claims for having the js parts in (not working, though)
This commit is contained in:
@@ -6,6 +6,7 @@ defmodule BDS.Generation do
|
||||
alias BDS.Generation.GeneratedFileHash
|
||||
alias BDS.Metadata
|
||||
alias BDS.Persistence
|
||||
alias BDS.PreviewAssets
|
||||
alias BDS.Posts.Post
|
||||
alias BDS.Posts.Translation
|
||||
alias BDS.Projects
|
||||
@@ -272,7 +273,14 @@ defmodule BDS.Generation do
|
||||
[]
|
||||
end
|
||||
|
||||
core_outputs ++ single_outputs ++ archive_outputs ++ sitemap ++ pagefind_outputs
|
||||
asset_outputs =
|
||||
if :core in plan.sections do
|
||||
PreviewAssets.generated_outputs()
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
core_outputs ++ single_outputs ++ archive_outputs ++ sitemap ++ pagefind_outputs ++ asset_outputs
|
||||
end
|
||||
|
||||
defp disk_generated_files(project_id) do
|
||||
|
||||
@@ -466,28 +466,39 @@ defmodule BDS.Preview do
|
||||
end
|
||||
|
||||
defp apply_preview_overrides(body, query_params) when is_binary(body) and is_map(query_params) do
|
||||
theme_override = normalize_pico_theme_override(query_params["theme"])
|
||||
mode_override = normalize_mode_override(query_params["mode"])
|
||||
|
||||
body
|
||||
|> override_pico_stylesheet_href(normalize_override(query_params["theme"]))
|
||||
|> override_html_attribute("data-theme", normalize_override(query_params["theme"]))
|
||||
|> override_html_attribute("data-mode", normalize_override(query_params["mode"]))
|
||||
|> override_pico_stylesheet_href(theme_override)
|
||||
|> override_html_attribute("data-theme", mode_override)
|
||||
|> override_html_attribute("data-mode", mode_override)
|
||||
end
|
||||
|
||||
defp override_pico_stylesheet_href(body, nil), do: body
|
||||
|
||||
defp override_pico_stylesheet_href(body, theme) do
|
||||
replacement =
|
||||
case theme do
|
||||
"default" -> "/assets/pico.min.css"
|
||||
value -> "/assets/pico.#{value}.min.css"
|
||||
end
|
||||
|
||||
Regex.replace(~r{/assets/pico(?:\.[a-z]+)?\.min\.css}, body, replacement, global: false)
|
||||
Regex.replace(
|
||||
~r{/assets/pico(?:\.[a-z]+)?\.min\.css},
|
||||
body,
|
||||
PreviewAssets.stylesheet_href(theme),
|
||||
global: false
|
||||
)
|
||||
end
|
||||
|
||||
defp normalize_override(nil), do: nil
|
||||
defp normalize_override(""), do: nil
|
||||
defp normalize_override(value), do: String.trim(value)
|
||||
|
||||
defp normalize_pico_theme_override(value), do: normalize_override(value)
|
||||
|
||||
defp normalize_mode_override(value) do
|
||||
case normalize_override(value) do
|
||||
mode when mode in ["dark", "light"] -> mode
|
||||
_other -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp override_html_attribute(body, _attribute, nil), do: body
|
||||
|
||||
defp override_html_attribute(body, attribute, value) do
|
||||
@@ -509,8 +520,7 @@ defmodule BDS.Preview do
|
||||
|
||||
defp not_found_assigns(query_params) do
|
||||
%{}
|
||||
|> maybe_put_assign("html_theme_attribute", query_params["theme"], fn value -> ~s(data-theme="#{value}") end)
|
||||
|> maybe_put_assign("html_mode_attribute", query_params["mode"], fn value -> ~s(data-mode="#{value}") end)
|
||||
|> maybe_put_assign("pico_stylesheet_href", normalize_pico_theme_override(query_params["theme"]), &PreviewAssets.stylesheet_href/1)
|
||||
end
|
||||
|
||||
defp maybe_put_assign(assigns, _key, nil, _mapper), do: assigns
|
||||
|
||||
@@ -1,335 +1,70 @@
|
||||
defmodule BDS.PreviewAssets do
|
||||
@moduledoc false
|
||||
|
||||
@theme_tokens %{
|
||||
"amber" => %{light_primary: "#876400", dark_primary: "#c79400"},
|
||||
"blue" => %{light_primary: "#2060df", dark_primary: "#8999f9"},
|
||||
"cyan" => %{light_primary: "#047878", dark_primary: "#0ab1b1"},
|
||||
"fuchsia" => %{light_primary: "#c1208b", dark_primary: "#f869bf"},
|
||||
"green" => %{light_primary: "#33790f", dark_primary: "#4eb31b"},
|
||||
"grey" => %{light_primary: "#6a6a6a", dark_primary: "#9e9e9e"},
|
||||
"indigo" => %{light_primary: "#655cd6", dark_primary: "#a294e5"},
|
||||
"jade" => %{light_primary: "#007a50", dark_primary: "#00b478"},
|
||||
"lime" => %{light_primary: "#577400", dark_primary: "#82ab00"},
|
||||
"orange" => %{light_primary: "#bd3c13", dark_primary: "#f56b3d"},
|
||||
"pink" => %{light_primary: "#c72259", dark_primary: "#f7708e"},
|
||||
"pumpkin" => %{light_primary: "#9c5900", dark_primary: "#e48500"},
|
||||
"purple" => %{light_primary: "#aa40bf", dark_primary: "#d47de4"},
|
||||
"red" => %{light_primary: "#c52f21", dark_primary: "#f17961"},
|
||||
"sand" => %{light_primary: "#6e6a60", dark_primary: "#a39e8f"},
|
||||
"slate" => %{light_primary: "#5d6b89", dark_primary: "#909ebe"},
|
||||
"violet" => %{light_primary: "#8352c5", dark_primary: "#b290d9"},
|
||||
"yellow" => %{light_primary: "#756b00", dark_primary: "#ad9f00"},
|
||||
"zinc" => %{light_primary: "#646b79", dark_primary: "#969eaf"}
|
||||
}
|
||||
|
||||
@highlight_stylesheet """
|
||||
.hljs { color: #e6edf3; background: transparent; display: block; overflow-x: auto; }
|
||||
.hljs-keyword, .hljs-selector-tag, .hljs-literal { color: #ff7b72; }
|
||||
.hljs-string, .hljs-attr { color: #a5d6ff; }
|
||||
.hljs-number, .hljs-title, .hljs-section { color: #f2cc60; }
|
||||
.hljs-comment, .hljs-quote { color: #8b949e; }
|
||||
.hljs-built_in, .hljs-type, .hljs-symbol { color: #7ee787; }
|
||||
"""
|
||||
|
||||
@highlight_script "window.hljs = window.hljs || { highlightElement: function () {} };"
|
||||
|
||||
@lightbox_script "window.lightbox = window.lightbox || { option: function () {}, init: function () {} };"
|
||||
|
||||
@calendar_stylesheet """
|
||||
[data-blog-calendar-root] { min-height: 12rem; }
|
||||
[data-blog-calendar-root] button { font: inherit; }
|
||||
"""
|
||||
|
||||
@calendar_script """
|
||||
(function () {
|
||||
function Calendar() {}
|
||||
Calendar.prototype.init = function () {};
|
||||
window.VanillaCalendar = window.VanillaCalendar || Calendar;
|
||||
window.VanillaCalendarPro = window.VanillaCalendarPro || Calendar;
|
||||
})();
|
||||
"""
|
||||
|
||||
@calendar_runtime """
|
||||
(function () {
|
||||
function toggle(panel, hidden) {
|
||||
if (!panel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hidden) {
|
||||
panel.setAttribute('hidden', 'hidden');
|
||||
} else {
|
||||
panel.removeAttribute('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
var toggleButton = document.querySelector('[data-blog-calendar-toggle]');
|
||||
var closeButton = document.querySelector('[data-blog-calendar-close]');
|
||||
var panel = document.querySelector('[data-blog-calendar-panel]');
|
||||
var status = document.querySelector('[data-blog-calendar-status]');
|
||||
|
||||
if (!toggleButton || !panel) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleButton.addEventListener('click', function () {
|
||||
var isHidden = panel.hasAttribute('hidden');
|
||||
toggle(panel, !isHidden);
|
||||
if (status && !status.dataset.previewReady) {
|
||||
status.textContent = 'Preview calendar is unavailable in draft mode.';
|
||||
status.dataset.previewReady = 'true';
|
||||
}
|
||||
});
|
||||
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener('click', function () {
|
||||
toggle(panel, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init, { once: true });
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
"""
|
||||
|
||||
@search_runtime """
|
||||
(function () {
|
||||
function setHidden(panel, hidden) {
|
||||
if (!panel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hidden) {
|
||||
panel.setAttribute('hidden', 'hidden');
|
||||
} else {
|
||||
panel.removeAttribute('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
var toggle = document.querySelector('[data-blog-search-toggle]');
|
||||
var panel = document.querySelector('[data-blog-search-panel]');
|
||||
if (!toggle || !panel) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggle.addEventListener('click', function () {
|
||||
setHidden(panel, !panel.hasAttribute('hidden'));
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
if (panel.hasAttribute('hidden')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (panel.contains(event.target) || toggle.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setHidden(panel, true);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init, { once: true });
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
"""
|
||||
|
||||
@tag_cloud_runtime """
|
||||
(function () {
|
||||
function init() {}
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init, { once: true });
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
"""
|
||||
|
||||
@d3_cloud_script """
|
||||
(function () {
|
||||
var layout = {
|
||||
size: function () { return layout; },
|
||||
words: function () { return layout; },
|
||||
padding: function () { return layout; },
|
||||
rotate: function () { return layout; },
|
||||
font: function () { return layout; },
|
||||
fontSize: function () { return layout; },
|
||||
on: function () { return layout; },
|
||||
start: function () { return layout; }
|
||||
};
|
||||
|
||||
window.d3 = window.d3 || {};
|
||||
window.d3.layout = window.d3.layout || {};
|
||||
window.d3.layout.cloud = function () { return layout; };
|
||||
})();
|
||||
"""
|
||||
@preview_root Application.app_dir(:bds, "priv/preview_assets")
|
||||
|
||||
def response(pathname) when is_binary(pathname) do
|
||||
case Regex.run(~r{^/assets/([^/]+)$}, pathname) do
|
||||
[_, asset_name] -> build_asset_response(asset_name)
|
||||
_other -> :error
|
||||
pathname
|
||||
|> request_path()
|
||||
|> case do
|
||||
{:ok, relative_path} ->
|
||||
case File.read(Path.join(@preview_root, relative_path)) do
|
||||
{:ok, body} -> {:ok, %{content_type: content_type(relative_path), body: body}}
|
||||
{:error, _reason} -> :error
|
||||
end
|
||||
|
||||
:error ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
defp build_asset_response(asset_name) do
|
||||
case asset_payload(asset_name) do
|
||||
{:ok, content_type, body} -> {:ok, %{content_type: content_type, body: body}}
|
||||
:error -> :error
|
||||
def generated_outputs do
|
||||
["assets", "images"]
|
||||
|> Enum.flat_map(fn directory ->
|
||||
@preview_root
|
||||
|> Path.join(directory)
|
||||
|> Path.join("**/*")
|
||||
|> Path.wildcard(match_dot: false)
|
||||
end)
|
||||
|> Enum.filter(&File.regular?/1)
|
||||
|> Enum.sort()
|
||||
|> Enum.map(fn path ->
|
||||
{Path.relative_to(path, @preview_root), File.read!(path)}
|
||||
end)
|
||||
end
|
||||
|
||||
def stylesheet_href(nil), do: "/assets/pico.min.css"
|
||||
def stylesheet_href(""), do: "/assets/pico.min.css"
|
||||
def stylesheet_href("default"), do: "/assets/pico.min.css"
|
||||
def stylesheet_href(theme), do: "/assets/pico.#{theme}.min.css"
|
||||
|
||||
defp request_path(pathname) do
|
||||
normalized = pathname |> URI.parse() |> Map.get(:path, pathname)
|
||||
|
||||
case String.split(normalized, "/", trim: true) do
|
||||
[directory, filename] when directory in ["assets", "images"] ->
|
||||
relative_path = Path.join(directory, filename)
|
||||
|
||||
if File.regular?(Path.join(@preview_root, relative_path)) do
|
||||
{:ok, relative_path}
|
||||
else
|
||||
:error
|
||||
end
|
||||
|
||||
_other ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
defp asset_payload(asset_name) do
|
||||
case Regex.run(~r/^pico(?:\.([a-z]+))?\.min\.css$/, asset_name) do
|
||||
[_, theme] -> {:ok, "text/css", pico_stylesheet(theme)}
|
||||
[single] when single == asset_name -> {:ok, "text/css", pico_stylesheet(nil)}
|
||||
_other -> named_asset_payload(asset_name)
|
||||
defp content_type(path) do
|
||||
case Path.extname(path) do
|
||||
".css" -> "text/css"
|
||||
".js" -> "application/javascript"
|
||||
".png" -> "image/png"
|
||||
".gif" -> "image/gif"
|
||||
".jpg" -> "image/jpeg"
|
||||
".jpeg" -> "image/jpeg"
|
||||
_other -> "application/octet-stream"
|
||||
end
|
||||
end
|
||||
|
||||
defp named_asset_payload("bds.css"), do: file_asset("bds.css", "text/css")
|
||||
defp named_asset_payload("code-enhancements.js"), do: file_asset("code-enhancements.js", "application/javascript")
|
||||
defp named_asset_payload("highlight.min.css"), do: {:ok, "text/css", @highlight_stylesheet}
|
||||
defp named_asset_payload("highlight.min.js"), do: {:ok, "application/javascript", @highlight_script}
|
||||
defp named_asset_payload("lightbox.min.css"), do: {:ok, "text/css", ""}
|
||||
defp named_asset_payload("lightbox.min.js"), do: {:ok, "application/javascript", @lightbox_script}
|
||||
defp named_asset_payload("vanilla-calendar.min.css"), do: {:ok, "text/css", @calendar_stylesheet}
|
||||
defp named_asset_payload("vanilla-calendar.min.js"), do: {:ok, "application/javascript", @calendar_script}
|
||||
defp named_asset_payload("calendar-runtime.js"), do: {:ok, "application/javascript", @calendar_runtime}
|
||||
defp named_asset_payload("search-runtime.js"), do: {:ok, "application/javascript", @search_runtime}
|
||||
defp named_asset_payload("tag-cloud.js"), do: {:ok, "application/javascript", @tag_cloud_runtime}
|
||||
defp named_asset_payload("d3.layout.cloud.js"), do: {:ok, "application/javascript", @d3_cloud_script}
|
||||
defp named_asset_payload(_asset_name), do: :error
|
||||
|
||||
defp file_asset(filename, content_type) do
|
||||
case File.read(asset_path(filename)) do
|
||||
{:ok, body} -> {:ok, content_type, body}
|
||||
{:error, _reason} -> :error
|
||||
end
|
||||
end
|
||||
|
||||
defp asset_path(filename) do
|
||||
Application.app_dir(:bds, "priv/preview_assets/#{filename}")
|
||||
end
|
||||
|
||||
defp pico_stylesheet(theme) do
|
||||
tokens = Map.get(@theme_tokens, theme || "", %{light_primary: "#2060df", dark_primary: "#8999f9"})
|
||||
|
||||
"""
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--pico-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;
|
||||
--pico-line-height: 1.6;
|
||||
--pico-border-radius: 0.35rem;
|
||||
--pico-background-color: #ffffff;
|
||||
--pico-color: #1f2937;
|
||||
--pico-muted-color: #5d6b89;
|
||||
--pico-muted-border-color: #d6dde8;
|
||||
--pico-card-background-color: #f7f9fc;
|
||||
--pico-primary: #{tokens.light_primary};
|
||||
--pico-primary-hover: #{tokens.light_primary};
|
||||
--pico-primary-focus: rgba(32, 96, 223, 0.16);
|
||||
--pico-primary-inverse: #ffffff;
|
||||
--pico-code-background-color: #1f2937;
|
||||
--pico-code-color: #e6edf3;
|
||||
--pico-ins-color: #2f7a38;
|
||||
--pico-del-color: #b74848;
|
||||
--pico-form-element-background-color: #ffffff;
|
||||
--pico-form-element-border-color: #c7d0dd;
|
||||
--pico-form-element-color: #1f2937;
|
||||
}
|
||||
|
||||
:root[data-mode='light'] {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
:root[data-mode='dark'] {
|
||||
color-scheme: dark;
|
||||
--pico-background-color: #13171f;
|
||||
--pico-color: #e6edf3;
|
||||
--pico-muted-color: #909ebe;
|
||||
--pico-muted-border-color: #2d3645;
|
||||
--pico-card-background-color: #1b2230;
|
||||
--pico-primary: #{tokens.dark_primary};
|
||||
--pico-primary-hover: #{tokens.dark_primary};
|
||||
--pico-primary-focus: rgba(137, 153, 249, 0.18);
|
||||
--pico-code-background-color: #0f1520;
|
||||
--pico-form-element-background-color: #13171f;
|
||||
--pico-form-element-border-color: #364153;
|
||||
--pico-form-element-color: #e6edf3;
|
||||
}
|
||||
|
||||
@media only screen and (prefers-color-scheme: dark) {
|
||||
:root:not([data-mode='light']) {
|
||||
color-scheme: dark;
|
||||
--pico-background-color: #13171f;
|
||||
--pico-color: #e6edf3;
|
||||
--pico-muted-color: #909ebe;
|
||||
--pico-muted-border-color: #2d3645;
|
||||
--pico-card-background-color: #1b2230;
|
||||
--pico-primary: #{tokens.dark_primary};
|
||||
--pico-primary-hover: #{tokens.dark_primary};
|
||||
--pico-primary-focus: rgba(137, 153, 249, 0.18);
|
||||
--pico-code-background-color: #0f1520;
|
||||
--pico-form-element-background-color: #13171f;
|
||||
--pico-form-element-border-color: #364153;
|
||||
--pico-form-element-color: #e6edf3;
|
||||
}
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html { font-family: var(--pico-font-family); background: var(--pico-background-color); color: var(--pico-color); }
|
||||
body { margin: 0; font-family: inherit; background: var(--pico-background-color); color: var(--pico-color); line-height: var(--pico-line-height); }
|
||||
h1, h2, h3, h4, h5, h6 { color: inherit; line-height: 1.2; margin: 0 0 0.75rem; }
|
||||
p, ul, ol, pre, table, blockquote { margin: 0 0 1rem; }
|
||||
a { color: var(--pico-primary); }
|
||||
a:hover, a:focus-visible { color: var(--pico-primary-hover); }
|
||||
button, [role='button'], input, textarea, select {
|
||||
font: inherit;
|
||||
}
|
||||
button, [role='button'] {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.35rem;
|
||||
border: 1px solid var(--pico-form-element-border-color);
|
||||
border-radius: var(--pico-border-radius);
|
||||
background: var(--pico-card-background-color);
|
||||
color: var(--pico-color);
|
||||
padding: 0.45rem 0.8rem;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
input, textarea, select {
|
||||
width: 100%;
|
||||
border: 1px solid var(--pico-form-element-border-color);
|
||||
border-radius: var(--pico-border-radius);
|
||||
padding: 0.55rem 0.7rem;
|
||||
background: var(--pico-form-element-background-color);
|
||||
color: var(--pico-form-element-color);
|
||||
}
|
||||
code, pre, kbd {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
}
|
||||
img { max-width: 100%; height: auto; }
|
||||
hr { border: 0; border-top: 1px solid var(--pico-muted-border-color); }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th, td { padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--pico-muted-border-color); text-align: left; }
|
||||
blockquote {
|
||||
margin-left: 0;
|
||||
padding-left: 1rem;
|
||||
border-left: 4px solid var(--pico-muted-border-color);
|
||||
color: var(--pico-muted-color);
|
||||
}
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule BDS.Rendering do
|
||||
alias BDS.Media.Media, as: MediaAsset
|
||||
alias BDS.Menu
|
||||
alias BDS.Metadata
|
||||
alias BDS.PreviewAssets
|
||||
alias BDS.PostLinks
|
||||
alias BDS.Projects
|
||||
alias BDS.I18n
|
||||
@@ -182,7 +183,7 @@ defmodule BDS.Rendering do
|
||||
Map.get(
|
||||
assigns,
|
||||
:html_theme_attribute,
|
||||
Map.get(assigns, "html_theme_attribute", html_theme_attribute(metadata.pico_theme))
|
||||
Map.get(assigns, "html_theme_attribute")
|
||||
),
|
||||
blog_languages: blog_languages(metadata, language),
|
||||
alternate_links: alternate_links(canonical_post, project_id, main_language),
|
||||
@@ -240,7 +241,7 @@ defmodule BDS.Rendering do
|
||||
Map.get(
|
||||
assigns,
|
||||
:html_theme_attribute,
|
||||
Map.get(assigns, "html_theme_attribute", html_theme_attribute(metadata.pico_theme))
|
||||
Map.get(assigns, "html_theme_attribute")
|
||||
),
|
||||
blog_languages: blog_languages(metadata, language),
|
||||
alternate_links: [],
|
||||
@@ -297,7 +298,7 @@ defmodule BDS.Rendering do
|
||||
Map.get(
|
||||
assigns,
|
||||
:html_theme_attribute,
|
||||
Map.get(assigns, "html_theme_attribute", html_theme_attribute(metadata.pico_theme))
|
||||
Map.get(assigns, "html_theme_attribute")
|
||||
),
|
||||
blog_languages: blog_languages(metadata, language),
|
||||
menu_items: menu_items(project_id),
|
||||
@@ -723,15 +724,7 @@ defmodule BDS.Rendering do
|
||||
defp show_archive_range_heading?(%{kind: "date"}, _day_blocks), do: true
|
||||
defp show_archive_range_heading?(_archive_context, _day_blocks), do: false
|
||||
|
||||
defp html_theme_attribute(nil), do: nil
|
||||
defp html_theme_attribute(""), do: nil
|
||||
defp html_theme_attribute("default"), do: nil
|
||||
defp html_theme_attribute(theme), do: ~s(data-theme="#{theme}")
|
||||
|
||||
defp default_pico_stylesheet_href(nil), do: "/assets/pico.min.css"
|
||||
defp default_pico_stylesheet_href(""), do: "/assets/pico.min.css"
|
||||
defp default_pico_stylesheet_href("default"), do: "/assets/pico.min.css"
|
||||
defp default_pico_stylesheet_href(theme), do: "/assets/pico.#{theme}.min.css"
|
||||
defp default_pico_stylesheet_href(theme), do: PreviewAssets.stylesheet_href(theme)
|
||||
|
||||
defp href_for_language(""), do: "/"
|
||||
defp href_for_language(prefix), do: prefix <> "/"
|
||||
|
||||
Reference in New Issue
Block a user