lightview 1.8.2 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/.codacy/cli.sh +149 -0
  2. package/.codacy/codacy.yaml +15 -0
  3. package/.github/instructions/codacy.instructions.md +72 -0
  4. package/.wranglerignore +21 -0
  5. package/README.md +1330 -19
  6. package/_headers +4 -0
  7. package/build.js +70 -0
  8. package/components/actions/button.js +151 -0
  9. package/components/actions/dropdown.js +120 -0
  10. package/components/actions/modal.js +146 -0
  11. package/components/actions/swap.js +118 -0
  12. package/components/daisyui.js +288 -0
  13. package/components/data-display/accordion.js +128 -0
  14. package/components/data-display/alert.js +112 -0
  15. package/components/data-display/avatar.js +170 -0
  16. package/components/data-display/badge.js +82 -0
  17. package/components/data-display/card.js +151 -0
  18. package/components/data-display/carousel.js +94 -0
  19. package/components/data-display/chart.js +220 -0
  20. package/components/data-display/chat.js +128 -0
  21. package/components/data-display/collapse.js +103 -0
  22. package/components/data-display/countdown.js +69 -0
  23. package/components/data-display/diff.js +111 -0
  24. package/components/data-display/kbd.js +65 -0
  25. package/components/data-display/loading.js +75 -0
  26. package/components/data-display/progress.js +79 -0
  27. package/components/data-display/radial-progress.js +88 -0
  28. package/components/data-display/skeleton.js +66 -0
  29. package/components/data-display/stats.js +159 -0
  30. package/components/data-display/table.js +146 -0
  31. package/components/data-display/timeline.js +146 -0
  32. package/components/data-display/toast.js +72 -0
  33. package/components/data-display/tooltip.js +74 -0
  34. package/components/data-input/checkbox.js +253 -0
  35. package/components/data-input/file-input.js +224 -0
  36. package/components/data-input/input.js +264 -0
  37. package/components/data-input/radio.js +338 -0
  38. package/components/data-input/range.js +204 -0
  39. package/components/data-input/rating.js +219 -0
  40. package/components/data-input/select.js +287 -0
  41. package/components/data-input/textarea.js +287 -0
  42. package/components/data-input/toggle.js +201 -0
  43. package/components/index.js +137 -0
  44. package/components/layout/divider.js +72 -0
  45. package/components/layout/drawer.js +142 -0
  46. package/components/layout/footer.js +100 -0
  47. package/components/layout/hero.js +109 -0
  48. package/components/layout/indicator.js +90 -0
  49. package/components/layout/join.js +78 -0
  50. package/components/layout/navbar.js +110 -0
  51. package/components/navigation/breadcrumbs.js +91 -0
  52. package/components/navigation/dock.js +103 -0
  53. package/components/navigation/menu.js +126 -0
  54. package/components/navigation/pagination.js +105 -0
  55. package/components/navigation/steps.js +89 -0
  56. package/components/navigation/tabs.css +177 -0
  57. package/components/navigation/tabs.js +123 -0
  58. package/components/theme/theme-switch.css +65 -0
  59. package/components/theme/theme-switch.js +177 -0
  60. package/docs/about.html +164 -0
  61. package/docs/api/computed.html +184 -0
  62. package/docs/api/effects.html +173 -0
  63. package/docs/api/elements.html +180 -0
  64. package/docs/api/enhance.html +225 -0
  65. package/docs/api/hypermedia.html +165 -0
  66. package/docs/api/index.html +178 -0
  67. package/docs/api/nav.html +18 -0
  68. package/docs/api/signals.html +136 -0
  69. package/docs/api/state.html +217 -0
  70. package/docs/assets/images/logo-favicon.svg +42 -0
  71. package/docs/assets/images/logo-static.svg +40 -0
  72. package/docs/assets/images/logo.svg +66 -0
  73. package/docs/assets/js/examplify.js +395 -0
  74. package/docs/assets/styles/site.css +1102 -0
  75. package/docs/assets/styles/themes.css +236 -0
  76. package/docs/components/accordion.html +439 -0
  77. package/docs/components/alert.html +528 -0
  78. package/docs/components/avatar.html +586 -0
  79. package/docs/components/badge.html +531 -0
  80. package/docs/components/breadcrumbs.html +278 -0
  81. package/docs/components/button.html +579 -0
  82. package/docs/components/card.html +561 -0
  83. package/docs/components/carousel.html +286 -0
  84. package/docs/components/chart-area.html +702 -0
  85. package/docs/components/chart-bar.html +782 -0
  86. package/docs/components/chart-column.html +735 -0
  87. package/docs/components/chart-line.html +794 -0
  88. package/docs/components/chart-pie.html +823 -0
  89. package/docs/components/chart.html +610 -15
  90. package/docs/components/chat.html +547 -0
  91. package/docs/components/checkbox.html +641 -0
  92. package/docs/components/collapse.html +536 -0
  93. package/docs/components/component-nav.html +53 -0
  94. package/docs/components/countdown.html +470 -0
  95. package/docs/components/diff.html +245 -0
  96. package/docs/components/divider.html +240 -0
  97. package/docs/components/dock.html +277 -0
  98. package/docs/components/drawer.html +515 -0
  99. package/docs/components/dropdown.html +479 -0
  100. package/docs/components/file-input.html +591 -0
  101. package/docs/components/footer.html +301 -0
  102. package/docs/components/gallery.html +504 -0
  103. package/docs/components/hero.html +264 -0
  104. package/docs/components/index.css +840 -0
  105. package/docs/components/index.html +735 -0
  106. package/docs/components/indicator.html +342 -0
  107. package/docs/components/input.html +644 -0
  108. package/docs/components/join.html +285 -0
  109. package/docs/components/kbd.html +322 -0
  110. package/docs/components/loading.html +521 -0
  111. package/docs/components/menu.html +461 -0
  112. package/docs/components/modal.html +639 -0
  113. package/docs/components/navbar.html +321 -0
  114. package/docs/components/pagination.html +279 -0
  115. package/docs/components/progress.html +514 -0
  116. package/docs/components/radial-progress.html +434 -0
  117. package/docs/components/radio.html +655 -0
  118. package/docs/components/range.html +611 -0
  119. package/docs/components/rating.html +642 -0
  120. package/docs/components/select.html +696 -0
  121. package/docs/components/sidebar-setup.js +93 -0
  122. package/docs/components/skeleton.html +447 -0
  123. package/docs/components/spinner.html +68 -0
  124. package/docs/components/stats.html +486 -0
  125. package/docs/components/steps.html +356 -0
  126. package/docs/components/swap.html +517 -0
  127. package/docs/components/switch.html +68 -0
  128. package/docs/components/table.html +668 -0
  129. package/docs/components/tabs.html +506 -0
  130. package/docs/components/text-input.html +68 -0
  131. package/docs/components/textarea.html +603 -0
  132. package/docs/components/timeline.html +485 -42
  133. package/docs/components/toast.html +474 -0
  134. package/docs/components/toggle.html +564 -0
  135. package/docs/components/tooltip.html +423 -0
  136. package/docs/examples/getting-started-example.html +40 -0
  137. package/docs/examples/index.html +93 -0
  138. package/docs/getting-started/index.html +739 -0
  139. package/docs/getting-started/reviews.html +23 -0
  140. package/docs/getting-started/reviews.odom +108 -0
  141. package/docs/getting-started/reviews.vdom +84 -0
  142. package/docs/index.html +132 -42
  143. package/docs/playground.html +416 -0
  144. package/docs/router.html +285 -0
  145. package/docs/styles/index.html +190 -0
  146. package/functions/_middleware.js +32 -0
  147. package/index.html +309 -0
  148. package/lightview-router.js +364 -0
  149. package/lightview-x.js +1577 -0
  150. package/lightview.js +659 -1200
  151. package/middleware/locale.js +25 -0
  152. package/middleware/markdown.js +44 -0
  153. package/middleware/notFound.js +37 -0
  154. package/package.json +27 -41
  155. package/watch.js +92 -0
  156. package/wrangler.toml +12 -0
  157. package/.idea/lightview.iml +0 -12
  158. package/.idea/modules.xml +0 -8
  159. package/.idea/vcs.xml +0 -6
  160. package/LICENSE +0 -21
  161. package/codepen-no-tabs-embed.css +0 -2
  162. package/docs/CNAME +0 -1
  163. package/docs/api.html +0 -674
  164. package/docs/blank.html +0 -10
  165. package/docs/comparedto.html +0 -89
  166. package/docs/components/chart-repl.html +0 -69
  167. package/docs/components/components.js +0 -113
  168. package/docs/components/contents.html +0 -17
  169. package/docs/components/gantt-repl.html +0 -61
  170. package/docs/components/gantt.html +0 -42
  171. package/docs/components/gauge-repl.html +0 -66
  172. package/docs/components/gauge.html +0 -20
  173. package/docs/components/orgchart-repl.html +0 -64
  174. package/docs/components/orgchart.html +0 -41
  175. package/docs/components/repl-as-src.html +0 -17
  176. package/docs/components/repl-repl.html +0 -95
  177. package/docs/components/repl.html +0 -527
  178. package/docs/components/timeline-repl.html +0 -72
  179. package/docs/components.html +0 -14
  180. package/docs/css/highlightjs.min.css +0 -9
  181. package/docs/css/tutorial.css +0 -35
  182. package/docs/examples/anchor.html +0 -11
  183. package/docs/examples/chart.html +0 -34
  184. package/docs/examples/counter.html +0 -26
  185. package/docs/examples/counter.test.mjs +0 -47
  186. package/docs/examples/counter2.html +0 -26
  187. package/docs/examples/directives.html +0 -79
  188. package/docs/examples/foreign.html +0 -50
  189. package/docs/examples/forgeinform.html +0 -98
  190. package/docs/examples/form.html +0 -61
  191. package/docs/examples/gauge.html +0 -18
  192. package/docs/examples/invalid-template-literals.html +0 -44
  193. package/docs/examples/medium/remote.html +0 -60
  194. package/docs/examples/message.html +0 -18
  195. package/docs/examples/nested.html +0 -11
  196. package/docs/examples/object-bound-form.html +0 -34
  197. package/docs/examples/remote-server.js +0 -51
  198. package/docs/examples/remote.html +0 -34
  199. package/docs/examples/remote.json +0 -1
  200. package/docs/examples/scratch.html +0 -69
  201. package/docs/examples/sensors/index.html +0 -44
  202. package/docs/examples/sensors/sensor-server.js +0 -30
  203. package/docs/examples/shared.html +0 -41
  204. package/docs/examples/template.html +0 -33
  205. package/docs/examples/timeline.html +0 -21
  206. package/docs/examples/todo.html +0 -40
  207. package/docs/examples/top.html +0 -10
  208. package/docs/examples/types.html +0 -94
  209. package/docs/examples/xor.html +0 -62
  210. package/docs/examples.html +0 -25
  211. package/docs/javascript/codejar.min.js +0 -8
  212. package/docs/javascript/highlightjs.min.js +0 -1173
  213. package/docs/javascript/isomorphic-git.js +0 -9
  214. package/docs/javascript/json5.min.js +0 -1
  215. package/docs/javascript/lightning-fs.js +0 -1
  216. package/docs/javascript/lightview.js +0 -1285
  217. package/docs/javascript/marked.min.js +0 -6
  218. package/docs/javascript/peerjs.min.js +0 -70
  219. package/docs/javascript/turndown.js +0 -973
  220. package/docs/javascript/types.js +0 -606
  221. package/docs/javascript/utils.js +0 -45
  222. package/docs/lightview.html +0 -63
  223. package/docs/old_index.html +0 -965
  224. package/docs/old_index.md +0 -1132
  225. package/docs/slidein.html +0 -51
  226. package/docs/tutorial/0-getting-started.html +0 -67
  227. package/docs/tutorial/1-intro-to-variables.html +0 -103
  228. package/docs/tutorial/10-template-components.html +0 -80
  229. package/docs/tutorial/11-linked-components.html +0 -76
  230. package/docs/tutorial/12-imported-components.html +0 -67
  231. package/docs/tutorial/13-input-binding.html +0 -94
  232. package/docs/tutorial/14-automatic-variable-creation.html +0 -74
  233. package/docs/tutorial/15-form-binding.html +0 -110
  234. package/docs/tutorial/16-if-directive.html +0 -60
  235. package/docs/tutorial/17-loop-directives.html +0 -83
  236. package/docs/tutorial/18-sanitizing-and-escaping-input.html +0 -79
  237. package/docs/tutorial/2-imported-and-exported-variables.html +0 -80
  238. package/docs/tutorial/3-data-types.html +0 -89
  239. package/docs/tutorial/4-extended-data-types.html +0 -83
  240. package/docs/tutorial/5-extended-functional-types.html +0 -96
  241. package/docs/tutorial/5.1-extended-functional-types.html +0 -79
  242. package/docs/tutorial/5.2-extended-functional-types.html +0 -70
  243. package/docs/tutorial/6-conventional-javascript.html +0 -75
  244. package/docs/tutorial/7-monitoring-with-observers.html +0 -107
  245. package/docs/tutorial/8-event-listeners.html +0 -65
  246. package/docs/tutorial/9-intro-to-components.html +0 -91
  247. package/docs/tutorial/contents.html +0 -32
  248. package/docs/tutorial/my-component.html +0 -29
  249. package/docs/tutorial/remote-value.json +0 -4
  250. package/docs/websiterepl.html +0 -46
  251. package/jest-puppeteer.config.js +0 -5
  252. package/jest.config.json +0 -12
  253. package/lightview.min.js +0 -1
  254. package/lightview_good.js +0 -1267
  255. package/lightview_optimized.js +0 -1274
  256. package/repl_hold.html +0 -320
  257. package/test/basic.html +0 -104
  258. package/test/basic.test.mjs +0 -315
  259. package/test/extended.html +0 -29
  260. package/test/extended.test.mjs +0 -448
  261. package/types.js +0 -607
  262. package/unsplash.key +0 -1
@@ -1,606 +0,0 @@
1
- const toJSON = (value) => {
2
- if([-Infinity,Infinity].includes(value)) return `@${value}`;
3
- if(typeof(value)==="number" && isNaN(value)) return "@NaN";
4
- if(value && typeof(value)==="object") {
5
- return Object.entries(value)
6
- .reduce((json,[key,value]) => {
7
- if(value && typeof(value)==="object" && value.toJSON) value = value.toJSON();
8
- json[key] = toJSON(value);
9
- return json;
10
- },Array.isArray(value) ? [] : {})
11
- }
12
- return value;
13
- };
14
- function reviver(property,value) {
15
- if(value==="@-Infinity") return -Infinity;
16
- if(value==="@Infinity") return Infinity;
17
- if(value==="@NaN") return NaN;
18
- return value;
19
- }
20
- const deepEqual = (a,b,matchType=deepEqual.LEFT, seen=new Set()) => {
21
- if(matchType===deepEqual.RIGHT) return deepEqual(b,a,deepEqual.LEFT,seen);
22
- if(matchType===deepEqual.COMMUTATIVE) return deepEqual(a,b,deepEqual.LEFT) && deepEqual(b,a,deepEqual.LEFT);
23
- if(a===b) return true;
24
- const type = typeof(a);
25
- if(type==="function" || type!==typeof(b) || (a && !b) || (b && !a)) return false;
26
- if(type==="number" && isNaN(a) && isNaN(b)) return true;
27
- if(a && type==="object") {
28
- if(seen.has(a)) return true;
29
- seen.add(a);
30
- if(a.constructor!==b.constructor || a.length!==b.length || a.size!==b.size) return false;
31
- if(a instanceof Date) a.getTime() === b.getTime();
32
- if(a instanceof RegExp) return a.toString() === b.toString();
33
- if(a instanceof Set) {
34
- for(const avalue of [...a]) {
35
- if(![...b].some((bvalue) => deepEqual(avalue,bvalue,matchType,seen))) return false;
36
- }
37
- return true;
38
- }
39
- if(a instanceof Map) {
40
- for(const [key,value] of [...a]) {
41
- if(!deepEqual(b.get(key),value,matchType,seen)) return false;
42
- }
43
- return true;
44
- }
45
- for(const key in a) {
46
- if(!deepEqual(a[key],b[key],matchType,seen)) return false;
47
- }
48
- return true;
49
- }
50
- return false;
51
- }
52
- deepEqual.LEFT = 1;
53
- deepEqual.COMMUTATIVE = 2;
54
- deepEqual.RIGHT = 3;
55
-
56
- function ValidityState(options) {
57
- if(!this || !(this instanceof ValidityState)) return new ValidityState(options);
58
- Object.assign(this,{
59
- valid:false,
60
- badInput:undefined,
61
- customError:undefined,
62
- patternMismatch:undefined,
63
- rangeUnderflow:undefined,
64
- rangeOverflow:undefined,
65
- typeMismatch:undefined,
66
- valueMissing:undefined,
67
- stepMistmatch:undefined,
68
- tooLong:undefined,
69
- tooShort:undefined
70
- },options);
71
- }
72
-
73
- function DataType(options) {
74
- if(!this || !(this instanceof DataType)) return new DataType(options);
75
- Object.assign(this,options);
76
- }
77
- DataType.prototype.toJSON = function() {
78
- return toJSON(this);
79
- }
80
-
81
- const tryParse = (value) => {
82
- try {
83
- return JSON.parse(value+"",reviver)
84
- } catch(e) {
85
-
86
- }
87
- }
88
-
89
- const ifInvalid = (variable) => {
90
- variable.validityState.type = typeof(variable.type)==="string" ? variable.type : variable.type.type;
91
- throw new TypeError(JSON.stringify(DataType(variable)));
92
- // or could return existing value variable.value
93
- // or could return nothing
94
- }
95
-
96
- const validateAny = function(value,variable) {
97
- if(value===undefined && variable.value===undefined) {
98
- return this.default;
99
- }
100
- if(this.required && value==null) {
101
- variable.validityState = ValidityState({valueMissing: true});
102
- } else {
103
- variable.validityState = ValidityState({valid:true});
104
- return value;
105
- }
106
- return this.whenInvalid(variable,value);
107
- }
108
- const any = ({required=false,whenInvalid = ifInvalid,...rest}) => { // ...rest allows use of property "default", which is otherwise reserved
109
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
110
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
111
- return {
112
- type: "any",
113
- required,
114
- whenInvalid,
115
- ...rest,
116
- validate: validateAny
117
- }
118
- }
119
- any.validate = validateAny;
120
- any.required = false;
121
-
122
- const validateArray = function(value,variable) {
123
- if(value===undefined && variable.value===undefined) {
124
- return this.default;
125
- }
126
- if(this.required && value==null) {
127
- variable.validityState = ValidityState({valueMissing: true});
128
- } else {
129
- let result = this.coerce && typeof(value)==="string" ? tryParse(value.startsWith("[") ? value : `[${value}]`) : value;
130
- if (!Array.isArray(result)) {
131
- if (value.includes(",")) result = value.split(",");
132
- }
133
- if(typeof(result)!=="object" || !(result instanceof Array || Array.isArray(result))) {
134
- variable.validityState = ValidityState({typeMismatch:true,value});
135
- } else if(result.length<this.minlength) {
136
- variable.validityState = ValidityState({tooShort:true,value});
137
- } else if(result.length>this.maxlength) {
138
- variable.validityState = ValidityState({tooLong:true,value});
139
- } else {
140
- variable.validityState = ValidityState({valid:true});
141
- return result;
142
- }
143
- }
144
- return this.whenInvalid(variable,value);
145
- }
146
- const array = ({coerce=false, required = false,whenInvalid = ifInvalid,maxlength=Infinity,minlength=0,...rest}={}) => {
147
- if(typeof(coerce)!=="boolean") throw new TypeError(`coerce, ${JSON.stringify(coerce)}, must be a boolean`);
148
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
149
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
150
- if(typeof(maxlength)!=="number") throw new TypeError(`maxlength, ${JSON.stringify(maxlength)}, must be a number`);
151
- if(typeof(minlength)!=="number") throw new TypeError(`minlength, ${JSON.stringify(minlength)}, must be a number`);
152
- if(rest.default!==undefined && (typeof(rest.default)!=="object" || !(rest.default instanceof Array || Array.isArray(rest.default)))) throw new TypeError(`default, ${rest.default}, must be an Array`);
153
- return {
154
- type: "array",
155
- coerce,
156
- required,
157
- whenInvalid,
158
- maxlength,
159
- minlength,
160
- ...rest,
161
- validate: validateArray
162
- }
163
- }
164
-
165
-
166
- const validateBoolean = function(value,variable) {
167
- if(value===undefined && variable.value===undefined) {
168
- return this.default;
169
- }
170
- if(variable.value===undefined) value = this.default;
171
- if(this.required && value==null) {
172
- variable.validityState = ValidityState({valueMissing: true});
173
- } else {
174
- const result = this.coerce ? tryParse(value) : value;
175
- if(typeof(result)!=="boolean") {
176
- variable.validityState = ValidityState({typeMismatch: true, value});
177
- } else {
178
- variable.validityState = ValidityState({valid:true});
179
- return result;
180
- }
181
- }
182
- return this.whenInvalid(variable,value);
183
- }
184
- const boolean = ({coerce=false,required=false, whenInvalid = ifInvalid,...rest}={}) =>{
185
- if(typeof(coerce)!=="boolean") throw new TypeError(`coerce, ${JSON.stringify(coerce)}, must be a boolean`);
186
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
187
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
188
- if(rest.default!==undefined && typeof(rest.default)!=="boolean") throw new TypeError(`default, ${rest.default}, must be a boolean`);
189
- return {
190
- type: "boolean",
191
- coerce,
192
- required,
193
- whenInvalid,
194
- ...rest,
195
- validate: validateBoolean
196
- }
197
- }
198
-
199
- const isDuration = (value) => {
200
- return parseDuration(value)!==undefined;
201
- }
202
- const durationMilliseconds = {
203
- ms: 1,
204
- s: 1000,
205
- m: 1000 * 60,
206
- h: 1000 * 60 * 60,
207
- d: 1000 * 60 * 60 * 24,
208
- w: 1000 * 60 * 60 * 24 * 7,
209
- mo: (1000 * 60 * 60 * 24 * 365.25)/12,
210
- q: (1000 * 60 * 60 * 24 * 365.25)/4,
211
- y: (1000 * 60 * 60 * 24 * 365.25)
212
- }
213
- const parseDuration = (value) => {
214
- if(typeof(value)==="number") return value;
215
- if(typeof(value)==="string") {
216
- const num = parseFloat(value),
217
- suffix = value.substring((num+"").length);
218
- if(typeof(num)==="number" && !isNaN(num) && suffix in durationMilliseconds) {
219
- return durationMilliseconds[suffix] * num;
220
- }
221
- }
222
- return null;
223
- }
224
-
225
- const validateDuration = function(value,variable) {
226
- const result = parseDuration(value);
227
- if(result==null && variable.value===undefined) {
228
- return parseDuration(this.default);
229
- }
230
- if(this.required && result==null) {
231
- variable.validityState = ValidityState({valueMissing: true});
232
- } else {
233
- if(typeof(result)!=="number") {
234
- variable.validityState = ValidityState({typeMismatch:true,value});
235
- } else if(isNaN(result)) {
236
- variable.validityState = ValidityState({badInput:true,value});
237
- } else if(this.min!=null && result<parseDuration(this.min)) {
238
- variable.validityState = ValidityState({rangeUnderflow:true,value});
239
- } else if(this.max!=null && result>parseDuration(this.max)) {
240
- variable.validityState = ValidityState({rangeOverflow:true,value});
241
- } else if(this.step!==null && (result % parseDuration(this.step)!==0)) {
242
- variable.validityState = ValidityState({rangeUnderflow:true,value});
243
- } else {
244
- variable.validityState = ValidityState({valid:true});
245
- return result;
246
- }
247
- }
248
- return this.whenInvalid(variable,value);
249
- }
250
- const duration = ({required = false,whenInvalid = ifInvalid,min=-Infinity,max=Infinity,step = 1,...rest}={}) => {
251
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
252
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
253
- if(min!=null && !parseDuration(min)) throw new TypeError(`min, ${JSON.stringify(min)}, must be a duration`);
254
- if(max!=null && !parseDuration(max)) throw new TypeError(`max, ${JSON.stringify(max)}, must be a duration`);
255
- if(step!=null && !parseDuration(step)) throw new TypeError(`step, ${JSON.stringify(step)}, must be a duration`);
256
- if(rest.default!==undefined && !parseDuration(rest.default)) throw new TypeError(`default, ${JSON.stringify(rest.default)}, must be a duration`);
257
- return {
258
- type: "duration",
259
- coerce: false,
260
- required,
261
- whenInvalid,
262
- min,
263
- max,
264
- step,
265
- ...rest,
266
- validate: validateDuration
267
- }
268
- }
269
- duration.parse = parseDuration;
270
-
271
- const validateNumber = function(value,variable) {
272
- if(value===undefined && variable.value===undefined) {
273
- return this.default;
274
- }
275
- if(this.required && value==null) {
276
- variable.validityState = ValidityState({valueMissing: true});
277
- } else {
278
- const result = this.coerce ? tryParse(value) : value;
279
- if(typeof(result)!=="number") {
280
- variable.validityState = ValidityState({typeMismatch:true,value});
281
- } else if(isNaN(result) && !this.allowNaN) {
282
- variable.validityState = ValidityState({badInput:true,value});
283
- } else if(this.min!=null && result<this.min && !(this.min===-Infinity && isNaN(result))) {
284
- variable.validityState = ValidityState({rangeUnderflow:true,value});
285
- } else if(this.max!=null && result>this.max && !(this.max===Infinity && isNaN(result))) {
286
- variable.validityState = ValidityState({rangeOverflow:true,value});
287
- } else if(this.step!=null && (result % this.step)!==0) {
288
- variable.validityState = ValidityState({rangeUnderflow:true,value});
289
- } else {
290
- variable.validityState = ValidityState({valid:true});
291
- return result;
292
- }
293
- }
294
- return this.whenInvalid(variable,value);
295
- }
296
- const number = ({coerce=false,required = false,whenInvalid = ifInvalid,min=-Infinity,max=Infinity,step,allowNaN = true,...rest}={}) => {
297
- if(typeof(coerce)!=="boolean") throw new TypeError(`coerce, ${JSON.stringify(coerce)}, must be a boolean`);
298
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
299
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
300
- if(min!=null && typeof(min)!=="number") throw new TypeError(`min, ${JSON.stringify(min)}, must be a number`);
301
- if(max!=null && typeof(max)!=="number") throw new TypeError(`max, ${JSON.stringify(max)}, must be a number`);
302
- if(step!=null && typeof(step)!=="number") throw new TypeError(`step, ${JSON.stringify(step)}, must be a number`);
303
- if(typeof(allowNaN)!=="boolean") throw new TypeError(`step, ${JSON.stringify(allowNaN)}, must be a boolean`);
304
- if(rest.default!==undefined && typeof(rest.default)!=="number") throw new TypeError(`default, ${JSON.stringify(rest.default)}, must be a number`);
305
- return {
306
- type: "number",
307
- coerce,
308
- required,
309
- whenInvalid,
310
- min,
311
- max,
312
- step,
313
- allowNaN,
314
- ...rest,
315
- validate: validateNumber
316
- }
317
- }
318
-
319
-
320
- const validateObject = function(value,variable) {
321
- if(value===undefined && variable.value===undefined) {
322
- return this.default;
323
- }
324
- if(this.required && value==null) {
325
- variable.validityState = ValidityState({valueMissing: true});
326
- } else {
327
- const result = this.coerce ? tryParse(value) : value;
328
- if(typeof(result)!=="object") {
329
- variable.validityState = ValidityState({typeMismatch:true,value});
330
- } else {
331
- variable.validityState = ValidityState({valid:true});
332
- return result;
333
- }
334
- }
335
- return this.whenInvalid(variable,value);
336
- }
337
- const object = ({coerce=false, required = false,whenInvalid = ifInvalid,...rest}={}) => {
338
- if(typeof(coerce)!=="boolean") throw new TypeError(`coerce, ${JSON.stringify(coerce)}, must be a boolean`);
339
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
340
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
341
- if(rest.default!==undefined && typeof(rest.default)!=="object") throw new TypeError(`default, ${rest.default}, must be of type object`);
342
- return {
343
- type: "object",
344
- coerce,
345
- required,
346
- whenInvalid,
347
- ...rest,
348
- validate: validateObject
349
- }
350
- }
351
-
352
-
353
- const validateString = function(value,variable) {
354
- if(value===undefined && variable.value===undefined) {
355
- return this.default;
356
- }
357
- if(this.required && value==null) {
358
- variable.validityState = ValidityState({valueMissing: true});
359
- } else {
360
- const result = this.coerce ? value+"" : value;
361
- if(typeof(result)!=="string") {
362
- variable.validityState = ValidityState({typeMismatch:true,value});
363
- } else if(result.length<this.minlength) {
364
- variable.validityState = ValidityState({tooShort:true,value});
365
- } else if(result.length>this.maxlength) {
366
- variable.validityState = ValidityState({tooLong:true,value});
367
- } else {
368
- variable.validityState = ValidityState({valid:true});
369
- return result;
370
- }
371
- }
372
- return this.whenInvalid(variable,value);
373
- }
374
- const string = ({coerce=false, required = false,whenInvalid = ifInvalid, maxlength = Infinity, minlength = 0, pattern,...rest}={}) => {
375
- if(typeof(coerce)!=="boolean") throw new TypeError(`coerce, ${JSON.stringify(coerce)}, must be a boolean`);
376
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
377
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
378
- if(typeof(maxlength)!=="number") throw new TypeError(`maxlength, ${JSON.stringify(maxlength)}, must be a number`);
379
- if(typeof(minlength)!=="number") throw new TypeError(`minlength, ${JSON.stringify(minlength)}, must be a number`);
380
- if(pattern && (typeof(pattern)!=="object" || !(pattern instanceof RegExp))) throw new TypeError(`pattern, ${pattern}, must be a RegExp`);
381
- if(rest.default!==undefined && typeof(rest.default)!=="string") throw new TypeError(`default, ${rest.default}, must be a string`);
382
- return {
383
- type: "string",
384
- coerce,
385
- required,
386
- whenInvalid,
387
- maxlength,
388
- minlength,
389
- ...rest,
390
- validate: validateString
391
- }
392
- }
393
-
394
- const html = (...args) => string(...args);
395
- html.safe = true;
396
-
397
- const css = (...args) => string(...args);
398
- css.safe = true;
399
-
400
- const script = (...args) => string(...args);
401
- script.safe = true;
402
-
403
-
404
- const validateSymbol = function(value,variable) {
405
- if(value===undefined && variable.value===undefined) {
406
- return this.default;
407
- }
408
- if(this.required && value==null) {
409
- variable.validityState = ValidityState({valueMissing: true});
410
- } else {
411
- const result = !!(this.coerce && typeof(value)!=="symbol" ? Symbol(value+"") : value);
412
- if(typeof(result)!=="symbol") {
413
- variable.validityState = ValidityState({typeMismatch: true, value});
414
- } else {
415
- variable.validityState = ValidityState({valid:true});
416
- return result;
417
- }
418
- }
419
- return this.whenInvalid(variable,value);
420
- }
421
- const symbol = ({coerce=false,required=false, whenInvalid = ifInvalid,...rest}={}) =>{
422
- if(typeof(coerce)!=="boolean") throw new TypeError(`coerce, ${JSON.stringify(coerce)}, must be a boolean`);
423
- if(typeof(required)!=="boolean") throw new TypeError(`required, ${JSON.stringify(required)}, must be a boolean`);
424
- if(typeof(whenInvalid)!=="function") throw new TypeError(`whenInvalid, ${whenInvalid}, must be a function`);
425
- if(rest.default!==undefined && typeof(rest.default)!=="symbol") throw new TypeError(`default, ${rest.default}, must be a symbol`);
426
- return {
427
- type: "symbol",
428
- coerce,
429
- required,
430
- whenInvalid,
431
- ...rest,
432
- validate: validateSymbol
433
- }
434
- }
435
-
436
- const remoteProxy = ({json, variable,config, reactive, component}) => {
437
- const type = typeof (config);
438
- return new Proxy(json, {
439
- get(target,property) {
440
- if(property==="__remoteProxytarget__") return json;
441
- return target[property];
442
- },
443
- async set(target, property, value) {
444
- if(value && typeof(value)==="object" && value instanceof Promise) value = await value;
445
- const oldValue = target[property];
446
- if (oldValue !== value) {
447
- let remotevalue;
448
- if (type === "string") {
449
- const href = new URL(config,window.location.href).href;
450
- remotevalue = patch({target,property,value,oldValue},href,variable);
451
- } else if(config && type==="object") {
452
- let href;
453
- if(config.path) href = new URL(config.path,window.location.href).href;
454
- if(!config.patch) {
455
- if(!href) throw new Error(`A remote path is required is no put function is provided for remote data`)
456
- config.patch = patch;
457
- }
458
- remotevalue = config.patch({target,property,value,oldValue},href,variable);
459
- }
460
- if(remotevalue) {
461
- await remotevalue.then((newjson) => {
462
- if (newjson && typeof (newjson) === "object" && reactive) {
463
- const target = variable.value?.__reactorProxyTarget__ ? json : variable.value;
464
- Object.entries(newjson).forEach(([key,newValue]) => {
465
- if(target[key]!==newValue) target[key] = newValue;
466
- })
467
- Object.keys(target).forEach((key) => {
468
- if(!(key in newjson)) delete target[key];
469
- });
470
- if(variable.value?.__reactorProxyTarget__) {
471
- const dependents = variable.value.__dependents__,
472
- observers = dependents[property] || [];
473
- [...observers].forEach((f) => {
474
- if (f.cancelled) dependents[property].delete(f);
475
- else f();
476
- })
477
- }
478
- } else {
479
- component.setVariableValue(variable.name,newjson)
480
- //variable.value = json;
481
- }
482
- })
483
- }
484
- }
485
- return true;
486
- }
487
- })
488
- }
489
-
490
- const patch = ({target,property,value,oldValue},href,variable) => {
491
- return fetch(href, {
492
- method: "PATCH",
493
- body: JSON.stringify({property,value,oldValue}),
494
- headers: {
495
- "Content-Type": "application/json"
496
- }
497
- }).then((response) => {
498
- if (response.status < 400) return response.json();
499
- })
500
- }
501
-
502
- const get = (href,variable) => {
503
- return fetch(href)
504
- .then((response) => {
505
- if (response.status < 400) return response.json();
506
- })
507
- }
508
-
509
- const put = (href,variable) => {
510
- return fetch(href, {
511
- method: "PUT",
512
- body: JSON.stringify(variable.value),
513
- headers: {
514
- "Content-Type": "application/json"
515
- }
516
- }).then((response) => {
517
- if (response.status === 200) return response.json();
518
- })
519
- }
520
-
521
- const handleRemote = async ({variable, functionalType, config=functionalType, component},doput) => {
522
- let value;
523
- if(!config.path) config.path = `./${variable.name}`;
524
- if(config.path.endsWith("/")) config.path = `${config.path}${variable.name}`;
525
- const href = new URL(config.path,new URL(config.base.replace("blob:","")).href).href;
526
- if(!config.get || !config.put) {
527
- if(!href) throw new Error(`A remote path is required if no put function is provided for remote data`)
528
- if(!config.get) config.get = get;
529
- if(!config.put && variable.reactive) config.put = put;
530
- }
531
- let areequal;
532
- value = (doput
533
- ? (areequal = deepEqual(variable.value,config.previousValue,deepEqual.COMMUTATIVE)) ? variable.value : config.put(href,variable)
534
- : config.get(href,variable));
535
- if(config.ttl && !doput && !config.intervalId) {
536
- config.intervalId = setInterval(async () => {
537
- await handleRemote({variable, config, component});
538
- //schedule();
539
- },config.ttl);
540
- }
541
- if(variable.value===undefined) variable.value = value;
542
- if(value && !areequal) {
543
- const json = config.previousValue = await value;
544
- if (json && typeof (json) === "object" && variable.reactive) {
545
- component.setVariableValue(variable.name,remoteProxy({json, variable,config, component}));
546
- // variable.value = remoteProxy({json, variable,config, component});
547
- } else {
548
- component.setVariableValue(variable.name,json);
549
- }
550
- }
551
- }
552
-
553
- const remote = (config,base=document.baseURI||window.location.href) => {
554
- if(typeof(config)==="string") config = {path:config};
555
- config.base = base;
556
- return {
557
- config:{...config},
558
- handleRemote
559
- }
560
- }
561
-
562
- const shared = () => {
563
- return {
564
- init({variable, component}) {
565
- const name = variable.name,
566
- set = variable.set || (() => {});
567
- variable.shared = true;
568
- variable.set = function(newValue) {
569
- set(newValue);
570
- if(this.shared) { // still shared
571
- component.siblings.forEach((instance) => {
572
- const svariable = instance.vars[name];
573
- if(svariable?.shared) {
574
- instance.setVariableValue(name, newValue);
575
- }
576
- });
577
- }
578
- }
579
- // initialize
580
- component.siblings.forEach((instance) => {
581
- if(instance===component) return;
582
- const svariable = instance.vars[name];
583
- if(svariable?.shared) {
584
- if(variable.value==null) {
585
- if(svariable.value!=null) variable.value = instance.vars[name].value
586
- } else instance.setVariableValue(name, variable.value);
587
- }
588
- });
589
- }
590
- }
591
- }
592
-
593
- const observed = () => {
594
- return {
595
- init({variable, component,coerce}) {
596
- const name = variable.name;
597
- variable.value = component.hasAttribute(name) ? coerce(component.getAttribute(name), variable.type) : variable.value;
598
- variable.observed = true;
599
- component.observedAttributes.add(name);
600
- }
601
- }
602
- }
603
-
604
- const remoteGenerator = handleRemote;
605
-
606
- export {ValidityState,any,array,boolean,duration,number,object,remote,shared,observed,remoteGenerator,string,symbol,reviver,html,css,script}
@@ -1,45 +0,0 @@
1
- function processMarkdown() {
2
- marked.setOptions({
3
- renderer: new marked.Renderer(),
4
- highlight: function(code, lang) {
5
- const language = hljs.getLanguage(lang) ? lang : 'plaintext';
6
- return hljs.highlight(code, { language }).value;
7
- },
8
- langPrefix: 'hljs language-', // highlight.js css expects a top-level 'hljs' class.
9
- pedantic: false,
10
- gfm: true,
11
- breaks: false,
12
- sanitize: false,
13
- smartLists: true,
14
- smartypants: false,
15
- xhtml: false
16
- });
17
- [...document.querySelectorAll(".markdown")].forEach((el) => {
18
- el.innerHTML = marked.parse(el.innerHTML);
19
- [...el.querySelectorAll(".hljs")].forEach((el) => {
20
- [...el.childNodes].forEach((node) => {
21
- if(node.nodeType===Node.TEXT_NODE) {
22
- if(["&lt;","&gt;","&amp;"].some((entity) => node.data.includes(entity))) {
23
- node.data = node.data.replaceAll(/&lt;/g,"<")
24
- .replaceAll(/&gt;/g,">")
25
- .replaceAll(/&amp;/g,"&");
26
- }
27
- }
28
- })
29
-
30
- })
31
- });
32
- }
33
-
34
- function ariaPatch() {
35
- [...document.body.querySelectorAll("input[name]")].forEach((input) => {
36
- if(input.id) {
37
- if(!document.querySelector(`label[for=${input.id}]`)) {
38
- const label = document.createElement("label");
39
- label.innerText = input.getAttribute("name");
40
- label.before(input);
41
- }
42
- }
43
- })
44
- // <meta name="viewport" content="width=device-width, initial-scale=1">
45
- }