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 200 responses with a 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.
Asset URLs are resolved through the Rails asset pipeline (Propshaft), so injected <link> and <script> tags use fingerprinted, cache-friendly paths that respect config.relative_url_root.
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.
Instance Method Summary collapse
-
#call(env) ⇒ Array(Integer, Hash, #each)
Rack-compatible response triplet.
-
#initialize(app, config:) ⇒ Middleware
constructor
A new instance of Middleware.
Constructor Details
#initialize(app, config:) ⇒ Middleware
Returns a new instance of Middleware.
31 32 33 34 35 36 37 |
# File 'lib/mission_control/jobs/theme/middleware.rb', line 31 def initialize(app, config:) @app = app @theme = config.theme @default_color_scheme = config.color_scheme @syntax_highlighting = config.syntax_highlighting @color_scheme_switcher = config.color_scheme_switcher end |
Instance Method Details
#call(env) ⇒ Array(Integer, Hash, #each)
Returns Rack-compatible response triplet.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/mission_control/jobs/theme/middleware.rb', line 41 def call(env) status, headers, response = @app.call(env) if inject_theme?(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 = build_injection(scheme, 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 |