Skip to content

Commit 1fc6aa8

Browse files
feat: support idAliases for PluginSlots (#110)
1 parent 78ddff8 commit 1fc6aa8

File tree

3 files changed

+89
-6
lines changed

3 files changed

+89
-6
lines changed

src/plugins/PluginSlot.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ function BasePluginSlot({
1414
as = React.Fragment,
1515
children = null,
1616
id,
17+
idAliases = [],
1718
pluginProps = {},
1819
slotOptions = {},
1920
slotErrorFallbackComponent,
@@ -23,7 +24,7 @@ function BasePluginSlot({
2324
for an example of how PluginSlot is populated, and example/src/index.jsx for a dummy JS config that holds all plugins
2425
*/
2526

26-
const { keepDefault, plugins } = usePluginSlot(id);
27+
const { keepDefault, plugins } = usePluginSlot(id, idAliases);
2728
const { formatMessage } = useIntl();
2829

2930
const defaultContents = React.useMemo(() => {
@@ -118,6 +119,8 @@ BasePluginSlot.propTypes = {
118119
children: PropTypes.node,
119120
/** ID of the PluginSlot configuration */
120121
id: PropTypes.string.isRequired,
122+
/** Aliases (additional IDs for the PluginSlot) */
123+
idAliases: PropTypes.arrayOf(PropTypes.string),
121124
/** Props that are passed down to each Plugin in the Slot */
122125
pluginProps: PropTypes.shape(),
123126
/** Options passed to the PluginSlot */

src/plugins/data/hooks.js

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,38 @@ import { PLUGIN_MOUNTED, PLUGIN_READY, PLUGIN_UNMOUNTED } from './constants';
1414
* @param {String} id - Name of PluginSlot
1515
* @returns {Object} - JS configuration for the PluginSlot
1616
*/
17-
export function usePluginSlot(id) {
18-
const configSlots = getConfigSlots()?.[id];
19-
if (configSlots) {
20-
return configSlots;
17+
export function usePluginSlot(id, idAliases = []) {
18+
const notFound = { keepDefault: true, plugins: [] };
19+
20+
const allConfigSlots = getConfigSlots();
21+
22+
if (!allConfigSlots) {
23+
return notFound;
24+
}
25+
26+
// When defining a JS object with multiple entries
27+
// that have the same key, only the last one is kept
28+
//
29+
// We want to treat all entries in the pluginSlots object
30+
// in env.config.jsx that have either "id" or any of the
31+
// "idAliases" as if they have the same id
32+
//
33+
// To do so, we grab the last entry in the object that with
34+
// a key that matches either the "id" or any of the "idAliases"
35+
const allSlotIds = [id].concat(idAliases);
36+
const lastMatchingId = Object.keys(allConfigSlots).findLast(slotId => allSlotIds.includes(slotId));
37+
38+
if (!lastMatchingId) {
39+
return notFound;
2140
}
22-
return { keepDefault: true, plugins: [] };
41+
42+
const configSlot = allConfigSlots[lastMatchingId];
43+
44+
if (!configSlot) {
45+
return notFound;
46+
}
47+
48+
return configSlot;
2349
}
2450

2551
/* Listening for events */

src/plugins/data/hooks.test.jsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,58 @@ describe('usePluginSlots', () => {
5252
expect(slotConfig.plugins).toStrictEqual([]);
5353
});
5454
});
55+
56+
describe('when the plugin slot is defined via alias', () => {
57+
it('returns keepDefault and plugin changes', () => {
58+
getConfig.mockImplementation(() => (
59+
{
60+
pluginSlots: {
61+
example_plugin_slot_alias: {
62+
plugins: mockSlotChanges,
63+
keepDefault: true,
64+
},
65+
},
66+
}
67+
));
68+
69+
const slotConfig = usePluginSlot('example_plugin_slot', ['example_plugin_slot_alias']);
70+
expect(slotConfig.keepDefault).toBe(true);
71+
expect(slotConfig.plugins).toBe(mockSlotChanges);
72+
});
73+
});
74+
75+
describe('when no matching plugin slot is found', () => {
76+
it('returns true for keepDefault and no plugin changes', () => {
77+
getConfig.mockImplementation(() => (
78+
{
79+
pluginSlots: {
80+
wrong_plugin_slot_alias: {
81+
plugins: mockSlotChanges,
82+
keepDefault: true,
83+
},
84+
},
85+
}
86+
));
87+
88+
const slotConfig = usePluginSlot('example_plugin_slot', ['example_plugin_slot_alias']);
89+
expect(slotConfig.keepDefault).toBe(true);
90+
expect(slotConfig.plugins).toStrictEqual([]);
91+
});
92+
});
93+
94+
describe('when the defined plugin is null', () => {
95+
it('returns true for keepDefault and no plugin changes', () => {
96+
getConfig.mockImplementation(() => (
97+
{
98+
pluginSlots: {
99+
example_plugin_slot_alias: null,
100+
},
101+
}
102+
));
103+
104+
const slotConfig = usePluginSlot('example_plugin_slot', ['example_plugin_slot_alias']);
105+
expect(slotConfig.keepDefault).toBe(true);
106+
expect(slotConfig.plugins).toStrictEqual([]);
107+
});
108+
});
55109
});

0 commit comments

Comments
 (0)