REFACTOR: PreloadStore to ES6

This commit is contained in:
Robin Ward 2016-07-04 14:15:51 -04:00
parent 25d6915cac
commit bba0fd0654
33 changed files with 149 additions and 141 deletions

View File

@ -1,7 +1,6 @@
app/assets/javascripts/env.js app/assets/javascripts/env.js
app/assets/javascripts/main_include.js app/assets/javascripts/main_include.js
app/assets/javascripts/main_include_admin.js app/assets/javascripts/main_include_admin.js
app/assets/javascripts/preload_store.js
app/assets/javascripts/pagedown_custom.js app/assets/javascripts/pagedown_custom.js
app/assets/javascripts/vendor.js app/assets/javascripts/vendor.js
app/assets/javascripts/locales/i18n.js app/assets/javascripts/locales/i18n.js

View File

@ -14,7 +14,6 @@
"RSVP":true, "RSVP":true,
"Discourse":true, "Discourse":true,
"Em":true, "Em":true,
"PreloadStore":true,
"Handlebars":true, "Handlebars":true,
"I18n":true, "I18n":true,
"bootbox":true, "bootbox":true,

View File

@ -1,4 +1,6 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import PreloadStore from 'preload-store';
const Backup = Discourse.Model.extend({ const Backup = Discourse.Model.extend({
destroy() { destroy() {

View File

@ -1,3 +1,5 @@
import PreloadStore from 'preload-store';
export default Ember.Route.extend({ export default Ember.Route.extend({
// since the logs are pushed via the message bus // since the logs are pushed via the message bus

View File

@ -2,6 +2,7 @@ import { ajax } from 'discourse/lib/ajax';
import showModal from 'discourse/lib/show-modal'; import showModal from 'discourse/lib/show-modal';
import BackupStatus from 'admin/models/backup-status'; import BackupStatus from 'admin/models/backup-status';
import Backup from 'admin/models/backup'; import Backup from 'admin/models/backup';
import PreloadStore from 'preload-store';
const LOG_CHANNEL = "/admin/backups/logs"; const LOG_CHANNEL = "/admin/backups/logs";

View File

@ -1,5 +1,6 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import RestAdapter from 'discourse/adapters/rest'; import RestAdapter from 'discourse/adapters/rest';
import PreloadStore from 'preload-store';
export function finderFor(filter, params) { export function finderFor(filter, params) {
return function() { return function() {

View File

@ -1,4 +1,5 @@
import { registerHelper } from 'discourse/lib/helpers'; import { registerHelper } from 'discourse/lib/helpers';
import PreloadStore from 'preload-store';
const _customizations = {}; const _customizations = {};

View File

@ -1,3 +1,5 @@
import PreloadStore from 'preload-store';
export default { export default {
name: "banner", name: "banner",
after: "message-bus", after: "message-bus",

View File

@ -1,5 +1,6 @@
import { withPluginApi } from 'discourse/lib/plugin-api'; import { withPluginApi } from 'discourse/lib/plugin-api';
import { registerEmoji } from 'pretty-text/emoji'; import { registerEmoji } from 'pretty-text/emoji';
import PreloadStore from 'preload-store';
export default { export default {
name: 'enable-emoji', name: 'enable-emoji',

View File

@ -1,3 +1,5 @@
import PreloadStore from 'preload-store';
export default { export default {
name: 'localization', name: 'localization',
after: 'inject-objects', after: 'inject-objects',

View File

@ -133,32 +133,37 @@ if (Handlebars.Compiler) {
var environment = new RawHandlebars.Compiler().compile(ast, options); var environment = new RawHandlebars.Compiler().compile(ast, options);
var templateSpec = new RawHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true); var templateSpec = new RawHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
var template = RawHandlebars.template(templateSpec); var t = RawHandlebars.template(templateSpec);
template.isMethod = false; t.isMethod = false;
return template; return t;
};
RawHandlebars.get = function(ctx, property, options) {
if (options.types && options.data.view) {
var view = options.data.view;
return view.getStream ? view.getStream(property).value() : view.getAttr(property);
} else {
return Ember.get(ctx, property);
}
}; };
} }
export function precompile(value, asObject) {
return RawHandlebars.precompile(value, asObject); RawHandlebars.get = function(ctx, property, options) {
if (options.types && options.data.view) {
var view = options.data.view;
return view.getStream ? view.getStream(property).value() : view.getAttr(property);
} else {
return Ember.get(ctx, property);
}
};
export function template() {
return RawHandlebars.template.apply(this, arguments);
} }
export function compile(string) { export function precompile() {
return RawHandlebars.compile(string); return RawHandlebars.precompile.apply(this, arguments);
} }
export function get(ctx, property, options) { export function compile() {
return RawHandlebars.get(ctx, property, options); return RawHandlebars.compile.apply(this, arguments);
}
export function get() {
return RawHandlebars.get.apply(this, arguments);
} }
export default RawHandlebars; export default RawHandlebars;

View File

@ -1,3 +1,4 @@
import PreloadStore from 'preload-store';
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
const CategoryList = Ember.ArrayProxy.extend({ const CategoryList = Ember.ArrayProxy.extend({

View File

@ -3,6 +3,7 @@ import Archetype from 'discourse/models/archetype';
import PostActionType from 'discourse/models/post-action-type'; import PostActionType from 'discourse/models/post-action-type';
import Singleton from 'discourse/mixins/singleton'; import Singleton from 'discourse/mixins/singleton';
import RestModel from 'discourse/models/rest'; import RestModel from 'discourse/models/rest';
import PreloadStore from 'preload-store';
const Site = RestModel.extend({ const Site = RestModel.extend({

View File

@ -2,6 +2,7 @@ import { NotificationLevels } from 'discourse/lib/notification-levels';
import computed from "ember-addons/ember-computed-decorators"; import computed from "ember-addons/ember-computed-decorators";
import { on } from "ember-addons/ember-computed-decorators"; import { on } from "ember-addons/ember-computed-decorators";
import { defaultHomepage } from 'discourse/lib/utilities'; import { defaultHomepage } from 'discourse/lib/utilities';
import PreloadStore from 'preload-store';
function isNew(topic) { function isNew(topic) {
return topic.last_read_post_number === null && return topic.last_read_post_number === null &&

View File

@ -8,6 +8,7 @@ import ActionSummary from 'discourse/models/action-summary';
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from 'discourse/lib/ajax-error';
import { censor } from 'pretty-text/censored-words'; import { censor } from 'pretty-text/censored-words';
import { emojiUnescape } from 'discourse/lib/text'; import { emojiUnescape } from 'discourse/lib/text';
import PreloadStore from 'preload-store';
export function loadTopicView(topic, args) { export function loadTopicView(topic, args) {
const topicId = topic.get('id'); const topicId = topic.get('id');

View File

@ -13,6 +13,7 @@ import UserAction from 'discourse/models/user-action';
import Group from 'discourse/models/group'; import Group from 'discourse/models/group';
import Topic from 'discourse/models/topic'; import Topic from 'discourse/models/topic';
import { emojiUnescape } from 'discourse/lib/text'; import { emojiUnescape } from 'discourse/lib/text';
import PreloadStore from 'preload-store';
const User = RestModel.extend({ const User = RestModel.extend({

View File

@ -1,4 +1,5 @@
import Badge from 'discourse/models/badge'; import Badge from 'discourse/models/badge';
import PreloadStore from 'preload-store';
export default Discourse.Route.extend({ export default Discourse.Route.extend({
model() { model() {

View File

@ -1,5 +1,6 @@
import UserBadge from 'discourse/models/user-badge'; import UserBadge from 'discourse/models/user-badge';
import Badge from 'discourse/models/badge'; import Badge from 'discourse/models/badge';
import PreloadStore from 'preload-store';
export default Discourse.Route.extend({ export default Discourse.Route.extend({
queryParams: { queryParams: {

View File

@ -2,6 +2,7 @@ import showModal from "discourse/lib/show-modal";
import OpenComposer from "discourse/mixins/open-composer"; import OpenComposer from "discourse/mixins/open-composer";
import CategoryList from "discourse/models/category-list"; import CategoryList from "discourse/models/category-list";
import { defaultHomepage } from 'discourse/lib/utilities'; import { defaultHomepage } from 'discourse/lib/utilities';
import PreloadStore from 'preload-store';
const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, { const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
renderTemplate() { renderTemplate() {

View File

@ -1,6 +1,7 @@
import { ajax } from 'discourse/lib/ajax'; import { ajax } from 'discourse/lib/ajax';
import { translateResults, getSearchKey, isValidSearchTerm } from "discourse/lib/search"; import { translateResults, getSearchKey, isValidSearchTerm } from "discourse/lib/search";
import Composer from 'discourse/models/composer'; import Composer from 'discourse/models/composer';
import PreloadStore from 'preload-store';
export default Discourse.Route.extend({ export default Discourse.Route.extend({
queryParams: { q: {}, context_id: {}, context: {}, skip_context: {} }, queryParams: { q: {}, context_id: {}, context: {}, skip_context: {} },

View File

@ -0,0 +1,54 @@
/**
We can insert data into the PreloadStore when the document is loaded.
The data can be accessed once by a key, after which it is removed
@class PreloadStore
**/
export default {
data: {},
store(key, value) {
this.data[key] = value;
},
/**
To retrieve a key, you provide the key you want, plus a finder to load
it if the key cannot be found. Once the key is used once, it is removed
from the store.
So, for example, you can't load a preloaded topic more than once.
**/
getAndRemove(key, finder) {
if (this.data[key]) {
var promise = Em.RSVP.resolve(this.data[key]);
delete this.data[key];
return promise;
}
if (finder) {
return new Ember.RSVP.Promise(function(resolve, reject) {
var result = finder();
// If the finder returns a promise, we support that too
if (result && result.then) {
result.then(toResolve => resolve(toResolve)).catch(toReject => reject(toReject));
} else {
resolve(result);
}
});
}
return Ember.RSVP.resolve(null);
},
get(key) {
return this.data[key];
},
remove(key) {
if (this.data[key]) delete this.data[key];
},
reset() {
this.data = {};
}
};

View File

@ -1,90 +0,0 @@
/**
We can insert data into the PreloadStore when the document is loaded.
The data can be accessed once by a key, after which it is removed
@class PreloadStore
**/
window.PreloadStore = {
data: {},
/**
Store an object in the store
@method store
@param {String} key the key to store the object with
@param {String} value the object we're inserting into the store
**/
store: function(key, value) {
this.data[key] = value;
},
/**
To retrieve a key, you provide the key you want, plus a finder to load
it if the key cannot be found. Once the key is used once, it is removed
from the store.
So, for example, you can't load a preloaded topic more than once.
@method getAndRemove
@param {String} key the key to look up the object with
@param {function} finder a function to find the object with
@returns {Promise} a promise that will eventually be the object we want.
**/
getAndRemove: function(key, finder) {
if (this.data[key]) {
var promise = Em.RSVP.resolve(this.data[key]);
delete this.data[key];
return promise;
}
if (finder) {
return new Ember.RSVP.Promise(function(resolve, reject) {
var result = finder();
// If the finder returns a promise, we support that too
if (result && result.then) {
result.then(function(result) {
return resolve(result);
}, function(result) {
return reject(result);
});
} else {
resolve(result);
}
});
}
return Ember.RSVP.resolve(null);
},
/**
If we are sure it's preloaded, we don't have to supply a finder.
Just returns undefined if it's not in the store.
@method get
@param {String} key the key to look up the object with
@returns {Object} the object from the store
**/
"get": function(key) {
return this.data[key];
},
/**
Removes the stored value if the key exists
@method remove
@param {String} key the key to remove
**/
remove: function(key) {
if (this.data[key]) delete this.data[key];
},
/**
Resets the contents of the store. Used in testing.
**/
reset: function() {
this.data = {};
}
};

View File

@ -60,13 +60,12 @@ export function sanitize(text, whiteLister) {
const whiteList = whiteLister.getWhiteList(); const whiteList = whiteLister.getWhiteList();
let hadIframe = false;
let result = xss(text, { let result = xss(text, {
whiteList: whiteList.tagList, whiteList: whiteList.tagList,
stripIgnoreTag: true, stripIgnoreTag: true,
stripIgnoreTagBody: ['script', 'table'], stripIgnoreTagBody: ['script', 'table'],
onIgnoreTagAttr(tag, name, value) { onIgnoreTagAttr(tag, name, value) {
hadIframe = hadIframe || tag === 'iframe';
const forTag = whiteList.attrList[tag]; const forTag = whiteList.attrList[tag];
if (forTag) { if (forTag) {
const forAttr = forTag[name]; const forAttr = forTag[name];

View File

@ -39,23 +39,27 @@
}); });
<%- end %> <%- end %>
Discourse.CDN = '<%= Rails.configuration.action_controller.asset_host %>'; (function() {
Discourse.BaseUrl = '<%= RailsMultisite::ConnectionManagement.current_hostname %>'.replace(/:[\d]*$/,""); var ps = require('preload-store').default;
Discourse.BaseUri = '<%= Discourse::base_uri %>';
Discourse.Environment = '<%= Rails.env %>'; Discourse.CDN = '<%= Rails.configuration.action_controller.asset_host %>';
Discourse.SiteSettings = PreloadStore.get('siteSettings'); Discourse.BaseUrl = '<%= RailsMultisite::ConnectionManagement.current_hostname %>'.replace(/:[\d]*$/,"");
Discourse.LetterAvatarVersion = '<%= LetterAvatar.version %>'; Discourse.BaseUri = '<%= Discourse::base_uri %>';
I18n.defaultLocale = '<%= SiteSetting.default_locale %>'; Discourse.Environment = '<%= Rails.env %>';
Discourse.start(); Discourse.SiteSettings = ps.get('siteSettings');
Discourse.set('assetVersion','<%= Discourse.assets_digest %>'); Discourse.LetterAvatarVersion = '<%= LetterAvatar.version %>';
Discourse.Session.currentProp("disableCustomCSS", <%= loading_admin? %>); I18n.defaultLocale = '<%= SiteSetting.default_locale %>';
Discourse.HighlightJSPath = <%= HighlightJs.path.inspect.html_safe %>; Discourse.start();
<%- if SiteSetting.enable_s3_uploads %> Discourse.set('assetVersion','<%= Discourse.assets_digest %>');
<%- if SiteSetting.s3_cdn_url.present? %> Discourse.Session.currentProp("disableCustomCSS", <%= loading_admin? %>);
Discourse.S3CDN = '<%= SiteSetting.s3_cdn_url %>'; Discourse.HighlightJSPath = <%= HighlightJs.path.inspect.html_safe %>;
<%- if SiteSetting.enable_s3_uploads %>
<%- if SiteSetting.s3_cdn_url.present? %>
Discourse.S3CDN = '<%= SiteSetting.s3_cdn_url %>';
<%- end %>
Discourse.S3BaseUrl = '<%= Discourse.store.absolute_base_url %>';
<%- end %> <%- end %>
Discourse.S3BaseUrl = '<%= Discourse.store.absolute_base_url %>'; })();
<%- end %>
</script> </script>
<%= script 'browser-update' %> <%= script 'browser-update' %>

View File

@ -22,9 +22,9 @@
window.EmberENV['FORCE_JQUERY'] = true; window.EmberENV['FORCE_JQUERY'] = true;
</script> </script>
<%= script "preload_store" %>
<%= script "locales/#{I18n.locale}" %> <%= script "locales/#{I18n.locale}" %>
<%= script "ember_jquery" %> <%= script "ember_jquery" %>
<%= script "preload-store" %>
<%= script "vendor" %> <%= script "vendor" %>
<%= script "pretty-text-bundle" %> <%= script "pretty-text-bundle" %>
<%= script "application" %> <%= script "application" %>
@ -89,9 +89,12 @@
<%- if @preloaded.present? %> <%- if @preloaded.present? %>
<script> <script>
<%- @preloaded.each do |key, json| %> (function() {
PreloadStore.store("<%= key %>",<%= escape_unicode(json) %>); var ps = require('preload-store').default;
<% end %> <%- @preloaded.each do |key, json| %>
ps.store("<%= key %>", <%= escape_unicode(json) %>);
<% end %>
})();
</script> </script>
<%- end %> <%- end %>

View File

@ -70,7 +70,7 @@ module Discourse
end] end]
config.assets.precompile += ['vendor.js', 'common.css', 'desktop.css', 'mobile.css', config.assets.precompile += ['vendor.js', 'common.css', 'desktop.css', 'mobile.css',
'admin.js', 'admin.css', 'shiny/shiny.css', 'preload_store.js', 'admin.js', 'admin.css', 'shiny/shiny.css', 'preload-store.js.es6',
'browser-update.js', 'embed.css', 'break_string.js', 'ember_jquery.js', 'browser-update.js', 'embed.css', 'break_string.js', 'ember_jquery.js',
'pretty-text-bundle.js'] 'pretty-text-bundle.js']

View File

@ -40,7 +40,7 @@ module Discourse
module Handlebars module Handlebars
module Helper module Helper
def precompile_handlebars(string) def precompile_handlebars(string)
"Discourse.EmberCompatHandlebars.template(#{Barber::Precompiler.compile(string)});" "require('discourse/lib/raw-handlebars').template(#{Barber::Precompiler.compile(string)});"
end end
def compile_handlebars(string) def compile_handlebars(string)

View File

@ -1 +0,0 @@
PreloadStore.store("currentUser", {"id":42,"username":"eviltrout","avatar_template":"//www.gravatar.com/avatar/c6e17f2ae2a215e87ff9e878a4e63cd9.png?s={size}&r=pg&d=identicon","name":"Evil Trout","unread_notifications":0,"unread_private_messages":0,"admin":false,"notification_channel_position":null,"site_flagged_posts_count":0,"moderator":false,"staff":false,"reply_count":0,"topic_count":0,"enable_quoting":true,"external_links_in_new_tab":false,"dynamic_favicon":false,"trust_level":0,"can_edit":true});

View File

@ -1,4 +1,6 @@
import { blank } from 'helpers/qunit-helpers'; import { blank } from 'helpers/qunit-helpers';
import PreloadStore from 'preload-store';
module("helper:custom-html"); module("helper:custom-html");
import { getCustomHTML, setCustomHTML } from 'discourse/helpers/custom-html'; import { getCustomHTML, setCustomHTML } from 'discourse/helpers/custom-html';
@ -11,5 +13,4 @@ test("customHTML", function() {
PreloadStore.store('customHTML', {cookie: 'monster'}); PreloadStore.store('customHTML', {cookie: 'monster'});
equal(getCustomHTML('cookie'), 'monster', 'it returns HTML fragments from the PreloadStore'); equal(getCustomHTML('cookie'), 'monster', 'it returns HTML fragments from the PreloadStore');
}); });

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,8 @@
import { blank } from 'helpers/qunit-helpers'; import { blank } from 'helpers/qunit-helpers';
import PreloadStore from 'preload-store';
module("Discourse.PreloadStore", { module("preload-store", {
setup: function() { setup() {
PreloadStore.store('bane', 'evil'); PreloadStore.store('bane', 'evil');
} }
}); });

View File

@ -1,7 +1,6 @@
/*global document, sinon, QUnit, Logster */ /*global document, sinon, QUnit, Logster */
//= require env //= require env
//= require preload_store
//= require probes //= require probes
//= require jquery.debug //= require jquery.debug
//= require jquery.ui.widget //= require jquery.ui.widget
@ -14,6 +13,7 @@
//= require route-recognizer //= require route-recognizer
//= require pretender //= require pretender
//= require loader //= require loader
//= require preload-store
//= require locales/i18n //= require locales/i18n
//= require locales/en //= require locales/en
@ -41,6 +41,7 @@
// //
//= require jquery.magnific-popup-min.js //= require jquery.magnific-popup-min.js
window.TestPreloadStore = require('preload-store').default;
window.inTestEnv = true; window.inTestEnv = true;
// Stop the message bus so we don't get ajax calls // Stop the message bus so we don't get ajax calls
@ -75,6 +76,13 @@ function dup(obj) {
return jQuery.extend(true, {}, obj); return jQuery.extend(true, {}, obj);
} }
function resetSite() {
var createStore = require('helpers/create-store').default;
var siteAttrs = dup(fixtures['site.json'].site);
siteAttrs.store = createStore();
Discourse.Site.resetCurrent(Discourse.Site.create(siteAttrs));
}
QUnit.testStart(function(ctx) { QUnit.testStart(function(ctx) {
server = createPretendServer(); server = createPretendServer();
@ -84,14 +92,15 @@ QUnit.testStart(function(ctx) {
Discourse.BaseUrl = "localhost"; Discourse.BaseUrl = "localhost";
Discourse.Session.resetCurrent(); Discourse.Session.resetCurrent();
Discourse.User.resetCurrent(); Discourse.User.resetCurrent();
Discourse.Site.resetCurrent(Discourse.Site.create(dup(fixtures['site.json'].site))); resetSite();
_DiscourseURL.redirectedTo = null; _DiscourseURL.redirectedTo = null;
_DiscourseURL.redirectTo = function(url) { _DiscourseURL.redirectTo = function(url) {
_DiscourseURL.redirectedTo = url; _DiscourseURL.redirectedTo = url;
}; };
PreloadStore.reset(); var ps = require('preload-store').default;
ps.reset();
window.sandbox = sinon.sandbox.create(); window.sandbox = sinon.sandbox.create();
window.sandbox.stub(ScrollingDOMMethods, "screenNotFull"); window.sandbox.stub(ScrollingDOMMethods, "screenNotFull");
@ -132,4 +141,5 @@ Object.keys(requirejs.entries).forEach(function(entry) {
} }
}); });
require('mdtest/mdtest', null, null, true); require('mdtest/mdtest', null, null, true);
resetSite();

1
vendor/assets/javascripts/xss.min.js vendored Normal file

File diff suppressed because one or more lines are too long