Skip to content

Commit d62f396

Browse files
committed
introduce extension component weight
1 parent f584775 commit d62f396

File tree

2 files changed

+53
-27
lines changed

2 files changed

+53
-27
lines changed

README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ If you choose to install everything manually, see [Manual install](manual-instal
1919

2020
## Extensions
2121

22-
Extensions are modules that export a default object with a `hooks` property, which is a named index pointing to Vue components. This seems complicated, but an example makes it much clearer:
22+
Extensions are modules that export a default object with a `hooks` property, which is an array of objects, pointing to Vue components (with metadata). This seems complicated, but an example makes it much clearer:
2323

2424
```javascript
2525
// extensions/FooExtension/index.js
@@ -28,13 +28,31 @@ import {FooElement, BazElement} from './components/othercomponents.vue'
2828

2929
export default {
3030
hooks: {
31-
"my-list-element": [AComponent],
32-
"blah-another-hook": [FooElement, BazElement]
33-
}
31+
"my-list.element": [{ component: AComponent }],
32+
"mycompany.hooks.ui.item": [
33+
{ component: FooElement, weight: 2 },
34+
{ component: BazElement, weight: 3 }
35+
]
36+
},
37+
routes: [{
38+
path: '/foo',
39+
component: () => import('layouts/MyLayout.vue'),
40+
children: [
41+
{ path: '', component: () => import('./pages/fooIndex.vue') }
42+
]
43+
}]
3444
}
3545
```
3646

37-
One module can provide components for more than one hooks.
47+
hooks
48+
49+
Hooks are strings that define an entry point for your extension components
50+
Each hook points to an array of objects which declare:
51+
52+
* **component**: the Vue component to render.
53+
* weight: order of the component in a list. The higher the component's weight, the further it "sinks" down (or right) in the list.
54+
55+
One module can provide components for more than one hooks.
3856

3957
There is an `<extensionpoint>` tag in your project available now:
4058

@@ -45,8 +63,8 @@ There is an `<extensionpoint>` tag in your project available now:
4563
<extensionpoint hook="my-list-element"/>
4664
</ul>
4765

48-
<h3>Extensionpoints for "blah-another-hook"</h3>
49-
<extensionpoint hook="blah-another-hook"/>
66+
<h3>Extensionpoints for "mycompany.hooks.ui.item"</h3>
67+
<extensionpoint hook="mycompany.hooks.ui.item"/>
5068
</template>
5169
```
5270

index.js

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
let hookRegistry = {}
32

43
export default {
@@ -10,10 +9,12 @@ export default {
109
* @param {Object} options An named index of objects:
1110
* "extensions": a named index of modules that export an extension:
1211
* name: the name of the extensions
13-
* hooks: named index, each one pointing to a list of Vue
14-
* components implementing that hook. They will be
15-
* rendered at each extensionpoint that has the same hook
16-
* name.
12+
* hooks: array of objects with the following schema:
13+
* component: a Vue component implementing that hook. They will be rendered within the
14+
* <extensionpoint> tag with given hook name.
15+
* weight: the "weight" of that component. "heavier" components sink down in the
16+
* list and are rendered *after* "lighter" ones.
17+
* Default weight = 0
1718
*/
1819
install: (Vue, options) => {
1920

@@ -22,21 +23,26 @@ export default {
2223
if(extension.initialize) {
2324
extension.initialize()
2425
}
25-
for (let hook in extension.hooks) {
26-
// make array
27-
let componentArray = Array.isArray(extension.hooks[hook]) ?
28-
extension.hooks[hook]
29-
: [extension.hooks[hook]]
26+
for (let hook in extension.hooks) {
27+
let extensionArray = extension.hooks[hook]
3028

31-
if (hookRegistry[hook] === undefined) {
32-
hookRegistry[hook] = componentArray
33-
} else {
34-
// if extension provides an array, merge it
35-
hookRegistry[hook] = hookRegistry[hook].concat(componentArray)
29+
// set a default weight for all extensions if there is none set.
30+
for (let obj of extensionArray) {
31+
if (!obj.weigth) {
32+
obj.weigth = 0
33+
}
34+
}
3635

37-
}
38-
// console.debug(`Registering component '${extensionName}' for hook '${hook}'`)
39-
}
36+
// if hook is not known already, create it
37+
if (hookRegistry[hook] === undefined) {
38+
hookRegistry[hook] = extensionArray
39+
} else {
40+
// if hook already exists, merge new one
41+
hookRegistry[hook] = hookRegistry[hook].concat(extensionArray)
42+
43+
}
44+
// console.debug(`Registering component '${extensionName}' for hook '${hook}'`, extensionArray)
45+
}
4046
}
4147

4248
Vue.component('extensionpoint', {
@@ -47,12 +53,14 @@ export default {
4753
computed: {
4854
extensions () {
4955
// console.log(`hook ${this.hook}: `, hookRegistry[this.hook])
50-
return hookRegistry[this.hook]
56+
return hookRegistry[this.hook].sort((obj1, obj2) => {
57+
return obj1.weight - obj2.weight
58+
})
5159
}
5260
},
5361
template: `
5462
<div class="extension-container">
55-
<component :is="extensionComponent" v-for="extensionComponent in extensions" :key="extensionComponent.id"/>
63+
<component :is="extensionComponent.component" v-for="extensionComponent in extensions" :key="extensionComponent.component.id"/>
5664
</div>
5765
`
5866
})

0 commit comments

Comments
 (0)