FEATURE: Site Customizations can use the plugin api
This commit is contained in:
parent
a7eec3da5c
commit
b4f306ce03
|
@ -6,6 +6,8 @@ define('ember', ['exports'], function(__exports__) {
|
||||||
__exports__.default = Ember;
|
__exports__.default = Ember;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var _pluginCallbacks = [];
|
||||||
|
|
||||||
window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
rootElement: '#main',
|
rootElement: '#main',
|
||||||
_docTitle: document.title,
|
_docTitle: document.title,
|
||||||
|
@ -127,6 +129,18 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Plugins that are registered via `<script>` tags.
|
||||||
|
var withPluginApi = require('discourse/lib/plugin-api').withPluginApi;
|
||||||
|
var initCount = 0;
|
||||||
|
_pluginCallbacks.forEach(function(cb) {
|
||||||
|
Discourse.instanceInitializer({
|
||||||
|
name: "_discourse_plugin_" + (++initCount),
|
||||||
|
after: 'inject-objects',
|
||||||
|
initialize: function() {
|
||||||
|
withPluginApi(cb.version, cb.code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
requiresRefresh: function(){
|
requiresRefresh: function(){
|
||||||
|
@ -134,6 +148,9 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
return desired && Discourse.get("currentAssetVersion") !== desired;
|
return desired && Discourse.get("currentAssetVersion") !== desired;
|
||||||
}.property("currentAssetVersion", "desiredAssetVersion"),
|
}.property("currentAssetVersion", "desiredAssetVersion"),
|
||||||
|
|
||||||
|
_registerPluginCode(version, code) {
|
||||||
|
_pluginCallbacks.push({ version: version, code: code });
|
||||||
|
},
|
||||||
|
|
||||||
assetVersion: Ember.computed({
|
assetVersion: Ember.computed({
|
||||||
get: function() {
|
get: function() {
|
||||||
|
|
|
@ -27,6 +27,17 @@ class SiteCustomization < ActiveRecord::Base
|
||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def transpile(es6_source, version)
|
||||||
|
template = Tilt::ES6ModuleTranspilerTemplate.new {}
|
||||||
|
wrapped = <<PLUGIN_API_JS
|
||||||
|
Discourse._registerPluginCode('#{version}', api => {
|
||||||
|
#{es6_source}
|
||||||
|
});
|
||||||
|
PLUGIN_API_JS
|
||||||
|
|
||||||
|
template.babel_transpile(wrapped)
|
||||||
|
end
|
||||||
|
|
||||||
def process_html(html)
|
def process_html(html)
|
||||||
doc = Nokogiri::HTML.fragment(html)
|
doc = Nokogiri::HTML.fragment(html)
|
||||||
doc.css('script[type="text/x-handlebars"]').each do |node|
|
doc.css('script[type="text/x-handlebars"]').each do |node|
|
||||||
|
@ -43,6 +54,17 @@ SCRIPT
|
||||||
node.replace("<script>#{compiled}</script>")
|
node.replace("<script>#{compiled}</script>")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
doc.css('script[type="text/discourse-plugin"]').each do |node|
|
||||||
|
if node['version'].present?
|
||||||
|
begin
|
||||||
|
code = transpile(node.inner_html, node['version'])
|
||||||
|
node.replace("<script>#{code}</script>")
|
||||||
|
rescue Tilt::ES6ModuleTranspilerTemplate::JavaScriptError => ex
|
||||||
|
node.replace("<script type='text/discourse-js-error'>#{ex.message}</script>")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
doc.to_s
|
doc.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,14 @@ module Tilt
|
||||||
@@whitelisted.include?(path) || path =~ /discourse\/mixins/
|
@@whitelisted.include?(path) || path =~ /discourse\/mixins/
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def babel_transpile(source)
|
||||||
|
klass = self.class
|
||||||
|
klass.protect do
|
||||||
|
klass.v8['console'] = Console.new("BABEL: babel-eval: ")
|
||||||
|
@output = klass.v8.eval(babel_source(source))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def evaluate(scope, locals, &block)
|
def evaluate(scope, locals, &block)
|
||||||
return @output if @output
|
return @output if @output
|
||||||
|
|
||||||
|
@ -139,11 +147,15 @@ module Tilt
|
||||||
@output
|
@output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def babel_source(source)
|
||||||
|
js_source = ::JSON.generate(source, quirks_mode: true)
|
||||||
|
"babel.transform(#{js_source}, {ast: false, whitelist: ['es6.constants', 'es6.properties.shorthand', 'es6.arrowFunctions', 'es6.blockScoping', 'es6.destructuring', 'es6.spread', 'es6.parameters', 'es6.templateLiterals', 'es6.regex.unicode', 'es7.decorators', 'es6.classes']})['code']"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def generate_source(scope)
|
def generate_source(scope)
|
||||||
js_source = ::JSON.generate(data, quirks_mode: true)
|
js_source = babel_source(data)
|
||||||
js_source = "babel.transform(#{js_source}, {ast: false, whitelist: ['es6.constants', 'es6.properties.shorthand', 'es6.arrowFunctions', 'es6.blockScoping', 'es6.destructuring', 'es6.spread', 'es6.parameters', 'es6.templateLiterals', 'es6.regex.unicode', 'es7.decorators', 'es6.classes']})['code']"
|
|
||||||
"new module.exports.Compiler(#{js_source}, '#{module_name(scope.root_path, scope.logical_path)}', #{compiler_options}).#{compiler_method}()"
|
"new module.exports.Compiler(#{js_source}, '#{module_name(scope.root_path, scope.logical_path)}', #{compiler_options}).#{compiler_method}()"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -119,4 +119,37 @@ HTML
|
||||||
expect(SiteCustomization.custom_head_tag).to match(/<b>test<\/b>/)
|
expect(SiteCustomization.custom_head_tag).to match(/<b>test<\/b>/)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "plugin api" do
|
||||||
|
def transpile(html)
|
||||||
|
c = SiteCustomization.create!(user_id: -1, name: "test", head_tag: html, body_tag: html)
|
||||||
|
c.head_tag_baked
|
||||||
|
end
|
||||||
|
|
||||||
|
it "transpiles ES6 code" do
|
||||||
|
html = <<HTML
|
||||||
|
<script type='text/discourse-plugin' version='0.1'>
|
||||||
|
const x = 1;
|
||||||
|
</script>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
transpiled = transpile(html)
|
||||||
|
expect(transpiled).to match(/\<script\>/)
|
||||||
|
expect(transpiled).to match(/var x = 1;/)
|
||||||
|
expect(transpiled).to match(/_registerPluginCode\('0.1'/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "converts errors to a script type that is not evaluated" do
|
||||||
|
html = <<HTML
|
||||||
|
<script type='text/discourse-plugin' version='0.1'>
|
||||||
|
const x = 1;
|
||||||
|
x = 2;
|
||||||
|
</script>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
transpiled = transpile(html)
|
||||||
|
expect(transpiled).to match(/text\/discourse-js-error/)
|
||||||
|
expect(transpiled).to match(/read-only/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue