@bbki.ng/site 5.8.2 → 5.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +2 -2
- package/src/app/app.tsx +4 -8
- package/src/app/components/BaseLayout.tsx +2 -3
- package/src/app/components/cover/index.tsx +17 -15
- package/src/app/hooks/use_plugin_entries.ts +17 -27
- package/src/core/components/SlotComp.tsx +4 -17
- package/src/core/hooks/index.ts +2 -2
- package/src/core/hooks/useMiddlewareTransData.ts +13 -82
- package/src/core/hooks/useSlotComp.ts +3 -26
- package/src/core/hooks/use_plugins.ts +4 -3
- package/src/core/plugin-system/pluginManager.ts +5 -2
- package/src/core/plugin-system/pluginManifestService.ts +2 -18
- package/src/core/plugin-system/pluginStore.ts +1 -0
- package/src/core/plugin-system/registry.ts +1 -106
- package/src/core/plugin-system/services/systemUIService.ts +31 -126
- package/src/core/shared-service/contract/IUIService.ts +15 -17
- package/src/core/shared-service/factory/createUIService.ts +121 -0
- package/src/core/shared-service/factory/createUIServiceReactKit.tsx +149 -0
- package/src/plugins/blog/components/BlogSlotCom.tsx +4 -17
- package/src/plugins/blog/hooks/useMiddlewareTransData.ts +11 -76
- package/src/plugins/blog/hooks/use_blog_slot_com.ts +2 -24
- package/src/plugins/blog/index.ts +6 -1
- package/src/plugins/blog/services/BlogUIService.ts +10 -103
- package/src/plugins/blog/services/IBlogUIService.ts +1 -16
- package/src/plugins/store/components/storeIcon.tsx +16 -0
- package/src/plugins/store/index.ts +3 -1
- package/src/types/slots.ts +0 -17
- package/tsconfig.json +1 -1
- package/src/utils/index.tsx +0 -20
|
@@ -1,26 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { IMiddlewareEntry, ISlotEntry } from '#/core/plugin-system/registry';
|
|
4
|
-
import { createEventBus } from '#/core/utils/eventBus';
|
|
5
|
-
import { IComPropsRegisteredToSlot } from '#/types/slots';
|
|
1
|
+
import { createUIService } from '#/core/shared-service/factory/createUIService';
|
|
6
2
|
|
|
7
3
|
import { BlogDataHookPoint, BlogSlotName, IBlogUIService } from './IBlogUIService';
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
'blog:slots:changed': void;
|
|
11
|
-
'blog:middleware:changed': BlogDataHookPoint;
|
|
12
|
-
};
|
|
5
|
+
const baseService = createUIService<BlogSlotName, BlogDataHookPoint>('blog');
|
|
13
6
|
|
|
14
7
|
export class BlogUIService implements IBlogUIService {
|
|
15
8
|
private static instance: BlogUIService;
|
|
16
9
|
|
|
17
10
|
private constructor() {}
|
|
18
11
|
|
|
19
|
-
private slots = new Map<BlogSlotName, Array<ISlotEntry>>();
|
|
20
|
-
private middlewares = new Map<BlogDataHookPoint, IMiddlewareEntry<unknown>[]>();
|
|
21
|
-
|
|
22
|
-
private bus = createEventBus<RegistryEvents>();
|
|
23
|
-
|
|
24
12
|
static getInstance(): BlogUIService {
|
|
25
13
|
if (!BlogUIService.instance) {
|
|
26
14
|
BlogUIService.instance = new BlogUIService();
|
|
@@ -28,93 +16,12 @@ export class BlogUIService implements IBlogUIService {
|
|
|
28
16
|
return BlogUIService.instance;
|
|
29
17
|
}
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
registerMiddleware: <S>(
|
|
40
|
-
hookPoint: BlogDataHookPoint,
|
|
41
|
-
fn: (data: S) => S | Promise<S>,
|
|
42
|
-
pluginId: string,
|
|
43
|
-
weight?: number
|
|
44
|
-
) => void = <S>(
|
|
45
|
-
hookPoint: BlogDataHookPoint,
|
|
46
|
-
fn: (data: S) => S | Promise<S>,
|
|
47
|
-
pluginId: string,
|
|
48
|
-
weight = 0
|
|
49
|
-
) => {
|
|
50
|
-
const existing = this.middlewares.get(hookPoint) || [];
|
|
51
|
-
|
|
52
|
-
const newEntry: IMiddlewareEntry<S> = {
|
|
53
|
-
id: `${pluginId}-${hookPoint}-middleware`,
|
|
54
|
-
pluginId,
|
|
55
|
-
fn,
|
|
56
|
-
weight,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const updated = [...existing, newEntry as IMiddlewareEntry<unknown>].sort(
|
|
60
|
-
(a, b) => (b.weight || 0) - (a.weight || 0)
|
|
61
|
-
);
|
|
62
|
-
this.middlewares.set(hookPoint, updated);
|
|
63
|
-
|
|
64
|
-
this.bus.emit('blog:middleware:changed', hookPoint);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
registerSlot: (
|
|
68
|
-
slotName: BlogSlotName,
|
|
69
|
-
component: React.ComponentType<{ data: unknown }>,
|
|
70
|
-
pluginId: string,
|
|
71
|
-
weight?: number
|
|
72
|
-
) => void = (slotName, component, pluginId, weight = 0) => {
|
|
73
|
-
const existing = this.slots.get(slotName) || [];
|
|
74
|
-
const newEntry: ISlotEntry = {
|
|
75
|
-
id: `${pluginId}-${slotName}-slot`,
|
|
76
|
-
pluginId,
|
|
77
|
-
component,
|
|
78
|
-
weight,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const updated = [...existing, newEntry].sort((a, b) => (b.weight || 0) - (a.weight || 0));
|
|
82
|
-
this.slots.set(slotName, updated);
|
|
83
|
-
|
|
84
|
-
this.bus.emit('blog:slots:changed', undefined);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
unregisterAllByPluginId: (pluginId: string) => void = pluginId => {
|
|
88
|
-
// 移除中间件
|
|
89
|
-
this.middlewares.forEach((entries, hookPoint) => {
|
|
90
|
-
const filtered = entries.filter(entry => entry.pluginId !== pluginId);
|
|
91
|
-
if (filtered.length !== entries.length) {
|
|
92
|
-
this.middlewares.set(hookPoint, filtered);
|
|
93
|
-
this.bus.emit('blog:middleware:changed', hookPoint);
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// 移除插槽组件
|
|
98
|
-
this.slots.forEach((entries, slotName) => {
|
|
99
|
-
const filtered = entries.filter(entry => entry.pluginId !== pluginId);
|
|
100
|
-
if (filtered.length !== entries.length) {
|
|
101
|
-
this.slots.set(slotName, filtered);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
this.bus.emit('blog:slots:changed', undefined);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
getComponents(slotName: BlogSlotName): React.ComponentType<IComPropsRegisteredToSlot>[] {
|
|
109
|
-
return (this.slots.get(slotName) || []).map(entry => entry.component);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async runMiddlewares<T>(point: BlogDataHookPoint, data: T): Promise<T> {
|
|
113
|
-
const fns = (this.middlewares.get(point) || []).map(entry => entry.fn);
|
|
114
|
-
let result = data;
|
|
115
|
-
for (const fn of fns) {
|
|
116
|
-
result = (await fn(result)) as T;
|
|
117
|
-
}
|
|
118
|
-
return result;
|
|
119
|
-
}
|
|
19
|
+
registerSlot = baseService.registerSlot.bind(baseService);
|
|
20
|
+
registerMiddleware = baseService.registerMiddleware.bind(baseService);
|
|
21
|
+
unregisterAllByPluginId = baseService.unregisterAllByPluginId.bind(baseService);
|
|
22
|
+
getSlotEntries = baseService.getSlotEntries.bind(baseService);
|
|
23
|
+
getComponents = baseService.getComponents.bind(baseService);
|
|
24
|
+
subscribeSlotChange = baseService.subscribeSlotChange.bind(baseService);
|
|
25
|
+
subscribeMiddlewareChange = baseService.subscribeMiddlewareChange.bind(baseService);
|
|
26
|
+
runMiddlewares = baseService.runMiddlewares.bind(baseService);
|
|
120
27
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
|
-
|
|
3
1
|
import { type IBaseUIService } from '#/core/shared-service/contract/IUIService';
|
|
4
2
|
|
|
5
3
|
declare module '#/core/shared-service/service-registry' {
|
|
@@ -15,17 +13,4 @@ export type BlogDataHookPoint =
|
|
|
15
13
|
| 'blog:transformPostContent'
|
|
16
14
|
| 'blog:transformTitleList';
|
|
17
15
|
|
|
18
|
-
export interface IBlogUIService extends IBaseUIService<BlogSlotName, BlogDataHookPoint> {
|
|
19
|
-
registerMiddleware: <S>(
|
|
20
|
-
hookPoint: BlogDataHookPoint,
|
|
21
|
-
fn: (data: S) => S | Promise<S>,
|
|
22
|
-
pluginId: string,
|
|
23
|
-
weight?: number
|
|
24
|
-
) => void;
|
|
25
|
-
registerSlot: (
|
|
26
|
-
slotName: BlogSlotName,
|
|
27
|
-
component: React.ComponentType<{ data: unknown }>,
|
|
28
|
-
pluginId: string,
|
|
29
|
-
weight?: number
|
|
30
|
-
) => void;
|
|
31
|
-
}
|
|
16
|
+
export interface IBlogUIService extends IBaseUIService<BlogSlotName, BlogDataHookPoint> {}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Link } from '@bbki.ng/ui';
|
|
2
|
+
|
|
3
|
+
const CupIcon = () => (
|
|
4
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
|
|
5
|
+
<path d="M8.75 8h6.5a.75.75 0 0 1 .75.75v6.5a.75.75 0 0 1-.75.75h-6.5a.75.75 0 0 1-.75-.75v-6.5A.75.75 0 0 1 8.75 8Zm.75 6.5h5v-5h-5Z"></path>
|
|
6
|
+
<path d="M15.25 1a.75.75 0 0 1 .75.75V4h2.25c.966 0 1.75.784 1.75 1.75V8h2.25a.75.75 0 0 1 0 1.5H20v5h2.25a.75.75 0 0 1 0 1.5H20v2.25A1.75 1.75 0 0 1 18.25 20H16v2.25a.75.75 0 0 1-1.5 0V20h-5v2.25a.75.75 0 0 1-1.5 0V20H5.75A1.75 1.75 0 0 1 4 18.25V16H1.75a.75.75 0 0 1 0-1.5H4v-5H1.75a.75.75 0 0 1 0-1.5H4V5.75C4 4.784 4.784 4 5.75 4H8V1.75a.75.75 0 0 1 1.5 0V4h5V1.75a.75.75 0 0 1 .75-.75Zm3 17.5a.25.25 0 0 0 .25-.25V5.75a.25.25 0 0 0-.25-.25H5.75a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25Z"></path>
|
|
7
|
+
</svg>
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
export const StoreIcon = () => {
|
|
11
|
+
return (
|
|
12
|
+
<Link to="/store" className="flex items-center">
|
|
13
|
+
<CupIcon />
|
|
14
|
+
</Link>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -2,6 +2,7 @@ import { BBPlugin } from '#/core/plugin-system/bbplugin';
|
|
|
2
2
|
import { IHostContext } from '#/types/hostApi';
|
|
3
3
|
import { PluginID } from '#/types/plugin';
|
|
4
4
|
|
|
5
|
+
import { StoreIcon } from './components/storeIcon';
|
|
5
6
|
import { StorePage } from './components/storePage';
|
|
6
7
|
import { StoreCtx } from './context';
|
|
7
8
|
|
|
@@ -20,10 +21,11 @@ export class StorePlugin extends BBPlugin {
|
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
systemUIService.registerSlot('nav-right', StoreIcon, this.id);
|
|
25
|
+
|
|
23
26
|
systemUIService.registerPluginEntry(
|
|
24
27
|
{
|
|
25
28
|
path: '/store',
|
|
26
|
-
label: 'cd ./store',
|
|
27
29
|
pageComponent: StoreCtx.withCtx(
|
|
28
30
|
{
|
|
29
31
|
install: ctx.store?.installPlugin || (async () => false),
|
package/src/types/slots.ts
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
export type SlotName =
|
|
2
|
-
| 'leftCol'
|
|
3
|
-
| 'rightCol'
|
|
4
|
-
| 'articleActionRow'
|
|
5
|
-
| 'logo'
|
|
6
|
-
| 'route'
|
|
7
|
-
| 'pageFooter'
|
|
8
|
-
| 'articleTitle';
|
|
9
|
-
|
|
10
|
-
export type HookPoint =
|
|
11
|
-
| 'filterPosts'
|
|
12
|
-
| 'transformPostContent'
|
|
13
|
-
| 'transformBreadcrumbPath'
|
|
14
|
-
| 'transformTitleList'
|
|
15
|
-
| 'extendedRoutes'
|
|
16
|
-
| 'transformCoverEntry';
|
|
17
|
-
|
|
18
1
|
export interface IComPropsRegisteredToSlot {
|
|
19
2
|
data: unknown;
|
|
20
3
|
}
|
package/tsconfig.json
CHANGED
package/src/utils/index.tsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { PathRouteProps } from 'react-router-dom';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import { IPluginEntry } from '#/types/plugin';
|
|
5
|
-
import { IComPropsRegisteredToSlot } from '#/types/slots';
|
|
6
|
-
|
|
7
|
-
export const buildEntrySlotCom = (entry: IPluginEntry) => {
|
|
8
|
-
const Component = (props: IComPropsRegisteredToSlot) => {
|
|
9
|
-
const route = props.data as Omit<PathRouteProps, 'element'>;
|
|
10
|
-
if (route.path === entry.path) {
|
|
11
|
-
const Com = entry.pageComponent;
|
|
12
|
-
return <Com data={props.data} />;
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
Component.displayName = `EntrySlotCom(${entry.path})`;
|
|
18
|
-
|
|
19
|
-
return Component;
|
|
20
|
-
};
|