From 16c6ab8661b38051b14d68297afdc8504bc1175b Mon Sep 17 00:00:00 2001 From: David Taylor Date: Fri, 18 Aug 2023 12:07:10 +0100 Subject: [PATCH] DEV: Allow plugin outlets to be defined using gjs (#23142) Previously we were discovering plugin outlets by checking first for dedicated template files, and then looking for classes to match them. This doesn't work for components which are entirely defined in JS (e.g. those authored with gjs, or those which are re-exports of a colocated component). This commit refactors our detection logic to look for both class and template modules in a single pass. It also refactors things so that the modules themselves are required lazily when needd, rather than all being loaded during app boot. --- .../addon/lib/raw-templates.js | 13 ++- .../discourse/app/lib/plugin-connectors.js | 93 ++++++++++--------- .../components/plugin-outlet-test.js | 36 ++++++- app/models/theme.rb | 2 +- app/models/theme_field.rb | 5 +- 5 files changed, 95 insertions(+), 54 deletions(-) diff --git a/app/assets/javascripts/discourse-common/addon/lib/raw-templates.js b/app/assets/javascripts/discourse-common/addon/lib/raw-templates.js index 5a8bd75e100..2a7c2a3a747 100644 --- a/app/assets/javascripts/discourse-common/addon/lib/raw-templates.js +++ b/app/assets/javascripts/discourse-common/addon/lib/raw-templates.js @@ -31,17 +31,20 @@ export function findRawTemplate(name) { ); } -export function buildRawConnectorCache(findOutlets) { +export function buildRawConnectorCache() { let result = {}; - findOutlets( - Object.keys(__DISCOURSE_RAW_TEMPLATES), - (outletName, resource) => { + Object.keys(__DISCOURSE_RAW_TEMPLATES).forEach((resource) => { + const segments = resource.split("/"); + const connectorIndex = segments.indexOf("connectors"); + + if (connectorIndex >= 0) { + const outletName = segments[connectorIndex + 1]; result[outletName] ??= []; result[outletName].push({ template: __DISCOURSE_RAW_TEMPLATES[resource], }); } - ); + }); return result; } diff --git a/app/assets/javascripts/discourse/app/lib/plugin-connectors.js b/app/assets/javascripts/discourse/app/lib/plugin-connectors.js index 1315bbcc1b2..2a7e1411f8a 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-connectors.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-connectors.js @@ -1,6 +1,5 @@ import { buildRawConnectorCache } from "discourse-common/lib/raw-templates"; import deprecated from "discourse-common/lib/deprecated"; -import DiscourseTemplateMap from "discourse-common/lib/discourse-template-map"; import { getComponentTemplate, hasInternalComponentManager, @@ -11,11 +10,9 @@ import templateOnly from "@ember/component/template-only"; let _connectorCache; let _rawConnectorCache; let _extraConnectorClasses = {}; -let _classPaths; export function resetExtraClasses() { _extraConnectorClasses = {}; - _classPaths = undefined; } // Note: In plugins, define a class by path and it will be wired up automatically @@ -24,14 +21,19 @@ export function extraConnectorClass(name, obj) { _extraConnectorClasses[name] = obj; } -function findOutlets(keys, callback) { - keys.forEach(function (res) { - const segments = res.split("/"); - if (segments.includes("connectors")) { - const outletName = segments[segments.length - 2]; - const uniqueName = segments[segments.length - 1]; +const OUTLET_REGEX = + /^discourse(\/[^\/]+)*?(?