mirror of
https://github.com/discourse/discourse.git
synced 2025-05-24 00:31:23 +08:00
DEV: Support for import Handlebars from 'handlebars'
; (#9600)
* Remove Handlebars.SafeString usage * DEV: Support for `import Handlebars from 'handlebars'`; * FIX: Sprockets was broken when `node_modules` was present By default the old version of sprockets looks for application.js anywhere, including in a node_modules folder if this exists (which it will when we move to Ember CLI.)
This commit is contained in:
@ -1,7 +1,8 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import { renderIcon } from "discourse-common/lib/icon-library";
|
import { renderIcon } from "discourse-common/lib/icon-library";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
registerUnbound("check-icon", function(value) {
|
registerUnbound("check-icon", function(value) {
|
||||||
let icon = value ? "check" : "times";
|
let icon = value ? "check" : "times";
|
||||||
return new Handlebars.SafeString(renderIcon("string", icon));
|
return htmlSafe(renderIcon("string", icon));
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ import Mixin from "@ember/object/mixin";
|
|||||||
import showModal from "discourse/lib/show-modal";
|
import showModal from "discourse/lib/show-modal";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
const CUSTOM_TYPES = [
|
const CUSTOM_TYPES = [
|
||||||
"bool",
|
"bool",
|
||||||
@ -63,7 +64,7 @@ export default Mixin.create({
|
|||||||
}
|
}
|
||||||
let preview = setting.get("preview");
|
let preview = setting.get("preview");
|
||||||
if (preview) {
|
if (preview) {
|
||||||
return new Handlebars.SafeString(
|
return htmlSafe(
|
||||||
"<div class='preview'>" +
|
"<div class='preview'>" +
|
||||||
preview.replace(/\{\{value\}\}/g, value) +
|
preview.replace(/\{\{value\}\}/g, value) +
|
||||||
"</div>"
|
"</div>"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import { renderIcon } from "discourse-common/lib/icon-library";
|
import { renderIcon } from "discourse-common/lib/icon-library";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
registerUnbound("d-icon", function(id, params) {
|
registerUnbound("d-icon", function(id, params) {
|
||||||
return new Handlebars.SafeString(renderIcon("string", id, params));
|
return htmlSafe(renderIcon("string", id, params));
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import { renderIcon } from "discourse-common/lib/icon-library";
|
import { renderIcon } from "discourse-common/lib/icon-library";
|
||||||
import deprecated from "discourse-common/lib/deprecated";
|
import deprecated from "discourse-common/lib/deprecated";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
export function iconHTML(id, params) {
|
export function iconHTML(id, params) {
|
||||||
return renderIcon("string", id, params);
|
return renderIcon("string", id, params);
|
||||||
@ -8,5 +9,5 @@ export function iconHTML(id, params) {
|
|||||||
|
|
||||||
registerUnbound("fa-icon", function(icon, params) {
|
registerUnbound("fa-icon", function(icon, params) {
|
||||||
deprecated("Use `{{d-icon}}` instead of `{{fa-icon}}");
|
deprecated("Use `{{d-icon}}` instead of `{{fa-icon}}");
|
||||||
return new Handlebars.SafeString(iconHTML(icon, params));
|
return htmlSafe(iconHTML(icon, params));
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { get } from "@ember/object";
|
import { get } from "@ember/object";
|
||||||
import Helper from "@ember/component/helper";
|
import Helper from "@ember/component/helper";
|
||||||
import RawHandlebars from "discourse-common/lib/raw-handlebars";
|
import RawHandlebars from "discourse-common/lib/raw-handlebars";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
export function makeArray(obj) {
|
export function makeArray(obj) {
|
||||||
if (obj === null || obj === undefined) {
|
if (obj === null || obj === undefined) {
|
||||||
@ -13,7 +14,7 @@ export function htmlHelper(fn) {
|
|||||||
return Helper.helper(function(...args) {
|
return Helper.helper(function(...args) {
|
||||||
args =
|
args =
|
||||||
args.length > 1 ? args[0].concat({ hash: args[args.length - 1] }) : 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) || "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import Handlebars from "handlebars";
|
||||||
|
|
||||||
// This is a mechanism for quickly rendering templates which is Ember aware
|
// 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"
|
// 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
|
// and discourseComputed properties function, additionally it uses stringParams like Ember does
|
||||||
|
|
||||||
const RawHandlebars = Handlebars.create();
|
const RawHandlebars = Handlebars.create();
|
||||||
|
|
||||||
function buildPath(blk, args) {
|
function buildPath(blk, args) {
|
||||||
|
@ -3,6 +3,7 @@ import { alias } from "@ember/object/computed";
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import { observes } from "discourse-common/utils/decorators";
|
import { observes } from "discourse-common/utils/decorators";
|
||||||
import LivePostCounts from "discourse/models/live-post-counts";
|
import LivePostCounts from "discourse/models/live-post-counts";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNameBindings: ["hidden:hidden", ":create-topics-notice"],
|
classNameBindings: ["hidden:hidden", ":create-topics-notice"],
|
||||||
@ -81,7 +82,7 @@ export default Component.extend({
|
|||||||
msg = "too_few_posts_notice_MF";
|
msg = "too_few_posts_notice_MF";
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Handlebars.SafeString(
|
return htmlSafe(
|
||||||
I18n.messageFormat(msg, {
|
I18n.messageFormat(msg, {
|
||||||
requiredTopics: this.requiredTopics,
|
requiredTopics: this.requiredTopics,
|
||||||
requiredPosts: this.requiredPosts,
|
requiredPosts: this.requiredPosts,
|
||||||
|
@ -5,6 +5,7 @@ import { iconHTML } from "discourse-common/lib/icon-library";
|
|||||||
import Category from "discourse/models/category";
|
import Category from "discourse/models/category";
|
||||||
import Site from "discourse/models/site";
|
import Site from "discourse/models/site";
|
||||||
import { escapeExpression } from "discourse/lib/utilities";
|
import { escapeExpression } from "discourse/lib/utilities";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
let _renderer = defaultCategoryLinkRenderer;
|
let _renderer = defaultCategoryLinkRenderer;
|
||||||
|
|
||||||
@ -79,9 +80,7 @@ export function categoryLinkHTML(category, options) {
|
|||||||
categoryOptions.recursive = true;
|
categoryOptions.recursive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Handlebars.SafeString(
|
return htmlSafe(categoryBadgeHTML(category, categoryOptions));
|
||||||
categoryBadgeHTML(category, categoryOptions)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerUnbound("category-link", categoryLinkHTML);
|
registerUnbound("category-link", categoryLinkHTML);
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import PreloadStore from "preload-store";
|
import PreloadStore from "preload-store";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
let _customizations = {};
|
let _customizations = {};
|
||||||
|
|
||||||
export function getCustomHTML(key) {
|
export function getCustomHTML(key) {
|
||||||
const c = _customizations[key];
|
const c = _customizations[key];
|
||||||
if (c) {
|
if (c) {
|
||||||
return new Handlebars.SafeString(c);
|
return htmlSafe(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
const html = PreloadStore.get("customHTML");
|
const html = PreloadStore.get("customHTML");
|
||||||
if (html && html[key] && html[key].length) {
|
if (html && html[key] && html[key].length) {
|
||||||
return new Handlebars.SafeString(html[key]);
|
return htmlSafe(html[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import renderTag from "discourse/lib/render-tag";
|
import renderTag from "discourse/lib/render-tag";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
export default registerUnbound("discourse-tag", function(name, params) {
|
export default registerUnbound("discourse-tag", function(name, params) {
|
||||||
return new Handlebars.SafeString(renderTag(name, params));
|
return htmlSafe(renderTag(name, params));
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import renderTags from "discourse/lib/render-tags";
|
import renderTags from "discourse/lib/render-tags";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
export default registerUnbound("discourse-tags", function(topic, params) {
|
export default registerUnbound("discourse-tags", function(topic, params) {
|
||||||
return new Handlebars.SafeString(renderTags(topic, params));
|
return htmlSafe(renderTags(topic, params));
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import { autoUpdatingRelativeAge } from "discourse/lib/formatter";
|
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
|
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) {
|
if (val) {
|
||||||
var date = new Date(val);
|
var date = new Date(val);
|
||||||
return new Handlebars.SafeString(
|
return htmlSafe(
|
||||||
autoUpdatingRelativeAge(date, {
|
autoUpdatingRelativeAge(date, {
|
||||||
format: format,
|
format: format,
|
||||||
title: title,
|
title: title,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { rawConnectorsFor } from "discourse/lib/plugin-connectors";
|
import { rawConnectorsFor } from "discourse/lib/plugin-connectors";
|
||||||
import RawHandlebars from "discourse-common/lib/raw-handlebars";
|
import RawHandlebars from "discourse-common/lib/raw-handlebars";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
RawHandlebars.registerHelper("raw-plugin-outlet", function(args) {
|
RawHandlebars.registerHelper("raw-plugin-outlet", function(args) {
|
||||||
const connectors = rawConnectorsFor(args.hash.name);
|
const connectors = rawConnectorsFor(args.hash.name);
|
||||||
if (connectors.length) {
|
if (connectors.length) {
|
||||||
const output = connectors.map(c => c.template({ context: this }));
|
const output = connectors.map(c => c.template({ context: this }));
|
||||||
return new Handlebars.SafeString(output.join(""));
|
return htmlSafe(output.join(""));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import { findRawTemplate } from "discourse/lib/raw-templates";
|
import { findRawTemplate } from "discourse/lib/raw-templates";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
let _injections;
|
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) {
|
registerUnbound("raw", function(templateName, params) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import renderTopicFeaturedLink from "discourse/lib/render-topic-featured-link";
|
import renderTopicFeaturedLink from "discourse/lib/render-topic-featured-link";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
export default registerUnbound("topic-featured-link", function(topic, params) {
|
export default registerUnbound("topic-featured-link", function(topic, params) {
|
||||||
return new Handlebars.SafeString(renderTopicFeaturedLink(topic, params));
|
return htmlSafe(renderTopicFeaturedLink(topic, params));
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
registerUnbound("topic-link", (topic, args) => {
|
registerUnbound("topic-link", (topic, args) => {
|
||||||
const title = topic.get("fancyTitle");
|
const title = topic.get("fancyTitle");
|
||||||
@ -14,5 +15,5 @@ registerUnbound("topic-link", (topic, args) => {
|
|||||||
const result = `<a href='${url}'
|
const result = `<a href='${url}'
|
||||||
class='${classes.join(" ")}'
|
class='${classes.join(" ")}'
|
||||||
data-topic-id='${topic.id}'>${title}</a>`;
|
data-topic-id='${topic.id}'>${title}</a>`;
|
||||||
return new Handlebars.SafeString(result);
|
return htmlSafe(result);
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ import { get } from "@ember/object";
|
|||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
import { avatarImg, formatUsername } from "discourse/lib/utilities";
|
import { avatarImg, formatUsername } from "discourse/lib/utilities";
|
||||||
import { prioritizeNameInUx } from "discourse/lib/settings";
|
import { prioritizeNameInUx } from "discourse/lib/settings";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
let _customAvatarHelpers;
|
let _customAvatarHelpers;
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ function renderAvatar(user, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerUnbound("avatar", function(user, params) {
|
registerUnbound("avatar", function(user, params) {
|
||||||
return new Handlebars.SafeString(renderAvatar.call(this, user, params));
|
return htmlSafe(renderAvatar.call(this, user, params));
|
||||||
});
|
});
|
||||||
|
|
||||||
export { renderAvatar };
|
export { renderAvatar };
|
||||||
|
@ -5,6 +5,7 @@ import { sanitize as textSanitize } from "pretty-text/sanitizer";
|
|||||||
import loadScript from "discourse/lib/load-script";
|
import loadScript from "discourse/lib/load-script";
|
||||||
import { formatUsername } from "discourse/lib/utilities";
|
import { formatUsername } from "discourse/lib/utilities";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
function getOpts(opts) {
|
function getOpts(opts) {
|
||||||
const siteSettings = Discourse.__container__.lookup("site-settings:main"),
|
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
|
// Use this to easily create a pretty text instance with proper options
|
||||||
export function cook(text, 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
|
// everything should eventually move to async API and this should be renamed
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { escape } from "pretty-text/sanitizer";
|
import { escape } from "pretty-text/sanitizer";
|
||||||
import toMarkdown from "discourse/lib/to-markdown";
|
import toMarkdown from "discourse/lib/to-markdown";
|
||||||
|
import Handlebars from "handlebars";
|
||||||
|
|
||||||
const homepageSelector = "meta[name=discourse_current_homepage]";
|
const homepageSelector = "meta[name=discourse_current_homepage]";
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import discourseComputed, {
|
|||||||
observes
|
observes
|
||||||
} from "discourse-common/utils/decorators";
|
} from "discourse-common/utils/decorators";
|
||||||
import { autoUpdatingRelativeAge } from "discourse/lib/formatter";
|
import { autoUpdatingRelativeAge } from "discourse/lib/formatter";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
|
||||||
const LOGS_NOTICE_KEY = "logs-notice-text";
|
const LOGS_NOTICE_KEY = "logs-notice-text";
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ const LogsNotice = EmberObject.extend({
|
|||||||
|
|
||||||
@discourseComputed("text")
|
@discourseComputed("text")
|
||||||
message(text) {
|
message(text) {
|
||||||
return new Handlebars.SafeString(text);
|
return htmlSafe(text);
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("currentUser")
|
@discourseComputed("currentUser")
|
||||||
|
9
app/assets/javascripts/handlebars-shim.js
Normal file
9
app/assets/javascripts/handlebars-shim.js
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -24,7 +24,6 @@ function escapeChar(chr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function escape(string) {
|
export function escape(string) {
|
||||||
// don't escape SafeStrings, since they're already safe
|
|
||||||
if (string === null) {
|
if (string === null) {
|
||||||
return "";
|
return "";
|
||||||
} else if (!string) {
|
} else if (!string) {
|
||||||
|
@ -1 +1,2 @@
|
|||||||
//= require handlebars.runtime
|
//= require handlebars.runtime
|
||||||
|
//= require handlebars-shim
|
||||||
|
@ -171,6 +171,11 @@ module Discourse
|
|||||||
# the exclusion list does not include hbs so you double compile all this stuff
|
# 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|
|
initializer :fix_sprockets_loose_file_searcher, after: :set_default_precompile do |app|
|
||||||
app.config.assets.precompile.delete(Sprockets::Railtie::LOOSE_APP_ASSETS)
|
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
|
start_path = ::Rails.root.join("app/assets").to_s
|
||||||
exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '']
|
exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '']
|
||||||
app.config.assets.precompile << lambda do |logical_path, filename|
|
app.config.assets.precompile << lambda do |logical_path, filename|
|
||||||
|
@ -16,7 +16,7 @@ class Barber::Precompiler
|
|||||||
transpiled = transpiler.perform(source)
|
transpiled = transpiler.perform(source)
|
||||||
|
|
||||||
# very hacky but lets us use ES6. I'm ashamed of this code -RW
|
# 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
|
@precompiler = StringIO.new <<~END
|
||||||
var __RawHandlebars;
|
var __RawHandlebars;
|
||||||
|
@ -76,6 +76,7 @@ module PrettyText
|
|||||||
ctx.eval("__PRETTY_TEXT = true")
|
ctx.eval("__PRETTY_TEXT = true")
|
||||||
|
|
||||||
ctx_load(ctx, "#{Rails.root}/app/assets/javascripts/discourse-loader.js")
|
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(ctx, "vendor/assets/javascripts/lodash.js")
|
||||||
ctx_load_manifest(ctx, "pretty-text-bundle.js")
|
ctx_load_manifest(ctx, "pretty-text-bundle.js")
|
||||||
ctx_load_manifest(ctx, "markdown-it-bundle.js")
|
ctx_load_manifest(ctx, "markdown-it-bundle.js")
|
||||||
|
Reference in New Issue
Block a user