q5 1.9.21 → 1.9.46
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/README.md +80 -26
- package/package.json +20 -10
- package/q5-server.js +3 -2
- package/q5.js +89 -12
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +257 -0
- package/src/q5-2d-drawing.js +508 -0
- package/src/q5-2d-image.js +572 -0
- package/src/q5-2d-text.js +216 -0
- package/src/q5-ai.js +65 -0
- package/src/q5-color.js +202 -0
- package/src/q5-core.js +273 -0
- package/src/q5-display.js +85 -0
- package/src/q5-dom.js +6 -0
- package/src/q5-input.js +157 -0
- package/src/q5-math.js +505 -0
- package/src/q5-sensors.js +96 -0
- package/src/q5-sound.js +19 -0
- package/src/q5-util.js +33 -0
- package/src/q5-vector.js +225 -0
- package/index.html +0 -12
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# <img src="q5js_logo.webp" height="64"> <img src="q5js_brand.webp" height="64">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The sequel to p5.js is here!
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**q5.js** implements all of [p5][]'s 2D drawing, math, and user input functionality.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
It's a drop-in replacement that's performance optimized and ~20x smaller than p5, while packing exclusive new features: HDR color support, modular use, top-level global mode, namespace mode, and text image caching.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Typical Use
|
|
10
10
|
|
|
11
11
|
q5 should work with your existing p5.js sketches, no modifications required! If you have any problems though, please [make an issue report][].
|
|
12
12
|
|
|
@@ -37,22 +37,53 @@ q5.js is compatible with popular p5 addons and projects that use p5, such as [p5
|
|
|
37
37
|
To use addons, simply load them after q5.js:
|
|
38
38
|
|
|
39
39
|
```html
|
|
40
|
-
<script src="q5.js"></script>
|
|
40
|
+
<script src="https://q5js.org/q5.js"></script>
|
|
41
41
|
<!-- load p5 addons after q5 -->
|
|
42
42
|
<script src="https://p5play.org/v3/planck.min.js"></script>
|
|
43
43
|
<script src="https://p5play.org/v3/p5play.js"></script>
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
##
|
|
46
|
+
## Exclusive Features
|
|
47
|
+
|
|
48
|
+
q5 includes some exclusive features that aren't available in p5.
|
|
49
|
+
|
|
50
|
+
## Ask AI ✨
|
|
51
|
+
|
|
52
|
+
Why doesn't this code work? `text('Hello!');`
|
|
53
|
+
|
|
54
|
+
JavaScript quietly avoids errors if possible (for example by giving undefined variables default values) and its error messages can be confusing for beginners.
|
|
55
|
+
|
|
56
|
+
p5's error messages are friendlier but often too vague, leaving beginners searching for help. 🙋
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
🌸 p5.js says: [test.js, line 19] text() was expecting at least 3 arguments, but received only 1.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
q5 creates error reports that can be sent to an AI just by clicking a link! Users can also run the `askAI()` function before a line of code that isn't working as expected. 🤖
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
function draw() {
|
|
66
|
+
askAI();
|
|
67
|
+
text('Hello!');
|
|
68
|
+
}
|
|
69
|
+
```
|
|
47
70
|
|
|
48
|
-
|
|
71
|
+
Optionally `askAI` can take a question as input, the default question is "What's wrong with this line? short answer".
|
|
72
|
+
|
|
73
|
+
ChatGPT 4o excels at identifying the most common errors that beginners make: typos, missing syntax, incorrect arguments, and more.
|
|
74
|
+
|
|
75
|
+
This feature can be disabled by setting `Q5.disableFriendlyErrors = true;`, though unlike in p5 this doesn't provide a performance boost from disabling argument validation because q5 mostly doesn't have any already.
|
|
76
|
+
|
|
77
|
+
q5 can catch errors in q5 function like `draw` and continue looping if you set `Q5.errorTolerant = true;`.
|
|
78
|
+
|
|
79
|
+
## Top-Level Global Mode
|
|
49
80
|
|
|
50
81
|
In **p5**, functions like `rect` can't be used on the file level. They must be called from within p5 functions like `setup` and `draw`.
|
|
51
82
|
|
|
52
83
|
In **q5**, existing p5 2D sketches don't require any modification. But if you initialize Q5 at the top of your sketch, the `preload` and `setup` functions become optional.
|
|
53
84
|
|
|
54
85
|
```js
|
|
55
|
-
|
|
86
|
+
Q5();
|
|
56
87
|
|
|
57
88
|
noStroke();
|
|
58
89
|
let c = color(0, 126, 255, 102);
|
|
@@ -63,7 +94,7 @@ rect(15, 15, 35, 70);
|
|
|
63
94
|
This is great because you don't have to declare variables on the file level and then define them in `preload` or `setup`. You can declare and define them at the same time!
|
|
64
95
|
|
|
65
96
|
```js
|
|
66
|
-
|
|
97
|
+
Q5();
|
|
67
98
|
|
|
68
99
|
let cow = loadImage('cow.png');
|
|
69
100
|
|
|
@@ -76,7 +107,7 @@ function setup() {
|
|
|
76
107
|
|
|
77
108
|
Note that if you use `loadImage` on the file level, q5 will wait to run `setup` and `draw` until the image loads. Optionally if you forgo defining `preload`, you can run it to signify that the sketch can start once loading is complete. Otherwise q5 will auto-start the sketch after 32ms of delay, this ensures code after `new Q5()` is run before the sketch starts.
|
|
78
109
|
|
|
79
|
-
##
|
|
110
|
+
## HDR Color Support
|
|
80
111
|
|
|
81
112
|
Most modern devices support the "display-p3" HDR color space. If a device doesn't support it, q5 will fall back to "srgb".
|
|
82
113
|
|
|
@@ -103,7 +134,7 @@ Support for the HSV color format was removed in q5 v1.9.3 because color experts
|
|
|
103
134
|
|
|
104
135
|
https://en.wikipedia.org/wiki/HSL_and_HSV#Disadvantages
|
|
105
136
|
|
|
106
|
-
##
|
|
137
|
+
## Customize Canvas Context Attributes
|
|
107
138
|
|
|
108
139
|
In **p5**, you're stuck with the default [canvas context attributes][], which can't be changed. So the canvas must have an alpha layer, even if you don't need one. HDR color space and [desynchronized rendering][] are not supported.
|
|
109
140
|
|
|
@@ -127,7 +158,7 @@ createCanvas(400, 400, '2d', {
|
|
|
127
158
|
});
|
|
128
159
|
```
|
|
129
160
|
|
|
130
|
-
##
|
|
161
|
+
## Namespace Mode
|
|
131
162
|
|
|
132
163
|
**p5**'s [instance mode][] enables multiple sketches to run on one page. To avoid needing to preface every p5 function with `p.` you can use a JS [with statement][].
|
|
133
164
|
|
|
@@ -177,11 +208,17 @@ q5 will automatically load and configure `canvas` and `jsdom` if they are instal
|
|
|
177
208
|
|
|
178
209
|
In node.js, q5's automatic global mode is disabled. To use global mode you need to assign q5 user defined functions like `draw` and `setup` to the `global` object then call `new Q5()`. q5 will add q5 variables and functions to the `global` object, just like it adds them to the `window` object in the browser.
|
|
179
210
|
|
|
211
|
+
## Modular Use
|
|
212
|
+
|
|
213
|
+
**p5.js** is nearly 5MB in size. This is mainly [due to the inclusion of the webgl render and the dependencies corejs and opentype](https://github.com/processing/p5.js/issues/6776#issuecomment-1918238317). If 2d rendering is all a sketch needs, p5 wastes user bandwidth and is slower to load, parse, and run.
|
|
214
|
+
|
|
215
|
+
**q5.js** (the default bundle) is 20x smaller than p5, which is already great for typical use. For extremely lightweight use you can load a subset of scripts from the `src` folder, just be sure to load `src/q5-core.js` first.
|
|
216
|
+
|
|
180
217
|
## Motivation: Part 1
|
|
181
218
|
|
|
182
|
-
> This section was written by @LingDong
|
|
219
|
+
> This section was written by @LingDong-
|
|
183
220
|
|
|
184
|
-
After having used many graphics libraries across many different languages, I have found that the Processing
|
|
221
|
+
After having used many graphics libraries across many different languages, I have found that the Processing system has one huge advantage over others:
|
|
185
222
|
|
|
186
223
|
It gets stuff drawn onto the screen quick and easy!
|
|
187
224
|
|
|
@@ -195,7 +232,7 @@ In fact, its not uncommon for successful software systems to have multiple imple
|
|
|
195
232
|
|
|
196
233
|
## Motivation: Part 2
|
|
197
234
|
|
|
198
|
-
> This section was written by @quinton-ashley
|
|
235
|
+
> This section was written by @quinton-ashley
|
|
199
236
|
|
|
200
237
|
I thought @LingDong-'s work on q5 and the idea itself had great potential, so I decided to implement more of the p5.js API. My main goal was to make it work with [p5play](https://p5play.org)!
|
|
201
238
|
|
|
@@ -203,14 +240,19 @@ An increase in performance of even a few frames per second can make a significan
|
|
|
203
240
|
|
|
204
241
|
I was also interested in working on q5 because for a lot of p5.js users, the library itself is a black box. Even as an expert JS programmer and someone who teaches CS for a living, I still find myself scratching my head when I look at the p5.js source code. p5 was initially released 10 years ago and bad design choices were made due to JS limitations at the time. It's also become an absolutely massive library, with literally over 100,000 lines of code and documentation!
|
|
205
242
|
|
|
206
|
-
I think it'd be better if the canvas mode, webgl mode, Friendly Error System, and accessibility features of p5 were offered in separate files. Yet, the powers that be at the Processing Foundation have made it clear that they don't want to do that.
|
|
243
|
+
I think it'd be better if the canvas mode, webgl mode, Friendly Error System, and accessibility features of p5 were offered in separate files. Yet, the powers that be at the Processing Foundation have made it clear that they don't want to do that. So q5 is a good alternative that trims out the fat.
|
|
207
244
|
|
|
208
245
|
Thanks in large part to @LingDong-'s design, q5 is well organized, concise, and utilizes many modern JS features! I think even without inline documentation, the source code is easier for experienced JS programmers to comprehend.
|
|
209
246
|
|
|
210
247
|
## More exclusive features
|
|
211
248
|
|
|
249
|
+
Features added by @Tezumie:
|
|
250
|
+
|
|
251
|
+
- `point()`: more efficient point drawing.
|
|
252
|
+
|
|
212
253
|
Features added by @quinton-ashley:
|
|
213
254
|
|
|
255
|
+
- `image.trim()`: removes transparent pixels from the edges of an image.
|
|
214
256
|
- `opacity(globalAlpha)`: set the opacity multiplier for anything subsequently drawn to the canvas in a range between 0 (transparent) and 1 (opaque).
|
|
215
257
|
- `textCache(enabled)`: Text image caching is enabled by default. Rotated text is only rendered once, and then cached as an image. This can result in ridiculously high 90x performance boosts for text-heavy sketches. Users don't need to change their code, the `text` function can be used as normal, q5 takes care of everything behind the scenes.
|
|
216
258
|
- `createImage`, `loadImage`, and `createGraphics`: as a last parameter to these functions, `opt` (options) object, users can specify canvas context attributes for an image or graphic. `opt.alpha` is set to true by default.
|
|
@@ -225,21 +267,21 @@ Features added by @LingDong-:
|
|
|
225
267
|
|
|
226
268
|
## Limitations
|
|
227
269
|
|
|
228
|
-
- `color` function only accepts numeric input, hex, and simple named colors. It doesn't parse strings like `color('hsl(160, 100%, 50%)')`.
|
|
270
|
+
- `color` function only accepts numeric input, hex, and simple named colors. It doesn't parse strings like `color('hsl(160, 100%, 50%)')`. q5 supports oklch which is a superior color format so use it instead. The `fill`, `stroke`, and `background` functions can accept any css color string though.
|
|
229
271
|
|
|
230
272
|
## Size Comparison
|
|
231
273
|
|
|
232
274
|
Unminified:
|
|
233
275
|
|
|
234
|
-
- p5.js **
|
|
276
|
+
- p5.js **4958kb** ⚠️
|
|
235
277
|
- p5.sound.js 488kb
|
|
236
|
-
- q5.js
|
|
278
|
+
- q5.js 71kb
|
|
237
279
|
|
|
238
280
|
Minified:
|
|
239
281
|
|
|
240
|
-
- p5.min.js
|
|
282
|
+
- p5.min.js 1033kb ⚠️
|
|
241
283
|
- p5.sound.min.js 200kb
|
|
242
|
-
- q5.min.js **
|
|
284
|
+
- q5.min.js **45kb** 🎉
|
|
243
285
|
|
|
244
286
|
## Benchmarks
|
|
245
287
|
|
|
@@ -278,17 +320,29 @@ Higher FPS (frames per second) is better.
|
|
|
278
320
|
|
|
279
321
|
<sub>\* Only for browsers that support CanvasRenderingContext2D.filter ([75% of all](https://caniuse.com/#feat=mdn-api_canvasrenderingcontext2d_filter) as of Aug 2020, including Chrome, Firefox and Edge). For those that don't, performance is similar to p5.js, as identical implementations are usually used as fallbacks.</sub>
|
|
280
322
|
|
|
281
|
-
##
|
|
323
|
+
## Contributor Code of Conduct
|
|
324
|
+
|
|
325
|
+
We aim to make contributing to the q5 project more approachable for non-experts by using modern JavaScript without any complicated build tools or frameworks.
|
|
326
|
+
|
|
327
|
+
All contributors are required to check their ego at the door and be open to feedback. Critique of code is not a critique of the person who wrote it. We're all here to learn and work with others to collectively write the best code possible.
|
|
328
|
+
|
|
329
|
+
Code is a language art that can be subjectively judged by its effectiveness at communicating its functionality to humans. Code can also be objectively measured by its performance. Since JavaScript is served over a network, size is a factor as well. Therefore, the q5 team strives to balance code readability with brevity and performance.
|
|
330
|
+
|
|
331
|
+
Check out the q5 project planning board:
|
|
332
|
+
|
|
333
|
+
https://github.com/users/quinton-ashley/projects/4/views/1
|
|
334
|
+
|
|
335
|
+
## Organization
|
|
282
336
|
|
|
283
|
-
|
|
337
|
+
If the q5 project is successful, all contributing developers will be paid for their work. The project will be run as a [worker co-op](https://en.wikipedia.org/wiki/Worker_cooperative).
|
|
284
338
|
|
|
285
339
|
## Licensing
|
|
286
340
|
|
|
287
|
-
q5.js
|
|
341
|
+
q5.js was created by the q5 team and is licensed under the LGPLv3. q5 is not affiliated with The Processing Foundation.
|
|
288
342
|
|
|
289
|
-
@LingDong- created the original q5xjs library
|
|
343
|
+
@LingDong- created the original q5xjs library which is MIT licensed.
|
|
290
344
|
|
|
291
|
-
|
|
345
|
+
p5.js is licensed under the LGPLv2, the two small sections of p5' code directly copied into q5 are credited below. The rest of q5 is a new implementation of part of the p5 API. APIs are not copyrightable in the United States, as decided by the Supreme Court in the Google v Oracle case.
|
|
292
346
|
|
|
293
347
|
## Credits
|
|
294
348
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
"author": "quinton-ashley",
|
|
3
2
|
"name": "q5",
|
|
4
|
-
"version": "1.9.
|
|
5
|
-
"description": "
|
|
3
|
+
"version": "1.9.46",
|
|
4
|
+
"description": "The sequel to p5.js that's smaller and faster",
|
|
5
|
+
"author": "quinton-ashley",
|
|
6
|
+
"contributors": [
|
|
7
|
+
"Tezumie",
|
|
8
|
+
"LingDong-"
|
|
9
|
+
],
|
|
10
|
+
"license": "LGPL-3.0",
|
|
11
|
+
"homepage": "https://q5js.org/home",
|
|
6
12
|
"main": "q5-server.js",
|
|
7
13
|
"scripts": {
|
|
14
|
+
"bundle": "cat src/q5-core.js src/q5-2d-canvas.js src/q5-2d-drawing.js src/q5-2d-image.js src/q5-2d-text.js src/q5-ai.js src/q5-color.js src/q5-display.js src/q5-input.js src/q5-math.js src/q5-sound.js src/q5-util.js src/q5-vector.js > q5.js",
|
|
8
15
|
"min": "terser q5.js --compress ecma=2024 --mangle > q5.min.js",
|
|
9
|
-
"dist": "cp q5.js ../../web/p5play-web/v3/q5.js && bun min && cp q5.min.js ../../web/p5play-web/v3/q5.min.js",
|
|
16
|
+
"dist": "bun bundle && cp q5.js ../../web/p5play-web/v3/q5.js && bun min && cp q5.min.js ../../web/p5play-web/v3/q5.min.js",
|
|
10
17
|
"v": "npm version patch --force",
|
|
11
18
|
"V": "npm version minor --force",
|
|
12
19
|
"version": "git add -A",
|
|
@@ -14,7 +21,10 @@
|
|
|
14
21
|
},
|
|
15
22
|
"repository": {
|
|
16
23
|
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/
|
|
24
|
+
"url": "git+https://github.com/q5js/q5.js.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/q5js/q5.js/issues"
|
|
18
28
|
},
|
|
19
29
|
"keywords": [
|
|
20
30
|
"p5",
|
|
@@ -25,9 +35,9 @@
|
|
|
25
35
|
"q5.js",
|
|
26
36
|
"q5js"
|
|
27
37
|
],
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"canvas": "^2.11.2",
|
|
40
|
+
"jsdom": "^24.1.0",
|
|
41
|
+
"@types/p5": "^1.7.6"
|
|
42
|
+
}
|
|
33
43
|
}
|
package/q5-server.js
CHANGED
|
@@ -8,7 +8,8 @@ try {
|
|
|
8
8
|
global.CairoCanvas ??= require('canvas');
|
|
9
9
|
global.JSDOM ??= require('jsdom').JSDOM;
|
|
10
10
|
} catch (e) {
|
|
11
|
-
|
|
11
|
+
require('./q5.js');
|
|
12
|
+
module.exports = Q5;
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -24,7 +25,7 @@ global.window = new JSDOM('', { url: 'http://localhost' }).window;
|
|
|
24
25
|
global.Event = window.Event;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
require('./q5.js');
|
|
28
29
|
|
|
29
30
|
Q5._createNodeJSCanvas = function () {
|
|
30
31
|
let cairoCanvas = CairoCanvas.createCanvas(...arguments);
|
package/q5.js
CHANGED
|
@@ -91,7 +91,7 @@ function Q5(scope, parent) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
$.createCanvas = function (width, height, renderer, options) {
|
|
94
|
-
if (renderer == 'webgl') throw `webgl renderer is not supported in q5, use '2d'
|
|
94
|
+
if (renderer == 'webgl') throw Error(`webgl renderer is not supported in q5, use '2d'`);
|
|
95
95
|
if (typeof renderer == 'object') options = renderer;
|
|
96
96
|
$.width = $.canvas.width = width || window.innerWidth;
|
|
97
97
|
$.height = $.canvas.height = height || window.innerHeight;
|
|
@@ -924,6 +924,7 @@ function Q5(scope, parent) {
|
|
|
924
924
|
blue: [0, 0, 255],
|
|
925
925
|
brown: [165, 42, 42],
|
|
926
926
|
crimson: [220, 20, 60],
|
|
927
|
+
cyan: [0, 255, 255],
|
|
927
928
|
darkviolet: [148, 0, 211],
|
|
928
929
|
gold: [255, 215, 0],
|
|
929
930
|
green: [0, 128, 0],
|
|
@@ -1026,6 +1027,7 @@ function Q5(scope, parent) {
|
|
|
1026
1027
|
$._doStroke = true;
|
|
1027
1028
|
$._strokeSet = true;
|
|
1028
1029
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
1030
|
+
else if (basicColors[c]) c = $.color(...basicColors[c]);
|
|
1029
1031
|
if (c.a <= 0) return ($._doStroke = false);
|
|
1030
1032
|
ctx.strokeStyle = c.toString();
|
|
1031
1033
|
};
|
|
@@ -1034,6 +1036,7 @@ function Q5(scope, parent) {
|
|
|
1034
1036
|
$._doFill = true;
|
|
1035
1037
|
$._fillSet = true;
|
|
1036
1038
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
1039
|
+
else if (basicColors[c]) c = $.color(...basicColors[c]);
|
|
1037
1040
|
if (c.a <= 0) return ($._doFill = false);
|
|
1038
1041
|
ctx.fillStyle = c.toString();
|
|
1039
1042
|
};
|
|
@@ -1059,7 +1062,8 @@ function Q5(scope, parent) {
|
|
|
1059
1062
|
if (c._q5) return $.image(c, 0, 0, $.width, $.height);
|
|
1060
1063
|
ctx.save();
|
|
1061
1064
|
ctx.resetTransform();
|
|
1062
|
-
if (!c.
|
|
1065
|
+
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
1066
|
+
else if (basicColors[c]) c = $.color(...basicColors[c]);
|
|
1063
1067
|
ctx.fillStyle = c.toString();
|
|
1064
1068
|
ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
|
|
1065
1069
|
ctx.restore();
|
|
@@ -2018,11 +2022,7 @@ function Q5(scope, parent) {
|
|
|
2018
2022
|
clearBuff();
|
|
2019
2023
|
firstVertex = true;
|
|
2020
2024
|
if (ctx) ctx.save();
|
|
2021
|
-
|
|
2022
|
-
$.draw();
|
|
2023
|
-
} catch (e) {
|
|
2024
|
-
console.error(e);
|
|
2025
|
-
}
|
|
2025
|
+
$.draw();
|
|
2026
2026
|
for (let m of Q5.prototype._methods.post) m.call($);
|
|
2027
2027
|
if (ctx) {
|
|
2028
2028
|
ctx.restore();
|
|
@@ -2311,6 +2311,72 @@ function Q5(scope, parent) {
|
|
|
2311
2311
|
return $.audioContext.resume();
|
|
2312
2312
|
};
|
|
2313
2313
|
|
|
2314
|
+
// AI
|
|
2315
|
+
|
|
2316
|
+
$.askAI = (q = '') => {
|
|
2317
|
+
throw Error('Ask AI ✨ ' + q);
|
|
2318
|
+
};
|
|
2319
|
+
|
|
2320
|
+
async function aiErrorAssistance(e) {
|
|
2321
|
+
let askAI = e.message.includes('Ask AI ✨');
|
|
2322
|
+
if (!askAI) console.error(e);
|
|
2323
|
+
if (Q5.disableFriendlyErrors) return;
|
|
2324
|
+
if (askAI || !Q5.errorTolerant) noLoop();
|
|
2325
|
+
let stackLines = e.stack.split('\n');
|
|
2326
|
+
if (stackLines.length <= 1) return;
|
|
2327
|
+
|
|
2328
|
+
let idx = 1;
|
|
2329
|
+
let sep = '(';
|
|
2330
|
+
if (navigator.userAgent.indexOf('Chrome') == -1) {
|
|
2331
|
+
idx = 0;
|
|
2332
|
+
sep = '@';
|
|
2333
|
+
}
|
|
2334
|
+
while (stackLines[idx].indexOf('q5.js:') >= 0) idx++;
|
|
2335
|
+
|
|
2336
|
+
let parts = stackLines[idx].split(sep).at(-1);
|
|
2337
|
+
parts = parts.split(':');
|
|
2338
|
+
let lineNum = parseInt(parts.at(-2));
|
|
2339
|
+
if (askAI) lineNum++;
|
|
2340
|
+
let fileUrl = parts.slice(0, -2).join(':');
|
|
2341
|
+
let fileBase = fileUrl.split('/').at(-1);
|
|
2342
|
+
|
|
2343
|
+
try {
|
|
2344
|
+
let res = await (await fetch(fileUrl)).text();
|
|
2345
|
+
let lines = res.split('\n');
|
|
2346
|
+
let errLine = lines[lineNum - 1].trim();
|
|
2347
|
+
|
|
2348
|
+
let context = '';
|
|
2349
|
+
let i = 1;
|
|
2350
|
+
while (context.length < 1600) {
|
|
2351
|
+
if (lineNum - i >= 0) {
|
|
2352
|
+
context = lines[lineNum - i].trim() + '\n' + context;
|
|
2353
|
+
}
|
|
2354
|
+
if (lineNum + i < lines.length) {
|
|
2355
|
+
context += lines[lineNum + i].trim() + '\n';
|
|
2356
|
+
}
|
|
2357
|
+
i++;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
let question =
|
|
2361
|
+
askAI && e.message.length > 10 ? e.message.slice(10) : 'Whats+wrong+with+this+line%3F+short+answer';
|
|
2362
|
+
|
|
2363
|
+
let url =
|
|
2364
|
+
'https://chatgpt.com/?q=q5.js+' +
|
|
2365
|
+
question +
|
|
2366
|
+
(askAI ? '' : '%0A%0A' + encodeURIComponent(e.name + ': ' + e.message)) +
|
|
2367
|
+
'%0A%0ALine%3A+' +
|
|
2368
|
+
encodeURIComponent(errLine) +
|
|
2369
|
+
'%0A%0AExcerpt+for+context%3A%0A%0A' +
|
|
2370
|
+
encodeURIComponent(context);
|
|
2371
|
+
|
|
2372
|
+
if (!askAI) console.log('Error in ' + fileBase + ' on line ' + lineNum + ':\n\n' + errLine);
|
|
2373
|
+
|
|
2374
|
+
console.warn('Ask AI ✨ ' + url);
|
|
2375
|
+
|
|
2376
|
+
if (askAI) window.open(url, '_blank');
|
|
2377
|
+
} catch (err) {}
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2314
2380
|
// INIT
|
|
2315
2381
|
|
|
2316
2382
|
if (scope == 'global') {
|
|
@@ -2354,7 +2420,7 @@ function Q5(scope, parent) {
|
|
|
2354
2420
|
|
|
2355
2421
|
let t = scope == 'global' ? (!Q5._nodejs ? window : global) : $;
|
|
2356
2422
|
let preloadDefined = t.preload;
|
|
2357
|
-
let
|
|
2423
|
+
let userFns = [
|
|
2358
2424
|
'setup',
|
|
2359
2425
|
'draw',
|
|
2360
2426
|
'preload',
|
|
@@ -2371,9 +2437,17 @@ function Q5(scope, parent) {
|
|
|
2371
2437
|
'touchEnded',
|
|
2372
2438
|
'windowResized'
|
|
2373
2439
|
];
|
|
2374
|
-
for (let k of
|
|
2440
|
+
for (let k of userFns) {
|
|
2375
2441
|
if (!t[k]) $[k] = () => {};
|
|
2376
|
-
else if ($._isGlobal)
|
|
2442
|
+
else if ($._isGlobal) {
|
|
2443
|
+
$[k] = () => {
|
|
2444
|
+
try {
|
|
2445
|
+
t[k]();
|
|
2446
|
+
} catch (e) {
|
|
2447
|
+
aiErrorAssistance(e);
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2377
2451
|
}
|
|
2378
2452
|
|
|
2379
2453
|
$._isTouchAware = $.touchStarted || $.touchMoved || $.mouseReleased;
|
|
@@ -2382,7 +2456,10 @@ function Q5(scope, parent) {
|
|
|
2382
2456
|
window.addEventListener('mousemove', (e) => $._onmousemove(e), false);
|
|
2383
2457
|
window.addEventListener('keydown', (e) => $._onkeydown(e), false);
|
|
2384
2458
|
window.addEventListener('keyup', (e) => $._onkeyup(e), false);
|
|
2385
|
-
window.addEventListener('resize', () =>
|
|
2459
|
+
window.addEventListener('resize', () => {
|
|
2460
|
+
$._shouldResize = true;
|
|
2461
|
+
if (!$._loop) $.redraw();
|
|
2462
|
+
});
|
|
2386
2463
|
}
|
|
2387
2464
|
|
|
2388
2465
|
if (!($.setup || $.draw)) return;
|
|
@@ -2765,7 +2842,7 @@ if (!window.matchMedia || !matchMedia('(dynamic-range: high) and (color-gamut: p
|
|
|
2765
2842
|
|
|
2766
2843
|
Q5._instanceCount = 0;
|
|
2767
2844
|
Q5._friendlyError = (msg, func) => {
|
|
2768
|
-
throw func + ': ' + msg;
|
|
2845
|
+
throw Error(func + ': ' + msg);
|
|
2769
2846
|
};
|
|
2770
2847
|
Q5._validateParameters = () => true;
|
|
2771
2848
|
|