@es-joy/jsoe 0.8.1 → 0.10.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.
- package/.eslintrc.cjs +3 -0
- package/.nyc_output/out.json +14319 -8379
- package/CHANGES.md +8 -0
- package/README.md +9 -3
- package/demo/index.js +17 -3
- package/dist/formats/structuredCloning.d.ts.map +1 -1
- package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
- package/dist/fundamentalTypes/blobType.d.ts +11 -0
- package/dist/fundamentalTypes/blobType.d.ts.map +1 -0
- package/dist/fundamentalTypes/errorType.d.ts.map +1 -1
- package/dist/fundamentalTypes/fileType.d.ts +13 -0
- package/dist/fundamentalTypes/fileType.d.ts.map +1 -0
- package/dist/fundamentalTypes/filelistType.d.ts +6 -0
- package/dist/fundamentalTypes/filelistType.d.ts.map +1 -0
- package/dist/types.d.ts +9 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/FileList.d.ts +26 -0
- package/dist/utils/FileList.d.ts.map +1 -0
- package/dist/utils/dialogs.d.ts +3 -1
- package/dist/utils/dialogs.d.ts.map +1 -1
- package/dist/utils/media.d.ts +18 -0
- package/dist/utils/media.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/formats/structuredCloning.js +25 -16
- package/src/fundamentalTypes/arrayType.js +57 -18
- package/src/fundamentalTypes/blobType.js +1001 -0
- package/src/fundamentalTypes/fileType.js +1 -101
- package/src/fundamentalTypes/filelistType.js +35 -0
- package/src/jsoe.css +8 -0
- package/src/types.js +9 -6
- package/src/utils/FileList.js +32 -0
- package/src/utils/media.js +103 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {jml} from '../vendor-imports.js';
|
|
2
2
|
import {$e} from '../utils/templateUtils.js';
|
|
3
|
+
import {visualize, getUserMedia, startScreenCapture} from '../utils/media.js';
|
|
3
4
|
import dialogs from '../utils/dialogs.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -13,107 +14,6 @@ import dialogs from '../utils/dialogs.js';
|
|
|
13
14
|
* @typedef {(file: FileInfo) => void} SetValue
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
|
-
/** @type {AudioContext} */
|
|
17
|
-
let audioCtx;
|
|
18
|
-
/**
|
|
19
|
-
* @param {MediaStream} stream
|
|
20
|
-
* @param {HTMLCanvasElement} canvas
|
|
21
|
-
* @see Adapted from {@link https://mdn.github.io/dom-examples/media/web-dictaphone/}
|
|
22
|
-
* @returns {void}
|
|
23
|
-
*/
|
|
24
|
-
function visualize (stream, canvas) {
|
|
25
|
-
if (!audioCtx) {
|
|
26
|
-
audioCtx = new AudioContext();
|
|
27
|
-
}
|
|
28
|
-
const canvasCtx = /** @type {CanvasRenderingContext2D} */ (
|
|
29
|
-
canvas.getContext('2d')
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const source = audioCtx.createMediaStreamSource(stream);
|
|
33
|
-
|
|
34
|
-
const analyser = audioCtx.createAnalyser();
|
|
35
|
-
analyser.fftSize = 2048;
|
|
36
|
-
const bufferLength = analyser.frequencyBinCount;
|
|
37
|
-
const dataArray = new Uint8Array(bufferLength);
|
|
38
|
-
|
|
39
|
-
source.connect(analyser);
|
|
40
|
-
// analyser.connect(audioCtx.destination);
|
|
41
|
-
|
|
42
|
-
draw();
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @returns {void}
|
|
46
|
-
*/
|
|
47
|
-
function draw () {
|
|
48
|
-
const WIDTH = canvas.width;
|
|
49
|
-
const HEIGHT = canvas.height;
|
|
50
|
-
|
|
51
|
-
requestAnimationFrame(draw);
|
|
52
|
-
|
|
53
|
-
analyser.getByteTimeDomainData(dataArray);
|
|
54
|
-
|
|
55
|
-
canvasCtx.fillStyle = 'rgb(200, 200, 200)';
|
|
56
|
-
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
|
|
57
|
-
|
|
58
|
-
canvasCtx.lineWidth = 2;
|
|
59
|
-
canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
|
|
60
|
-
|
|
61
|
-
canvasCtx.beginPath();
|
|
62
|
-
|
|
63
|
-
const sliceWidth = WIDTH * 1 / bufferLength;
|
|
64
|
-
let x = 0;
|
|
65
|
-
|
|
66
|
-
for (let i = 0; i < bufferLength; i++) {
|
|
67
|
-
const v = dataArray[i] / 128;
|
|
68
|
-
const y = v * HEIGHT / 2;
|
|
69
|
-
|
|
70
|
-
if (i === 0) {
|
|
71
|
-
canvasCtx.moveTo(x, y);
|
|
72
|
-
} else {
|
|
73
|
-
canvasCtx.lineTo(x, y);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
x += sliceWidth;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
canvasCtx.lineTo(canvas.width, canvas.height / 2);
|
|
80
|
-
canvasCtx.stroke();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* @param {MediaStreamConstraints} constraints
|
|
86
|
-
* @returns {Promise<MediaStream|null>}
|
|
87
|
-
*/
|
|
88
|
-
async function getUserMedia (constraints) {
|
|
89
|
-
let stream = null;
|
|
90
|
-
try {
|
|
91
|
-
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
92
|
-
/* c8 ignore next 4 */
|
|
93
|
-
} catch (err) {
|
|
94
|
-
console.error('err', err);
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
return stream;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* @param {DisplayMediaStreamOptions|undefined} displayMediaOptions
|
|
102
|
-
* @returns {Promise<MediaStream|null>}
|
|
103
|
-
*/
|
|
104
|
-
async function startScreenCapture (displayMediaOptions) {
|
|
105
|
-
let captureStream = null;
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
captureStream =
|
|
109
|
-
await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
|
|
110
|
-
/* c8 ignore next 3 */
|
|
111
|
-
} catch (err) {
|
|
112
|
-
console.error(`Error: ${err}`);
|
|
113
|
-
}
|
|
114
|
-
return captureStream;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
17
|
/**
|
|
118
18
|
* @param {number} timestamp
|
|
119
19
|
* @returns {string}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import arrayType from './arrayType.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {import('../types.js').TypeObject}
|
|
5
|
+
*/
|
|
6
|
+
const filelistType = {
|
|
7
|
+
option: ['FileList'],
|
|
8
|
+
array: true,
|
|
9
|
+
filelist: true,
|
|
10
|
+
regexEndings: [',', ')'],
|
|
11
|
+
stringRegexBegin: /^FileList\(/u,
|
|
12
|
+
stringRegexEnd: /^\)/u,
|
|
13
|
+
|
|
14
|
+
toValue (...args) {
|
|
15
|
+
return arrayType.toValue.apply(this, args);
|
|
16
|
+
},
|
|
17
|
+
getValue (...args) {
|
|
18
|
+
return arrayType.getValue.apply(this, args);
|
|
19
|
+
},
|
|
20
|
+
getInput (...args) {
|
|
21
|
+
return arrayType.getInput.apply(this, args);
|
|
22
|
+
},
|
|
23
|
+
viewUI ({...args}) {
|
|
24
|
+
return arrayType.viewUI.call(this, {
|
|
25
|
+
...args, type: 'filelist'
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
editUI ({...args}) {
|
|
29
|
+
return arrayType.editUI.call(this, {
|
|
30
|
+
...args, type: 'filelist'
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default filelistType;
|
package/src/jsoe.css
CHANGED
|
@@ -97,6 +97,14 @@ video.recordedMedia {
|
|
|
97
97
|
background-color: beige;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
[data-type="filelist"] {
|
|
101
|
+
background-color: bisque;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
[data-type="blob"] {
|
|
105
|
+
background-color: lightgray;
|
|
106
|
+
}
|
|
107
|
+
|
|
100
108
|
[class^="propertyName-"] {
|
|
101
109
|
background-color: yellow;
|
|
102
110
|
}
|
package/src/types.js
CHANGED
|
@@ -35,6 +35,8 @@ import SpecialNumberSuperType from './superTypes/SpecialNumberType.js';
|
|
|
35
35
|
import errorType from './fundamentalTypes/errorType.js';
|
|
36
36
|
import errorsSpecialType from './superTypes/errorsSpecialType.js';
|
|
37
37
|
import fileType from './fundamentalTypes/fileType.js';
|
|
38
|
+
import filelistType from './fundamentalTypes/filelistType.js';
|
|
39
|
+
import blobType from './fundamentalTypes/blobType.js';
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
42
|
* Utility to retrieve the property value given a legend element.
|
|
@@ -269,9 +271,11 @@ const Types = {};
|
|
|
269
271
|
* @property {boolean} [array] Private context variable. Whether or not
|
|
270
272
|
* it is an array. Do not use in other types.
|
|
271
273
|
* @property {boolean} [map] Private context variable. Whether or not
|
|
272
|
-
* it is a Map
|
|
274
|
+
* it is a `Map`. Do not use in other types.
|
|
273
275
|
* @property {boolean} [set] Private context variable. Whether or not
|
|
274
|
-
* it is a
|
|
276
|
+
* it is a `Set`. Do not use in other types.
|
|
277
|
+
* @property {boolean} [filelist] Private context variable. Whether or not
|
|
278
|
+
* it is a `FileList` type. Do not use in other types.
|
|
275
279
|
* @property {boolean} [sparse] Private context variable. Whether or not
|
|
276
280
|
* it is a sparse array. Do not use in other types.
|
|
277
281
|
* @property {boolean} [valid] Private context variable. Whether or not
|
|
@@ -385,9 +389,8 @@ Types.availableTypes = {
|
|
|
385
389
|
set: setType,
|
|
386
390
|
|
|
387
391
|
file: fileType,
|
|
388
|
-
filelist:
|
|
389
|
-
|
|
390
|
-
},
|
|
392
|
+
filelist: filelistType,
|
|
393
|
+
blob: blobType,
|
|
391
394
|
blobHTML: blobHTMLType,
|
|
392
395
|
arraybuffer: {
|
|
393
396
|
option: ['ArrayBuffer']
|
|
@@ -470,7 +473,7 @@ Types.availableTypes = {
|
|
|
470
473
|
* "int8array"|"uint8array"|"uint8clampedarray"|"int16array"|"uint16array"|
|
|
471
474
|
* "int32array"|"uint32array"|"float32array"|"float64array"|"IntlCollator"|
|
|
472
475
|
* "IntlDateTimeFormat"|"IntlNumberFormat"|"ValidDate"|
|
|
473
|
-
* "arrayNonindexKeys"|"error"|"errors"} AvailableType
|
|
476
|
+
* "arrayNonindexKeys"|"error"|"errors"|"blob"} AvailableType
|
|
474
477
|
*/
|
|
475
478
|
|
|
476
479
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {number} Integer
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* `FileList` polyfill.
|
|
6
|
+
*/
|
|
7
|
+
class FileList {
|
|
8
|
+
/**
|
|
9
|
+
* Set private properties and length.
|
|
10
|
+
*/
|
|
11
|
+
constructor () {
|
|
12
|
+
// eslint-disable-next-line prefer-rest-params
|
|
13
|
+
this._files = arguments[0];
|
|
14
|
+
this.length = this._files.length;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @param {Integer} index
|
|
18
|
+
* @returns {File}
|
|
19
|
+
*/
|
|
20
|
+
item (index) {
|
|
21
|
+
return this._files[index];
|
|
22
|
+
}
|
|
23
|
+
/* eslint-disable class-methods-use-this */
|
|
24
|
+
/**
|
|
25
|
+
* @returns {"FileList"}
|
|
26
|
+
*/
|
|
27
|
+
get [Symbol.toStringTag] () {
|
|
28
|
+
/* eslint-enable class-methods-use-this */
|
|
29
|
+
return 'FileList';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export default FileList;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** @type {AudioContext} */
|
|
2
|
+
let audioCtx;
|
|
3
|
+
/**
|
|
4
|
+
* @param {MediaStream} stream
|
|
5
|
+
* @param {HTMLCanvasElement} canvas
|
|
6
|
+
* @see Adapted from {@link https://mdn.github.io/dom-examples/media/web-dictaphone/}
|
|
7
|
+
* @returns {void}
|
|
8
|
+
*/
|
|
9
|
+
function visualize (stream, canvas) {
|
|
10
|
+
if (!audioCtx) {
|
|
11
|
+
audioCtx = new AudioContext();
|
|
12
|
+
}
|
|
13
|
+
const canvasCtx = /** @type {CanvasRenderingContext2D} */ (
|
|
14
|
+
canvas.getContext('2d')
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const source = audioCtx.createMediaStreamSource(stream);
|
|
18
|
+
|
|
19
|
+
const analyser = audioCtx.createAnalyser();
|
|
20
|
+
analyser.fftSize = 2048;
|
|
21
|
+
const bufferLength = analyser.frequencyBinCount;
|
|
22
|
+
const dataArray = new Uint8Array(bufferLength);
|
|
23
|
+
|
|
24
|
+
source.connect(analyser);
|
|
25
|
+
// analyser.connect(audioCtx.destination);
|
|
26
|
+
|
|
27
|
+
draw();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @returns {void}
|
|
31
|
+
*/
|
|
32
|
+
function draw () {
|
|
33
|
+
const WIDTH = canvas.width;
|
|
34
|
+
const HEIGHT = canvas.height;
|
|
35
|
+
|
|
36
|
+
requestAnimationFrame(draw);
|
|
37
|
+
|
|
38
|
+
analyser.getByteTimeDomainData(dataArray);
|
|
39
|
+
|
|
40
|
+
canvasCtx.fillStyle = 'rgb(200, 200, 200)';
|
|
41
|
+
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
|
|
42
|
+
|
|
43
|
+
canvasCtx.lineWidth = 2;
|
|
44
|
+
canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
|
|
45
|
+
|
|
46
|
+
canvasCtx.beginPath();
|
|
47
|
+
|
|
48
|
+
const sliceWidth = WIDTH * 1 / bufferLength;
|
|
49
|
+
let x = 0;
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < bufferLength; i++) {
|
|
52
|
+
const v = dataArray[i] / 128;
|
|
53
|
+
const y = v * HEIGHT / 2;
|
|
54
|
+
|
|
55
|
+
if (i === 0) {
|
|
56
|
+
canvasCtx.moveTo(x, y);
|
|
57
|
+
} else {
|
|
58
|
+
canvasCtx.lineTo(x, y);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
x += sliceWidth;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
canvasCtx.lineTo(canvas.width, canvas.height / 2);
|
|
65
|
+
canvasCtx.stroke();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {MediaStreamConstraints} constraints
|
|
72
|
+
* @returns {Promise<MediaStream|null>}
|
|
73
|
+
*/
|
|
74
|
+
async function getUserMedia (constraints) {
|
|
75
|
+
let stream = null;
|
|
76
|
+
try {
|
|
77
|
+
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
78
|
+
/* c8 ignore next 4 */
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error('err', err);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return stream;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {DisplayMediaStreamOptions|undefined} displayMediaOptions
|
|
88
|
+
* @returns {Promise<MediaStream|null>}
|
|
89
|
+
*/
|
|
90
|
+
async function startScreenCapture (displayMediaOptions) {
|
|
91
|
+
let captureStream = null;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
captureStream =
|
|
95
|
+
await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
|
|
96
|
+
/* c8 ignore next 3 */
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error(`Error: ${err}`);
|
|
99
|
+
}
|
|
100
|
+
return captureStream;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export {visualize, getUserMedia, startScreenCapture};
|