Class: MissionControl::Jobs::Theme::Middleware
- Inherits:
-
Object
- Object
- MissionControl::Jobs::Theme::Middleware
- Defined in:
- lib/mission_control/jobs/theme/middleware.rb
Overview
Intercept HTML responses from the Mission Control Jobs engine and inject theme CSS and optional Prism.js syntax highlighting before </head>.
Only rewrites responses that match the engine mount path and have an text/html content type.
The color scheme is resolved per-request: a mc_jobs_color_scheme cookie (set by the client-side color scheme switcher) takes precedence over the configured default. When the effective scheme is :auto, both light and dark stylesheets are injected with prefers-color-scheme media queries. When an explicit scheme is active, only that variant’s CSS is loaded.
Injected <script> tags automatically receive a CSP nonce when one is available via action_dispatch.content_security_policy_nonce in the Rack env or a <meta name=“csp-nonce”> tag in the response body.
Constant Summary collapse
- NONCE_PLACEHOLDER =
"THEME_NONCE"- NONCE_ATTR =
" nonce=\"#{NONCE_PLACEHOLDER}\"".freeze
Instance Method Summary collapse
-
#call(env) ⇒ Array(Integer, Hash, #each)
Process a Rack request, injecting theme assets into matching HTML responses.
-
#initialize(app, mount_path: RouteDiscovery::FALLBACK, config: Configuration.new) ⇒ Middleware
constructor
A new instance of Middleware.
Constructor Details
#initialize(app, mount_path: RouteDiscovery::FALLBACK, config: Configuration.new) ⇒ Middleware
Returns a new instance of Middleware.
41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/mission_control/jobs/theme/middleware.rb', line 41 def initialize(app, mount_path: RouteDiscovery::FALLBACK, config: Configuration.new) @app = app @mount_path = mount_path @mount_path_prefix = "#{mount_path}/" @theme = config.theme @default_color_scheme = config.color_scheme @syntax_highlighting = config.syntax_highlighting @color_scheme_switcher = config.color_scheme_switcher @injections = (Configuration::COLOR_SCHEMES + [:auto]).to_h { |scheme| [scheme, build_injection(scheme)] } end |
Instance Method Details
#call(env) ⇒ Array(Integer, Hash, #each)
Process a Rack request, injecting theme assets into matching HTML responses.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/mission_control/jobs/theme/middleware.rb', line 57 def call(env) status, headers, response = @app.call(env) if inject_theme?(env, status, headers) body = +"" response.each { |part| body << part } response.close if response.respond_to?(:close) scheme = resolve_color_scheme(env) nonce = resolve_csp_nonce(env, body) injection = @injections[scheme].gsub(nonce ? NONCE_PLACEHOLDER : NONCE_ATTR, nonce || "") body.sub!("</head>", injection) headers["content-length"] = body.bytesize.to_s if headers.key?("content-length") [status, headers, [body]] else [status, headers, response] end end |