Class: RailroadDiagrams::Theme

Inherits:
Struct
  • Object
show all
Defined in:
lib/railroad_diagrams/theme.rb,
sig/generated/railroad_diagrams/theme.rbs

Overview

A named color and typography palette for diagram output.

Examples:

Theme[:dark].css

Constant Summary collapse

DEFAULT_TOKENS =

Returns:

  • (Object)
{
  '--rr-bg' => 'white',
  '--rr-stroke' => '#333333',
  '--rr-stroke-width' => '3',
  '--rr-terminal-fill' => 'hsl(190, 100%, 83%)',
  '--rr-nonterminal-fill' => 'hsl(223, 100%, 83%)',
  '--rr-text' => '#333333',
  '--rr-font' => 'bold 14px monospace',
  '--rr-comment-font' => 'italic 12px monospace',
  '--rr-group-stroke' => 'gray',
  '--rr-track-stroke' => 'black',
  '--rr-track-fill' => 'rgba(0,0,0,0)',
  '--rr-rect-fill' => 'hsl(120,100%,90%)',
  '--rr-diagram-text-fill' => 'white',
  '--rr-hover-fill' => '#eee'
}.freeze
CLASSIC_TOKENS =

Returns:

  • (Object)
DEFAULT_TOKENS.merge(
  '--rr-bg' => 'hsl(30,20%,95%)',
  '--rr-stroke' => 'black',
  '--rr-terminal-fill' => 'hsl(120,100%,90%)',
  '--rr-nonterminal-fill' => 'hsl(120,100%,90%)',
  '--rr-text' => 'black'
).freeze
DARK_TOKENS =

Returns:

  • (Object)
DEFAULT_TOKENS.merge(
  '--rr-bg' => '#1e1e1e',
  '--rr-stroke' => '#d4d4d4',
  '--rr-terminal-fill' => 'hsl(190, 60%, 30%)',
  '--rr-nonterminal-fill' => 'hsl(223, 50%, 35%)',
  '--rr-text' => '#f0f0f0',
  '--rr-group-stroke' => '#888',
  '--rr-track-stroke' => '#d4d4d4',
  '--rr-rect-fill' => '#333333',
  '--rr-diagram-text-fill' => '#1e1e1e',
  '--rr-hover-fill' => '#444444'
).freeze
DEFAULT_TOKENS.merge(
  '--rr-stroke' => 'black',
  '--rr-terminal-fill' => 'none',
  '--rr-nonterminal-fill' => 'none',
  '--rr-text' => 'black',
  '--rr-group-stroke' => 'black',
  '--rr-rect-fill' => 'none',
  '--rr-diagram-text-fill' => 'white',
  '--rr-hover-fill' => 'white'
).freeze
HIGH_CONTRAST_TOKENS =

Returns:

  • (Object)
DARK_TOKENS.merge(
  '--rr-bg' => 'black',
  '--rr-stroke' => 'white',
  '--rr-stroke-width' => '4',
  '--rr-terminal-fill' => 'black',
  '--rr-nonterminal-fill' => 'black',
  '--rr-text' => 'white',
  '--rr-group-stroke' => 'white',
  '--rr-track-stroke' => 'white',
  '--rr-rect-fill' => 'black',
  '--rr-diagram-text-fill' => 'black',
  '--rr-hover-fill' => '#222222'
).freeze
THEMES =

Returns:

  • (Object)
{
  default: new(name: :default, tokens: DEFAULT_TOKENS).freeze,
  classic: new(name: :classic, tokens: CLASSIC_TOKENS).freeze,
  dark: new(name: :dark, tokens: DARK_TOKENS).freeze,
  auto: new(name: :auto, tokens: DEFAULT_TOKENS).freeze,
  print: new(name: :print, tokens: PRINT_TOKENS).freeze,
  high_contrast: new(name: :high_contrast, tokens: HIGH_CONTRAST_TOKENS).freeze
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#name ⇒ Object

Returns the value of attribute name

Returns:

  • (Object) —

    the current value of name



10
11
12
# File 'lib/railroad_diagrams/theme.rb', line 10

def name
  @name
end

#tokens ⇒ Object

Returns the value of attribute tokens

Returns:

  • (Object) —

    the current value of tokens



10
11
12
# File 'lib/railroad_diagrams/theme.rb', line 10

def tokens
  @tokens
end

Class Method Details

.[](name) ⇒ Object

Resolve one of the built-in themes by name.

Examples:

Theme[:print]

Parameters:

  • name (Object)

Returns:

  • (Object)


86
87
88
# File 'lib/railroad_diagrams/theme.rb', line 86

def self.[](name)
  THEMES.fetch(name.to_sym) { raise InvalidArgument, "unknown theme: #{name.inspect}" }
end

Instance Method Details

#css(css_variables: true) ⇒ Object

Parameters:

  • css_variables: (Object) (defaults to: true)

Returns:

  • (Object)


90
91
92
93
94
95
96
97
98
99
100
# File 'lib/railroad_diagrams/theme.rb', line 90

def css(css_variables: true)
  return render(tokens, css_variables, name) unless name == :auto

  base_css = render(DEFAULT_TOKENS, css_variables, :default)
  dark_css = if css_variables
               "  svg.railroad-diagram {\n#{DARK_TOKENS.map { |key, value| "    #{key}: #{value};\n" }.join}  }\n"
             else
               render(DARK_TOKENS, false, :dark).lines.map { |line| "  #{line}" }.join
             end
  ERB.new(File.read(File.expand_path('themes/auto.css.erb', __dir__))).result(binding)
end

#inline_style(element, classes) ⇒ Object

Parameters:

  • element (Object)
  • classes (Object)

Returns:

  • (Object)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/railroad_diagrams/theme.rb', line 102

def inline_style(element, classes)
  palette = tokens
  own_classes = element.attrs.fetch('class', '').split
  all_classes = classes + own_classes
  rules = case element.name
          when 'svg'
            ["background-color:#{palette.fetch('--rr-bg')}", "color:#{palette.fetch('--rr-text')}"]
          when 'path'
            ["stroke-width:#{palette.fetch('--rr-stroke-width')}", "stroke:#{palette.fetch('--rr-stroke')}",
             "fill:#{palette.fetch('--rr-track-fill')}"]
          when 'rect'
            ["stroke-width:#{palette.fetch('--rr-stroke-width')}", "stroke:#{palette.fetch('--rr-stroke')}",
             "fill:#{palette.fetch('--rr-rect-fill')}"]
          when 'text'
            ["font:#{palette.fetch('--rr-font')}", 'text-anchor:middle', 'white-space:pre']
          else []
          end
  if element.name == 'rect'
    rules << "fill:#{palette.fetch('--rr-terminal-fill')}" if all_classes.include?('terminal')
    rules << "fill:#{palette.fetch('--rr-nonterminal-fill')}" if all_classes.include?('non-terminal')
    rules.push("stroke:#{palette.fetch('--rr-group-stroke')}", 'stroke-dasharray:10 5', 'fill:none') if own_classes.include?('group-box')
  elsif element.name == 'path' && own_classes.include?('diagram-text')
    rules.push("fill:#{palette.fetch('--rr-diagram-text-fill')}", 'cursor:help')
  elsif element.name == 'text'
    rules << "fill:#{palette.fetch('--rr-text')}" unless %i[default auto].include?(name)
    rules << 'font-size:12px' if own_classes.include?('diagram-text')
    rules << 'font-size:16px' if own_classes.include?('diagram-arrow')
    rules << 'text-anchor:start' if own_classes.include?('label')
    rules << "font:#{palette.fetch('--rr-comment-font')}" if own_classes.include?('comment')
  end
  rules.join(';')
end

#render(palette, css_variables, theme_name) ⇒ Object

Parameters:

  • palette (Object)
  • css_variables (Object)
  • theme_name (Object)

Returns:

  • (Object)


137
138
139
140
141
142
143
144
145
146
147
# File 'lib/railroad_diagrams/theme.rb', line 137

def render(palette, css_variables, theme_name)
  value = ->(key) { css_variables ? "var(#{key})" : palette.fetch(key) }
  declarations = if css_variables
                   "svg.railroad-diagram {\n#{palette.map { |key, entry| "  #{key}: #{entry};\n" }.join}}\n"
                 else
                   ''
                 end
  color_selector = theme_name == :default && !css_variables ? '*' : 'svg.railroad-diagram *'
  text_fill = theme_name == :default && !css_variables ? '' : "\n  fill: #{value.call('--rr-text')};"
  ERB.new(File.read(File.expand_path('themes/base.css.erb', __dir__))).result(binding)
end