@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,115 @@
|
|
|
1
|
+
/* eslint-disable promise/avoid-new */
|
|
2
|
+
import {jml, nbsp} from '../../node_modules/jamilih/dist/jml-es.js';
|
|
3
|
+
import {$e} from './templateUtils.js';
|
|
4
|
+
|
|
5
|
+
const localeStrings = {
|
|
6
|
+
submit: 'Submit',
|
|
7
|
+
cancel: 'Cancel',
|
|
8
|
+
ok: 'Ok'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Todo: i18nize
|
|
12
|
+
const dialogs = {
|
|
13
|
+
setLocale (locale = {}) {
|
|
14
|
+
this.localeStrings = {...localeStrings, ...locale};
|
|
15
|
+
},
|
|
16
|
+
makeDialog ({atts = {}, children = [], close, remove = true} = {}) {
|
|
17
|
+
if (close) {
|
|
18
|
+
if (!atts.$on) {
|
|
19
|
+
atts.$on = {};
|
|
20
|
+
}
|
|
21
|
+
if (!atts.$on.close) {
|
|
22
|
+
atts.$on.close = close;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const dialog = jml('dialog', atts, children, document.body);
|
|
26
|
+
dialog.showModal();
|
|
27
|
+
if (remove) {
|
|
28
|
+
dialog.addEventListener('close', () => {
|
|
29
|
+
dialog.remove();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return dialog;
|
|
33
|
+
},
|
|
34
|
+
makeSubmitDialog ({submit, submitClass = 'submit', ...args}) {
|
|
35
|
+
const dialog = this.makeCancelDialog(args);
|
|
36
|
+
$e(dialog, `button.${args.cancelClass || 'cancel'}`).before(
|
|
37
|
+
jml('button', {
|
|
38
|
+
class: submitClass,
|
|
39
|
+
$on: {
|
|
40
|
+
click (e) {
|
|
41
|
+
submit.call(this, {e, dialog});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}, [this.localeStrings.submit]),
|
|
45
|
+
nbsp.repeat(2)
|
|
46
|
+
);
|
|
47
|
+
return dialog;
|
|
48
|
+
},
|
|
49
|
+
makeCancelDialog ({
|
|
50
|
+
submit, // Don't pass this on to `args` if present
|
|
51
|
+
cancel,
|
|
52
|
+
cancelClass = 'cancel', submitClass = 'submit',
|
|
53
|
+
...args
|
|
54
|
+
}) {
|
|
55
|
+
const dialog = this.makeDialog(args);
|
|
56
|
+
jml('div', {class: submitClass}, [
|
|
57
|
+
['br'], ['br'],
|
|
58
|
+
['button', {class: cancelClass, $on: {
|
|
59
|
+
click (e) {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
if (cancel) {
|
|
62
|
+
if (cancel.call(this, {e, dialog}) === false) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
dialog.close();
|
|
67
|
+
}
|
|
68
|
+
}}, [this.localeStrings.cancel]]
|
|
69
|
+
], dialog);
|
|
70
|
+
return dialog;
|
|
71
|
+
},
|
|
72
|
+
alert (message) {
|
|
73
|
+
message = typeof message === 'string' ? {message} : message;
|
|
74
|
+
const {submitClass = 'submit'} = message;
|
|
75
|
+
({message} = message);
|
|
76
|
+
return new Promise((resolve, _reject) => {
|
|
77
|
+
const dialog = jml('dialog', [
|
|
78
|
+
message,
|
|
79
|
+
['br'], ['br'],
|
|
80
|
+
['div', {class: submitClass}, [
|
|
81
|
+
['button', {$on: {click () {
|
|
82
|
+
dialog.close();
|
|
83
|
+
resolve();
|
|
84
|
+
}}}, [this.localeStrings.ok]]
|
|
85
|
+
]]
|
|
86
|
+
], document.body);
|
|
87
|
+
dialog.showModal();
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
confirm ({atts = {}, message, submitClass = 'submit'}) {
|
|
91
|
+
({message} = typeof message === 'string' ? {message} : message);
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
const dialog = jml('dialog', atts, [
|
|
94
|
+
message,
|
|
95
|
+
['br'], ['br'],
|
|
96
|
+
['div', {class: submitClass}, [
|
|
97
|
+
['button', {$on: {click () {
|
|
98
|
+
dialog.close();
|
|
99
|
+
resolve();
|
|
100
|
+
}}}, [this.localeStrings.ok]],
|
|
101
|
+
nbsp.repeat(2),
|
|
102
|
+
['button', {$on: {click () {
|
|
103
|
+
dialog.close();
|
|
104
|
+
reject(new Error('cancelled'));
|
|
105
|
+
}}}, [this.localeStrings.cancel]]
|
|
106
|
+
]]
|
|
107
|
+
], document.body);
|
|
108
|
+
dialog.showModal();
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
dialogs.setLocale();
|
|
114
|
+
|
|
115
|
+
export default dialogs;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {...string} args
|
|
3
|
+
* @returns {string}
|
|
4
|
+
*/
|
|
5
|
+
const makeJSONPointer = (...args) => {
|
|
6
|
+
return '#/' + args.map((path) => {
|
|
7
|
+
return escapeJSONPointer(path);
|
|
8
|
+
}).join('/');
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} path
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
const escapeJSONPointer = (path) => {
|
|
16
|
+
return path.replace(/~/gu, '~0').replace(/\//gu, '~1');
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} pathPart
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
const unescapeJSONPointerPart = (pathPart) => {
|
|
24
|
+
return pathPart.replace(/~([01])/gu, (_n0, n1) => {
|
|
25
|
+
if (n1 === '0') {
|
|
26
|
+
return '~';
|
|
27
|
+
}
|
|
28
|
+
return '/';
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} path
|
|
34
|
+
* @returns {string[]}
|
|
35
|
+
*/
|
|
36
|
+
const getJSONPointerParts = (path) => {
|
|
37
|
+
return path.split('/').slice(1).map(
|
|
38
|
+
(pathPart) => unescapeJSONPointerPart(pathPart)
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {ArbitraryObject} obj
|
|
44
|
+
* @param {string} pathPart
|
|
45
|
+
* @returns {ArbitraryObject|string}
|
|
46
|
+
*/
|
|
47
|
+
const reduceJSONPointerParts = (obj, pathPart) => {
|
|
48
|
+
if (!(pathPart in obj)) {
|
|
49
|
+
throw new TypeError('Path part not found in object');
|
|
50
|
+
}
|
|
51
|
+
obj = obj[pathPart];
|
|
52
|
+
return obj;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {object} cfg
|
|
57
|
+
* @param {string} cfg.path
|
|
58
|
+
* @param {ArbitraryObject} cfg.obj
|
|
59
|
+
* @returns {string|ArbitraryObject}
|
|
60
|
+
*/
|
|
61
|
+
const resolveJSONPointer = ({path, obj}) => {
|
|
62
|
+
return getJSONPointerParts(path).reduce(
|
|
63
|
+
(obj, pathPart) => reduceJSONPointerParts(obj, pathPart),
|
|
64
|
+
obj
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {string} path
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
const typesonPathToJSONPointer = (path) => {
|
|
73
|
+
if (!path) {
|
|
74
|
+
return path;
|
|
75
|
+
}
|
|
76
|
+
return '/' + path.split('.').map((keyPathComponent) => {
|
|
77
|
+
// Keep `~0` (representing tilde) escaped as same sequence in
|
|
78
|
+
// JSONPointer (that's why we don't just use
|
|
79
|
+
// Typeson's `unescapeKeyPathComponent` + `escapeJSONPointer` here)
|
|
80
|
+
return keyPathComponent.replace(/~1/gu, '.').replace(/\//gu, '~1');
|
|
81
|
+
}).join('/');
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
makeJSONPointer, escapeJSONPointer,
|
|
86
|
+
unescapeJSONPointerPart, getJSONPointerParts, reduceJSONPointerParts,
|
|
87
|
+
resolveJSONPointer,
|
|
88
|
+
typesonPathToJSONPointer
|
|
89
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
|
|
2
|
+
const nbsp = '\u00A0';
|
|
3
|
+
const upArrow = '\u2191';
|
|
4
|
+
const downArrow = '\u2193';
|
|
5
|
+
const U = {nbsp, upArrow, downArrow};
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} sel
|
|
9
|
+
* @returns {Element}
|
|
10
|
+
*/
|
|
11
|
+
const $ = (sel) => document.querySelector(sel);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} sel
|
|
15
|
+
* @returns {Element[]}
|
|
16
|
+
*/
|
|
17
|
+
const $$ = (sel) => [...document.querySelectorAll(sel)];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Element|string} el
|
|
21
|
+
* @param {string} descendentsSel
|
|
22
|
+
* @returns {Element}
|
|
23
|
+
*/
|
|
24
|
+
const $e = (el, descendentsSel) => {
|
|
25
|
+
el = typeof el === 'string' ? $(el) : el;
|
|
26
|
+
return el.querySelector(descendentsSel);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {Element|string} el
|
|
31
|
+
* @param {string} descendentsSel
|
|
32
|
+
* @returns {Element[]}
|
|
33
|
+
*/
|
|
34
|
+
const $$e = (el, descendentsSel) => {
|
|
35
|
+
el = typeof el === 'string' ? $(el) : el;
|
|
36
|
+
return [...el.querySelectorAll(descendentsSel)];
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {Node} node
|
|
41
|
+
* @returns {void}
|
|
42
|
+
*/
|
|
43
|
+
const removeChildren = (node) => {
|
|
44
|
+
node = typeof node === 'string' ? $(node) : node;
|
|
45
|
+
while (node.hasChildNodes()) {
|
|
46
|
+
node.lastChild.remove();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {Element|string} sel
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
const removeIfExists = (sel) => {
|
|
55
|
+
const el = typeof sel === 'string' ? $(sel) : sel;
|
|
56
|
+
if (el) {
|
|
57
|
+
el.remove();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {Element} el
|
|
63
|
+
* @param {string|string[]} selectors
|
|
64
|
+
* @returns {Element[]}
|
|
65
|
+
*/
|
|
66
|
+
const filterChildElements = (el, selectors) => {
|
|
67
|
+
/**
|
|
68
|
+
* @param {Element} el
|
|
69
|
+
* @param {string} sel
|
|
70
|
+
* @returns {Element[]}
|
|
71
|
+
*/
|
|
72
|
+
const getMatchingChildrenForElement = (el, sel) => {
|
|
73
|
+
const childElements = el.children;
|
|
74
|
+
const matchingChildElements = [...childElements].filter((el) => {
|
|
75
|
+
return el.matches(sel);
|
|
76
|
+
});
|
|
77
|
+
return matchingChildElements;
|
|
78
|
+
};
|
|
79
|
+
el = typeof el === 'string' ? $(el) : el;
|
|
80
|
+
let filtered = [el];
|
|
81
|
+
selectors = Array.isArray(selectors) ? selectors : [selectors];
|
|
82
|
+
selectors.forEach((sel) => {
|
|
83
|
+
filtered = filtered.reduce((els, childElement) => {
|
|
84
|
+
els.push(...getMatchingChildrenForElement(childElement, sel));
|
|
85
|
+
return els;
|
|
86
|
+
}, []);
|
|
87
|
+
});
|
|
88
|
+
return filtered;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {string} s
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
95
|
+
const initialCaps = (s) => {
|
|
96
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const DOM = {removeChildren, removeIfExists, filterChildElements, initialCaps};
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
U,
|
|
103
|
+
$, $$,
|
|
104
|
+
$e, $$e,
|
|
105
|
+
DOM
|
|
106
|
+
};
|