discourse/app/assets/javascripts/discourse-common/resolver.js.es6
Robin Ward f5d391a48a
REFACTOR: Move app-events:main to service:app-events (#8152)
AppEvents was always a service object in disguise, so we should move it
to the correct place in the application. Doing this allows other service
objects to inject it easily without container access.

In the future we should also deprecate `this.appEvents` without an
explicit injection too.
2019-10-04 10:06:08 -04:00

262 lines
7.8 KiB
JavaScript

import { findHelper } from "discourse-common/lib/helpers";
import deprecated from "discourse-common/lib/deprecated";
/* global requirejs, require */
var classify = Ember.String.classify;
var get = Ember.get;
const _options = {};
export function setResolverOption(name, value) {
_options[name] = value;
}
export function getResolverOption(name) {
return _options[name];
}
function parseName(fullName) {
const nameParts = fullName.split(":");
const type = nameParts[0];
let fullNameWithoutType = nameParts[1];
const namespace = get(this, "namespace");
const root = namespace;
return {
fullName,
type,
fullNameWithoutType,
name: fullNameWithoutType,
root,
resolveMethodName: "resolve" + classify(type)
};
}
export function buildResolver(baseName) {
return Ember.DefaultResolver.extend({
parseName,
resolveRouter(parsedName) {
const routerPath = `${baseName}/router`;
if (requirejs.entries[routerPath]) {
const module = requirejs(routerPath, null, null, true);
return module.default;
}
return this._super(parsedName);
},
normalize(fullName) {
if (fullName === "app-events:main") {
deprecated(
"`app-events:main` has been replaced with `service:app-events`",
{ since: "2.4.0" }
);
return "service:app-events";
}
const split = fullName.split(":");
if (split.length > 1) {
const appBase = `${baseName}/${split[0]}s/`;
const adminBase = "admin/" + split[0] + "s/";
// Allow render 'admin/templates/xyz' too
split[1] = split[1].replace(".templates", "").replace("/templates", "");
// Try slashes
let dashed = Ember.String.dasherize(split[1].replace(/\./g, "/"));
if (
requirejs.entries[appBase + dashed] ||
requirejs.entries[adminBase + dashed]
) {
return split[0] + ":" + dashed;
}
// Try with dashes instead of slashes
dashed = Ember.String.dasherize(split[1].replace(/\./g, "-"));
if (
requirejs.entries[appBase + dashed] ||
requirejs.entries[adminBase + dashed]
) {
return split[0] + ":" + dashed;
}
}
return this._super(fullName);
},
customResolve(parsedName) {
// If we end with the name we want, use it. This allows us to define components within plugins.
const suffix = parsedName.type + "s/" + parsedName.fullNameWithoutType,
dashed = Ember.String.dasherize(suffix),
moduleName = Object.keys(requirejs.entries).find(function(e) {
return (
e.indexOf(suffix, e.length - suffix.length) !== -1 ||
e.indexOf(dashed, e.length - dashed.length) !== -1
);
});
var module;
if (moduleName) {
module = requirejs(moduleName, null, null, true /* force sync */);
if (module && module["default"]) {
module = module["default"];
}
}
return module;
},
resolveWidget(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveAdapter(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveModel(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveView(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveHelper(parsedName) {
return (
findHelper(parsedName.fullNameWithoutType) ||
this.customResolve(parsedName) ||
this._super(parsedName)
);
},
resolveController(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveComponent(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveService(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
resolveRoute(parsedName) {
return this.customResolve(parsedName) || this._super(parsedName);
},
findLoadingTemplate(parsedName) {
if (parsedName.fullNameWithoutType.match(/loading$/)) {
return Ember.TEMPLATES.loading;
}
},
findConnectorTemplate(parsedName) {
const full = parsedName.fullNameWithoutType.replace("components/", "");
if (full.indexOf("connectors") === 0) {
return Ember.TEMPLATES[`javascripts/${full}`];
}
},
resolveTemplate(parsedName) {
return (
this.findPluginMobileTemplate(parsedName) ||
this.findPluginTemplate(parsedName) ||
this.findMobileTemplate(parsedName) ||
this.findTemplate(parsedName) ||
this.findLoadingTemplate(parsedName) ||
this.findConnectorTemplate(parsedName) ||
Ember.TEMPLATES.not_found
);
},
findPluginTemplate(parsedName) {
const pluginParsedName = this.parseName(
parsedName.fullName.replace("template:", "template:javascripts/")
);
return this.findTemplate(pluginParsedName);
},
findPluginMobileTemplate(parsedName) {
if (_options.mobileView) {
var pluginParsedName = this.parseName(
parsedName.fullName.replace(
"template:",
"template:javascripts/mobile/"
)
);
return this.findTemplate(pluginParsedName);
}
},
findMobileTemplate(parsedName) {
if (_options.mobileView) {
var mobileParsedName = this.parseName(
parsedName.fullName.replace("template:", "template:mobile/")
);
return this.findTemplate(mobileParsedName);
}
},
findTemplate(parsedName) {
const withoutType = parsedName.fullNameWithoutType,
slashedType = withoutType.replace(/\./g, "/"),
decamelized = withoutType.decamelize(),
dashed = decamelized.replace(/\./g, "-").replace(/\_/g, "-"),
templates = Ember.TEMPLATES;
return (
this._super(parsedName) ||
templates[slashedType] ||
templates[withoutType] ||
templates[withoutType.replace(/\.raw$/, "")] ||
templates[dashed] ||
templates[decamelized.replace(/\./, "/")] ||
templates[decamelized.replace(/\_/, "/")] ||
templates[`${baseName}/templates/${withoutType}`] ||
this.findAdminTemplate(parsedName) ||
this.findUnderscoredTemplate(parsedName)
);
},
findUnderscoredTemplate(parsedName) {
var decamelized = parsedName.fullNameWithoutType.decamelize();
var underscored = decamelized.replace(/\-/g, "_");
return Ember.TEMPLATES[underscored];
},
// Try to find a template within a special admin namespace, e.g. adminEmail => admin/templates/email
// (similar to how discourse lays out templates)
findAdminTemplate(parsedName) {
var decamelized = parsedName.fullNameWithoutType.decamelize();
if (decamelized.indexOf("components") === 0) {
let comPath = `admin/templates/${decamelized}`;
const compTemplate =
Ember.TEMPLATES[`javascripts/${comPath}`] || Ember.TEMPLATES[comPath];
if (compTemplate) {
return compTemplate;
}
}
if (decamelized === "javascripts/admin") {
return Ember.TEMPLATES["admin/templates/admin"];
}
if (
decamelized.indexOf("admin") === 0 ||
decamelized.indexOf("javascripts/admin") === 0
) {
decamelized = decamelized.replace(/^admin\_/, "admin/templates/");
decamelized = decamelized.replace(/^admin\./, "admin/templates/");
decamelized = decamelized.replace(/\./g, "_");
const dashed = decamelized.replace(/_/g, "-");
return (
Ember.TEMPLATES[decamelized] ||
Ember.TEMPLATES[dashed] ||
Ember.TEMPLATES[dashed.replace("admin-", "admin/")]
);
}
}
});
}