From 63b96bb8e76d4bccd55968cd508f58c48d03a259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Sun, 9 Nov 2025 09:50:07 +0100 Subject: [PATCH] feat: add custom Pivoine Rose theme to asciinema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- asciinema/compose.yaml | 5 +++-- asciinema/custom.exs | 40 +++++++++++++++++++++++++++++++++++++++ asciinema/theme/custom.js | 17 +++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 asciinema/theme/custom.js diff --git a/asciinema/compose.yaml b/asciinema/compose.yaml index 9e49440..c7f87f0 100644 --- a/asciinema/compose.yaml +++ b/asciinema/compose.yaml @@ -8,8 +8,9 @@ services: volumes: - asciinema_data:/var/opt/asciinema - ./custom.exs:/opt/app/etc/custom.exs:ro - - ./theme:/opt/app/priv/static/theme:ro - - ./app.html.heex:/opt/app/lib/asciinema_web-*/eex/layout/app.html.heex:ro + - ./theme/custom.css:/opt/app/priv/static/css/custom.css: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: SECRET_KEY_BASE: ${ASCIINEMA_SECRET_KEY} URL_HOST: ${ASCIINEMA_TRAEFIK_HOST} diff --git a/asciinema/custom.exs b/asciinema/custom.exs index dd1b726..46a7ef5 100644 --- a/asciinema/custom.exs +++ b/asciinema/custom.exs @@ -15,3 +15,43 @@ config :asciinema, Asciinema.Emails.Mailer, verify: :verify_none, 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, "") do + script_tag = ~s(\n) + modified_body = String.replace(body, "", "#{script_tag}", 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] diff --git a/asciinema/theme/custom.js b/asciinema/theme/custom.js new file mode 100644 index 0000000..9a6a4b6 --- /dev/null +++ b/asciinema/theme/custom.js @@ -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'); +})();