@es-joy/jsoe 0.0.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/.editorconfig +15 -0
- package/.eslintignore +7 -0
- package/.eslintrc.cjs +120 -0
- package/CHANGES.md +5 -0
- package/LICENSE-MIT.txt +22 -0
- package/README.md +82 -0
- package/package.json +101 -0
- package/rollup.config.js +29 -0
- package/server.js +25 -0
- package/src/deepEqual.js +72 -0
- package/src/formats/indexedDBKey.js +66 -0
- package/src/formats/json.js +64 -0
- package/src/formats/schemaAndArbitrary.js +20 -0
- package/src/formats/schemaOnly.js +529 -0
- package/src/formats/structuredCloning.js +372 -0
- package/src/formats.js +229 -0
- package/src/fundamentalTypes/BooleanObjectType.js +55 -0
- package/src/fundamentalTypes/NumberObjectType.js +41 -0
- package/src/fundamentalTypes/StringObjectType.js +37 -0
- package/src/fundamentalTypes/arrayReferenceType.js +203 -0
- package/src/fundamentalTypes/arrayType.js +898 -0
- package/src/fundamentalTypes/bigintType.js +53 -0
- package/src/fundamentalTypes/dateType.js +129 -0
- package/src/fundamentalTypes/nullType.js +33 -0
- package/src/fundamentalTypes/numberType.js +56 -0
- package/src/fundamentalTypes/objectReferenceType.js +51 -0
- package/src/fundamentalTypes/objectType.js +30 -0
- package/src/fundamentalTypes/regexpType.js +95 -0
- package/src/fundamentalTypes/sparseUndefinedType.js +43 -0
- package/src/fundamentalTypes/stringType.js +31 -0
- package/src/fundamentalTypes/undefinedType.js +37 -0
- package/src/index.js +7 -0
- package/src/subTypes/blobHTMLType.js +160 -0
- package/src/subTypes/falseType.js +42 -0
- package/src/subTypes/trueType.js +42 -0
- package/src/superTypes/InfinitiesSuperType.js +49 -0
- package/src/superTypes/SpecialNumberSuperType.js +62 -0
- package/src/typeChoices.js +125 -0
- package/src/types.js +665 -0
- package/src/utils/dialogs.js +115 -0
- package/src/utils/jsonPointer.js +89 -0
- package/src/utils/templateUtils.js +106 -0
- package/src/utils/types.js +6 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {$e} from '../utils/templateUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {TypeObject}
|
|
5
|
+
*/
|
|
6
|
+
const StringObjectType = {
|
|
7
|
+
stringRegex: /^String\(([^)]*)\)$/u,
|
|
8
|
+
toValue (s) {
|
|
9
|
+
/* eslint-disable no-new-wrappers, unicorn/new-for-builtins */
|
|
10
|
+
return {value: new String(s)};
|
|
11
|
+
/* eslint-enable no-new-wrappers, unicorn/new-for-builtins */
|
|
12
|
+
},
|
|
13
|
+
option: ['StringObject'],
|
|
14
|
+
getInput ({root}) {
|
|
15
|
+
return $e(root, 'textarea');
|
|
16
|
+
},
|
|
17
|
+
getValue ({root}) {
|
|
18
|
+
return this.toValue(this.getInput({root}).value).value;
|
|
19
|
+
},
|
|
20
|
+
setValue ({root, value}) {
|
|
21
|
+
this.getInput({root}).value = value;
|
|
22
|
+
},
|
|
23
|
+
viewUI ({value}) {
|
|
24
|
+
return ['span', {dataset: {type: 'StringObject'}}, [
|
|
25
|
+
['i', ['String(']],
|
|
26
|
+
['span', [value.valueOf()]],
|
|
27
|
+
['i', [')']]
|
|
28
|
+
]];
|
|
29
|
+
},
|
|
30
|
+
editUI ({typeNamespace, value = ''}) {
|
|
31
|
+
return ['div', {dataset: {type: 'StringObject'}}, [
|
|
32
|
+
['textarea', {name: `${typeNamespace}-StringObject`}, [value]]
|
|
33
|
+
]];
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default StringObjectType;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import Types, {getPropertyValueFromLegend} from '../types.js';
|
|
2
|
+
import {$e, $$e, DOM} from '../utils/templateUtils.js';
|
|
3
|
+
import {
|
|
4
|
+
getJSONPointerParts
|
|
5
|
+
} from '../utils/jsonPointer.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @type {TypeObject}
|
|
9
|
+
*/
|
|
10
|
+
const arrayReferenceType = {
|
|
11
|
+
option: ['Array reference'],
|
|
12
|
+
type: 'array',
|
|
13
|
+
stringRegex: /^arrayRef\((?:|\/[^)]*)\)$/u,
|
|
14
|
+
toValue (s, {rootHolder, parent, parentPath}) {
|
|
15
|
+
const path = s.slice(`${this.type}Ref(`.length, -1);
|
|
16
|
+
rootHolder.push([this.type, parent, parentPath, path]);
|
|
17
|
+
return {assign: false};
|
|
18
|
+
},
|
|
19
|
+
resolveReference (path, value) {
|
|
20
|
+
let parent = value;
|
|
21
|
+
if (path !== '') {
|
|
22
|
+
getJSONPointerParts(path).forEach((pathPart) => {
|
|
23
|
+
parent = parent[pathPart];
|
|
24
|
+
if (!parent) {
|
|
25
|
+
throw new Error('Bad path');
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return parent;
|
|
30
|
+
},
|
|
31
|
+
stateDependent: {
|
|
32
|
+
structuredCloning: {
|
|
33
|
+
// after: 'sparseArrays',
|
|
34
|
+
after: 'arrayNonindexKeys',
|
|
35
|
+
contexts: ['arrayNonindexKeys', 'object']
|
|
36
|
+
// contexts: ['sparseArrays', 'object']
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
getInput ({root}) {
|
|
40
|
+
return $e(root, 'input');
|
|
41
|
+
},
|
|
42
|
+
setValue ({root, value}) {
|
|
43
|
+
this.getInput({root}).value = value;
|
|
44
|
+
},
|
|
45
|
+
getValue ({root, stateObj, currentPath}) {
|
|
46
|
+
const referentPath = this.getInput({root}).value;
|
|
47
|
+
// eslint-disable-next-line max-len -- Long
|
|
48
|
+
/* istanbul ignore else -- ArrayRef will not be a root, so should have stateObj */
|
|
49
|
+
if (stateObj) {
|
|
50
|
+
if (!stateObj.paths) {
|
|
51
|
+
stateObj.paths = {};
|
|
52
|
+
}
|
|
53
|
+
stateObj.paths[currentPath] = {
|
|
54
|
+
referentPath,
|
|
55
|
+
// Todo (low): Should be utilized along with
|
|
56
|
+
// other validation checking
|
|
57
|
+
expectArrayReferent: this.type === 'array'
|
|
58
|
+
};
|
|
59
|
+
stateObj.handlingReference = true;
|
|
60
|
+
}
|
|
61
|
+
console.log(referentPath);
|
|
62
|
+
},
|
|
63
|
+
validate ({root, topRoot}) {
|
|
64
|
+
const {type} = this;
|
|
65
|
+
const input = this.getInput({root});
|
|
66
|
+
const path = input.value;
|
|
67
|
+
const invalidMessage = (message) => {
|
|
68
|
+
return {valid: false, message};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
if (input.validity.patternMismatch) {
|
|
72
|
+
return invalidMessage(
|
|
73
|
+
'You must use a path beginning with "/" (or the empty string)'
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
if ((/~([^01]|$)/u).test(path)) {
|
|
77
|
+
return invalidMessage(
|
|
78
|
+
'You must use a valid JSON Pointer (with ' +
|
|
79
|
+
'tildes followed by 0 or 1)'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let referent = topRoot ||
|
|
84
|
+
/* istanbul ignore next -- Should always exist? */
|
|
85
|
+
root;
|
|
86
|
+
const isObjectOrArray = () => {
|
|
87
|
+
return [
|
|
88
|
+
'array', 'object',
|
|
89
|
+
'arrayNonindexKeys'
|
|
90
|
+
// 'sparseArrays'
|
|
91
|
+
].includes(
|
|
92
|
+
Types.getTypeForRoot(referent)
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
let message;
|
|
96
|
+
if (path !== '') { // If empty string, referent will be topRoot
|
|
97
|
+
if (getJSONPointerParts(path).some((pathPart, i) => {
|
|
98
|
+
// Todo (low): We should also support `arrayReference` and
|
|
99
|
+
// `objectReference`, but will need to resolve and bear
|
|
100
|
+
// in mind that references may need to be added out of
|
|
101
|
+
// order)
|
|
102
|
+
const legends = DOM.filterChildElements(
|
|
103
|
+
// Ensure we are only getting one array level at a time
|
|
104
|
+
$e(referent, '.arrayItems'), ['fieldset', 'legend']
|
|
105
|
+
);
|
|
106
|
+
const childPropertyValues = legends.map(
|
|
107
|
+
(legend) => getPropertyValueFromLegend(legend)
|
|
108
|
+
);
|
|
109
|
+
const partMatchIndex = childPropertyValues.indexOf(pathPart);
|
|
110
|
+
if (partMatchIndex === -1) {
|
|
111
|
+
message = "Specified path doesn't exist";
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
referent = $e(
|
|
115
|
+
legends[partMatchIndex].parentElement, 'div[data-type]'
|
|
116
|
+
);
|
|
117
|
+
if (referent === root) {
|
|
118
|
+
message = "Can't reference self";
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
// Condition that path isn't an object/array
|
|
122
|
+
if (!isObjectOrArray()) {
|
|
123
|
+
message = `Referent portion (at segment ${i}) is ` +
|
|
124
|
+
`not an object or array`;
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
128
|
+
})) {
|
|
129
|
+
return invalidMessage(message);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Root can only be an object or array unless it is itself
|
|
133
|
+
// else if (!isObjectOrArray()) {
|
|
134
|
+
// return invalidMessage('Referent is not an object or array');
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// UI prevents array/object references at root
|
|
138
|
+
// Condition to forbid path to self
|
|
139
|
+
// if (referent === root) {
|
|
140
|
+
// return invalidMessage("Can't reference self");
|
|
141
|
+
// }
|
|
142
|
+
|
|
143
|
+
// Condition to confirm that referenced element is an array or
|
|
144
|
+
// object (or reference) with the designated `type`
|
|
145
|
+
const referentType = Types.getTypeForRoot(referent);
|
|
146
|
+
const referentBaseType = [
|
|
147
|
+
'array',
|
|
148
|
+
'arrayNonindexKeys'
|
|
149
|
+
// 'sparseArrays'
|
|
150
|
+
].includes(referentType)
|
|
151
|
+
? 'array'
|
|
152
|
+
: (referentType === 'object'
|
|
153
|
+
? 'object'
|
|
154
|
+
/* istanbul ignore next -- Bad ref should have been caught earlier */
|
|
155
|
+
: null);
|
|
156
|
+
|
|
157
|
+
if (referentBaseType !== type) {
|
|
158
|
+
return invalidMessage(
|
|
159
|
+
'Reference must match expected reference type ' +
|
|
160
|
+
'(array or object)'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
valid: true
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
validateAll ({topRoot}) {
|
|
168
|
+
const type = `${this.type}Reference`;
|
|
169
|
+
$$e(topRoot, `div[data-type="${type}"]`).forEach((root) => {
|
|
170
|
+
Types.validate({
|
|
171
|
+
type,
|
|
172
|
+
root,
|
|
173
|
+
topRoot
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
viewUI ({value}) {
|
|
178
|
+
return ['i', {
|
|
179
|
+
dataset: {type: `${this.type}Reference`}
|
|
180
|
+
}, [`${this.type}Ref(${value})`]];
|
|
181
|
+
},
|
|
182
|
+
// Note: The `value` here must not be the object itself (the
|
|
183
|
+
// circular object/array) as the `value` usually should be,
|
|
184
|
+
// but instead the array/object path
|
|
185
|
+
editUI ({typeNamespace, value = '' /* , topRoot */}) {
|
|
186
|
+
const {type} = this;
|
|
187
|
+
return ['div', {dataset: {type: `${type}Reference`}}, [
|
|
188
|
+
['label', [
|
|
189
|
+
`JSON Pointer path to ${type} (leave blank for path to root) `,
|
|
190
|
+
['input', {
|
|
191
|
+
name: `${typeNamespace}-${type}Reference`,
|
|
192
|
+
type: 'text',
|
|
193
|
+
pattern: '^(|/.*)$',
|
|
194
|
+
value
|
|
195
|
+
}]
|
|
196
|
+
]]
|
|
197
|
+
// Todo (low): Add button to enable mode (supporting
|
|
198
|
+
// scrolling) for clicking on desired referent element
|
|
199
|
+
]];
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export default arrayReferenceType;
|