feat: add custom Pivoine Rose theme to asciinema
- Mount custom CSS, favicon, and JS into static directories - Create custom.js to inject theme CSS and favicon via JavaScript - Add CustomThemeInjector Plug in custom.exs to inject script tag - Custom theme features: - Pivoine rose primary color (#CE275B) - Gray tone backgrounds - Custom SVG favicon with rose gradient - Bootstrap 4 component overrides 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- asciinema_data:/var/opt/asciinema
|
- asciinema_data:/var/opt/asciinema
|
||||||
- ./custom.exs:/opt/app/etc/custom.exs:ro
|
- ./custom.exs:/opt/app/etc/custom.exs:ro
|
||||||
- ./theme:/opt/app/priv/static/theme:ro
|
- ./theme/custom.css:/opt/app/priv/static/css/custom.css:ro
|
||||||
- ./app.html.heex:/opt/app/lib/asciinema_web-*/eex/layout/app.html.heex:ro
|
- ./theme/favicon.svg:/opt/app/priv/static/images/favicon-custom.svg:ro
|
||||||
|
- ./theme/custom.js:/opt/app/priv/static/js/custom.js:ro
|
||||||
environment:
|
environment:
|
||||||
SECRET_KEY_BASE: ${ASCIINEMA_SECRET_KEY}
|
SECRET_KEY_BASE: ${ASCIINEMA_SECRET_KEY}
|
||||||
URL_HOST: ${ASCIINEMA_TRAEFIK_HOST}
|
URL_HOST: ${ASCIINEMA_TRAEFIK_HOST}
|
||||||
|
|||||||
@@ -15,3 +15,43 @@ config :asciinema, Asciinema.Emails.Mailer,
|
|||||||
verify: :verify_none,
|
verify: :verify_none,
|
||||||
versions: [:"tlsv1.2", :"tlsv1.3"]
|
versions: [:"tlsv1.2", :"tlsv1.3"]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Custom Plug to inject theme JavaScript into HTML responses
|
||||||
|
defmodule CustomThemeInjector do
|
||||||
|
@behaviour Plug
|
||||||
|
|
||||||
|
def init(opts), do: opts
|
||||||
|
|
||||||
|
def call(conn, _opts) do
|
||||||
|
Plug.Conn.register_before_send(conn, fn conn ->
|
||||||
|
if html_response?(conn) do
|
||||||
|
inject_custom_script(conn)
|
||||||
|
else
|
||||||
|
conn
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp html_response?(conn) do
|
||||||
|
case Plug.Conn.get_resp_header(conn, "content-type") do
|
||||||
|
[content_type | _] -> String.contains?(content_type, "text/html")
|
||||||
|
[] -> false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp inject_custom_script(conn) do
|
||||||
|
{status, headers, body} = Plug.Conn.sent_resp(conn)
|
||||||
|
|
||||||
|
if is_binary(body) and String.contains?(body, "</head>") do
|
||||||
|
script_tag = ~s(<script src="/js/custom.js"></script>\n)
|
||||||
|
modified_body = String.replace(body, "</head>", "#{script_tag}</head>", global: false)
|
||||||
|
%{conn | status: status, resp_headers: headers, resp_body: modified_body}
|
||||||
|
else
|
||||||
|
conn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add the custom plug to the endpoint
|
||||||
|
config :asciinema, AsciinemaWeb.Endpoint,
|
||||||
|
http: [plug: CustomThemeInjector]
|
||||||
|
|||||||
17
asciinema/theme/custom.js
Normal file
17
asciinema/theme/custom.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Pivoine Rose Custom Theme Injector
|
||||||
|
(function() {
|
||||||
|
// Inject custom CSS
|
||||||
|
var customCSS = document.createElement('link');
|
||||||
|
customCSS.rel = 'stylesheet';
|
||||||
|
customCSS.href = '/css/custom.css';
|
||||||
|
document.head.appendChild(customCSS);
|
||||||
|
|
||||||
|
// Inject custom favicon
|
||||||
|
var customFavicon = document.createElement('link');
|
||||||
|
customFavicon.rel = 'icon';
|
||||||
|
customFavicon.type = 'image/svg+xml';
|
||||||
|
customFavicon.href = '/images/favicon-custom.svg';
|
||||||
|
document.head.appendChild(customFavicon);
|
||||||
|
|
||||||
|
console.log('Pivoine Rose theme loaded');
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user