module BannerFontStore
BannerFontStore — per-channel blocks-banner fonts and glyph overrides. Public: active, set_active!, fonts, default_overrides, effective_glyphs, set_glyph!, reset_glyph!, save_font!, create_font!, delete_font!, reset_font!, custom_font_names Depends: RabbotDb, BannerFont, BannerFontGlyphs Tests: test/lib/banner_font_store_test.rb
Constants
- ACTIVE_KEY
- DEFAULT_FONT
- DEFAULT_OVERRIDES_KEY
- FONTS_KEY
- PLUGIN
- VALID_GLYPH_CHARS
- VALID_LETTER
Public Instance Methods
Source
# File lib/banner_font_store.rb, line 24 def active(network:, channel:, store: RabbotDb) name = store.get_plugin_json( plugin: PLUGIN, key: ACTIVE_KEY, network: network, channel: channel, default: DEFAULT_FONT ) name.to_s.empty? ? DEFAULT_FONT : name.to_s end
Source
# File lib/banner_font_store.rb, line 146 def create_font!(name, network:, channel:, store: RabbotDb) normalized_name = normalize_font_name(name) delta = {} effective_glyphs(network: network, channel: channel, store: store).each do |char, rows| base_rows = BannerFont::GLYPHS[char] delta[char] = rows if rows != base_rows end save_font!(normalized_name, delta, network: network, channel: channel, store: store) set_active!(normalized_name, network: network, channel: channel, store: store) normalized_name end
Source
# File lib/banner_font_store.rb, line 71 def custom_font_names(network:, channel:, store: RabbotDb) fonts(network: network, channel: channel, store: store).keys.sort end
Source
# File lib/banner_font_store.rb, line 171 def customized_letters(network:, channel:, font_name: nil, store: RabbotDb) name = font_name || active(network: network, channel: channel, store: store) map = if name == DEFAULT_FONT default_overrides(network: network, channel: channel, store: store) else fonts(network: network, channel: channel, store: store)[name] || {} end map.keys.sort end
Source
# File lib/banner_font_store.rb, line 60 def default_overrides(network:, channel:, store: RabbotDb) raw = store.get_plugin_json( plugin: PLUGIN, key: DEFAULT_OVERRIDES_KEY, network: network, channel: channel, default: {} ) symbolize_glyph_map(raw) end
Source
# File lib/banner_font_store.rb, line 158 def delete_font!(name, network:, channel:, store: RabbotDb) normalized_name = normalize_font_name(name) raise ArgumentError, "Cannot delete the default font." if normalized_name == DEFAULT_FONT raise ArgumentError, "Unknown font." unless fonts(network: network, channel: channel, store: store).key?(normalized_name) font_map = fonts(network: network, channel: channel, store: store) font_map.delete(normalized_name) persist_fonts!(font_map, network: network, channel: channel, store: store) was_active = active(network: network, channel: channel, store: store) == normalized_name set_active!(DEFAULT_FONT, network: network, channel: channel, store: store) if was_active normalized_name end
Source
# File lib/banner_font_store.rb, line 75 def effective_glyphs(network:, channel:, store: RabbotDb) active_name = active(network: network, channel: channel, store: store) base = BannerFont::GLYPHS overrides = if active_name == DEFAULT_FONT default_overrides(network: network, channel: channel, store: store) else fonts(network: network, channel: channel, store: store)[active_name] || {} end normalize_glyph_map(base.merge(overrides)) end
Source
# File lib/banner_font_store.rb, line 219 def font_exists?(name, network:, channel:, store: RabbotDb) normalized = name.to_s.downcase return true if normalized == DEFAULT_FONT fonts(network: network, channel: channel, store: store).key?(normalized) end
Source
# File lib/banner_font_store.rb, line 49 def fonts(network:, channel:, store: RabbotDb) raw = store.get_plugin_json( plugin: PLUGIN, key: FONTS_KEY, network: network, channel: channel, default: {} ) symbolize_font_map(raw) end
Source
# File lib/banner_font_store.rb, line 182 def glyphs_for_font(font_name, network:, channel:, store: RabbotDb) name = font_name.to_s.downcase base = BannerFont::GLYPHS overrides = if name == DEFAULT_FONT default_overrides(network: network, channel: channel, store: store) else fonts(network: network, channel: channel, store: store)[name] || {} end normalize_glyph_map(base.merge(overrides)) end
Source
# File lib/banner_font_store.rb, line 226 def normalize_font_name(name) normalized = name.to_s.strip.downcase raise ArgumentError, "Font name cannot be empty." if normalized.empty? raise ArgumentError, "Font name cannot be 'default'." if normalized == DEFAULT_FONT raise ArgumentError, "Invalid font name." unless normalized.match?(/\A[a-z0-9][a-z0-9_-]{0,31}\z/) normalized end
Source
# File lib/banner_font_store.rb, line 235 def normalize_glyph_map(map) map.each_with_object({}) do |(key, rows), out| w = BannerFont.glyph_row_width(rows) normalized = Array(rows).map { |row| BannerFont.normalize_glyph_row(row, w) } out[key.to_s.upcase] = BannerFont.ensure_height(normalized, width: w) end end
Source
# File lib/banner_font_store.rb, line 195 def normalize_letter(letter) char = letter.to_s.strip.upcase char = " " if char == "SPACE" raise ArgumentError, "Letter must be A–Z, 0–9, or space." unless char.match?(VALID_LETTER) char end
Source
# File lib/banner_font_store.rb, line 273 def persist_default_overrides!(overrides, network:, channel:, store:) store.set_plugin_json( plugin: PLUGIN, key: DEFAULT_OVERRIDES_KEY, value: overrides, network: network, channel: channel ) end
Source
# File lib/banner_font_store.rb, line 262 def persist_fonts!(font_map, network:, channel:, store:) store.set_plugin_json( plugin: PLUGIN, key: FONTS_KEY, value: font_map, network: network, channel: channel ) end
Source
# File lib/banner_font_store.rb, line 122 def reset_font!(letter: nil, network:, channel:, store: RabbotDb) if letter reset_glyph!(letter, network: network, channel: channel, store: store) return end active_name = active(network: network, channel: channel, store: store) if active_name == DEFAULT_FONT persist_default_overrides!({}, network: network, channel: channel, store: store) else font_map = fonts(network: network, channel: channel, store: store) font_map[active_name] = {} persist_fonts!(font_map, network: network, channel: channel, store: store) end end
Source
# File lib/banner_font_store.rb, line 107 def reset_glyph!(letter, network:, channel:, store: RabbotDb) char = normalize_letter(letter) active_name = active(network: network, channel: channel, store: store) if active_name == DEFAULT_FONT overrides = default_overrides(network: network, channel: channel, store: store) overrides.delete(char) persist_default_overrides!(overrides, network: network, channel: channel, store: store) else font_map = fonts(network: network, channel: channel, store: store) font_map[active_name]&.delete(char) persist_fonts!(font_map, network: network, channel: channel, store: store) end end
Source
# File lib/banner_font_store.rb, line 138 def save_font!(name, glyphs, network:, channel:, store: RabbotDb) normalized_name = normalize_font_name(name) font_map = fonts(network: network, channel: channel, store: store) font_map[normalized_name] = normalize_glyph_map(glyphs) persist_fonts!(font_map, network: network, channel: channel, store: store) normalized_name end
Source
# File lib/banner_font_store.rb, line 35 def set_active!(name, network:, channel:, store: RabbotDb) normalized = name.to_s.downcase raise ArgumentError, "Unknown font." unless font_exists?(normalized, network: network, channel: channel, store: store) store.set_plugin_json( plugin: PLUGIN, key: ACTIVE_KEY, value: normalized, network: network, channel: channel ) normalized end
Source
# File lib/banner_font_store.rb, line 88 def set_glyph!(letter, rows, network:, channel:, store: RabbotDb, width: nil) char = normalize_letter(letter) normalized_rows = validate_glyph_rows(rows, width: width) active_name = active(network: network, channel: channel, store: store) if active_name == DEFAULT_FONT overrides = default_overrides(network: network, channel: channel, store: store) overrides[char] = normalized_rows persist_default_overrides!(overrides, network: network, channel: channel, store: store) else font_map = fonts(network: network, channel: channel, store: store) font_map[active_name] ||= {} font_map[active_name][char] = normalized_rows persist_fonts!(font_map, network: network, channel: channel, store: store) end normalized_rows end
Source
# File lib/banner_font_store.rb, line 253 def symbolize_font_map(raw) return {} unless raw.is_a?(Hash) raw.each_with_object({}) do |(name, glyphs), out| out[name.to_s.downcase] = symbolize_glyph_map(glyphs) end end
Source
# File lib/banner_font_store.rb, line 244 def symbolize_glyph_map(raw) return {} unless raw.is_a?(Hash) raw.each_with_object({}) do |(key, rows), out| out[key.to_s.upcase] = Array(rows).map(&:to_s) end end
Source
# File lib/banner_font_store.rb, line 203 def validate_glyph_rows(rows, width: nil) list = Array(rows) w = width || BannerFont::WIDTH unless list.length == BannerFont::HEIGHT || list.length == BannerFont::CAP_HEIGHT raise ArgumentError, "Glyph needs exactly #{BannerFont::HEIGHT} rows." end normalized = list.map do |row| text = row.to_s raise ArgumentError, "Glyph rows may only use █▀▄. and spaces." unless text.match?(VALID_GLYPH_CHARS) BannerFont.normalize_glyph_row(text, w) end BannerFont.ensure_height(normalized, width: w) end