p5 2.0.0 → 2.0.2
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/{src → dist}/accessibility/color_namer.js +48 -3
- package/{src → dist}/accessibility/describe.js +12 -2
- package/{src → dist}/accessibility/gridOutput.js +2 -2
- package/dist/accessibility/index.js +60 -0
- package/{src → dist}/accessibility/outputs.js +23 -2
- package/{src → dist}/accessibility/textOutput.js +2 -2
- package/dist/app.js +120 -0
- package/{src → dist}/color/color_conversion.js +48 -10
- package/{src → dist}/color/color_spaces/hsb.js +3 -1
- package/dist/color/creating_reading.js +3 -0
- package/dist/color/index.js +13 -0
- package/dist/color/p5.Color.culori.js +1 -0
- package/dist/color/p5.Color.js +3 -0
- package/{src → dist}/color/setting.js +9 -6
- package/{src/core/constants.js → dist/constants-tYr0tCl8.js} +284 -132
- package/{src → dist}/core/States.js +3 -1
- package/dist/core/constants.js +1 -0
- package/{src → dist}/core/environment.js +12 -10
- package/{src → dist}/core/friendly_errors/browser_errors.js +1 -1
- package/{src → dist}/core/friendly_errors/fes_core.js +14 -44
- package/{src → dist}/core/friendly_errors/file_errors.js +6 -3
- package/dist/core/friendly_errors/index.js +23 -0
- package/dist/core/friendly_errors/param_validator.js +5421 -0
- package/{src → dist}/core/friendly_errors/sketch_reader.js +50 -4
- package/{src → dist}/core/friendly_errors/sketch_verifier.js +6 -6
- package/{src → dist}/core/friendly_errors/stacktrace.js +3 -5
- package/{src → dist}/core/friendly_errors/validate_params.js +50 -41
- package/{src → dist}/core/helpers.js +9 -6
- package/dist/core/init.js +105 -0
- package/dist/core/internationalization.js +302 -0
- package/dist/core/legacy.js +73 -0
- package/dist/core/main.js +44 -0
- package/dist/core/noop.js +3 -0
- package/dist/core/p5.Graphics.js +40 -0
- package/dist/core/p5.Renderer.js +11 -0
- package/dist/core/p5.Renderer2D.js +44 -0
- package/dist/core/reference.js +1 -0
- package/dist/core/rendering.js +40 -0
- package/{src → dist}/core/structure.js +3 -3
- package/{src → dist}/core/transform.js +2 -2
- package/{src/color/creating_reading.js → dist/creating_reading-Cr8L2Jnm.js} +841 -13
- package/{src → dist}/data/index.js +3 -1
- package/{src → dist}/data/local_storage.js +2 -8
- package/{src → dist}/dom/dom.js +19 -13
- package/dist/dom/index.js +18 -0
- package/{src → dist}/dom/p5.Element.js +14 -12
- package/{src → dist}/dom/p5.File.js +4 -4
- package/{src → dist}/dom/p5.MediaElement.js +10 -4
- package/{src → dist}/events/acceleration.js +26 -26
- package/{src → dist}/events/index.js +3 -1
- package/{src → dist}/events/keyboard.js +14 -12
- package/{src → dist}/events/pointer.js +16 -17
- package/dist/image/const.js +9 -0
- package/{src → dist}/image/filterRenderer2D.js +57 -37
- package/{src → dist}/image/filters.js +1 -3
- package/dist/image/image.js +40 -0
- package/dist/image/index.js +51 -0
- package/dist/image/loading_displaying.js +40 -0
- package/dist/image/p5.Image.js +11 -0
- package/{src → dist}/image/pixels.js +5 -3
- package/{src → dist}/io/csv.js +72 -70
- package/dist/io/files.js +40 -0
- package/dist/io/index.js +51 -0
- package/{src → dist}/io/p5.Table.js +6 -6
- package/{src → dist}/io/p5.TableRow.js +5 -6
- package/{src → dist}/io/p5.XML.js +2 -5
- package/{src → dist}/io/utilities.js +1 -1
- package/{src/core/p5.Renderer2D.js → dist/main-CAxvgiOV.js} +738 -57
- package/{src → dist}/math/Matrices/Matrix.js +10 -8
- package/{src → dist}/math/Matrices/MatrixInterface.js +5 -3
- package/{src → dist}/math/Matrices/MatrixNumjs.js +12 -26
- package/{src → dist}/math/calculation.js +2 -2
- package/{src → dist}/math/index.js +6 -3
- package/{src → dist}/math/math.js +3 -3
- package/{src → dist}/math/noise.js +2 -2
- package/{src → dist}/math/p5.Matrix.js +7 -4
- package/{src → dist}/math/p5.Vector.js +6 -6
- package/{src → dist}/math/random.js +2 -2
- package/{src → dist}/math/trigonometry.js +16 -15
- package/{src/image/p5.Image.js → dist/p5.Renderer-Swjl9HQO.js} +393 -22
- package/dist/rendering-B5TRR7aY.js +24960 -0
- package/{src → dist}/shape/2d_primitives.js +18 -17
- package/{src → dist}/shape/attributes.js +18 -17
- package/{src → dist}/shape/curves.js +2 -2
- package/{src → dist}/shape/custom_shapes.js +44 -64
- package/{src → dist}/shape/index.js +10 -2
- package/{src → dist}/shape/vertex.js +2 -3
- package/dist/type/index.js +25 -0
- package/{src → dist}/type/lib/Typr.js +76 -94
- package/{src → dist}/type/p5.Font.js +37 -63
- package/{src → dist}/type/textCore.js +35 -58
- package/{src → dist}/type/unicodeRanges.js +3 -1
- package/{src → dist}/utilities/conversion.js +2 -2
- package/{src → dist}/utilities/index.js +3 -1
- package/{src → dist}/utilities/time_date.js +6 -7
- package/{src → dist}/utilities/utility_functions.js +2 -2
- package/dist/webgl/3d_primitives.js +40 -0
- package/{src → dist}/webgl/GeometryBufferCache.js +3 -1
- package/{src → dist}/webgl/GeometryBuilder.js +12 -8
- package/{src → dist}/webgl/ShaderGenerator.js +79 -82
- package/{src → dist}/webgl/ShapeBuilder.js +26 -23
- package/dist/webgl/index.js +76 -0
- package/{src → dist}/webgl/interaction.js +7 -6
- package/dist/webgl/light.js +40 -0
- package/{src → dist}/webgl/loading.js +45 -12
- package/dist/webgl/material.js +40 -0
- package/dist/webgl/p5.Camera.js +40 -0
- package/{src → dist}/webgl/p5.DataArray.js +3 -5
- package/dist/webgl/p5.Framebuffer.js +40 -0
- package/{src → dist}/webgl/p5.Geometry.js +12 -15
- package/{src → dist}/webgl/p5.Quat.js +5 -4
- package/{src → dist}/webgl/p5.RenderBuffer.js +2 -3
- package/dist/webgl/p5.RendererGL.js +40 -0
- package/dist/webgl/p5.Shader.js +40 -0
- package/dist/webgl/p5.Texture.js +40 -0
- package/{src → dist}/webgl/text.js +78 -38
- package/lib/p5.esm.js +296 -194
- package/lib/p5.js +296 -194
- package/lib/p5.min.js +1 -1
- package/package.json +17 -17
- package/translations/dev.js +6 -6
- package/translations/index.js +1 -1
- package/types/accessibility/color_namer.d.ts +8 -0
- package/types/accessibility/describe.d.ts +184 -0
- package/types/accessibility/gridOutput.d.ts +8 -0
- package/types/accessibility/outputs.d.ts +235 -0
- package/types/accessibility/textOutput.d.ts +8 -0
- package/types/color/color_conversion.d.ts +47 -0
- package/types/color/creating_reading.d.ts +1348 -0
- package/types/color/p5.Color.d.ts +1070 -0
- package/types/color/setting.d.ts +2085 -0
- package/types/core/constants.d.ts +341 -0
- package/types/core/environment.d.ts +668 -0
- package/types/core/friendly_errors/fes_core.d.ts +8 -0
- package/types/core/friendly_errors/file_errors.d.ts +8 -0
- package/types/core/friendly_errors/param_validator.d.ts +30 -0
- package/types/core/friendly_errors/sketch_reader.d.ts +8 -0
- package/types/core/friendly_errors/stacktrace.d.ts +11 -0
- package/types/core/friendly_errors/validate_params.d.ts +8 -0
- package/types/core/helpers.d.ts +8 -0
- package/types/core/legacy.d.ts +8 -0
- package/types/core/main.d.ts +5996 -0
- package/types/core/p5.Graphics.d.ts +484 -0
- package/types/core/p5.Renderer.d.ts +14 -0
- package/types/core/reference.d.ts +8 -0
- package/types/core/rendering.d.ts +481 -0
- package/types/core/structure.d.ts +492 -0
- package/types/core/transform.d.ts +1638 -0
- package/types/data/local_storage.d.ts +323 -0
- package/types/dom/dom.d.ts +1295 -0
- package/types/dom/p5.Element.d.ts +2011 -0
- package/types/dom/p5.File.d.ts +13 -0
- package/types/dom/p5.MediaElement.d.ts +1249 -0
- package/types/events/acceleration.d.ts +193 -0
- package/types/events/keyboard.d.ts +499 -0
- package/types/events/pointer.d.ts +782 -0
- package/types/global.d.ts +5542 -0
- package/types/image/filterRenderer2D.d.ts +54 -0
- package/types/image/image.d.ts +326 -0
- package/types/image/loading_displaying.d.ts +580 -0
- package/types/image/p5.Image.d.ts +5882 -0
- package/types/image/pixels.d.ts +832 -0
- package/types/io/files.d.ts +1447 -0
- package/types/io/p5.Table.d.ts +1247 -0
- package/types/io/p5.TableRow.d.ts +343 -0
- package/types/io/p5.XML.d.ts +1188 -0
- package/types/math/Matrices/Matrix.d.ts +1029 -0
- package/types/math/Matrices/MatrixNumjs.d.ts +8 -0
- package/types/math/calculation.d.ts +923 -0
- package/types/math/math.d.ts +90 -0
- package/types/math/noise.d.ts +311 -0
- package/types/math/p5.Matrix.d.ts +8 -0
- package/types/math/p5.Vector.d.ts +3416 -0
- package/types/math/random.d.ts +267 -0
- package/types/math/trigonometry.d.ts +663 -0
- package/types/p5.d.ts +6663 -0
- package/types/shape/2d_primitives.d.ts +1033 -0
- package/types/shape/attributes.d.ts +466 -0
- package/types/shape/curves.d.ts +740 -0
- package/types/shape/custom_shapes.d.ts +888 -0
- package/types/shape/vertex.d.ts +1141 -0
- package/types/type/p5.Font.d.ts +575 -0
- package/types/type/textCore.d.ts +1198 -0
- package/types/utilities/conversion.d.ts +894 -0
- package/types/utilities/time_date.d.ts +295 -0
- package/types/utilities/utility_functions.d.ts +587 -0
- package/types/webgl/3d_primitives.d.ts +1432 -0
- package/types/webgl/ShaderGenerator.d.ts +8 -0
- package/types/webgl/interaction.d.ts +371 -0
- package/types/webgl/light.d.ts +1184 -0
- package/types/webgl/loading.d.ts +481 -0
- package/types/webgl/material.d.ts +2656 -0
- package/types/webgl/p5.Camera.d.ts +3023 -0
- package/types/webgl/p5.DataArray.d.ts +61 -0
- package/types/webgl/p5.Framebuffer.d.ts +760 -0
- package/types/webgl/p5.Geometry.d.ts +1191 -0
- package/types/webgl/p5.Quat.d.ts +45 -0
- package/types/webgl/p5.RendererGL.d.ts +234 -0
- package/types/webgl/p5.Shader.d.ts +660 -0
- package/types/webgl/p5.Texture.d.ts +61 -0
- package/types/webgl/text.d.ts +74 -0
- package/src/README.md +0 -27
- package/src/accessibility/index.js +0 -13
- package/src/app.js +0 -61
- package/src/color/index.js +0 -9
- package/src/color/p5.Color.culori.js +0 -66
- package/src/color/p5.Color.js +0 -851
- package/src/core/README.md +0 -91
- package/src/core/friendly_errors/index.js +0 -13
- package/src/core/friendly_errors/param_validator.js +0 -561
- package/src/core/init.js +0 -58
- package/src/core/internationalization.js +0 -195
- package/src/core/legacy.js +0 -29
- package/src/core/main.js +0 -689
- package/src/core/noop.js +0 -1
- package/src/core/p5.Graphics.js +0 -696
- package/src/core/p5.Renderer.js +0 -408
- package/src/core/reference.js +0 -2060
- package/src/core/rendering.js +0 -697
- package/src/dom/index.js +0 -11
- package/src/image/const.js +0 -6
- package/src/image/image.js +0 -731
- package/src/image/index.js +0 -15
- package/src/image/loading_displaying.js +0 -1431
- package/src/io/files.js +0 -2210
- package/src/io/index.js +0 -11
- package/src/math/README.md +0 -40
- package/src/type/index.js +0 -9
- package/src/webgl/3d_primitives.js +0 -2741
- package/src/webgl/index.js +0 -37
- package/src/webgl/light.js +0 -1851
- package/src/webgl/material.js +0 -3854
- package/src/webgl/p5.Camera.js +0 -4010
- package/src/webgl/p5.Framebuffer.js +0 -1865
- package/src/webgl/p5.RendererGL.js +0 -2867
- package/src/webgl/p5.Shader.js +0 -1505
- package/src/webgl/p5.Texture.js +0 -541
- package/src/webgl/shaders/basic.frag +0 -6
- package/src/webgl/shaders/filters/base.frag +0 -22
- package/src/webgl/shaders/filters/base.vert +0 -19
- package/src/webgl/shaders/filters/blur.frag +0 -60
- package/src/webgl/shaders/filters/default.vert +0 -18
- package/src/webgl/shaders/filters/dilate.frag +0 -39
- package/src/webgl/shaders/filters/erode.frag +0 -39
- package/src/webgl/shaders/filters/gray.frag +0 -16
- package/src/webgl/shaders/filters/invert.frag +0 -15
- package/src/webgl/shaders/filters/opaque.frag +0 -12
- package/src/webgl/shaders/filters/posterize.frag +0 -29
- package/src/webgl/shaders/filters/threshold.frag +0 -23
- package/src/webgl/shaders/font.frag +0 -216
- package/src/webgl/shaders/font.vert +0 -44
- package/src/webgl/shaders/imageLight.vert +0 -33
- package/src/webgl/shaders/imageLightDiffused.frag +0 -82
- package/src/webgl/shaders/imageLightSpecular.frag +0 -134
- package/src/webgl/shaders/light.vert +0 -37
- package/src/webgl/shaders/light_texture.frag +0 -26
- package/src/webgl/shaders/lighting.glsl +0 -227
- package/src/webgl/shaders/line.frag +0 -74
- package/src/webgl/shaders/line.vert +0 -294
- package/src/webgl/shaders/normal.frag +0 -6
- package/src/webgl/shaders/normal.vert +0 -72
- package/src/webgl/shaders/phong.frag +0 -84
- package/src/webgl/shaders/phong.vert +0 -87
- package/src/webgl/shaders/point.frag +0 -29
- package/src/webgl/shaders/point.vert +0 -19
- package/src/webgl/shaders/sphereMapping.frag +0 -26
- package/src/webgl/shaders/webgl2Compatibility.glsl +0 -34
package/src/core/README.md
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# p5.js Core
|
|
2
|
-
|
|
3
|
-
This folder contains the core functionality of p5.js, including the init and main files, environment, constants, the friendly error system, and the graphics pipeline (with the exception of 3D/WebGL). [Here is a diagram](
|
|
4
|
-
https://sketchboard.me/zBOkvPuQisyA#/) that outlines how the main graphics-related classes inherit from and extend one another. There is still more to be done to document this pipeline more clearly.
|
|
5
|
-
|
|
6
|
-

|
|
7
|
-
|
|
8
|
-
## [init.js](./init.js)
|
|
9
|
-
|
|
10
|
-
The `init.js` module initializes a new `p5` object in either global mode, instance mode, or unit testing mode. Broadly speaking, this module should only contain logic that needs to execute *before startup*, such as testing the environment in which the code is running in order to make decisions about how it should load.
|
|
11
|
-
|
|
12
|
-
## [main.js](./main.js)
|
|
13
|
-
|
|
14
|
-
The sole job of the `main.js` module is to create and then export the constructor function for creating a new `p5` object. This constructor function is also called `p5`, and doesn't use the typical JavaScript convention of capitalizing constructor functions. The constructor handles a number of mechanical startup concerns, including assigning functions and properties from elsewhere in the source code to the newly created `p5` object as either public or private methods and properties.
|
|
15
|
-
|
|
16
|
-
Aside from the exported constructor function, the most important thing in this module is the set of functions that define the loop used by nearly every p5.js project: `preload()`, `setup()`, `draw()`, `remove()`, and so on. These functions are both available on the `p5` object as methods, and also assigned to variables in the global space for syntactic simplicity, because calling a function named `draw()` is more creatively expressive than namespacing the same functionality with an object as with `mySketch.draw()` or similar. The `friendlyBindGlobal()` function standardizes the process by which the necessary global variables can be created, notably including logging [friendly error messages](https://github.com/processing/p5.js/blob/main/contributor_docs/friendly_error_system.md) when conflicts are detected, but it is not exported from the module's internal scope.
|
|
17
|
-
|
|
18
|
-
## [structure.js](./structure.js)
|
|
19
|
-
|
|
20
|
-
The `structure.js` module is best thought of as a collection of ways to make *modifications* to the typical *loop structure* exposed by the `draw()` function. The functions in this module allow you to add and extract individual renders from the loop, draw the loop one frame at a time, pause and resume the loop, and so on.
|
|
21
|
-
|
|
22
|
-
## [constants.js](./constants.js)
|
|
23
|
-
|
|
24
|
-
The `constants.js` module provides various default values mostly related to math and web standards using clear semantic names to increase syntax clarity when they are used in other algorithms. These values are attached to the `p5` object prototype as properties by the constructor function so they can be more easily accessed by other parts of the p5.js library or by user code.
|
|
25
|
-
|
|
26
|
-
## [friendly_errors/fes_core.js](./friendly_errors/fes_core.js)
|
|
27
|
-
This is the main file for the Friendly Error System (FES). The Friendly Error System (FES) is a system designed to help new programmers with common user errors as they get started learning. It catches common beginning errors and provides clear language and links to help a user resolve the error. FES is only applied to functions that are ones a user might encounter when they are just starting. You can learn more about the FES in the comment section at the top of this file, or in the [contributors_docs/friendly_error_system.md](https://github.com/processing/p5.js/blob/main/contributor_docs/friendly_error_system.md) file.
|
|
28
|
-
|
|
29
|
-
## [legacy.js](./legacy.js)
|
|
30
|
-
These are functions that are part of the Processing API but are not part of the p5.js API. In some cases they have a new name, in others, they are removed completely. Not all unsupported Processing functions are listed here but we try to include ones that a user coming from Processing might likely call.
|
|
31
|
-
|
|
32
|
-
# Browser
|
|
33
|
-
|
|
34
|
-
*utilizing and abstracting web technologies*
|
|
35
|
-
|
|
36
|
-
## [environment.js](./environment.js)
|
|
37
|
-
|
|
38
|
-
The `environment.js` module detects and semantically reassigns various features of the code execution environment that are arguably beyond the control of the p5.js library, such as device properties, window dimensions, and the URL bar. In general, this module should only contain code that exposes mechanics of the web that usually would not be considered part of the p5.js "sketch." This module is conceptually similar to `init.js` in that it tests the environment in which the p5.js code is executing, but one major difference is that broadly speaking the code in `environment.js` does *not* need to run solely at initialization as with `init.js`, and can be invoked whenever necessary.
|
|
39
|
-
|
|
40
|
-
## [shim.js](./shim.js)
|
|
41
|
-
|
|
42
|
-
Sometimes p5.js needs to use new browser APIs or other features which haven't yet been completely standardized; for example, a feature that still uses [vendor prefixes](https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix). In any such cases where it is necessary to handle multiple versions of the same functionality, the `shim.js` module juggles the available variants and assigns the results of that evaluation to a standardized property on the `p5` object. The rest of the p5.js library can then use that functionality without needing to constantly reconsider the specific browser implementation details.
|
|
43
|
-
|
|
44
|
-
## [p5.Element.js](./p5.Element.js)
|
|
45
|
-
|
|
46
|
-
Although p5.js is a general toolkit for all sorts of interactive art projects, in practice many p5.js sketches focus on rendering two dimensional graphics into a `<canvas>` element. The `p5.Element.js` module is a wrapper around the browser's DOM API which is focused on the `<canvas>` element and also handles user input events like clicks and mouse movements. Conceptually, p5.js considers the sketch to be *the entire web page*. It's useful to separate `<canvas>` from the more general DOM because so many p5.js projects focus on `<canvas>` and this enables smaller [custom builds](https://github.com/processing/p5.js/blob/main/contributor_docs/custom_p5_build.md).
|
|
47
|
-
|
|
48
|
-
# Rendering
|
|
49
|
-
|
|
50
|
-
*project output options*
|
|
51
|
-
|
|
52
|
-
## [rendering.js](./rendering.js)
|
|
53
|
-
|
|
54
|
-
The `rendering.js` module presents the user-facing API for p5's various graphical output options. In the overwhelming majority of cases, a p5.js sketch will be output to a `<canvas>` tag on the current web page, but it is also possible to do "headless" output using `nocanvas` mode or "render" to a graphics buffer that is computed but never actually appears on the screen.
|
|
55
|
-
|
|
56
|
-
## [p5.Renderer.js](./p5.Renderer.js)
|
|
57
|
-
|
|
58
|
-
The `p5.Renderer.js` module provides a common base definition for a p5 project output mode that can then be extended as with [p5.Renderer2D](./p5.Renderer2D.js). For three dimensional output, see the [webgl module](../webgl/). Each `p5` object instance typically has a `Renderer` attached as a property.
|
|
59
|
-
|
|
60
|
-
## [p5.Renderer2D.js](./p5.Renderer2D.js)
|
|
61
|
-
|
|
62
|
-
The `p5.Renderer2D.js` module extends the generic `p5.Renderer` definition and optimizes it for two dimensional images.
|
|
63
|
-
|
|
64
|
-
## [p5.Graphics.js](./p5.Graphics.js)
|
|
65
|
-
|
|
66
|
-
The `p5.Graphics` module is a lightweight wrapper around renderers which is used to create output graphics in memory without ever actually drawing them on the screen.
|
|
67
|
-
|
|
68
|
-
# Drawing
|
|
69
|
-
|
|
70
|
-
*lines, shapes, and visual styles*
|
|
71
|
-
|
|
72
|
-
## [transform.js](./transform.js)
|
|
73
|
-
|
|
74
|
-
The `transform.js` module implements logic for scaling, rotation, and matrix transformations.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
## [shape/attributes.js](./shape/attributes.js)
|
|
78
|
-
|
|
79
|
-
Attributes are an important part of the general API for the web, but the `attributes.js` module defines and handles miscellaneous *graphical* attributes that can be consider a set of active parameters for the current drawing style. Think of this as a grab bag of all the remaining drawing parameters that were not moved out into separate dedicated modules as with [color](../color/) and [typography](../typography/).
|
|
80
|
-
|
|
81
|
-
## [shape/2d_primitives.js](./shape/2d_primitives.js)
|
|
82
|
-
|
|
83
|
-
The `2d_primitives.js` module provides helper functions for drawing common shapes. The resulting drawing commands are sent to the currently active [renderer](./rendering.js).
|
|
84
|
-
|
|
85
|
-
## [shape/vertex.js](./shape/vertex.js)
|
|
86
|
-
|
|
87
|
-
The `vertex.js` module handles points and coordinates for drawing curves and shapes.
|
|
88
|
-
|
|
89
|
-
## [shape/curves.js](./shape/curves.js)
|
|
90
|
-
|
|
91
|
-
The `curves.js` module draws curves based on a set of vertices.
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import fesCore from './fes_core';
|
|
2
|
-
import stacktrace from './stacktrace';
|
|
3
|
-
import validateParams from './param_validator.js';
|
|
4
|
-
import sketchVerifier from './sketch_verifier.js';
|
|
5
|
-
import fileErrors from './file_errors';
|
|
6
|
-
|
|
7
|
-
export default function (p5) {
|
|
8
|
-
p5.registerAddon(fesCore);
|
|
9
|
-
p5.registerAddon(stacktrace);
|
|
10
|
-
p5.registerAddon(validateParams);
|
|
11
|
-
p5.registerAddon(sketchVerifier);
|
|
12
|
-
p5.registerAddon(fileErrors);
|
|
13
|
-
}
|
|
@@ -1,561 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @for p5
|
|
3
|
-
* @requires core
|
|
4
|
-
*/
|
|
5
|
-
import * as constants from '../constants.js';
|
|
6
|
-
import * as z from 'zod';
|
|
7
|
-
import dataDoc from '../../../docs/parameterData.json';
|
|
8
|
-
|
|
9
|
-
function validateParams(p5, fn, lifecycles) {
|
|
10
|
-
// Cache for Zod schemas
|
|
11
|
-
let schemaRegistry = new Map();
|
|
12
|
-
|
|
13
|
-
// Mapping names of p5 types to their constructor functions.
|
|
14
|
-
// p5Constructors:
|
|
15
|
-
// - Color: f()
|
|
16
|
-
// - Graphics: f()
|
|
17
|
-
// - Vector: f()
|
|
18
|
-
// and so on.
|
|
19
|
-
// const p5Constructors = {};
|
|
20
|
-
// NOTE: This is a tempt fix for unit test but is not correct
|
|
21
|
-
// Attaced constructors are `undefined`
|
|
22
|
-
const p5Constructors = Object.keys(p5).reduce((acc, val) => {
|
|
23
|
-
if (
|
|
24
|
-
val.match(/^[A-Z]/) && // Starts with a capital
|
|
25
|
-
!val.match(/^[A-Z][A-Z0-9]*$/) && // Is not an all caps constant
|
|
26
|
-
p5[val] instanceof Function // Is a function
|
|
27
|
-
) {
|
|
28
|
-
acc[val] = p5[val];
|
|
29
|
-
}
|
|
30
|
-
return acc;
|
|
31
|
-
}, {});
|
|
32
|
-
|
|
33
|
-
function loadP5Constructors() {
|
|
34
|
-
// Make a list of all p5 classes to be used for argument validation
|
|
35
|
-
// This must be done only when everything has loaded otherwise we get
|
|
36
|
-
// an empty array
|
|
37
|
-
for (let key of Object.keys(p5)) {
|
|
38
|
-
// Get a list of all constructors in p5. They are functions whose names
|
|
39
|
-
// start with a capital letter
|
|
40
|
-
if (typeof p5[key] === 'function' && key[0] !== key[0].toLowerCase()) {
|
|
41
|
-
p5Constructors[key] = p5[key];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// `constantsMap` maps constants to their values, e.g.
|
|
47
|
-
// {
|
|
48
|
-
// ADD: 'lighter',
|
|
49
|
-
// ALT: 18,
|
|
50
|
-
// ARROW: 'default',
|
|
51
|
-
// AUTO: 'auto',
|
|
52
|
-
// ...
|
|
53
|
-
// }
|
|
54
|
-
const constantsMap = {};
|
|
55
|
-
for (const [key, value] of Object.entries(constants)) {
|
|
56
|
-
constantsMap[key] = value;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Start initializing `schemaMap` with primitive types. `schemaMap` will
|
|
60
|
-
// eventually contain both primitive types and web API objects.
|
|
61
|
-
const schemaMap = {
|
|
62
|
-
'Any': z.any(),
|
|
63
|
-
'Array': z.array(z.any()),
|
|
64
|
-
'Boolean': z.boolean(),
|
|
65
|
-
'Function': z.function(),
|
|
66
|
-
'Integer': z.number().int(),
|
|
67
|
-
'Number': z.number(),
|
|
68
|
-
'Object': z.object({}),
|
|
69
|
-
'String': z.string(),
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const webAPIObjects = [
|
|
73
|
-
'AudioNode',
|
|
74
|
-
'HTMLCanvasElement',
|
|
75
|
-
'HTMLElement',
|
|
76
|
-
'KeyboardEvent',
|
|
77
|
-
'MouseEvent',
|
|
78
|
-
'RegExp',
|
|
79
|
-
'TouchEvent',
|
|
80
|
-
'UIEvent',
|
|
81
|
-
'WheelEvent'
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
function generateWebAPISchemas(apiObjects) {
|
|
85
|
-
return apiObjects.reduce((acc, obj) => {
|
|
86
|
-
acc[obj] = z.custom(data => data instanceof globalThis[obj], {
|
|
87
|
-
message: `Expected a ${obj}`
|
|
88
|
-
});
|
|
89
|
-
return acc;
|
|
90
|
-
}, {});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const webAPISchemas = generateWebAPISchemas(webAPIObjects);
|
|
94
|
-
// Add web API schemas to the schema map.
|
|
95
|
-
Object.assign(schemaMap, webAPISchemas);
|
|
96
|
-
|
|
97
|
-
// For mapping 0-indexed parameters to their ordinal representation, e.g.
|
|
98
|
-
// "first" for 0, "second" for 1, "third" for 2, etc.
|
|
99
|
-
const ordinals = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth"];
|
|
100
|
-
|
|
101
|
-
function extractFuncNameAndClass(func) {
|
|
102
|
-
const ichDot = func.lastIndexOf('.');
|
|
103
|
-
const funcName = func.slice(ichDot + 1);
|
|
104
|
-
const funcClass = func.slice(0, ichDot !== -1 ? ichDot : 0) || 'p5';
|
|
105
|
-
return { funcName, funcClass };
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function validBracketNesting(type) {
|
|
109
|
-
let level = 0;
|
|
110
|
-
for (let i = 0; i < type.length; i++) {
|
|
111
|
-
if (type[i] === '[') {
|
|
112
|
-
level++;
|
|
113
|
-
} else if (type[i] === ']') {
|
|
114
|
-
level--;
|
|
115
|
-
if (level < 0) return false;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return level === 0;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* This is a helper function that generates Zod schemas for a function based on
|
|
123
|
-
* the parameter data from `docs/parameterData.json`.
|
|
124
|
-
*
|
|
125
|
-
* Example parameter data for function `background`:
|
|
126
|
-
* "background": {
|
|
127
|
-
"overloads": [
|
|
128
|
-
["p5.Color"],
|
|
129
|
-
["String", "Number?"],
|
|
130
|
-
["Number", "Number?"],
|
|
131
|
-
["Number", "Number", "Number", "Number?"],
|
|
132
|
-
["Number[]"],
|
|
133
|
-
["p5.Image", "Number?"]
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
* Where each array in `overloads` represents a set of valid overloaded
|
|
137
|
-
* parameters, and `?` is a shorthand for `Optional`.
|
|
138
|
-
*
|
|
139
|
-
* @method generateZodSchemasForFunc
|
|
140
|
-
* @param {String} func - Name of the function. Expect global functions like `sin` and class methods like `p5.Vector.add`
|
|
141
|
-
* @returns {z.ZodSchema} Zod schema
|
|
142
|
-
*/
|
|
143
|
-
fn.generateZodSchemasForFunc = function (func) {
|
|
144
|
-
const { funcName, funcClass } = extractFuncNameAndClass(func);
|
|
145
|
-
let funcInfo = dataDoc[funcClass][funcName];
|
|
146
|
-
|
|
147
|
-
if(!funcInfo) return;
|
|
148
|
-
|
|
149
|
-
let overloads = [];
|
|
150
|
-
if (funcInfo.hasOwnProperty('overloads')) {
|
|
151
|
-
overloads = funcInfo.overloads;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Returns a schema for a single type, i.e. z.boolean() for `boolean`.
|
|
155
|
-
const generateTypeSchema = baseType => {
|
|
156
|
-
if (!baseType) return z.any();
|
|
157
|
-
|
|
158
|
-
let typeSchema;
|
|
159
|
-
|
|
160
|
-
// Check for constants. Note that because we're ultimately interested in the value of
|
|
161
|
-
// the constant, mapping constants to their values via `constantsMap` is
|
|
162
|
-
// necessary.
|
|
163
|
-
if (baseType in constantsMap) {
|
|
164
|
-
typeSchema = z.literal(constantsMap[baseType]);
|
|
165
|
-
}
|
|
166
|
-
// Some more constants are attached directly to p5.prototype, e.g. by addons:
|
|
167
|
-
else if (baseType.match(/^[A-Z][A-Z0-9]*$/) && baseType in fn) {
|
|
168
|
-
typeSchema = z.literal(fn[baseType]);
|
|
169
|
-
}
|
|
170
|
-
// Function types
|
|
171
|
-
else if (baseType.startsWith('function')) {
|
|
172
|
-
typeSchema = z.function();
|
|
173
|
-
}
|
|
174
|
-
// All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`.
|
|
175
|
-
else if (/^p5\.[a-zA-Z0-9]+$/.exec(baseType) || baseType === 'p5') {
|
|
176
|
-
const className = baseType.substring(baseType.indexOf('.') + 1);
|
|
177
|
-
typeSchema = z.instanceof(p5Constructors[className]);
|
|
178
|
-
}
|
|
179
|
-
// For primitive types and web API objects.
|
|
180
|
-
else if (schemaMap[baseType]) {
|
|
181
|
-
typeSchema = schemaMap[baseType];
|
|
182
|
-
}
|
|
183
|
-
// Tuple types
|
|
184
|
-
else if (
|
|
185
|
-
baseType.startsWith('[') &&
|
|
186
|
-
baseType.endsWith(']') &&
|
|
187
|
-
validBracketNesting(baseType.slice(1, -1))
|
|
188
|
-
) {
|
|
189
|
-
typeSchema = z.tuple(
|
|
190
|
-
baseType
|
|
191
|
-
.slice(1, -1)
|
|
192
|
-
.split(/, */g)
|
|
193
|
-
.map(entry => generateTypeSchema(entry))
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
// JavaScript classes, e.g. Request
|
|
197
|
-
else if (baseType.match(/^[A-Z]/) && baseType in window) {
|
|
198
|
-
typeSchema = z.instanceof(window[baseType]);
|
|
199
|
-
}
|
|
200
|
-
// Generate a schema for a single parameter that can be of multiple
|
|
201
|
-
// types / constants, i.e. `String|Number|Array`.
|
|
202
|
-
//
|
|
203
|
-
// Here, z.union() is used over z.enum() (which seems more intuitive) for
|
|
204
|
-
// constants for the following reasons:
|
|
205
|
-
// 1) z.enum() only allows a fixed set of allowable string values. However,
|
|
206
|
-
// our constants sometimes have numeric or non-primitive values.
|
|
207
|
-
// 2) In some cases, the type can be constants or strings, making z.enum()
|
|
208
|
-
// insufficient for the use case.
|
|
209
|
-
else if (baseType.includes('|') && baseType.split('|').every(t => validBracketNesting(t))) {
|
|
210
|
-
const types = baseType.split('|');
|
|
211
|
-
typeSchema = z.union(types
|
|
212
|
-
.map(t => generateTypeSchema(t))
|
|
213
|
-
.filter(s => s !== undefined));
|
|
214
|
-
} else if (baseType.endsWith('[]')) {
|
|
215
|
-
typeSchema = z.array(generateTypeSchema(baseType.slice(0, -2)));
|
|
216
|
-
} else {
|
|
217
|
-
throw new Error(`Unsupported type '${baseType}' in parameter validation. Please report this issue.`);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return typeSchema;
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
// Generate a schema for a single parameter. In the case where a parameter can
|
|
224
|
-
// be of multiple types, `generateTypeSchema` is called for each type.
|
|
225
|
-
const generateParamSchema = param => {
|
|
226
|
-
const isOptional = param?.endsWith('?');
|
|
227
|
-
param = param?.replace(/\?$/, '');
|
|
228
|
-
|
|
229
|
-
let schema = generateTypeSchema(param);
|
|
230
|
-
|
|
231
|
-
return isOptional ? schema.optional() : schema;
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// Note that in Zod, `optional()` only checks for undefined, not the absence
|
|
235
|
-
// of value.
|
|
236
|
-
//
|
|
237
|
-
// Let's say we have a function with 3 parameters, and the last one is
|
|
238
|
-
// optional, i.e. func(a, b, c?). If we only have a z.tuple() for the
|
|
239
|
-
// parameters, where the third schema is optional, then we will only be able
|
|
240
|
-
// to validate func(10, 10, undefined), but not func(10, 10), which is
|
|
241
|
-
// a completely valid call.
|
|
242
|
-
//
|
|
243
|
-
// Therefore, on top of using `optional()`, we also have to generate parameter
|
|
244
|
-
// combinations that are valid for all numbers of parameters.
|
|
245
|
-
const generateOverloadCombinations = params => {
|
|
246
|
-
// No optional parameters, return the original parameter list right away.
|
|
247
|
-
if (!params.some(p => p?.endsWith('?'))) {
|
|
248
|
-
return [params];
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const requiredParamsCount = params.filter(p => p === null || !p.endsWith('?')).length;
|
|
252
|
-
const result = [];
|
|
253
|
-
|
|
254
|
-
for (let i = requiredParamsCount; i <= params.length; i++) {
|
|
255
|
-
result.push(params.slice(0, i));
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return result;
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
// Generate schemas for each function overload and merge them
|
|
262
|
-
const overloadSchemas = overloads.flatMap(overload => {
|
|
263
|
-
const combinations = generateOverloadCombinations(overload);
|
|
264
|
-
|
|
265
|
-
return combinations.map(combo =>
|
|
266
|
-
z.tuple(
|
|
267
|
-
combo
|
|
268
|
-
.map(p => generateParamSchema(p))
|
|
269
|
-
// For now, ignore schemas that cannot be mapped to a defined type
|
|
270
|
-
.filter(schema => schema !== undefined)
|
|
271
|
-
)
|
|
272
|
-
);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
return overloadSchemas.length === 1
|
|
276
|
-
? overloadSchemas[0]
|
|
277
|
-
: z.union(overloadSchemas);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Finds the closest schema to the input arguments.
|
|
282
|
-
*
|
|
283
|
-
* This is a helper function that identifies the closest schema to the input
|
|
284
|
-
* arguments, in the case of an initial validation error. We will then use the
|
|
285
|
-
* closest schema to generate a friendly error message.
|
|
286
|
-
*
|
|
287
|
-
* @private
|
|
288
|
-
* @param {z.ZodSchema} schema - Zod schema.
|
|
289
|
-
* @param {Array} args - User input arguments.
|
|
290
|
-
* @returns {z.ZodSchema} Closest schema matching the input arguments.
|
|
291
|
-
*/
|
|
292
|
-
fn.findClosestSchema = function (schema, args) {
|
|
293
|
-
if (!(schema instanceof z.ZodUnion)) {
|
|
294
|
-
return schema;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Helper function that scores how close the input arguments are to a schema.
|
|
298
|
-
// Lower score means closer match.
|
|
299
|
-
const scoreSchema = schema => {
|
|
300
|
-
let score = Infinity;
|
|
301
|
-
if (!(schema instanceof z.ZodTuple)) {
|
|
302
|
-
console.warn('Schema below is not a tuple: ');
|
|
303
|
-
printZodSchema(schema);
|
|
304
|
-
return score;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const numArgs = args.length;
|
|
308
|
-
const schemaItems = schema.items;
|
|
309
|
-
const numSchemaItems = schemaItems.length;
|
|
310
|
-
const numRequiredSchemaItems = schemaItems.filter(item => !item.isOptional()).length;
|
|
311
|
-
|
|
312
|
-
if (numArgs >= numRequiredSchemaItems && numArgs <= numSchemaItems) {
|
|
313
|
-
score = 0;
|
|
314
|
-
}
|
|
315
|
-
// Here, give more weight to mismatch in number of arguments.
|
|
316
|
-
//
|
|
317
|
-
// For example, color() can either take [Number, Number?] or
|
|
318
|
-
// [Number, Number, Number, Number?] as list of parameters.
|
|
319
|
-
// If the user passed in 3 arguments, [10, undefined, undefined], it's
|
|
320
|
-
// more than likely that they intended to pass in 3 arguments, but the
|
|
321
|
-
// last two arguments are invalid.
|
|
322
|
-
//
|
|
323
|
-
// If there's no bias towards matching the number of arguments, the error
|
|
324
|
-
// message will show that we're expecting at most 2 arguments, but more
|
|
325
|
-
// are received.
|
|
326
|
-
else {
|
|
327
|
-
score = Math.abs(
|
|
328
|
-
numArgs < numRequiredSchemaItems ? numRequiredSchemaItems - numArgs : numArgs - numSchemaItems
|
|
329
|
-
) * 4;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
for (let i = 0; i < Math.min(schemaItems.length, args.length); i++) {
|
|
333
|
-
const paramSchema = schemaItems[i];
|
|
334
|
-
const arg = args[i];
|
|
335
|
-
|
|
336
|
-
if (!paramSchema.safeParse(arg).success) score++;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return score;
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
// Default to the first schema, so that we are guaranteed to return a result.
|
|
343
|
-
let closestSchema = schema._def.options[0];
|
|
344
|
-
// We want to return the schema with the lowest score.
|
|
345
|
-
let bestScore = Infinity;
|
|
346
|
-
|
|
347
|
-
const schemaUnion = schema._def.options;
|
|
348
|
-
schemaUnion.forEach(schema => {
|
|
349
|
-
const score = scoreSchema(schema);
|
|
350
|
-
if (score < bestScore) {
|
|
351
|
-
closestSchema = schema;
|
|
352
|
-
bestScore = score;
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
return closestSchema;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Prints a friendly error message after parameter validation, if validation
|
|
361
|
-
* has failed.
|
|
362
|
-
*
|
|
363
|
-
* @method _friendlyParamError
|
|
364
|
-
* @private
|
|
365
|
-
* @param {z.ZodError} zodErrorObj - The Zod error object containing validation errors.
|
|
366
|
-
* @param {String} func - Name of the function. Expect global functions like `sin` and class methods like `p5.Vector.add`
|
|
367
|
-
* @returns {String} The friendly error message.
|
|
368
|
-
*/
|
|
369
|
-
fn.friendlyParamError = function (zodErrorObj, func, args) {
|
|
370
|
-
let message = '🌸 p5.js says: ';
|
|
371
|
-
let isVersionError = false;
|
|
372
|
-
// The `zodErrorObj` might contain multiple errors of equal importance
|
|
373
|
-
// (after scoring the schema closeness in `findClosestSchema`). Here, we
|
|
374
|
-
// always print the first error so that user can work through the errors
|
|
375
|
-
// one by one.
|
|
376
|
-
let currentError = zodErrorObj.errors[0];
|
|
377
|
-
|
|
378
|
-
// Helper function to build a type mismatch message.
|
|
379
|
-
const buildTypeMismatchMessage = (actualType, expectedTypeStr, position) => {
|
|
380
|
-
const positionStr = position ? `at the ${ordinals[position]} parameter` : '';
|
|
381
|
-
const actualTypeStr = actualType ? `, but received ${actualType}` : '';
|
|
382
|
-
return `Expected ${expectedTypeStr} ${positionStr}${actualTypeStr}`;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Union errors occur when a parameter can be of multiple types but is not
|
|
386
|
-
// of any of them. In this case, aggregate all possible types and print
|
|
387
|
-
// a friendly error message that indicates what the expected types are at
|
|
388
|
-
// which position (position is not 0-indexed, for accessibility reasons).
|
|
389
|
-
const processUnionError = (error) => {
|
|
390
|
-
const expectedTypes = new Set();
|
|
391
|
-
let actualType;
|
|
392
|
-
|
|
393
|
-
error.unionErrors.forEach(err => {
|
|
394
|
-
const issue = err.issues[0];
|
|
395
|
-
if (issue) {
|
|
396
|
-
if (!actualType) {
|
|
397
|
-
actualType = issue.received;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
if (issue.code === 'invalid_type') {
|
|
401
|
-
expectedTypes.add(issue.expected);
|
|
402
|
-
}
|
|
403
|
-
// The case for constants. Since we don't want to print out the actual
|
|
404
|
-
// constant values in the error message, the error message will
|
|
405
|
-
// direct users to the documentation.
|
|
406
|
-
else if (issue.code === 'invalid_literal') {
|
|
407
|
-
expectedTypes.add("constant (please refer to documentation for allowed values)");
|
|
408
|
-
} else if (issue.code === 'custom') {
|
|
409
|
-
const match = issue.message.match(/Input not instance of (\w+)/);
|
|
410
|
-
if (match) expectedTypes.add(match[1]);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
if (expectedTypes.size > 0) {
|
|
416
|
-
if (error.path?.length > 0 && args[error.path[0]] instanceof Promise) {
|
|
417
|
-
message += 'Did you mean to put `await` before a loading function? ' +
|
|
418
|
-
'An unexpected Promise was found. ';
|
|
419
|
-
isVersionError = true;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
const expectedTypesStr = Array.from(expectedTypes).join(' or ');
|
|
423
|
-
const position = error.path.join('.');
|
|
424
|
-
|
|
425
|
-
message += buildTypeMismatchMessage(actualType, expectedTypesStr, position);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return message;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
switch (currentError.code) {
|
|
432
|
-
case 'invalid_union': {
|
|
433
|
-
processUnionError(currentError);
|
|
434
|
-
break;
|
|
435
|
-
}
|
|
436
|
-
case 'too_small': {
|
|
437
|
-
const minArgs = currentError.minimum;
|
|
438
|
-
message += `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`;
|
|
439
|
-
break;
|
|
440
|
-
}
|
|
441
|
-
case 'invalid_type': {
|
|
442
|
-
message += buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.'));
|
|
443
|
-
break;
|
|
444
|
-
}
|
|
445
|
-
case 'too_big': {
|
|
446
|
-
const maxArgs = currentError.maximum;
|
|
447
|
-
message += `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`;
|
|
448
|
-
break;
|
|
449
|
-
}
|
|
450
|
-
default: {
|
|
451
|
-
console.log('Zod error object', currentError);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// Let the user know which function is generating the error.
|
|
456
|
-
message += ` in ${func}().`;
|
|
457
|
-
|
|
458
|
-
// Generates a link to the documentation based on the given function name.
|
|
459
|
-
// TODO: Check if the link is reachable before appending it to the error
|
|
460
|
-
// message.
|
|
461
|
-
const generateDocumentationLink = (func) => {
|
|
462
|
-
const { funcName, funcClass } = extractFuncNameAndClass(func);
|
|
463
|
-
const p5BaseUrl = 'https://p5js.org/reference';
|
|
464
|
-
const url = `${p5BaseUrl}/${funcClass}/${funcName}`;
|
|
465
|
-
|
|
466
|
-
return url;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (currentError.code === 'too_big' || currentError.code === 'too_small') {
|
|
470
|
-
const documentationLink = generateDocumentationLink(func);
|
|
471
|
-
message += ` For more information, see ${documentationLink}.`;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (isVersionError) {
|
|
475
|
-
p5._error(this, message);
|
|
476
|
-
} else {
|
|
477
|
-
console.log(message);
|
|
478
|
-
}
|
|
479
|
-
return message;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Runs parameter validation by matching the input parameters to Zod schemas
|
|
484
|
-
* generated from the parameter data from `docs/parameterData.json`.
|
|
485
|
-
*
|
|
486
|
-
* @private
|
|
487
|
-
* @param {String} func - Name of the function.
|
|
488
|
-
* @param {Array} args - User input arguments.
|
|
489
|
-
* @returns {Object} The validation result.
|
|
490
|
-
* @returns {Boolean} result.success - Whether the validation was successful.
|
|
491
|
-
* @returns {any} [result.data] - The parsed data if validation was successful.
|
|
492
|
-
* @returns {String} [result.error] - The validation error message if validation has failed.
|
|
493
|
-
*/
|
|
494
|
-
fn.validate = function (func, args) {
|
|
495
|
-
if (p5.disableFriendlyErrors) {
|
|
496
|
-
return; // skip FES
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (!Array.isArray(args)) {
|
|
500
|
-
args = Array.from(args);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// An edge case: even when all arguments are optional and therefore,
|
|
504
|
-
// theoretically allowed to stay undefined and valid, it is likely that the
|
|
505
|
-
// user intended to call the function with non-undefined arguments. Skip
|
|
506
|
-
// regular workflow and return a friendly error message right away.
|
|
507
|
-
if (Array.isArray(args) && args.every(arg => arg === undefined)) {
|
|
508
|
-
const undefinedErrorMessage = `🌸 p5.js says: All arguments for ${func}() are undefined. There is likely an error in the code.`;
|
|
509
|
-
|
|
510
|
-
return {
|
|
511
|
-
success: false,
|
|
512
|
-
error: undefinedErrorMessage
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
let funcSchemas = schemaRegistry.get(func);
|
|
517
|
-
if (!funcSchemas) {
|
|
518
|
-
funcSchemas = fn.generateZodSchemasForFunc(func);
|
|
519
|
-
if (!funcSchemas) return;
|
|
520
|
-
schemaRegistry.set(func, funcSchemas);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
try {
|
|
524
|
-
return {
|
|
525
|
-
success: true,
|
|
526
|
-
data: funcSchemas.parse(args)
|
|
527
|
-
};
|
|
528
|
-
} catch (error) {
|
|
529
|
-
const closestSchema = fn.findClosestSchema(funcSchemas, args);
|
|
530
|
-
const zodError = closestSchema.safeParse(args).error;
|
|
531
|
-
const errorMessage = fn.friendlyParamError(zodError, func, args);
|
|
532
|
-
|
|
533
|
-
return {
|
|
534
|
-
success: false,
|
|
535
|
-
error: errorMessage
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
};
|
|
539
|
-
|
|
540
|
-
lifecycles.presetup = function(){
|
|
541
|
-
loadP5Constructors();
|
|
542
|
-
|
|
543
|
-
const excludes = ['validate'];
|
|
544
|
-
for(const f in this){
|
|
545
|
-
if(!excludes.includes(f) && !f.startsWith('_') && typeof this[f] === 'function'){
|
|
546
|
-
const copy = this[f];
|
|
547
|
-
|
|
548
|
-
this[f] = function(...args) {
|
|
549
|
-
this.validate(f, args);
|
|
550
|
-
return copy.call(this, ...args);
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
export default validateParams;
|
|
558
|
-
|
|
559
|
-
if (typeof p5 !== 'undefined') {
|
|
560
|
-
validateParams(p5, p5.prototype);
|
|
561
|
-
}
|