class Asciidoctor::Pdf::ThemeLoader
Constants
- AddSubtractOpRx
- BaseThemePath
- DataDir
- DefaultThemePath
- FontsDir
- HexColorEntryRx
- LoneVariableRx
- MeasurementValueRx
- MultiplyDivideOpRx
- PrecisionFuncRx
- ThemesDir
- VariableRx
Public Class Methods
load_base_theme()
click to toggle source
NOTE base theme is loaded “as is” (no post-processing)
# File lib/asciidoctor-pdf/theme_loader.rb, line 56 def self.load_base_theme ::OpenStruct.new(::SafeYAML.load_file BaseThemePath) end
load_file(filename, theme_data = nil)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 76 def self.load_file filename, theme_data = nil raw_data = (::IO.read filename).each_line.map {|l| l.sub HexColorEntryRx, '\k<k>: \\k<v>\' }.join self.new.load((::SafeYAML.load raw_data), theme_data) end
load_theme(theme_name = nil, theme_path = nil, opts = {})
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 60 def self.load_theme theme_name = nil, theme_path = nil, opts = {} if (theme_file = resolve_theme_file theme_name, theme_path) == BaseThemePath || (theme_file != DefaultThemePath && (opts.fetch :apply_base_theme, true)) theme_data = load_base_theme else theme_data = nil end if theme_file == BaseThemePath theme_data else # QUESTION should we do any post-load calculations or defaults? load_file theme_file, theme_data end end
resolve_theme_asset(asset_path, theme_path = nil)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 51 def self.resolve_theme_asset asset_path, theme_path = nil ::File.expand_path asset_path, (theme_path || ThemesDir) end
resolve_theme_file(theme_name = nil, theme_path = nil)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 38 def self.resolve_theme_file theme_name = nil, theme_path = nil theme_name ||= 'default' # if .yml extension is given, assume it's a full file name if (theme_name.end_with? '.yml') # FIXME restrict to jail! # QUESTION why are we not using expand_path in this case? theme_path ? (::File.join theme_path, theme_name) : theme_name else # QUESTION should we append '-theme.yml' or just '.yml'? ::File.expand_path %Q(#{theme_name}-theme.yml), (theme_path || ThemesDir) end end
Public Instance Methods
load(hash, theme_data = nil)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 81 def load hash, theme_data = nil theme_data ||= ::OpenStruct.new hash.inject(theme_data) {|data, (key, val)| process_entry key, val, data } end
Private Instance Methods
evaluate(expr, vars)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 104 def evaluate expr, vars case expr when ::String evaluate_math(expand_vars expr, vars) when ::Array expr.map {|e| evaluate e, vars } else expr end end
evaluate_math(expr)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 128 def evaluate_math expr return expr if !(::String === expr) || ColorValue === expr original = expr # FIXME quick HACK to turn a single negative number into an expression expr = %Q(1 - #{expr[1..-1]}) if expr.start_with? '-' # expand measurement values (e.g., 0.5in) expr = expr.gsub(MeasurementValueRx) { # TODO extract to_pt method and use it here val = $1.to_f case $2 when 'in' val = val * 72 when 'mm' val = val * (72 / 25.4) when 'cm' val = val * (720 / 25.4) #when '%' # val = val / 100.0 # default is pt end # QUESTION should we round the value? val } while true result = expr.gsub(MultiplyDivideOpRx) { $1.to_f.send $2.to_sym, $3.to_f } unchanged = (result == expr) expr = result break if unchanged end while true result = expr.gsub(AddSubtractOpRx) { $1.to_f.send $2.to_sym, $3.to_f } unchanged = (result == expr) expr = result break if unchanged end if (expr.end_with? ')') && expr =~ PrecisionFuncRx op = $1 offset = op.length + 1 expr = expr[offset...-1].to_f.send op.to_sym end if expr == original original else (int_val = expr.to_i) == (flt_val = expr.to_f) ? int_val : flt_val end end
expand_vars(expr, vars)
click to toggle source
NOTE we assume expr is a String
# File lib/asciidoctor-pdf/theme_loader.rb, line 116 def expand_vars expr, vars if (idx = (expr.index '$')) if idx == 0 && expr =~ LoneVariableRx vars[$1] else expr.gsub(VariableRx) { vars[$1] } end else expr end end
process_entry(key, val, data)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 88 def process_entry key, val, data if key.start_with? 'admonition_icon_' data[key] = (val || {}).map do |(key2, val2)| static_val2 = evaluate val2, data [key2.to_sym, (key2.end_with? '_color') ? to_color(static_val2) : static_val2] end.to_h elsif key != 'font_catalog' && ::Hash === val val.each do |key2, val2| process_entry %Q(#{key}_#{key2.tr '-', '_'}), val2, data end else data[key] = (key.end_with? '_color') ? to_color(evaluate val, data) : (evaluate val, data) end data end
to_color(value)
click to toggle source
# File lib/asciidoctor-pdf/theme_loader.rb, line 175 def to_color value case value when ColorValue # already converted return value when ::String if value == 'transparent' # FIXME should we have a TransparentColorValue class? return HexColorValue.new value elsif value.size == 6 return HexColorValue.new value.upcase end when ::Array case value.size # CMYK value when 4 value = value.map do |e| if ::Numeric === e e = e * 100.0 unless e > 1 else e = e.to_s.chomp('%').to_f end e == (int_e = e.to_i) ? int_e : e end case value when [0, 0, 0, 0] return HexColorValue.new 'FFFFFF' when [100, 100, 100, 100] return HexColorValue.new '000000' else value.extend CmykColorValue return value end # RGB value when 3 return HexColorValue.new value.map {|e| '%02X' % e}.join # Nonsense array value; flatten to string else value = value.join end else # Unknown type; coerce to a string value = %Q(#{value}) end value = case value.size when 6 value when 3 # expand hex shorthand (e.g., f00 -> ff0000) value.each_char.map {|c| c * 2 }.join else # truncate or pad with leading zeros (e.g., ff -> 0000ff) value[0..5].rjust 6, '0' end HexColorValue.new value.upcase end