Class: Przn::Theme

Inherits:
Object
  • Object
show all
Defined in:
lib/przn/theme.rb

Constant Summary collapse

DEFAULT_PATH =
File.expand_path('../../../default_theme.yml', __FILE__)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Theme

Returns a new instance of Theme.



81
82
83
84
85
86
87
88
# File 'lib/przn/theme.rb', line 81

def initialize(config)
  @colors = config[:colors]
  @font = config[:font]
  @bullet = config[:bullet]
  @background = config[:background]
  @title = config[:title]
  @rabbit = config[:rabbit]
end

Instance Attribute Details

#backgroundObject (readonly)

Returns the value of attribute background.



9
10
11
# File 'lib/przn/theme.rb', line 9

def background
  @background
end

#bulletObject (readonly)

Returns the value of attribute bullet.



9
10
11
# File 'lib/przn/theme.rb', line 9

def bullet
  @bullet
end

#colorsObject (readonly)

Returns the value of attribute colors.



9
10
11
# File 'lib/przn/theme.rb', line 9

def colors
  @colors
end

#fontObject (readonly)

Returns the value of attribute font.



9
10
11
# File 'lib/przn/theme.rb', line 9

def font
  @font
end

#rabbitObject (readonly)

Returns the value of attribute rabbit.



9
10
11
# File 'lib/przn/theme.rb', line 9

def rabbit
  @rabbit
end

#titleObject (readonly)

Returns the value of attribute title.



9
10
11
# File 'lib/przn/theme.rb', line 9

def title
  @title
end

Class Method Details

.auto_discover(near:) ⇒ Object

Look for a sibling ‘theme.yml` next to the given file and load it if present, so a deck can ship its theme alongside the markdown without the user having to pass `–theme` explicitly. Returns nil if no file is found.



61
62
63
64
# File 'lib/przn/theme.rb', line 61

def self.auto_discover(near:)
  candidate = File.join(File.dirname(File.expand_path(near)), 'theme.yml')
  File.exist?(candidate) ? load(candidate) : nil
end

.defaultObject



53
54
55
# File 'lib/przn/theme.rb', line 53

def self.default
  new(load_yaml(DEFAULT_PATH))
end

.load(path) ⇒ Object

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/przn/theme.rb', line 11

def self.load(path)
  raise ArgumentError, "Theme file not found: #{path}" unless File.exist?(path)

  defaults = load_yaml(DEFAULT_PATH)
  overrides = load_yaml(path)
  merged = {
    colors: defaults[:colors].merge(overrides[:colors] || {}),
    font: defaults[:font].merge(overrides[:font] || {}),
    bullet: defaults[:bullet].merge(overrides[:bullet] || {}),
    background: defaults[:background].merge(overrides[:background] || {}),
    title: defaults[:title].merge(overrides[:title] || {}),
    # `rabbit` is opt-in: absent → nil → renderer uses the plain N/M footer.
    # Present (even as an empty block) → hash → renderer uses the runner bar.
    rabbit: defaults[:rabbit] || overrides[:rabbit] ?
      (defaults[:rabbit] || {}).merge(overrides[:rabbit] || {}) :
      nil
  }
  new(merged)
end

.parse_duration(input) ⇒ Object

Convert a human-friendly duration string to seconds.

"30m"     -> 1800
"1h30m"   -> 5400
"1h2m3s"  -> 3723
"45"      -> 45  (bare integers are seconds)
45        -> 45  (already a number)
nil / ""  -> nil
"garbage" -> nil


39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/przn/theme.rb', line 39

def self.parse_duration(input)
  return nil if input.nil?
  return input.to_i if input.is_a?(Numeric)

  s = input.to_s.strip
  return nil if s.empty?
  return s.to_i if s =~ /\A\d+\z/

  m = s.match(/\A(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?\z/)
  return nil unless m && m[0] != ''
  h, mi, se = m[1].to_i, m[2].to_i, m[3].to_i
  h * 3600 + mi * 60 + se
end