class Emerald::PreProcessor
Preprocess the emerald code and add notion of indentation so it may be parsed by a context free grammar. Removes all whitespace and adds braces to denote indentation.
Public Class Methods
new()
click to toggle source
# File lib/emerald/preprocessor.rb, line 14 def initialize reset end
Public Instance Methods
check_and_enter_literal(line)
click to toggle source
# File lib/emerald/preprocessor.rb, line 126 def check_and_enter_literal(line) if line.rstrip.end_with?('->') @in_literal = true @current_indent += 2 @templateless_literal = false @preserve_html_literal = false elsif line.rstrip.end_with?('=>') @in_literal = true @current_indent += 2 @templateless_literal = true @preserve_html_literal = false elsif line.rstrip.end_with?('~>') @in_literal = true @current_indent += 2 @templateless_literal = true @preserve_html_literal = true end end
check_new_indent(new_indent)
click to toggle source
Compares the value of the new_indent with the old indentation. Invoked by: process_emerald
# File lib/emerald/preprocessor.rb, line 60 def check_new_indent(new_indent) if new_indent > @current_indent open_tags(new_indent) elsif new_indent < @current_indent close_tags(new_indent) end end
close_literal(new_indent)
click to toggle source
Append closing braces if in literal and new indent is less than old one
# File lib/emerald/preprocessor.rb, line 85 def close_literal(new_indent) @output += "$\n" @in_literal = false (2..((@current_indent - new_indent) / 2)).each do @output += "}\n" @b_count -= 1 end end
process_emerald(input)
click to toggle source
Process the emerald to remove indentation and replace with brace convention for an easier time parsing with context free grammar
# File lib/emerald/preprocessor.rb, line 31 def process_emerald(input) input.each_line.with_index do |line, line_number| if @in_literal if line[0...-1].empty? new_indent = @current_indent line = " "*@current_indent + "\n" else new_indent = line.length - line.lstrip.length end else next if line.lstrip.empty? new_indent = line.length - line.lstrip.length end check_new_indent(new_indent) @output += remove_indent_whitespace(line) @source_map[@output.lines.length] = { source_line: line_number + 1 } check_and_enter_literal(line) end close_tags(0) [@output, @source_map] end
remove_indent_whitespace(line)
click to toggle source
Crop off only Emerald
indent whitespace to preserve whitespace in the literal. Since $ is the end character, we need to escape it in the literal.
# File lib/emerald/preprocessor.rb, line 105 def remove_indent_whitespace(line) if @in_literal # Ignore indent whitespace, only count post-indent as the literal, # but keep any extra whitespace that might exist for literals cropped = line[@current_indent..-1] || '' if @templateless_literal # this is a fun one https://www.ruby-forum.com/topic/143645 cropped = cropped.gsub("\\"){ "\\\\" } end unless @preserve_html_literal cropped = @encoder.encode cropped end # Escape $ since we use it as a terminator for literals, and encode HTML cropped.gsub('$', "\\$") else line.lstrip end end
reset()
click to toggle source
Reset class variables, used for testing
# File lib/emerald/preprocessor.rb, line 19 def reset @in_literal = false @templateless_literal = false @current_indent = 0 @b_count = 0 @output = '' @encoder = HTMLEntities.new @source_map = {} end