@jupyterlab/settingregistry 4.0.0-alpha.8 → 4.0.0-beta.0
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/plugin-schema.json +88 -0
- package/lib/settingregistry.d.ts +49 -21
- package/lib/settingregistry.js +115 -95
- package/lib/settingregistry.js.map +1 -1
- package/lib/tokens.d.ts +94 -0
- package/lib/tokens.js.map +1 -1
- package/package.json +17 -15
- package/src/index.ts +11 -0
- package/src/plugin-schema.json +388 -0
- package/src/settingregistry.ts +1489 -0
- package/src/tokens.ts +771 -0
package/lib/plugin-schema.json
CHANGED
|
@@ -56,6 +56,13 @@
|
|
|
56
56
|
},
|
|
57
57
|
"additionalProperties": false
|
|
58
58
|
},
|
|
59
|
+
"jupyter.lab.metadataforms": {
|
|
60
|
+
"items": {
|
|
61
|
+
"$ref": "#/definitions/metadataForm"
|
|
62
|
+
},
|
|
63
|
+
"type": "array",
|
|
64
|
+
"default": []
|
|
65
|
+
},
|
|
59
66
|
"jupyter.lab.setting-deprecated": {
|
|
60
67
|
"type": "boolean",
|
|
61
68
|
"default": false
|
|
@@ -295,6 +302,87 @@
|
|
|
295
302
|
"required": ["name"],
|
|
296
303
|
"additionalProperties": false,
|
|
297
304
|
"type": "object"
|
|
305
|
+
},
|
|
306
|
+
"metadataForm": {
|
|
307
|
+
"type": "object",
|
|
308
|
+
"properties": {
|
|
309
|
+
"id": {
|
|
310
|
+
"type": "string",
|
|
311
|
+
"description": "The section ID"
|
|
312
|
+
},
|
|
313
|
+
"metadataSchema": {
|
|
314
|
+
"type": "object",
|
|
315
|
+
"items": {
|
|
316
|
+
"$ref": "#/definitions/metadataSchema"
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
"uiSchema": {
|
|
320
|
+
"type": "object"
|
|
321
|
+
},
|
|
322
|
+
"metadataOptions": {
|
|
323
|
+
"type": "object",
|
|
324
|
+
"items": {
|
|
325
|
+
"$ref": "#/definitions/metadataOptions"
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
"label": {
|
|
329
|
+
"type": "string",
|
|
330
|
+
"description": "The section label"
|
|
331
|
+
},
|
|
332
|
+
"rank": {
|
|
333
|
+
"type": "integer",
|
|
334
|
+
"description": "The rank of the section in the right panel"
|
|
335
|
+
},
|
|
336
|
+
"showModified": {
|
|
337
|
+
"type": "boolean",
|
|
338
|
+
"description": "Whether to show modified values from defaults"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
"required": ["id", "metadataSchema"]
|
|
342
|
+
},
|
|
343
|
+
"metadataSchema": {
|
|
344
|
+
"properties": {
|
|
345
|
+
"properties": {
|
|
346
|
+
"type": "object",
|
|
347
|
+
"description": "The property set up by extension",
|
|
348
|
+
"properties": {
|
|
349
|
+
"title": {
|
|
350
|
+
"type": "string"
|
|
351
|
+
},
|
|
352
|
+
"description": {
|
|
353
|
+
"type": "string"
|
|
354
|
+
},
|
|
355
|
+
"type": {
|
|
356
|
+
"type": "string"
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
"type": "object",
|
|
362
|
+
"required": ["properties"]
|
|
363
|
+
},
|
|
364
|
+
"metadataOptions": {
|
|
365
|
+
"properties": {
|
|
366
|
+
"customRenderer": {
|
|
367
|
+
"type": "string"
|
|
368
|
+
},
|
|
369
|
+
"metadataLevel": {
|
|
370
|
+
"type": "string",
|
|
371
|
+
"enum": ["cell", "notebook"],
|
|
372
|
+
"default": "cell"
|
|
373
|
+
},
|
|
374
|
+
"cellTypes": {
|
|
375
|
+
"type": "array",
|
|
376
|
+
"items": {
|
|
377
|
+
"type": "string",
|
|
378
|
+
"enum": ["code", "markdown", "raw"]
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
"writeDefault": {
|
|
382
|
+
"type": "boolean"
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
"type": "object"
|
|
298
386
|
}
|
|
299
387
|
}
|
|
300
388
|
}
|
package/lib/settingregistry.d.ts
CHANGED
|
@@ -29,18 +29,14 @@ export declare namespace ISchemaValidator {
|
|
|
29
29
|
* A schema validation error definition.
|
|
30
30
|
*/
|
|
31
31
|
interface IError {
|
|
32
|
-
/**
|
|
33
|
-
* The path in the data where the error occurred.
|
|
34
|
-
*/
|
|
35
|
-
dataPath: string;
|
|
36
32
|
/**
|
|
37
33
|
* The keyword whose validation failed.
|
|
38
34
|
*/
|
|
39
|
-
keyword: string;
|
|
35
|
+
keyword: string | string[];
|
|
40
36
|
/**
|
|
41
37
|
* The error message.
|
|
42
38
|
*/
|
|
43
|
-
message
|
|
39
|
+
message?: string;
|
|
44
40
|
/**
|
|
45
41
|
* Optional parameter metadata that might be included in an error.
|
|
46
42
|
*/
|
|
@@ -49,6 +45,26 @@ export declare namespace ISchemaValidator {
|
|
|
49
45
|
* The path in the schema where the error occurred.
|
|
50
46
|
*/
|
|
51
47
|
schemaPath: string;
|
|
48
|
+
/**
|
|
49
|
+
* @todo handle new fields from ajv8
|
|
50
|
+
**/
|
|
51
|
+
schema?: unknown;
|
|
52
|
+
/**
|
|
53
|
+
* @todo handle new fields from ajv8
|
|
54
|
+
**/
|
|
55
|
+
instancePath: string;
|
|
56
|
+
/**
|
|
57
|
+
* @todo handle new fields from ajv8
|
|
58
|
+
**/
|
|
59
|
+
propertyName?: string;
|
|
60
|
+
/**
|
|
61
|
+
* @todo handle new fields from ajv8
|
|
62
|
+
**/
|
|
63
|
+
data?: unknown;
|
|
64
|
+
/**
|
|
65
|
+
* @todo handle new fields from ajv8
|
|
66
|
+
**/
|
|
67
|
+
parentSchema?: unknown;
|
|
52
68
|
}
|
|
53
69
|
}
|
|
54
70
|
/**
|
|
@@ -229,10 +245,35 @@ export declare class SettingRegistry implements ISettingRegistry {
|
|
|
229
245
|
private _timeout;
|
|
230
246
|
private _transformers;
|
|
231
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Base settings specified by a JSON schema.
|
|
250
|
+
*/
|
|
251
|
+
export declare class BaseSettings<T extends ISettingRegistry.IProperty = ISettingRegistry.IProperty> {
|
|
252
|
+
constructor(options: {
|
|
253
|
+
schema: T;
|
|
254
|
+
});
|
|
255
|
+
/**
|
|
256
|
+
* The plugin's schema.
|
|
257
|
+
*/
|
|
258
|
+
get schema(): T;
|
|
259
|
+
/**
|
|
260
|
+
* Checks if any fields are different from the default value.
|
|
261
|
+
*/
|
|
262
|
+
isDefault(user: ReadonlyPartialJSONObject): boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Calculate the default value of a setting by iterating through the schema.
|
|
265
|
+
*
|
|
266
|
+
* @param key - The name of the setting whose default value is calculated.
|
|
267
|
+
*
|
|
268
|
+
* @returns A calculated default JSON value for a specific setting.
|
|
269
|
+
*/
|
|
270
|
+
default(key?: string): PartialJSONValue | undefined;
|
|
271
|
+
private _schema;
|
|
272
|
+
}
|
|
232
273
|
/**
|
|
233
274
|
* A manager for a specific plugin's settings.
|
|
234
275
|
*/
|
|
235
|
-
export declare class Settings implements ISettingRegistry.ISettings {
|
|
276
|
+
export declare class Settings extends BaseSettings<ISettingRegistry.ISchema> implements ISettingRegistry.ISettings {
|
|
236
277
|
/**
|
|
237
278
|
* Instantiate a new plugin settings manager.
|
|
238
279
|
*/
|
|
@@ -258,18 +299,13 @@ export declare class Settings implements ISettingRegistry.ISettings {
|
|
|
258
299
|
*/
|
|
259
300
|
get isDisposed(): boolean;
|
|
260
301
|
get plugin(): ISettingRegistry.IPlugin;
|
|
261
|
-
/**
|
|
262
|
-
* The plugin's schema.
|
|
263
|
-
*/
|
|
264
|
-
get schema(): ISettingRegistry.ISchema;
|
|
265
302
|
/**
|
|
266
303
|
* The plugin settings raw text value.
|
|
267
304
|
*/
|
|
268
305
|
get raw(): string;
|
|
269
306
|
/**
|
|
270
|
-
*
|
|
307
|
+
* Whether the settings have been modified by the user or not.
|
|
271
308
|
*/
|
|
272
|
-
isDefault(user: ReadonlyPartialJSONObject): boolean;
|
|
273
309
|
get isModified(): boolean;
|
|
274
310
|
/**
|
|
275
311
|
* The user settings.
|
|
@@ -283,14 +319,6 @@ export declare class Settings implements ISettingRegistry.ISettings {
|
|
|
283
319
|
* Return the defaults in a commented JSON format.
|
|
284
320
|
*/
|
|
285
321
|
annotatedDefaults(): string;
|
|
286
|
-
/**
|
|
287
|
-
* Calculate the default value of a setting by iterating through the schema.
|
|
288
|
-
*
|
|
289
|
-
* @param key - The name of the setting whose default value is calculated.
|
|
290
|
-
*
|
|
291
|
-
* @returns A calculated default JSON value for a specific setting.
|
|
292
|
-
*/
|
|
293
|
-
default(key?: string): PartialJSONValue | undefined;
|
|
294
322
|
/**
|
|
295
323
|
* Dispose of the plugin settings resources.
|
|
296
324
|
*/
|
package/lib/settingregistry.js
CHANGED
|
@@ -11,6 +11,17 @@ import SCHEMA from './plugin-schema.json';
|
|
|
11
11
|
* An alias for the JSON deep copy function.
|
|
12
12
|
*/
|
|
13
13
|
const copy = JSONExt.deepCopy;
|
|
14
|
+
/** Default arguments for Ajv instances.
|
|
15
|
+
*
|
|
16
|
+
* https://ajv.js.org/options.html
|
|
17
|
+
*/
|
|
18
|
+
const AJV_DEFAULT_OPTIONS = {
|
|
19
|
+
/**
|
|
20
|
+
* @todo the implications of enabling strict mode are beyond the scope of
|
|
21
|
+
* the initial PR
|
|
22
|
+
*/
|
|
23
|
+
strict: false
|
|
24
|
+
};
|
|
14
25
|
/**
|
|
15
26
|
* The default number of milliseconds before a `load()` call to the registry
|
|
16
27
|
* will wait before timing out if it requires a transformation that has not been
|
|
@@ -29,8 +40,11 @@ export class DefaultSchemaValidator {
|
|
|
29
40
|
* Instantiate a schema validator.
|
|
30
41
|
*/
|
|
31
42
|
constructor() {
|
|
32
|
-
this._composer = new Ajv({
|
|
33
|
-
|
|
43
|
+
this._composer = new Ajv({
|
|
44
|
+
useDefaults: true,
|
|
45
|
+
...AJV_DEFAULT_OPTIONS
|
|
46
|
+
});
|
|
47
|
+
this._validator = new Ajv({ ...AJV_DEFAULT_OPTIONS });
|
|
34
48
|
this._composer.addSchema(SCHEMA, 'jupyterlab-plugin-schema');
|
|
35
49
|
this._validator.addSchema(SCHEMA, 'jupyterlab-plugin-schema');
|
|
36
50
|
}
|
|
@@ -55,7 +69,7 @@ export class DefaultSchemaValidator {
|
|
|
55
69
|
const keyword = 'schema';
|
|
56
70
|
const message = `Setting registry schemas' root-level type must be ` +
|
|
57
71
|
`'object', rejecting type: ${plugin.schema.type}`;
|
|
58
|
-
return [{
|
|
72
|
+
return [{ instancePath: 'type', keyword, schemaPath: '', message }];
|
|
59
73
|
}
|
|
60
74
|
const errors = this._addSchema(plugin.id, plugin.schema);
|
|
61
75
|
return errors || this.validateData(plugin);
|
|
@@ -69,7 +83,7 @@ export class DefaultSchemaValidator {
|
|
|
69
83
|
if (error instanceof SyntaxError) {
|
|
70
84
|
return [
|
|
71
85
|
{
|
|
72
|
-
|
|
86
|
+
instancePath: '',
|
|
73
87
|
keyword: 'syntax',
|
|
74
88
|
schemaPath: '',
|
|
75
89
|
message: error.message
|
|
@@ -80,7 +94,7 @@ export class DefaultSchemaValidator {
|
|
|
80
94
|
const line = error.lineNumber;
|
|
81
95
|
return [
|
|
82
96
|
{
|
|
83
|
-
|
|
97
|
+
instancePath: '',
|
|
84
98
|
keyword: 'parse',
|
|
85
99
|
schemaPath: '',
|
|
86
100
|
message: `${description} (line ${line} column ${column})`
|
|
@@ -226,7 +240,7 @@ export class SettingRegistry {
|
|
|
226
240
|
if (fetched === undefined) {
|
|
227
241
|
throw [
|
|
228
242
|
{
|
|
229
|
-
|
|
243
|
+
instancePath: '',
|
|
230
244
|
keyword: 'id',
|
|
231
245
|
message: `Could not fetch settings for ${plugin}.`,
|
|
232
246
|
schemaPath: ''
|
|
@@ -281,7 +295,10 @@ export class SettingRegistry {
|
|
|
281
295
|
}
|
|
282
296
|
// Parse the raw JSON string removing all comments and return an object.
|
|
283
297
|
const raw = json5.parse(plugins[plugin].raw);
|
|
284
|
-
plugins[plugin].raw = Private.annotatedPlugin(plugins[plugin],
|
|
298
|
+
plugins[plugin].raw = Private.annotatedPlugin(plugins[plugin], {
|
|
299
|
+
...raw,
|
|
300
|
+
[key]: value
|
|
301
|
+
});
|
|
285
302
|
return this._save(plugin);
|
|
286
303
|
}
|
|
287
304
|
/**
|
|
@@ -305,7 +322,9 @@ export class SettingRegistry {
|
|
|
305
322
|
transform(plugin, transforms) {
|
|
306
323
|
const transformers = this._transformers;
|
|
307
324
|
if (plugin in transformers) {
|
|
308
|
-
|
|
325
|
+
const error = new Error(`${plugin} already has a transformer.`);
|
|
326
|
+
error.name = 'TransformError';
|
|
327
|
+
throw error;
|
|
309
328
|
}
|
|
310
329
|
transformers[plugin] = {
|
|
311
330
|
fetch: transforms.fetch || (plugin => plugin),
|
|
@@ -347,9 +366,9 @@ export class SettingRegistry {
|
|
|
347
366
|
catch (errors) {
|
|
348
367
|
const output = [`Validating ${plugin} failed:`];
|
|
349
368
|
errors.forEach((error, index) => {
|
|
350
|
-
const {
|
|
351
|
-
if (
|
|
352
|
-
output.push(`${index} - schema @ ${schemaPath}, data @ ${
|
|
369
|
+
const { instancePath, schemaPath, keyword, message } = error;
|
|
370
|
+
if (instancePath || schemaPath) {
|
|
371
|
+
output.push(`${index} - schema @ ${schemaPath}, data @ ${instancePath}`);
|
|
353
372
|
}
|
|
354
373
|
output.push(`{${keyword}} ${message}`);
|
|
355
374
|
});
|
|
@@ -396,7 +415,7 @@ export class SettingRegistry {
|
|
|
396
415
|
if (fetched === undefined) {
|
|
397
416
|
throw [
|
|
398
417
|
{
|
|
399
|
-
|
|
418
|
+
instancePath: '',
|
|
400
419
|
keyword: 'id',
|
|
401
420
|
message: `Could not fetch settings for ${plugin}.`,
|
|
402
421
|
schemaPath: ''
|
|
@@ -422,7 +441,7 @@ export class SettingRegistry {
|
|
|
422
441
|
if (transformed.id !== id) {
|
|
423
442
|
throw [
|
|
424
443
|
{
|
|
425
|
-
|
|
444
|
+
instancePath: '',
|
|
426
445
|
keyword: 'id',
|
|
427
446
|
message: 'Plugin transformations cannot change plugin IDs.',
|
|
428
447
|
schemaPath: ''
|
|
@@ -442,7 +461,7 @@ export class SettingRegistry {
|
|
|
442
461
|
}
|
|
443
462
|
throw [
|
|
444
463
|
{
|
|
445
|
-
|
|
464
|
+
instancePath: '',
|
|
446
465
|
keyword: 'timeout',
|
|
447
466
|
message: `Transforming ${plugin.id} timed out.`,
|
|
448
467
|
schemaPath: ''
|
|
@@ -462,14 +481,58 @@ export class SettingRegistry {
|
|
|
462
481
|
this.plugins[plugin.id] = await this._transform('compose', plugin);
|
|
463
482
|
}
|
|
464
483
|
}
|
|
484
|
+
/**
|
|
485
|
+
* Base settings specified by a JSON schema.
|
|
486
|
+
*/
|
|
487
|
+
export class BaseSettings {
|
|
488
|
+
constructor(options) {
|
|
489
|
+
this._schema = options.schema;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* The plugin's schema.
|
|
493
|
+
*/
|
|
494
|
+
get schema() {
|
|
495
|
+
return this._schema;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Checks if any fields are different from the default value.
|
|
499
|
+
*/
|
|
500
|
+
isDefault(user) {
|
|
501
|
+
for (const key in this.schema.properties) {
|
|
502
|
+
const value = user[key];
|
|
503
|
+
const defaultValue = this.default(key);
|
|
504
|
+
if (value === undefined ||
|
|
505
|
+
defaultValue === undefined ||
|
|
506
|
+
JSONExt.deepEqual(value, JSONExt.emptyObject) ||
|
|
507
|
+
JSONExt.deepEqual(value, JSONExt.emptyArray)) {
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
if (!JSONExt.deepEqual(value, defaultValue)) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Calculate the default value of a setting by iterating through the schema.
|
|
518
|
+
*
|
|
519
|
+
* @param key - The name of the setting whose default value is calculated.
|
|
520
|
+
*
|
|
521
|
+
* @returns A calculated default JSON value for a specific setting.
|
|
522
|
+
*/
|
|
523
|
+
default(key) {
|
|
524
|
+
return Private.reifyDefault(this.schema, key);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
465
527
|
/**
|
|
466
528
|
* A manager for a specific plugin's settings.
|
|
467
529
|
*/
|
|
468
|
-
export class Settings {
|
|
530
|
+
export class Settings extends BaseSettings {
|
|
469
531
|
/**
|
|
470
532
|
* Instantiate a new plugin settings manager.
|
|
471
533
|
*/
|
|
472
534
|
constructor(options) {
|
|
535
|
+
super({ schema: options.plugin.schema });
|
|
473
536
|
this._changed = new Signal(this);
|
|
474
537
|
this._isDisposed = false;
|
|
475
538
|
this.id = options.plugin.id;
|
|
@@ -497,12 +560,6 @@ export class Settings {
|
|
|
497
560
|
get plugin() {
|
|
498
561
|
return this.registry.plugins[this.id];
|
|
499
562
|
}
|
|
500
|
-
/**
|
|
501
|
-
* The plugin's schema.
|
|
502
|
-
*/
|
|
503
|
-
get schema() {
|
|
504
|
-
return this.plugin.schema;
|
|
505
|
-
}
|
|
506
563
|
/**
|
|
507
564
|
* The plugin settings raw text value.
|
|
508
565
|
*/
|
|
@@ -510,24 +567,8 @@ export class Settings {
|
|
|
510
567
|
return this.plugin.raw;
|
|
511
568
|
}
|
|
512
569
|
/**
|
|
513
|
-
*
|
|
570
|
+
* Whether the settings have been modified by the user or not.
|
|
514
571
|
*/
|
|
515
|
-
isDefault(user) {
|
|
516
|
-
for (const key in this.schema.properties) {
|
|
517
|
-
const value = user[key];
|
|
518
|
-
const defaultValue = this.default(key);
|
|
519
|
-
if (value === undefined ||
|
|
520
|
-
defaultValue === undefined ||
|
|
521
|
-
JSONExt.deepEqual(value, JSONExt.emptyObject) ||
|
|
522
|
-
JSONExt.deepEqual(value, JSONExt.emptyArray)) {
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
if (!JSONExt.deepEqual(value, defaultValue)) {
|
|
526
|
-
return false;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
return true;
|
|
530
|
-
}
|
|
531
572
|
get isModified() {
|
|
532
573
|
return !this.isDefault(this.user);
|
|
533
574
|
}
|
|
@@ -549,16 +590,6 @@ export class Settings {
|
|
|
549
590
|
annotatedDefaults() {
|
|
550
591
|
return Private.annotatedDefaults(this.schema, this.id);
|
|
551
592
|
}
|
|
552
|
-
/**
|
|
553
|
-
* Calculate the default value of a setting by iterating through the schema.
|
|
554
|
-
*
|
|
555
|
-
* @param key - The name of the setting whose default value is calculated.
|
|
556
|
-
*
|
|
557
|
-
* @returns A calculated default JSON value for a specific setting.
|
|
558
|
-
*/
|
|
559
|
-
default(key) {
|
|
560
|
-
return Private.reifyDefault(this.schema, key);
|
|
561
|
-
}
|
|
562
593
|
/**
|
|
563
594
|
* Dispose of the plugin settings resources.
|
|
564
595
|
*/
|
|
@@ -667,7 +698,11 @@ export class Settings {
|
|
|
667
698
|
addition.forEach(menu => {
|
|
668
699
|
const refIndex = merged.findIndex(ref => ref.id === menu.id);
|
|
669
700
|
if (refIndex >= 0) {
|
|
670
|
-
merged[refIndex] =
|
|
701
|
+
merged[refIndex] = {
|
|
702
|
+
...merged[refIndex],
|
|
703
|
+
...menu,
|
|
704
|
+
items: reconcileItems(merged[refIndex].items, menu.items, warn, addNewItems)
|
|
705
|
+
};
|
|
671
706
|
}
|
|
672
707
|
else {
|
|
673
708
|
if (addNewItems) {
|
|
@@ -700,7 +735,7 @@ export class Settings {
|
|
|
700
735
|
switch ((_a = item.type) !== null && _a !== void 0 ? _a : 'command') {
|
|
701
736
|
case 'separator':
|
|
702
737
|
if (addNewItems) {
|
|
703
|
-
items.push(
|
|
738
|
+
items.push({ ...item });
|
|
704
739
|
}
|
|
705
740
|
break;
|
|
706
741
|
case 'submenu':
|
|
@@ -712,9 +747,13 @@ export class Settings {
|
|
|
712
747
|
}
|
|
713
748
|
}
|
|
714
749
|
else {
|
|
715
|
-
items[refIndex] =
|
|
750
|
+
items[refIndex] = {
|
|
751
|
+
...items[refIndex],
|
|
752
|
+
...item,
|
|
753
|
+
submenu: reconcileMenus(items[refIndex].submenu
|
|
716
754
|
? [items[refIndex].submenu]
|
|
717
|
-
: null, [item.submenu], warn, addNewItems)[0]
|
|
755
|
+
: null, [item.submenu], warn, addNewItems)[0]
|
|
756
|
+
};
|
|
718
757
|
}
|
|
719
758
|
}
|
|
720
759
|
break;
|
|
@@ -728,14 +767,14 @@ export class Settings {
|
|
|
728
767
|
});
|
|
729
768
|
if (refIndex < 0) {
|
|
730
769
|
if (addNewItems) {
|
|
731
|
-
items.push(
|
|
770
|
+
items.push({ ...item });
|
|
732
771
|
}
|
|
733
772
|
}
|
|
734
773
|
else {
|
|
735
774
|
if (warn) {
|
|
736
775
|
console.warn(`Menu entry for command '${item.command}' is duplicated.`);
|
|
737
776
|
}
|
|
738
|
-
items[refIndex] =
|
|
777
|
+
items[refIndex] = { ...items[refIndex], ...item };
|
|
739
778
|
}
|
|
740
779
|
}
|
|
741
780
|
}
|
|
@@ -752,12 +791,15 @@ export class Settings {
|
|
|
752
791
|
function filterDisabledItems(items) {
|
|
753
792
|
return items.reduce((final, value) => {
|
|
754
793
|
var _a;
|
|
755
|
-
const copy =
|
|
794
|
+
const copy = { ...value };
|
|
756
795
|
if (!copy.disabled) {
|
|
757
796
|
if (copy.type === 'submenu') {
|
|
758
797
|
const { submenu } = copy;
|
|
759
798
|
if (submenu && !submenu.disabled) {
|
|
760
|
-
copy.submenu =
|
|
799
|
+
copy.submenu = {
|
|
800
|
+
...submenu,
|
|
801
|
+
items: filterDisabledItems((_a = submenu.items) !== null && _a !== void 0 ? _a : [])
|
|
802
|
+
};
|
|
761
803
|
}
|
|
762
804
|
}
|
|
763
805
|
final.push(copy);
|
|
@@ -829,7 +871,7 @@ export class Settings {
|
|
|
829
871
|
.filter(shortcut => !shortcut.disabled)
|
|
830
872
|
// Fix shortcuts comparison in rjsf Form to avoid polluting the user settings
|
|
831
873
|
.map(shortcut => {
|
|
832
|
-
return
|
|
874
|
+
return { args: {}, ...shortcut };
|
|
833
875
|
}));
|
|
834
876
|
}
|
|
835
877
|
SettingRegistry.reconcileShortcuts = reconcileShortcuts;
|
|
@@ -851,39 +893,17 @@ export class Settings {
|
|
|
851
893
|
const items = JSONExt.deepCopy(reference);
|
|
852
894
|
// Merge array element depending on the type
|
|
853
895
|
addition.forEach(item => {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
if (refIndex < 0) {
|
|
864
|
-
items.push(Object.assign({}, item));
|
|
865
|
-
}
|
|
866
|
-
else {
|
|
867
|
-
if (warn) {
|
|
868
|
-
console.warn(`Toolbar item for command '${item.command}' is duplicated.`);
|
|
869
|
-
}
|
|
870
|
-
items[refIndex] = Object.assign(Object.assign({}, items[refIndex]), item);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
break;
|
|
874
|
-
case 'spacer':
|
|
875
|
-
default: {
|
|
876
|
-
const refIndex = items.findIndex(ref => ref.name === item.name);
|
|
877
|
-
if (refIndex < 0) {
|
|
878
|
-
items.push(Object.assign({}, item));
|
|
879
|
-
}
|
|
880
|
-
else {
|
|
881
|
-
if (warn) {
|
|
882
|
-
console.warn(`Toolbar item '${item.name}' is duplicated.`);
|
|
883
|
-
}
|
|
884
|
-
items[refIndex] = Object.assign(Object.assign({}, items[refIndex]), item);
|
|
885
|
-
}
|
|
896
|
+
// Name must be unique so it's sufficient to only compare it
|
|
897
|
+
const refIndex = items.findIndex(ref => ref.name === item.name);
|
|
898
|
+
if (refIndex < 0) {
|
|
899
|
+
items.push({ ...item });
|
|
900
|
+
}
|
|
901
|
+
else {
|
|
902
|
+
if (warn &&
|
|
903
|
+
JSONExt.deepEqual(Object.keys(item), Object.keys(items[refIndex]))) {
|
|
904
|
+
console.warn(`Toolbar item '${item.name}' is duplicated.`);
|
|
886
905
|
}
|
|
906
|
+
items[refIndex] = { ...items[refIndex], ...item };
|
|
887
907
|
}
|
|
888
908
|
});
|
|
889
909
|
return items;
|
|
@@ -999,9 +1019,9 @@ var Private;
|
|
|
999
1019
|
/**
|
|
1000
1020
|
* Create a fully extrapolated default value for a root key in a schema.
|
|
1001
1021
|
*/
|
|
1002
|
-
function reifyDefault(schema, root) {
|
|
1003
|
-
var _a, _b, _c;
|
|
1004
|
-
|
|
1022
|
+
function reifyDefault(schema, root, definitions) {
|
|
1023
|
+
var _a, _b, _c, _d;
|
|
1024
|
+
definitions = definitions !== null && definitions !== void 0 ? definitions : schema.definitions;
|
|
1005
1025
|
// If the property is at the root level, traverse its schema.
|
|
1006
1026
|
schema = (root ? (_a = schema.properties) === null || _a === void 0 ? void 0 : _a[root] : schema) || {};
|
|
1007
1027
|
if (schema.type === 'object') {
|
|
@@ -1010,7 +1030,7 @@ var Private;
|
|
|
1010
1030
|
// Iterate through and populate each child property.
|
|
1011
1031
|
const props = schema.properties || {};
|
|
1012
1032
|
for (const property in props) {
|
|
1013
|
-
result[property] = reifyDefault(props[property]);
|
|
1033
|
+
result[property] = reifyDefault(props[property], undefined, definitions);
|
|
1014
1034
|
}
|
|
1015
1035
|
return result;
|
|
1016
1036
|
}
|
|
@@ -1027,9 +1047,9 @@ var Private;
|
|
|
1027
1047
|
// Iterate through the items in the array and fill in defaults
|
|
1028
1048
|
for (const item in result) {
|
|
1029
1049
|
// Use the values that are hard-coded in the default array over the defaults for each field.
|
|
1030
|
-
const reified = reifyDefault(props)
|
|
1050
|
+
const reified = (_c = reifyDefault(props, undefined, definitions)) !== null && _c !== void 0 ? _c : {};
|
|
1031
1051
|
for (const prop in reified) {
|
|
1032
|
-
if ((
|
|
1052
|
+
if ((_d = result[item]) === null || _d === void 0 ? void 0 : _d[prop]) {
|
|
1033
1053
|
reified[prop] = result[item][prop];
|
|
1034
1054
|
}
|
|
1035
1055
|
}
|