FIX: Ensure minification does not break colocated connectors (#18664)

The filenames (minus the extensions) were being used as keys in a hash to pass to Terser, which meant that colocated connector files would overwrite each other. This commit moves the un-colocating earlier in the pipeline so that the fixed filenames are passed to Terser.

Followup to be3d6a56ce
This commit is contained in:
David Taylor
2022-10-19 10:49:01 +01:00
committed by GitHub
parent a53eb0882a
commit c185043590
2 changed files with 33 additions and 17 deletions

View File

@@ -2,7 +2,7 @@
class ThemeJavascriptCompiler class ThemeJavascriptCompiler
COLOCATED_CONNECTOR_REGEX = /\A(?<prefix>.*)\/connectors\/(?<outlet>[^\/]+)\/(?<name>[^\/\.]+)\z/ COLOCATED_CONNECTOR_REGEX = /\A(?<prefix>.*\/?)connectors\/(?<outlet>[^\/]+)\/(?<name>[^\/\.]+)\.(?<extension>.+)\z/
class CompileError < StandardError class CompileError < StandardError
end end
@@ -101,6 +101,23 @@ class ThemeJavascriptCompiler
end end
end end
# Some themes are colocating connector JS under `/connectors`. Move template to /templates to avoid module name clash
tree.transform_keys! do |filename|
match = COLOCATED_CONNECTOR_REGEX.match(filename)
next filename if !match
is_template = match[:extension] == "hbs"
is_in_templates_directory = match[:prefix].split("/").last == "templates"
if is_template && !is_in_templates_directory
"#{match[:prefix]}templates/connectors/#{match[:outlet]}/#{match[:name]}.#{match[:extension]}"
elsif !is_template && is_in_templates_directory
"#{match[:prefix].chomp('templates/')}connectors/#{match[:outlet]}/#{match[:name]}.#{match[:extension]}"
else
filename
end
end
# Handle colocated components # Handle colocated components
tree.dup.each_pair do |filename, content| tree.dup.each_pair do |filename, content|
is_component_template = filename.end_with?(".hbs") && filename.start_with?("#{root_name}/components/") is_component_template = filename.end_with?(".hbs") && filename.start_with?("#{root_name}/components/")
@@ -164,11 +181,6 @@ class ThemeJavascriptCompiler
module_name = "/#{module_name}" if !module_name.start_with?("/") module_name = "/#{module_name}" if !module_name.start_with?("/")
module_name = "discourse/theme-#{@theme_id}#{module_name}" module_name = "discourse/theme-#{@theme_id}#{module_name}"
# Some themes are colocating connector JS under `/connectors`. Move template to /templates to avoid module name clash
if (match = COLOCATED_CONNECTOR_REGEX.match(module_name)) && !match[:prefix].end_with?("/templates")
module_name = "#{match[:prefix]}/templates/connectors/#{match[:outlet]}/#{match[:name]}"
end
# Mimics the ember-cli implementation # Mimics the ember-cli implementation
# https://github.com/ember-cli/ember-cli-htmlbars/blob/d5aa14b3/lib/template-compiler-plugin.js#L18-L26 # https://github.com/ember-cli/ember-cli-htmlbars/blob/d5aa14b3/lib/template-compiler-plugin.js#L18-L26
script = <<~JS script = <<~JS
@@ -216,11 +228,6 @@ class ThemeJavascriptCompiler
original_filename = name original_filename = name
name = "discourse/theme-#{@theme_id}/#{name.gsub(/^discourse\//, '')}" name = "discourse/theme-#{@theme_id}/#{name.gsub(/^discourse\//, '')}"
# Some themes are colocating connector JS under `/templates/connectors`. Move out of templates to avoid module name clash
if (match = COLOCATED_CONNECTOR_REGEX.match(name)) && match[:prefix].end_with?("/templates")
name = "#{match[:prefix].delete_suffix("/templates")}/connectors/#{match[:outlet]}/#{match[:name]}"
end
script = "#{theme_settings}#{script}" if include_variables script = "#{theme_settings}#{script}" if include_variables
transpiler = DiscourseJsProcessor::Transpiler.new transpiler = DiscourseJsProcessor::Transpiler.new
@output_tree << ["#{original_filename}.js", <<~JS] @output_tree << ["#{original_filename}.js", <<~JS]

View File

@@ -37,24 +37,33 @@ RSpec.describe ThemeJavascriptCompiler do
it 'separates colocated connectors to avoid module name clash' do it 'separates colocated connectors to avoid module name clash' do
# Colocated under `/connectors` # Colocated under `/connectors`
compiler = ThemeJavascriptCompiler.new(1, 'marks') compiler = ThemeJavascriptCompiler.new(1, 'marks')
compiler.append_ember_template("connectors/outlet/blah-1", "{{var}}") compiler.append_tree({
compiler.append_module("console.log('test')", "connectors/outlet/blah-1") "connectors/outlet/blah-1.hbs" => "{{var}}",
"connectors/outlet/blah-1.js" => "console.log('test')"
})
expect(compiler.raw_content.to_s).to include("discourse/theme-1/connectors/outlet/blah-1") expect(compiler.raw_content.to_s).to include("discourse/theme-1/connectors/outlet/blah-1")
expect(compiler.raw_content.to_s).to include("discourse/theme-1/templates/connectors/outlet/blah-1") expect(compiler.raw_content.to_s).to include("discourse/theme-1/templates/connectors/outlet/blah-1")
expect(JSON.parse(compiler.source_map)["sources"]).to contain_exactly("connectors/outlet/blah-1.js", "templates/connectors/outlet/blah-1.js")
# Colocated under `/templates/connectors` # Colocated under `/templates/connectors`
compiler = ThemeJavascriptCompiler.new(1, 'marks') compiler = ThemeJavascriptCompiler.new(1, 'marks')
compiler.append_ember_template("templates/connectors/outlet/blah-1", "{{var}}") compiler.append_tree({
compiler.append_module("console.log('test')", "templates/connectors/outlet/blah-1") "templates/connectors/outlet/blah-1.hbs" => "{{var}}",
"templates/connectors/outlet/blah-1.js" => "console.log('test')"
})
expect(compiler.raw_content.to_s).to include("discourse/theme-1/connectors/outlet/blah-1") expect(compiler.raw_content.to_s).to include("discourse/theme-1/connectors/outlet/blah-1")
expect(compiler.raw_content.to_s).to include("discourse/theme-1/templates/connectors/outlet/blah-1") expect(compiler.raw_content.to_s).to include("discourse/theme-1/templates/connectors/outlet/blah-1")
expect(JSON.parse(compiler.source_map)["sources"]).to contain_exactly("connectors/outlet/blah-1.js", "templates/connectors/outlet/blah-1.js")
# Not colocated # Not colocated
compiler = ThemeJavascriptCompiler.new(1, 'marks') compiler = ThemeJavascriptCompiler.new(1, 'marks')
compiler.append_ember_template("templates/connectors/outlet/blah-1", "{{var}}") compiler.append_tree({
compiler.append_module("console.log('test')", "connectors/outlet/blah-1") "templates/connectors/outlet/blah-1.hbs" => "{{var}}",
"connectors/outlet/blah-1.js" => "console.log('test')"
})
expect(compiler.raw_content.to_s).to include("discourse/theme-1/connectors/outlet/blah-1") expect(compiler.raw_content.to_s).to include("discourse/theme-1/connectors/outlet/blah-1")
expect(compiler.raw_content.to_s).to include("discourse/theme-1/templates/connectors/outlet/blah-1") expect(compiler.raw_content.to_s).to include("discourse/theme-1/templates/connectors/outlet/blah-1")
expect(JSON.parse(compiler.source_map)["sources"]).to contain_exactly("connectors/outlet/blah-1.js", "templates/connectors/outlet/blah-1.js")
end end
end end