@es-joy/jsoe 0.23.0 → 0.24.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/CHANGES.md +8 -0
- package/README.md +1 -1
- package/dist/formatAndTypeChoices.d.ts +9 -2
- package/dist/formatAndTypeChoices.d.ts.map +1 -1
- package/dist/formats/arbitraryJS.d.ts +4 -0
- package/dist/formats/arbitraryJS.d.ts.map +1 -0
- package/dist/formats/schema.d.ts.map +1 -1
- package/dist/formats/structuredCloning.d.ts +1 -1
- package/dist/formats/structuredCloning.d.ts.map +1 -1
- package/dist/formats.d.ts +13 -10
- package/dist/formats.d.ts.map +1 -1
- package/dist/fundamentalTypes/functionType.d.ts +1 -0
- package/dist/fundamentalTypes/functionType.d.ts.map +1 -1
- package/dist/fundamentalTypes/promiseType.d.ts.map +1 -1
- package/dist/fundamentalTypes/stringType.d.ts.map +1 -1
- package/dist/fundamentalTypes/symbolType.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/subTypes/blobHTMLType.d.ts.map +1 -1
- package/dist/types.d.ts +33 -27
- package/dist/types.d.ts.map +1 -1
- package/dist/vendor-imports.d.ts +2 -1
- package/package.json +13 -14
- package/rollup.config.js +12 -0
- package/src/formatAndTypeChoices.js +32 -7
- package/src/formats/arbitraryJS.js +27 -0
- package/src/formats/indexedDBKey.js +1 -1
- package/src/formats/json.js +1 -1
- package/src/formats/schema.js +17 -13
- package/src/formats/structuredCloning.js +37 -8
- package/src/formats.js +15 -7
- package/src/fundamentalTypes/arrayReferenceType.js +1 -1
- package/src/fundamentalTypes/bigintObjectType.js +1 -1
- package/src/fundamentalTypes/bigintType.js +1 -1
- package/src/fundamentalTypes/functionType.js +237 -69
- package/src/fundamentalTypes/numberType.js +3 -3
- package/src/fundamentalTypes/objectReferenceType.js +1 -1
- package/src/fundamentalTypes/promiseType.js +144 -15
- package/src/fundamentalTypes/stringType.js +8 -7
- package/src/fundamentalTypes/symbolType.js +14 -6
- package/src/subTypes/blobHTMLType.js +3 -1
- package/src/types.js +31 -25
- package/src/vendor-imports.js +6 -1
- package/vendor/acorn/dist/acorn.d.mts +856 -0
- package/vendor/acorn/dist/acorn.d.ts +856 -0
- package/vendor/acorn/dist/acorn.js +6065 -0
- package/vendor/acorn/dist/acorn.mjs +6036 -0
- package/vendor/acorn/dist/bin.js +90 -0
- package/vendor/jamilih/dist/jml-es.js +9 -14
- package/vendor/typeson-registry/dist/index.js +70 -26
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Typeson, unescapeKeyPathComponent, structuredCloningThrowing,
|
|
3
|
-
resurrectable as noneditable, toStringTag
|
|
3
|
+
resurrectable as noneditable, symbol, promise, toStringTag
|
|
4
4
|
} from '../vendor-imports.js';
|
|
5
5
|
|
|
6
6
|
import {buildTypeChoices} from '../typeChoices.js';
|
|
@@ -24,7 +24,7 @@ import json from './json.js';
|
|
|
24
24
|
* method which is housed in the array type object).
|
|
25
25
|
* @typedef {(info: {
|
|
26
26
|
* propName: string,
|
|
27
|
-
* type: import('../types.js').
|
|
27
|
+
* type: import('../types.js').AvailableArbitraryType,
|
|
28
28
|
* value: import('../formats.js').StructuredCloneValue,
|
|
29
29
|
* bringIntoFocus?: boolean,
|
|
30
30
|
* setAValue?: boolean,
|
|
@@ -113,7 +113,7 @@ const encapsulateObserver = (stateObj) => {
|
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
/** @type {import('../types.js').
|
|
116
|
+
/** @type {import('../types.js').AvailableArbitraryType} */
|
|
117
117
|
let newType;
|
|
118
118
|
let newValue = value;
|
|
119
119
|
|
|
@@ -363,8 +363,8 @@ const replaceTypes = (originTypes, replacements) => {
|
|
|
363
363
|
* containing format-specific data.
|
|
364
364
|
* @param {import('../formats.js').AvailableFormat} format The current format.
|
|
365
365
|
* @param {string} state The current state.
|
|
366
|
-
* @param {import('../types.js').
|
|
367
|
-
* checked.
|
|
366
|
+
* @param {import('../types.js').AvailableArbitraryType} valType The value
|
|
367
|
+
* type being checked.
|
|
368
368
|
* @param {import('../formats.js').StructuredCloneValue} v The value being
|
|
369
369
|
* checked.
|
|
370
370
|
* @param {string} arrayOrObjectPropertyName
|
|
@@ -373,7 +373,7 @@ const replaceTypes = (originTypes, replacements) => {
|
|
|
373
373
|
* being checked.
|
|
374
374
|
* @throws {Error} May throw if data found to be invalid.
|
|
375
375
|
* @returns {{
|
|
376
|
-
* newType: import('../types.js').
|
|
376
|
+
* newType: import('../types.js').AvailableArbitraryType,
|
|
377
377
|
* schema?: import('zodex').SzType|undefined,
|
|
378
378
|
* mustBeOptional?: boolean,
|
|
379
379
|
* schemaIdx?: number
|
|
@@ -382,6 +382,7 @@ const replaceTypes = (originTypes, replacements) => {
|
|
|
382
382
|
const canonicalTypeToAvailableTypeAndSchema = (
|
|
383
383
|
types, formats, format, state, valType, v, arrayOrObjectPropertyName,
|
|
384
384
|
parentSchema, stateObj
|
|
385
|
+
// eslint-disable-next-line sonarjs/sonar-max-params -- Convenient
|
|
385
386
|
) => {
|
|
386
387
|
const frmt = formats.getAvailableFormat(format);
|
|
387
388
|
const {getTypesAndSchemasForState, convertFromTypeson, testInvalid} = frmt;
|
|
@@ -394,7 +395,7 @@ const canonicalTypeToAvailableTypeAndSchema = (
|
|
|
394
395
|
}
|
|
395
396
|
|
|
396
397
|
/**
|
|
397
|
-
* @type {import('../types.js').
|
|
398
|
+
* @type {import('../types.js').AvailableArbitraryType|undefined}
|
|
398
399
|
*/
|
|
399
400
|
let ret;
|
|
400
401
|
|
|
@@ -511,7 +512,35 @@ const structuredCloning = {
|
|
|
511
512
|
);
|
|
512
513
|
const typeson = new Typeson({
|
|
513
514
|
encapsulateObserver: encapsulateObserver(stateObj)
|
|
514
|
-
}).register(
|
|
515
|
+
}).register(
|
|
516
|
+
stateObj.format === 'arbitraryJS' ||
|
|
517
|
+
// Todo: Should have an arbitraryJS variant of schema instead
|
|
518
|
+
// to allow function/promise/symbol schemas to be cloneable but not
|
|
519
|
+
// through same schema
|
|
520
|
+
// Todo: Typeson has an issue for symbol-iterating keys; then add
|
|
521
|
+
// to regular demo and test; add tests
|
|
522
|
+
stateObj.format === 'schema'
|
|
523
|
+
? [
|
|
524
|
+
...structuredCloningFixed,
|
|
525
|
+
symbol,
|
|
526
|
+
promise,
|
|
527
|
+
{
|
|
528
|
+
function: {
|
|
529
|
+
test (x) {
|
|
530
|
+
return typeof x === 'function';
|
|
531
|
+
},
|
|
532
|
+
replace (funcType) {
|
|
533
|
+
return '(' + funcType.toString() + ')';
|
|
534
|
+
},
|
|
535
|
+
revive (o) {
|
|
536
|
+
// eslint-disable-next-line no-eval -- User opted in
|
|
537
|
+
return eval(o);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
]
|
|
542
|
+
: structuredCloningFixed
|
|
543
|
+
);
|
|
515
544
|
|
|
516
545
|
await typeson.encapsulateAsync(records, null, {
|
|
517
546
|
throwOnBadSyncType: false
|
package/src/formats.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import indexedDBKey from './formats/indexedDBKey.js';
|
|
2
2
|
import json from './formats/json.js';
|
|
3
3
|
import structuredCloning from './formats/structuredCloning.js';
|
|
4
|
+
import arbitraryJS from './formats/arbitraryJS.js';
|
|
4
5
|
import schema from './formats/schema.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -30,12 +31,13 @@ export const getTypeForFormatStateAndValue = ({format, state, value}) => {
|
|
|
30
31
|
*/
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
|
-
* @typedef {"indexedDBKey"|"json"|"structuredCloning"|
|
|
34
|
+
* @typedef {"indexedDBKey"|"json"|"structuredCloning"|
|
|
35
|
+
* "arbitraryJS"|"schema"} AvailableFormat
|
|
34
36
|
*/
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
39
|
* @typedef {{
|
|
38
|
-
* types: (import('./types.js').
|
|
40
|
+
* types: (import('./types.js').AvailableArbitraryType)[],
|
|
39
41
|
* schemaObjects: import('./formats/schema.js').ZodexSchema[]
|
|
40
42
|
* }} TypesAndSchemaObjects
|
|
41
43
|
*/
|
|
@@ -51,7 +53,9 @@ export const getTypeForFormatStateAndValue = ({format, state, value}) => {
|
|
|
51
53
|
|
|
52
54
|
/**
|
|
53
55
|
* @typedef {object} Format
|
|
54
|
-
* @property {() => (
|
|
56
|
+
* @property {() => (
|
|
57
|
+
* import('./types.js').AvailableArbitraryType
|
|
58
|
+
* )[]} types Returns list
|
|
55
59
|
* of types generally available to structured cloning. See
|
|
56
60
|
* {@link getTypesAndSchemasForState} for context-dependent method.
|
|
57
61
|
* @property {FormatIterator} iterate Traverses over data to build and return
|
|
@@ -69,14 +73,14 @@ export const getTypeForFormatStateAndValue = ({format, state, value}) => {
|
|
|
69
73
|
* newType: string, value: Date|Array<StructuredCloneValue>
|
|
70
74
|
* ) => boolean|undefined} [testInvalid]
|
|
71
75
|
* @property {(
|
|
72
|
-
* typesonType: import('./types.js').
|
|
76
|
+
* typesonType: import('./types.js').AvailableArbitraryType,
|
|
73
77
|
* types: import('./types.js').default,
|
|
74
78
|
* v?: import('./formats.js').StructuredCloneValue,
|
|
75
79
|
* arrayOrObjectPropertyName?: string,
|
|
76
80
|
* parentSchema?: [import('zodex').SzType, number|undefined]|undefined,
|
|
77
81
|
* stateObj?: import('./types.js').StateObject,
|
|
78
82
|
* ) => {
|
|
79
|
-
* type: import('./types.js').
|
|
83
|
+
* type: import('./types.js').AvailableArbitraryType|undefined
|
|
80
84
|
* schema?: import('zodex').SzType|undefined,
|
|
81
85
|
* mustBeOptional?: boolean,
|
|
82
86
|
* schemaIdx?: number
|
|
@@ -106,6 +110,9 @@ class Formats {
|
|
|
106
110
|
// case 'structuredCloning':
|
|
107
111
|
// formatValue = structuredCloning;
|
|
108
112
|
// break;
|
|
113
|
+
// case 'arbitraryJS':
|
|
114
|
+
// formatValue = arbitraryJS;
|
|
115
|
+
// break;
|
|
109
116
|
// default:
|
|
110
117
|
// throw new Error('Unknown format');
|
|
111
118
|
// }
|
|
@@ -117,8 +124,9 @@ class Formats {
|
|
|
117
124
|
this.availableFormats = /** @type {{[key: string]: Format}} */ ({
|
|
118
125
|
indexedDBKey,
|
|
119
126
|
json,
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
structuredCloning,
|
|
128
|
+
arbitraryJS,
|
|
129
|
+
schema
|
|
122
130
|
});
|
|
123
131
|
}
|
|
124
132
|
|
|
@@ -1,47 +1,233 @@
|
|
|
1
|
-
import {$e} from '../utils/templateUtils.js';
|
|
1
|
+
import {$e, $$e} from '../utils/templateUtils.js';
|
|
2
|
+
import {jml, parseAcorn} from '../vendor-imports.js';
|
|
2
3
|
import {copyObject} from '../utils/objects.js';
|
|
3
4
|
|
|
5
|
+
const observerMap = new WeakMap();
|
|
6
|
+
|
|
7
|
+
// See https://github.com/tc39/proposal-regexp-unicode-property-escapes#other-examples
|
|
8
|
+
const idRegex =
|
|
9
|
+
String.raw`^(?:[$_\p{ID_Start}])(?:[$_\u200C\u200D\p{ID_Continue}])*$`;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {{
|
|
13
|
+
* root: HTMLDivElement,
|
|
14
|
+
* specificSchemaObject?: import('../formats/schema.js').ZodexSchema
|
|
15
|
+
* textareas: HTMLTextAreaElement[]
|
|
16
|
+
* textareaBody: HTMLTextAreaElement
|
|
17
|
+
* }} cfg
|
|
18
|
+
*/
|
|
19
|
+
const setTooltips = ({root, specificSchemaObject, textareas, textareaBody}) => {
|
|
20
|
+
// Todo: For these `JSON.stringify` calls, might instead use
|
|
21
|
+
// zodex->(zod)->zod-to-json-schema instead
|
|
22
|
+
textareaBody.title = `Return type:\n\n${JSON.stringify(
|
|
23
|
+
/** @type {import('zodex').SzFunction<any, any>} */
|
|
24
|
+
(specificSchemaObject).returns,
|
|
25
|
+
null,
|
|
26
|
+
2
|
|
27
|
+
)}`;
|
|
28
|
+
// eslint-disable-next-line prefer-destructuring -- TS
|
|
29
|
+
const args = /** @type {import('zodex').SzFunction<any, any>} */
|
|
30
|
+
(specificSchemaObject).args;
|
|
31
|
+
textareas.forEach((textarea, idx) => {
|
|
32
|
+
textarea.title = JSON.stringify(
|
|
33
|
+
args.items[idx] ?? args.rest,
|
|
34
|
+
null,
|
|
35
|
+
2
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (observerMap.has(root)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {Node} node
|
|
45
|
+
*/
|
|
46
|
+
const addTitles = (node) => {
|
|
47
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const textarea = /** @type {Element} */ (
|
|
51
|
+
node
|
|
52
|
+
).querySelector('textarea');
|
|
53
|
+
if (textarea) {
|
|
54
|
+
const textareas = /** @type {HTMLTextAreaElement[]} */ (
|
|
55
|
+
$$e(root, 'textarea')
|
|
56
|
+
).slice(0, -1);
|
|
57
|
+
|
|
58
|
+
// Redo them all, as order may have changed
|
|
59
|
+
textareas.forEach((textarea, idx) => {
|
|
60
|
+
textarea.title = JSON.stringify(
|
|
61
|
+
args.items[idx] ?? args.rest,
|
|
62
|
+
null,
|
|
63
|
+
2
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const observer = new MutationObserver((mutationList) => {
|
|
70
|
+
for (const mutation of mutationList) {
|
|
71
|
+
if (mutation.type === 'childList') {
|
|
72
|
+
for (const node of mutation.removedNodes) {
|
|
73
|
+
addTitles(node);
|
|
74
|
+
}
|
|
75
|
+
for (const node of mutation.addedNodes) {
|
|
76
|
+
addTitles(node);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
observer.observe(root, {
|
|
82
|
+
attributes: false, childList: true, subtree: true
|
|
83
|
+
});
|
|
84
|
+
observerMap.set(root, observer);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @typedef {Function} ArbitraryFunction
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {ArbitraryFunction} func
|
|
93
|
+
*/
|
|
94
|
+
const getArgsAndBodyOfFunction = (func) => {
|
|
95
|
+
const funcStr = String(func);
|
|
96
|
+
const funcStrFull = String(`(${
|
|
97
|
+
funcStr.trimStart().startsWith('function')
|
|
98
|
+
? funcStr
|
|
99
|
+
: `function ${funcStr}`
|
|
100
|
+
})`);
|
|
101
|
+
const body = funcStrFull.slice(
|
|
102
|
+
funcStrFull.indexOf('{') + 1, funcStrFull.lastIndexOf('}')
|
|
103
|
+
).trim();
|
|
104
|
+
|
|
105
|
+
const ast = /** @type {import('acorn').ExpressionStatement} */ (
|
|
106
|
+
parseAcorn(funcStrFull, {
|
|
107
|
+
ecmaVersion: 'latest',
|
|
108
|
+
sourceType: 'module'
|
|
109
|
+
}).body[0]
|
|
110
|
+
).expression;
|
|
111
|
+
|
|
112
|
+
const args = /** @type {import('acorn').Identifier[]} */ (
|
|
113
|
+
/** @type {import('acorn').FunctionExpression} */ (
|
|
114
|
+
ast
|
|
115
|
+
).params
|
|
116
|
+
).map(({name}) => name.trim());
|
|
117
|
+
|
|
118
|
+
return {args, body};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {{
|
|
123
|
+
* root: HTMLDivElement,
|
|
124
|
+
* value: import('../types.js').StructuredCloneValue
|
|
125
|
+
* specificSchemaObject?: import('../formats/schema.js').ZodexSchema
|
|
126
|
+
* }} cfg
|
|
127
|
+
*/
|
|
128
|
+
const setValueAndTooltips = ({root, value, specificSchemaObject}) => {
|
|
129
|
+
const {args, body} = getArgsAndBodyOfFunction(value);
|
|
130
|
+
|
|
131
|
+
// Wait for textareas to be available
|
|
132
|
+
setTimeout(() => {
|
|
133
|
+
let textareas = /** @type {HTMLTextAreaElement[]} */ (
|
|
134
|
+
$$e(root, 'textarea[name$="-string"]')
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const textareaBody = /** @type {HTMLTextAreaElement} */ (textareas.pop());
|
|
138
|
+
|
|
139
|
+
args.forEach((_arg, idx) => {
|
|
140
|
+
if (!textareas[idx]) {
|
|
141
|
+
$e(root, '.addArrayElement')?.click();
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
textareas = /** @type {HTMLTextAreaElement[]} */ (
|
|
147
|
+
$$e(root, 'textarea[name$="-string"]').slice(0, -1)
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
if (value) {
|
|
151
|
+
args.forEach((arg, idx) => {
|
|
152
|
+
textareas[idx].value = arg;
|
|
153
|
+
});
|
|
154
|
+
textareaBody.value = body;
|
|
155
|
+
}
|
|
156
|
+
if (specificSchemaObject) {
|
|
157
|
+
setTooltips({root, specificSchemaObject, textareas, textareaBody});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
|
|
4
163
|
/**
|
|
5
164
|
* @type {import('../types.js').TypeObject}
|
|
6
165
|
*/
|
|
7
166
|
const functionType = {
|
|
8
167
|
option: ['function'],
|
|
9
|
-
|
|
10
|
-
|
|
168
|
+
regexEndings: ['}'],
|
|
169
|
+
stringRegexBegin: /^function\((?<args>[^)]*?)\) \{(?<returns>.*)\}$/u,
|
|
170
|
+
stringRegexEnd: /^\}/u,
|
|
171
|
+
array: true,
|
|
172
|
+
|
|
11
173
|
valueMatch (x) {
|
|
12
174
|
return typeof x === 'function';
|
|
13
175
|
},
|
|
14
|
-
toValue (s) {
|
|
15
|
-
|
|
176
|
+
toValue (s, rootInfo) {
|
|
177
|
+
const {groups: {
|
|
178
|
+
args, returns
|
|
179
|
+
/* istanbul ignore next -- Should always be found */
|
|
180
|
+
} = {}} = /** @type {RegExpMatchArray} */ (
|
|
181
|
+
/** @type {import('../types.js').RootInfo} */ (rootInfo).match
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// Todo: Either re-use proper acorn parsing here for the `split` or
|
|
185
|
+
// get rid of acorn
|
|
186
|
+
|
|
187
|
+
// eslint-disable-next-line no-new-func -- Needed
|
|
188
|
+
return {value: new Function(...args.split(/\s*,\s*/u), returns)};
|
|
16
189
|
},
|
|
17
190
|
getInput ({root}) {
|
|
18
|
-
return /** @type {HTMLTextAreaElement} */ ($e(root, '
|
|
191
|
+
return /** @type {HTMLTextAreaElement} */ ($e(root, 'textarea'));
|
|
19
192
|
},
|
|
20
193
|
setValue ({root, value}) {
|
|
21
|
-
|
|
194
|
+
setValueAndTooltips({root, value});
|
|
22
195
|
},
|
|
23
196
|
getValue ({root}) {
|
|
24
|
-
|
|
197
|
+
const textareas = /** @type {HTMLTextAreaElement[]} */ (
|
|
198
|
+
$$e(root, 'textarea')
|
|
199
|
+
);
|
|
200
|
+
const textareaBody = /** @type {HTMLTextAreaElement} */ (textareas.pop());
|
|
201
|
+
// eslint-disable-next-line no-new-func -- Needed
|
|
202
|
+
return new Function(
|
|
203
|
+
...textareas.map(({value}) => value.trim()),
|
|
204
|
+
textareaBody.value.trim()
|
|
205
|
+
);
|
|
25
206
|
},
|
|
26
207
|
viewUI ({value, specificSchemaObject}) {
|
|
208
|
+
const {args, body} = getArgsAndBodyOfFunction(value);
|
|
27
209
|
return ['span', {
|
|
28
210
|
dataset: {type: 'function'},
|
|
29
211
|
title: specificSchemaObject?.description ?? '(a function)'
|
|
30
|
-
}, [
|
|
212
|
+
}, [
|
|
213
|
+
['b', ['Args']],
|
|
214
|
+
' ',
|
|
215
|
+
`(${args.join(', ')})`,
|
|
216
|
+
['br'],
|
|
217
|
+
['b', ['Body']],
|
|
218
|
+
' ',
|
|
219
|
+
body
|
|
220
|
+
]];
|
|
31
221
|
},
|
|
32
222
|
editUI ({
|
|
33
|
-
|
|
223
|
+
type, buildTypeChoices, specificSchemaObject,
|
|
34
224
|
topRoot, // schemaContent,
|
|
35
|
-
typeNamespace
|
|
225
|
+
typeNamespace, value
|
|
36
226
|
}) {
|
|
37
|
-
// Todo: Support `getValue`; add to demo with tests; could also add to
|
|
38
|
-
// use with `Promise` so that could also build a meaningful
|
|
39
|
-
// implementation; use schema to inform user of types of args,
|
|
40
|
-
// but remember we are not reimplementing the function schema to
|
|
41
|
-
// ask for argument types, etc.
|
|
42
|
-
|
|
43
227
|
// We want to allow overriding its descriptions
|
|
44
|
-
const specificSchemaObj =
|
|
228
|
+
const specificSchemaObj = specificSchemaObject
|
|
229
|
+
? copyObject(specificSchemaObject)
|
|
230
|
+
: undefined;
|
|
45
231
|
const argsTuple = /** @type {import('zodex').SzFunction<any, any>} */ (
|
|
46
232
|
specificSchemaObj
|
|
47
233
|
)?.args ?? {type: 'tuple', items: [], rest: {type: 'any'}};
|
|
@@ -51,54 +237,31 @@ const functionType = {
|
|
|
51
237
|
argsTuple.rest.description = 'Argument';
|
|
52
238
|
}
|
|
53
239
|
|
|
54
|
-
const size = argsTuple.items.length
|
|
240
|
+
const size = argsTuple.items.length;
|
|
55
241
|
const args = /** @type {import('zodex').SzType} */ (
|
|
56
242
|
{
|
|
57
243
|
type: 'set',
|
|
58
244
|
minSize: size,
|
|
59
|
-
maxSize: size,
|
|
245
|
+
maxSize: argsTuple.rest ? undefined : size,
|
|
60
246
|
value: {
|
|
61
247
|
type: 'string',
|
|
62
|
-
|
|
63
|
-
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
64
|
-
regex: String.raw`^(?:[$_\p{ID_Start}])(?:[$_\u200C\u200D\p{ID_Continue}])*$`,
|
|
248
|
+
regex: idRegex,
|
|
65
249
|
flags: 'v'
|
|
66
250
|
}
|
|
67
251
|
}
|
|
68
252
|
);
|
|
69
253
|
|
|
70
|
-
|
|
254
|
+
const div = jml('div', {dataset: {type: 'function'}}, [
|
|
71
255
|
['b', ['Arguments']],
|
|
72
256
|
['br'],
|
|
73
257
|
|
|
74
|
-
// This was working to allow choice of specific function argument types,
|
|
75
|
-
// but we want function argument names to build a real function; the
|
|
76
|
-
// specific attached schema should already specify function argument
|
|
77
|
-
// types.
|
|
78
|
-
// ...(/** @type {import('../typeChoices.js').BuildTypeChoices} */ (
|
|
79
|
-
// buildTypeChoices
|
|
80
|
-
// )({
|
|
81
|
-
// // resultType,
|
|
82
|
-
// // eslint-disable-next-line object-shorthand -- TS
|
|
83
|
-
// topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
84
|
-
// // eslint-disable-next-line object-shorthand -- TS
|
|
85
|
-
// format:
|
|
86
|
-
// /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
87
|
-
// schemaOriginal: schemaContent,
|
|
88
|
-
// schemaContent: argsTuple,
|
|
89
|
-
// state: type,
|
|
90
|
-
// // itemIndex,
|
|
91
|
-
// typeNamespace
|
|
92
|
-
// }).domArray),
|
|
93
|
-
|
|
94
258
|
...(/** @type {import('../typeChoices.js').BuildTypeChoices} */ (
|
|
95
259
|
buildTypeChoices
|
|
96
260
|
)({
|
|
97
261
|
// resultType,
|
|
98
262
|
// eslint-disable-next-line object-shorthand -- TS
|
|
99
263
|
topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
100
|
-
//
|
|
101
|
-
format: /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
264
|
+
format: 'schema', // We're always supplying a schema
|
|
102
265
|
// schemaOriginal: schemaContent,
|
|
103
266
|
schemaContent: args,
|
|
104
267
|
state: type,
|
|
@@ -114,36 +277,41 @@ const functionType = {
|
|
|
114
277
|
// resultType,
|
|
115
278
|
// eslint-disable-next-line object-shorthand -- TS
|
|
116
279
|
topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
117
|
-
//
|
|
118
|
-
format: /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
280
|
+
format: 'schema', // We're always supplying a schema
|
|
119
281
|
// schemaOriginal: schemaContent,
|
|
120
282
|
schemaContent: {type: 'string'},
|
|
121
283
|
state: type,
|
|
122
284
|
// itemIndex,
|
|
123
285
|
typeNamespace
|
|
124
286
|
}).domArray)
|
|
287
|
+
]);
|
|
125
288
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
289
|
+
if (value) {
|
|
290
|
+
setTimeout(() => {
|
|
291
|
+
setValueAndTooltips({
|
|
292
|
+
root: div,
|
|
293
|
+
value,
|
|
294
|
+
specificSchemaObject
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
} else if (specificSchemaObject) {
|
|
298
|
+
setTimeout(() => {
|
|
299
|
+
setTimeout(() => {
|
|
300
|
+
// Should have some empty textareas by now
|
|
301
|
+
const textareas = /** @type {HTMLTextAreaElement[]} */ (
|
|
302
|
+
$$e(div, 'textarea')
|
|
303
|
+
);
|
|
304
|
+
const textareaBody = /** @type {HTMLTextAreaElement} */ (
|
|
305
|
+
textareas.pop()
|
|
306
|
+
);
|
|
307
|
+
setTooltips({
|
|
308
|
+
root: div, specificSchemaObject, textareas, textareaBody
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return [div];
|
|
147
315
|
}
|
|
148
316
|
};
|
|
149
317
|
|
|
@@ -9,11 +9,11 @@ const numberType = {
|
|
|
9
9
|
'^' + // No leading content.
|
|
10
10
|
'[-+]?' + // Optional sign.
|
|
11
11
|
// Optionally 0-30 decimal digits of mantissa.
|
|
12
|
-
String.raw`(
|
|
12
|
+
String.raw`(?:\d{0,30}\.)?` +
|
|
13
13
|
// 1-30 decimal digits of integer or fraction.
|
|
14
|
-
|
|
14
|
+
String.raw`\d{1,30}` +
|
|
15
15
|
// Optional exponent 0-29 for scientific notation.
|
|
16
|
-
|
|
16
|
+
String.raw`(?:[Ee][-+]?[1-2]?\d)?` +
|
|
17
17
|
'$', // No trailing content.
|
|
18
18
|
'u'
|
|
19
19
|
),
|
|
@@ -6,7 +6,7 @@ import arrayReferenceType from './arrayReferenceType.js';
|
|
|
6
6
|
const objectReferenceType = {
|
|
7
7
|
option: ['Object reference'],
|
|
8
8
|
type: 'object',
|
|
9
|
-
stringRegex: /^objectRef\((
|
|
9
|
+
stringRegex: /^objectRef\((?:\/[^)]*|)\)$/u,
|
|
10
10
|
toValue (...args) {
|
|
11
11
|
return /** @type {import('../types.js').ToValue} */ (
|
|
12
12
|
arrayReferenceType.toValue
|