# frozen_string_literal: true # barber patches to re-route raw compilation via ember compat handlebars class Barber::Precompiler def sources [File.open("#{Rails.root}/app/assets/javascripts/node_modules/handlebars/dist/handlebars.js"), precompiler] end def precompiler if !@precompiler source = File.read("#{Rails.root}/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js") transpiler = DiscourseJsProcessor::Transpiler.new(skip_module: true) transpiled = transpiler.perform(source) # very hacky but lets us use ES6. I'm ashamed of this code -RW transpiled = transpiled[transpiled.index('var RawHandlebars = ')...transpiled.index('export ')] @precompiler = StringIO.new <<~JS var __RawHandlebars; (function() { #{transpiled}; __RawHandlebars = RawHandlebars; })(); Barber = { precompile: function(string) { return __RawHandlebars.precompile(string, false).toString(); } }; JS end @precompiler end end module Discourse module Ember module Handlebars module Helper def precompile_handlebars(string, input = nil) "requirejs('discourse-common/lib/raw-handlebars').template(#{Barber::Precompiler.compile(string)});" end def compile_handlebars(string, input = nil) "requirejs('discourse-common/lib/raw-handlebars').compile(#{indent(string).inspect});" end end end end end class Ember::Handlebars::Template prepend Discourse::Ember::Handlebars::Helper def path_for(module_name, config) # We need this for backward-compatibility reasons. # Plugins may not have an app subdirectory. template_path(module_name, config).inspect.gsub('discourse/templates/', '') end def global_template_target(namespace, module_name, config) "#{namespace}[#{path_for(module_name, config)}]" end def call(input) data = input[:data] filename = input[:filename] raw = handlebars?(filename) if raw template = data else template = mustache_to_handlebars(filename, data) end template_name = input[:name] module_name = case config.output_type when :amd amd_template_target(config.amd_namespace, template_name) when :global template_path(template_name, config) else raise "Unsupported `output_type`: #{config.output_type}" end meta = meta_supported? ? { moduleName: module_name } : false if config.precompile if raw template = precompile_handlebars(template, input) else template = precompile_ember_handlebars(template, config.ember_template, input, meta) end else if raw template = compile_handlebars(data) else template = compile_ember_handlebars(template, config.ember_template, meta) end end case config.output_type when :amd "define('#{module_name}', ['exports'], function(__exports__){ __exports__['default'] = #{template} });" when :global if raw return <<~JS var __t = #{template}; requirejs('discourse-common/lib/raw-templates').addRawTemplate(#{path_for(template_name, config)}, __t); JS end target = global_template_target('Ember.TEMPLATES', template_name, config) "#{target} = #{template}\n" else raise "Unsupported `output_type`: #{config.output_type}" end end # FIXME: Previously, ember-handlebars-templates uses the logical path which incorrectly # returned paths with the `.raw` extension and our code is depending on the `.raw` # to find the right template to use. def actual_name(input) actual_name = input[:name] input[:filename].include?('.raw') ? "#{actual_name}.raw" : actual_name end private def handlebars?(filename) filename.to_s =~ /\.raw\.(handlebars|hjs|hbs)/ || filename.to_s.ends_with?(".hbr") || filename.to_s.ends_with?(".hbr.erb") end end