@es-joy/jsoe 0.5.1 → 0.6.1
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/.eslintignore +2 -0
- package/.eslintrc.cjs +2 -0
- package/.nyc_output/out.json +121296 -0
- package/CHANGES.md +10 -0
- package/README.md +47 -21
- package/cypress.config.ts +13 -0
- package/demo/index-instrumented.html +29 -0
- package/demo/index.html +10 -1
- package/demo/index.js +482 -126
- package/dist/formatAndTypeChoices.d.ts +2 -2
- package/dist/formatAndTypeChoices.d.ts.map +1 -1
- package/dist/formats/json.d.ts.map +1 -1
- package/dist/formats/structuredCloning.d.ts +2 -1
- package/dist/formats/structuredCloning.d.ts.map +1 -1
- package/dist/fundamentalTypes/arrayType.d.ts +6 -37
- package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
- package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
- package/dist/fundamentalTypes/errorType.d.ts +6 -0
- package/dist/fundamentalTypes/errorType.d.ts.map +1 -0
- package/dist/fundamentalTypes/mapType.d.ts +6 -0
- package/dist/fundamentalTypes/mapType.d.ts.map +1 -0
- package/dist/fundamentalTypes/nullType.d.ts.map +1 -1
- package/dist/fundamentalTypes/objectReferenceType.d.ts.map +1 -1
- package/dist/fundamentalTypes/setType.d.ts +6 -0
- package/dist/fundamentalTypes/setType.d.ts.map +1 -0
- package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -1
- package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -1
- package/dist/subTypes/blobHTMLType.d.ts +12 -6
- package/dist/subTypes/blobHTMLType.d.ts.map +1 -1
- package/dist/superTypes/SpecialNumberType.d.ts +14 -0
- package/dist/superTypes/SpecialNumberType.d.ts.map +1 -0
- package/dist/superTypes/SpecialRealNumberType.d.ts +6 -0
- package/dist/superTypes/SpecialRealNumberType.d.ts.map +1 -0
- package/dist/superTypes/errorsSpecialType.d.ts +8 -0
- package/dist/superTypes/errorsSpecialType.d.ts.map +1 -0
- package/dist/typeChoices.d.ts +4 -2
- package/dist/typeChoices.d.ts.map +1 -1
- package/dist/types.d.ts +83 -231
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/dialogs.d.ts +22 -22
- package/dist/utils/dialogs.d.ts.map +1 -1
- package/dist/utils/templateUtils.d.ts +6 -6
- package/dist/utils/templateUtils.d.ts.map +1 -1
- package/dist/vendor-imports.d.ts +1 -1
- package/package.json +39 -34
- package/rollup.config.js +14 -2
- package/server.js +1 -1
- package/src/formatAndTypeChoices.js +9 -9
- package/src/formats/indexedDBKey.js +2 -2
- package/src/formats/json.js +1 -2
- package/src/formats/structuredCloning.js +101 -29
- package/src/formats.js +2 -2
- package/src/fundamentalTypes/arrayReferenceType.js +3 -3
- package/src/fundamentalTypes/arrayType.js +390 -87
- package/src/fundamentalTypes/dateType.js +4 -6
- package/src/fundamentalTypes/errorType.js +416 -0
- package/src/fundamentalTypes/mapType.js +34 -0
- package/src/fundamentalTypes/nullType.js +1 -2
- package/src/fundamentalTypes/objectReferenceType.js +2 -1
- package/src/fundamentalTypes/regexpType.js +2 -2
- package/src/fundamentalTypes/setType.js +34 -0
- package/src/fundamentalTypes/sparseUndefinedType.js +2 -3
- package/src/fundamentalTypes/undefinedType.js +2 -3
- package/src/jsoe.css +3 -0
- package/src/subTypes/blobHTMLType.js +37 -33
- package/src/subTypes/falseType.js +2 -2
- package/src/subTypes/trueType.js +2 -2
- package/src/superTypes/{SpecialNumberSuperType.js → SpecialNumberType.js} +1 -1
- package/src/superTypes/{SpecialRealNumberSuperType.js → SpecialRealNumberType.js} +3 -2
- package/src/superTypes/errorsSpecialType.js +768 -0
- package/src/typeChoices.js +27 -20
- package/src/types.js +71 -39
- package/src/utils/dialogs.js +11 -12
- package/src/utils/jsonPointer.js +3 -3
- package/src/utils/templateUtils.js +4 -4
- package/src/vendor-imports.js +2 -2
- package/tsconfig.json +1 -1
- package/typings/CypressPlugins.d.ts +10 -0
- package/vendor/jamilih/dist/jml-es.js +126 -106
- package/vendor/typeson-registry/dist/index.js +188 -44
|
@@ -17,9 +17,10 @@ import json from './json.js';
|
|
|
17
17
|
* type: import('../types.js').AvailableType,
|
|
18
18
|
* value: import('../formats.js').StructuredCloneValue,
|
|
19
19
|
* bringIntoFocus?: boolean,
|
|
20
|
+
* setAValue?: boolean,
|
|
20
21
|
* schemaContent?: object,
|
|
21
22
|
* schemaState?: import('../types.js').GetPossibleSchemasForPathAndType
|
|
22
|
-
* }) => HTMLElement} AddAndSetArrayElement
|
|
23
|
+
* }) => HTMLElement|null} AddAndSetArrayElement
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -44,6 +45,10 @@ const encapsulateObserver = (stateObj) => {
|
|
|
44
45
|
* }}}
|
|
45
46
|
*/
|
|
46
47
|
const parents = {};
|
|
48
|
+
|
|
49
|
+
/** @type {string[]} */
|
|
50
|
+
const mapPaths = [];
|
|
51
|
+
|
|
47
52
|
return (observerObj) => {
|
|
48
53
|
const {
|
|
49
54
|
type,
|
|
@@ -57,13 +62,15 @@ const encapsulateObserver = (stateObj) => {
|
|
|
57
62
|
endIterateUnsetNumeric,
|
|
58
63
|
clone
|
|
59
64
|
} = observerObj;
|
|
60
|
-
// console.log('observerObj', observerObj);
|
|
61
65
|
if ('replaced' in observerObj) {
|
|
62
66
|
return;
|
|
63
67
|
}
|
|
64
68
|
if (cyclic === 'readonly' && !Array.isArray(observerObj.value)) {
|
|
65
69
|
return;
|
|
66
70
|
}
|
|
71
|
+
if (cyclic === 'readonly' && type === 'set') {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
67
74
|
if (endIterateIn || endIterateOwn) {
|
|
68
75
|
return;
|
|
69
76
|
}
|
|
@@ -73,6 +80,12 @@ const encapsulateObserver = (stateObj) => {
|
|
|
73
80
|
return;
|
|
74
81
|
}
|
|
75
82
|
|
|
83
|
+
// What other situations is this firing twice, and it
|
|
84
|
+
// shouldn't reach here?
|
|
85
|
+
if (observerObj.replacing && type === 'negativeZero') {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
76
89
|
/* istanbul ignore if -- Not part of format */
|
|
77
90
|
if (type === 'sparseUndefined') { // We'll handle otherwise
|
|
78
91
|
return;
|
|
@@ -119,12 +132,21 @@ const encapsulateObserver = (stateObj) => {
|
|
|
119
132
|
const parentPath = li === -1 ? '' : keypath.slice(0, li);
|
|
120
133
|
|
|
121
134
|
const hasChildren = [
|
|
122
|
-
'array', 'object',
|
|
135
|
+
'array', 'object', 'set', 'map',
|
|
123
136
|
// 'sparseArrays',
|
|
124
137
|
'arrayNonindexKeys'
|
|
125
138
|
].includes(newType);
|
|
126
139
|
|
|
140
|
+
// Maps are followed up by arrays which we don't want as such;
|
|
141
|
+
// we track the paths to avoid reporting these child arrays
|
|
142
|
+
const mapType = type === 'map' &&
|
|
143
|
+
Object.prototype.toString.call(value) === '[object Map]';
|
|
144
|
+
if (mapType) {
|
|
145
|
+
mapPaths.push(keypath);
|
|
146
|
+
}
|
|
147
|
+
|
|
127
148
|
if (!stateObj.rootUI) {
|
|
149
|
+
// console.log('vvvv0', newType, newValue);
|
|
128
150
|
stateObj.rootUI = Types.getUIForModeAndType({
|
|
129
151
|
readonly,
|
|
130
152
|
typeNamespace,
|
|
@@ -152,6 +174,18 @@ const encapsulateObserver = (stateObj) => {
|
|
|
152
174
|
* @type {HTMLElement &
|
|
153
175
|
* {$addAndSetArrayElement: AddAndSetArrayElement}}
|
|
154
176
|
*/ (stateObj.rootUI);
|
|
177
|
+
|
|
178
|
+
// Since we're skipping the array elements, we need to add the
|
|
179
|
+
// map element to the array index where the array children
|
|
180
|
+
// will be found (which we do want)
|
|
181
|
+
if (mapType) {
|
|
182
|
+
/** @type {Map<any, any>} */ [...value].forEach((_, i) => {
|
|
183
|
+
parents[i] = /**
|
|
184
|
+
* @type {HTMLElement &
|
|
185
|
+
* {$addAndSetArrayElement: AddAndSetArrayElement}}
|
|
186
|
+
*/ (stateObj.rootUI);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
155
189
|
return;
|
|
156
190
|
}
|
|
157
191
|
|
|
@@ -172,6 +206,22 @@ const encapsulateObserver = (stateObj) => {
|
|
|
172
206
|
return;
|
|
173
207
|
}
|
|
174
208
|
|
|
209
|
+
// Skip the array structures immediately following the Map,
|
|
210
|
+
// as map needs to handle
|
|
211
|
+
if (!mapType && mapPaths.some((mapPath) => {
|
|
212
|
+
if (mapPath === keypath ||
|
|
213
|
+
(mapPath === '' && (/^\d+$/u).test(keypath))) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
const trailingIndex = keypath.match(/\.\d+$/u);
|
|
217
|
+
return (trailingIndex && mapPath !== '' &&
|
|
218
|
+
keypath.slice(0, -trailingIndex[0].length) === mapPath);
|
|
219
|
+
})) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// console.log('vvvv', newType, '::', newValue, '::', newValue?.cause);
|
|
224
|
+
|
|
175
225
|
const root = ui.$addAndSetArrayElement({
|
|
176
226
|
propName: arrayOrObjectPropertyName,
|
|
177
227
|
type: newType,
|
|
@@ -188,6 +238,12 @@ const encapsulateObserver = (stateObj) => {
|
|
|
188
238
|
})
|
|
189
239
|
*/
|
|
190
240
|
});
|
|
241
|
+
|
|
242
|
+
/* istanbul ignore if -- Guard for `null` return */
|
|
243
|
+
if (!root) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
191
247
|
if (!readonly) {
|
|
192
248
|
Types.setValue({
|
|
193
249
|
type: newType,
|
|
@@ -210,6 +266,18 @@ const encapsulateObserver = (stateObj) => {
|
|
|
210
266
|
*/ (
|
|
211
267
|
root
|
|
212
268
|
);
|
|
269
|
+
|
|
270
|
+
// Since we're skipping the array elements, we need to add the
|
|
271
|
+
// map element to the array index where the array children
|
|
272
|
+
// will be found (which we do want)
|
|
273
|
+
if (mapType) {
|
|
274
|
+
/** @type {Map<any, any>} */ [...value].forEach((_, i) => {
|
|
275
|
+
parents[`${keypath}.${i}`] = /**
|
|
276
|
+
* @type {HTMLElement &
|
|
277
|
+
* {$addAndSetArrayElement: AddAndSetArrayElement}}
|
|
278
|
+
*/ (root);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
213
281
|
}
|
|
214
282
|
});
|
|
215
283
|
};
|
|
@@ -247,7 +315,7 @@ const canonicalToAvailableType = (format, state, valType, v) => {
|
|
|
247
315
|
* @type {import('../types.js').AvailableType|undefined}
|
|
248
316
|
*/
|
|
249
317
|
let ret;
|
|
250
|
-
console.log('format, state, valType, v', format, state, valType, v);
|
|
318
|
+
// console.log('format, state, valType, v', format, state, valType, v);
|
|
251
319
|
|
|
252
320
|
/**
|
|
253
321
|
* @param {string} newValType
|
|
@@ -278,9 +346,9 @@ const canonicalToAvailableType = (format, state, valType, v) => {
|
|
|
278
346
|
})) {
|
|
279
347
|
return /** @type {import('../types.js').AvailableType} */ (ret);
|
|
280
348
|
}
|
|
281
|
-
console.log('ret', ret);
|
|
349
|
+
// console.log('ret', ret);
|
|
282
350
|
allowableTypes.some((allowableType) => {
|
|
283
|
-
// eslint-disable-next-line max-len -- Long
|
|
351
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
284
352
|
const typeObj = /** @type {import('../types.js').TypeObject & {childTypes: string[]}} */ (
|
|
285
353
|
Types.availableTypes[allowableType]
|
|
286
354
|
);
|
|
@@ -298,7 +366,7 @@ const canonicalToAvailableType = (format, state, valType, v) => {
|
|
|
298
366
|
}
|
|
299
367
|
return false;
|
|
300
368
|
});
|
|
301
|
-
console.log('ret2', ret);
|
|
369
|
+
// console.log('ret2', ret);
|
|
302
370
|
if (ret === undefined) {
|
|
303
371
|
return isInvalid(valType);
|
|
304
372
|
}
|
|
@@ -315,7 +383,7 @@ const canonicalToAvailableType = (format, state, valType, v) => {
|
|
|
315
383
|
/** @type {import('../formats.js').Format} */
|
|
316
384
|
const structuredCloning = {
|
|
317
385
|
iterate (records, stateObj) {
|
|
318
|
-
console.log('records', records);
|
|
386
|
+
// console.log('records', records);
|
|
319
387
|
if (!stateObj.format) {
|
|
320
388
|
stateObj.format = 'structuredCloning';
|
|
321
389
|
}
|
|
@@ -348,6 +416,12 @@ const structuredCloning = {
|
|
|
348
416
|
});
|
|
349
417
|
return typesForFormat;
|
|
350
418
|
}
|
|
419
|
+
// Todo: Could we implement schemas here by introducing new keys to
|
|
420
|
+
// `Types.contexts` which could be used rather than manual
|
|
421
|
+
// handling to determine a delimited group of children
|
|
422
|
+
if (state === 'errorsArray') {
|
|
423
|
+
return ['error', 'errors'];
|
|
424
|
+
}
|
|
351
425
|
return this.types();
|
|
352
426
|
/*
|
|
353
427
|
// Todo (low): These need to specify their own inner contexts
|
|
@@ -375,35 +449,33 @@ const structuredCloning = {
|
|
|
375
449
|
...jsonTypes,
|
|
376
450
|
'undef', // Explicit undefined only
|
|
377
451
|
'bigint',
|
|
378
|
-
'SpecialNumber', // '`NaN`, `Infinity`, `-Infinity`
|
|
452
|
+
'SpecialNumber', // '`NaN`, `Infinity`, `-Infinity`, `-0`
|
|
379
453
|
'date',
|
|
380
454
|
'regexp',
|
|
381
455
|
'BooleanObject',
|
|
382
456
|
'NumberObject',
|
|
383
457
|
'StringObject',
|
|
384
|
-
'
|
|
458
|
+
'error',
|
|
459
|
+
'errors',
|
|
460
|
+
'blobHTML',
|
|
461
|
+
'set',
|
|
462
|
+
'map'
|
|
385
463
|
// Ok, but will need some work
|
|
386
|
-
// '
|
|
387
|
-
// '
|
|
388
|
-
// 'arraybuffer', 'arraybufferview'
|
|
464
|
+
// 'blob', 'file', 'filelist',
|
|
465
|
+
// 'arraybuffer',
|
|
389
466
|
// 'dataview', 'imagedata', 'imagebitmap',
|
|
390
467
|
/*
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
// Intl (imperfect)
|
|
403
|
-
'IntlCollator',
|
|
404
|
-
'IntlDateTimeFormat',
|
|
405
|
-
'IntlNumberFormat'
|
|
406
|
-
*/
|
|
468
|
+
// Typed Arrays
|
|
469
|
+
'int8array',
|
|
470
|
+
'uint8array',
|
|
471
|
+
'uint8clampedarray',
|
|
472
|
+
'int16array',
|
|
473
|
+
'uint16array',
|
|
474
|
+
'int32array',
|
|
475
|
+
'uint32array',
|
|
476
|
+
'float32array',
|
|
477
|
+
'float64array',
|
|
478
|
+
*/
|
|
407
479
|
];
|
|
408
480
|
}
|
|
409
481
|
};
|
package/src/formats.js
CHANGED
|
@@ -56,8 +56,8 @@ const Formats = {
|
|
|
56
56
|
* @returns {Promise<Element>}
|
|
57
57
|
*/
|
|
58
58
|
export async function getControlsForFormatAndValue (format, record, stateObj) {
|
|
59
|
-
return await Formats.availableFormats[format]
|
|
60
|
-
|
|
59
|
+
return await Formats.availableFormats[format].
|
|
60
|
+
iterate(record, {
|
|
61
61
|
...stateObj,
|
|
62
62
|
// This had been before `stateObj` but should apparently have precedence
|
|
63
63
|
// or just avoid passing `format` to this function
|
|
@@ -35,7 +35,7 @@ const arrayReferenceType = {
|
|
|
35
35
|
structuredCloning: {
|
|
36
36
|
// after: 'sparseArrays',
|
|
37
37
|
after: 'arrayNonindexKeys',
|
|
38
|
-
contexts: ['arrayNonindexKeys', 'object']
|
|
38
|
+
contexts: ['arrayNonindexKeys', 'object', 'set']
|
|
39
39
|
// contexts: ['sparseArrays', 'object']
|
|
40
40
|
}
|
|
41
41
|
},
|
|
@@ -47,7 +47,7 @@ const arrayReferenceType = {
|
|
|
47
47
|
},
|
|
48
48
|
getValue ({root, stateObj, currentPath}) {
|
|
49
49
|
const referentPath = this.getInput({root}).value;
|
|
50
|
-
// eslint-disable-next-line max-len -- Long
|
|
50
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
51
51
|
/* istanbul ignore else -- ArrayRef will not be a root, so should have stateObj */
|
|
52
52
|
if (stateObj) {
|
|
53
53
|
if (!stateObj.paths) {
|
|
@@ -97,7 +97,7 @@ const arrayReferenceType = {
|
|
|
97
97
|
'arrayNonindexKeys'
|
|
98
98
|
// 'sparseArrays'
|
|
99
99
|
].includes(
|
|
100
|
-
|
|
100
|
+
Types.getTypeForRoot(referent)
|
|
101
101
|
);
|
|
102
102
|
};
|
|
103
103
|
let message;
|