DEV: Introduce plugin api for conditionally rendering assets (#9200)

This commit is contained in:
David Taylor 2020-03-13 15:30:31 +00:00 committed by GitHub
parent 8a4784d36f
commit 3d71b68195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 22 deletions

View File

@ -12,6 +12,6 @@
<%= discourse_stylesheet_link_tag(mobile_view? ? :mobile_theme : :desktop_theme) %> <%= discourse_stylesheet_link_tag(mobile_view? ? :mobile_theme : :desktop_theme) %>
<%- end %> <%- end %>
<%- Discourse.find_plugin_css_assets(include_official: allow_plugins?, include_unofficial: allow_third_party_plugins?, mobile_view: mobile_view?, desktop_view: !mobile_view?).each do |file| %> <%- Discourse.find_plugin_css_assets(include_official: allow_plugins?, include_unofficial: allow_third_party_plugins?, mobile_view: mobile_view?, desktop_view: !mobile_view?, request: request).each do |file| %>
<%= discourse_stylesheet_link_tag(file) %> <%= discourse_stylesheet_link_tag(file) %>
<%- end %> <%- end %>

View File

@ -28,7 +28,7 @@
<%= preload_script "vendor" %> <%= preload_script "vendor" %>
<%= preload_script "pretty-text-bundle" %> <%= preload_script "pretty-text-bundle" %>
<%= preload_script "application" %> <%= preload_script "application" %>
<%- Discourse.find_plugin_js_assets(include_official: allow_plugins?, include_unofficial: allow_third_party_plugins?).each do |file| %> <%- Discourse.find_plugin_js_assets(include_official: allow_plugins?, include_unofficial: allow_third_party_plugins?, request: request).each do |file| %>
<%= preload_script file %> <%= preload_script file %>
<%- end %> <%- end %>
<%- if staff? %> <%- if staff? %>

View File

@ -271,6 +271,10 @@ module Discourse
def self.find_plugin_css_assets(args) def self.find_plugin_css_assets(args)
plugins = self.find_plugins(args) plugins = self.find_plugins(args)
plugins = plugins.select do |plugin|
plugin.asset_filters.all? { |b| b.call(:css, args[:request]) }
end
assets = [] assets = []
targets = [nil] targets = [nil]
@ -289,9 +293,15 @@ module Discourse
end end
def self.find_plugin_js_assets(args) def self.find_plugin_js_assets(args)
self.find_plugins(args).find_all do |plugin| plugins = self.find_plugins(args).select do |plugin|
plugin.js_asset_exists? plugin.js_asset_exists?
end.map { |plugin| "plugins/#{plugin.directory_name}" } end
plugins = plugins.select do |plugin|
plugin.asset_filters.all? { |b| b.call(:js, args[:request]) }
end
plugins.map { |plugin| "plugins/#{plugin.directory_name}" }
end end
def self.assets_digest def self.assets_digest

View File

@ -49,6 +49,7 @@ class Plugin::Instance
:styles, :styles,
:themes, :themes,
:csp_extensions, :csp_extensions,
:asset_filters
].each do |att| ].each do |att|
class_eval %Q{ class_eval %Q{
def #{att} def #{att}
@ -413,6 +414,14 @@ class Plugin::Instance
csp_extensions << extension csp_extensions << extension
end end
# Register a block to run when adding css and js assets
# Two arguments will be passed: (type, request)
# Type is :css or :js. `request` is an instance of Rack::Request
# When using this, make sure to consider the effect on AnonymousCache
def register_asset_filter(&blk)
asset_filters << blk
end
# @option opts [String] :name # @option opts [String] :name
# @option opts [String] :nativeName # @option opts [String] :nativeName
# @option opts [String] :fallbackLocale # @option opts [String] :fallbackLocale

View File

@ -20,22 +20,9 @@ DiscourseEvent.on(:after_plugin_activation) do ||
end end
after_initialize do after_initialize do
# Conditionally load the stylesheet
# Conditionally load the stylesheet. There is unfortunately no easy way to do this via register_asset_filter do |type, request|
# Plugin API. request.nil? || request.env['HTTP_USER_AGENT'] =~ /MSIE|Trident/
reloadable_patch do |plugin|
ApplicationHelper.module_eval do
alias_method :previous_discourse_stylesheet_link_tag, :discourse_stylesheet_link_tag
def discourse_stylesheet_link_tag(name, opts = {})
if name == 'discourse-internet-explorer'
return unless SiteSetting.discourse_internet_explorer_enabled?
return unless request.env['HTTP_USER_AGENT'] =~ /MSIE|Trident/
end
previous_discourse_stylesheet_link_tag(name, opts)
end
end
end end
register_anonymous_cache_key(:ie) do register_anonymous_cache_key(:ie) do

View File

@ -75,12 +75,17 @@ describe Discourse do
end end
end end
let(:plugin1) { plugin_class.new.tap { |p| p.enabled = true } } let(:plugin1) { plugin_class.new.tap { |p| p.enabled = true; p.path = "my-plugin-1" } }
let(:plugin2) { plugin_class.new.tap { |p| p.enabled = false } } let(:plugin2) { plugin_class.new.tap { |p| p.enabled = false; p.path = "my-plugin-1" } }
before { Discourse.plugins.append(plugin1, plugin2) } before { Discourse.plugins.append(plugin1, plugin2) }
after { Discourse.plugins.clear } after { Discourse.plugins.clear }
before do
plugin_class.any_instance.stubs(:css_asset_exists?).returns(true)
plugin_class.any_instance.stubs(:js_asset_exists?).returns(true)
end
it 'can find plugins correctly' do it 'can find plugins correctly' do
expect(Discourse.plugins).to contain_exactly(plugin1, plugin2) expect(Discourse.plugins).to contain_exactly(plugin1, plugin2)
@ -90,6 +95,19 @@ describe Discourse do
# Include disabled plugins when requested # Include disabled plugins when requested
expect(Discourse.find_plugins(include_disabled: true)).to contain_exactly(plugin1, plugin2) expect(Discourse.find_plugins(include_disabled: true)).to contain_exactly(plugin1, plugin2)
end end
it 'can find plugin assets' do
plugin2.enabled = true
expect(Discourse.find_plugin_css_assets({}).length).to eq(2)
expect(Discourse.find_plugin_js_assets({}).length).to eq(2)
plugin1.register_asset_filter do |type, request|
false
end
expect(Discourse.find_plugin_css_assets({}).length).to eq(1)
expect(Discourse.find_plugin_js_assets({}).length).to eq(1)
end
end end
context 'authenticators' do context 'authenticators' do