solarite 0.1.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 (63) hide show
  1. package/build/build.bat +3 -0
  2. package/build/build.js +139 -0
  3. package/build/lib/rollup.min.js +11 -0
  4. package/build/lib/source-map.min.js +1 -0
  5. package/build/lib/terser.min.js +1 -0
  6. package/dist/Solarite-debug.js +4143 -0
  7. package/dist/Solarite.js +3740 -0
  8. package/dist/Solarite.min.js +4 -0
  9. package/docs/index.md +423 -0
  10. package/docs/js/Playground.js +184 -0
  11. package/docs/js/codemirror/codemirror6.js +32036 -0
  12. package/docs/js/codemirror/themeSolarIce.js +312 -0
  13. package/docs/js/documentation.js +32 -0
  14. package/docs/js/ui/CodeEditor.js +840 -0
  15. package/docs/js/ui/DarkToggle.js +52 -0
  16. package/docs/js/ui/FlexResizer.js +142 -0
  17. package/docs/js/util/Draggable2.js +151 -0
  18. package/docs/js/util/Errors.js +9 -0
  19. package/docs/js/util/Html.js +147 -0
  20. package/docs/js/util/Icons.js +623 -0
  21. package/docs/js/util/Input.js +253 -0
  22. package/docs/js/util/Util.js +88 -0
  23. package/docs/js/util/delve.js +43 -0
  24. package/docs/media/FiraCode400.woff2 +0 -0
  25. package/docs/media/cabin-latin-700.woff2 +0 -0
  26. package/docs/media/documentation.css +93 -0
  27. package/docs/media/eternium.css +1123 -0
  28. package/docs/media/solarite-machine.webp +0 -0
  29. package/index.html +325 -0
  30. package/package.json +33 -0
  31. package/readme.md +3 -0
  32. package/src/solarite/ExprPath.js +554 -0
  33. package/src/solarite/MultiValueMap.js +65 -0
  34. package/src/solarite/NodeGroup.js +706 -0
  35. package/src/solarite/NodeGroupManager.js +582 -0
  36. package/src/solarite/Shell.js +307 -0
  37. package/src/solarite/Solarite.js +19 -0
  38. package/src/solarite/Template.js +85 -0
  39. package/src/solarite/Util.js +264 -0
  40. package/src/solarite/createSolarite.js +267 -0
  41. package/src/solarite/getArg.js +99 -0
  42. package/src/solarite/hash.js +101 -0
  43. package/src/solarite/r.js +143 -0
  44. package/src/solarite/udomdiff.js +233 -0
  45. package/src/solarite/watch.js +302 -0
  46. package/src/solarite/watch2.js +439 -0
  47. package/src/unused/FastLookupArray.js +54 -0
  48. package/src/unused/Hashes.js +339 -0
  49. package/src/unused/InUse.test.js +92 -0
  50. package/src/unused/InUseMap.js +98 -0
  51. package/src/unused/LinkedList.js +117 -0
  52. package/src/unused/LinkedList.test.js +115 -0
  53. package/src/unused/Perf.js +47 -0
  54. package/src/unused/Template.js +108 -0
  55. package/src/util/Errors.js +9 -0
  56. package/src/util/Util.js +88 -0
  57. package/src/util/delve.js +43 -0
  58. package/tests/Benchmark.test.js +319 -0
  59. package/tests/NodeGroup.test.js +115 -0
  60. package/tests/Shell.test.js +75 -0
  61. package/tests/Solarite.test.js +2896 -0
  62. package/tests/Testimony.js +602 -0
  63. package/tests/index.html +75 -0
@@ -0,0 +1,115 @@
1
+ import Testimony, {assert} from "../../tests/Testimony.js";
2
+ import LinkedList from "./LinkedList.js";
3
+
4
+ Testimony.test('LinkedList.constructor with Array input', () => {
5
+ const linkedList = new LinkedList(['A', 'B', 'C']);
6
+ assert.eq([...linkedList], ['A', 'B', 'C']);
7
+ });
8
+
9
+ Testimony.test('LinkedList.constructor with LinkedList input', () => {
10
+ const originalList = new LinkedList(['X', 'Y', 'Z']);
11
+ const copiedList = new LinkedList(originalList);
12
+ assert.eq([...copiedList], ['X', 'Y', 'Z']);
13
+ });
14
+
15
+ Testimony.test('LinkedList.constructor with mixed input', () => {
16
+ const originalList = new LinkedList(['D', 'E']);
17
+ const extendedList = new LinkedList([...originalList, 'F', 'G']);
18
+ assert.eq([...extendedList], ['D', 'E', 'F', 'G']);
19
+ });
20
+
21
+ Testimony.test('LinkedList.constructor with no input', () => {
22
+ const emptyList = new LinkedList();
23
+ assert.eq([...emptyList], []);
24
+ });
25
+
26
+
27
+ Testimony.test('LinkedList.push', () => {
28
+ const linkedList = new LinkedList();
29
+ linkedList.push("A");
30
+ linkedList.push("B");
31
+ assert.eq([...linkedList], ['A', 'B']);
32
+ });
33
+
34
+ Testimony.test('LinkedList.unshift', () => {
35
+ const linkedList = new LinkedList();
36
+ linkedList.unshift("B");
37
+ linkedList.unshift("A");
38
+ assert.eq([...linkedList], ['A', 'B']);
39
+ });
40
+
41
+ Testimony.test('LinkedList.shift', () => {
42
+ const linkedList = new LinkedList();
43
+ linkedList.push("A");
44
+ linkedList.push("B");
45
+ linkedList.shift();
46
+ assert.eq([...linkedList], ['B']);
47
+ linkedList.shift();
48
+ assert.eq([...linkedList], []);
49
+ });
50
+
51
+ Testimony.test('LinkedList.pop', () => {
52
+ const linkedList = new LinkedList();
53
+ linkedList.push("A");
54
+ linkedList.push("B");
55
+ linkedList.pop();
56
+ assert.eq([...linkedList], ['A']);
57
+ linkedList.pop();
58
+ assert.eq([...linkedList], []);
59
+ });
60
+
61
+ Testimony.test('LinkedList.slice', () => {
62
+ const linkedList = new LinkedList();
63
+ linkedList.push("A");
64
+ linkedList.push("B");
65
+ linkedList.push("C");
66
+ const subList = linkedList.slice("A", "B");
67
+ assert.eq([...subList], ['A', 'B']);
68
+ });
69
+
70
+ Testimony.test('LinkedList._splice', () => {
71
+ const linkedList = new LinkedList();
72
+ linkedList.push("A");
73
+ linkedList.push("B");
74
+ linkedList.splice("A", null, ["X", "Y"]);
75
+ assert.eq([...linkedList], ['A', 'X', 'Y', 'B']);
76
+ linkedList.splice("X", "Y");
77
+ assert.eq([...linkedList], ['B']);
78
+ });
79
+
80
+
81
+
82
+
83
+ function buildData(count = rowCount) {
84
+ function _random(max) {
85
+ return Math.round(Math.random()*1000)%max;
86
+ }
87
+
88
+ var adjectives = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"];
89
+ var colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
90
+ var nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"];
91
+ var data = [];
92
+ for (let i=0; i<count; i++)
93
+ data.push({id: i, label: adjectives[_random(adjectives.length)] + " " + colours[_random(colours.length)] + " " + nouns[_random(nouns.length)] });
94
+ return data;
95
+ }
96
+
97
+
98
+ Testimony.test('LinkedList.benchmark', () => {
99
+
100
+ let data = buildData(10_000)
101
+ let start = performance.now()
102
+ let list = new LinkedList(data);
103
+ console.log(performance.now() - start)
104
+
105
+ start = performance.now()
106
+ let i = 0;
107
+ for (let item in list) {
108
+ i++;
109
+ }
110
+ console.log(i)
111
+ console.log(performance.now() - start)
112
+
113
+
114
+
115
+ });
@@ -0,0 +1,47 @@
1
+ var Perf = {
2
+ _timers: {},
3
+
4
+ /**
5
+ * Start a timer with a given name.
6
+ * @param timerName {string}
7
+ */
8
+ start(timerName) {
9
+ if (!Perf._timers[timerName]) {
10
+ Perf._timers[timerName] = {
11
+ startTime: null,
12
+ elapsedTime: 0
13
+ };
14
+ }
15
+ Perf._timers[timerName].startTime = performance.now();
16
+ },
17
+
18
+ /**
19
+ * Stop a timer with a given name and calculate the elapsed time.
20
+ * @param timerName {string}
21
+ */
22
+ stop(timerName) {
23
+ if (Perf._timers[timerName] && Perf._timers[timerName].startTime !== null) {
24
+ let stopTime = performance.now();
25
+ Perf._timers[timerName].elapsedTime += stopTime - Perf._timers[timerName].startTime;
26
+ Perf._timers[timerName].startTime = null; // Reset start time
27
+ }
28
+ },
29
+
30
+ /**
31
+ * Get the total time elapsed for each timer.
32
+ * @return {string[]}
33
+ */
34
+ getReport() {
35
+ let report = [];
36
+ for (let timerName in Perf._timers) {
37
+ report.push(`${timerName}: ${Perf._timers[timerName].elapsedTime.toFixed(2)} ms`);
38
+ }
39
+ return report;
40
+ },
41
+
42
+ clear() {
43
+ this._timers = {};
44
+ }
45
+ }
46
+
47
+ export default Perf;
@@ -0,0 +1,108 @@
1
+ import getObjectId from "./getObjectId.js";
2
+
3
+ import {memoize, hashObject, hashObject64, hash64Cache, hashObjectJson, getObjectId3} from "./Util.js";
4
+
5
+ let htmlMap = new WeakMap();
6
+
7
+ /**
8
+ * version of the template class that still has the old memoize function, If I ever want to compare hashing speed again.
9
+ */
10
+ export default class Template {
11
+
12
+ /** @type {string[]} Html strings. Stored externally from object to speed up JSON serialization. */
13
+ //get html() { return htmlMap.get(this) }
14
+
15
+
16
+ /** @type {(Template|string|function)|(Template|string|function)[]} Evaulated expressions. */
17
+ exprs = []
18
+
19
+ html = [];
20
+
21
+ hashedFields;
22
+
23
+ /**
24
+ *
25
+ * @param htmlStrings {string}
26
+ * @param exprs {*[]} */
27
+ constructor(htmlStrings, exprs) {
28
+ //htmlMap.set(this, htmlStrings)
29
+ this.html = htmlStrings;
30
+ this.exprs = exprs;
31
+
32
+ this.hashedFields = [getObjectId(htmlStrings), exprs]
33
+
34
+ //#IFDEV
35
+ Object.defineProperty(this, 'debug', {
36
+ get() {
37
+ return this.memoize();
38
+ }
39
+ })
40
+ //#ENDIF
41
+ }
42
+
43
+ /**
44
+ * Called by JSON.serialize when it encounters a Template.
45
+ * This prevents the hashed version from being too large.
46
+ * @returns {*}
47
+ */
48
+ toJSON() {
49
+ return this.hashedFields
50
+ }
51
+
52
+ memoize() {
53
+
54
+ // Slower
55
+ // let result2 = hashObject64(this)
56
+ // return result2[0].toString(16) + result2[1].toString(16);
57
+
58
+ // This version is slower but includes the full html in the template and can help with debugging:
59
+ //#IFDEV
60
+ // let exprLength = this.exprs.length;
61
+ // let l = this.html.length + exprLength;
62
+ // let result = new Array(l);
63
+ // for (let i=0; i<exprLength; i++) {
64
+ // result[i*2] = this.html[i];
65
+ // result[i*2+1] = '${' + s(this.exprs[i]) + '}'
66
+ // }
67
+ // result[result.length-1] = this.html[this.html.length-1];
68
+ //
69
+ // return result.join('')
70
+ //#ENDIF
71
+
72
+ // Speed up most common case:
73
+ if (this.exprs.length === 1)
74
+ return memoizeValue(this.exprs[0]) + '\f' + this.htmlId // \f is the "Form feed" control character, unlikely to be usedin regular text.
75
+
76
+ let exprLength = this.exprs.length;
77
+ let result = new Array(exprLength+1);
78
+ let exprs = this.exprs;
79
+ for (let i=0; i<exprLength; i++) {
80
+ result[i] = memoizeValue(exprs[i])
81
+ }
82
+ result[result.length] = this.htmlId;
83
+
84
+ return result.join('\f')
85
+ }
86
+
87
+ getCloseKey() {
88
+ // Use the joined html when debugging?
89
+ //return '@'+this.html.join('|')
90
+
91
+ return '@'+this.hashedFields[0];
92
+ }
93
+ }
94
+
95
+
96
+
97
+
98
+ function memoizeValue(val) {
99
+ if (typeof val === 'string')
100
+ return val;
101
+ else if (Array.isArray(val))
102
+ return '[' + val.map(v => memoizeValue(v)) + `]`; // join(',') is implicitly called here.
103
+ else if (val && val.memoize) // is another Template
104
+ return 'T('+val.memoize()+')'
105
+ else
106
+ return memoize(val); // TODO: This might not differentiate between 1 and '1'
107
+
108
+ }
@@ -0,0 +1,9 @@
1
+ //#IFDEV
2
+ /*@__NO_SIDE_EFFECTS__*/
3
+ export function assert(val) {
4
+ if (!val) {
5
+ debugger;
6
+ throw new Error('Assertion failed: ' + val);
7
+ }
8
+ }
9
+ //#ENDIF
@@ -0,0 +1,88 @@
1
+
2
+
3
+
4
+ /**
5
+ * @typedef {Array|function(...*)} Callbacks
6
+ * @property {function(function)} push
7
+ * @property {function()} remove
8
+ * @property {function()} pause
9
+ * @property {function()} resume
10
+ * */
11
+
12
+
13
+ /**
14
+ * A place for functions that have no other home. */
15
+ var Util = {
16
+
17
+ /**
18
+ * Create an array-like object that stores a group of callbacks.
19
+ * Supports all array functions and properties like push() and .length.
20
+ * Can be called directly.
21
+ *
22
+ * @param functions {function[]}
23
+ * @return {Callbacks|function}
24
+ *
25
+ * @example
26
+ * var c = Util.callback();
27
+ * var f = () => console.log(3);
28
+ * c.push(f);
29
+ * c();
30
+ * c.remove(f);
31
+ * c();
32
+ */
33
+ callback(...functions) {
34
+ var paused = false;
35
+
36
+ // Make it callable. When we call it, call all callbacks() with the given args.
37
+ let result = async function(...args) {
38
+ let result2 = [];
39
+ if (!paused)
40
+ for (let i=0; i<result.length; i++)
41
+ result2.push(result[i](...args));
42
+ return await Promise.all(result2);
43
+ };
44
+
45
+ // Make it iterable.
46
+ result[Symbol.iterator] = function() {
47
+ let index = 0;
48
+ return {
49
+ next: () => index < result.length
50
+ ? {value: result[index++], done: false}
51
+ : {done: true}
52
+ };
53
+ };
54
+
55
+ // Use properties from Array
56
+ for (let prop of Object.getOwnPropertyNames(Array.prototype))
57
+ if (prop !== 'length' && prop !== 'constructor')
58
+ result[prop] = Array.prototype[prop];
59
+
60
+ result.l = 0; // Internal length
61
+ Object.defineProperty(result, 'length', {
62
+ get() { return result.l },
63
+ set(val) { result.l = val}
64
+ });
65
+
66
+ // Add the remove() function.
67
+ result.remove = func => {
68
+ let idx = result.findIndex(item => item === func);
69
+ if (idx !== -1)
70
+ result.splice(idx, 1);
71
+ };
72
+ result.pause = () => paused = true;
73
+
74
+ result.resume = () => paused = false;
75
+
76
+ // Add initial functions
77
+ for (let f of functions)
78
+ result.push(f);
79
+
80
+ return result;
81
+ },
82
+
83
+
84
+
85
+ };
86
+
87
+
88
+ export default Util;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Follow a path into an object.
3
+ * @param obj {object}
4
+ * @param path {string[]}
5
+ * @param createVal {*} If set, non-existant paths will be created and value at path will be set to createVal.
6
+ * @return {*} The value, or undefined if it can't be reached. */
7
+ export default function delve(obj, path, createVal = delveDontCreate) {
8
+ let isCreate = createVal !== delveDontCreate;
9
+
10
+ let len = path.length;
11
+ if (!obj && !isCreate && len)
12
+ return undefined;
13
+
14
+ let i = 0;
15
+ for (let srcProp of path) {
16
+
17
+ // If the path is undefined and we're not to the end yet:
18
+ if (obj[srcProp] === undefined) {
19
+
20
+ // If the next index is an integer or integer string.
21
+ if (isCreate) {
22
+ if (i < len - 1) {
23
+ // If next level path is a number, create as an array
24
+ let isArray = (path[i + 1] + '').match(/^\d+$/);
25
+ obj[srcProp] = isArray ? [] : {};
26
+ }
27
+ } else
28
+ return undefined; // can't traverse
29
+ }
30
+
31
+ // If last item in path
32
+ if (isCreate && i === len - 1)
33
+ obj[srcProp] = createVal;
34
+
35
+ // Traverse deeper along destination object.
36
+ obj = obj[srcProp];
37
+ i++;
38
+ }
39
+
40
+ return obj;
41
+ }
42
+
43
+ let delveDontCreate = {};