lively 0.12.0 → 0.13.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/lively/application.rb +38 -0
- data/lib/lively/assets.rb +66 -14
- data/lib/lively/environment/application.rb +17 -2
- data/lib/lively/hello_world.rb +16 -0
- data/lib/lively/pages/index.rb +19 -1
- data/lib/lively/pages/index.xrb +2 -4
- data/lib/lively/version.rb +3 -2
- data/public/_components/@socketry/live/Live.js +42 -48
- data/public/_components/@socketry/live/package.json +4 -1
- data/public/_components/@socketry/live/readme.md +147 -31
- data/public/_components/@socketry/live-audio/Live/Audio/Controller.js +168 -0
- data/public/_components/@socketry/live-audio/Live/Audio/Library.js +748 -0
- data/public/_components/@socketry/live-audio/Live/Audio/Output.js +87 -0
- data/public/_components/@socketry/live-audio/Live/Audio/Sound.js +34 -0
- data/public/_components/@socketry/live-audio/Live/Audio/Visualizer.js +265 -0
- data/public/_components/@socketry/live-audio/Live/Audio.js +24 -0
- data/public/_components/@socketry/live-audio/package.json +35 -0
- data/public/_components/@socketry/live-audio/readme.md +250 -0
- data/public/application.js +4 -0
- data.tar.gz.sig +0 -0
- metadata +10 -2
- metadata.gz.sig +0 -0
- data/public/_components/@socketry/live/test/Live.js +0 -357
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lively
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -98,10 +98,17 @@ files:
|
|
98
98
|
- lib/lively/pages/index.xrb
|
99
99
|
- lib/lively/version.rb
|
100
100
|
- license.md
|
101
|
+
- public/_components/@socketry/live-audio/Live/Audio.js
|
102
|
+
- public/_components/@socketry/live-audio/Live/Audio/Controller.js
|
103
|
+
- public/_components/@socketry/live-audio/Live/Audio/Library.js
|
104
|
+
- public/_components/@socketry/live-audio/Live/Audio/Output.js
|
105
|
+
- public/_components/@socketry/live-audio/Live/Audio/Sound.js
|
106
|
+
- public/_components/@socketry/live-audio/Live/Audio/Visualizer.js
|
107
|
+
- public/_components/@socketry/live-audio/package.json
|
108
|
+
- public/_components/@socketry/live-audio/readme.md
|
101
109
|
- public/_components/@socketry/live/Live.js
|
102
110
|
- public/_components/@socketry/live/package.json
|
103
111
|
- public/_components/@socketry/live/readme.md
|
104
|
-
- public/_components/@socketry/live/test/Live.js
|
105
112
|
- public/_components/morphdom/morphdom-esm.js
|
106
113
|
- public/_components/morphdom/morphdom-factory.js
|
107
114
|
- public/_components/morphdom/morphdom-umd.js
|
@@ -111,6 +118,7 @@ files:
|
|
111
118
|
- public/_static/icon.png
|
112
119
|
- public/_static/index.css
|
113
120
|
- public/_static/site.css
|
121
|
+
- public/application.js
|
114
122
|
- readme.md
|
115
123
|
homepage: https://github.com/socketry/lively
|
116
124
|
licenses:
|
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,357 +0,0 @@
|
|
1
|
-
import {describe, before, beforeEach, after, it} from 'node:test';
|
2
|
-
import {ok, strict, strictEqual, deepStrictEqual} from 'node:assert';
|
3
|
-
|
4
|
-
import {WebSocket} from 'ws';
|
5
|
-
import {JSDOM} from 'jsdom';
|
6
|
-
import {Live} from '../Live.js';
|
7
|
-
|
8
|
-
class Queue {
|
9
|
-
constructor() {
|
10
|
-
this.items = [];
|
11
|
-
this.waiting = [];
|
12
|
-
}
|
13
|
-
|
14
|
-
push(item) {
|
15
|
-
if (this.waiting.length > 0) {
|
16
|
-
let resolve = this.waiting.shift();
|
17
|
-
resolve(item);
|
18
|
-
} else {
|
19
|
-
this.items.push(item);
|
20
|
-
}
|
21
|
-
}
|
22
|
-
|
23
|
-
pop() {
|
24
|
-
return new Promise(resolve => {
|
25
|
-
if (this.items.length > 0) {
|
26
|
-
resolve(this.items.shift());
|
27
|
-
} else {
|
28
|
-
this.waiting.push(resolve);
|
29
|
-
}
|
30
|
-
});
|
31
|
-
}
|
32
|
-
|
33
|
-
async popUntil(callback) {
|
34
|
-
while (true) {
|
35
|
-
let item = await this.pop();
|
36
|
-
if (callback(item)) return item;
|
37
|
-
}
|
38
|
-
}
|
39
|
-
|
40
|
-
clear() {
|
41
|
-
this.items = [];
|
42
|
-
this.waiting = [];
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
describe('Live', function () {
|
47
|
-
let dom;
|
48
|
-
let webSocketServer;
|
49
|
-
let messages = new Queue();
|
50
|
-
|
51
|
-
const webSocketServerConfig = {port: 3000};
|
52
|
-
const webSocketServerURL = `ws://localhost:${webSocketServerConfig.port}/live`;
|
53
|
-
|
54
|
-
before(async function () {
|
55
|
-
const listening = new Promise((resolve, reject) => {
|
56
|
-
webSocketServer = new WebSocket.Server(webSocketServerConfig, resolve);
|
57
|
-
webSocketServer.on('error', reject);
|
58
|
-
});
|
59
|
-
|
60
|
-
dom = new JSDOM('<!DOCTYPE html><html><body><div id="my" class="live"><p>Hello World</p></div></body></html>');
|
61
|
-
// Ensure the WebSocket class is available:
|
62
|
-
dom.window.WebSocket = WebSocket;
|
63
|
-
|
64
|
-
await new Promise(resolve => dom.window.addEventListener('load', resolve));
|
65
|
-
|
66
|
-
await listening;
|
67
|
-
|
68
|
-
webSocketServer.on('connection', socket => {
|
69
|
-
socket.on('message', message => {
|
70
|
-
let payload = JSON.parse(message);
|
71
|
-
messages.push(payload);
|
72
|
-
});
|
73
|
-
});
|
74
|
-
});
|
75
|
-
|
76
|
-
beforeEach(function () {
|
77
|
-
messages.clear();
|
78
|
-
});
|
79
|
-
|
80
|
-
after(function () {
|
81
|
-
webSocketServer.close();
|
82
|
-
});
|
83
|
-
|
84
|
-
it('should start the live connection', function () {
|
85
|
-
const live = Live.start({window: dom.window, base: 'http://localhost/'});
|
86
|
-
ok(live);
|
87
|
-
|
88
|
-
strictEqual(live.url.href, 'ws://localhost/live');
|
89
|
-
|
90
|
-
live.disconnect();
|
91
|
-
});
|
92
|
-
|
93
|
-
it('should connect to the WebSocket server', function () {
|
94
|
-
const live = new Live(dom.window, webSocketServerURL);
|
95
|
-
|
96
|
-
const server = live.connect();
|
97
|
-
ok(server);
|
98
|
-
|
99
|
-
live.disconnect();
|
100
|
-
});
|
101
|
-
|
102
|
-
it('should handle visibility changes', async function () {
|
103
|
-
const live = new Live(dom.window, webSocketServerURL);
|
104
|
-
|
105
|
-
// It's tricky to test the method directly.
|
106
|
-
// - Changing document.hidden is a hack.
|
107
|
-
// - Sending custom events seems to cause a hang.
|
108
|
-
|
109
|
-
live.connect();
|
110
|
-
deepStrictEqual(await messages.pop(), ['bind', 'my', {}]);
|
111
|
-
|
112
|
-
live.disconnect();
|
113
|
-
|
114
|
-
live.connect()
|
115
|
-
deepStrictEqual(await messages.pop(), ['bind', 'my', {}]);
|
116
|
-
|
117
|
-
live.disconnect();
|
118
|
-
});
|
119
|
-
|
120
|
-
it('can execute scripts', async function () {
|
121
|
-
const live = new Live(dom.window, webSocketServerURL);
|
122
|
-
|
123
|
-
live.connect();
|
124
|
-
|
125
|
-
const connected = new Promise(resolve => {
|
126
|
-
webSocketServer.on('connection', resolve);
|
127
|
-
});
|
128
|
-
|
129
|
-
let socket = await connected;
|
130
|
-
|
131
|
-
socket.send(
|
132
|
-
JSON.stringify(['script', 'my', 'return 1+2', {reply: true}])
|
133
|
-
);
|
134
|
-
|
135
|
-
let successReply = await messages.popUntil(message => message[0] == 'reply');
|
136
|
-
strictEqual(successReply[2], 3);
|
137
|
-
|
138
|
-
socket.send(
|
139
|
-
JSON.stringify(['script', 'my', 'throw new Error("Test Error")', {reply: true}])
|
140
|
-
);
|
141
|
-
|
142
|
-
let errorReply = await messages.popUntil(message => message[0] == 'reply');
|
143
|
-
strictEqual(errorReply[2], null);
|
144
|
-
console.log(errorReply);
|
145
|
-
|
146
|
-
live.disconnect();
|
147
|
-
});
|
148
|
-
|
149
|
-
it('should handle updates', async function () {
|
150
|
-
const live = new Live(dom.window, webSocketServerURL);
|
151
|
-
|
152
|
-
live.connect();
|
153
|
-
|
154
|
-
const connected = new Promise(resolve => {
|
155
|
-
webSocketServer.on('connection', resolve);
|
156
|
-
});
|
157
|
-
|
158
|
-
let socket = await connected;
|
159
|
-
|
160
|
-
socket.send(
|
161
|
-
JSON.stringify(['update', 'my', '<div id="my"><p>Goodbye World!</p></div>', {reply: true}])
|
162
|
-
);
|
163
|
-
|
164
|
-
await messages.popUntil(message => message[0] == 'reply');
|
165
|
-
|
166
|
-
strictEqual(dom.window.document.getElementById('my').innerHTML, '<p>Goodbye World!</p>');
|
167
|
-
|
168
|
-
live.disconnect();
|
169
|
-
});
|
170
|
-
|
171
|
-
it('should handle updates with child live elements', async function () {
|
172
|
-
const live = new Live(dom.window, webSocketServerURL);
|
173
|
-
|
174
|
-
live.connect();
|
175
|
-
|
176
|
-
const connected = new Promise(resolve => {
|
177
|
-
webSocketServer.on('connection', resolve);
|
178
|
-
});
|
179
|
-
|
180
|
-
let socket = await connected;
|
181
|
-
|
182
|
-
socket.send(
|
183
|
-
JSON.stringify(['update', 'my', '<div id="my"><div id="mychild" class="live"></div></div>'])
|
184
|
-
);
|
185
|
-
|
186
|
-
let payload = await messages.popUntil(message => message[0] == 'bind');
|
187
|
-
deepStrictEqual(payload, ['bind', 'mychild', {}]);
|
188
|
-
|
189
|
-
live.disconnect();
|
190
|
-
});
|
191
|
-
|
192
|
-
it('can unbind removed elements', async function () {
|
193
|
-
dom.window.document.body.innerHTML = '<div id="my" class="live"><p>Hello World</p></div>';
|
194
|
-
|
195
|
-
const live = new Live(dom.window, webSocketServerURL);
|
196
|
-
|
197
|
-
live.connect();
|
198
|
-
|
199
|
-
dom.window.document.getElementById('my').remove();
|
200
|
-
|
201
|
-
let payload = await messages.popUntil(message => {
|
202
|
-
return message[0] == 'unbind' && message[1] == 'my';
|
203
|
-
});
|
204
|
-
|
205
|
-
deepStrictEqual(payload, ['unbind', 'my']);
|
206
|
-
|
207
|
-
live.disconnect();
|
208
|
-
});
|
209
|
-
|
210
|
-
it('should handle replacements', async function () {
|
211
|
-
dom.window.document.body.innerHTML = '<div id="my"><p>Hello World</p></div>';
|
212
|
-
|
213
|
-
const live = new Live(dom.window, webSocketServerURL);
|
214
|
-
|
215
|
-
live.connect();
|
216
|
-
|
217
|
-
const connected = new Promise(resolve => {
|
218
|
-
webSocketServer.on('connection', resolve);
|
219
|
-
});
|
220
|
-
|
221
|
-
let socket = await connected;
|
222
|
-
|
223
|
-
socket.send(
|
224
|
-
JSON.stringify(['replace', '#my p', '<p>Replaced!</p>', {reply: true}])
|
225
|
-
);
|
226
|
-
|
227
|
-
await messages.popUntil(message => message[0] == 'reply');
|
228
|
-
strictEqual(dom.window.document.getElementById('my').innerHTML, '<p>Replaced!</p>');
|
229
|
-
|
230
|
-
live.disconnect();
|
231
|
-
});
|
232
|
-
|
233
|
-
it('should handle prepends', async function () {
|
234
|
-
const live = new Live(dom.window, webSocketServerURL);
|
235
|
-
|
236
|
-
live.connect();
|
237
|
-
|
238
|
-
const connected = new Promise(resolve => {
|
239
|
-
webSocketServer.on('connection', resolve);
|
240
|
-
});
|
241
|
-
|
242
|
-
let socket = await connected;
|
243
|
-
|
244
|
-
socket.send(
|
245
|
-
JSON.stringify(['update', 'my', '<div id="my"><p>Middle</p></div>'])
|
246
|
-
);
|
247
|
-
|
248
|
-
socket.send(
|
249
|
-
JSON.stringify(['prepend', '#my', '<p>Prepended!</p>', {reply: true}])
|
250
|
-
);
|
251
|
-
|
252
|
-
await messages.popUntil(message => message[0] == 'reply');
|
253
|
-
strictEqual(dom.window.document.getElementById('my').innerHTML, '<p>Prepended!</p><p>Middle</p>');
|
254
|
-
|
255
|
-
live.disconnect();
|
256
|
-
});
|
257
|
-
|
258
|
-
it('should handle appends', async function () {
|
259
|
-
const live = new Live(dom.window, webSocketServerURL);
|
260
|
-
|
261
|
-
live.connect();
|
262
|
-
|
263
|
-
const connected = new Promise(resolve => {
|
264
|
-
webSocketServer.on('connection', resolve);
|
265
|
-
});
|
266
|
-
|
267
|
-
let socket = await connected;
|
268
|
-
|
269
|
-
socket.send(
|
270
|
-
JSON.stringify(['update', 'my', '<div id="my"><p>Middle</p></div>'])
|
271
|
-
);
|
272
|
-
|
273
|
-
socket.send(
|
274
|
-
JSON.stringify(['append', '#my', '<p>Appended!</p>', {reply: true}])
|
275
|
-
);
|
276
|
-
|
277
|
-
await messages.popUntil(message => message[0] == 'reply');
|
278
|
-
strictEqual(dom.window.document.getElementById('my').innerHTML, '<p>Middle</p><p>Appended!</p>');
|
279
|
-
|
280
|
-
live.disconnect();
|
281
|
-
});
|
282
|
-
|
283
|
-
it ('should handle removals', async function () {
|
284
|
-
const live = new Live(dom.window, webSocketServerURL);
|
285
|
-
|
286
|
-
live.connect();
|
287
|
-
|
288
|
-
const connected = new Promise(resolve => {
|
289
|
-
webSocketServer.on('connection', resolve);
|
290
|
-
});
|
291
|
-
|
292
|
-
let socket = await connected;
|
293
|
-
|
294
|
-
socket.send(
|
295
|
-
JSON.stringify(['update', 'my', '<div id="my"><p>Middle</p></div>'])
|
296
|
-
);
|
297
|
-
|
298
|
-
socket.send(
|
299
|
-
JSON.stringify(['remove', '#my p', {reply: true}])
|
300
|
-
);
|
301
|
-
|
302
|
-
await messages.popUntil(message => message[0] == 'reply');
|
303
|
-
strictEqual(dom.window.document.getElementById('my').innerHTML, '');
|
304
|
-
|
305
|
-
live.disconnect();
|
306
|
-
});
|
307
|
-
|
308
|
-
it ('can dispatch custom events', async function () {
|
309
|
-
const live = new Live(dom.window, webSocketServerURL);
|
310
|
-
|
311
|
-
live.connect();
|
312
|
-
|
313
|
-
const connected = new Promise(resolve => {
|
314
|
-
webSocketServer.on('connection', resolve);
|
315
|
-
});
|
316
|
-
|
317
|
-
let socket = await connected;
|
318
|
-
|
319
|
-
socket.send(
|
320
|
-
JSON.stringify(['dispatchEvent', '#my', 'click', {reply: true}])
|
321
|
-
);
|
322
|
-
|
323
|
-
await messages.popUntil(message => message[0] == 'reply');
|
324
|
-
|
325
|
-
live.disconnect();
|
326
|
-
});
|
327
|
-
|
328
|
-
it ('can forward events', async function () {
|
329
|
-
const live = new Live(dom.window, webSocketServerURL);
|
330
|
-
|
331
|
-
live.connect();
|
332
|
-
|
333
|
-
const connected = new Promise(resolve => {
|
334
|
-
webSocketServer.on('connection', resolve);
|
335
|
-
});
|
336
|
-
|
337
|
-
let socket = await connected;
|
338
|
-
|
339
|
-
dom.window.document.getElementById('my').addEventListener('click', event => {
|
340
|
-
live.forwardEvent('my', event);
|
341
|
-
});
|
342
|
-
|
343
|
-
dom.window.document.getElementById('my').click();
|
344
|
-
|
345
|
-
let payload = await messages.popUntil(message => message[0] == 'event');
|
346
|
-
strictEqual(payload[1], 'my');
|
347
|
-
strictEqual(payload[2].type, 'click');
|
348
|
-
|
349
|
-
live.disconnect();
|
350
|
-
});
|
351
|
-
|
352
|
-
it ('can log errors', function () {
|
353
|
-
const live = new Live(dom.window, webSocketServerURL);
|
354
|
-
|
355
|
-
live.error('my', 'Test Error');
|
356
|
-
});
|
357
|
-
});
|