Class: DocsUI::Code

Inherits:
Phlex::HTML
  • Object
show all
Includes:
Phlex::Rails::Helpers::ContentSecurityPolicyNonce
Defined in:
app/components/docs_ui/code.rb

Overview

A syntax-highlighted code block for docs and demo panels. Rouge does the highlighting; an optional filename/label sits in a title bar like a real docs code sample. Self-contained: it injects its own Rouge theme CSS so no separate stylesheet asset is required.

render DocsUI::Code.new(ruby_source)                          # ruby, no title
render DocsUI::Code.new(py, lexer: :python, filename: "a.py")  # any language

Any language Rouge knows (~200 lexers) works by its name or alias — python, go, rust, elixir, kotlin, swift, json, dockerfile, ... — no allowlist. Add friendly lexer aliases via DocsKit.configure (code_lexer_aliases). An unknown language falls back to plaintext (never raises). (Tab labels are a DocsUI::Example concern — set via code_language_labels, not here; Code has no label, only a filename.)

Constant Summary collapse

FORMATTER =
Rouge::Formatters::HTML.new

Instance Method Summary collapse

Constructor Details

#initialize(source, lexer: :ruby, filename: nil) ⇒ Code

Returns a new instance of Code.



25
26
27
28
29
# File 'app/components/docs_ui/code.rb', line 25

def initialize(source, lexer: :ruby, filename: nil)
  @source = source.to_s.strip
  @lexer = lexer
  @filename = filename
end

Instance Method Details

#view_templateObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/components/docs_ui/code.rb', line 31

def view_template
  # Nonce the inline theme CSS so it survives a nonce-based style-src. Off a
  # request there is no nonce (see #csp_nonce) and Phlex omits a nil-valued
  # attribute, so the no-nonce markup is unchanged.
  style(nonce: csp_nonce) { highlight_css }
  resolved = lexer
  div(class: "not-prose my-4 overflow-hidden rounded-box border border-base-300 bg-base-300/40") do
    title_bar if @filename
    # data-md-lang carries the RESOLVED Rouge tag (ruby/python/plaintext/…) so
    # DocsKit::MarkdownExport emits a ```lang fence without re-resolving the
    # language. It's the real lexer tag, not the requested alias.
    div(class: "code-highlight overflow-x-auto p-4 text-sm leading-relaxed", data: { md_lang: resolved.tag }) do
      pre { raw(safe(FORMATTER.format(resolved.lex(@source)))) }
    end
  end
end