From 7b4fdebbce3bd564e5c5becb72ac49ebf96265b6 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 13 Apr 2020 15:05:46 -0400 Subject: [PATCH] FEATURE: Plugin support for transpiling regular `.js` files (#9398) This adds support for a new piece of metadata to your plugin.rb files. If you add: ``` transpile_js: true ``` Then Discourse will support transpilation of assets in your `assets/javascripts` directory. Previously they had to be named `.js.es6` but now regular `.js` will work. Note this is opt-in because some plugins currently have `.js` files in app/assets that are not meant to be transpiled. Going forward all plugins should migrate to this setting as they are comfortable able to do so. --- lib/discourse_js_processor.rb | 6 ++++++ lib/plugin/instance.rb | 22 +++++++++++++++++++--- lib/plugin/metadata.rb | 2 +- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/discourse_js_processor.rb b/lib/discourse_js_processor.rb index 7417207ff5c..6d56af70983 100644 --- a/lib/discourse_js_processor.rb +++ b/lib/discourse_js_processor.rb @@ -4,6 +4,10 @@ require 'mini_racer' class DiscourseJsProcessor + def self.plugin_transpile_paths + @@plugin_transpile_paths ||= Set.new + end + def self.call(input) root_path = input[:load_path] || '' logical_path = (input[:filename] || '').sub(root_path, '').gsub(/\.(js|es6).*$/, '').sub(/^\//, '') @@ -56,6 +60,8 @@ class DiscourseJsProcessor embed-application ).any? { |f| relative_path == "#{js_root}/#{f}.js" } + return true if plugin_transpile_paths.any? { |prefix| relative_path.start_with?(prefix) } + !!(relative_path =~ /^#{js_root}\/[^\/]+\// || relative_path =~ /^#{test_root}\/[^\/]+\//) end diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index 2510e6c4998..85f06dfb229 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -66,6 +66,13 @@ class Plugin::Instance } end + # If plugins provide `transpile_js: true` in their metadata we will + # transpile regular JS files in the assets folders. Going forward, + # all plugins should do this. + def transpile_js + metadata.try(:transpile_js) == "true" + end + def seed_data @seed_data ||= HashWithIndifferentAccess.new({}) end @@ -511,16 +518,22 @@ class Plugin::Instance def activate! if @path + root_dir_name = File.dirname(@path) + # Automatically include all ES6 JS and hbs files - root_path = "#{File.dirname(@path)}/assets/javascripts" + root_path = "#{root_dir_name}/assets/javascripts" DiscoursePluginRegistry.register_glob(root_path, 'js.es6') DiscoursePluginRegistry.register_glob(root_path, 'hbs') DiscoursePluginRegistry.register_glob(root_path, 'hbr') - admin_path = "#{File.dirname(@path)}/admin/assets/javascripts" + admin_path = "#{root_dir_name}/admin/assets/javascripts" DiscoursePluginRegistry.register_glob(admin_path, 'js.es6', admin: true) DiscoursePluginRegistry.register_glob(admin_path, 'hbs', admin: true) DiscoursePluginRegistry.register_glob(admin_path, 'hbr', admin: true) + + if transpile_js + DiscourseJsProcessor.plugin_transpile_paths << root_path.sub(Rails.root.to_s, '').sub(/^\/*/, '') + end end self.instance_eval File.read(path), path @@ -663,9 +676,12 @@ class Plugin::Instance root_path = "#{File.dirname(@path)}/assets/javascripts" Dir.glob("#{root_path}/**/*") do |f| + f_str = f.to_s if File.directory?(f) yield [f, true] - elsif f.to_s.ends_with?(".js.es6") || f.to_s.ends_with?(".hbs") || f.to_s.ends_with?(".hbr") + elsif f_str.ends_with?(".js.es6") || f_str.ends_with?(".hbs") || f_str.ends_with?(".hbr") + yield [f, false] + elsif transpile_js && f_str.ends_with?(".js") yield [f, false] end end diff --git a/lib/plugin/metadata.rb b/lib/plugin/metadata.rb index 5ceabfde794..1af6c157501 100644 --- a/lib/plugin/metadata.rb +++ b/lib/plugin/metadata.rb @@ -78,7 +78,7 @@ class Plugin::Metadata "discourse-internet-explorer" ]) - FIELDS ||= [:name, :about, :version, :authors, :url, :required_version] + FIELDS ||= [:name, :about, :version, :authors, :url, :required_version, :transpile_js] attr_accessor(*FIELDS) def self.parse(text)