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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 17 deletions

View File

@ -2,7 +2,7 @@
class ThemeJavascriptCompiler
COLOCATED_CONNECTOR_REGEX = /\A(?<prefix>.*)\/connectors\/(?<outlet>[^\/]+)\/(?<name>[^\/\.]+)\z/
COLOCATED_CONNECTOR_REGEX = /\A(?<prefix>.*\/?)connectors\/(?<outlet>[^\/]+)\/(?<name>[^\/\.]+)\.(?<extension>.+)\z/
class CompileError < StandardError
end
@ -101,6 +101,23 @@ class ThemeJavascriptCompiler
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
tree.dup.each_pair do |filename, content|
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 = "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
# https://github.com/ember-cli/ember-cli-htmlbars/blob/d5aa14b3/lib/template-compiler-plugin.js#L18-L26
script = <<~JS
@ -216,11 +228,6 @@ class ThemeJavascriptCompiler
original_filename = name
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
transpiler = DiscourseJsProcessor::Transpiler.new
@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
# Colocated under `/connectors`
compiler = ThemeJavascriptCompiler.new(1, 'marks')
compiler.append_ember_template("connectors/outlet/blah-1", "{{var}}")
compiler.append_module("console.log('test')", "connectors/outlet/blah-1")
compiler.append_tree({
"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/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`
compiler = ThemeJavascriptCompiler.new(1, 'marks')
compiler.append_ember_template("templates/connectors/outlet/blah-1", "{{var}}")
compiler.append_module("console.log('test')", "templates/connectors/outlet/blah-1")
compiler.append_tree({
"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/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
compiler = ThemeJavascriptCompiler.new(1, 'marks')
compiler.append_ember_template("templates/connectors/outlet/blah-1", "{{var}}")
compiler.append_module("console.log('test')", "connectors/outlet/blah-1")
compiler.append_tree({
"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/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