@blocklet/meta 1.15.17 → 1.16.0-beta-b16cb035
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/lib/channel.d.ts +32 -0
- package/lib/channel.js +54 -0
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +5 -152
- package/lib/did.d.ts +3 -0
- package/lib/did.js +9 -9
- package/lib/engine.d.ts +7 -0
- package/lib/engine.js +21 -25
- package/lib/entry.d.ts +3 -0
- package/lib/entry.js +51 -64
- package/lib/extension.d.ts +14 -0
- package/lib/extension.js +82 -77
- package/lib/file.d.ts +23 -0
- package/lib/file.js +51 -36
- package/lib/fix.d.ts +36 -0
- package/lib/fix.js +231 -228
- package/lib/get-component-process-id.d.ts +5 -0
- package/lib/get-component-process-id.js +16 -0
- package/lib/has-reserved-key.d.ts +3 -0
- package/lib/has-reserved-key.js +15 -0
- package/lib/index.d.ts +86 -0
- package/lib/index.js +55 -34
- package/lib/info.d.ts +15 -0
- package/lib/info.js +70 -38
- package/lib/name.d.ts +15 -0
- package/lib/name.js +41 -8
- package/lib/nft-templates.d.ts +86 -0
- package/lib/nft-templates.js +52 -0
- package/lib/parse-navigation-from-blocklet.d.ts +92 -0
- package/lib/parse-navigation-from-blocklet.js +539 -0
- package/lib/parse-navigation.d.ts +3 -0
- package/lib/parse-navigation.js +197 -0
- package/lib/parse.d.ts +22 -0
- package/lib/parse.js +100 -89
- package/lib/payment/index.d.ts +254 -0
- package/lib/payment/index.js +14 -0
- package/lib/payment/v1.d.ts +185 -0
- package/lib/payment/v1.js +84 -0
- package/lib/payment/v2.d.ts +242 -0
- package/lib/payment/v2.js +576 -0
- package/lib/schema.d.ts +63 -0
- package/lib/schema.js +669 -283
- package/lib/service.d.ts +27 -0
- package/lib/service.js +71 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +18 -0
- package/lib/types/schema.d.ts +284 -0
- package/lib/types/schema.js +3 -0
- package/lib/url-friendly.d.ts +6 -0
- package/lib/url-friendly.js +20 -0
- package/lib/util-meta.d.ts +42 -0
- package/lib/util-meta.js +146 -0
- package/lib/util.d.ts +201 -0
- package/lib/util.js +501 -82
- package/lib/validate.d.ts +13 -0
- package/lib/validate.js +37 -61
- package/lib/verify-multi-sig.d.ts +3 -0
- package/lib/verify-multi-sig.js +86 -59
- package/lib/wallet.d.ts +9 -0
- package/lib/wallet.js +19 -30
- package/package.json +59 -20
- package/lib/payment.js +0 -114
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.splitNavigationBySection = exports.flatternNavigation = exports.checkLink = exports.joinLink = exports.cleanOrphanNavigation = exports.filterNavigation = exports.nestNavigationList = exports.isMatchSection = exports.deepWalk = exports.parseNavigation = void 0;
|
|
7
|
+
const unionWith_1 = __importDefault(require("lodash/unionWith"));
|
|
8
|
+
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
9
|
+
const pick_1 = __importDefault(require("lodash/pick"));
|
|
10
|
+
const isNil_1 = __importDefault(require("lodash/isNil"));
|
|
11
|
+
const omit_1 = __importDefault(require("lodash/omit"));
|
|
12
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
13
|
+
const url_join_1 = __importDefault(require("url-join"));
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const is_absolute_url_1 = __importDefault(require("is-absolute-url"));
|
|
16
|
+
const lodash_1 = require("lodash");
|
|
17
|
+
const DEFAULT_SECTION = 'header';
|
|
18
|
+
const BASE_PATH = '/';
|
|
19
|
+
const DEFAULT_LINK = '/';
|
|
20
|
+
const ID_SEPARATE = '/';
|
|
21
|
+
/**
|
|
22
|
+
* 判断一个 url 是否为合法的 url 拼接路径
|
|
23
|
+
* /abc, /abc/bcd valid
|
|
24
|
+
* /abc, /abc//bcd invalid
|
|
25
|
+
* @param value 需要检查的 url path
|
|
26
|
+
* @returns boolean
|
|
27
|
+
*/
|
|
28
|
+
const checkUrlPath = (value) => {
|
|
29
|
+
return /^\/(?:[^/]+\/)*$/.test(value) || /^\/(?:[^/]+\/)*[^/]+$/.test(value);
|
|
30
|
+
};
|
|
31
|
+
const checkLink = (value) => {
|
|
32
|
+
if ((0, is_absolute_url_1.default)(value) || checkUrlPath(value)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
};
|
|
37
|
+
exports.checkLink = checkLink;
|
|
38
|
+
function deepWalk(tree, cb = () => { }, { key = 'children', order = 'first' } = {}) {
|
|
39
|
+
function walk(current, { index = 0, parent = null, level = 0 } = {}) {
|
|
40
|
+
if (Array.isArray(current)) {
|
|
41
|
+
current.forEach((item, i) => {
|
|
42
|
+
walk(item, { index: i, parent, level: level + 1 });
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else if (current) {
|
|
46
|
+
if (order === 'first') {
|
|
47
|
+
cb(current, parent, { index, level });
|
|
48
|
+
}
|
|
49
|
+
walk(current[key], { parent: current, level });
|
|
50
|
+
if (order === 'last') {
|
|
51
|
+
cb(current, parent, { index, level });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
walk(tree);
|
|
56
|
+
}
|
|
57
|
+
exports.deepWalk = deepWalk;
|
|
58
|
+
/**
|
|
59
|
+
* 判断一个传入值是否属于一个 section
|
|
60
|
+
* @param {string | array} sections 需要判断的对象
|
|
61
|
+
* @param {string} section 目标 section
|
|
62
|
+
*/
|
|
63
|
+
function isMatchSection(sections, section) {
|
|
64
|
+
if (section === DEFAULT_SECTION && (0, isNil_1.default)(sections)) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(sections)) {
|
|
68
|
+
return sections.includes(section);
|
|
69
|
+
}
|
|
70
|
+
return sections === section;
|
|
71
|
+
}
|
|
72
|
+
exports.isMatchSection = isMatchSection;
|
|
73
|
+
function tryParseItem(item) {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(item);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return item;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function normalizeNavigationList(navigationList) {
|
|
82
|
+
return navigationList.map((item) => {
|
|
83
|
+
const tempData = { ...item };
|
|
84
|
+
if (tempData.role) {
|
|
85
|
+
tempData.role = tryParseItem(tempData.role);
|
|
86
|
+
}
|
|
87
|
+
if (tempData.section) {
|
|
88
|
+
tempData.section = tryParseItem(tempData.section);
|
|
89
|
+
}
|
|
90
|
+
if (tempData.title) {
|
|
91
|
+
tempData.title = tryParseItem(tempData.title);
|
|
92
|
+
}
|
|
93
|
+
if (tempData.link) {
|
|
94
|
+
tempData.link = tryParseItem(tempData.link);
|
|
95
|
+
}
|
|
96
|
+
return tempData;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function optionalJoin(prefix = '/', url = '') {
|
|
100
|
+
if ((0, is_absolute_url_1.default)(url || '')) {
|
|
101
|
+
return url;
|
|
102
|
+
}
|
|
103
|
+
// remove last slash
|
|
104
|
+
const resultUrl = path_1.default.join(prefix, url || DEFAULT_LINK);
|
|
105
|
+
if (resultUrl.length > 1 && resultUrl.endsWith('/')) {
|
|
106
|
+
return resultUrl.slice(0, resultUrl.length - 1);
|
|
107
|
+
}
|
|
108
|
+
return resultUrl;
|
|
109
|
+
}
|
|
110
|
+
function smartJoinLink(_parentLink, _childLink, { strict = true, } = {}) {
|
|
111
|
+
let parentLink = _parentLink;
|
|
112
|
+
let childLink = _childLink;
|
|
113
|
+
if (!strict) {
|
|
114
|
+
parentLink = parentLink || '/';
|
|
115
|
+
childLink = childLink || '/';
|
|
116
|
+
}
|
|
117
|
+
if ((0, lodash_1.isObject)(parentLink) && (0, lodash_1.isString)(childLink) && checkLink(childLink)) {
|
|
118
|
+
return Object.keys(parentLink).reduce((res, key) => {
|
|
119
|
+
res[key] = optionalJoin(parentLink[key], childLink);
|
|
120
|
+
return res;
|
|
121
|
+
}, {});
|
|
122
|
+
}
|
|
123
|
+
if ((0, lodash_1.isString)(parentLink) && checkLink(parentLink) && (0, lodash_1.isObject)(childLink)) {
|
|
124
|
+
return Object.keys(childLink).reduce((res, key) => {
|
|
125
|
+
res[key] = optionalJoin(parentLink, childLink[key]);
|
|
126
|
+
return res;
|
|
127
|
+
}, {});
|
|
128
|
+
}
|
|
129
|
+
if ((0, lodash_1.isString)(parentLink) && (0, lodash_1.isString)(childLink)) {
|
|
130
|
+
if (checkLink(parentLink) || checkLink(childLink)) {
|
|
131
|
+
return optionalJoin(parentLink, childLink);
|
|
132
|
+
}
|
|
133
|
+
return childLink;
|
|
134
|
+
}
|
|
135
|
+
if ((0, lodash_1.isObject)(parentLink) && (0, lodash_1.isObject)(childLink)) {
|
|
136
|
+
const keys = [...new Set([...Object.keys(parentLink), ...Object.keys(childLink)])];
|
|
137
|
+
return keys.reduce((res, key) => {
|
|
138
|
+
res[key] = optionalJoin(parentLink[key], childLink[key]);
|
|
139
|
+
return res;
|
|
140
|
+
}, {});
|
|
141
|
+
}
|
|
142
|
+
return childLink;
|
|
143
|
+
}
|
|
144
|
+
function joinLink(navigation, components) {
|
|
145
|
+
const copyNavigation = (0, cloneDeep_1.default)(navigation);
|
|
146
|
+
deepWalk(copyNavigation, (item, parent) => {
|
|
147
|
+
const component = item.component || item.child;
|
|
148
|
+
if (component) {
|
|
149
|
+
const findComponent = components.find((v) => v.name === component);
|
|
150
|
+
if (findComponent) {
|
|
151
|
+
item.link = smartJoinLink(findComponent.link, item.link, { strict: false });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (parent) {
|
|
155
|
+
item.link = smartJoinLink(parent.link, item.link);
|
|
156
|
+
}
|
|
157
|
+
}, { key: 'items' });
|
|
158
|
+
return copyNavigation;
|
|
159
|
+
}
|
|
160
|
+
exports.joinLink = joinLink;
|
|
161
|
+
/**
|
|
162
|
+
* 将树状结构的导航列表进行扁平化处理
|
|
163
|
+
* @param {array} navigationList 树状结构的导航列表
|
|
164
|
+
* @param {object} params 配置参数
|
|
165
|
+
* @param {number} params.depth 扁平化的层级,默认为 1(全拍平)
|
|
166
|
+
* @param {function} params.transform 当发生拍平处理时
|
|
167
|
+
* @returns 扁平化后的导航列表
|
|
168
|
+
*/
|
|
169
|
+
function flatternNavigation(list = [], { depth = 1, transform = (v) => v } = {}) {
|
|
170
|
+
const copyList = (0, cloneDeep_1.default)(list);
|
|
171
|
+
const finalList = [];
|
|
172
|
+
deepWalk(copyList, (item, parent, { level }) => {
|
|
173
|
+
if (level >= depth) {
|
|
174
|
+
const { items = [] } = item;
|
|
175
|
+
if (items && Array.isArray(items) && items.length > 0) {
|
|
176
|
+
delete item.items;
|
|
177
|
+
const transformedItems = items.map((v) => transform(v, item));
|
|
178
|
+
if (parent) {
|
|
179
|
+
parent.items.push(...transformedItems);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const tmpItem = transform((0, omit_1.default)(item, ['items']), parent);
|
|
183
|
+
finalList.push(tmpItem, ...transformedItems);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else if (level === 1) {
|
|
187
|
+
const tmpItem = transform((0, omit_1.default)(item, ['items']), parent);
|
|
188
|
+
finalList.push(tmpItem);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else if (level === 1) {
|
|
192
|
+
finalList.push(item);
|
|
193
|
+
}
|
|
194
|
+
}, { key: 'items', order: 'last' });
|
|
195
|
+
return finalList;
|
|
196
|
+
}
|
|
197
|
+
exports.flatternNavigation = flatternNavigation;
|
|
198
|
+
/**
|
|
199
|
+
* 将 blocklet 中的数据进行处理,获得当前应用的导航数据及组件数据
|
|
200
|
+
* @param {object} blocklet blocklet 应用实例对象
|
|
201
|
+
* @returns 导航数据及组件数据
|
|
202
|
+
*/
|
|
203
|
+
function parseBlockletNavigationList(blocklet = {}) {
|
|
204
|
+
const components = [];
|
|
205
|
+
/**
|
|
206
|
+
*
|
|
207
|
+
* @param {object} current 当前 blocklet 的数据
|
|
208
|
+
* @param {object} parent 当前 blocklet 的父组件数据
|
|
209
|
+
* @returns
|
|
210
|
+
*/
|
|
211
|
+
function genNavigationListByBlocklet(current, parent = {}) {
|
|
212
|
+
const targetList = [];
|
|
213
|
+
const { children = [], meta = {} } = current;
|
|
214
|
+
const navigation = (0, cloneDeep_1.default)(meta?.navigation || []);
|
|
215
|
+
if (current.meta?.capabilities?.navigation !== false) {
|
|
216
|
+
targetList.push(...navigation);
|
|
217
|
+
}
|
|
218
|
+
const parentName = parent.name || '';
|
|
219
|
+
const parentBase = parent.mountPoint || BASE_PATH;
|
|
220
|
+
const currentName = current === blocklet ? '' : meta.name || '';
|
|
221
|
+
const currentBase = current === blocklet ? '' : current.mountPoint || BASE_PATH;
|
|
222
|
+
for (const child of children) {
|
|
223
|
+
const childName = child.meta.name;
|
|
224
|
+
const childBase = child.mountPoint;
|
|
225
|
+
const mergeName = [parentName, currentName, childName].filter(Boolean).join('.');
|
|
226
|
+
const childNavigation = child.meta.navigation || [];
|
|
227
|
+
const mergeBase = (0, url_join_1.default)(parentBase, currentBase, childBase);
|
|
228
|
+
if (child.meta?.capabilities?.navigation !== false) {
|
|
229
|
+
components.push({
|
|
230
|
+
did: child.meta.did,
|
|
231
|
+
name: mergeName,
|
|
232
|
+
link: mergeBase,
|
|
233
|
+
title: child.meta.title || '',
|
|
234
|
+
navigation: childNavigation.map((item) => ({
|
|
235
|
+
// 给每个 navigation 赋予一个 setion,用于在 autocomplete 提供依据 section 筛选的基础
|
|
236
|
+
section: DEFAULT_SECTION,
|
|
237
|
+
...item,
|
|
238
|
+
})),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
// 在现有的 navigation 中判断是否存在 children
|
|
242
|
+
const matchNavigation = navigation.find((item) => {
|
|
243
|
+
if (item.component) {
|
|
244
|
+
return item.component === childName;
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
});
|
|
248
|
+
// 如果存在,并且当前 navigation 未配置任何 link,则将 child mountpoint 给它
|
|
249
|
+
if (matchNavigation) {
|
|
250
|
+
if (!matchNavigation.link) {
|
|
251
|
+
if (child.meta.navigation && child.meta.navigation.length > 0) {
|
|
252
|
+
const items = genNavigationListByBlocklet(child, { mountPoint: currentBase, name: currentName });
|
|
253
|
+
if (items.length > 0) {
|
|
254
|
+
matchNavigation.items = matchNavigation.items ?? [];
|
|
255
|
+
matchNavigation.items.push(...items);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
matchNavigation.link = DEFAULT_LINK;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else if (child.meta?.capabilities?.navigation !== false) {
|
|
264
|
+
const childItems = genNavigationListByBlocklet(child, { mountPoint: currentBase, name: currentName });
|
|
265
|
+
// 否则动态注入一个 navigation
|
|
266
|
+
const tmpData = {
|
|
267
|
+
title: child.meta.title,
|
|
268
|
+
component: childName,
|
|
269
|
+
// 动态注入的 navigation 需要一个默认的 id,blocklet.meta.id 是唯一的,可以用上这个值
|
|
270
|
+
id: child.meta.did,
|
|
271
|
+
};
|
|
272
|
+
if (childItems.length > 0) {
|
|
273
|
+
tmpData.items = childItems;
|
|
274
|
+
tmpData.link = undefined;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
tmpData.link = DEFAULT_LINK;
|
|
278
|
+
}
|
|
279
|
+
targetList.push(tmpData);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return targetList;
|
|
283
|
+
}
|
|
284
|
+
const navigationList = genNavigationListByBlocklet(blocklet);
|
|
285
|
+
return {
|
|
286
|
+
navigationList,
|
|
287
|
+
components,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function patchBuiltinNavigation(navigation) {
|
|
291
|
+
const copyNavigation = (0, cloneDeep_1.default)(navigation).filter((item) => item.id);
|
|
292
|
+
deepWalk(copyNavigation, (item, parent) => {
|
|
293
|
+
if (item.items && item.items.length) {
|
|
294
|
+
for (let i = item.items.length - 1; i >= 0; i--) {
|
|
295
|
+
if (!item.items[i].id) {
|
|
296
|
+
item.items.splice(i, 1);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// 如果 items 全都不符合规范,保留 item 本身,为其增加一个默认的链接
|
|
300
|
+
if (item.items.length === 0) {
|
|
301
|
+
if (item.component) {
|
|
302
|
+
item.link = item.link || DEFAULT_LINK;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (parent) {
|
|
307
|
+
item.parent = parent.id;
|
|
308
|
+
// 由于默认设置的 id(在 blocklet.yml 中手动赋予的存在重复的可能性比较大,所以通过 `/` 拼接父节点的 id,可以大大降低重复的概率)
|
|
309
|
+
item.id = [parent.id, item.id].join(ID_SEPARATE);
|
|
310
|
+
}
|
|
311
|
+
item.from = item.from || 'yaml';
|
|
312
|
+
item.visible = item.visible ?? true;
|
|
313
|
+
}, { key: 'items' });
|
|
314
|
+
return copyNavigation;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* 将多层结构的导航列表压缩至指定最大深度的树状结构
|
|
318
|
+
* @param {array} navigation 树状结构的导航列表数据
|
|
319
|
+
* @param {number} depth 压缩的层级
|
|
320
|
+
* @returns 压缩后的树状结构导航列表数据
|
|
321
|
+
*/
|
|
322
|
+
function compactNavigation(navigation, depth = 2) {
|
|
323
|
+
const copyNavigation = (0, cloneDeep_1.default)(navigation);
|
|
324
|
+
const resData = flatternNavigation(copyNavigation, {
|
|
325
|
+
depth,
|
|
326
|
+
transform: (item, parent) => {
|
|
327
|
+
if (parent) {
|
|
328
|
+
if (!item._parent) {
|
|
329
|
+
item._parent = parent.id;
|
|
330
|
+
if (!parent.component) {
|
|
331
|
+
item.link = smartJoinLink(parent.link, item.link);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
item.section = item.section || parent.section || [DEFAULT_SECTION];
|
|
335
|
+
item.visible = item.visible ?? parent.visible;
|
|
336
|
+
}
|
|
337
|
+
item.component = [parent.component, item.component].filter(Boolean).join('.');
|
|
338
|
+
return item;
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
deepWalk(resData, (item) => {
|
|
342
|
+
if (item.items && item.items.length > 0) {
|
|
343
|
+
item.items.reduceRight((all, cur) => {
|
|
344
|
+
if (cur._parent) {
|
|
345
|
+
const index = item.items.findIndex((v) => v.id === cur._parent);
|
|
346
|
+
if (index >= 0) {
|
|
347
|
+
item.items.splice(index, 1);
|
|
348
|
+
}
|
|
349
|
+
delete cur._parent;
|
|
350
|
+
}
|
|
351
|
+
return null;
|
|
352
|
+
}, null);
|
|
353
|
+
}
|
|
354
|
+
}, { key: 'items' });
|
|
355
|
+
return resData;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* 返回指定的导航中的子菜单(属于指定 section)
|
|
359
|
+
* @param {object} navigationItem 指定的某一个导航数据
|
|
360
|
+
* @param {string} section 指定的 section 区域
|
|
361
|
+
* @returns
|
|
362
|
+
*/
|
|
363
|
+
function getNavigationListBySection(navigationItem, section) {
|
|
364
|
+
if (section && Array.isArray(navigationItem.items)) {
|
|
365
|
+
return navigationItem.items
|
|
366
|
+
.filter((item) => {
|
|
367
|
+
// 如果当前子菜单没有 section,它的 section 应该跟随父菜单的 section
|
|
368
|
+
if ((0, isNil_1.default)(item.section)) {
|
|
369
|
+
return isMatchSection(navigationItem.section, section);
|
|
370
|
+
}
|
|
371
|
+
if (isMatchSection(item.section, section)) {
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
return false;
|
|
375
|
+
})
|
|
376
|
+
.map((item) => ({ ...item, section }));
|
|
377
|
+
}
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* 根据导航中每一个子菜单所属的 section,将原由的导航数据分离为多个导航数据(此时每一个导航 item 只会包含一个 section)
|
|
382
|
+
* @param {array} navigation 导航列表数据(树状结构,目前只适用于两层的树状结构)
|
|
383
|
+
* @returns
|
|
384
|
+
*/
|
|
385
|
+
function splitNavigationBySection(navigation) {
|
|
386
|
+
const copyNavigation = (0, cloneDeep_1.default)(navigation);
|
|
387
|
+
const allNavigationList = [];
|
|
388
|
+
for (const navigationItem of copyNavigation) {
|
|
389
|
+
const baseNavigation = (0, cloneDeep_1.default)((0, omit_1.default)(navigationItem, ['items']));
|
|
390
|
+
const itemNavigationList = [];
|
|
391
|
+
// eslint-disable-next-line no-inner-declarations
|
|
392
|
+
function patchNavigationItem(item, section) {
|
|
393
|
+
const sectionNavigationList = getNavigationListBySection(item, section);
|
|
394
|
+
itemNavigationList.push({
|
|
395
|
+
...baseNavigation,
|
|
396
|
+
section,
|
|
397
|
+
items: sectionNavigationList,
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
if (Array.isArray(navigationItem.section)) {
|
|
401
|
+
for (const section of navigationItem.section) {
|
|
402
|
+
patchNavigationItem(navigationItem, section);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
else if (navigationItem.section) {
|
|
406
|
+
const { section } = navigationItem;
|
|
407
|
+
patchNavigationItem(navigationItem, section);
|
|
408
|
+
}
|
|
409
|
+
else if (navigationItem.items && navigationItem.items.length > 0) {
|
|
410
|
+
const allSectionList = navigationItem.items.reduce((list, currentValue) => {
|
|
411
|
+
const { section = [DEFAULT_SECTION] } = currentValue || {};
|
|
412
|
+
list.push(...section);
|
|
413
|
+
return list;
|
|
414
|
+
}, []);
|
|
415
|
+
const sectionList = [...new Set(allSectionList)];
|
|
416
|
+
for (const section of sectionList) {
|
|
417
|
+
patchNavigationItem(navigationItem, section);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
itemNavigationList.push({
|
|
422
|
+
...navigationItem,
|
|
423
|
+
section: DEFAULT_SECTION,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
allNavigationList.push(...itemNavigationList);
|
|
427
|
+
}
|
|
428
|
+
return allNavigationList;
|
|
429
|
+
}
|
|
430
|
+
exports.splitNavigationBySection = splitNavigationBySection;
|
|
431
|
+
/**
|
|
432
|
+
* 将导航数据进行层叠处理
|
|
433
|
+
* @param {array} list 扁平化的导航数据
|
|
434
|
+
* @returns 处理后的导航
|
|
435
|
+
*/
|
|
436
|
+
function nestNavigationList(list = []) {
|
|
437
|
+
const cloneList = (0, cloneDeep_1.default)(list);
|
|
438
|
+
cloneList.reduceRight((res, item, index) => {
|
|
439
|
+
if (item.parent) {
|
|
440
|
+
const parent = cloneList.find((i) => {
|
|
441
|
+
if (item.section && i.section) {
|
|
442
|
+
return i.section === item.section && i.id === item.parent;
|
|
443
|
+
}
|
|
444
|
+
return i.id === item.parent;
|
|
445
|
+
});
|
|
446
|
+
if (parent) {
|
|
447
|
+
if (!parent.items)
|
|
448
|
+
parent.items = [];
|
|
449
|
+
// 由于 reduceRight 是从后向前遍历,所以后遍历到的其实顺序在前面
|
|
450
|
+
parent.items = [item, ...parent.items];
|
|
451
|
+
}
|
|
452
|
+
cloneList.splice(index, 1);
|
|
453
|
+
}
|
|
454
|
+
return null;
|
|
455
|
+
}, null);
|
|
456
|
+
return cloneList;
|
|
457
|
+
}
|
|
458
|
+
exports.nestNavigationList = nestNavigationList;
|
|
459
|
+
function filterNavigation(navigationList, components = []) {
|
|
460
|
+
const nestedNavigation = nestNavigationList(navigationList);
|
|
461
|
+
deepWalk(nestedNavigation, (item) => {
|
|
462
|
+
if (item?.component) {
|
|
463
|
+
if (!components.some((x) => x.name === item.component)) {
|
|
464
|
+
item.visible = false;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (item.items && item.items.length) {
|
|
468
|
+
for (let i = item.items.length - 1; i >= 0; i--) {
|
|
469
|
+
if (item.items[i].visible === false) {
|
|
470
|
+
item.items.splice(i, 1);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}, { key: 'items' });
|
|
475
|
+
const filteredNavigation = nestedNavigation.filter((item) => {
|
|
476
|
+
if (item.visible === false)
|
|
477
|
+
return false;
|
|
478
|
+
// 如果某一菜单的 子菜单 均为隐藏状态,则一级菜单本身也不显示出来
|
|
479
|
+
if (item.items &&
|
|
480
|
+
Array.isArray(item.items) &&
|
|
481
|
+
item.items.length > 0 &&
|
|
482
|
+
item.items?.every((v) => v.visible === false))
|
|
483
|
+
return false;
|
|
484
|
+
return true;
|
|
485
|
+
});
|
|
486
|
+
return filteredNavigation;
|
|
487
|
+
}
|
|
488
|
+
exports.filterNavigation = filterNavigation;
|
|
489
|
+
function cleanOrphanNavigation(list) {
|
|
490
|
+
// 将仅有一个 child 的菜单提升到上一级
|
|
491
|
+
return list.map((item) => {
|
|
492
|
+
if (item.items && Array.isArray(item.items) && item.items.length === 1) {
|
|
493
|
+
if (['header', 'footer', '', undefined, null].includes(item.section)) {
|
|
494
|
+
return item.items[0];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return item;
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
exports.cleanOrphanNavigation = cleanOrphanNavigation;
|
|
501
|
+
function parseNavigation(blocklet = {}, options = {}) {
|
|
502
|
+
const { beforeProcess = (v) => v } = options;
|
|
503
|
+
const { navigationList: builtinNavigation, components } = parseBlockletNavigationList(blocklet);
|
|
504
|
+
const customNavigationList = blocklet?.settings?.navigations || [];
|
|
505
|
+
const compactedNavigation = compactNavigation(beforeProcess(builtinNavigation));
|
|
506
|
+
const patchedNavigation = patchBuiltinNavigation(compactedNavigation);
|
|
507
|
+
const splitNavigation = splitNavigationBySection(patchedNavigation);
|
|
508
|
+
// 将 footer-social, footer-bottom, sessionManager 的二级菜单提升为一级菜单
|
|
509
|
+
const levelUpNavigation = splitNavigation.reduce((all, cur) => {
|
|
510
|
+
if (['bottom', 'social', 'sessionManager'].includes(cur.section)) {
|
|
511
|
+
if (cur.items && cur.items.length > 0) {
|
|
512
|
+
all.push(...cur.items.map((x) => {
|
|
513
|
+
const { section } = cur;
|
|
514
|
+
const link = smartJoinLink(cur.link, x.link);
|
|
515
|
+
const component = [cur.component, x.component].filter(Boolean).join('.');
|
|
516
|
+
return { ...x, section, link, component, parent: '' };
|
|
517
|
+
}));
|
|
518
|
+
return all;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
all.push(cur);
|
|
522
|
+
return all;
|
|
523
|
+
}, []);
|
|
524
|
+
const flatNavigation = flatternNavigation(levelUpNavigation, {
|
|
525
|
+
transform(item, parent) {
|
|
526
|
+
let { component } = item;
|
|
527
|
+
if (parent?.component) {
|
|
528
|
+
component = [parent.component, item.component].filter(Boolean).join('.');
|
|
529
|
+
}
|
|
530
|
+
return { ...item, component };
|
|
531
|
+
},
|
|
532
|
+
});
|
|
533
|
+
const rawNavigation = (0, unionWith_1.default)(normalizeNavigationList(customNavigationList), flatNavigation, (prev, next) => {
|
|
534
|
+
const keys = ['id', 'section'];
|
|
535
|
+
return (0, isEqual_1.default)((0, pick_1.default)(prev, keys), (0, pick_1.default)(next, keys));
|
|
536
|
+
});
|
|
537
|
+
return { navigationList: rawNavigation, components, builtinList: flatNavigation };
|
|
538
|
+
}
|
|
539
|
+
exports.parseNavigation = parseNavigation;
|