mirror of
https://github.com/discourse/discourse.git
synced 2025-01-24 05:13:57 +08:00
146 lines
3.7 KiB
JavaScript
146 lines
3.7 KiB
JavaScript
import { defaultHomepage } from 'discourse/lib/utilities';
|
|
import { rewritePath } from 'discourse/lib/url';
|
|
|
|
const rootURL = Discourse.BaseUri;
|
|
|
|
const BareRouter = Ember.Router.extend({
|
|
rootURL,
|
|
location: Ember.testing ? 'none': 'discourse-location',
|
|
|
|
handleURL(url) {
|
|
url = rewritePath(url);
|
|
const params = url.split('?');
|
|
|
|
if (params[0] === "/") {
|
|
url = defaultHomepage();
|
|
if (params[1] && params[1].length) {
|
|
url = `${url}?${params[1]}`;
|
|
}
|
|
}
|
|
return this._super(url);
|
|
}
|
|
});
|
|
|
|
// Ember's router can't be extended. We need to allow plugins to add routes to routes that were defined
|
|
// in the core app. This class has the same API as Ember's `Router.map` but saves the results in a tree.
|
|
// The tree is applied after all plugins are defined.
|
|
class RouteNode {
|
|
constructor(name, opts={}, depth=0) {
|
|
this.name = name;
|
|
this.opts = opts;
|
|
this.depth = depth;
|
|
this.children = [];
|
|
this.childrenByName = {};
|
|
this.paths = {};
|
|
|
|
if (!opts.path) {
|
|
opts.path = name;
|
|
}
|
|
|
|
this.paths[opts.path] = true;
|
|
}
|
|
|
|
route(name, opts, fn) {
|
|
if (typeof opts === 'function') {
|
|
fn = opts;
|
|
opts = {};
|
|
} else {
|
|
opts = opts || {};
|
|
}
|
|
|
|
const existing = this.childrenByName[name];
|
|
if (existing) {
|
|
if (opts.path) {
|
|
existing.paths[opts.path] = true;
|
|
}
|
|
existing.extract(fn);
|
|
} else {
|
|
const node = new RouteNode(name, opts, this.depth+1);
|
|
node.extract(fn);
|
|
this.childrenByName[name] = node;
|
|
this.children.push(node);
|
|
}
|
|
}
|
|
|
|
extract(fn) {
|
|
if (!fn) { return; }
|
|
fn.call(this);
|
|
}
|
|
|
|
mapRoutes(router) {
|
|
const children = this.children;
|
|
if (this.name === 'root') {
|
|
children.forEach(c => c.mapRoutes(router));
|
|
} else {
|
|
|
|
const builder = (children.length === 0) ? undefined : function() {
|
|
children.forEach(c => c.mapRoutes(this));
|
|
};
|
|
router.route(this.name, this.opts, builder);
|
|
|
|
// We can have multiple paths to the same route
|
|
const paths = Object.keys(this.paths);
|
|
if (paths.length > 1) {
|
|
paths.filter(p => p !== this.opts.path).forEach(path => {
|
|
const newOpts = jQuery.extend({}, this.opts, { path });
|
|
console.log(`warning: we can't have duplicate route names anymore`, newOpts);
|
|
// router.route(this.name, newOpts, builder);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
findSegment(segments) {
|
|
if (segments && segments.length) {
|
|
const first = segments.shift();
|
|
const node = this.childrenByName[first];
|
|
if (node) {
|
|
return (segments.length === 0) ? node : node.findSegment(segments);
|
|
}
|
|
}
|
|
}
|
|
|
|
findPath(path) {
|
|
if (path) {
|
|
return this.findSegment(path.split('.'));
|
|
}
|
|
}
|
|
}
|
|
|
|
export function mapRoutes() {
|
|
const tree = new RouteNode('root');
|
|
const extras = [];
|
|
|
|
// If a module is defined as `route-map` in discourse or a plugin, its routes
|
|
// will be built automatically. You can supply a `resource` property to
|
|
// automatically put it in that resource, such as `admin`. That way plugins
|
|
// can define admin routes.
|
|
Object.keys(requirejs._eak_seen).forEach(function(key) {
|
|
if (/route-map$/.test(key)) {
|
|
var module = require(key, null, null, true);
|
|
if (!module || !module.default) { throw new Error(key + ' must export a route map.'); }
|
|
|
|
const mapObj = module.default;
|
|
if (typeof mapObj === 'function') {
|
|
tree.extract(mapObj);
|
|
} else {
|
|
extras.push(mapObj);
|
|
}
|
|
}
|
|
});
|
|
|
|
extras.forEach(extra => {
|
|
const node = tree.findPath(extra.resource);
|
|
if (node) {
|
|
node.extract(extra.map);
|
|
}
|
|
});
|
|
|
|
return BareRouter.extend().map(function() {
|
|
tree.mapRoutes(this);
|
|
this.route('unknown', {path: '*path'});
|
|
});
|
|
}
|
|
|
|
export default BareRouter;
|