DEV: Remove `Ember.TEMPLATES` and centralize template resolution rules (#19220)
In the past, the result of template compilation would be stored directly in `Ember.TEMPLATES`. Following the move to more modern ember-cli-based compilation, templates are now compiled to es6 modules. To handle forward/backwards compatibility during these changes we had logic in `discourse-boot` which would extract templates from the es6 modules and store them into the legacy-style `Ember.TEMPLATES` object. This commit removes that shim, and updates our resolver to fetch templates directly from es6 modules. This is closer to how 'vanilla' Ember handles template resolution. We still have a lot of discourse-specific logic, but now it is centralised in one location and should be easier to understand and normalize in future. This commit should not introduce any behaviour change.
This commit is contained in:
parent
8b2c2e5c34
commit
c139767055
|
@ -0,0 +1,102 @@
|
||||||
|
const pluginRegex = /^discourse\/plugins\/([^\/]+)\/(.*)$/;
|
||||||
|
const themeRegex = /^discourse\/theme-([^\/]+)\/(.*)$/;
|
||||||
|
|
||||||
|
function appendToCache(cache, key, value) {
|
||||||
|
let cachedValue = cache.get(key);
|
||||||
|
cachedValue ??= [];
|
||||||
|
cachedValue.push(value);
|
||||||
|
cache.set(key, cachedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NAMESPACES = ["discourse/", "wizard/", "admin/"];
|
||||||
|
|
||||||
|
function isInRecognisedNamespace(moduleName) {
|
||||||
|
for (const ns of NAMESPACES) {
|
||||||
|
if (moduleName.startsWith(ns)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTemplate(moduleName) {
|
||||||
|
return moduleName.includes("/templates/");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides takes set of core/plugin/theme modules, finds the template modules,
|
||||||
|
* and makes an efficient lookup table for the resolver to use. It takes care of sourcing
|
||||||
|
* component/route templates from themes/plugins, and also handles template overrides.
|
||||||
|
*/
|
||||||
|
class DiscourseTemplateMap {
|
||||||
|
coreTemplates = new Map();
|
||||||
|
pluginTemplates = new Map();
|
||||||
|
themeTemplates = new Map();
|
||||||
|
prioritizedCaches = [
|
||||||
|
this.themeTemplates,
|
||||||
|
this.pluginTemplates,
|
||||||
|
this.coreTemplates,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the TemplateMap to use the supplied module names. It is expected that the list
|
||||||
|
* will be generated using `Object.keys(requirejs.entries)`.
|
||||||
|
*/
|
||||||
|
setModuleNames(moduleNames) {
|
||||||
|
this.coreTemplates.clear();
|
||||||
|
this.pluginTemplates.clear();
|
||||||
|
this.themeTemplates.clear();
|
||||||
|
for (const moduleName of moduleNames) {
|
||||||
|
if (isInRecognisedNamespace(moduleName) && isTemplate(moduleName)) {
|
||||||
|
this.#add(moduleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#add(originalPath) {
|
||||||
|
let path = originalPath;
|
||||||
|
|
||||||
|
let pluginMatch, themeMatch, cache;
|
||||||
|
if ((pluginMatch = path.match(pluginRegex))) {
|
||||||
|
path = pluginMatch[2];
|
||||||
|
cache = this.pluginTemplates;
|
||||||
|
} else if ((themeMatch = path.match(themeRegex))) {
|
||||||
|
path = themeMatch[2];
|
||||||
|
cache = this.themeTemplates;
|
||||||
|
} else {
|
||||||
|
cache = this.coreTemplates;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = path.replace(/^discourse\/templates\//, "");
|
||||||
|
|
||||||
|
appendToCache(cache, path, originalPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a template name to a module name, taking into account
|
||||||
|
* theme/plugin namespaces and overrides.
|
||||||
|
*/
|
||||||
|
resolve(name) {
|
||||||
|
for (const cache of this.prioritizedCaches) {
|
||||||
|
const val = cache.get(name);
|
||||||
|
if (val) {
|
||||||
|
return val[val.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all available template keys, after theme/plugin namespaces have
|
||||||
|
* been stripped.
|
||||||
|
*/
|
||||||
|
keys() {
|
||||||
|
const uniqueKeys = new Set([
|
||||||
|
...this.coreTemplates.keys(),
|
||||||
|
...this.pluginTemplates.keys(),
|
||||||
|
...this.themeTemplates.keys(),
|
||||||
|
]);
|
||||||
|
return [...uniqueKeys];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new DiscourseTemplateMap();
|
|
@ -32,11 +32,25 @@ export function findRawTemplate(name) {
|
||||||
|
|
||||||
export function buildRawConnectorCache(findOutlets) {
|
export function buildRawConnectorCache(findOutlets) {
|
||||||
let result = {};
|
let result = {};
|
||||||
findOutlets(__DISCOURSE_RAW_TEMPLATES, (outletName, resource) => {
|
findOutlets(
|
||||||
result[outletName] = result[outletName] || [];
|
Object.keys(__DISCOURSE_RAW_TEMPLATES),
|
||||||
|
(outletName, resource) => {
|
||||||
|
result[outletName] ??= [];
|
||||||
result[outletName].push({
|
result[outletName].push({
|
||||||
template: __DISCOURSE_RAW_TEMPLATES[resource],
|
template: __DISCOURSE_RAW_TEMPLATES[resource],
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function eagerLoadRawTemplateModules() {
|
||||||
|
for (const [key, value] of Object.entries(requirejs.entries)) {
|
||||||
|
if (
|
||||||
|
key.includes("/templates/") &&
|
||||||
|
value.deps.includes("discourse-common/lib/raw-templates")
|
||||||
|
) {
|
||||||
|
require(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import Ember from "ember";
|
|
||||||
import { dasherize, decamelize } from "@ember/string";
|
import { dasherize, decamelize } from "@ember/string";
|
||||||
import deprecated from "discourse-common/lib/deprecated";
|
import deprecated from "discourse-common/lib/deprecated";
|
||||||
import { findHelper } from "discourse-common/lib/helpers";
|
import { findHelper } from "discourse-common/lib/helpers";
|
||||||
import SuffixTrie from "discourse-common/lib/suffix-trie";
|
import SuffixTrie from "discourse-common/lib/suffix-trie";
|
||||||
import Resolver from "ember-resolver";
|
import Resolver from "ember-resolver";
|
||||||
import { buildResolver as buildLegacyResolver } from "discourse-common/lib/legacy-resolver";
|
import { buildResolver as buildLegacyResolver } from "discourse-common/lib/legacy-resolver";
|
||||||
|
import DiscourseTemplateMap from "discourse-common/lib/discourse-template-map";
|
||||||
|
|
||||||
let _options = {};
|
let _options = {};
|
||||||
let moduleSuffixTrie = null;
|
let moduleSuffixTrie = null;
|
||||||
|
@ -287,21 +287,19 @@ export function buildResolver(baseName) {
|
||||||
|
|
||||||
resolveTemplate(parsedName) {
|
resolveTemplate(parsedName) {
|
||||||
return (
|
return (
|
||||||
this.findPluginMobileTemplate(parsedName) ||
|
|
||||||
this.findPluginTemplate(parsedName) ||
|
|
||||||
this.findMobileTemplate(parsedName) ||
|
this.findMobileTemplate(parsedName) ||
|
||||||
this.findTemplate(parsedName) ||
|
this.findTemplate(parsedName) ||
|
||||||
this.findAdminTemplate(parsedName) ||
|
this.findAdminTemplate(parsedName) ||
|
||||||
this.findWizardTemplate(parsedName) ||
|
this.findWizardTemplate(parsedName) ||
|
||||||
this.findLoadingTemplate(parsedName) ||
|
this.findLoadingTemplate(parsedName) ||
|
||||||
this.findConnectorTemplate(parsedName) ||
|
this.findConnectorTemplate(parsedName) ||
|
||||||
Ember.TEMPLATES.not_found
|
this.discourseTemplateModule("not_found")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
findLoadingTemplate(parsedName) {
|
findLoadingTemplate(parsedName) {
|
||||||
if (parsedName.fullNameWithoutType.match(/loading$/)) {
|
if (parsedName.fullNameWithoutType.match(/loading$/)) {
|
||||||
return Ember.TEMPLATES.loading;
|
return this.discourseTemplateModule("loading");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,17 +310,7 @@ export function buildResolver(baseName) {
|
||||||
.replace("template:connectors/", "template:")
|
.replace("template:connectors/", "template:")
|
||||||
.replace("components/", "")
|
.replace("components/", "")
|
||||||
);
|
);
|
||||||
return this.findTemplate(connectorParsedName, "javascripts/");
|
return this.findTemplate(connectorParsedName);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findPluginTemplate(parsedName) {
|
|
||||||
return this.findTemplate(parsedName, "javascripts/");
|
|
||||||
}
|
|
||||||
|
|
||||||
findPluginMobileTemplate(parsedName) {
|
|
||||||
if (_options.mobileView) {
|
|
||||||
return this.findTemplate(parsedName, "javascripts/mobile/");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,31 +320,43 @@ export function buildResolver(baseName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a template path, this function will return a template, taking into account
|
||||||
|
* priority rules for theme and plugin overrides. See `lib/discourse-template-map.js`
|
||||||
|
*/
|
||||||
|
discourseTemplateModule(name) {
|
||||||
|
const resolvedName = DiscourseTemplateMap.resolve(name);
|
||||||
|
if (resolvedName) {
|
||||||
|
return require(resolvedName).default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
findTemplate(parsedName, prefix) {
|
findTemplate(parsedName, prefix) {
|
||||||
prefix = prefix || "";
|
prefix = prefix || "";
|
||||||
|
|
||||||
const withoutType = parsedName.fullNameWithoutType,
|
const withoutType = parsedName.fullNameWithoutType,
|
||||||
underscored = decamelize(withoutType).replace(/-/g, "_"),
|
underscored = decamelize(withoutType).replace(/-/g, "_"),
|
||||||
segments = withoutType.split("/"),
|
segments = withoutType.split("/");
|
||||||
templates = Ember.TEMPLATES;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// Convert dots and dashes to slashes
|
// Convert dots and dashes to slashes
|
||||||
templates[prefix + withoutType.replace(/[\.-]/g, "/")] ||
|
this.discourseTemplateModule(
|
||||||
|
prefix + withoutType.replace(/[\.-]/g, "/")
|
||||||
|
) ||
|
||||||
// Default unmodified behavior of original resolveTemplate.
|
// Default unmodified behavior of original resolveTemplate.
|
||||||
templates[prefix + withoutType] ||
|
this.discourseTemplateModule(prefix + withoutType) ||
|
||||||
// Underscored without namespace
|
// Underscored without namespace
|
||||||
templates[prefix + underscored] ||
|
this.discourseTemplateModule(prefix + underscored) ||
|
||||||
// Underscored with first segment as directory
|
// Underscored with first segment as directory
|
||||||
templates[prefix + underscored.replace("_", "/")] ||
|
this.discourseTemplateModule(prefix + underscored.replace("_", "/")) ||
|
||||||
// Underscore only the last segment
|
// Underscore only the last segment
|
||||||
templates[
|
this.discourseTemplateModule(
|
||||||
`${prefix}${segments.slice(0, -1).join("/")}/${segments[
|
`${prefix}${segments.slice(0, -1).join("/")}/${segments[
|
||||||
segments.length - 1
|
segments.length - 1
|
||||||
].replace(/-/g, "_")}`
|
].replace(/-/g, "_")}`
|
||||||
] ||
|
) ||
|
||||||
// All dasherized
|
// All dasherized
|
||||||
templates[prefix + withoutType.replace(/\//g, "-")]
|
this.discourseTemplateModule(prefix + withoutType.replace(/\//g, "-"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,17 +364,15 @@ export function buildResolver(baseName) {
|
||||||
// (similar to how discourse lays out templates)
|
// (similar to how discourse lays out templates)
|
||||||
findAdminTemplate(parsedName) {
|
findAdminTemplate(parsedName) {
|
||||||
if (parsedName.fullNameWithoutType === "admin") {
|
if (parsedName.fullNameWithoutType === "admin") {
|
||||||
return Ember.TEMPLATES["admin/templates/admin"];
|
return this.discourseTemplateModule("admin/templates/admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
let namespaced, match;
|
let namespaced, match;
|
||||||
|
|
||||||
if (parsedName.fullNameWithoutType.startsWith("components/")) {
|
if (parsedName.fullNameWithoutType.startsWith("components/")) {
|
||||||
return (
|
return (
|
||||||
// Built-in
|
|
||||||
this.findTemplate(parsedName, "admin/templates/") ||
|
this.findTemplate(parsedName, "admin/templates/") ||
|
||||||
// Plugin
|
this.findTemplate(parsedName, "admin/") // Nested under discourse/templates/admin (e.g. from plugins)
|
||||||
this.findTemplate(parsedName, "javascripts/admin/")
|
|
||||||
);
|
);
|
||||||
} else if (/^admin[_\.-]/.test(parsedName.fullNameWithoutType)) {
|
} else if (/^admin[_\.-]/.test(parsedName.fullNameWithoutType)) {
|
||||||
namespaced = parsedName.fullNameWithoutType.slice(6);
|
namespaced = parsedName.fullNameWithoutType.slice(6);
|
||||||
|
@ -389,11 +387,9 @@ export function buildResolver(baseName) {
|
||||||
if (namespaced) {
|
if (namespaced) {
|
||||||
let adminParsedName = this.parseName(`template:${namespaced}`);
|
let adminParsedName = this.parseName(`template:${namespaced}`);
|
||||||
resolved =
|
resolved =
|
||||||
// Built-in
|
|
||||||
this.findTemplate(adminParsedName, "admin/templates/") ||
|
this.findTemplate(adminParsedName, "admin/templates/") ||
|
||||||
this.findTemplate(parsedName, "admin/templates/") ||
|
this.findTemplate(parsedName, "admin/templates/") ||
|
||||||
// Plugin
|
this.findTemplate(adminParsedName, "admin/"); // Nested under discourse/templates/admin (e.g. from plugin)
|
||||||
this.findTemplate(adminParsedName, "javascripts/admin/");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolved;
|
return resolved;
|
||||||
|
@ -401,7 +397,7 @@ export function buildResolver(baseName) {
|
||||||
|
|
||||||
findWizardTemplate(parsedName) {
|
findWizardTemplate(parsedName) {
|
||||||
if (parsedName.fullNameWithoutType === "wizard") {
|
if (parsedName.fullNameWithoutType === "wizard") {
|
||||||
return Ember.TEMPLATES["wizard/templates/wizard"];
|
return this.discourseTemplateModule("wizard/templates/wizard");
|
||||||
}
|
}
|
||||||
|
|
||||||
let namespaced;
|
let namespaced;
|
||||||
|
@ -415,10 +411,10 @@ export function buildResolver(baseName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namespaced) {
|
if (namespaced) {
|
||||||
let adminParsedName = this.parseName(
|
let wizardParsedName = this.parseName(
|
||||||
`template:wizard/templates/${namespaced}`
|
`template:wizard/templates/${namespaced}`
|
||||||
);
|
);
|
||||||
return this.findTemplate(adminParsedName);
|
return this.findTemplate(wizardParsedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import { action, set } from "@ember/object";
|
import { action, set } from "@ember/object";
|
||||||
import showModal from "discourse/lib/show-modal";
|
import showModal from "discourse/lib/show-modal";
|
||||||
import { inject as service } from "@ember/service";
|
import { inject as service } from "@ember/service";
|
||||||
import Ember from "ember";
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
|
||||||
let _components = {};
|
let _components = {};
|
||||||
|
|
||||||
|
@ -106,12 +106,11 @@ export default Component.extend({
|
||||||
return _components[type];
|
return _components[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
let dasherized = dasherize(type);
|
const dasherized = dasherize(type);
|
||||||
let templatePath = `components/${dasherized}`;
|
const componentExists = getOwner(this).hasRegistration(
|
||||||
let template =
|
`component:${dasherized}`
|
||||||
Ember.TEMPLATES[`${templatePath}`] ||
|
);
|
||||||
Ember.TEMPLATES[`javascripts/${templatePath}`];
|
_components[type] = componentExists ? dasherized : null;
|
||||||
_components[type] = template ? dasherized : null;
|
|
||||||
return _components[type];
|
return _components[type];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { eagerLoadRawTemplateModules } from "discourse-common/lib/raw-templates";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "eager-load-raw-templates",
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
eagerLoadRawTemplateModules();
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
import discourseTemplateMap from "discourse-common/lib/discourse-template-map";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "populate-template-map",
|
||||||
|
initialize() {
|
||||||
|
discourseTemplateMap.setModuleNames(Object.keys(requirejs.entries));
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
import { buildRawConnectorCache } from "discourse-common/lib/raw-templates";
|
import { buildRawConnectorCache } from "discourse-common/lib/raw-templates";
|
||||||
import deprecated from "discourse-common/lib/deprecated";
|
import deprecated from "discourse-common/lib/deprecated";
|
||||||
import Ember from "ember";
|
import DiscourseTemplateMap from "discourse-common/lib/discourse-template-map";
|
||||||
|
|
||||||
let _connectorCache;
|
let _connectorCache;
|
||||||
let _rawConnectorCache;
|
let _rawConnectorCache;
|
||||||
|
@ -25,11 +25,11 @@ const DefaultConnectorClass = {
|
||||||
teardownComponent() {},
|
teardownComponent() {},
|
||||||
};
|
};
|
||||||
|
|
||||||
function findOutlets(collection, callback) {
|
function findOutlets(keys, callback) {
|
||||||
Object.keys(collection).forEach(function (res) {
|
keys.forEach(function (res) {
|
||||||
if (res.includes("/connectors/")) {
|
|
||||||
const segments = res.split("/");
|
const segments = res.split("/");
|
||||||
let outletName = segments[segments.length - 2];
|
if (segments.includes("connectors")) {
|
||||||
|
const outletName = segments[segments.length - 2];
|
||||||
const uniqueName = segments[segments.length - 1];
|
const uniqueName = segments[segments.length - 1];
|
||||||
|
|
||||||
callback(outletName, res, uniqueName);
|
callback(outletName, res, uniqueName);
|
||||||
|
@ -45,7 +45,7 @@ export function clearCache() {
|
||||||
function findClass(outletName, uniqueName) {
|
function findClass(outletName, uniqueName) {
|
||||||
if (!_classPaths) {
|
if (!_classPaths) {
|
||||||
_classPaths = {};
|
_classPaths = {};
|
||||||
findOutlets(require._eak_seen, (outlet, res, un) => {
|
findOutlets(Object.keys(require._eak_seen), (outlet, res, un) => {
|
||||||
const possibleConnectorClass = requirejs(res).default;
|
const possibleConnectorClass = requirejs(res).default;
|
||||||
if (possibleConnectorClass.__id) {
|
if (possibleConnectorClass.__id) {
|
||||||
// This is the template, not the connector class
|
// This is the template, not the connector class
|
||||||
|
@ -63,20 +63,31 @@ function findClass(outletName, uniqueName) {
|
||||||
: DefaultConnectorClass;
|
: DefaultConnectorClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cache of connectors. Should only be used in tests when
|
||||||
|
* `requirejs.entries` is changed.
|
||||||
|
*/
|
||||||
|
export function expireConnectorCache() {
|
||||||
|
_connectorCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
function buildConnectorCache() {
|
function buildConnectorCache() {
|
||||||
_connectorCache = {};
|
_connectorCache = {};
|
||||||
|
|
||||||
findOutlets(Ember.TEMPLATES, (outletName, resource, uniqueName) => {
|
findOutlets(
|
||||||
|
DiscourseTemplateMap.keys(),
|
||||||
|
(outletName, resource, uniqueName) => {
|
||||||
_connectorCache[outletName] = _connectorCache[outletName] || [];
|
_connectorCache[outletName] = _connectorCache[outletName] || [];
|
||||||
|
|
||||||
_connectorCache[outletName].push({
|
_connectorCache[outletName].push({
|
||||||
outletName,
|
outletName,
|
||||||
templateName: resource.replace("javascripts/", ""),
|
templateName: resource,
|
||||||
template: Ember.TEMPLATES[resource],
|
template: require(DiscourseTemplateMap.resolve(resource)).default,
|
||||||
classNames: `${outletName}-outlet ${uniqueName}`,
|
classNames: `${outletName}-outlet ${uniqueName}`,
|
||||||
connectorClass: findClass(outletName, uniqueName),
|
connectorClass: findClass(outletName, uniqueName),
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function connectorsFor(outletName) {
|
export function connectorsFor(outletName) {
|
||||||
|
|
|
@ -3,50 +3,6 @@
|
||||||
throw "Unsupported browser detected";
|
throw "Unsupported browser detected";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove this and have resolver find the templates
|
|
||||||
const discoursePrefix = "discourse/templates/";
|
|
||||||
const adminPrefix = "admin/templates/";
|
|
||||||
const wizardPrefix = "wizard/templates/";
|
|
||||||
const discoursePrefixLength = discoursePrefix.length;
|
|
||||||
|
|
||||||
const pluginRegex = /^discourse\/plugins\/([^\/]+)\//;
|
|
||||||
const themeRegex = /^discourse\/theme-([^\/]+)\//;
|
|
||||||
|
|
||||||
Object.keys(requirejs.entries).forEach(function (key) {
|
|
||||||
let templateKey;
|
|
||||||
let pluginName;
|
|
||||||
let themeId;
|
|
||||||
if (key.startsWith(discoursePrefix)) {
|
|
||||||
templateKey = key.slice(discoursePrefixLength);
|
|
||||||
} else if (key.startsWith(adminPrefix) || key.startsWith(wizardPrefix)) {
|
|
||||||
templateKey = key;
|
|
||||||
} else if (
|
|
||||||
(pluginName = key.match(pluginRegex)?.[1]) &&
|
|
||||||
key.includes("/templates/") &&
|
|
||||||
require(key).default.__id // really is a template
|
|
||||||
) {
|
|
||||||
// This logic mimics the old sprockets compilation system which used to
|
|
||||||
// output templates directly to `Ember.TEMPLATES` with this naming logic
|
|
||||||
templateKey = key.slice(`discourse/plugins/${pluginName}/`.length);
|
|
||||||
templateKey = templateKey.replace("discourse/templates/", "");
|
|
||||||
templateKey = `javascripts/${templateKey}`;
|
|
||||||
} else if (
|
|
||||||
(themeId = key.match(themeRegex)?.[1]) &&
|
|
||||||
key.includes("/templates/")
|
|
||||||
) {
|
|
||||||
// And likewise for themes - this mimics the old logic
|
|
||||||
templateKey = key.slice(`discourse/theme-${themeId}/`.length);
|
|
||||||
templateKey = templateKey.replace("discourse/templates/", "");
|
|
||||||
if (!templateKey.startsWith("javascripts/")) {
|
|
||||||
templateKey = `javascripts/${templateKey}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (templateKey) {
|
|
||||||
Ember.TEMPLATES[templateKey] = require(key).default;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
window.__widget_helpers = require("discourse-widget-hbs/helpers").default;
|
window.__widget_helpers = require("discourse-widget-hbs/helpers").default;
|
||||||
|
|
||||||
// TODO: Eliminate this global
|
// TODO: Eliminate this global
|
||||||
|
|
|
@ -2,15 +2,14 @@ import { acceptance, query } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { visit } from "@ember/test-helpers";
|
import { visit } from "@ember/test-helpers";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "discourse/tests/helpers/template-module-helper";
|
||||||
|
|
||||||
acceptance("CustomHTML template", function (needs) {
|
acceptance("CustomHTML template", function (needs) {
|
||||||
needs.hooks.beforeEach(() => {
|
needs.hooks.beforeEach(() => {
|
||||||
Ember.TEMPLATES["top"] = hbs`<span class='top-span'>TOP</span>`;
|
registerTemplateModule(
|
||||||
});
|
"discourse/templates/top",
|
||||||
|
hbs`<span class='top-span'>TOP</span>`
|
||||||
needs.hooks.afterEach(() => {
|
);
|
||||||
delete Ember.TEMPLATES["top"];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("renders custom template", async function (assert) {
|
test("renders custom template", async function (assert) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { test } from "qunit";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import showModal from "discourse/lib/show-modal";
|
import showModal from "discourse/lib/show-modal";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "../helpers/template-module-helper";
|
||||||
|
|
||||||
acceptance("Modal", function (needs) {
|
acceptance("Modal", function (needs) {
|
||||||
let _translations;
|
let _translations;
|
||||||
|
@ -54,9 +54,10 @@ acceptance("Modal", function (needs) {
|
||||||
await triggerKeyEvent("#main-outlet", "keydown", "Escape");
|
await triggerKeyEvent("#main-outlet", "keydown", "Escape");
|
||||||
assert.ok(!exists(".d-modal:visible"), "ESC should close the modal");
|
assert.ok(!exists(".d-modal:visible"), "ESC should close the modal");
|
||||||
|
|
||||||
Ember.TEMPLATES[
|
registerTemplateModule(
|
||||||
"modal/not-dismissable"
|
"discourse/templates/modal/not-dismissable",
|
||||||
] = hbs`{{#d-modal-body title="" class="" dismissable=false}}test{{/d-modal-body}}`;
|
hbs`{{#d-modal-body title="" class="" dismissable=false}}test{{/d-modal-body}}`
|
||||||
|
);
|
||||||
|
|
||||||
showModal("not-dismissable", {});
|
showModal("not-dismissable", {});
|
||||||
await settled();
|
await settled();
|
||||||
|
@ -78,7 +79,10 @@ acceptance("Modal", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("rawTitle in modal panels", async function (assert) {
|
test("rawTitle in modal panels", async function (assert) {
|
||||||
Ember.TEMPLATES["modal/test-raw-title-panels"] = hbs``;
|
registerTemplateModule(
|
||||||
|
"discourse/templates/modal/test-raw-title-panels",
|
||||||
|
hbs``
|
||||||
|
);
|
||||||
const panels = [
|
const panels = [
|
||||||
{ id: "test1", rawTitle: "Test 1" },
|
{ id: "test1", rawTitle: "Test 1" },
|
||||||
{ id: "test2", rawTitle: "Test 2" },
|
{ id: "test2", rawTitle: "Test 2" },
|
||||||
|
@ -96,10 +100,11 @@ acceptance("Modal", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("modal title", async function (assert) {
|
test("modal title", async function (assert) {
|
||||||
Ember.TEMPLATES["modal/test-title"] = hbs``;
|
registerTemplateModule("discourse/templates/modal/test-title", hbs``);
|
||||||
Ember.TEMPLATES[
|
registerTemplateModule(
|
||||||
"modal/test-title-with-body"
|
"discourse/templates/modal/test-title-with-body",
|
||||||
] = hbs`{{#d-modal-body}}test{{/d-modal-body}}`;
|
hbs`{{#d-modal-body}}test{{/d-modal-body}}`
|
||||||
|
);
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ import { action } from "@ember/object";
|
||||||
import { extraConnectorClass } from "discourse/lib/plugin-connectors";
|
import { extraConnectorClass } from "discourse/lib/plugin-connectors";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "discourse/tests/helpers/template-module-helper";
|
||||||
|
|
||||||
const PREFIX = "javascripts/single-test/connectors";
|
const PREFIX = "discourse/plugins/some-plugin/templates/connectors";
|
||||||
|
|
||||||
acceptance("Plugin Outlet - Connector Class", function (needs) {
|
acceptance("Plugin Outlet - Connector Class", function (needs) {
|
||||||
needs.hooks.beforeEach(() => {
|
needs.hooks.beforeEach(() => {
|
||||||
|
@ -49,25 +49,22 @@ acceptance("Plugin Outlet - Connector Class", function (needs) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Ember.TEMPLATES[
|
registerTemplateModule(
|
||||||
`${PREFIX}/user-profile-primary/hello`
|
`${PREFIX}/user-profile-primary/hello`,
|
||||||
] = hbs`<span class='hello-username'>{{model.username}}</span>
|
hbs`<span class='hello-username'>{{model.username}}</span>
|
||||||
<button class='say-hello' {{on "click" (action "sayHello")}}></button>
|
<button class='say-hello' {{on "click" (action "sayHello")}}></button>
|
||||||
<button class='say-hello-using-this' {{on "click" this.sayHello}}></button>
|
<button class='say-hello-using-this' {{on "click" this.sayHello}}></button>
|
||||||
<span class='hello-result'>{{hello}}</span>`;
|
<span class='hello-result'>{{hello}}</span>`
|
||||||
Ember.TEMPLATES[
|
);
|
||||||
`${PREFIX}/user-profile-primary/hi`
|
registerTemplateModule(
|
||||||
] = hbs`<button class='say-hi' {{on "click" (action "sayHi")}}></button>
|
`${PREFIX}/user-profile-primary/hi`,
|
||||||
<span class='hi-result'>{{hi}}</span>`;
|
hbs`<button class='say-hi' {{on "click" (action "sayHi")}}></button>
|
||||||
Ember.TEMPLATES[
|
<span class='hi-result'>{{hi}}</span>`
|
||||||
`${PREFIX}/user-profile-primary/dont-render`
|
);
|
||||||
] = hbs`I'm not rendered!`;
|
registerTemplateModule(
|
||||||
});
|
`${PREFIX}/user-profile-primary/dont-render`,
|
||||||
|
hbs`I'm not rendered!`
|
||||||
needs.hooks.afterEach(() => {
|
);
|
||||||
delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/hello`];
|
|
||||||
delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/hi`];
|
|
||||||
delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/dont-render`];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Renders a template into the outlet", async function (assert) {
|
test("Renders a template into the outlet", async function (assert) {
|
||||||
|
|
|
@ -7,16 +7,22 @@ import { hbs } from "ember-cli-htmlbars";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { visit } from "@ember/test-helpers";
|
import { visit } from "@ember/test-helpers";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "../helpers/template-module-helper";
|
||||||
|
|
||||||
const PREFIX = "javascripts/single-test/connectors";
|
const PREFIX = "discourse/plugins/some-plugin/templates/connectors";
|
||||||
|
|
||||||
acceptance("Plugin Outlet - Decorator", function (needs) {
|
acceptance("Plugin Outlet - Decorator", function (needs) {
|
||||||
needs.user();
|
needs.user();
|
||||||
|
|
||||||
needs.hooks.beforeEach(() => {
|
needs.hooks.beforeEach(() => {
|
||||||
Ember.TEMPLATES[`${PREFIX}/discovery-list-container-top/foo`] = hbs`FOO`;
|
registerTemplateModule(
|
||||||
Ember.TEMPLATES[`${PREFIX}/discovery-list-container-top/bar`] = hbs`BAR`;
|
`${PREFIX}/discovery-list-container-top/foo`,
|
||||||
|
hbs`FOO`
|
||||||
|
);
|
||||||
|
registerTemplateModule(
|
||||||
|
`${PREFIX}/discovery-list-container-top/bar`,
|
||||||
|
hbs`BAR`
|
||||||
|
);
|
||||||
|
|
||||||
withPluginApi("0.8.38", (api) => {
|
withPluginApi("0.8.38", (api) => {
|
||||||
api.decoratePluginOutlet(
|
api.decoratePluginOutlet(
|
||||||
|
@ -37,11 +43,6 @@ acceptance("Plugin Outlet - Decorator", function (needs) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
needs.hooks.afterEach(() => {
|
|
||||||
delete Ember.TEMPLATES[`${PREFIX}/discovery-list-container-top/foo`];
|
|
||||||
delete Ember.TEMPLATES[`${PREFIX}/discovery-list-container-top/bar`];
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Calls the plugin callback with the rendered outlet", async function (assert) {
|
test("Calls the plugin callback with the rendered outlet", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
|
|
||||||
|
|
|
@ -6,21 +6,17 @@ import {
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { visit } from "@ember/test-helpers";
|
import { visit } from "@ember/test-helpers";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "../helpers/template-module-helper";
|
||||||
|
|
||||||
const HELLO = "javascripts/multi-test/connectors/user-profile-primary/hello";
|
const HELLO =
|
||||||
|
"discourse/plugins/my-plugin/templates/connectors/user-profile-primary/hello";
|
||||||
const GOODBYE =
|
const GOODBYE =
|
||||||
"javascripts/multi-test/connectors/user-profile-primary/goodbye";
|
"discourse/plugins/my-plugin/templates/connectors/user-profile-primary/goodbye";
|
||||||
|
|
||||||
acceptance("Plugin Outlet - Multi Template", function (needs) {
|
acceptance("Plugin Outlet - Multi Template", function (needs) {
|
||||||
needs.hooks.beforeEach(() => {
|
needs.hooks.beforeEach(() => {
|
||||||
Ember.TEMPLATES[HELLO] = hbs`<span class='hello-span'>Hello</span>`;
|
registerTemplateModule(HELLO, hbs`<span class='hello-span'>Hello</span>`);
|
||||||
Ember.TEMPLATES[GOODBYE] = hbs`<span class='bye-span'>Goodbye</span>`;
|
registerTemplateModule(GOODBYE, hbs`<span class='bye-span'>Goodbye</span>`);
|
||||||
});
|
|
||||||
|
|
||||||
needs.hooks.afterEach(() => {
|
|
||||||
delete Ember.TEMPLATES[HELLO];
|
|
||||||
delete Ember.TEMPLATES[GOODBYE];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Renders a template into the outlet", async function (assert) {
|
test("Renders a template into the outlet", async function (assert) {
|
||||||
|
|
|
@ -6,20 +6,17 @@ import {
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { visit } from "@ember/test-helpers";
|
import { visit } from "@ember/test-helpers";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "../helpers/template-module-helper";
|
||||||
|
|
||||||
const CONNECTOR =
|
const CONNECTOR_MODULE =
|
||||||
"javascripts/single-test/connectors/user-profile-primary/hello";
|
"discourse/theme-12/templates/connectors/user-profile-primary/hello";
|
||||||
|
|
||||||
acceptance("Plugin Outlet - Single Template", function (needs) {
|
acceptance("Plugin Outlet - Single Template", function (needs) {
|
||||||
needs.hooks.beforeEach(() => {
|
needs.hooks.beforeEach(() => {
|
||||||
Ember.TEMPLATES[
|
registerTemplateModule(
|
||||||
CONNECTOR
|
CONNECTOR_MODULE,
|
||||||
] = hbs`<span class='hello-username'>{{model.username}}</span>`;
|
hbs`<span class='hello-username'>{{model.username}}</span>`
|
||||||
});
|
);
|
||||||
|
|
||||||
needs.hooks.afterEach(() => {
|
|
||||||
delete Ember.TEMPLATES[CONNECTOR];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Renders a template into the outlet", async function (assert) {
|
test("Renders a template into the outlet", async function (assert) {
|
||||||
|
|
|
@ -76,6 +76,7 @@ import { resetNotificationTypeRenderers } from "discourse/lib/notification-types
|
||||||
import { resetUserMenuTabs } from "discourse/lib/user-menu/tab";
|
import { resetUserMenuTabs } from "discourse/lib/user-menu/tab";
|
||||||
import { reset as resetLinkLookup } from "discourse/lib/link-lookup";
|
import { reset as resetLinkLookup } from "discourse/lib/link-lookup";
|
||||||
import { resetModelTransformers } from "discourse/lib/model-transformers";
|
import { resetModelTransformers } from "discourse/lib/model-transformers";
|
||||||
|
import { cleanupTemporaryTemplateRegistrations } from "./template-module-helper";
|
||||||
|
|
||||||
export function currentUser() {
|
export function currentUser() {
|
||||||
return User.create(sessionFixtures["/session/current.json"].current_user);
|
return User.create(sessionFixtures["/session/current.json"].current_user);
|
||||||
|
@ -207,6 +208,7 @@ export function testCleanup(container, app) {
|
||||||
resetUserMenuTabs();
|
resetUserMenuTabs();
|
||||||
resetLinkLookup();
|
resetLinkLookup();
|
||||||
resetModelTransformers();
|
resetModelTransformers();
|
||||||
|
cleanupTemporaryTemplateRegistrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function discourseModule(name, options) {
|
export function discourseModule(name, options) {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import DiscourseTemplateMap from "discourse-common/lib/discourse-template-map";
|
||||||
|
import { expireConnectorCache } from "discourse/lib/plugin-connectors";
|
||||||
|
|
||||||
|
const modifications = [];
|
||||||
|
|
||||||
|
function generateTemplateModule(template) {
|
||||||
|
return function (_exports) {
|
||||||
|
Object.defineProperty(_exports, "__esModule", {
|
||||||
|
value: true,
|
||||||
|
});
|
||||||
|
_exports.default = template;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerTemplateModule(moduleName, template) {
|
||||||
|
const modificationData = {
|
||||||
|
moduleName,
|
||||||
|
existingModule: requirejs.entries[moduleName],
|
||||||
|
};
|
||||||
|
delete requirejs.entries[moduleName];
|
||||||
|
define(moduleName, ["exports"], generateTemplateModule(template));
|
||||||
|
modifications.push(modificationData);
|
||||||
|
expireConnectorCache();
|
||||||
|
DiscourseTemplateMap.setModuleNames(Object.keys(requirejs.entries));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cleanupTemporaryTemplateRegistrations() {
|
||||||
|
for (const modificationData of modifications.reverse()) {
|
||||||
|
const { moduleName, existingModule } = modificationData;
|
||||||
|
delete requirejs.entries[moduleName];
|
||||||
|
if (existingModule) {
|
||||||
|
requirejs.entries[moduleName] = existingModule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (modifications.length) {
|
||||||
|
expireConnectorCache();
|
||||||
|
DiscourseTemplateMap.setModuleNames(Object.keys(requirejs.entries));
|
||||||
|
}
|
||||||
|
modifications.clear();
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import { buildResolver, setResolverOption } from "discourse-common/resolver";
|
import { buildResolver, setResolverOption } from "discourse-common/resolver";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import Ember from "ember";
|
import { registerTemplateModule } from "discourse/tests/helpers/template-module-helper";
|
||||||
|
import DiscourseTemplateMap from "discourse-common/lib/discourse-template-map";
|
||||||
|
|
||||||
let originalTemplates;
|
|
||||||
let resolver;
|
let resolver;
|
||||||
|
|
||||||
function lookupTemplate(assert, name, expectedTemplate, message) {
|
function lookupTemplate(assert, name, expectedTemplate, message) {
|
||||||
|
@ -11,57 +11,71 @@ function lookupTemplate(assert, name, expectedTemplate, message) {
|
||||||
assert.strictEqual(result, expectedTemplate, message);
|
assert.strictEqual(result, expectedTemplate, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTemplates(lookupTemplateStrings) {
|
function setTemplates(templateModuleNames) {
|
||||||
lookupTemplateStrings.forEach(function (lookupTemplateString) {
|
for (const name of templateModuleNames) {
|
||||||
Ember.TEMPLATES[lookupTemplateString] = lookupTemplateString;
|
registerTemplateModule(name, name);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DiscourseResolver = buildResolver("discourse");
|
const DiscourseResolver = buildResolver("discourse");
|
||||||
|
|
||||||
module("Unit | Ember | resolver", function (hooks) {
|
module("Unit | Ember | resolver", function (hooks) {
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function () {
|
||||||
originalTemplates = Ember.TEMPLATES;
|
DiscourseTemplateMap.setModuleNames(Object.keys(requirejs.entries));
|
||||||
Ember.TEMPLATES = {};
|
|
||||||
|
|
||||||
resolver = DiscourseResolver.create({
|
resolver = DiscourseResolver.create({
|
||||||
namespace: { modulePrefix: "discourse" },
|
namespace: { modulePrefix: "discourse" },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
hooks.afterEach(function () {
|
|
||||||
Ember.TEMPLATES = originalTemplates;
|
|
||||||
});
|
|
||||||
|
|
||||||
test("finds templates in top level dir", function (assert) {
|
test("finds templates in top level dir", function (assert) {
|
||||||
setTemplates(["foobar", "fooBar", "foo_bar", "foo.bar"]);
|
setTemplates([
|
||||||
|
"discourse/templates/foobar",
|
||||||
|
"discourse/templates/fooBar",
|
||||||
|
"discourse/templates/foo_bar",
|
||||||
|
"discourse/templates/foo.bar",
|
||||||
|
]);
|
||||||
|
|
||||||
// Default unmodified behavior
|
// Default unmodified behavior
|
||||||
lookupTemplate(assert, "template:foobar", "foobar", "by lowcased name");
|
lookupTemplate(
|
||||||
|
assert,
|
||||||
|
"template:foobar",
|
||||||
|
"discourse/templates/foobar",
|
||||||
|
"by lowcased name"
|
||||||
|
);
|
||||||
|
|
||||||
// Default unmodified behavior
|
// Default unmodified behavior
|
||||||
lookupTemplate(assert, "template:fooBar", "fooBar", "by camel cased name");
|
lookupTemplate(
|
||||||
|
assert,
|
||||||
|
"template:fooBar",
|
||||||
|
"discourse/templates/fooBar",
|
||||||
|
"by camel cased name"
|
||||||
|
);
|
||||||
|
|
||||||
// Default unmodified behavior
|
// Default unmodified behavior
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo_bar",
|
"template:foo_bar",
|
||||||
"foo_bar",
|
"discourse/templates/foo_bar",
|
||||||
"by underscored name"
|
"by underscored name"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default unmodified behavior
|
// Default unmodified behavior
|
||||||
lookupTemplate(assert, "template:foo.bar", "foo.bar", "by dotted name");
|
lookupTemplate(
|
||||||
|
assert,
|
||||||
|
"template:foo.bar",
|
||||||
|
"discourse/templates/foo.bar",
|
||||||
|
"by dotted name"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("finds templates in first-level subdir", function (assert) {
|
test("finds templates in first-level subdir", function (assert) {
|
||||||
setTemplates(["foo/bar_baz"]);
|
setTemplates(["discourse/templates/foo/bar_baz"]);
|
||||||
|
|
||||||
// Default unmodified behavior
|
// Default unmodified behavior
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo/bar_baz",
|
"template:foo/bar_baz",
|
||||||
"foo/bar_baz",
|
"discourse/templates/foo/bar_baz",
|
||||||
"with subdir defined by slash"
|
"with subdir defined by slash"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -69,7 +83,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo.bar_baz",
|
"template:foo.bar_baz",
|
||||||
"foo/bar_baz",
|
"discourse/templates/foo/bar_baz",
|
||||||
"with subdir defined by dot"
|
"with subdir defined by dot"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -77,7 +91,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo-bar_baz",
|
"template:foo-bar_baz",
|
||||||
"foo/bar_baz",
|
"discourse/templates/foo/bar_baz",
|
||||||
"with subdir defined by dash"
|
"with subdir defined by dash"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -85,7 +99,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:fooBarBaz",
|
"template:fooBarBaz",
|
||||||
"foo/bar_baz",
|
"discourse/templates/foo/bar_baz",
|
||||||
"with subdir defined by first camel case and the rest of camel cases converted to underscores"
|
"with subdir defined by first camel case and the rest of camel cases converted to underscores"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -93,19 +107,25 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo_bar_baz",
|
"template:foo_bar_baz",
|
||||||
"foo/bar_baz",
|
"discourse/templates/foo/bar_baz",
|
||||||
"with subdir defined by first underscore"
|
"with subdir defined by first underscore"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolves precedence between overlapping top level dir and first level subdir templates", function (assert) {
|
test("resolves precedence between overlapping top level dir and first level subdir templates", function (assert) {
|
||||||
setTemplates(["fooBar", "foo_bar", "foo.bar", "foo/bar", "baz/qux"]);
|
setTemplates([
|
||||||
|
"discourse/templates/fooBar",
|
||||||
|
"discourse/templates/foo_bar",
|
||||||
|
"discourse/templates/foo.bar",
|
||||||
|
"discourse/templates/foo/bar",
|
||||||
|
"discourse/templates/baz/qux",
|
||||||
|
]);
|
||||||
|
|
||||||
// Directories are prioritized when dotted
|
// Directories are prioritized when dotted
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo.bar",
|
"template:foo.bar",
|
||||||
"foo/bar",
|
"discourse/templates/foo/bar",
|
||||||
"preferring first level subdir for dotted name"
|
"preferring first level subdir for dotted name"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -113,7 +133,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo-bar",
|
"template:foo-bar",
|
||||||
"foo/bar",
|
"discourse/templates/foo/bar",
|
||||||
"preferring first level subdir for dotted name"
|
"preferring first level subdir for dotted name"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -121,7 +141,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:fooBar",
|
"template:fooBar",
|
||||||
"fooBar",
|
"discourse/templates/fooBar",
|
||||||
"preferring top level dir for camel cased name"
|
"preferring top level dir for camel cased name"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -129,7 +149,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo_bar",
|
"template:foo_bar",
|
||||||
"foo_bar",
|
"discourse/templates/foo_bar",
|
||||||
"preferring top level dir for underscored name"
|
"preferring top level dir for underscored name"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -137,19 +157,19 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:baz-qux",
|
"template:baz-qux",
|
||||||
"baz/qux",
|
"discourse/templates/baz/qux",
|
||||||
"fallback subdir for dashed name"
|
"fallback subdir for dashed name"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("finds templates in subdir deeper than one level", function (assert) {
|
test("finds templates in subdir deeper than one level", function (assert) {
|
||||||
setTemplates(["foo/bar/baz/qux"]);
|
setTemplates(["discourse/templates/foo/bar/baz/qux"]);
|
||||||
|
|
||||||
// Default unmodified
|
// Default unmodified
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo/bar/baz/qux",
|
"template:foo/bar/baz/qux",
|
||||||
"foo/bar/baz/qux",
|
"discourse/templates/foo/bar/baz/qux",
|
||||||
"for subdirs defined by slashes"
|
"for subdirs defined by slashes"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -157,7 +177,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo.bar.baz.qux",
|
"template:foo.bar.baz.qux",
|
||||||
"foo/bar/baz/qux",
|
"discourse/templates/foo/bar/baz/qux",
|
||||||
"for subdirs defined by dots"
|
"for subdirs defined by dots"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -165,7 +185,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo/bar/bazQux",
|
"template:foo/bar/bazQux",
|
||||||
"foo/bar/baz/qux",
|
"discourse/templates/foo/bar/baz/qux",
|
||||||
"for subdirs defined by slashes plus one camel case"
|
"for subdirs defined by slashes plus one camel case"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -173,7 +193,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo/bar/baz_qux",
|
"template:foo/bar/baz_qux",
|
||||||
"foo/bar/baz/qux",
|
"discourse/templates/foo/bar/baz/qux",
|
||||||
"for subdirs defined by slashes plus one underscore"
|
"for subdirs defined by slashes plus one underscore"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -211,7 +231,12 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolves mobile templates to 'mobile/' namespace", function (assert) {
|
test("resolves mobile templates to 'mobile/' namespace", function (assert) {
|
||||||
setTemplates(["mobile/foo", "bar", "mobile/bar", "baz"]);
|
setTemplates([
|
||||||
|
"discourse/templates/mobile/foo",
|
||||||
|
"discourse/templates/bar",
|
||||||
|
"discourse/templates/mobile/bar",
|
||||||
|
"discourse/templates/baz",
|
||||||
|
]);
|
||||||
|
|
||||||
setResolverOption("mobileView", true);
|
setResolverOption("mobileView", true);
|
||||||
|
|
||||||
|
@ -219,7 +244,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo",
|
"template:foo",
|
||||||
"mobile/foo",
|
"discourse/templates/mobile/foo",
|
||||||
"finding mobile version even if normal one is not present"
|
"finding mobile version even if normal one is not present"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -227,7 +252,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:bar",
|
"template:bar",
|
||||||
"mobile/bar",
|
"discourse/templates/mobile/bar",
|
||||||
"preferring mobile version when both mobile and normal versions are present"
|
"preferring mobile version when both mobile and normal versions are present"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -235,71 +260,87 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:baz",
|
"template:baz",
|
||||||
"baz",
|
"discourse/templates/baz",
|
||||||
"falling back to a normal version when mobile version is not present"
|
"falling back to a normal version when mobile version is not present"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolves plugin templates to 'javascripts/' namespace", function (assert) {
|
test("resolves templates to plugin and theme namespaces", function (assert) {
|
||||||
setTemplates(["javascripts/foo", "bar", "javascripts/bar", "baz"]);
|
setTemplates([
|
||||||
|
"discourse/plugins/my-plugin/discourse/templates/foo",
|
||||||
|
"discourse/templates/bar",
|
||||||
|
"discourse/plugins/my-plugin/discourse/templates/bar",
|
||||||
|
"discourse/templates/baz",
|
||||||
|
"discourse/plugins/my-plugin/discourse/templates/baz",
|
||||||
|
"discourse/theme-12/discourse/templates/baz",
|
||||||
|
"discourse/templates/qux",
|
||||||
|
]);
|
||||||
|
|
||||||
// Default with javascripts/ added
|
// Defined in plugin only
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo",
|
"template:foo",
|
||||||
"javascripts/foo",
|
"discourse/plugins/my-plugin/discourse/templates/foo",
|
||||||
"finding plugin version even if normal one is not present"
|
"finding plugin version even if normal one is not present"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default with javascripts/ added, takes precedence
|
// Defined in core and plugin
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:bar",
|
"template:bar",
|
||||||
"javascripts/bar",
|
"discourse/plugins/my-plugin/discourse/templates/bar",
|
||||||
"preferring plugin version when both versions are present"
|
"prefers plugin version over core"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default when javascripts version not present
|
// Defined in core and plugin and theme
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:baz",
|
"template:baz",
|
||||||
"baz",
|
"discourse/theme-12/discourse/templates/baz",
|
||||||
"falling back to a normal version when plugin version is not present"
|
"prefers theme version over plugin and core"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Defined in core only
|
||||||
|
lookupTemplate(
|
||||||
|
assert,
|
||||||
|
"template:qux",
|
||||||
|
"discourse/templates/qux",
|
||||||
|
"uses core if there are no theme/plugin definitions"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolves plugin mobile templates to 'javascripts/mobile/' namespace", function (assert) {
|
test("resolves plugin mobile templates", function (assert) {
|
||||||
setTemplates([
|
setTemplates([
|
||||||
"javascripts/mobile/foo",
|
"discourse/plugins/my-plugin/discourse/templates/mobile/foo",
|
||||||
"javascripts/mobile/bar",
|
"discourse/plugins/my-plugin/discourse/templates/mobile/bar",
|
||||||
"javascripts/bar",
|
"discourse/plugins/my-plugin/discourse/templates/bar",
|
||||||
"javascripts/mobile/baz",
|
"discourse/plugins/my-plugin/discourse/templates/mobile/baz",
|
||||||
"mobile/baz",
|
"discourse/templates/mobile/baz",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setResolverOption("mobileView", true);
|
setResolverOption("mobileView", true);
|
||||||
|
|
||||||
// Default with javascripts/mobile/ added
|
// Default with plugin template override
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo",
|
"template:foo",
|
||||||
"javascripts/mobile/foo",
|
"discourse/plugins/my-plugin/discourse/templates/mobile/foo",
|
||||||
"finding plugin version even if normal one is not present"
|
"finding plugin version even if normal one is not present"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default with javascripts/mobile added, takes precedence over non-mobile
|
// Default with plugin mobile added, takes precedence over non-mobile
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:bar",
|
"template:bar",
|
||||||
"javascripts/mobile/bar",
|
"discourse/plugins/my-plugin/discourse/templates/mobile/bar",
|
||||||
"preferring plugin mobile version when both non-mobile plugin version is also present"
|
"preferring plugin mobile version when both non-mobile plugin version is also present"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default with javascripts/mobile when non-plugin mobile version is present
|
// Default with when non-plugin mobile version is present
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:baz",
|
"template:baz",
|
||||||
"javascripts/mobile/baz",
|
"discourse/plugins/my-plugin/discourse/templates/mobile/baz",
|
||||||
"preferring plugin mobile version over non-plugin mobile version"
|
"preferring plugin mobile version over non-plugin mobile version"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -307,13 +348,13 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
test("resolves templates with 'admin' prefix", function (assert) {
|
test("resolves templates with 'admin' prefix", function (assert) {
|
||||||
setTemplates([
|
setTemplates([
|
||||||
"admin/templates/foo",
|
"admin/templates/foo",
|
||||||
"adminBar",
|
"discourse/templates/adminBar",
|
||||||
"admin_bar",
|
"discourse/templates/admin_bar",
|
||||||
"admin.bar",
|
"discourse/templates/admin.bar",
|
||||||
"admin/templates/bar",
|
"admin/templates/bar",
|
||||||
"admin/templates/dashboard_general",
|
"admin/templates/dashboard_general",
|
||||||
"admin-baz-qux",
|
"discourse/templates/admin-baz-qux",
|
||||||
"javascripts/admin/plugin-template",
|
"discourse/plugins/my-plugin/discourse/templates/admin/plugin-template",
|
||||||
"admin/templates/components/my-admin-component",
|
"admin/templates/components/my-admin-component",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -353,7 +394,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:adminBar",
|
"template:adminBar",
|
||||||
"adminBar",
|
"discourse/templates/adminBar",
|
||||||
"but not when template with the exact camel cased name exists"
|
"but not when template with the exact camel cased name exists"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -361,7 +402,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:admin_bar",
|
"template:admin_bar",
|
||||||
"admin_bar",
|
"discourse/templates/admin_bar",
|
||||||
"but not when template with the exact underscored name exists"
|
"but not when template with the exact underscored name exists"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -369,7 +410,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:admin.bar",
|
"template:admin.bar",
|
||||||
"admin.bar",
|
"discourse/templates/admin.bar",
|
||||||
"but not when template with the exact dotted name exists"
|
"but not when template with the exact dotted name exists"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -383,14 +424,14 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:admin-baz/qux",
|
"template:admin-baz/qux",
|
||||||
"admin-baz-qux",
|
"discourse/templates/admin-baz-qux",
|
||||||
"also tries dasherized"
|
"also tries dasherized"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:admin-plugin/template",
|
"template:admin-plugin/template",
|
||||||
"javascripts/admin/plugin-template",
|
"discourse/plugins/my-plugin/discourse/templates/admin/plugin-template",
|
||||||
"looks up templates in plugins"
|
"looks up templates in plugins"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -412,7 +453,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
test("resolves component templates with 'admin' prefix to 'admin/templates/' namespace", function (assert) {
|
test("resolves component templates with 'admin' prefix to 'admin/templates/' namespace", function (assert) {
|
||||||
setTemplates([
|
setTemplates([
|
||||||
"admin/templates/components/foo",
|
"admin/templates/components/foo",
|
||||||
"components/bar",
|
"discourse/templates/components/bar",
|
||||||
"admin/templates/components/bar",
|
"admin/templates/components/bar",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -428,7 +469,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:components/bar",
|
"template:components/bar",
|
||||||
"components/bar",
|
"discourse/templates/components/bar",
|
||||||
"uses standard match when both exist"
|
"uses standard match when both exist"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -437,54 +478,59 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
// close to Ember's default behavior.
|
// close to Ember's default behavior.
|
||||||
// See https://guides.emberjs.com/release/routing/loading-and-error-substates/
|
// See https://guides.emberjs.com/release/routing/loading-and-error-substates/
|
||||||
test("resolves loading templates", function (assert) {
|
test("resolves loading templates", function (assert) {
|
||||||
setTemplates(["fooloading", "foo/loading", "foo_loading", "loading"]);
|
setTemplates([
|
||||||
|
"discourse/templates/fooloading",
|
||||||
|
"discourse/templates/foo/loading",
|
||||||
|
"discourse/templates/foo_loading",
|
||||||
|
"discourse/templates/loading",
|
||||||
|
]);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:fooloading",
|
"template:fooloading",
|
||||||
"fooloading",
|
"discourse/templates/fooloading",
|
||||||
"exact match without separator"
|
"exact match without separator"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo/loading",
|
"template:foo/loading",
|
||||||
"foo/loading",
|
"discourse/templates/foo/loading",
|
||||||
"exact match with slash"
|
"exact match with slash"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:foo_loading",
|
"template:foo_loading",
|
||||||
"foo_loading",
|
"discourse/templates/foo_loading",
|
||||||
"exact match underscore"
|
"exact match underscore"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:barloading",
|
"template:barloading",
|
||||||
"loading",
|
"discourse/templates/loading",
|
||||||
"fallback without separator"
|
"fallback without separator"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:bar/loading",
|
"template:bar/loading",
|
||||||
"loading",
|
"discourse/templates/loading",
|
||||||
"fallback with slash"
|
"fallback with slash"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:bar.loading",
|
"template:bar.loading",
|
||||||
"loading",
|
"discourse/templates/loading",
|
||||||
"fallback with dot"
|
"fallback with dot"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:bar_loading",
|
"template:bar_loading",
|
||||||
"loading",
|
"discourse/templates/loading",
|
||||||
"fallback underscore"
|
"fallback underscore"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -493,61 +539,66 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
|
|
||||||
test("resolves connector templates", function (assert) {
|
test("resolves connector templates", function (assert) {
|
||||||
setTemplates([
|
setTemplates([
|
||||||
"javascripts/foo",
|
"discourse/plugins/my-plugin/discourse/templates/foo",
|
||||||
"javascripts/connectors/foo-bar/baz_qux",
|
"discourse/plugins/my-plugin/discourse/templates/connectors/foo-bar/baz_qux",
|
||||||
"javascripts/connectors/foo-bar/camelCase",
|
"discourse/plugins/my-plugin/discourse/templates/connectors/foo-bar/camelCase",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:connectors/foo",
|
"template:connectors/foo",
|
||||||
"javascripts/foo",
|
"discourse/plugins/my-plugin/discourse/templates/foo",
|
||||||
"looks up in javascripts/ namespace"
|
"looks up in plugin namespace"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:connectors/components/foo",
|
"template:connectors/components/foo",
|
||||||
"javascripts/foo",
|
"discourse/plugins/my-plugin/discourse/templates/foo",
|
||||||
"removes components segment"
|
"removes components segment"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:connectors/foo-bar/baz-qux",
|
"template:connectors/foo-bar/baz-qux",
|
||||||
"javascripts/connectors/foo-bar/baz_qux",
|
"discourse/plugins/my-plugin/discourse/templates/connectors/foo-bar/baz_qux",
|
||||||
"underscores last segment"
|
"underscores last segment"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:connectors/foo-bar/camelCase",
|
"template:connectors/foo-bar/camelCase",
|
||||||
"javascripts/connectors/foo-bar/camelCase",
|
"discourse/plugins/my-plugin/discourse/templates/connectors/foo-bar/camelCase",
|
||||||
"handles camelcase file names"
|
"handles camelcase file names"
|
||||||
);
|
);
|
||||||
|
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
resolver.normalize("template:connectors/foo-bar/camelCase"),
|
resolver.normalize("template:connectors/foo-bar/camelCase"),
|
||||||
"javascripts/connectors/foo-bar/camelCase",
|
"discourse/plugins/my-plugin/discourse/templates/connectors/foo-bar/camelCase",
|
||||||
"handles camelcase file names when normalized"
|
"handles camelcase file names when normalized"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("returns 'not_found' template when template name cannot be resolved", function (assert) {
|
test("returns 'not_found' template when template name cannot be resolved", function (assert) {
|
||||||
setTemplates(["not_found"]);
|
setTemplates(["discourse/templates/not_found"]);
|
||||||
|
|
||||||
lookupTemplate(assert, "template:foo/bar/baz", "not_found", "");
|
lookupTemplate(
|
||||||
|
assert,
|
||||||
|
"template:foo/bar/baz",
|
||||||
|
"discourse/templates/not_found",
|
||||||
|
""
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolves templates with 'wizard' prefix", function (assert) {
|
test("resolves templates with 'wizard' prefix", function (assert) {
|
||||||
setTemplates([
|
setTemplates([
|
||||||
"wizard/templates/foo",
|
"wizard/templates/foo",
|
||||||
"wizard_bar",
|
"discourse/templates/wizard_bar",
|
||||||
"wizard.bar",
|
"discourse/templates/wizard.bar",
|
||||||
"wizard/templates/bar",
|
"wizard/templates/bar",
|
||||||
"wizard/templates/dashboard_general",
|
"wizard/templates/dashboard_general",
|
||||||
"wizard-baz-qux",
|
"discourse/templates/wizard-baz-qux",
|
||||||
"javascripts/wizard/plugin-template",
|
"javascripts/wizard/plugin-template",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -579,7 +630,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:wizard_bar",
|
"template:wizard_bar",
|
||||||
"wizard_bar",
|
"discourse/templates/wizard_bar",
|
||||||
"but not when template with the exact underscored name exists"
|
"but not when template with the exact underscored name exists"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -587,7 +638,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:wizard.bar",
|
"template:wizard.bar",
|
||||||
"wizard.bar",
|
"discourse/templates/wizard.bar",
|
||||||
"but not when template with the exact dotted name exists"
|
"but not when template with the exact dotted name exists"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -601,7 +652,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:wizard-baz/qux",
|
"template:wizard-baz/qux",
|
||||||
"wizard-baz-qux",
|
"discourse/templates/wizard-baz-qux",
|
||||||
"also tries dasherized"
|
"also tries dasherized"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -609,7 +660,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
test("resolves component templates with 'wizard' prefix to 'wizard/templates/' namespace", function (assert) {
|
test("resolves component templates with 'wizard' prefix to 'wizard/templates/' namespace", function (assert) {
|
||||||
setTemplates([
|
setTemplates([
|
||||||
"wizard/templates/components/foo",
|
"wizard/templates/components/foo",
|
||||||
"components/bar",
|
"discourse/templates/components/bar",
|
||||||
"wizard/templates/components/bar",
|
"wizard/templates/components/bar",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -625,7 +676,7 @@ module("Unit | Ember | resolver", function (hooks) {
|
||||||
lookupTemplate(
|
lookupTemplate(
|
||||||
assert,
|
assert,
|
||||||
"template:components/bar",
|
"template:components/bar",
|
||||||
"components/bar",
|
"discourse/templates/components/bar",
|
||||||
"uses standard match when both exist"
|
"uses standard match when both exist"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import DiscourseTemplateMap from "discourse-common/lib/discourse-template-map";
|
||||||
let _allCategories = null;
|
let _allCategories = null;
|
||||||
let _sectionsById = {};
|
let _sectionsById = {};
|
||||||
let _notes = {};
|
let _notes = {};
|
||||||
|
@ -30,7 +31,7 @@ export function allCategories() {
|
||||||
|
|
||||||
// Find a list of sections based on what templates are available
|
// Find a list of sections based on what templates are available
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
Object.keys(Ember.TEMPLATES).forEach((e) => {
|
DiscourseTemplateMap.keys().forEach((e) => {
|
||||||
let regexp = new RegExp(`styleguide\/(${paths})\/(\\d+)?\\-?([^\\/]+)$`);
|
let regexp = new RegExp(`styleguide\/(${paths})\/(\\d+)?\\-?([^\\/]+)$`);
|
||||||
let matches = e.match(regexp);
|
let matches = e.match(regexp);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
|
|
Loading…
Reference in New Issue