/**
A plugin outlet is an extension point for templates where other templates can
be inserted by plugins.
## Usage
If your handlebars template has:
```handlebars
{{plugin-outlet "evil-trout"}}
```
Then any handlebars files you create in the `connectors/evil-trout` directory
will automatically be appended. For example:
plugins/hello/assets/javascripts/discourse/templates/connectors/evil-trout/hello.hbs
With the contents:
```handlebars
Hello World
```
Will insert Hello World at that point in the template.
## Disabling
If a plugin returns a disabled status, the outlets will not be wired up for it.
The list of disabled plugins is returned via the `Site` singleton.
**/
let _connectorCache, _templateCache;
function findOutlets(collection, callback) {
const disabledPlugins = Discourse.Site.currentProp('disabled_plugins') || [];
Object.keys(collection).forEach(function(res) {
if (res.indexOf("/connectors/") !== -1) {
// Skip any disabled plugins
for (let i=0; i {
const connector = _connectorCache[outletName];
(connector || []).forEach(s => {
_templateCache.push(s.template);
s.templateId = parseInt(_templateCache.length - 1);
});
});
}
// unbound version of outlets, only has a template
Handlebars.registerHelper('plugin-outlet', function(name) {
if (!_connectorCache) { buildConnectorCache(); }
const connector = _connectorCache[name];
if (connector && connector.length) {
const output = connector.map(c => c.template({context: this}));
return new Handlebars.SafeString(output.join(""));
}
});
const { registerKeyword } = Ember.__loader.require("ember-htmlbars/keywords");
const { internal } = Ember.__loader.require('htmlbars-runtime');
registerKeyword('plugin-outlet', {
setupState(state, env, scope, params) {
if (!_connectorCache) { buildConnectorCache(); }
return { outletName: env.hooks.getValue(params[0]) };
},
render(renderNode, env, scope, params, hash, template, inverse, visitor) {
let state = renderNode.getState();
if (!state.outletName) { return true; }
const connector = _connectorCache[state.outletName];
if (!connector || connector.length === 0) { return true; }
const listTemplate = Ember.TEMPLATES['outlet-list'];
listTemplate.raw.locals = ['templateId', 'outletClasses', 'tagName'];
internal.hostBlock(renderNode, env, scope, listTemplate.raw, null, null, visitor, function(options) {
connector.forEach(source => {
const tid = source.templateId;
options.templates.template.yieldItem(`d-outlet-${tid}`, [
tid,
source.classNames,
hash.tagName || 'div'
]);
});
});
return true;
}
});
registerKeyword('connector', function(morph, env, scope, params, hash, template, inverse, visitor) {
template = _templateCache[parseInt(env.hooks.getValue(hash.templateId))];
env.hooks.component(morph,
env,
scope,
'connector-container',
params,
hash,
{ default: template.raw, inverse },
visitor);
return true;
});