Skip to content

Commit d72744a

Browse files
authored
Merge pull request #7465 from diyaayay/typescript-declarations
Typescript declaration files script
2 parents 03a02b0 + de71330 commit d72744a

File tree

11 files changed

+1219
-49
lines changed

11 files changed

+1219
-49
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ docs/reference/*
1010
examples/3d/
1111
.idea
1212
dist/
13+
*.d.ts
1314
p5.zip
1415
bower-repo/
1516
p5-website/

contributor_docs/contributor_guidelines.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ When opening a discussion issue, you can use the "Labels" panel on the side pane
194194

195195
## Prerequisites
196196

197-
To proceed you should be minimally familiar with working with the command line, git, node.js (at least v18 and up), and have a local development environment setup.
197+
To proceed you should be minimally familiar with working with the command line, git, node.js (at least v20 and up), and have a local development environment setup.
198198

199199

200200
## Introduction

docs/parameterData.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
"paletteLerp": {
131131
"overloads": [
132132
[
133-
null,
133+
"[p5.Color|String|Number|Number[], Number][]",
134134
"Number"
135135
]
136136
]

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"bench:report": "vitest bench --reporter=verbose",
1111
"test": "vitest",
1212
"lint": "eslint .",
13-
"lint:fix": "eslint --fix ."
13+
"lint:fix": "eslint --fix .",
14+
"generate-types": "npm run docs && node utils/generate-types && node utils/patch"
1415
},
1516
"lint-staged": {
1617
"Gruntfile.js": "eslint",
@@ -86,7 +87,8 @@
8687
"lib/p5.min.js",
8788
"lib/p5.js",
8889
"lib/p5.esm.js",
89-
"translations/**"
90+
"translations/**",
91+
"types/**"
9092
],
9193
"description": "[![npm version](https://badge.fury.io/js/p5.svg)](https://www.npmjs.com/package/p5)",
9294
"bugs": {
@@ -105,5 +107,6 @@
105107
"workerDirectory": [
106108
"test"
107109
]
108-
}
110+
},
111+
"types": "./types/p5.d.ts"
109112
}

src/color/creating_reading.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1589,8 +1589,8 @@ function creatingReading(p5, fn){
15891589
* <a href="/reference/p5/colorMode/">colorMode()</a>.
15901590
*
15911591
* @method paletteLerp
1592-
* @param {[p5.Color|String|Number|Number[], Number][]} colors_stops color stops to interpolate from
1593-
* @param {Number} amt number to use to interpolate relative to color stops
1592+
* @param {Array<[(p5.Color|String|Number|Number[]), Number]>} colors_stops color stops to interpolate from
1593+
* @param {Number} amt number to use to interpolate relative to color stops
15941594
* @return {p5.Color} interpolated color.
15951595
*
15961596
* @example

src/core/friendly_errors/param_validator.js

+38-25
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,19 @@ function validateParams(p5, fn, lifecycles) {
105105
return { funcName, funcClass };
106106
}
107107

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+
108121
/**
109122
* This is a helper function that generates Zod schemas for a function based on
110123
* the parameter data from `docs/parameterData.json`.
@@ -139,11 +152,8 @@ function validateParams(p5, fn, lifecycles) {
139152
}
140153

141154
// Returns a schema for a single type, i.e. z.boolean() for `boolean`.
142-
const generateTypeSchema = type => {
143-
if (!type) return z.any();
144-
145-
const isArray = type.endsWith('[]');
146-
const baseType = isArray ? type.slice(0, -2) : type;
155+
const generateTypeSchema = baseType => {
156+
if (!baseType) return z.any();
147157

148158
let typeSchema;
149159

@@ -162,7 +172,7 @@ function validateParams(p5, fn, lifecycles) {
162172
typeSchema = z.function();
163173
}
164174
// All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`.
165-
else if (baseType.startsWith('p5')) {
175+
else if (/^p5\.[a-zA-Z0-9]+$/.exec(baseType) || baseType === 'p5') {
166176
const className = baseType.substring(baseType.indexOf('.') + 1);
167177
typeSchema = z.instanceof(p5Constructors[className]);
168178
}
@@ -171,7 +181,11 @@ function validateParams(p5, fn, lifecycles) {
171181
typeSchema = schemaMap[baseType];
172182
}
173183
// Tuple types
174-
else if (baseType.startsWith('[') && baseType.endsWith(']')) {
184+
else if (
185+
baseType.startsWith('[') &&
186+
baseType.endsWith(']') &&
187+
validBracketNesting(baseType.slice(1, -1))
188+
) {
175189
typeSchema = z.tuple(
176190
baseType
177191
.slice(1, -1)
@@ -182,21 +196,7 @@ function validateParams(p5, fn, lifecycles) {
182196
// JavaScript classes, e.g. Request
183197
else if (baseType.match(/^[A-Z]/) && baseType in window) {
184198
typeSchema = z.instanceof(window[baseType]);
185-
} else {
186-
throw new Error(`Unsupported type '${type}' in parameter validation. Please report this issue.`);
187199
}
188-
189-
return isArray ? z.array(typeSchema) : typeSchema;
190-
};
191-
192-
// Generate a schema for a single parameter. In the case where a parameter can
193-
// be of multiple types, `generateTypeSchema` is called for each type.
194-
const generateParamSchema = param => {
195-
const isOptional = param?.endsWith('?');
196-
param = param?.replace(/\?$/, '');
197-
198-
let schema;
199-
200200
// Generate a schema for a single parameter that can be of multiple
201201
// types / constants, i.e. `String|Number|Array`.
202202
//
@@ -206,15 +206,28 @@ function validateParams(p5, fn, lifecycles) {
206206
// our constants sometimes have numeric or non-primitive values.
207207
// 2) In some cases, the type can be constants or strings, making z.enum()
208208
// insufficient for the use case.
209-
if (param?.includes('|')) {
210-
const types = param.split('|');
211-
schema = z.union(types
209+
else if (baseType.includes('|') && baseType.split('|').every(t => validBracketNesting(t))) {
210+
const types = baseType.split('|');
211+
typeSchema = z.union(types
212212
.map(t => generateTypeSchema(t))
213213
.filter(s => s !== undefined));
214+
} else if (baseType.endsWith('[]')) {
215+
typeSchema = z.array(generateTypeSchema(baseType.slice(0, -2)));
214216
} else {
215-
schema = generateTypeSchema(param);
217+
throw new Error(`Unsupported type '${baseType}' in parameter validation. Please report this issue.`);
216218
}
217219

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+
218231
return isOptional ? schema.optional() : schema;
219232
};
220233

0 commit comments

Comments
 (0)