# frozen_string_literal: true require 'opal/compiler' module Opal module ERB # Compile ERB code into javascript. # # [Opal::ERB] can be used to compile [ERB] templates into javascript code. # This module uses the [Opal::Compiler] internally. # # Compiled templates, when run in a javascript environment, will appear # under the `Template` namespace, and can be accessed as: # # Template['template_name'] # => template instance # # @example # # source = "
<%= @content %>
" # # Opal::ERB.compile source, "my_template.erb" # # @param source [String] erb content # @param file_name [String] filename for reference in template # @return [String] javascript code # def self.compile(source, file_name = '(erb)') Compiler.new(source, file_name).compile end class Compiler BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/ def initialize(source, file_name = '(erb)') @source, @file_name, @result = source, file_name, source end def prepared_source @prepared_source ||= begin source = @source source = fix_quotes(source) source = find_contents(source) source = find_code(source) source = wrap_compiled(source) source = require_erb(source) source end end def compile Opal.compile prepared_source end def fix_quotes(result) result.gsub '"', '\\"' end def require_erb(result) 'require "erb";' + result end def find_contents(result) result.gsub(/<%=([\s\S]+?)%>/) do inner = Regexp.last_match(1).gsub(/\\'/, "'").gsub(/\\"/, '"') if inner =~ BLOCK_EXPR "\")\noutput_buffer.append= #{inner}\noutput_buffer.append(\"" else "\")\noutput_buffer.append=(#{inner})\noutput_buffer.append(\"" end end end def find_code(result) result.gsub(/<%([\s\S]+?)%>/) do inner = Regexp.last_match(1).gsub(/\\"/, '"') "\")\n#{inner}\noutput_buffer.append(\"" end end def wrap_compiled(result) path = @file_name.sub(/\.opalerb#{REGEXP_END}/, '') "Template.new('#{path}') do |output_buffer|\noutput_buffer.append(\"#{result}\")\noutput_buffer.join\nend\n" end end end end