Class: Fiasco::Template::Compiler

Inherits:
Object
  • Object
show all
Defined in:
lib/fiasco/template/compiler.rb

Constant Summary collapse

OPENERS =
/(.*?)(^[ \t]*%|\{%-?|\{\{-?|\{#-?|\z)/m
DEFAULT_DISPLAY_VALUE =
->(outvar, literal){"#{outvar} << (#{literal}).to_s"}
DEFAULT_DISPLAY_TEXT =
->(text){text.dump}

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Compiler

Returns a new instance of Compiler.



9
10
11
12
13
# File 'lib/fiasco/template/compiler.rb', line 9

def initialize(options = {})
  @output_var = options.fetch(:output_var, '@render_output')
  @display_value = options.fetch(:display_value, DEFAULT_DISPLAY_VALUE)
  @display_text = options.fetch(:display_text, DEFAULT_DISPLAY_TEXT)
end

Instance Method Details

#closer_for(tag) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/fiasco/template/compiler.rb', line 15

def closer_for(tag)
  case tag
  when /\{%-?/ then /(.*?)(-?%\}|\z)/m
  when /\{\{-?/ then /(.*?)(-?}\}|\z)/m
  when /\{#-?/ then /(.*?)(-?#\}|\z)/m
  when '%' then /(.*?)($)/
  end
end

#compile(body) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/fiasco/template/compiler.rb', line 58

def compile(body)
  src = []

  scan(body) do |command, data|
    case command
    when :newlines
      src << "\n" * data unless data == 0
    when :text
      src << "#{@output_var} << #{@display_text.(data)}" unless data.empty?
    when :code, :code_line
      src << data
    when :display
      src << @display_value.(@output_var, data)
    when :comment
      # skip
    end
  end

  src.join(';')
end

#scan(body) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/fiasco/template/compiler.rb', line 24

def scan(body)
  scanner = StringScanner.new(body)
  open_tag = nil

  until scanner.eos?
    if open_tag
      scanner.scan(closer_for(open_tag))
      inner, close_tag = scanner[1], scanner[2]

      case open_tag
      when '{{', '{{-' then yield [:display,   inner]
      when '{%', '{%-' then yield [:code,      inner]
      when '{#', '{#-' then yield [:comment,   inner]
      when '%'         then yield [:code_line, inner]
      end

      open_tag = nil
    else
      scanner.scan(OPENERS)
      before, open_tag = scanner[1], scanner[2]
      newlines_count = before.count("\n")
      open_tag.lstrip! # for % which captures preceeding whitespace

      text = before
      text.lstrip! if close_tag && close_tag[0] == '-'
      text.rstrip! if open_tag[-1] == '-'
      text.chomp! if open_tag == '%'

      yield [:text, text]
      yield [:newlines, newlines_count]
    end
  end
end