enigmatic 0.10.3 → 0.11.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.
@@ -0,0 +1,15 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "type": "chrome",
9
+ "request": "launch",
10
+ "name": "Launch Chrome against localhost",
11
+ "url": "http://localhost:8080/test.html",
12
+ "webRoot": "${workspaceFolder}"
13
+ }
14
+ ]
15
+ }
package/README.md ADDED
File without changes
package/components.js CHANGED
@@ -14,5 +14,3 @@ window.components = {
14
14
  onMount: async e => await loadCSS('https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css')
15
15
  }
16
16
  }
17
-
18
- console.log('components.mjs', components)
package/enigmatic.js CHANGED
@@ -1,150 +1,185 @@
1
- const w = {}, d = document;
2
-
3
- // helpers
4
-
5
- w.$ = d.querySelector.bind(d);
6
- w.$$ = d.querySelectorAll.bind(d);
1
+ /*
2
+ enigmatic v 0.11.0 front end js utils
3
+
4
+ Usage:
5
+ <div id='mykey' transform='func1' fetch='some.site/data' immediate>${name} ${value}</div>
6
+ <div id='mykey2' transform='func2' stream='some.site/data'>${name} ${value}</div>
7
+
8
+ $('selector')
9
+ $$('selector')
10
+ await loadJS('sounds.js')
11
+ await loadCSS('enigmatic.css')
12
+ await wait(1000)
13
+ await ready()
14
+ beep()
15
+ element(beforeData=>beforeData.field, '<div>${o.mykey}</div>')
16
+ window.components
17
+ state
18
+ await get
19
+ await stream
20
+ */
21
+
22
+ const w = {},
23
+ d = document
24
+
25
+ /////// Helpers
26
+
27
+ w.$ = d.querySelector.bind(d)
28
+ w.$$ = d.querySelectorAll.bind(d)
7
29
  w.loadJS = (src) => {
8
30
  return new Promise((r, j) => {
9
- if ($(`script[src="${src}"]`)) return r(true);
10
- const s = d.createElement('script');
11
- s.src = src;
12
- s.addEventListener('load', r);
13
- d.head.appendChild(s);
14
- });
15
- };
31
+ if ($(`script[src="${src}"]`)) return r(true)
32
+ const s = d.createElement('script')
33
+ s.src = src
34
+ s.addEventListener('load', r)
35
+ d.head.appendChild(s)
36
+ })
37
+ }
16
38
  w.loadCSS = (src) => {
17
39
  return new Promise((r, j) => {
18
- const s = document.createElement('link');
19
- s.rel = 'stylesheet';
20
- s.href = src;
21
- s.addEventListener('load', r);
22
- d.head.appendChild(s);
23
- });
24
- };
25
- w.wait = (ms) => new Promise((r) => setTimeout(r, ms));
40
+ const s = document.createElement('link')
41
+ s.rel = 'stylesheet'
42
+ s.href = src
43
+ s.addEventListener('load', r)
44
+ d.head.appendChild(s)
45
+ })
46
+ }
47
+ w.wait = (ms) => new Promise((r) => setTimeout(r, ms))
26
48
  w.ready = async () => {
27
49
  return new Promise((r) => {
28
- if (document.readyState === 'complete') r(true);
50
+ if (document.readyState === 'complete') r(true)
29
51
  document.onreadystatechange = () => {
30
- if (document.readyState === 'complete') r();
31
- };
32
- });
33
- };
34
- w.child = (type = 'div', html = '') => {
35
- const e = d.createElement(type);
36
- e.innerHTML = html;
37
- d.body.appendChild(e);
38
- return e;
39
- };
40
-
41
- // Custom element
52
+ if (document.readyState === 'complete') r()
53
+ }
54
+ })
55
+ }
42
56
 
43
- w.element = (name, {onMount = x=>x, beforeData = x=>x, style, template = ''}) => {
44
- customElements.define(name, class extends HTMLElement {
45
- async connectedCallback(props) {
46
- await onMount()
57
+ /////// Custom element
58
+
59
+ w.element = (
60
+ name,
61
+ { onMount = x => x, beforeData = (x) => x, style, template = '' }
62
+ ) => {
63
+ customElements.define(
64
+ name,
65
+ class extends HTMLElement {
66
+ connectedCallback(props) {
67
+ onMount(this)
47
68
  if (style) {
48
69
  const s = document.createElement('style')
49
70
  s.innerHTML = `${name} {${style}}`
50
- d.body.appendChild(s);
71
+ d.body.appendChild(s)
51
72
  }
52
- this.template = template;
53
- if(!this.template.match('{'))
54
- this.innerHTML = this.template
55
- }
56
- set(o) {
57
- this.innerHTML = ''
58
- o = beforeData(o)
59
- if(!Array.isArray(o)) o = [o];
60
- const m = new Function('o', 'return `' + this.template + '`');
61
- o.map((i) => (this.innerHTML += m(o)));
73
+ this.template = template
74
+ if (!this.template.match('{')) this.innerHTML = this.template
75
+ }
76
+ set(o) {
77
+ this.innerHTML = ''
78
+ o = beforeData(o)
79
+ if (!Array.isArray(o)) o = [o]
80
+ const m = new Function('o', 'return `' + this.template + '`')
81
+ o.map((i) => (this.innerHTML += m(i)))
82
+ return true
83
+ }
62
84
  }
63
- })
85
+ )
64
86
  }
65
87
 
66
88
  if (window.components) {
67
- for (let name in window.components)
68
- w.element(name, window.components[name])
89
+ for (let name in window.components) w.element(name, window.components[name])
69
90
  }
70
91
 
71
- // Data
92
+ /////// State, data, and reactivity
72
93
 
73
- w.state = new Proxy(
74
- {}, {
94
+ w.state = new Proxy({}, {
75
95
  set: (obj, prop, value) => {
76
- let ret = []
77
- for (const e of $$(`[data*=${prop}]`)) {
78
- console.log(['setting e', e.tagName, e.id, value])
79
- e.set(value);
96
+ console.log(prop, value)
97
+ if(this[prop] === value) {
98
+ return true
80
99
  }
81
- obj[prop] = value;
100
+ for (const e of $$(`[data=${prop}]`)) {
101
+ if(e.set) e.set(value)
102
+ }
103
+ obj[prop] = value
104
+ return value
82
105
  },
83
106
  get: (obj, prop, receiver) => {
84
- if (prop == '_state') return obj;
85
- return obj[prop];
86
- },
107
+ if (prop == '_all') return obj
108
+ return obj[prop]
109
+ }
87
110
  }
88
111
  )
89
112
 
90
- w.dataEvent = (x) => console.log(`dataevent: ${x}`);
91
-
92
- w.fetchJSON = async (url, key) => {
93
- const j = await (await fetch(url)).json();
94
- if (key) state[key] = j;
95
- dataEvent(j);
96
- return j;
97
- };
113
+ w.get = async (
114
+ url,
115
+ options = null,
116
+ transform = null,
117
+ key = 'temp'
118
+ ) => {
119
+ let data = await (await fetch(`https://${url}`, options)).json()
120
+ if (transform) data = transform(data)
121
+ state[key] = data
122
+ return data
123
+ }
98
124
 
99
- w.streamJSON = async (url, key) => {
100
- const ev = new EventSource(url);
125
+ w.stream = async (url, key) => {
126
+ const ev = new EventSource(url)
101
127
  ev.onmessage = (ev) => {
102
- const j = JSON.parse(ev.data);
103
- if (key) state[key] = j;
104
- dataEvent(j);
105
- return j;
106
- };
107
- };
108
-
109
- // State changes
110
-
111
- w.trackStateChanges = () =>
112
- (w.dataEvent = (o) =>
113
- localStorage.set(new Date().toISOString(), JSON.stringify(o)));
114
- w.untrackStateChanges = () =>
115
- (w.dataEvent = (o) => console.log('dataevent:', o));
128
+ const data = JSON.parse(ev.data)
129
+ w.state[key] = data
130
+ return data
131
+ }
132
+ }
116
133
 
117
- // Startup
134
+ /////// Startup
118
135
 
119
136
  w.start = async () => {
120
137
  await w.ready();
121
- [...$$('div')].map((e) => {
122
- if (!e.id)
123
- e.id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 3)
124
- e.pr = {};
125
- [...e.attributes].map((a) => (e.pr[a.name] = a.value));
126
- if (e.pr.fetch) e.fetch = fetchJSON.bind(null, e.pr.fetch, e.id);
127
- if ('immediate' in e.pr) e.fetch();
128
- if (e.pr.stream) e.stream = streamJSON.bind(null, e.pr.stream, e.id);
129
- if (e.pr.data) {
138
+ [...$$('*')].map(e => {
139
+ e.attr = {};
140
+ [...e.attributes].map((a) => (e.attr[a.name] = a.value))
141
+ if (e.attr?.fetch) {
142
+ e.fetch = async () => {
143
+ return w.get(e.attr?.fetch, {}, w[e.attr?.transform], e.attr.data)
144
+ }
145
+ }
146
+ if (e.hasAttribute('immediate')) {
147
+ e.fetch()
148
+ }
149
+ if (e.attr?.stream) {
150
+ e.stream = w.stream.bind(null, e.pr.stream, null, window[e.pr.transform], e.id)
151
+ }
152
+ let dta = e.attr?.data
153
+ if (dta) {
154
+ if(dta.endsWith('[]')) {
155
+ dta = dta.replace('[]', '')
156
+ }
130
157
  if (e.innerHTML && e.innerHTML.includes('{')) {
131
- e.template = e.innerHTML.replaceAll('{', '${');
132
- e.innerHTML = '';
158
+ e.template = e.innerHTML.replaceAll('{', '${')
159
+ e.innerHTML = ''
133
160
  }
134
161
  e.set = (o) => {
135
162
  e.innerHTML = ''
136
- if (!Array.isArray(o)) o = [o];
137
- const m = new Function('o', 'return `' + e.template + '`');
138
- o.map((i) => (e.innerHTML += m(i)));
139
- };
163
+ const template = e.template.replaceAll('{', '{rec.')
164
+ if (!Array.isArray(o)) o = [o]
165
+ const f = new Function('rec', 'return `' + template + '`')
166
+ o.map(rec => {
167
+ if(typeof rec !== 'object') rec = {value: rec}
168
+ e.innerHTML += f(rec)
169
+ })
170
+ }
171
+ if (e.attr?.value) {
172
+ let o = e.attr.value
173
+ try { o = JSON.parse(o) } catch(e) {}
174
+ w.state[dta] = o
175
+ }
140
176
  }
141
177
  })
142
178
  }
143
179
 
144
- w.enigmatic = { version: '2022-03-05 0.10.2' };
180
+ w.enigmatic = { version: '2022-09-24 0.11.1' }
145
181
  Object.assign(window, w);
146
182
 
147
- (async() => {
183
+ (async () => {
148
184
  await w.start()
149
- if(window.main) window.main()
150
- })();
185
+ })()
package/package.json CHANGED
@@ -1,5 +1,12 @@
1
1
  {
2
2
  "name": "enigmatic",
3
3
  "main": "enigmatic.js",
4
- "version": "0.10.3"
5
- }
4
+ "version": "0.11.1",
5
+ "scripts": {
6
+ "test": "node test.mjs"
7
+ },
8
+ "devDependencies": {
9
+ "instax": "^0.1.5",
10
+ "puppeteer": "^17.1.3"
11
+ }
12
+ }
package/server.mjs ADDED
@@ -0,0 +1,9 @@
1
+ import http from 'node:http'
2
+ import { read } from 'instax'
3
+
4
+ http.createServer(({url}, s) => {
5
+ console.log(url)
6
+ s.end(read(`.${url}`))
7
+ }).listen(3000)
8
+
9
+ console.log('started on 3000')
package/test.html ADDED
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <script src='components.js'></script>
3
+ <script src='enigmatic.js'></script>
4
+
5
+ <div id="counter" data="count" value="0">{value}</div>
6
+ <button onclick="state.count++">Incr</button>
7
+
8
+ <div id='div1' data="users" fetch="randomuser.me/api" value='{"results": [ {"name": {"first": "set", "last": "me"}} ]}'>
9
+ {results[0].name.first} {results[0].name.last}
10
+ </div>
11
+
12
+ <button onclick='state.users = {"results": [ {"name": {"first": "first", "last": "last"} }]}'>Set user</button>
13
+ <button onclick="div1.fetch()">Fetch user</button>
14
+
15
+ <div id='div2' data="users2" fetch="randomuser.me/api" immediate>
16
+ <div>{results[0].name.first} {results[0].name.last}</div>
17
+ </div>
18
+
19
+ <div id='div3' data="users2">
20
+ <div>{results[0].name.first} {results[0].name.last}</div>
21
+ </div>
22
+
23
+ <random-users data="users"></random-users>
24
+ <tailwind-example></tailwind-example>
package/test.mjs ADDED
@@ -0,0 +1,26 @@
1
+ // wsl install:
2
+ // wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
3
+ // sudo apt - y install./ google - chrome - stable_current_amd64.deb
4
+
5
+ import puppeteer from 'puppeteer'
6
+ import { te, tde, tm, wait } from 'instax'
7
+ const host = 'http://127.0.0.1:8080'
8
+
9
+ const browser = await puppeteer.launch({ headless: true })
10
+ const page = await browser.newPage()
11
+ await page.goto(`${host}/test.html`, {
12
+ waitUntil: 'networkidle2',
13
+ timeout: 5000
14
+ })
15
+
16
+ const e = (await page.evaluate("enigmatic"))
17
+ tm(e.version, /0.11.1/)
18
+ tm(await page.evaluate("$('#div1').template"), /results/)
19
+
20
+ // get
21
+ // state
22
+ // div
23
+ // custom
24
+ await wait(2000)
25
+ await page.close()
26
+ await browser.close()
package/index.html DELETED
@@ -1,10 +0,0 @@
1
- <script src='components.js'></script>
2
- <script src='enigmatic.js'></script>
3
-
4
- <div data='key'>This is data: {o.a}</div>
5
- <hello-world></hello-world>
6
- <tailwind-example></tailwind-example>
7
-
8
- <script>
9
- main = x => state.key = [{a: 'one'}, { a: 'two' }]
10
- </script>