@es-joy/jsoe 0.2.0 → 0.4.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.
Files changed (192) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.cjs +2 -0
  3. package/.ncurc.cjs +9 -0
  4. package/CHANGES.md +9 -0
  5. package/README.md +2 -2
  6. package/demo/index.html +8 -0
  7. package/demo/index.js +1 -1
  8. package/dist/formatAndTypeChoices.d.ts +56 -0
  9. package/dist/formatAndTypeChoices.d.ts.map +1 -0
  10. package/dist/formats/indexedDBKey.d.ts +4 -0
  11. package/dist/formats/indexedDBKey.d.ts.map +1 -0
  12. package/dist/formats/json.d.ts +4 -0
  13. package/dist/formats/json.d.ts.map +1 -0
  14. package/dist/formats/schemaAndArbitrary.d.ts +6 -0
  15. package/dist/formats/schemaAndArbitrary.d.ts.map +1 -0
  16. package/dist/formats/schemaOnly.d.ts +6 -0
  17. package/dist/formats/schemaOnly.d.ts.map +1 -0
  18. package/dist/formats/structuredCloning.d.ts +20 -0
  19. package/dist/formats/structuredCloning.d.ts.map +1 -0
  20. package/dist/formats.d.ts +26 -0
  21. package/dist/formats.d.ts.map +1 -0
  22. package/dist/fundamentalTypes/BooleanObjectType.d.ts +8 -0
  23. package/dist/fundamentalTypes/BooleanObjectType.d.ts.map +1 -0
  24. package/dist/fundamentalTypes/NumberObjectType.d.ts +6 -0
  25. package/dist/fundamentalTypes/NumberObjectType.d.ts.map +1 -0
  26. package/dist/fundamentalTypes/StringObjectType.d.ts +6 -0
  27. package/dist/fundamentalTypes/StringObjectType.d.ts.map +1 -0
  28. package/dist/fundamentalTypes/arrayReferenceType.d.ts +8 -0
  29. package/dist/fundamentalTypes/arrayReferenceType.d.ts.map +1 -0
  30. package/dist/fundamentalTypes/arrayType.d.ts +60 -0
  31. package/dist/fundamentalTypes/arrayType.d.ts.map +1 -0
  32. package/dist/fundamentalTypes/bigintType.d.ts +6 -0
  33. package/dist/fundamentalTypes/bigintType.d.ts.map +1 -0
  34. package/dist/fundamentalTypes/dateType.d.ts +26 -0
  35. package/dist/fundamentalTypes/dateType.d.ts.map +1 -0
  36. package/dist/fundamentalTypes/nullType.d.ts +6 -0
  37. package/dist/fundamentalTypes/nullType.d.ts.map +1 -0
  38. package/dist/fundamentalTypes/numberType.d.ts +6 -0
  39. package/dist/fundamentalTypes/numberType.d.ts.map +1 -0
  40. package/dist/fundamentalTypes/objectReferenceType.d.ts +8 -0
  41. package/dist/fundamentalTypes/objectReferenceType.d.ts.map +1 -0
  42. package/dist/fundamentalTypes/objectType.d.ts +6 -0
  43. package/dist/fundamentalTypes/objectType.d.ts.map +1 -0
  44. package/dist/fundamentalTypes/regexpType.d.ts +8 -0
  45. package/dist/fundamentalTypes/regexpType.d.ts.map +1 -0
  46. package/dist/fundamentalTypes/sparseUndefinedType.d.ts +6 -0
  47. package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -0
  48. package/dist/fundamentalTypes/stringType.d.ts +6 -0
  49. package/dist/fundamentalTypes/stringType.d.ts.map +1 -0
  50. package/dist/fundamentalTypes/undefinedType.d.ts +6 -0
  51. package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -0
  52. package/dist/index.d.ts +5 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/src/deepEqual.d.ts +3 -0
  55. package/dist/src/deepEqual.d.ts.map +1 -0
  56. package/dist/src/formatAndTypeChoices.d.ts +47 -0
  57. package/dist/src/formatAndTypeChoices.d.ts.map +1 -0
  58. package/dist/src/formats/indexedDBKey.d.ts +9 -0
  59. package/dist/src/formats/indexedDBKey.d.ts.map +1 -0
  60. package/dist/src/formats/json.d.ts +9 -0
  61. package/dist/src/formats/json.d.ts.map +1 -0
  62. package/dist/src/formats/schemaAndArbitrary.d.ts +6 -0
  63. package/dist/src/formats/schemaAndArbitrary.d.ts.map +1 -0
  64. package/dist/src/formats/schemaOnly.d.ts +6 -0
  65. package/dist/src/formats/schemaOnly.d.ts.map +1 -0
  66. package/dist/src/formats/structuredCloning.d.ts +15 -0
  67. package/dist/src/formats/structuredCloning.d.ts.map +1 -0
  68. package/dist/src/formats.d.ts +18 -0
  69. package/dist/src/formats.d.ts.map +1 -0
  70. package/dist/src/fundamentalTypes/BooleanObjectType.d.ts +6 -0
  71. package/dist/src/fundamentalTypes/BooleanObjectType.d.ts.map +1 -0
  72. package/dist/src/fundamentalTypes/NumberObjectType.d.ts +6 -0
  73. package/dist/src/fundamentalTypes/NumberObjectType.d.ts.map +1 -0
  74. package/dist/src/fundamentalTypes/StringObjectType.d.ts +6 -0
  75. package/dist/src/fundamentalTypes/StringObjectType.d.ts.map +1 -0
  76. package/dist/src/fundamentalTypes/arrayReferenceType.d.ts +6 -0
  77. package/dist/src/fundamentalTypes/arrayReferenceType.d.ts.map +1 -0
  78. package/dist/src/fundamentalTypes/arrayType.d.ts +6 -0
  79. package/dist/src/fundamentalTypes/arrayType.d.ts.map +1 -0
  80. package/dist/src/fundamentalTypes/bigintType.d.ts +6 -0
  81. package/dist/src/fundamentalTypes/bigintType.d.ts.map +1 -0
  82. package/dist/src/fundamentalTypes/dateType.d.ts +6 -0
  83. package/dist/src/fundamentalTypes/dateType.d.ts.map +1 -0
  84. package/dist/src/fundamentalTypes/nullType.d.ts +6 -0
  85. package/dist/src/fundamentalTypes/nullType.d.ts.map +1 -0
  86. package/dist/src/fundamentalTypes/numberType.d.ts +6 -0
  87. package/dist/src/fundamentalTypes/numberType.d.ts.map +1 -0
  88. package/dist/src/fundamentalTypes/objectReferenceType.d.ts +6 -0
  89. package/dist/src/fundamentalTypes/objectReferenceType.d.ts.map +1 -0
  90. package/dist/src/fundamentalTypes/objectType.d.ts +6 -0
  91. package/dist/src/fundamentalTypes/objectType.d.ts.map +1 -0
  92. package/dist/src/fundamentalTypes/regexpType.d.ts +6 -0
  93. package/dist/src/fundamentalTypes/regexpType.d.ts.map +1 -0
  94. package/dist/src/fundamentalTypes/sparseUndefinedType.d.ts +6 -0
  95. package/dist/src/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -0
  96. package/dist/src/fundamentalTypes/stringType.d.ts +6 -0
  97. package/dist/src/fundamentalTypes/stringType.d.ts.map +1 -0
  98. package/dist/src/fundamentalTypes/undefinedType.d.ts +6 -0
  99. package/dist/src/fundamentalTypes/undefinedType.d.ts.map +1 -0
  100. package/dist/src/index.d.ts +5 -0
  101. package/dist/src/index.d.ts.map +1 -0
  102. package/dist/src/subTypes/blobHTMLType.d.ts +26 -0
  103. package/dist/src/subTypes/blobHTMLType.d.ts.map +1 -0
  104. package/dist/src/subTypes/falseType.d.ts +6 -0
  105. package/dist/src/subTypes/falseType.d.ts.map +1 -0
  106. package/dist/src/subTypes/trueType.d.ts +6 -0
  107. package/dist/src/subTypes/trueType.d.ts.map +1 -0
  108. package/dist/src/superTypes/SpecialNumberSuperType.d.ts +11 -0
  109. package/dist/src/superTypes/SpecialNumberSuperType.d.ts.map +1 -0
  110. package/dist/src/superTypes/SpecialRealNumberSuperType.d.ts +6 -0
  111. package/dist/src/superTypes/SpecialRealNumberSuperType.d.ts.map +1 -0
  112. package/dist/src/typeChoices.d.ts +30 -0
  113. package/dist/src/typeChoices.d.ts.map +1 -0
  114. package/dist/src/types.d.ts +333 -0
  115. package/dist/src/types.d.ts.map +1 -0
  116. package/dist/src/utils/dialogs.d.ts +29 -0
  117. package/dist/src/utils/dialogs.d.ts.map +1 -0
  118. package/dist/src/utils/jsonPointer.d.ts +42 -0
  119. package/dist/src/utils/jsonPointer.d.ts.map +1 -0
  120. package/dist/src/utils/templateUtils.d.ts +59 -0
  121. package/dist/src/utils/templateUtils.d.ts.map +1 -0
  122. package/dist/src/utils/types.d.ts +2 -0
  123. package/dist/src/utils/types.d.ts.map +1 -0
  124. package/dist/subTypes/blobHTMLType.d.ts +14 -0
  125. package/dist/subTypes/blobHTMLType.d.ts.map +1 -0
  126. package/dist/subTypes/falseType.d.ts +8 -0
  127. package/dist/subTypes/falseType.d.ts.map +1 -0
  128. package/dist/subTypes/trueType.d.ts +8 -0
  129. package/dist/subTypes/trueType.d.ts.map +1 -0
  130. package/dist/superTypes/SpecialNumberSuperType.d.ts +14 -0
  131. package/dist/superTypes/SpecialNumberSuperType.d.ts.map +1 -0
  132. package/dist/superTypes/SpecialRealNumberSuperType.d.ts +6 -0
  133. package/dist/superTypes/SpecialRealNumberSuperType.d.ts.map +1 -0
  134. package/dist/typeChoices.d.ts +103 -0
  135. package/dist/typeChoices.d.ts.map +1 -0
  136. package/dist/types.d.ts +523 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/utils/dialogs.d.ts +109 -0
  139. package/dist/utils/dialogs.d.ts.map +1 -0
  140. package/dist/utils/jsonPointer.d.ts +46 -0
  141. package/dist/utils/jsonPointer.d.ts.map +1 -0
  142. package/dist/utils/templateUtils.d.ts +59 -0
  143. package/dist/utils/templateUtils.d.ts.map +1 -0
  144. package/dist/utils/types.d.ts +2 -0
  145. package/dist/utils/types.d.ts.map +1 -0
  146. package/dist/vendor/jamilih/dist/jml-es.d.ts +436 -0
  147. package/dist/vendor/jamilih/dist/jml-es.d.ts.map +1 -0
  148. package/dist/vendor/typeson-registry/dist/index.d.ts +400 -0
  149. package/dist/vendor/typeson-registry/dist/index.d.ts.map +1 -0
  150. package/dist/vendor-imports.d.ts +3 -0
  151. package/dist/vendor-imports.d.ts.map +1 -0
  152. package/package.json +19 -14
  153. package/postorder-traversal.js +58 -0
  154. package/src/formatAndTypeChoices.js +95 -50
  155. package/src/formats/indexedDBKey.js +49 -56
  156. package/src/formats/json.js +47 -56
  157. package/src/formats/schemaOnly.js +12 -2
  158. package/src/formats/structuredCloning.js +162 -105
  159. package/src/formats.js +38 -10
  160. package/src/fundamentalTypes/BooleanObjectType.js +6 -4
  161. package/src/fundamentalTypes/NumberObjectType.js +5 -3
  162. package/src/fundamentalTypes/StringObjectType.js +1 -1
  163. package/src/fundamentalTypes/arrayReferenceType.js +29 -14
  164. package/src/fundamentalTypes/arrayType.js +789 -278
  165. package/src/fundamentalTypes/bigintType.js +2 -2
  166. package/src/fundamentalTypes/dateType.js +42 -14
  167. package/src/fundamentalTypes/nullType.js +1 -1
  168. package/src/fundamentalTypes/numberType.js +2 -2
  169. package/src/fundamentalTypes/objectReferenceType.js +7 -5
  170. package/src/fundamentalTypes/regexpType.js +45 -24
  171. package/src/fundamentalTypes/sparseUndefinedType.js +7 -1
  172. package/src/fundamentalTypes/stringType.js +1 -1
  173. package/src/fundamentalTypes/undefinedType.js +2 -2
  174. package/src/jsoe.css +1 -1
  175. package/src/subTypes/blobHTMLType.js +42 -22
  176. package/src/subTypes/falseType.js +2 -2
  177. package/src/subTypes/trueType.js +2 -2
  178. package/src/superTypes/SpecialNumberSuperType.js +30 -16
  179. package/src/superTypes/SpecialRealNumberSuperType.js +62 -0
  180. package/src/typeChoices.js +137 -55
  181. package/src/types.js +312 -148
  182. package/src/utils/dialogs.js +98 -29
  183. package/src/utils/jsonPointer.js +4 -0
  184. package/src/utils/templateUtils.js +27 -12
  185. package/src/vendor-imports.js +8 -0
  186. package/tsconfig.json +18 -0
  187. package/typings/sceditor.d.ts +20 -0
  188. package/vendor/jamilih/dist/jml-es.js +1019 -389
  189. package/vendor/jamilih/dist/jml.d.ts +436 -0
  190. package/vendor/jamilih/package.json +136 -0
  191. package/vendor/typeson-registry/dist/index.js +382 -84
  192. package/src/superTypes/InfinitiesSuperType.js +0 -49
package/src/types.js CHANGED
@@ -1,7 +1,9 @@
1
- import {jml} from '../vendor/jamilih/dist/jml-es.js';
2
1
  import {
2
+ // jamilih
3
+ jml,
4
+ // typeson-registry
3
5
  Typeson, getJSONType, structuredCloningThrowing
4
- } from '../vendor/typeson-registry/dist/index.js';
6
+ } from './vendor-imports.js';
5
7
 
6
8
  import Formats from './formats.js';
7
9
 
@@ -25,7 +27,8 @@ import BooleanObjectType from './fundamentalTypes/BooleanObjectType.js';
25
27
  import NumberObjectType from './fundamentalTypes/NumberObjectType.js';
26
28
  import StringObjectType from './fundamentalTypes/StringObjectType.js';
27
29
  import sparseUndefinedType from './fundamentalTypes/sparseUndefinedType.js';
28
- import InfinitiesSuperType from './superTypes/InfinitiesSuperType.js';
30
+ import SpecialRealNumberSuperType from
31
+ './superTypes/SpecialRealNumberSuperType.js';
29
32
  import SpecialNumberSuperType from './superTypes/SpecialNumberSuperType.js';
30
33
 
31
34
  /**
@@ -35,64 +38,118 @@ import SpecialNumberSuperType from './superTypes/SpecialNumberSuperType.js';
35
38
  */
36
39
  export const getPropertyValueFromLegend = (legend) => {
37
40
  const propElem = $e(legend, '*[data-prop="true"]');
38
- return propElem.nodeName.toLowerCase() === 'input'
39
- ? propElem.value
40
- : String(Number.parseInt(propElem.textContent) - 1); // 1-based to 0-based
41
+ if (!propElem) {
42
+ throw new Error(
43
+ 'No property on the supplied legend element'
44
+ );
45
+ }
46
+ if (propElem.nodeName.toLowerCase() === 'input') {
47
+ return /** @type {HTMLInputElement} */ (propElem).value;
48
+ }
49
+ if (!propElem.textContent) {
50
+ throw new Error(
51
+ 'No property with text present on the supplied legend element'
52
+ );
53
+ }
54
+ // 1-based to 0-based
55
+ return String(Number.parseInt(propElem.textContent) - 1);
41
56
  };
42
57
 
43
58
  const Types = {};
44
59
 
60
+ /**
61
+ * @typedef {import('./formats.js').StructuredCloneValue} StructuredCloneValue
62
+ */
63
+
64
+ /**
65
+ * @typedef {import('jamilih').JamilihArray} JamilihArray
66
+ */
67
+
68
+ /**
69
+ * @typedef {{
70
+ * format: import('./formats.js').AvailableFormat,
71
+ * endMatchTypeObjs: TypeObject[],
72
+ * remnant: string,
73
+ * rootHolder: [
74
+ * type: string, parent: object, parentPath: string|number, path: string
75
+ * ][],
76
+ * parent: object,
77
+ * parentPath: string|number
78
+ * }} RootInfo
79
+ */
80
+
45
81
  /**
46
82
  * @typedef {object} TypeObject
47
- * @property {JamilihArray} option Creates the option HTML. May set an option
48
- * `title` or `value`
83
+ * @property {[
84
+ * string, {value?: AvailableType, title?: string}?
85
+ * ]} option Creates the option HTML. May set an option `title` or `value`
49
86
  * @property {boolean} [array] Private context variable. Whether or not
50
87
  * it is an array. Do not use in other types.
51
88
  * @property {string[]} [regexEndings] Used for string parsing.
52
- * @property {RegExp} [stringRegex] Used for string parsing. If not
53
- * present, use `stringRegexBegin` and `stringRegexEnd`
89
+ * @property {RegExp|((nonGrouping?: boolean) => RegExp)} [stringRegex] Used
90
+ * for string parsing. If not present, use `stringRegexBegin` and
91
+ * `stringRegexEnd`.
54
92
  * @property {RegExp} [stringRegexBegin] Used for string parsing. If not
55
93
  * present, use `stringRegex`
56
94
  * @property {RegExp} [stringRegexEnd] Used for string parsing. If not
57
95
  * present, use `stringRegex`
58
- * @property {(ArbitraryValue) => boolean} [valueMatch] Function to
96
+ * @property {(v: StructuredCloneValue) => boolean} [valueMatch] Function to
59
97
  * check whether this subtype matches
60
98
  * @property {string} [superType] The greater fundamental type to which
61
99
  * the type belongs
62
- * @property {(s: string) => ArbitraryValue} toValue Converts from
63
- * string to value. May use `stringRegex` to find components.
64
- * @property {(info: {root?: HTMLDivElement}) =>
65
- * ArbitraryValue
100
+ * @property {(
101
+ * s: string, info?: RootInfo
102
+ * ) => StructuredCloneValue} toValue Converts from string to value. May use
103
+ * `stringRegex` to find components.
104
+ * @property {(info: {
105
+ * root: HTMLDivElement,
106
+ * stateObj?: StateObject,
107
+ * currentPath?: string
108
+ * }) =>
109
+ * StructuredCloneValue
66
110
  * } getValue Gets the value for the type
67
- * @property {(info: {root?: HTMLDivElement}) => void} [setValue] Should set
68
- * the value of the form's `getInput` element
111
+ * @property {(
112
+ * info: {
113
+ * root: HTMLDivElement,
114
+ * value: StructuredCloneValue
115
+ * }
116
+ * ) => void} [setValue] Should set the value of the form's `getInput` element
69
117
  * @property {(info: {
70
- * value?: ArbitraryValue,
118
+ * value?: StructuredCloneValue,
71
119
  * typeNamespace?: string,
72
- * type?: string,
120
+ * type?: AvailableType,
73
121
  * topRoot?: HTMLDivElement,
74
122
  * resultType?: "keys"|"values"|"both",
75
- * format?: string
123
+ * format: import('./formats.js').AvailableFormat
76
124
  * }) => JamilihArray} viewUI
77
125
  * @property {(info: {
78
- * value?: ArbitraryValue,
126
+ * value?: StructuredCloneValue,
79
127
  * typeNamespace?: string,
128
+ * bringIntoFocus?: boolean,
129
+ * format?: import('./formats.js').AvailableFormat,
130
+ * resultType?: "keys"|"values"|"both",
131
+ * type?: AvailableType,
132
+ * buildTypeChoices?: import('./typeChoices.js').BuildTypeChoices,
133
+ * topRoot?: HTMLDivElement
80
134
  * }) => JamilihArray} editUI
81
135
  * @property {(info: {root: HTMLDivElement}) =>
82
- * HTMLInputElement|HTMLTextareaElement|HTMLSelectElement} getInput Gets the
83
- * form control (with `value`)
84
- * @property {(path: string, value: ArbitraryValue) =>
85
- * ArbitraryValue} [resolveReference] Gets the reference. For array and object
86
- * references types only
136
+ * HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement|
137
+ * HTMLButtonElement} getInput Gets the form control (with `value`)
138
+ * @property {(
139
+ * info: {root: HTMLDivElement}
140
+ * ) => HTMLSelectElement} [getSelect]
141
+ * @property {(path: string, value: StructuredCloneValue) =>
142
+ * StructuredCloneValue} [resolveReference] Gets the reference. For array
143
+ * and object references types only
87
144
  * @property {(info: {root: HTMLDivElement, topRoot?: HTMLDivElement}) => {
88
- * message: string,
145
+ * message?: string,
89
146
  * valid: boolean
90
147
  * }} [validate] Message will be used if validity is false.
91
148
  * @property {(info: {topRoot: HTMLDivElement}) => void} [validateAll] For
92
149
  * validation of array and object references only.
93
150
  * @property {{
94
151
  * structuredCloning: {
95
- * after: string,
152
+ * after: AvailableType,
96
153
  * contexts: string[]
97
154
  * }
98
155
  * }} [stateDependent] The type after which it should be placed and its
@@ -121,7 +178,7 @@ Types.availableTypes = {
121
178
  // passed in:
122
179
  userObject: ['User objects'],
123
180
  undef: undefinedType,
124
- Infinities: InfinitiesSuperType,
181
+ SpecialRealNumber: SpecialRealNumberSuperType,
125
182
  SpecialNumber: SpecialNumberSuperType,
126
183
 
127
184
  regexp: regexpType,
@@ -200,62 +257,97 @@ Types.availableTypes = {
200
257
  },
201
258
 
202
259
  // We're catching this instead of using this
203
- sparseUndefined: sparseUndefinedType
204
- };
205
- Types.availableTypes.ValidDate = {
206
- valid: true
207
- };
208
- /*
209
- Types.availableTypes.sparseArrays = {
260
+ sparseUndefined: sparseUndefinedType,
261
+
262
+ ValidDate: {
263
+ valid: true
264
+ },
265
+ /*
266
+ sparseArrays: {
267
+ sparse: true
268
+ },
269
+ */
270
+ arrayNonindexKeys: {
210
271
  sparse: true
272
+ }
211
273
  };
274
+
275
+ /**
276
+ * @typedef {"null"|"true"|"false"|"number"|"bigint"|"string"|"arrayReference"|
277
+ * "objectReference"|"array"|"object"|"date"|"userObject"|"undef"|
278
+ * "SpecialRealNumber"|"SpecialNumber"|"regexp"|"BooleanObject"|
279
+ * "NumberObject"|"StringObject"|"map"|"set"|"file"|"filelist"|"blobHTML"|
280
+ * "arraybuffer"|"arraybufferview"|"dataview"|"imagedata"|"imagebitmap"|
281
+ * "int8array"|"uint8array"|"uint8clampedarray"|"int16array"|"uint16array"|
282
+ * "int32array"|"uint32array"|"float32array"|"float64array"|"IntlCollator"|
283
+ * "IntlDateTimeFormat"|"IntlNumberFormat"|"sparseUndefined"|"ValidDate"|
284
+ * "arrayNonindexKeys"} AvailableType
212
285
  */
213
- Types.availableTypes.arrayNonindexKeys = {
214
- sparse: true
215
- };
216
286
 
217
287
  /**
218
- * @param {[copyTo: string, copyFrom: string]} replacements
288
+ * @param {[
289
+ * copyFrom: AvailableType, copyTo: AvailableType
290
+ * ][]} replacements
219
291
  * @returns {void}
220
292
  */
221
293
  const copyTypeObjs = (replacements) => {
222
294
  replacements.forEach(([copyFrom, copyTo]) => {
223
- Object.assign(Types.availableTypes[copyTo], Types.availableTypes[copyFrom]);
295
+ Object.assign(Types.availableTypes[
296
+ /** @type {AvailableType} */
297
+ (copyTo)
298
+ ], Types.availableTypes[
299
+ /** @type {AvailableType} */
300
+ (copyFrom)
301
+ ]);
224
302
  });
225
303
  };
226
- copyTypeObjs([
227
- ['date', 'ValidDate'],
304
+
305
+ copyTypeObjs(
228
306
  [
229
- 'array',
230
- 'arrayNonindexKeys'
307
+ /** @type {[AvailableType, AvailableType]} */ (
308
+ ['date', 'ValidDate']
309
+ ),
231
310
  // 'sparseArrays'
311
+ /** @type {[AvailableType, AvailableType]} */ (
312
+ ['array', 'arrayNonindexKeys']
313
+ )
232
314
  ]
233
- ]);
315
+ );
234
316
 
235
317
  /**
236
318
  * Utility to retrieve the type out of a type root element.
237
319
  * @public
238
320
  * @param {?RootElement} root
239
- * @returns {string|undefined} Why would it not exist?
321
+ * @returns {string|undefined|null} Why would it not exist?
240
322
  */
241
323
  Types.getTypeForRoot = (root) => {
242
324
  return root && root.dataset.type;
243
325
  };
244
326
 
245
327
  /**
246
- * @typedef {{
247
- * typeNamespace: string,
248
- * "readonly": boolean,
249
- * format: string,
250
- * error: Error,
251
- * rootUI: Element,
252
- * schemaContent: string,
253
- * getPossibleSchemasForPathAndType: (
328
+ * @typedef {(
254
329
  * keypath: string,
255
- * parentPath: string,
256
- * arrayOrObjectPropertyName: string,
257
- * valueType: string
258
- * ) => StateObject
330
+ * parentPath: string,
331
+ * arrayOrObjectPropertyName: string,
332
+ * valueType: string
333
+ * ) => StateObject} GetPossibleSchemasForPathAndType
334
+ */
335
+
336
+ /**
337
+ * @typedef {{
338
+ * typeNamespace?: string,
339
+ * "readonly"?: boolean,
340
+ * format?: import('./formats.js').AvailableFormat,
341
+ * error?: Error,
342
+ * rootUI?: Element,
343
+ * schema?: string,
344
+ * schemaContent?: object,
345
+ * getPossibleSchemasForPathAndType?: GetPossibleSchemasForPathAndType,
346
+ * paths?: {[currentPath: string]: {
347
+ * referentPath: string,
348
+ * expectArrayReferent: boolean
349
+ * }},
350
+ * handlingReference?: boolean
259
351
  * }} StateObject
260
352
  */
261
353
 
@@ -270,7 +362,10 @@ Types.getTypeForRoot = (root) => {
270
362
  */
271
363
  Types.getValueForRoot = (root, stateObj, currentPath) => {
272
364
  const typeObject = /** @type {TypeObject} */ (
273
- Types.availableTypes[Types.getTypeForRoot(root)]
365
+ Types.availableTypes[
366
+ /** @type {AvailableType} */
367
+ (Types.getTypeForRoot(root))
368
+ ]
274
369
  );
275
370
  return typeObject.getValue({
276
371
  root, stateObj, currentPath
@@ -281,10 +376,14 @@ Types.getValueForRoot = (root, stateObj, currentPath) => {
281
376
  * Utility to get the form control (e.g., input element) for a root.
282
377
  * @public
283
378
  * @param {RootElement} root
284
- * @returns {null|HTMLInputElement}
379
+ * @returns {null|
380
+ * HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement|HTMLButtonElement}
285
381
  */
286
382
  Types.getFormControlForRoot = (root) => {
287
- const typeObj = Types.availableTypes[Types.getTypeForRoot(root)];
383
+ const typeObj = /** @type {TypeObject} */ (Types.availableTypes[
384
+ /** @type {AvailableType} */
385
+ (Types.getTypeForRoot(root))
386
+ ]);
288
387
  /* istanbul ignore if -- All have except aliases */
289
388
  if (!typeObj.getInput) {
290
389
  return null;
@@ -300,16 +399,21 @@ Types.getFormControlForRoot = (root) => {
300
399
  * @returns {StructuredCloneValue}
301
400
  */
302
401
  Types.getValueFromRootAncestor = (selOrEl, stateObj) => {
303
- return Types.getValueForRoot($e(selOrEl, 'div[data-type]'), stateObj);
402
+ return Types.getValueForRoot(
403
+ /** @type {RootElement} */
404
+ ($e(selOrEl, 'div[data-type]')),
405
+ stateObj
406
+ );
304
407
  };
305
408
 
306
409
  /**
307
410
  * @public
308
411
  * @param {string|Element} selOrEl
309
- * @returns {null|HTMLInputElement}
412
+ * @returns {null|HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement|
413
+ * HTMLButtonElement}
310
414
  */
311
415
  Types.getFormControlFromRootAncestor = (selOrEl) => {
312
- const root = $e(selOrEl, 'div[data-type]');
416
+ const root = /** @type {RootElement} */ ($e(selOrEl, 'div[data-type]'));
313
417
  if (!root) {
314
418
  return null;
315
419
  }
@@ -318,8 +422,8 @@ Types.getFormControlFromRootAncestor = (selOrEl) => {
318
422
 
319
423
  /**
320
424
  * @param {string} format
321
- * @param {string} state
322
- * @returns {string[]}
425
+ * @param {string} [state]
426
+ * @returns {AvailableType[]|undefined}
323
427
  */
324
428
  Types.getTypesForFormatAndState = (
325
429
  format, state
@@ -327,68 +431,85 @@ Types.getTypesForFormatAndState = (
327
431
 
328
432
  /**
329
433
  * @public
330
- * @param {string} type
331
- * @returns {JamilihArray}
434
+ * @param {AvailableType} type
435
+ * @returns {[string, {value: AvailableType, title?: string}]}
332
436
  */
333
437
  Types.getOptionForType = (type) => {
334
- const optInfo = [...Types.availableTypes[type].option];
335
- optInfo[1] = {value: type, ...optInfo[1]};
336
- return optInfo;
438
+ /** @type {[string, {value?: AvailableType, title?: string}?]} */
439
+ const optInfo = [
440
+ ...(/** @type {TypeObject} */ (
441
+ Types.availableTypes[type]
442
+ )).option
443
+ ];
444
+ optInfo[1] = {value: type, ...(optInfo[1])};
445
+ return /** @type {[string, {value: AvailableType, title?: string}]} */ (
446
+ optInfo
447
+ );
337
448
  };
338
449
 
339
450
  /**
340
451
  * @public
341
452
  * @param {string} format
342
- * @param {string} parserState
343
- * @returns {JamilihArray[]}
453
+ * @param {string} [parserState]
454
+ * @returns {[string, {value: AvailableType, title?: string}][]}
344
455
  */
345
456
  Types.getTypeOptionsForFormatAndState = (format, parserState) => {
346
457
  const typesForFormatAndState = Types.getTypesForFormatAndState(
347
458
  format, parserState
348
459
  );
460
+ if (!typesForFormatAndState) {
461
+ throw new Error('Unexpected type for format and state');
462
+ }
349
463
  return typesForFormatAndState.map((type) => {
350
464
  return Types.getOptionForType(type);
351
465
  });
352
466
  };
353
467
 
468
+ /* eslint-disable jsdoc/valid-types -- readonly reserved */
354
469
  /**
355
470
  * @public
356
471
  * @param {object} cfg
357
- * @param {boolean} cfg."readonly"
358
- * @param {"both"|"keys"|"values"} cfg.resultType
359
- * @param {string} cfg.typeNamespace
360
- * @param {string} cfg.type
361
- * @param {RootElement} cfg.topRoot
362
- * @param {boolean} cfg.bringIntoFocus
363
- * @param {BuildTypeChoices} cfg.buildTypeChoices
364
- * @param {string} cfg.format
365
- * @param {string} cfg.schemaContent
366
- * @param {StateObject} cfg.schemaState Not currently in use and may
367
- * need to change the type
472
+ * @param {boolean} [cfg.readonly]
473
+ * @param {"both"|"keys"|"values"} [cfg.resultType]
474
+ * @param {string} [cfg.typeNamespace]
475
+ * @param {AvailableType} cfg.type
476
+ * @param {RootElement} [cfg.topRoot]
477
+ * @param {boolean|undefined} cfg.bringIntoFocus
478
+ * @param {import('./typeChoices.js').BuildTypeChoices} [cfg.buildTypeChoices]
479
+ * @param {import('./formats.js').AvailableFormat} cfg.format
480
+ * @param {object} [cfg.schemaContent]
481
+ * @param {GetPossibleSchemasForPathAndType} [cfg.schemaState] Not currently
482
+ * in use
368
483
  * @param {StructuredCloneValue} cfg.value
369
484
  * @param {boolean} cfg.hasValue
485
+ * @param {StructuredCloneValue} [cfg.replaced]
370
486
  * @returns {Element}
371
487
  */
372
488
  Types.getUIForModeAndType = ({
373
489
  readonly, resultType, typeNamespace, type, topRoot, bringIntoFocus,
374
- buildTypeChoices, format, schemaContent, schemaState, value, hasValue
490
+ buildTypeChoices, format, schemaContent, schemaState, value, hasValue,
491
+ replaced
375
492
  }) => {
376
- const typeObj = Types.availableTypes[type];
377
- const root = jml(
378
- ...typeObj[readonly ? 'viewUI' : 'editUI'](
379
- hasValue
380
- ? {
381
- typeNamespace, type, buildTypeChoices,
382
- format, schemaContent, schemaState,
383
- resultType, topRoot, bringIntoFocus, value
384
- }
385
- : {
386
- typeNamespace, type, buildTypeChoices,
387
- format, schemaContent, schemaState,
388
- resultType, topRoot, bringIntoFocus
389
- }
390
- )
391
- );
493
+ /* eslint-enable jsdoc/valid-types -- readonly reserved */
494
+ const typeObj = /** @type {TypeObject} */ (Types.availableTypes[type]);
495
+ const arg = hasValue
496
+ ? {
497
+ typeNamespace, type, buildTypeChoices,
498
+ format, schemaContent, schemaState,
499
+ resultType, topRoot, bringIntoFocus, value,
500
+ replaced
501
+ }
502
+ : {
503
+ typeNamespace, type, buildTypeChoices,
504
+ format, schemaContent, schemaState,
505
+ resultType, topRoot, bringIntoFocus,
506
+ replaced
507
+ };
508
+ const root = /** @type {HTMLDivElement} */ (jml(
509
+ ...(readonly
510
+ ? typeObj.viewUI(arg)
511
+ : typeObj.editUI(arg))
512
+ ));
392
513
  if (!readonly && typeObj.validate) {
393
514
  const formControl = typeObj.getInput({root});
394
515
  formControl.addEventListener('input', () => {
@@ -398,8 +519,17 @@ Types.getUIForModeAndType = ({
398
519
  return root;
399
520
  };
400
521
 
522
+ /**
523
+ * @type {{
524
+ * [key: string]: {
525
+ * [key: string]: {type: AvailableType, after: AvailableType}[]
526
+ * }
527
+ * }}
528
+ */
401
529
  Types.contexts = {};
402
- Object.entries(Types.availableTypes).forEach(([type, {stateDependent}]) => {
530
+ Object.entries(Types.availableTypes).forEach(([typ, typeObj]) => {
531
+ const type = /** @type {AvailableType} */ (typ);
532
+ const {stateDependent} = /** @type {TypeObject} */ (typeObj);
403
533
  if (stateDependent) {
404
534
  Object.entries(stateDependent).forEach(([format, formatStateDependent]) => {
405
535
  if (!Types.contexts[format]) {
@@ -420,8 +550,8 @@ Object.entries(Types.availableTypes).forEach(([type, {stateDependent}]) => {
420
550
  * @public
421
551
  * @param {object} cfg
422
552
  * @param {HTMLFormElement} cfg.form
423
- * @param {string} cfg.typeNamespace
424
- * @param {string} cfg.keySelectClass
553
+ * @param {string} [cfg.typeNamespace]
554
+ * @param {string} [cfg.keySelectClass]
425
555
  * @returns {boolean}
426
556
  */
427
557
  Types.validValuesSet = ({form, typeNamespace, keySelectClass}) => {
@@ -434,10 +564,13 @@ Types.validValuesSet = ({form, typeNamespace, keySelectClass}) => {
434
564
  return false;
435
565
  }
436
566
 
437
- const typeChoices = $$e(
438
- form,
439
- keySelectClass ? `.${keySelectClass}` : `.typeChoices-${typeNamespace}`
440
- );
567
+ const typeChoices =
568
+ /** @type {(HTMLSelectElement & {$validate: () => boolean})[]} */ (
569
+ $$e(
570
+ form,
571
+ keySelectClass ? `.${keySelectClass}` : `.typeChoices-${typeNamespace}`
572
+ )
573
+ );
441
574
  return (
442
575
  // Specific value type set if present (any descendant, not
443
576
  // only the first) chosen
@@ -474,7 +607,8 @@ Types.validateAllReferences = ({topRoot}) => {
474
607
 
475
608
  // Could just hard-code arrayReference and objectReference,
476
609
  // but we'll try to avoid depending on specific types
477
- Object.values(Types.availableTypes).forEach((typeObject) => {
610
+ Object.values(Types.availableTypes).forEach((typeObj) => {
611
+ const typeObject = /** @type {TypeObject} */ (typeObj);
478
612
  if (typeObject.validateAll) {
479
613
  typeObject.validateAll({topRoot});
480
614
  }
@@ -485,16 +619,21 @@ Types.validateAllReferences = ({topRoot}) => {
485
619
  }
486
620
  };
487
621
 
622
+ /**
623
+ * @type {null|((info: {topRoot: HTMLDivElement}) => void)}
624
+ */
625
+ Types.customValidateAllReferences = null;
626
+
488
627
  /**
489
628
  * @public
490
629
  * @param {object} cfg
491
- * @param {string} cfg.type
630
+ * @param {AvailableType} cfg.type
492
631
  * @param {RootElement} cfg.root
493
- * @param {RootElement} cfg.topRoot
632
+ * @param {RootElement} [cfg.topRoot]
494
633
  * @returns {boolean}
495
634
  */
496
635
  Types.validate = ({type, root, topRoot}) => {
497
- const typeObj = Types.availableTypes[type];
636
+ const typeObj = /** @type {TypeObject} */ (Types.availableTypes[type]);
498
637
  // Todo (low): We limit for now to input boxes which have `validate`
499
638
  if (typeObj.validate) {
500
639
  const {valid, message} = typeObj.validate({root, topRoot});
@@ -513,13 +652,13 @@ Types.validate = ({type, root, topRoot}) => {
513
652
 
514
653
  /**
515
654
  * @param {object} cfg
516
- * @param {string} cfg.type
655
+ * @param {AvailableType} cfg.type
517
656
  * @param {RootElement} cfg.root
518
657
  * @param {StructuredCloneValue} cfg.value
519
658
  * @returns {void}
520
659
  */
521
660
  Types.setValue = ({type, root, value}) => {
522
- const typeObj = Types.availableTypes[type];
661
+ const typeObj = /** @type {TypeObject} */ (Types.availableTypes[type]);
523
662
  if (typeObj.setValue) {
524
663
  typeObj.setValue({root, value});
525
664
  }
@@ -548,68 +687,86 @@ function escapeRegex (str) {
548
687
  * @public
549
688
  * @param {string} s
550
689
  * @param {object} cfg
551
- * @param {string} cfg.format
690
+ * @param {import('./formats.js').AvailableFormat} cfg.format
552
691
  * @param {string} cfg.state
553
692
  * @param {TypeObject[]} [cfg.endMatchTypeObjs=[]]
554
693
  * @param {boolean} [cfg.firstRun=true]
555
- * @param {
556
- * [
557
- * type: string,
558
- * parent: array|object,
559
- * parentPath: string,
560
- * path: string
561
- * ]
562
- * } [cfg.rootHolder=[]]
563
- * @param {ArbitraryArray|ArbitraryObject} cfg.parent
564
- * @param {string} cfg.parentPath
565
- * @returns {{
566
- * value: ArbitraryValue,
694
+ * @param {[
695
+ * type: string,
696
+ * parent: {[key: string]: any},
697
+ * parentPath: string|number,
698
+ * path: string
699
+ * ][]} [cfg.rootHolder=[]]
700
+ * @param {{[key: string]: any}} cfg.parent
701
+ * @param {string|number} cfg.parentPath
702
+ * @returns {[
703
+ * value: StructuredCloneValue,
567
704
  * remnant: string,
568
705
  * beginOnly: boolean,
569
706
  * assign: boolean
570
- * }}
707
+ * ]}
571
708
  */
572
709
  Types.getValueForString = (s, {
573
710
  format, state, endMatchTypeObjs = [], firstRun = true,
574
711
  rootHolder = [], parent, parentPath
575
712
  }) => {
576
- let assign = true;
577
- let match;
578
713
  const allowedTypes = Types.getTypesForFormatAndState(format, state);
714
+ if (!allowedTypes) {
715
+ throw new Error('Could not get types for format and state');
716
+ }
579
717
  const allowedTypeObjs = Object.entries(
580
718
  Types.availableTypes
581
- ).filter(([type]) => allowedTypes.includes(type));
719
+ ).filter(([type]) => {
720
+ return allowedTypes.includes(/** @type {AvailableType} */ (type));
721
+ });
582
722
  const allowedTypeObjsVals = allowedTypeObjs.map(([, arr]) => arr);
583
723
 
584
- const endings = '|' + allowedTypeObjsVals.reduce((arr, typeObj) => {
724
+ const reduced = allowedTypeObjsVals.reduce((array, typObj) => {
725
+ const typeObj = /** @type {TypeObject} */ (typObj);
726
+ let arr = /** @type {string[]} */ (array);
585
727
  if (typeObj.regexEndings) {
586
728
  arr.push(...typeObj.regexEndings);
587
729
  arr = [...new Set(arr)];
588
730
  }
589
731
  return arr;
590
- }, []).map((str) => escapeRegex(str)).join('|');
591
-
592
- let found = allowedTypeObjs.find(([_type, typeObj]) => {
732
+ }, []);
733
+ const endings = '|' + /** @type {string[]} */ (
734
+ reduced
735
+ ).map((str) => escapeRegex(str)).join('|');
736
+
737
+ /**
738
+ * @type {RegExpMatchArray|boolean|null}
739
+ */
740
+ let match = null;
741
+ let found = allowedTypeObjs.find(([_type, typObj]) => {
742
+ const typeObj = /** @type {TypeObject} */ (typObj);
593
743
  let {stringRegex} = typeObj;
594
- if (typeof stringRegex === 'function') {
744
+ if (typeof typeObj.stringRegex === 'function') {
595
745
  stringRegex = typeObj.stringRegex(true);
596
746
  }
597
747
  stringRegex = stringRegex
598
748
  // Strip off terminal (dollar sign) when matching substrings
599
749
  ? new RegExp(
600
- stringRegex.source.slice(0, -1) + '(?=$' + endings + ')',
750
+ /** @type {RegExp} */ (
751
+ stringRegex
752
+ ).source.slice(0, -1) + '(?=$' + endings + ')',
601
753
  'u'
602
754
  )
603
755
  : stringRegex;
604
- match = stringRegex && s && s.match(stringRegex);
756
+ match = Boolean(stringRegex && s) && s.match(
757
+ /** @type {RegExp} */ (stringRegex)
758
+ );
605
759
  return match;
606
760
  });
607
761
 
608
- let beginOnly;
762
+ let beginOnly = false;
609
763
  if (found === undefined) {
610
- found = allowedTypeObjs.find(([_type, typeObj]) => {
764
+ found = allowedTypeObjs.find(([_type, typObj]) => {
765
+ const typeObj = /** @type {TypeObject} */ (typObj);
611
766
  const {stringRegexBegin} = typeObj;
612
- match = stringRegexBegin && s && s.match(stringRegexBegin);
767
+ match = Boolean(stringRegexBegin && s) && s.match(
768
+ /** @type {RegExp} */ (stringRegexBegin)
769
+ );
613
770
  if (match) {
614
771
  beginOnly = true;
615
772
  endMatchTypeObjs.push(typeObj);
@@ -617,13 +774,16 @@ Types.getValueForString = (s, {
617
774
  return match;
618
775
  });
619
776
  }
777
+ let assign = true;
620
778
  if (found !== undefined) {
621
- let remnant = s.slice(match[0].length);
622
- s = s.slice(0, match[0].length);
779
+ // @ts-ignore The `found` is evaluated again, so sets `match` to non-null
780
+ const [content, innerContent] = /** @type {RegExpMatchArray} */ (match);
781
+ let remnant = s.slice(content.length);
782
+ s = s.slice(0, content.length);
623
783
  // console.log('s0', s, '::', remnant, match);
624
784
  let valObj;
625
785
  try {
626
- valObj = found[1].toValue(match[1] || s, {
786
+ valObj = /** @type {TypeObject} */ (found[1]).toValue(innerContent || s, {
627
787
  format,
628
788
  endMatchTypeObjs,
629
789
  remnant,
@@ -645,7 +805,7 @@ Types.getValueForString = (s, {
645
805
 
646
806
  if (beginOnly && endMatchTypeObjs.length) {
647
807
  const endMatch = remnant.match(
648
- endMatchTypeObjs.slice(-1)[0].stringRegexEnd
808
+ /** @type {RegExp} */ (endMatchTypeObjs.slice(-1)[0].stringRegexEnd)
649
809
  );
650
810
  if (endMatch) {
651
811
  endMatchTypeObjs.pop(); // Safe now to extract
@@ -659,8 +819,12 @@ Types.getValueForString = (s, {
659
819
  try {
660
820
  const topRoot = typeson.revive(value);
661
821
  rootHolder.forEach(([type, parent, parentPath, path]) => {
662
- const val = Types.availableTypes[type + 'Reference']
663
- .resolveReference(path, topRoot);
822
+ const typeObject = Types.availableTypes[
823
+ /** @type {AvailableType} */ (type + 'Reference')
824
+ ];
825
+
826
+ // @ts-expect-error Reference method exists
827
+ const val = typeObject.resolveReference(path, topRoot);
664
828
  const basicType = getJSONType(val);
665
829
  // eslint-disable-next-line max-len -- Long
666
830
  /* istanbul ignore else -- Successful reference always an object/array? */