@es-joy/jsoe 0.16.0 → 0.17.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 (208) hide show
  1. package/.ncurc.cjs +4 -5
  2. package/CHANGES.md +4 -0
  3. package/README.md +27 -3
  4. package/badges/licenses-badge.svg +1 -0
  5. package/dist/formatAndTypeChoices.d.ts +39 -19
  6. package/dist/formatAndTypeChoices.d.ts.map +1 -1
  7. package/dist/formats/indexedDBKey.d.ts +1 -1
  8. package/dist/formats/indexedDBKey.d.ts.map +1 -1
  9. package/dist/formats/json.d.ts +1 -1
  10. package/dist/formats/json.d.ts.map +1 -1
  11. package/dist/formats/schema.d.ts +11 -0
  12. package/dist/formats/schema.d.ts.map +1 -0
  13. package/dist/formats/structuredCloning.d.ts +11 -13
  14. package/dist/formats/structuredCloning.d.ts.map +1 -1
  15. package/dist/formats.d.ts +86 -25
  16. package/dist/formats.d.ts.map +1 -1
  17. package/dist/fundamentalTypes/BooleanObjectType.d.ts +1 -1
  18. package/dist/fundamentalTypes/BooleanObjectType.d.ts.map +1 -1
  19. package/dist/fundamentalTypes/NumberObjectType.d.ts +1 -1
  20. package/dist/fundamentalTypes/NumberObjectType.d.ts.map +1 -1
  21. package/dist/fundamentalTypes/StringObjectType.d.ts +1 -1
  22. package/dist/fundamentalTypes/StringObjectType.d.ts.map +1 -1
  23. package/dist/fundamentalTypes/arrayReferenceType.d.ts +1 -1
  24. package/dist/fundamentalTypes/arrayType.d.ts +3 -3
  25. package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
  26. package/dist/fundamentalTypes/bigintObjectType.d.ts +6 -0
  27. package/dist/fundamentalTypes/bigintObjectType.d.ts.map +1 -0
  28. package/dist/fundamentalTypes/bigintType.d.ts +1 -1
  29. package/dist/fundamentalTypes/bigintType.d.ts.map +1 -1
  30. package/dist/fundamentalTypes/blobType.d.ts +1 -1
  31. package/dist/fundamentalTypes/blobType.d.ts.map +1 -1
  32. package/dist/fundamentalTypes/booleanType.d.ts +8 -0
  33. package/dist/fundamentalTypes/booleanType.d.ts.map +1 -0
  34. package/dist/fundamentalTypes/catchType.d.ts +6 -0
  35. package/dist/fundamentalTypes/catchType.d.ts.map +1 -0
  36. package/dist/fundamentalTypes/dateType.d.ts +4 -4
  37. package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
  38. package/dist/fundamentalTypes/domexceptionType.d.ts +1 -1
  39. package/dist/fundamentalTypes/domexceptionType.d.ts.map +1 -1
  40. package/dist/fundamentalTypes/enumType.d.ts +6 -0
  41. package/dist/fundamentalTypes/enumType.d.ts.map +1 -0
  42. package/dist/fundamentalTypes/errorType.d.ts +1 -1
  43. package/dist/fundamentalTypes/errorType.d.ts.map +1 -1
  44. package/dist/fundamentalTypes/fileType.d.ts +1 -1
  45. package/dist/fundamentalTypes/fileType.d.ts.map +1 -1
  46. package/dist/fundamentalTypes/filelistType.d.ts +1 -1
  47. package/dist/fundamentalTypes/filelistType.d.ts.map +1 -1
  48. package/dist/fundamentalTypes/functionType.d.ts +6 -0
  49. package/dist/fundamentalTypes/functionType.d.ts.map +1 -0
  50. package/dist/fundamentalTypes/literalType.d.ts +6 -0
  51. package/dist/fundamentalTypes/literalType.d.ts.map +1 -0
  52. package/dist/fundamentalTypes/mapType.d.ts +1 -1
  53. package/dist/fundamentalTypes/mapType.d.ts.map +1 -1
  54. package/dist/fundamentalTypes/nanType.d.ts +6 -0
  55. package/dist/fundamentalTypes/nanType.d.ts.map +1 -0
  56. package/dist/fundamentalTypes/nativeEnumType.d.ts +6 -0
  57. package/dist/fundamentalTypes/nativeEnumType.d.ts.map +1 -0
  58. package/dist/fundamentalTypes/neverType.d.ts +6 -0
  59. package/dist/fundamentalTypes/neverType.d.ts.map +1 -0
  60. package/dist/fundamentalTypes/noneditableType.d.ts +1 -1
  61. package/dist/fundamentalTypes/noneditableType.d.ts.map +1 -1
  62. package/dist/fundamentalTypes/nullType.d.ts +1 -1
  63. package/dist/fundamentalTypes/nullType.d.ts.map +1 -1
  64. package/dist/fundamentalTypes/numberType.d.ts +1 -1
  65. package/dist/fundamentalTypes/numberType.d.ts.map +1 -1
  66. package/dist/fundamentalTypes/objectReferenceType.d.ts +1 -1
  67. package/dist/fundamentalTypes/objectType.d.ts +1 -1
  68. package/dist/fundamentalTypes/objectType.d.ts.map +1 -1
  69. package/dist/fundamentalTypes/promiseType.d.ts +6 -0
  70. package/dist/fundamentalTypes/promiseType.d.ts.map +1 -0
  71. package/dist/fundamentalTypes/recordType.d.ts +6 -0
  72. package/dist/fundamentalTypes/recordType.d.ts.map +1 -0
  73. package/dist/fundamentalTypes/regexpType.d.ts +1 -1
  74. package/dist/fundamentalTypes/regexpType.d.ts.map +1 -1
  75. package/dist/fundamentalTypes/setType.d.ts +1 -1
  76. package/dist/fundamentalTypes/setType.d.ts.map +1 -1
  77. package/dist/fundamentalTypes/sparseUndefinedType.d.ts +1 -1
  78. package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -1
  79. package/dist/fundamentalTypes/stringType.d.ts +1 -1
  80. package/dist/fundamentalTypes/stringType.d.ts.map +1 -1
  81. package/dist/fundamentalTypes/symbolType.d.ts +8 -0
  82. package/dist/fundamentalTypes/symbolType.d.ts.map +1 -0
  83. package/dist/fundamentalTypes/tupleType.d.ts +6 -0
  84. package/dist/fundamentalTypes/tupleType.d.ts.map +1 -0
  85. package/dist/fundamentalTypes/undefinedType.d.ts +1 -1
  86. package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -1
  87. package/dist/fundamentalTypes/voidType.d.ts +6 -0
  88. package/dist/fundamentalTypes/voidType.d.ts.map +1 -0
  89. package/dist/index.d.ts +2 -2
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +9660 -1586
  92. package/dist/subTypes/blobHTMLType.d.ts.map +1 -1
  93. package/dist/subTypes/falseType.d.ts +1 -1
  94. package/dist/subTypes/trueType.d.ts +1 -1
  95. package/dist/superTypes/SpecialNumberType.d.ts +1 -1
  96. package/dist/superTypes/SpecialRealNumberType.d.ts +1 -1
  97. package/dist/superTypes/SpecialRealNumberType.d.ts.map +1 -1
  98. package/dist/superTypes/buffersourceType.d.ts +1 -1
  99. package/dist/superTypes/buffersourceType.d.ts.map +1 -1
  100. package/dist/superTypes/dommatrixType.d.ts +1 -1
  101. package/dist/superTypes/dommatrixType.d.ts.map +1 -1
  102. package/dist/superTypes/dompointType.d.ts +1 -1
  103. package/dist/superTypes/dompointType.d.ts.map +1 -1
  104. package/dist/superTypes/domrectType.d.ts +1 -1
  105. package/dist/superTypes/domrectType.d.ts.map +1 -1
  106. package/dist/superTypes/errorsSpecialType.d.ts +1 -1
  107. package/dist/superTypes/errorsSpecialType.d.ts.map +1 -1
  108. package/dist/typeChoices.d.ts +33 -16
  109. package/dist/typeChoices.d.ts.map +1 -1
  110. package/dist/types.d.ts +161 -157
  111. package/dist/types.d.ts.map +1 -1
  112. package/dist/utils/dialogs.d.ts +3 -3
  113. package/dist/utils/dialogs.d.ts.map +1 -1
  114. package/dist/utils/jsonPointer.d.ts.map +1 -1
  115. package/dist/utils/media.d.ts.map +1 -1
  116. package/dist/utils/objects.d.ts +16 -0
  117. package/dist/utils/objects.d.ts.map +1 -0
  118. package/dist/utils/types.d.ts +1 -1
  119. package/dist/utils/types.d.ts.map +1 -1
  120. package/dist/vendor-imports.d.ts +1 -1
  121. package/eslint.config.js +74 -0
  122. package/licenseInfo.json +4 -0
  123. package/package.json +33 -42
  124. package/rollup.config.js +15 -0
  125. package/src/formatAndTypeChoices.js +68 -54
  126. package/src/formats/indexedDBKey.js +9 -4
  127. package/src/formats/json.js +7 -4
  128. package/src/formats/schema.js +772 -0
  129. package/src/formats/structuredCloning.js +187 -86
  130. package/src/formats.js +61 -26
  131. package/src/fundamentalTypes/BooleanObjectType.js +18 -6
  132. package/src/fundamentalTypes/NumberObjectType.js +18 -5
  133. package/src/fundamentalTypes/StringObjectType.js +20 -8
  134. package/src/fundamentalTypes/arrayType.js +1241 -533
  135. package/src/fundamentalTypes/bigintObjectType.js +64 -0
  136. package/src/fundamentalTypes/bigintType.js +31 -5
  137. package/src/fundamentalTypes/blobType.js +201 -190
  138. package/src/fundamentalTypes/booleanType.js +63 -0
  139. package/src/fundamentalTypes/catchType.js +140 -0
  140. package/src/fundamentalTypes/dateType.js +57 -19
  141. package/src/fundamentalTypes/domexceptionType.js +61 -63
  142. package/src/fundamentalTypes/enumType.js +52 -0
  143. package/src/fundamentalTypes/errorType.js +20 -7
  144. package/src/fundamentalTypes/fileType.js +195 -189
  145. package/src/fundamentalTypes/filelistType.js +4 -0
  146. package/src/fundamentalTypes/functionType.js +150 -0
  147. package/src/fundamentalTypes/literalType.js +81 -0
  148. package/src/fundamentalTypes/mapType.js +4 -0
  149. package/src/fundamentalTypes/nanType.js +41 -0
  150. package/src/fundamentalTypes/nativeEnumType.js +155 -0
  151. package/src/fundamentalTypes/neverType.js +44 -0
  152. package/src/fundamentalTypes/noneditableType.js +19 -5
  153. package/src/fundamentalTypes/nullType.js +16 -6
  154. package/src/fundamentalTypes/numberType.js +49 -6
  155. package/src/fundamentalTypes/objectType.js +10 -2
  156. package/src/fundamentalTypes/promiseType.js +60 -0
  157. package/src/fundamentalTypes/recordType.js +42 -0
  158. package/src/fundamentalTypes/regexpType.js +51 -33
  159. package/src/fundamentalTypes/setType.js +4 -0
  160. package/src/fundamentalTypes/sparseUndefinedType.js +3 -0
  161. package/src/fundamentalTypes/stringType.js +254 -6
  162. package/src/fundamentalTypes/symbolType.js +81 -0
  163. package/src/fundamentalTypes/tupleType.js +39 -0
  164. package/src/fundamentalTypes/undefinedType.js +14 -4
  165. package/src/fundamentalTypes/voidType.js +48 -0
  166. package/src/jsoe.css +37 -3
  167. package/src/subTypes/blobHTMLType.js +33 -24
  168. package/src/superTypes/SpecialRealNumberType.js +22 -6
  169. package/src/superTypes/buffersourceType.js +86 -30
  170. package/src/superTypes/dommatrixType.js +24 -7
  171. package/src/superTypes/dompointType.js +27 -7
  172. package/src/superTypes/domrectType.js +33 -7
  173. package/src/superTypes/errorsSpecialType.js +30 -14
  174. package/src/typeChoices.js +115 -44
  175. package/src/types.js +129 -45
  176. package/src/utils/FileList.js +3 -3
  177. package/src/utils/dialogs.js +6 -8
  178. package/src/utils/objects.js +22 -0
  179. package/src/vendor-imports.js +1 -1
  180. package/tsconfig.json +2 -2
  181. package/vendor/jamilih/dist/jml-es.js +23 -6
  182. package/vendor/typeson-registry/dist/index.js +77 -47
  183. package/vendor/zod/lib/index.mjs +4236 -0
  184. package/vendor/zodex/dist/esm/dezerialize.d.ts +26 -0
  185. package/vendor/zodex/dist/esm/dezerialize.js +393 -0
  186. package/vendor/zodex/dist/esm/index.d.ts +9 -0
  187. package/vendor/zodex/dist/esm/index.js +4 -0
  188. package/vendor/zodex/dist/esm/infer.d.ts +29 -0
  189. package/vendor/zodex/dist/esm/infer.js +1 -0
  190. package/vendor/zodex/dist/esm/package.json +1 -0
  191. package/vendor/zodex/dist/esm/types.d.ts +201 -0
  192. package/vendor/zodex/dist/esm/types.js +13 -0
  193. package/vendor/zodex/dist/esm/ui.d.ts +23 -0
  194. package/vendor/zodex/dist/esm/ui.js +10 -0
  195. package/vendor/zodex/dist/esm/zerialize.d.ts +50 -0
  196. package/vendor/zodex/dist/esm/zerialize.js +417 -0
  197. package/vendor/zodex/dist/esm/zod-types.d.ts +11 -0
  198. package/vendor/zodex/dist/esm/zod-types.js +1 -0
  199. package/.eslintignore +0 -13
  200. package/.eslintrc.cjs +0 -145
  201. package/.nyc_output/out.json +0 -117370
  202. package/cypress.config.ts +0 -15
  203. package/demo/index-instrumented.html +0 -29
  204. package/demo/index-instrumented.js +0 -644
  205. package/demo/index.html +0 -29
  206. package/demo/index.js +0 -215
  207. package/src/formats/schemaAndArbitrary.js +0 -20
  208. package/src/formats/schemaOnly.js +0 -539
@@ -1,4 +1,4 @@
1
- import {jml} from '../vendor-imports.js';
1
+ import {jml, toStringTag} from '../vendor-imports.js';
2
2
  import {$e} from '../utils/templateUtils.js';
3
3
 
4
4
  /**
@@ -14,6 +14,9 @@ const regexpType = {
14
14
  this.allowedFlags.length
15
15
  }})$`, 'u');
16
16
  },
17
+ valueMatch (x) {
18
+ return toStringTag(x) === 'RegExp';
19
+ },
17
20
  toValue (s) {
18
21
  /* istanbul ignore if */
19
22
  if (typeof this.stringRegex !== 'function') {
@@ -61,48 +64,63 @@ const regexpType = {
61
64
  );
62
65
  },
63
66
  allowedFlags: ['g', 'i', 'm', 'u', 'y', 's', 'v'],
64
- viewUI ({value}) {
65
- return ['i', {dataset: {type: 'regexp'}}, [String(value)]];
67
+ viewUI ({value, specificSchemaObject}) {
68
+ return ['i', {
69
+ dataset: {type: 'regexp'},
70
+ title: specificSchemaObject?.description ?? '(a `RegExp`)'
71
+ }, [
72
+ String(value)
73
+ ]];
66
74
  },
67
- editUI ({typeNamespace, types, value = {source: '', flags: ''}}) {
75
+ editUI ({
76
+ typeNamespace, specificSchemaObject, types, value = {source: '', flags: ''}
77
+ }) {
68
78
  // Todo (low): Add RegExp syntax highlighter
69
- const select = /** @type {HTMLSelectElement} */ (jml(
70
- 'select',
71
- {multiple: true, size: 5, $custom: {
79
+ const select = jml('select', {
80
+ multiple: true, size: 5, $custom: {
72
81
  /**
82
+ * @callback $Set
73
83
  * @param {string[]} valArr
74
84
  * @returns {void}
75
85
  */
86
+
87
+ /** @type {$Set} */
76
88
  $set (valArr) { // A useful reusable method for multiple selects
77
- [...(/** @type {HTMLSelectElement} */ (
78
- this
79
- )).options].forEach((opt) => {
89
+ [...(
90
+ /**
91
+ * @type {HTMLSelectElement & {
92
+ * $set: $Set
93
+ * }}
94
+ */ (
95
+ this
96
+ )
97
+ ).options].forEach((opt) => {
80
98
  opt.selected = valArr.includes(opt.value);
81
99
  });
82
100
  }
83
- }},
84
- this.allowedFlags.map((flag) => {
85
- return ['option', {
86
- selected: value.flags.includes(flag)
87
- }, [flag]];
88
- })
89
- ));
90
- const root = /** @type {HTMLDivElement} */ (
91
- jml('div', {dataset: {type: 'regexp'}}, [
92
- ['label', [
93
- 'Source ',
94
- ['input', {
95
- name: `${typeNamespace}-regexp`, type: 'text',
96
- value: value.source
97
- }]
98
- ]],
99
- ['br'],
100
- ['label', [
101
- 'Flags ',
102
- select
103
- ]]
104
- ])
105
- );
101
+ }
102
+ }, this.allowedFlags.map((flag) => {
103
+ return ['option', {
104
+ selected: value.flags.includes(flag)
105
+ }, [flag]];
106
+ }));
107
+ const root = jml('div', {
108
+ dataset: {type: 'regexp'},
109
+ title: specificSchemaObject?.description ?? 'RegExp'
110
+ }, [
111
+ ['label', [
112
+ 'Source ',
113
+ ['input', {
114
+ name: `${typeNamespace}-regexp`, type: 'text',
115
+ value: value.source
116
+ }]
117
+ ]],
118
+ ['br'],
119
+ ['label', [
120
+ 'Flags ',
121
+ select
122
+ ]]
123
+ ]);
106
124
  // Could be disallowed flags; we might instead try in
107
125
  // advance which will work
108
126
  select.addEventListener('change', () => {
@@ -1,3 +1,4 @@
1
+ import {toStringTag} from '../vendor-imports.js';
1
2
  import arrayType from './arrayType.js';
2
3
 
3
4
  /**
@@ -10,6 +11,9 @@ const setType = {
10
11
  regexEndings: [',', ')'],
11
12
  stringRegexBegin: /^Set\(/u,
12
13
  stringRegexEnd: /^\)/u,
14
+ valueMatch (x) {
15
+ return toStringTag(x) === 'Set';
16
+ },
13
17
  toValue (...args) {
14
18
  return /** @type {import('../types.js').ToValue} */ (
15
19
  arrayType.toValue
@@ -14,6 +14,9 @@ const sparseUndefinedType = {
14
14
  ]
15
15
  }
16
16
  },
17
+ valueMatch (x) {
18
+ return x === undefined;
19
+ },
17
20
  toValue (/* _s */) {
18
21
  return {value: undefined};
19
22
  },
@@ -1,16 +1,71 @@
1
+ import {datetimeRegex} from 'zod';
1
2
  import {$e} from '../utils/templateUtils.js';
2
3
 
4
+ // Adapted from Zod: https://github.com/colinhacks/zod/blob/9257ab78eec366c04331a3c2d59deb344a02d9f6/src/types.ts
5
+ const ipv4Regex =
6
+ /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/u;
7
+ const ipv6Regex =
8
+ /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/u;
9
+ // https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
10
+ const base64Regex =
11
+ /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/u;
12
+ // from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression
13
+ const emojiRegexStr = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
14
+ const emojiRegex = new RegExp(emojiRegexStr, 'u');
15
+ const cuidRegex = /^c[^\s-]{8,}$/iu;
16
+ const cuid2Regex = /^[0-9a-z]+$/u;
17
+ const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/iu;
18
+ const uuidRegex =
19
+ /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/iu;
20
+ const nanoidRegex = /^[a-z0-9_-]{21}$/iu;
21
+ const durationRegex =
22
+ /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/u;
23
+ // End adapted from Zod
24
+
25
+ /**
26
+ * @param {{precision?: number|null}} args
27
+ * @returns {string}
28
+ */
29
+ function timeRegexSource (args) {
30
+ // let regex = `\\d{2}:\\d{2}:\\d{2}`;
31
+ let regex = `([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d`;
32
+
33
+ if (args.precision) {
34
+ regex = `${regex}\\.\\d{${args.precision}}`;
35
+ } else if (args.precision === null || args.precision === undefined) {
36
+ regex = `${regex}(\\.\\d+)?`;
37
+ }
38
+ return regex;
39
+ }
40
+
41
+ /**
42
+ * @param {{
43
+ * offset?: boolean;
44
+ * local?: boolean;
45
+ * precision?: number|null;
46
+ * }} args
47
+ * @returns {RegExp}
48
+ */
49
+ function timeRegex (args) {
50
+ return new RegExp(`^${timeRegexSource(args)}$`, 'u');
51
+ }
52
+
3
53
  /**
4
54
  * @type {import('../types.js').TypeObject}
5
55
  */
6
56
  const stringType = {
7
57
  option: ['String'],
8
58
  stringRegex: /^"(?:[^\\"]|\\\\|\\")*"$/u,
59
+ valueMatch (x) {
60
+ return typeof x === 'string';
61
+ },
9
62
  toValue (s) {
10
63
  return {value: s.slice(1, -1)};
11
64
  },
12
65
  getInput ({root}) {
13
- return /** @type {HTMLTextAreaElement} */ ($e(root, 'textarea'));
66
+ return /** @type {HTMLTextAreaElement} */ (
67
+ $e(root, '[data-type="string"] > textarea,input')
68
+ );
14
69
  },
15
70
  setValue ({root, value}) {
16
71
  this.getInput({root}).value = value;
@@ -18,12 +73,205 @@ const stringType = {
18
73
  getValue ({root}) {
19
74
  return this.getInput({root}).value;
20
75
  },
21
- viewUI ({value}) {
22
- return ['span', {dataset: {type: 'string'}}, [value]];
76
+ viewUI ({value, specificSchemaObject}) {
77
+ const kind = /** @type {import('zodex').SzString} */ (
78
+ specificSchemaObject
79
+ // @ts-expect-error Does exist
80
+ )?.kind;
81
+ return ['span', {
82
+ dataset: {type: 'string'},
83
+ title: specificSchemaObject?.description ??
84
+ (kind === 'email'
85
+ ? `(an ${kind} string)`
86
+ : kind
87
+ ? `(a ${kind} string)` // url, date
88
+ : '(a string)')
89
+ }, [value]];
23
90
  },
24
- editUI ({typeNamespace, value = ''}) {
25
- return ['div', {dataset: {type: 'string'}}, [
26
- ['textarea', {name: `${typeNamespace}-string`}, [value]]
91
+ editUI ({typeNamespace, specificSchemaObject, value}) {
92
+ const stringSchemaObject = /** @type {import('zodex').SzString} */ (
93
+ specificSchemaObject
94
+ );
95
+ // @ts-expect-error Does exist
96
+ const kind = stringSchemaObject?.kind;
97
+ const isLiteral = specificSchemaObject?.type === 'literal';
98
+ const minlength = stringSchemaObject?.min ?? stringSchemaObject?.length;
99
+ const maxlength = stringSchemaObject?.max ?? stringSchemaObject?.length;
100
+
101
+ const startsWith = stringSchemaObject?.startsWith;
102
+ const endsWith = stringSchemaObject?.endsWith;
103
+
104
+ const toLowerCase = stringSchemaObject?.toLowerCase;
105
+ const toUpperCase = stringSchemaObject?.toUpperCase;
106
+ const trim = stringSchemaObject?.trim;
107
+
108
+ // @ts-expect-error It is indeed potentially present
109
+ const includes = stringSchemaObject?.includes;
110
+ // @ts-expect-error It is indeed potentially present
111
+ const position = stringSchemaObject?.position;
112
+
113
+ // @ts-expect-error It is indeed potentially present
114
+ const regex = stringSchemaObject?.regex;
115
+ // @ts-expect-error It is indeed potentially present
116
+ const flags = stringSchemaObject?.flags;
117
+
118
+ /**
119
+ * @param {string} value
120
+ */
121
+ const checkValue = (value) => {
122
+ if (startsWith && !value.startsWith(startsWith)) {
123
+ return `Value doesn't start with expected: ${startsWith}`;
124
+ }
125
+ if (endsWith && !value.endsWith(endsWith)) {
126
+ return `Value doesn't end with expected: ${endsWith}`;
127
+ }
128
+ if (includes && !value.includes(includes, position ?? 0)) {
129
+ return `Value doesn't include the expected: ${includes}${
130
+ position ? ` after position: ${position}` : ''
131
+ }`;
132
+ }
133
+ if (regex && !(new RegExp(regex, flags ?? '')).test(value)) {
134
+ return `Value doesn't match regular expression: ${regex}${
135
+ flags ? ` with flags: ${flags}` : ''
136
+ }`;
137
+ }
138
+ if (kind) {
139
+ switch (kind) {
140
+ case 'ip':
141
+ // @ts-expect-error Is present
142
+ switch (stringSchemaObject?.version) {
143
+ case 'v4':
144
+ if (!ipv4Regex.test(value)) {
145
+ return `Value doesn't match IP v4 pattern.`;
146
+ }
147
+ break;
148
+ default:
149
+ if (!ipv6Regex.test(value)) {
150
+ return `Value doesn't match IP v6 pattern.`;
151
+ }
152
+ }
153
+ break;
154
+ case 'time':
155
+ // @ts-expect-error It is present
156
+ if (!timeRegex(stringSchemaObject).test(value)) {
157
+ return `Value does not match time/precision.`;
158
+ }
159
+ break;
160
+ case 'datetime':
161
+ // @ts-expect-error It is present
162
+ if (!datetimeRegex(stringSchemaObject).test(value)) {
163
+ return `Value does not match datetime/precision/offset/local`;
164
+ }
165
+ break;
166
+ case 'emoji':
167
+ if (!emojiRegex.test(value)) {
168
+ return `Value does not match emoji pattern`;
169
+ }
170
+ break;
171
+ case 'uuid':
172
+ if (!uuidRegex.test(value)) {
173
+ return `Value does not match uuid pattern`;
174
+ }
175
+ break;
176
+ case 'nanoid':
177
+ if (!nanoidRegex.test(value)) {
178
+ return `Value does not match nanoid pattern`;
179
+ }
180
+ break;
181
+ case 'cuid':
182
+ if (!cuidRegex.test(value)) {
183
+ return `Value does not match cuid pattern`;
184
+ }
185
+ break;
186
+ case 'cuid2':
187
+ if (!cuid2Regex.test(value)) {
188
+ return `Value does not match cuid2 pattern`;
189
+ }
190
+ break;
191
+ case 'ulid':
192
+ if (!ulidRegex.test(value)) {
193
+ return `Value does not match ulid pattern`;
194
+ }
195
+ break;
196
+ case 'duration':
197
+ if (!durationRegex.test(value)) {
198
+ return `Value does not match duration pattern`;
199
+ }
200
+ break;
201
+ case 'base64':
202
+ if (!base64Regex.test(value)) {
203
+ return `Value does not match base64 pattern`;
204
+ }
205
+ break;
206
+ default:
207
+ // 'email'|'url'|'date' should already be handled by the input element
208
+ break;
209
+ }
210
+ }
211
+ return null;
212
+ };
213
+
214
+ /**
215
+ * @param {string} value
216
+ */
217
+ const transform = (value) => {
218
+ if (toLowerCase) {
219
+ value = value.toLowerCase();
220
+ }
221
+ if (toUpperCase) {
222
+ value = value.toUpperCase();
223
+ }
224
+ if (trim) {
225
+ value = value.trim();
226
+ }
227
+ return value;
228
+ };
229
+
230
+ return ['div', {
231
+ dataset: {type: 'string'},
232
+ title: specificSchemaObject?.description ?? 'String'
233
+ }, [
234
+ [
235
+ // There is a `time` and `datetime-local` but they don't
236
+ // support milliseconds
237
+ 'email', 'url', 'date'
238
+ ].includes(kind)
239
+ ? ['input', {
240
+ $on: {
241
+ change () {
242
+ const that = /** @type {HTMLInputElement} */ (this);
243
+ that.value = transform(that.value);
244
+ const message = checkValue(that.value);
245
+ that.setCustomValidity(message ?? '');
246
+ that.reportValidity();
247
+ }
248
+ },
249
+ name: `${typeNamespace}-string`,
250
+ type: kind,
251
+ value: value ?? specificSchemaObject?.defaultValue ?? '',
252
+
253
+ // Form doesn't support for date
254
+ minlength: kind === 'date' ? undefined : minlength,
255
+ maxlength: kind === 'date' ? undefined : maxlength
256
+ }]
257
+ : ['textarea', {
258
+ $on: {
259
+ change () {
260
+ const that = /** @type {HTMLTextAreaElement} */ (this);
261
+ that.value = transform(that.value);
262
+ const message = checkValue(that.value);
263
+ that.setCustomValidity(message ?? '');
264
+ that.reportValidity();
265
+ }
266
+ },
267
+ name: `${typeNamespace}-string`,
268
+ disabled: isLiteral,
269
+ minlength, maxlength
270
+ }, [
271
+ isLiteral
272
+ ? specificSchemaObject?.value
273
+ : (value ?? specificSchemaObject?.defaultValue ?? '')
274
+ ]]
27
275
  ]];
28
276
  }
29
277
  };
@@ -0,0 +1,81 @@
1
+ import {$e} from '../utils/templateUtils.js';
2
+
3
+ /**
4
+ * @type {import('../types.js').TypeObject & {ct: number}}
5
+ */
6
+ const symbolType = {
7
+ option: ['Symbol'],
8
+ stringRegex: /^(?<symbolClassType>Symbol|Symbol.for)\("(?<innerContent>[^\\"]|\\\\|\\")*"\)$/u,
9
+ ct: 0,
10
+ valueMatch (x) {
11
+ return typeof x === 'symbol';
12
+ },
13
+ toValue (s, rootInfo) {
14
+ const {groups: {
15
+ symbolClassType
16
+ /* istanbul ignore next -- Should always be found */
17
+ } = {}} = /** @type {RegExpMatchArray} */ (
18
+ /** @type {import('../types.js').RootInfo} */ (rootInfo).match
19
+ );
20
+ const symbolClass = symbolClassType === 'Symbol'
21
+ ? Symbol
22
+ : Symbol.for.bind(Symbol);
23
+
24
+ return {value: symbolClass(s)};
25
+ },
26
+ getInput ({root}) {
27
+ return /** @type {HTMLInputElement} */ ($e(root, 'input.symbolInput'));
28
+ },
29
+ setValue ({root, value}) {
30
+ if (Symbol.keyFor(value)) {
31
+ /** @type {HTMLInputElement} */ (
32
+ $e(root, 'input[value="Symbol.for"]')
33
+ ).checked = true;
34
+ } else {
35
+ /** @type {HTMLInputElement} */ (
36
+ $e(root, 'input[value="Symbol"]')
37
+ ).checked = true;
38
+ }
39
+ this.getInput({root}).value = String(value).slice(7, -1);
40
+ },
41
+ getValue ({root}) {
42
+ const method = /** @type {HTMLInputElement} */ (
43
+ $e(root, 'input[value="Symbol"]')
44
+ ).checked
45
+ ? Symbol
46
+ : Symbol.for.bind(Symbol);
47
+ return method(this.getInput({root}).value);
48
+ },
49
+ viewUI ({value, specificSchemaObject}) {
50
+ return ['span', {
51
+ dataset: {type: 'symbol'},
52
+ title: specificSchemaObject?.description ?? '(a Symbol)'
53
+ }, [value]];
54
+ },
55
+ editUI ({typeNamespace, value = ''}) {
56
+ return ['div', {dataset: {type: 'symbol'}}, [
57
+ ['label', [
58
+ 'Symbol()',
59
+ ['input', {
60
+ type: 'radio', name: `${typeNamespace}-symbol${this.ct}`,
61
+ value: 'Symbol', checked: !value || !Symbol.keyFor(value)
62
+ }]
63
+ ]],
64
+ ['label', [
65
+ 'Symbol.for()',
66
+ ['input', {
67
+ type: 'radio', name: `${typeNamespace}-symbol${this.ct}`,
68
+ value: 'Symbol.for', checked: value && Boolean(Symbol.keyFor(value))
69
+ }]
70
+ ]],
71
+ ['br'],
72
+ ['input', {
73
+ className: 'symbolInput',
74
+ name: `${typeNamespace}-string`,
75
+ value: String(value).slice(7, -1)
76
+ }]
77
+ ]];
78
+ }
79
+ };
80
+
81
+ export default symbolType;
@@ -0,0 +1,39 @@
1
+ import arrayType from './arrayType.js';
2
+
3
+ /**
4
+ * @type {import('../types.js').TypeObject}
5
+ */
6
+ const tupleType = {
7
+ option: ['Tuple'],
8
+ array: true,
9
+ regexEndings: [',', ']'],
10
+ stringRegexBegin: /^Tuple\[/u,
11
+ stringRegexEnd: /^\]/u,
12
+ tuple: true,
13
+ valueMatch (x) {
14
+ return Array.isArray(x);
15
+ },
16
+ toValue (...args) {
17
+ return /** @type {import('../types.js').ToValue} */ (
18
+ arrayType.toValue
19
+ ).apply(this, args);
20
+ },
21
+ getValue (...args) {
22
+ return arrayType.getValue.apply(this, args);
23
+ },
24
+ getInput (...args) {
25
+ return arrayType.getInput.apply(this, args);
26
+ },
27
+ viewUI ({...args}) {
28
+ return arrayType.viewUI.call(this, {
29
+ ...args, type: 'tuple'
30
+ });
31
+ },
32
+ editUI ({...args}) {
33
+ return arrayType.editUI.call(this, {
34
+ ...args, type: 'tuple'
35
+ });
36
+ }
37
+ };
38
+
39
+ export default tupleType;
@@ -6,6 +6,9 @@ import {$e} from '../utils/templateUtils.js';
6
6
  const undefinedType = {
7
7
  stringRegex: /^undefined$/u,
8
8
  option: ['Explicit undefined'], // Explicit undefined only
9
+ valueMatch (x) {
10
+ return x === undefined;
11
+ },
9
12
  toValue (/* _s */) {
10
13
  return {value: undefined};
11
14
  },
@@ -14,20 +17,27 @@ const undefinedType = {
14
17
  this.toValue
15
18
  )('').value;
16
19
  },
17
- viewUI (/* {value} */) {
18
- return ['i', {dataset: {type: 'undef'}}, ['undefined']];
20
+ viewUI ({specificSchemaObject}) {
21
+ return ['i', {
22
+ dataset: {type: 'undef'},
23
+ title: specificSchemaObject?.description ?? '(an `undefined`)'
24
+ }, ['undefined']];
19
25
  },
20
26
  /* istanbul ignore next -- No dupe keys, array refs, or validation */
21
27
  getInput ({root}) {
22
28
  return /** @type {HTMLInputElement} */ ($e(root, 'input'));
23
29
  },
24
- editUI ({typeNamespace}) {
25
- return ['div', {dataset: {type: 'undef'}}, [
30
+ editUI ({typeNamespace, specificSchemaObject}) {
31
+ return ['div', {
32
+ dataset: {type: 'undef'},
33
+ title: specificSchemaObject?.description ?? 'Undefined'
34
+ }, [
26
35
  ['label', [
27
36
  'Undefined',
28
37
  ['input', {
29
38
  type: 'checkbox',
30
39
  name: `${typeNamespace}-undef`,
40
+ disabled: true,
31
41
  checked: true
32
42
  }]
33
43
  ]]
@@ -0,0 +1,48 @@
1
+ import {$e} from '../utils/templateUtils.js';
2
+
3
+ /**
4
+ * @type {import('../types.js').TypeObject}
5
+ */
6
+ const voidType = {
7
+ stringRegex: /^void$/u,
8
+ option: ['Void'],
9
+ valueMatch (x) {
10
+ return x === undefined;
11
+ },
12
+ toValue (/* _s */) {
13
+ return {value: undefined};
14
+ },
15
+ getValue () {
16
+ return /** @type {import('../types.js').ToValue} */ (
17
+ this.toValue
18
+ )('').value;
19
+ },
20
+ /* istanbul ignore next -- No dupe keys, array refs, or validation */
21
+ getInput ({root}) {
22
+ return /** @type {HTMLInputElement} */ ($e(root, 'input'));
23
+ },
24
+ viewUI ({specificSchemaObject}) {
25
+ return ['i', {
26
+ dataset: {type: 'void'},
27
+ title: specificSchemaObject?.description ?? '(a `void`)'
28
+ }, ['void']];
29
+ },
30
+ editUI ({typeNamespace, specificSchemaObject}) {
31
+ return ['div', {
32
+ dataset: {type: 'void'},
33
+ title: specificSchemaObject?.description ?? 'Void'
34
+ }, [
35
+ ['label', [
36
+ 'Void',
37
+ ['input', {
38
+ type: 'checkbox',
39
+ name: `${typeNamespace}-void`,
40
+ checked: true,
41
+ disabled: true
42
+ }]
43
+ ]]
44
+ ]];
45
+ }
46
+ };
47
+
48
+ export default voidType;