diff --git a/app/assets/javascripts/admin/helpers/check-icon.js b/app/assets/javascripts/admin/helpers/check-icon.js
index 88cddc3d4dc..4641a15fa2a 100644
--- a/app/assets/javascripts/admin/helpers/check-icon.js
+++ b/app/assets/javascripts/admin/helpers/check-icon.js
@@ -1,7 +1,8 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import { renderIcon } from "discourse-common/lib/icon-library";
+import { htmlSafe } from "@ember/template";
registerUnbound("check-icon", function(value) {
let icon = value ? "check" : "times";
- return new Handlebars.SafeString(renderIcon("string", icon));
+ return htmlSafe(renderIcon("string", icon));
});
diff --git a/app/assets/javascripts/admin/mixins/setting-component.js b/app/assets/javascripts/admin/mixins/setting-component.js
index 200ec00c1f8..e7afc119f27 100644
--- a/app/assets/javascripts/admin/mixins/setting-component.js
+++ b/app/assets/javascripts/admin/mixins/setting-component.js
@@ -7,6 +7,7 @@ import Mixin from "@ember/object/mixin";
import showModal from "discourse/lib/show-modal";
import { Promise } from "rsvp";
import { ajax } from "discourse/lib/ajax";
+import { htmlSafe } from "@ember/template";
const CUSTOM_TYPES = [
"bool",
@@ -63,7 +64,7 @@ export default Mixin.create({
}
let preview = setting.get("preview");
if (preview) {
- return new Handlebars.SafeString(
+ return htmlSafe(
"
" +
preview.replace(/\{\{value\}\}/g, value) +
"
"
diff --git a/app/assets/javascripts/discourse-common/addon/helpers/d-icon.js b/app/assets/javascripts/discourse-common/addon/helpers/d-icon.js
index 454bb224b06..97f93273d95 100644
--- a/app/assets/javascripts/discourse-common/addon/helpers/d-icon.js
+++ b/app/assets/javascripts/discourse-common/addon/helpers/d-icon.js
@@ -1,6 +1,7 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import { renderIcon } from "discourse-common/lib/icon-library";
+import { htmlSafe } from "@ember/template";
registerUnbound("d-icon", function(id, params) {
- return new Handlebars.SafeString(renderIcon("string", id, params));
+ return htmlSafe(renderIcon("string", id, params));
});
diff --git a/app/assets/javascripts/discourse-common/addon/helpers/fa-icon.js b/app/assets/javascripts/discourse-common/addon/helpers/fa-icon.js
index 1d657d086f1..12b1823cede 100644
--- a/app/assets/javascripts/discourse-common/addon/helpers/fa-icon.js
+++ b/app/assets/javascripts/discourse-common/addon/helpers/fa-icon.js
@@ -1,6 +1,7 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import { renderIcon } from "discourse-common/lib/icon-library";
import deprecated from "discourse-common/lib/deprecated";
+import { htmlSafe } from "@ember/template";
export function iconHTML(id, params) {
return renderIcon("string", id, params);
@@ -8,5 +9,5 @@ export function iconHTML(id, params) {
registerUnbound("fa-icon", function(icon, params) {
deprecated("Use `{{d-icon}}` instead of `{{fa-icon}}");
- return new Handlebars.SafeString(iconHTML(icon, params));
+ return htmlSafe(iconHTML(icon, params));
});
diff --git a/app/assets/javascripts/discourse-common/addon/lib/helpers.js b/app/assets/javascripts/discourse-common/addon/lib/helpers.js
index 0f87040d953..759cc8995ad 100644
--- a/app/assets/javascripts/discourse-common/addon/lib/helpers.js
+++ b/app/assets/javascripts/discourse-common/addon/lib/helpers.js
@@ -1,6 +1,7 @@
import { get } from "@ember/object";
import Helper from "@ember/component/helper";
import RawHandlebars from "discourse-common/lib/raw-handlebars";
+import { htmlSafe } from "@ember/template";
export function makeArray(obj) {
if (obj === null || obj === undefined) {
@@ -13,7 +14,7 @@ export function htmlHelper(fn) {
return Helper.helper(function(...args) {
args =
args.length > 1 ? args[0].concat({ hash: args[args.length - 1] }) : args;
- return new Handlebars.SafeString(fn.apply(this, args) || "");
+ return htmlSafe(fn.apply(this, args) || "");
});
}
diff --git a/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js b/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js
index ca08cfd476e..6fe75917464 100644
--- a/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js
+++ b/app/assets/javascripts/discourse-common/addon/lib/raw-handlebars.js
@@ -1,7 +1,8 @@
+import Handlebars from "handlebars";
+
// This is a mechanism for quickly rendering templates which is Ember aware
// templates are highly compatible with Ember so you don't need to worry about calling "get"
// and discourseComputed properties function, additionally it uses stringParams like Ember does
-
const RawHandlebars = Handlebars.create();
function buildPath(blk, args) {
diff --git a/app/assets/javascripts/discourse/app/components/create-topics-notice.js b/app/assets/javascripts/discourse/app/components/create-topics-notice.js
index 7789ccd2bc4..7db4e65df95 100644
--- a/app/assets/javascripts/discourse/app/components/create-topics-notice.js
+++ b/app/assets/javascripts/discourse/app/components/create-topics-notice.js
@@ -3,6 +3,7 @@ import { alias } from "@ember/object/computed";
import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators";
import LivePostCounts from "discourse/models/live-post-counts";
+import { htmlSafe } from "@ember/template";
export default Component.extend({
classNameBindings: ["hidden:hidden", ":create-topics-notice"],
@@ -81,7 +82,7 @@ export default Component.extend({
msg = "too_few_posts_notice_MF";
}
- return new Handlebars.SafeString(
+ return htmlSafe(
I18n.messageFormat(msg, {
requiredTopics: this.requiredTopics,
requiredPosts: this.requiredPosts,
diff --git a/app/assets/javascripts/discourse/app/helpers/category-link.js b/app/assets/javascripts/discourse/app/helpers/category-link.js
index d2141122e5e..7f566b576fa 100644
--- a/app/assets/javascripts/discourse/app/helpers/category-link.js
+++ b/app/assets/javascripts/discourse/app/helpers/category-link.js
@@ -5,6 +5,7 @@ import { iconHTML } from "discourse-common/lib/icon-library";
import Category from "discourse/models/category";
import Site from "discourse/models/site";
import { escapeExpression } from "discourse/lib/utilities";
+import { htmlSafe } from "@ember/template";
let _renderer = defaultCategoryLinkRenderer;
@@ -79,9 +80,7 @@ export function categoryLinkHTML(category, options) {
categoryOptions.recursive = true;
}
}
- return new Handlebars.SafeString(
- categoryBadgeHTML(category, categoryOptions)
- );
+ return htmlSafe(categoryBadgeHTML(category, categoryOptions));
}
registerUnbound("category-link", categoryLinkHTML);
diff --git a/app/assets/javascripts/discourse/app/helpers/custom-html.js b/app/assets/javascripts/discourse/app/helpers/custom-html.js
index fc055ee9b99..b9d424a2c9f 100644
--- a/app/assets/javascripts/discourse/app/helpers/custom-html.js
+++ b/app/assets/javascripts/discourse/app/helpers/custom-html.js
@@ -1,16 +1,17 @@
import PreloadStore from "preload-store";
+import { htmlSafe } from "@ember/template";
let _customizations = {};
export function getCustomHTML(key) {
const c = _customizations[key];
if (c) {
- return new Handlebars.SafeString(c);
+ return htmlSafe(c);
}
const html = PreloadStore.get("customHTML");
if (html && html[key] && html[key].length) {
- return new Handlebars.SafeString(html[key]);
+ return htmlSafe(html[key]);
}
}
diff --git a/app/assets/javascripts/discourse/app/helpers/discourse-tag.js b/app/assets/javascripts/discourse/app/helpers/discourse-tag.js
index 1477cf93367..9a560075315 100644
--- a/app/assets/javascripts/discourse/app/helpers/discourse-tag.js
+++ b/app/assets/javascripts/discourse/app/helpers/discourse-tag.js
@@ -1,6 +1,7 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import renderTag from "discourse/lib/render-tag";
+import { htmlSafe } from "@ember/template";
export default registerUnbound("discourse-tag", function(name, params) {
- return new Handlebars.SafeString(renderTag(name, params));
+ return htmlSafe(renderTag(name, params));
});
diff --git a/app/assets/javascripts/discourse/app/helpers/discourse-tags.js b/app/assets/javascripts/discourse/app/helpers/discourse-tags.js
index 6a7eb5e5c02..ba367e72811 100644
--- a/app/assets/javascripts/discourse/app/helpers/discourse-tags.js
+++ b/app/assets/javascripts/discourse/app/helpers/discourse-tags.js
@@ -1,6 +1,7 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import renderTags from "discourse/lib/render-tags";
+import { htmlSafe } from "@ember/template";
export default registerUnbound("discourse-tags", function(topic, params) {
- return new Handlebars.SafeString(renderTags(topic, params));
+ return htmlSafe(renderTags(topic, params));
});
diff --git a/app/assets/javascripts/discourse/app/helpers/format-date.js b/app/assets/javascripts/discourse/app/helpers/format-date.js
index fea8f452a70..1cb8c8fbd15 100644
--- a/app/assets/javascripts/discourse/app/helpers/format-date.js
+++ b/app/assets/javascripts/discourse/app/helpers/format-date.js
@@ -1,5 +1,6 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import { autoUpdatingRelativeAge } from "discourse/lib/formatter";
+import { htmlSafe } from "@ember/template";
/**
Display logic for dates. It is unbound in Ember but will use jQuery to
@@ -22,7 +23,7 @@ registerUnbound("format-date", function(val, params) {
if (val) {
var date = new Date(val);
- return new Handlebars.SafeString(
+ return htmlSafe(
autoUpdatingRelativeAge(date, {
format: format,
title: title,
diff --git a/app/assets/javascripts/discourse/app/helpers/raw-plugin-outlet.js b/app/assets/javascripts/discourse/app/helpers/raw-plugin-outlet.js
index 4aa8484a553..c03b8f66dc7 100644
--- a/app/assets/javascripts/discourse/app/helpers/raw-plugin-outlet.js
+++ b/app/assets/javascripts/discourse/app/helpers/raw-plugin-outlet.js
@@ -1,10 +1,11 @@
import { rawConnectorsFor } from "discourse/lib/plugin-connectors";
import RawHandlebars from "discourse-common/lib/raw-handlebars";
+import { htmlSafe } from "@ember/template";
RawHandlebars.registerHelper("raw-plugin-outlet", function(args) {
const connectors = rawConnectorsFor(args.hash.name);
if (connectors.length) {
const output = connectors.map(c => c.template({ context: this }));
- return new Handlebars.SafeString(output.join(""));
+ return htmlSafe(output.join(""));
}
});
diff --git a/app/assets/javascripts/discourse/app/helpers/raw.js b/app/assets/javascripts/discourse/app/helpers/raw.js
index db6b48d3849..f1fb8739273 100644
--- a/app/assets/javascripts/discourse/app/helpers/raw.js
+++ b/app/assets/javascripts/discourse/app/helpers/raw.js
@@ -1,5 +1,6 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import { findRawTemplate } from "discourse/lib/raw-templates";
+import { htmlSafe } from "@ember/template";
let _injections;
@@ -31,7 +32,7 @@ function renderRaw(ctx, container, template, templateName, params) {
}
}
- return new Handlebars.SafeString(template(params));
+ return htmlSafe(template(params));
}
registerUnbound("raw", function(templateName, params) {
diff --git a/app/assets/javascripts/discourse/app/helpers/topic-featured-link.js b/app/assets/javascripts/discourse/app/helpers/topic-featured-link.js
index 8316af884d5..ab31cc5ec4e 100644
--- a/app/assets/javascripts/discourse/app/helpers/topic-featured-link.js
+++ b/app/assets/javascripts/discourse/app/helpers/topic-featured-link.js
@@ -1,6 +1,7 @@
import { registerUnbound } from "discourse-common/lib/helpers";
import renderTopicFeaturedLink from "discourse/lib/render-topic-featured-link";
+import { htmlSafe } from "@ember/template";
export default registerUnbound("topic-featured-link", function(topic, params) {
- return new Handlebars.SafeString(renderTopicFeaturedLink(topic, params));
+ return htmlSafe(renderTopicFeaturedLink(topic, params));
});
diff --git a/app/assets/javascripts/discourse/app/helpers/topic-link.js b/app/assets/javascripts/discourse/app/helpers/topic-link.js
index 44f9d10d54f..bf8004a8885 100644
--- a/app/assets/javascripts/discourse/app/helpers/topic-link.js
+++ b/app/assets/javascripts/discourse/app/helpers/topic-link.js
@@ -1,4 +1,5 @@
import { registerUnbound } from "discourse-common/lib/helpers";
+import { htmlSafe } from "@ember/template";
registerUnbound("topic-link", (topic, args) => {
const title = topic.get("fancyTitle");
@@ -14,5 +15,5 @@ registerUnbound("topic-link", (topic, args) => {
const result = `${title}`;
- return new Handlebars.SafeString(result);
+ return htmlSafe(result);
});
diff --git a/app/assets/javascripts/discourse/app/helpers/user-avatar.js b/app/assets/javascripts/discourse/app/helpers/user-avatar.js
index 9d5f0cdc05b..0421799eceb 100644
--- a/app/assets/javascripts/discourse/app/helpers/user-avatar.js
+++ b/app/assets/javascripts/discourse/app/helpers/user-avatar.js
@@ -2,6 +2,7 @@ import { get } from "@ember/object";
import { registerUnbound } from "discourse-common/lib/helpers";
import { avatarImg, formatUsername } from "discourse/lib/utilities";
import { prioritizeNameInUx } from "discourse/lib/settings";
+import { htmlSafe } from "@ember/template";
let _customAvatarHelpers;
@@ -75,7 +76,7 @@ function renderAvatar(user, options) {
}
registerUnbound("avatar", function(user, params) {
- return new Handlebars.SafeString(renderAvatar.call(this, user, params));
+ return htmlSafe(renderAvatar.call(this, user, params));
});
export { renderAvatar };
diff --git a/app/assets/javascripts/discourse/app/lib/text.js b/app/assets/javascripts/discourse/app/lib/text.js
index 7f75cb497dc..867ecf9d328 100644
--- a/app/assets/javascripts/discourse/app/lib/text.js
+++ b/app/assets/javascripts/discourse/app/lib/text.js
@@ -5,6 +5,7 @@ import { sanitize as textSanitize } from "pretty-text/sanitizer";
import loadScript from "discourse/lib/load-script";
import { formatUsername } from "discourse/lib/utilities";
import { Promise } from "rsvp";
+import { htmlSafe } from "@ember/template";
function getOpts(opts) {
const siteSettings = Discourse.__container__.lookup("site-settings:main"),
@@ -26,7 +27,7 @@ function getOpts(opts) {
// Use this to easily create a pretty text instance with proper options
export function cook(text, options) {
- return new Handlebars.SafeString(createPrettyText(options).cook(text));
+ return htmlSafe(createPrettyText(options).cook(text));
}
// everything should eventually move to async API and this should be renamed
diff --git a/app/assets/javascripts/discourse/app/lib/utilities.js b/app/assets/javascripts/discourse/app/lib/utilities.js
index 03ef200016b..b848ca7f862 100644
--- a/app/assets/javascripts/discourse/app/lib/utilities.js
+++ b/app/assets/javascripts/discourse/app/lib/utilities.js
@@ -1,5 +1,6 @@
import { escape } from "pretty-text/sanitizer";
import toMarkdown from "discourse/lib/to-markdown";
+import Handlebars from "handlebars";
const homepageSelector = "meta[name=discourse_current_homepage]";
diff --git a/app/assets/javascripts/discourse/app/services/logs-notice.js b/app/assets/javascripts/discourse/app/services/logs-notice.js
index 7292e4465fc..217e1bad7ff 100644
--- a/app/assets/javascripts/discourse/app/services/logs-notice.js
+++ b/app/assets/javascripts/discourse/app/services/logs-notice.js
@@ -5,6 +5,7 @@ import discourseComputed, {
observes
} from "discourse-common/utils/decorators";
import { autoUpdatingRelativeAge } from "discourse/lib/formatter";
+import { htmlSafe } from "@ember/template";
const LOGS_NOTICE_KEY = "logs-notice-text";
@@ -53,7 +54,7 @@ const LogsNotice = EmberObject.extend({
@discourseComputed("text")
message(text) {
- return new Handlebars.SafeString(text);
+ return htmlSafe(text);
},
@discourseComputed("currentUser")
diff --git a/app/assets/javascripts/handlebars-shim.js b/app/assets/javascripts/handlebars-shim.js
new file mode 100644
index 00000000000..e01e17c49ee
--- /dev/null
+++ b/app/assets/javascripts/handlebars-shim.js
@@ -0,0 +1,9 @@
+// allow us to import this as a module
+if (typeof define !== "undefined") {
+ define("handlebars", ["exports"], function(__exports__) {
+ // It might not be defined server side, which is OK for pretty-text
+ if (typeof Handlebars !== "undefined") {
+ __exports__.default = Handlebars;
+ }
+ });
+}
diff --git a/app/assets/javascripts/pretty-text/sanitizer.js b/app/assets/javascripts/pretty-text/sanitizer.js
index d17ff4c178f..ceeeeaba9e9 100644
--- a/app/assets/javascripts/pretty-text/sanitizer.js
+++ b/app/assets/javascripts/pretty-text/sanitizer.js
@@ -24,7 +24,6 @@ function escapeChar(chr) {
}
export function escape(string) {
- // don't escape SafeStrings, since they're already safe
if (string === null) {
return "";
} else if (!string) {
diff --git a/app/assets/javascripts/template_include.js b/app/assets/javascripts/template_include.js
index 461d711ea31..e61120646eb 100644
--- a/app/assets/javascripts/template_include.js
+++ b/app/assets/javascripts/template_include.js
@@ -1 +1,2 @@
//= require handlebars.runtime
+//= require handlebars-shim
diff --git a/app/assets/javascripts/template_include.js.erb b/app/assets/javascripts/template_include.js.erb
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/config/application.rb b/config/application.rb
index 6bd11004ae6..0145ddbe7a0 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -171,6 +171,11 @@ module Discourse
# the exclusion list does not include hbs so you double compile all this stuff
initializer :fix_sprockets_loose_file_searcher, after: :set_default_precompile do |app|
app.config.assets.precompile.delete(Sprockets::Railtie::LOOSE_APP_ASSETS)
+
+ # We don't want application from node_modules, only from the root
+ app.config.assets.precompile.delete(/(?:\/|\\|\A)application\.(css|js)$/)
+ app.config.assets.precompile += ['application.js']
+
start_path = ::Rails.root.join("app/assets").to_s
exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '']
app.config.assets.precompile << lambda do |logical_path, filename|
diff --git a/lib/freedom_patches/raw_handlebars.rb b/lib/freedom_patches/raw_handlebars.rb
index 1242481f0e7..feaee4d0697 100644
--- a/lib/freedom_patches/raw_handlebars.rb
+++ b/lib/freedom_patches/raw_handlebars.rb
@@ -16,7 +16,7 @@ class Barber::Precompiler
transpiled = transpiler.perform(source)
# very hacky but lets us use ES6. I'm ashamed of this code -RW
- transpiled = transpiled[0...transpiled.index('export ')]
+ transpiled = transpiled[transpiled.index('var RawHandlebars = ')...transpiled.index('export ')]
@precompiler = StringIO.new <<~END
var __RawHandlebars;
diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb
index 8f260089efe..73c18d0099c 100644
--- a/lib/pretty_text.rb
+++ b/lib/pretty_text.rb
@@ -76,6 +76,7 @@ module PrettyText
ctx.eval("__PRETTY_TEXT = true")
ctx_load(ctx, "#{Rails.root}/app/assets/javascripts/discourse-loader.js")
+ ctx_load(ctx, "#{Rails.root}/app/assets/javascripts/handlebars-shim.js")
ctx_load(ctx, "vendor/assets/javascripts/lodash.js")
ctx_load_manifest(ctx, "pretty-text-bundle.js")
ctx_load_manifest(ctx, "markdown-it-bundle.js")