DEV: Introduce support for template colocation in themes
This commit is contained in:
parent
65a5c84a92
commit
cb87067c77
|
@ -4,6 +4,7 @@
|
|||
|
||||
const makeEmberTemplateCompilerPlugin =
|
||||
require("babel-plugin-ember-template-compilation").default;
|
||||
const colocatedBabelPlugin = require("colocated-babel-plugin").default;
|
||||
const precompile = require("ember-template-compiler").precompile;
|
||||
const Handlebars = require("handlebars").default;
|
||||
|
||||
|
@ -50,6 +51,7 @@ function buildTemplateCompilerBabelPlugins({ themeId }) {
|
|||
}
|
||||
|
||||
return [
|
||||
colocatedBabelPlugin,
|
||||
require("widget-hbs-compiler").WidgetHbsCompiler,
|
||||
[
|
||||
makeEmberTemplateCompilerPlugin(() => compileFunction),
|
||||
|
|
|
@ -6,7 +6,7 @@ require 'json_schemer'
|
|||
class Theme < ActiveRecord::Base
|
||||
include GlobalPath
|
||||
|
||||
BASE_COMPILER_VERSION = 63
|
||||
BASE_COMPILER_VERSION = 64
|
||||
|
||||
attr_accessor :child_components
|
||||
|
||||
|
|
|
@ -157,6 +157,7 @@ class DiscourseJsProcessor
|
|||
load_file_in_context(ctx, "node_modules/babel-plugin-ember-template-compilation/src/plugin.js", wrap_in_module: "babel-plugin-ember-template-compilation/index")
|
||||
load_file_in_context(ctx, "node_modules/babel-plugin-ember-template-compilation/src/expression-parser.js", wrap_in_module: "babel-plugin-ember-template-compilation/expression-parser")
|
||||
load_file_in_context(ctx, "node_modules/babel-import-util/src/index.js", wrap_in_module: "babel-import-util")
|
||||
load_file_in_context(ctx, "node_modules/ember-cli-htmlbars/lib/colocated-babel-plugin.js", wrap_in_module: "colocated-babel-plugin")
|
||||
|
||||
# Widget HBS compiler
|
||||
widget_hbs_compiler_source = File.read("#{Rails.root}/lib/javascripts/widget-hbs-compiler.js")
|
||||
|
|
|
@ -39,6 +39,46 @@ class ThemeJavascriptCompiler
|
|||
end
|
||||
end
|
||||
|
||||
# Handle colocated components
|
||||
tree.dup.each_pair do |filename, content|
|
||||
is_component_template = filename.end_with?(".hbs") && filename.start_with?("#{root_name}/components/")
|
||||
next if !is_component_template
|
||||
template_contents = content
|
||||
|
||||
hbs_invocation_options = {
|
||||
moduleName: filename,
|
||||
parseOptions: {
|
||||
srcName: filename
|
||||
}
|
||||
}
|
||||
hbs_invocation = "hbs(#{template_contents.to_json}, #{hbs_invocation_options.to_json})"
|
||||
|
||||
prefix = <<~JS
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
const __COLOCATED_TEMPLATE__ = #{hbs_invocation};
|
||||
JS
|
||||
|
||||
js_filename = filename.sub(/\.hbs\z/, ".js")
|
||||
js_contents = tree[js_filename] # May be nil for template-only component
|
||||
if js_contents && !js_contents.include?("export default")
|
||||
message = "#{filename} does not contain a `default export`. Did you forget to export the component class?"
|
||||
js_contents += "throw new Error(#{message.to_json});"
|
||||
end
|
||||
|
||||
if js_contents.nil?
|
||||
# No backing class, use template-only
|
||||
js_contents = <<~JS
|
||||
import templateOnly from '@ember/component/template-only';
|
||||
export default templateOnly();
|
||||
JS
|
||||
end
|
||||
|
||||
js_contents = prefix + js_contents
|
||||
|
||||
tree[js_filename] = js_contents
|
||||
tree.delete(filename)
|
||||
end
|
||||
|
||||
# Transpile and write to output
|
||||
tree.each_pair do |filename, content|
|
||||
module_name, extension = filename.split(".", 2)
|
||||
|
|
|
@ -86,5 +86,44 @@ RSpec.describe ThemeJavascriptCompiler do
|
|||
expect(compiler.content).to include('define("discourse/theme-1/components/mycomponent"')
|
||||
expect(compiler.content).to include('define("discourse/theme-1/discourse/templates/components/mycomponent"')
|
||||
end
|
||||
|
||||
it "handles colocated components" do
|
||||
compiler.append_tree(
|
||||
{
|
||||
"discourse/components/mycomponent.js" => <<~JS,
|
||||
import Component from "@glimmer/component";
|
||||
export default class MyComponent extends Component {}
|
||||
JS
|
||||
"discourse/components/mycomponent.hbs" => "{{my-component-template}}"
|
||||
}
|
||||
)
|
||||
expect(compiler.content).to include("__COLOCATED_TEMPLATE__ =")
|
||||
expect(compiler.content).to include("setComponentTemplate")
|
||||
end
|
||||
|
||||
it "prints error when default export missing" do
|
||||
compiler.append_tree(
|
||||
{
|
||||
"discourse/components/mycomponent.js" => <<~JS,
|
||||
import Component from "@glimmer/component";
|
||||
class MyComponent extends Component {}
|
||||
JS
|
||||
"discourse/components/mycomponent.hbs" => "{{my-component-template}}"
|
||||
}
|
||||
)
|
||||
expect(compiler.content).to include("__COLOCATED_TEMPLATE__ =")
|
||||
expect(compiler.content).to include("throw new Error")
|
||||
end
|
||||
|
||||
it "handles template-only components" do
|
||||
compiler.append_tree(
|
||||
{
|
||||
"discourse/components/mycomponent.hbs" => "{{my-component-template}}"
|
||||
}
|
||||
)
|
||||
expect(compiler.content).to include("__COLOCATED_TEMPLATE__ =")
|
||||
expect(compiler.content).to include("setComponentTemplate")
|
||||
expect(compiler.content).to include("@ember/component/template-only")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue