From 94eb5fad61729df0389e38fd453d836a19705d5a Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 27 Aug 2025 08:13:29 +0900 Subject: [PATCH 1/4] style: fix eslint warnings --- docs/parameterData.json | 4 + eslint.config.mjs | 4 +- utils/convert.mjs | 10 +- utils/generate-types.mjs | 6 +- utils/helper.mjs | 998 +++++++++++++++++++-------------------- utils/patch.mjs | 50 +- utils/sample-linter.mjs | 2 +- 7 files changed, 538 insertions(+), 536 deletions(-) diff --git a/docs/parameterData.json b/docs/parameterData.json index b99217ebe8..9d2c312077 100644 --- a/docs/parameterData.json +++ b/docs/parameterData.json @@ -4655,6 +4655,10 @@ }, "modify": { "overloads": [ + [ + "Function", + "Object?" + ], [ "Object?" ] diff --git a/eslint.config.mjs b/eslint.config.mjs index 040c2b7727..a691ea6ea0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -80,7 +80,7 @@ const commonRules = { '@stylistic/max-len': [ warn, { - code: 80, + code: 120, ignoreComments: true, ignoreStrings: true, ignoreTemplateLiterals: true, @@ -272,4 +272,4 @@ export default defineConfig([ // * contributor_docs/zh-Hans/unit_testing.md 35:1 error Parsing error: Unexpected token // * rfc_p5js_2.md 205:50 error Parsing error: Binding arguments in strict mode // ...markdown.configs.processor -]); \ No newline at end of file +]); diff --git a/utils/convert.mjs b/utils/convert.mjs index 9fb921c2a2..ee0c5794f3 100644 --- a/utils/convert.mjs +++ b/utils/convert.mjs @@ -232,11 +232,11 @@ function getParams(entry) { // string, so we match these params to the Documentation.js-provided `params` // array and grab the description from those. return (entry.tags || []) - + // Filter out the nested parameters (eg. options.extrude), // to be treated as part of parent parameters (eg. options) // and not separate entries - .filter(t => t.title === 'param' && !t.name.includes('.')) + .filter(t => t.title === 'param' && !t.name.includes('.')) .map(node => { const param = (entry.params || []).find(param => param.name === node.name); return { @@ -522,7 +522,7 @@ function cleanUpClassItems(data) { return Object.values(overload.params).map(param => processParam(param)); } return overload; - } + }; // To simplify `parameterData.json`, instead of having a separate field for // optional parameters, we'll add a ? to the end of parameter type to @@ -536,7 +536,7 @@ function cleanUpClassItems(data) { type = `...${type}[]`; } return type; - } + }; // In some cases, even when the arguments are intended to mean different // things, their types and order are identical. Since the exact meaning @@ -549,7 +549,7 @@ function cleanUpClassItems(data) { } uniqueOverloads.add(overloadString); return true; - } + }; for (const [key, value] of Object.entries(funcObj)) { if (value && typeof value === 'object' && value.overloads) { diff --git a/utils/generate-types.mjs b/utils/generate-types.mjs index 51921bf040..1d2d97a4ee 100644 --- a/utils/generate-types.mjs +++ b/utils/generate-types.mjs @@ -3,7 +3,7 @@ import path from 'path'; import { fileURLToPath } from 'url'; import { generateTypeDefinitions -} from "./helper.mjs"; +} from './helper.mjs'; // Fix for __dirname equivalent in ES modules const __filename = fileURLToPath(import.meta.url); @@ -19,7 +19,7 @@ function findDtsFiles(dir, files = []) { } const entries = fs.readdirSync(dir, { withFileTypes: true }); - + for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { @@ -44,7 +44,7 @@ export function generateAllDeclarationFiles() { fileTypes.forEach((content, filePath) => { const parsedPath = path.parse(filePath); const relativePath = path.relative( - path.join(__dirname, "../src"), + path.join(__dirname, '../src'), filePath ); const dtsPath = path.join( diff --git a/utils/helper.mjs b/utils/helper.mjs index 6c340bc1df..8939422fe9 100644 --- a/utils/helper.mjs +++ b/utils/helper.mjs @@ -18,7 +18,6 @@ export function normalizeClassName(className) { } export function generateTypeDefinitions(data) { - const organized = organizeData(data); return { @@ -28,594 +27,593 @@ export function generateTypeDefinitions(data) { }; } function generateP5TypeDefinitions(organizedData) { - let output = '// This file is auto-generated from JSDoc documentation\n\n'; - - output += `declare class p5 {\n`; - output += ` constructor(sketch?: (p: p5) => void, node?: HTMLElement, sync?: boolean);\n\n`; - const instanceItems = organizedData.classitems.filter(item => - item.class === 'p5' && !item.isStatic - ); - instanceItems.forEach(item => { - output += generateMethodDeclarations(item, false); - }); - - const staticItems = organizedData.classitems.filter(item => - item.class === 'p5' && item.isStatic - ); - staticItems.forEach(item => { - output += generateMethodDeclarations(item, true); - }); - - Object.values(organizedData.consts).forEach(constData => { - if (constData.class === 'p5') { - if (constData.description) { - output += ` /**\n * ${constData.description}\n */\n`; - } - if (constData.kind === 'constant') { - output += ` readonly ${constData.name.toUpperCase()}: ${constData.type};\n\n`; - } else { - output += ` static ${constData.name}: ${constData.type};\n\n`; - } + let output = '// This file is auto-generated from JSDoc documentation\n\n'; + + output += 'declare class p5 {\n'; + output += ' constructor(sketch?: (p: p5) => void, node?: HTMLElement, sync?: boolean);\n\n'; + const instanceItems = organizedData.classitems.filter(item => + item.class === 'p5' && !item.isStatic + ); + instanceItems.forEach(item => { + output += generateMethodDeclarations(item, false); + }); + + const staticItems = organizedData.classitems.filter(item => + item.class === 'p5' && item.isStatic + ); + staticItems.forEach(item => { + output += generateMethodDeclarations(item, true); + }); + + Object.values(organizedData.consts).forEach(constData => { + if (constData.class === 'p5') { + if (constData.description) { + output += ` /**\n * ${constData.description}\n */\n`; } - }); + if (constData.kind === 'constant') { + output += ` readonly ${constData.name.toUpperCase()}: ${constData.type};\n\n`; + } else { + output += ` static ${constData.name}: ${constData.type};\n\n`; + } + } + }); - output += `}\n\n`; + output += '}\n\n'; - output += `declare namespace p5 {\n`; + output += 'declare namespace p5 {\n'; - Object.values(organizedData.consts).forEach(constData => { - if (constData.kind === 'typedef') { - if (constData.description) { - output += ` /**\n * ${constData.description}\n */\n`; - } - output += ` type ${constData.name} = ${constData.type};\n\n`; + Object.values(organizedData.consts).forEach(constData => { + if (constData.kind === 'typedef') { + if (constData.description) { + output += ` /**\n * ${constData.description}\n */\n`; } - }); + output += ` type ${constData.name} = ${constData.type};\n\n`; + } + }); - Object.values(organizedData.classes).forEach(classDoc => { - if (classDoc.name !== 'p5') { - output += generateClassDeclaration(classDoc, organizedData); - } - }); - output += `}\n\n`; + Object.values(organizedData.classes).forEach(classDoc => { + if (classDoc.name !== 'p5') { + output += generateClassDeclaration(classDoc, organizedData); + } + }); + output += '}\n\n'; - output += `export default p5;\n`; - output += `export as namespace p5;\n`; + output += 'export default p5;\n'; + output += 'export as namespace p5;\n'; - return output; - } + return output; +} function generateGlobalTypeDefinitions(organizedData) { - let output = '// This file is auto-generated from JSDoc documentation\n\n'; - output += `import p5 from 'p5';\n\n`; - output += `declare global {\n`; - - const instanceItems = organizedData.classitems.filter(item => - item.class === 'p5' && !item.isStatic - ); - instanceItems.forEach(item => { - if (item.kind === 'function') { - if (item.description) { - output += ` /**\n${formatJSDocComment(item.description, 2)}\n */\n`; - } - - if (item.overloads?.length > 0) { - item.overloads.forEach(overload => { - const params = (overload.params || []) - .map(param => generateParamDeclaration(param)) - .join(', '); - const returnType = overload.returns?.[0]?.type - ? generateTypeFromTag(overload.returns[0]) - : 'void'; - output += ` function ${item.name}(${params}): ${returnType};\n`; - }); - } - - const params = (item.params || []) - .map(param => generateParamDeclaration(param)) - .join(', '); - output += ` function ${item.name}(${params}): ${item.returnType};\n\n`; + let output = '// This file is auto-generated from JSDoc documentation\n\n'; + output += 'import p5 from \'p5\';\n\n'; + output += 'declare global {\n'; + + const instanceItems = organizedData.classitems.filter(item => + item.class === 'p5' && !item.isStatic + ); + instanceItems.forEach(item => { + if (item.kind === 'function') { + if (item.description) { + output += ` /**\n${formatJSDocComment(item.description, 2)}\n */\n`; } - }); - Object.values(organizedData.consts).forEach(constData => { - if (constData.kind === 'constant') { - if (constData.description) { - output += ` /**\n${formatJSDocComment(constData.description, 2)}\n */\n`; - } - output += ` const ${constData.name.toUpperCase()}: p5.${constData.name.toUpperCase()};\n\n`; + if (item.overloads?.length > 0) { + item.overloads.forEach(overload => { + const params = (overload.params || []) + .map(param => generateParamDeclaration(param)) + .join(', '); + const returnType = overload.returns?.[0]?.type + ? generateTypeFromTag(overload.returns[0]) + : 'void'; + output += ` function ${item.name}(${params}): ${returnType};\n`; + }); } - }); - output += ` interface Window {\n`; + const params = (item.params || []) + .map(param => generateParamDeclaration(param)) + .join(', '); + output += ` function ${item.name}(${params}): ${item.returnType};\n\n`; + } + }); - instanceItems.forEach(item => { - if (item.kind === 'function') { - output += ` ${item.name}: typeof ${item.name};\n`; + Object.values(organizedData.consts).forEach(constData => { + if (constData.kind === 'constant') { + if (constData.description) { + output += ` /**\n${formatJSDocComment(constData.description, 2)}\n */\n`; } - }); + output += ` const ${constData.name.toUpperCase()}: p5.${constData.name.toUpperCase()};\n\n`; + } + }); - Object.values(organizedData.consts).forEach(constData => { - if (constData.kind === 'constant') { - if (constData.description) { - output += ` /**\n * ${constData.description}\n */\n`; - } - output += ` readonly ${constData.name.toUpperCase()}: typeof ${constData.name.toUpperCase()};\n`; + output += ' interface Window {\n'; + + instanceItems.forEach(item => { + if (item.kind === 'function') { + output += ` ${item.name}: typeof ${item.name};\n`; + } + }); + + Object.values(organizedData.consts).forEach(constData => { + if (constData.kind === 'constant') { + if (constData.description) { + output += ` /**\n * ${constData.description}\n */\n`; } - }); + output += ` readonly ${constData.name.toUpperCase()}: typeof ${constData.name.toUpperCase()};\n`; + } + }); - output += ` }\n`; - output += `}\n\n`; - output += `export {};\n`; + output += ' }\n'; + output += '}\n\n'; + output += 'export {};\n'; - return output; - } + return output; +} function generateFileTypeDefinitions(organizedData, data) { - const fileDefinitions = new Map(); - const fileGroups = groupByFile(getAllEntries(data)); + const fileDefinitions = new Map(); + const fileGroups = groupByFile(getAllEntries(data)); - fileGroups.forEach((items, filePath) => { - const declarationContent = generateDeclarationFile(items, organizedData); - fileDefinitions.set(filePath, declarationContent); - }); + fileGroups.forEach((items, filePath) => { + const declarationContent = generateDeclarationFile(items, organizedData); + fileDefinitions.set(filePath, declarationContent); + }); - return fileDefinitions; - } - const organized = { - modules: {}, - classes: {}, - classitems: [], - consts: {} - }; + return fileDefinitions; +} +const organized = { + modules: {}, + classes: {}, + classitems: [], + consts: {} +}; function generateDeclarationFile(items, organizedData) { - let output = '// This file is auto-generated from JSDoc documentation\n\n'; - const imports = new Set([`import p5 from 'p5';`]); - const hasColorDependency = items.some(item => { - const typeName = item.type?.name; - const desc = extractDescription(item.description); - return typeName === 'Color' || (typeof desc === 'string' && desc.includes('Color')); - }); - - const hasVectorDependency = items.some(item => { - const typeName = item.type?.name; - const desc = extractDescription(item.description); - return typeName === 'Vector' || (typeof desc === 'string' && desc.includes('Vector')); - }); + let output = '// This file is auto-generated from JSDoc documentation\n\n'; + const imports = new Set(['import p5 from \'p5\';']); + const hasColorDependency = items.some(item => { + const typeName = item.type?.name; + const desc = extractDescription(item.description); + return typeName === 'Color' || (typeof desc === 'string' && desc.includes('Color')); + }); + + const hasVectorDependency = items.some(item => { + const typeName = item.type?.name; + const desc = extractDescription(item.description); + return typeName === 'Vector' || (typeof desc === 'string' && desc.includes('Vector')); + }); + + const hasConstantsDependency = items.some(item => + item.tags?.some(tag => tag.title === 'requires' && tag.description === 'constants') + ); + + if (hasColorDependency) { + imports.add('import { Color } from \'../color/p5.Color\';'); + } + if (hasVectorDependency) { + imports.add('import { Vector } from \'../math/p5.Vector\';'); + } + if (hasConstantsDependency) { + imports.add('import * as constants from \'../core/constants\';'); + } - const hasConstantsDependency = items.some(item => - item.tags?.some(tag => tag.title === 'requires' && tag.description === 'constants') - ); + output += Array.from(imports).join('\n') + '\n\n'; + output += 'declare module \'p5\' {\n'; - if (hasColorDependency) { - imports.add(`import { Color } from '../color/p5.Color';`); - } - if (hasVectorDependency) { - imports.add(`import { Vector } from '../math/p5.Vector';`); - } - if (hasConstantsDependency) { - imports.add(`import * as constants from '../core/constants';`); + const classDoc = items.find(item => item.kind === 'class'); + if (classDoc) { + const fullClassName = normalizeClassName(classDoc.name); + const classDocName = fullClassName.replace('p5.', ''); + let parentClass = classDoc.tags?.find(tag => tag.title === 'extends')?.name; + if (parentClass) { + parentClass = parentClass.replace('p5.', ''); } + const extendsClause = parentClass ? ` extends ${parentClass}` : ''; - output += Array.from(imports).join('\n') + '\n\n'; - output += `declare module 'p5' {\n`; - - const classDoc = items.find(item => item.kind === 'class'); - if (classDoc) { - const fullClassName = normalizeClassName(classDoc.name); - const classDocName = fullClassName.replace('p5.', ''); - let parentClass = classDoc.tags?.find(tag => tag.title === 'extends')?.name; - if (parentClass) { - parentClass = parentClass.replace('p5.', ''); - } - const extendsClause = parentClass ? ` extends ${parentClass}` : ''; - - output += ` class ${classDocName}${extendsClause} {\n`; + output += ` class ${classDocName}${extendsClause} {\n`; - if (classDoc.params?.length > 0) { - output += ' constructor('; - output += classDoc.params - .map(param => generateParamDeclaration(param)) - .join(', '); - output += ');\n\n'; - } + if (classDoc.params?.length > 0) { + output += ' constructor('; + output += classDoc.params + .map(param => generateParamDeclaration(param)) + .join(', '); + output += ');\n\n'; + } - const classItems = organizedData.classitems.filter(item => - item.class === fullClassName || - item.class === fullClassName.replace('p5.', '') - ); + const classItems = organizedData.classitems.filter(item => + item.class === fullClassName || + item.class === fullClassName.replace('p5.', '') + ); - const staticItems = classItems.filter(item => item.isStatic); - const instanceItems = classItems.filter(item => !item.isStatic); - staticItems.forEach(item => { - output += generateMethodDeclarations(item, true); - }); - instanceItems.forEach(item => { - output += generateMethodDeclarations(item, false); - }); - output += ' }\n\n'; - } + const staticItems = classItems.filter(item => item.isStatic); + const instanceItems = classItems.filter(item => !item.isStatic); + staticItems.forEach(item => { + output += generateMethodDeclarations(item, true); + }); + instanceItems.forEach(item => { + output += generateMethodDeclarations(item, false); + }); + output += ' }\n\n'; + } - items.forEach(item => { - if (item.kind !== 'class' && (!item.memberof || item.memberof !== classDoc?.name)) { - switch (item.kind) { - case 'function': - output += generateFunctionDeclaration(item); - break; - case 'constant': - case 'typedef': - const constData = organizedData.consts[item.name]; - if (constData) { - if (constData.description) { - output += ` /**\n * ${constData.description}\n */\n`; - } - if (constData.kind === 'constant') { - output += ` const ${constData.name}: ${constData.type};\n\n`; - } else { - output += ` type ${constData.name} = ${constData.type};\n\n`; - } + items.forEach(item => { + if (item.kind !== 'class' && (!item.memberof || item.memberof !== classDoc?.name)) { + switch (item.kind) { + case 'function': + output += generateFunctionDeclaration(item); + break; + case 'constant': + case 'typedef': { + const constData = organizedData.consts[item.name]; + if (constData) { + if (constData.description) { + output += ` /**\n * ${constData.description}\n */\n`; } - break; - } + if (constData.kind === 'constant') { + output += ` const ${constData.name}: ${constData.type};\n\n`; + } else { + output += ` type ${constData.name} = ${constData.type};\n\n`; + } + } + break; } - }); + } + }); - output += '}\n\n'; + output += '}\n\n'; - return output; - } + return output; +} - export function organizeData(data) { - const allData = getAllEntries(data); - - organized.modules = {}; - organized.classes = {}; - organized.classitems = []; - organized.consts = {}; - - allData.forEach(entry => { - const { module, submodule, forEntry } = getModuleInfo(entry); - const className = normalizeClassName(forEntry || entry.memberof || 'p5'); - - switch(entry.kind) { - case 'class': - organized.classes[className] = { - name: entry.name, - description: extractDescription(entry.description), - params: (entry.params || []).map(param => ({ - name: param.name, - type: generateTypeFromTag(param), - optional: param.type?.type === 'OptionalType' - })), - module, - submodule, - extends: entry.tags?.find(tag => tag.title === 'extends')?.name || null - }; break; - case 'function': - case 'property': - const overloads = entry.overloads?.map(overload => ({ - params: overload.params, - returns: overload.returns, - description: extractDescription(overload.description) - })); - - organized.classitems.push({ - name: entry.name, - kind: entry.kind, - description: extractDescription(entry.description), - params: (entry.params || []).map(param => ({ - name: param.name, - type: generateTypeFromTag(param), - optional: param.type?.type === 'OptionalType' - })), - returnType: entry.returns?.[0] ? generateTypeFromTag(entry.returns[0]) : 'void', - module, - submodule, - class: className, - isStatic: entry.path?.[0]?.scope === 'static', - overloads - }); break; - case 'constant': - case 'typedef': - organized.consts[entry.name] = { - name: entry.name, - kind: entry.kind, - description: extractDescription(entry.description), - type: entry.kind === 'constant' ? `P5.${entry.name.toUpperCase()}` : (entry.type ? generateTypeFromTag(entry) : 'any'), - module, - submodule, - class: forEntry || 'p5' - }; break; - } - }); - return organized; - } +export function organizeData(data) { + const allData = getAllEntries(data); + + organized.modules = {}; + organized.classes = {}; + organized.classitems = []; + organized.consts = {}; + + allData.forEach(entry => { + const { module, submodule, forEntry } = getModuleInfo(entry); + const cassName = normalizeClassNam(forEntry || entry.memberof || 'p5'); + + switch (entry.kind) { + case 'class': + organized.classes[className] = { + name: entry.name, + description: extractDescription(entry.description), + params: (entry.params || []).map(param => ({ + name: param.name, + type: generateTypeFromTag(param), + optional: param.type?.type === 'OptionalType' + })), + module, + submodule, + extends: entry.tags?.find(tag => tag.title === 'extends')?.name || null + }; break; + case 'function': + case 'property': + const overloads = entry.overloads?.map(overload => ({ + params: overload.params, + returns: overload.returns, + description: extractDescription(overload.description) + })); + + organized.classitems.push({ + name: entry.name, + kind: entry.kind, + description: extractDescription(entry.description), + params: (entry.params || []).map(param => ({ + name: param.name, + type: generateTypeFromTag(param), + optional: param.type?.type === 'OptionalType' + })), + returnType: entry.returns?.[0] ? generateTypeFromTag(entry.returns[0]) : 'void', + module, + submodule, + class: className, + isStatic: entry.path?.[0]?.scope === 'static', + overloads + }); break; + case 'constant': + case 'typedef': + organized.consts[entry.name] = { + name: entry.name, + kind: entry.kind, + description: extractDescription(entry.description), + type: entry.kind === 'constant' ? `P5.${entry.name.toUpperCase()}` : (entry.type ? generateTypeFromTag(entry) : 'any'), + module, + submodule, + class: forEntry || 'p5' + }; break; + } + }); + return organized; +} - export function getModuleInfo(entry) { - return { - module: entry.tags?.find(tag => tag.title === 'module')?.name || 'p5', - submodule: entry.tags?.find(tag => tag.title === 'submodule')?.description || null, - forEntry: entry.tags?.find(tag => tag.title === 'for')?.description || entry.memberof - }; +export function getModuleInfo(entry) { + return { + module: entry.tags?.find(tag => tag.title === 'module')?.name || 'p5', + submodule: entry.tags?.find(tag => tag.title === 'submodule')?.description || null, + forEntry: entry.tags?.find(tag => tag.title === 'for')?.description || entry.memberof + }; } export function extractDescription(desc) { - if (!desc) return ''; - if (typeof desc === 'string') return desc; - if (desc.children) { - return desc.children.map(child => { - if (child.type === 'text') return child.value; - if (child.type === 'paragraph') return extractDescription(child); - if (child.type === 'inlineCode' || child.type === 'code') return `\`${child.value}\``; - return ''; - }) - .join('').trim().replace(/\n{3,}/g, '\n\n'); - } - return ''; + if (!desc) return ''; + if (typeof desc === 'string') return desc; + if (desc.children) { + return desc.children.map(child => { + if (child.type === 'text') return child.value; + if (child.type === 'paragraph') return extractDescription(child); + if (child.type === 'inlineCode' || child.type === 'code') return `\`${child.value}\``; + return ''; + }) + .join('').trim().replace(/\n{3,}/g, '\n\n'); } + return ''; +} export function generateTypeFromTag(param) { - if (!param || !param.type) return 'any'; - - switch (param.type.type) { - case 'NameExpression': - return normalizeTypeName(param.type.name); - case 'TypeApplication': { - const baseType = normalizeTypeName(param.type.expression.name); - - if (baseType === 'Array') { - const innerType = param.type.applications[0]; - const innerTypeStr = generateTypeFromTag({ type: innerType }); - return `${innerTypeStr}[]`; - } - - const typeParams = param.type.applications - .map(app => generateTypeFromTag({ type: app })) - .join(', '); - return `${baseType}<${typeParams}>`; + if (!param || !param.type) return 'any'; + + switch (param.type.type) { + case 'NameExpression': + return normalizeTypeName(param.type.name); + case 'TypeApplication': { + const baseType = normalizeTypeName(param.type.expression.name); + + if (baseType === 'Array') { + const innerType = param.type.applications[0]; + const innerTypeStr = generateTypeFromTag({ type: innerType }); + return `${innerTypeStr}[]`; } - case 'UnionType': - const unionTypes = param.type.elements - .map(el => generateTypeFromTag({ type: el })) - .join(' | '); - return unionTypes; - case 'OptionalType': - return generateTypeFromTag({ type: param.type.expression }); - case 'AllLiteral': - return 'any'; - case 'RecordType': - return 'object'; - case 'StringLiteralType': - return `'${param.type.value}'`; - case 'UndefinedLiteralType': - return 'undefined'; - case 'ArrayType': { - const innerTypeStrs = param.type.elements.map(e => generateTypeFromTag({ type: e })); - return `[${innerTypeStrs.join(', ')}]`; - } - case 'RestType': - return `${generateTypeFromTag({ type: param.type.expression })}[]`; - default: - return 'any'; + + const typeParams = param.type.applications + .map(app => generateTypeFromTag({ type: app })) + .join(', '); + return `${baseType}<${typeParams}>`; + } + case 'UnionType': + const unionTypes = param.type.elements + .map(el => generateTypeFromTag({ type: el })) + .join(' | '); + return unionTypes; + case 'OptionalType': + return generateTypeFromTag({ type: param.type.expression }); + case 'AllLiteral': + return 'any'; + case 'RecordType': + return 'object'; + case 'StringLiteralType': + return `'${param.type.value}'`; + case 'UndefinedLiteralType': + return 'undefined'; + case 'ArrayType': { + const innerTypeStrs = param.type.elements.map(e => generateTypeFromTag({ type: e })); + return `[${innerTypeStrs.join(', ')}]`; } + case 'RestType': + return `${generateTypeFromTag({ type: param.type.expression })}[]`; + default: + return 'any'; } +} - export function normalizeTypeName(type) { - if (!type) return 'any'; - - if (type === '[object Object]') return 'any'; +export function normalizeTypeName(type) { + if (!type) return 'any'; - const primitiveTypes = { - 'String': 'string', - 'Number': 'number', - 'Integer': 'number', - 'Boolean': 'boolean', - 'Void': 'void', - 'Object': 'object', - 'Array': 'Array', - 'Function': 'Function' - }; + if (type === '[object Object]') return 'any'; - return primitiveTypes[type] || type; - } + const primitiveTypes = { + 'String': 'string', + 'Number': 'number', + 'Integer': 'number', + 'Boolean': 'boolean', + 'Void': 'void', + 'Object': 'object', + 'Array': 'Array', + 'Function': 'Function' + }; - export function generateParamDeclaration(param) { - if (!param) return 'any'; - - let type = param.type; - let prefix = ''; - const isOptional = param.type?.type === 'OptionalType'; - if (typeof type === 'string') { - type = normalizeTypeName(type); - } else if (param.type?.type) { - type = generateTypeFromTag(param); - } else { - type = 'any'; - } + return primitiveTypes[type] || type; +} - if (param.type?.type === 'RestType') { - prefix = '...'; - } +export function generateParamDeclaration(param) { + if (!param) return 'any'; + + let type = param.type; + let prefix = ''; + const isOptional = param.type?.type === 'OptionalType'; + if (typeof type === 'string') { + type = normalizeTypeName(type); + } else if (param.type?.type) { + type = generateTypeFromTag(param); + } else { + type = 'any'; + } - return `${prefix}${param.name}${isOptional ? '?' : ''}: ${type}`; + if (param.type?.type === 'RestType') { + prefix = '...'; } - export function generateFunctionDeclaration(funcDoc) { + return `${prefix}${param.name}${isOptional ? '?' : ''}: ${type}`; +} - let output = ''; +export function generateFunctionDeclaration(funcDoc) { + let output = ''; - if (funcDoc.description || funcDoc.tags?.length > 0) { - output += '/**\n'; - const description = extractDescription(funcDoc.description); + if (funcDoc.description || funcDoc.tags?.length > 0) { + output += '/**\n'; + const description = extractDescription(funcDoc.description); + if (description) { + output += formatJSDocComment(description) + '\n'; + } + if (funcDoc.tags) { if (description) { - output += formatJSDocComment(description) + '\n'; + output += ' *\n'; } - if (funcDoc.tags) { - if (description) { - output += ' *\n'; + funcDoc.tags.forEach(tag => { + if (tag.description) { + const tagDesc = extractDescription(tag.description); + output += formatJSDocComment(`@${tag.title} ${tagDesc}`, 0) + '\n'; } - funcDoc.tags.forEach(tag => { - if (tag.description) { - const tagDesc = extractDescription(tag.description); - output += formatJSDocComment(`@${tag.title} ${tagDesc}`, 0) + '\n'; - } - }); - } - output += ' */\n'; + }); } + output += ' */\n'; + } - const params = (funcDoc.params || []) - .map(param => generateParamDeclaration(param)) - .join(', '); + const params = (funcDoc.params || []) + .map(param => generateParamDeclaration(param)) + .join(', '); - const returnType = funcDoc.returns?.[0]?.type - ? generateTypeFromTag(funcDoc.returns[0]) - : 'void'; + const returnType = funcDoc.returns?.[0]?.type + ? generateTypeFromTag(funcDoc.returns[0]) + : 'void'; - output += `function ${funcDoc.name}(${params}): ${returnType};\n\n`; - return output; - } - - export function generateMethodDeclarations(item, isStatic = false, isGlobal = false) { - let output = ''; + output += `function ${funcDoc.name}(${params}): ${returnType};\n\n`; + return output; +} - if (item.description) { - output += ' /**\n'; - const itemDesc = extractDescription(item.description); - output += formatJSDocComment(itemDesc, 2) + '\n'; - if (item.params?.length > 0) { - output += ' *\n'; - item.params.forEach(param => { - const paramDesc = extractDescription(param.description); - output += formatJSDocComment(`@param ${paramDesc}`, 2) + '\n'; - }); - } - if (item.returns) { - output += ' *\n'; - const returnDesc = extractDescription(item.returns[0]?.description); - output += formatJSDocComment(`@return ${returnDesc}`, 2) + '\n'; - } - output += ' */\n'; +export function generateMethodDeclarations(item, isStatic = false, isGlobal = false) { + let output = ''; + + if (item.description) { + output += ' /**\n'; + const itemDesc = extractDescription(item.description); + output += formatJSDocComment(itemDesc, 2) + '\n'; + if (item.params?.length > 0) { + output += ' *\n'; + item.params.forEach(param => { + const paramDesc = extractDescription(param.description); + output += formatJSDocComment(`@param ${paramDesc}`, 2) + '\n'; + }); + } + if (item.returns) { + output += ' *\n'; + const returnDesc = extractDescription(item.returns[0]?.description); + output += formatJSDocComment(`@return ${returnDesc}`, 2) + '\n'; } + output += ' */\n'; + } - if (item.kind === 'function') { - const staticPrefix = isStatic ? 'static ' : ''; + if (item.kind === 'function') { + const staticPrefix = isStatic ? 'static ' : ''; - if (item.overloads?.length > 0) { - item.overloads.forEach(overload => { - const params = (overload.params || []) - .map(param => generateParamDeclaration(param)) - .join(', '); - const returnType = overload.returns?.[0]?.type - ? generateTypeFromTag(overload.returns[0]) - : 'void'; - output += ` ${staticPrefix}${item.name}(${params}): ${returnType};\n`; - }); - } - - const params = (item.params || []) - .map(param => generateParamDeclaration(param)) - .join(', '); - output += ` ${staticPrefix}${item.name}(${params}): ${item.returnType};\n\n`; - } else { - const staticPrefix = isStatic ? 'static ' : ''; - output += ` ${staticPrefix}${item.name}: ${item.returnType};\n\n`; + if (item.overloads?.length > 0) { + item.overloads.forEach(overload => { + const params = (overload.params || []) + .map(param => generateParamDeclaration(param)) + .join(', '); + const returnType = overload.returns?.[0]?.type + ? generateTypeFromTag(overload.returns[0]) + : 'void'; + output += ` ${staticPrefix}${item.name}(${params}): ${returnType};\n`; + }); } - return output; + const params = (item.params || []) + .map(param => generateParamDeclaration(param)) + .join(', '); + output += ` ${staticPrefix}${item.name}(${params}): ${item.returnType};\n\n`; + } else { + const staticPrefix = isStatic ? 'static ' : ''; + output += ` ${staticPrefix}${item.name}: ${item.returnType};\n\n`; } + return output; +} + export function generateClassDeclaration(classDoc, organizedData) { - let output = ''; + let output = ''; - if (classDoc.description || classDoc.tags?.length > 0) { - output += '/**\n'; - const description = extractDescription(classDoc.description); + if (classDoc.description || classDoc.tags?.length > 0) { + output += '/**\n'; + const description = extractDescription(classDoc.description); + if (description) { + output += formatJSDocComment(description) + '\n'; + } + if (classDoc.tags) { if (description) { - output += formatJSDocComment(description) + '\n'; + output += ' *\n'; } - if (classDoc.tags) { - if (description) { - output += ' *\n'; + classDoc.tags.forEach(tag => { + if (tag.description) { + const tagDesc = extractDescription(tag.description); + output += formatJSDocComment(`@${tag.title} ${tagDesc}`, 0) + '\n'; } - classDoc.tags.forEach(tag => { - if (tag.description) { - const tagDesc = extractDescription(tag.description); - output += formatJSDocComment(`@${tag.title} ${tagDesc}`, 0) + '\n'; - } - }); - } - output += ' */\n'; + }); } + output += ' */\n'; + } - const parentClass = classDoc.extends; - const extendsClause = parentClass ? ` extends ${parentClass}` : ''; + const parentClass = classDoc.extends; + const extendsClause = parentClass ? ` extends ${parentClass}` : ''; - const fullClassName = normalizeClassName(classDoc.name); - const classDocName = fullClassName.replace('p5.', ''); - output += `class ${classDocName}${extendsClause} {\n`; + const fullClassName = normalizeClassName(classDoc.name); + const classDocName = fullClassName.replace('p5.', ''); + output += `class ${classDocName}${extendsClause} {\n`; - if (classDoc.params?.length > 0) { - output += ' constructor('; - output += classDoc.params - .map(param => generateParamDeclaration(param)) - .join(', '); - output += ');\n\n'; - } + if (classDoc.params?.length > 0) { + output += ' constructor('; + output += classDoc.params + .map(param => generateParamDeclaration(param)) + .join(', '); + output += ');\n\n'; + } - const classItems = organizedData.classitems.filter(item => - item.class === fullClassName || - item.class === fullClassName.replace('p5.', '') - ); - const staticItems = classItems.filter(item => item.isStatic); - const instanceItems = classItems.filter(item => !item.isStatic); + const classItems = organizedData.classitems.filter(item => + item.class === fullClassName || + item.class === fullClassName.replace('p5.', '') + ); + const staticItems = classItems.filter(item => item.isStatic); + const instanceItems = classItems.filter(item => !item.isStatic); - staticItems.forEach(item => { - output += generateMethodDeclarations(item, true); - }); + staticItems.forEach(item => { + output += generateMethodDeclarations(item, true); + }); - instanceItems.forEach(item => { - output += generateMethodDeclarations(item, false); - }); + instanceItems.forEach(item => { + output += generateMethodDeclarations(item, false); + }); - output += '}\n\n'; - return output; - } + output += '}\n\n'; + return output; +} function formatJSDocComment(text, indentLevel = 0) { - if (!text) return ''; - const indent = ' '.repeat(indentLevel); - - const lines = text - .split('\n') - .map(line => line.trim()) - .reduce((acc, line) => { - // If we're starting and line is empty, skip it - if (acc.length === 0 && line === '') return acc; - // If we have content and hit an empty line, keep one empty line - if (acc.length > 0 && line === '' && acc[acc.length - 1] === '') return acc; - acc.push(line); - return acc; - }, []) - .filter((line, i, arr) => i < arr.length - 1 || line !== ''); // Remove trailing empty line - - return lines - .map(line => `${indent} * ${line}`) - .join('\n'); - } - function groupByFile(items) { - const fileGroups = new Map(); + if (!text) return ''; + const indent = ' '.repeat(indentLevel); + + const lines = text + .split('\n') + .map(line => line.trim()) + .reduce((acc, line) => { + // If we're starting and line is empty, skip it + if (acc.length === 0 && line === '') return acc; + // If we have content and hit an empty line, keep one empty line + if (acc.length > 0 && line === '' && acc[acc.length - 1] === '') return acc; + acc.push(line); + return acc; + }, []) + .filter((line, i, arr) => i < arr.length - 1 || line !== ''); // Remove trailing empty line + + return lines + .map(line => `${indent} * ${line}`) + .join('\n'); +} +function groupByFile(items) { + const fileGroups = new Map(); - items.forEach(item => { - if (!item.context || !item.context.file) return; + items.forEach(item => { + if (!item.context || !item.context.file) return; - const filePath = item.context.file; - if (!fileGroups.has(filePath)) { - fileGroups.set(filePath, []); - } - fileGroups.get(filePath).push(item); - }); + const filePath = item.context.file; + if (!fileGroups.has(filePath)) { + fileGroups.set(filePath, []); + } + fileGroups.get(filePath).push(item); + }); - return fileGroups; - } + return fileGroups; +} diff --git a/utils/patch.mjs b/utils/patch.mjs index d70f983006..ddd144c3e7 100644 --- a/utils/patch.mjs +++ b/utils/patch.mjs @@ -1,41 +1,41 @@ import fs from 'fs'; const replace = (path, src, dest) => { - try { - const data = fs - .readFileSync(path, { encoding: 'utf-8' }) - .replace(src, dest); - fs.writeFileSync(path, data); - } catch (err) { - console.error(err); - } + try { + const data = fs + .readFileSync(path, { encoding: 'utf-8' }) + .replace(src, dest); + fs.writeFileSync(path, data); + } catch (err) { + console.error(err); + } }; replace( - "./types/core/structure.d.ts", - "function p5(sketch: object, node: string | HTMLElement): void;", - "function p5: typeof p5" + './types/core/structure.d.ts', + 'function p5(sketch: object, node: string | HTMLElement): void;', + 'function p5: typeof p5' ); replace( - "./types/webgl/p5.Geometry.d.ts", - "constructor(detailX?: number, detailY?: number, callback?: function);", - `constructor( - detailX?: number, - detailY?: number, - callback?: (this: { - detailY: number, - detailX: number, - vertices: p5.Vector[], - uvs: number[] - }) => void);` + './types/webgl/p5.Geometry.d.ts', + 'constructor(detailX?: number, detailY?: number, callback?: function);', + `constructor( + detailX?: number, + detailY?: number, + callback?: (this: { + detailY: number, + detailX: number, + vertices: p5.Vector[], + uvs: number[] + }) => void);` ); // https://github.com/p5-types/p5.ts/issues/31 replace( - "./types/math/random.d.ts", - "function random(choices: Array): any;", - "function random(choices: T[]): T;" + './types/math/random.d.ts', + 'function random(choices: Array): any;', + 'function random(choices: T[]): T;' ); diff --git a/utils/sample-linter.mjs b/utils/sample-linter.mjs index 08b4fb94e1..8ce8aec42f 100644 --- a/utils/sample-linter.mjs +++ b/utils/sample-linter.mjs @@ -101,7 +101,7 @@ const plugin = { return globalSamples.map(s => s.code + userFunctionTrailer); }, - postprocess: function(sampleMessages, filename) { + postprocess: function(sampleMessages, _filename) { const problems = []; for (let i = 0; i < sampleMessages.length; i++) { From e55dd09035438a2069ca44c846ee9232af85c0fe Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 27 Aug 2025 09:18:16 +0900 Subject: [PATCH 2/4] fix: fix syntax error --- utils/helper.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/helper.mjs b/utils/helper.mjs index 8939422fe9..59f800018e 100644 --- a/utils/helper.mjs +++ b/utils/helper.mjs @@ -256,6 +256,7 @@ function generateDeclarationFile(items, organizedData) { } } break; + } } } }); From 9f5212976db9635af15ce41e8198b9547c79c83c Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 27 Aug 2025 09:54:02 +0900 Subject: [PATCH 3/4] chore: fix warnings in helper.mjs --- utils/convert.mjs | 14 +++++++------- utils/helper.mjs | 14 +++++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/utils/convert.mjs b/utils/convert.mjs index ee0c5794f3..6521033121 100644 --- a/utils/convert.mjs +++ b/utils/convert.mjs @@ -517,13 +517,6 @@ function cleanUpClassItems(data) { const flattenOverloads = funcObj => { const result = {}; - const processOverload = overload => { - if (overload.params) { - return Object.values(overload.params).map(param => processParam(param)); - } - return overload; - }; - // To simplify `parameterData.json`, instead of having a separate field for // optional parameters, we'll add a ? to the end of parameter type to // indicate that it's optional. @@ -538,6 +531,13 @@ function cleanUpClassItems(data) { return type; }; + const processOverload = overload => { + if (overload.params) { + return Object.values(overload.params).map(param => processParam(param)); + } + return overload; + }; + // In some cases, even when the arguments are intended to mean different // things, their types and order are identical. Since the exact meaning // of the arguments is less important for parameter validation, we'll diff --git a/utils/helper.mjs b/utils/helper.mjs index 59f800018e..67b6fa7424 100644 --- a/utils/helper.mjs +++ b/utils/helper.mjs @@ -276,7 +276,7 @@ export function organizeData(data) { allData.forEach(entry => { const { module, submodule, forEntry } = getModuleInfo(entry); - const cassName = normalizeClassNam(forEntry || entry.memberof || 'p5'); + const className = normalizeClassName(forEntry || entry.memberof || 'p5'); switch (entry.kind) { case 'class': @@ -293,7 +293,7 @@ export function organizeData(data) { extends: entry.tags?.find(tag => tag.title === 'extends')?.name || null }; break; case 'function': - case 'property': + case 'property': { const overloads = entry.overloads?.map(overload => ({ params: overload.params, returns: overload.returns, @@ -315,7 +315,9 @@ export function organizeData(data) { class: className, isStatic: entry.path?.[0]?.scope === 'static', overloads - }); break; + }); + break; + } case 'constant': case 'typedef': organized.consts[entry.name] = { @@ -326,7 +328,8 @@ export function organizeData(data) { module, submodule, class: forEntry || 'p5' - }; break; + }; + break; } }); return organized; @@ -373,11 +376,12 @@ export function generateTypeFromTag(param) { .join(', '); return `${baseType}<${typeParams}>`; } - case 'UnionType': + case 'UnionType': { const unionTypes = param.type.elements .map(el => generateTypeFromTag({ type: el })) .join(' | '); return unionTypes; + } case 'OptionalType': return generateTypeFromTag({ type: param.type.expression }); case 'AllLiteral': From 9846f10c7e57db808bce2414c9ea369cd697d9f0 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 12 Sep 2025 13:19:39 +0900 Subject: [PATCH 4/4] fix: fix merge mistake --- contributor_docs/ko/method.example.js | 14 +-- .../project_wrapups/slominski_gsoc_2022.md | 2 +- src/color/p5.Color.js | 6 +- src/core/friendly_errors/sketch_verifier.js | 2 +- src/image/filterRenderer2D.js | 6 +- src/shape/curves.js | 38 ++++---- src/shape/custom_shapes.js | 86 +++++++++---------- src/type/textCore.js | 2 +- src/webgl/ShaderGenerator.js | 20 ++--- test/unit/assets/array.js | 2 +- test/unit/assets/object.js | 2 +- utils/helper.mjs | 39 --------- utils/patch.mjs | 20 ++--- 13 files changed, 100 insertions(+), 139 deletions(-) diff --git a/contributor_docs/ko/method.example.js b/contributor_docs/ko/method.example.js index 72c889878b..782dd40111 100644 --- a/contributor_docs/ko/method.example.js +++ b/contributor_docs/ko/method.example.js @@ -1,5 +1,5 @@ /** - * "이것은 메소드의 인라인 문서 템플릿입니다. 이 템플릿을 사용하려면 큰 따옴표 + * "이것은 메소드의 인라인 문서 템플릿입니다. 이 템플릿을 사용하려면 큰 따옴표 * 사이의 모든 텍스트를 제거하십시오. 메소드에 대한 일부 설명은 여기에 들어갑니다. * 간단한 단어로 함수가 하는 일과 그에 대한 좋은/나쁜 사용 예를 설명하십시오. * 만약 비정상적인 케이스나 경고가 있다면 여기에서 설명해 주세요." @@ -31,7 +31,7 @@ * "두 번째 예시를 명확히 설명하는 줄입니다" */ -// "메소드에 둘 이상의 특징이 있으면, 각 특징은 다음과 같은 파라미터 설명과 함께 +// "메소드에 둘 이상의 특징이 있으면, 각 특징은 다음과 같은 파라미터 설명과 함께 // 자체 블록에 문서화할 수 있습니다." /** * @method "메소드명" @@ -46,11 +46,11 @@ p5.prototype.methodName = function() { // 이 부분은 템플릿을 채운 예시입니다. /** - * background() 함수는 p5.js 캔버스의 배경 색상을 - * 설정합니다. 이 함수는 일반적으로 draw()에서 각 프레임의 시작 부분에 디스플레이 - * 윈도우를 지우는 데 사용되지만, 애니메이션의 첫 번째 프레임에 배경색을 설정하거나 + * background() 함수는 p5.js 캔버스의 배경 색상을 + * 설정합니다. 이 함수는 일반적으로 draw()에서 각 프레임의 시작 부분에 디스플레이 + * 윈도우를 지우는 데 사용되지만, 애니메이션의 첫 번째 프레임에 배경색을 설정하거나 * 배경을 한 번만 설정해야 할 경우 setup() 내에서 사용할 수 있습니다. - * + * * 배경색 기본 설정은 투명입니다. * * @method background @@ -81,7 +81,7 @@ p5.prototype.methodName = function() { /** * @method background * @param {String} 문자열 형태의 색상 설정에 사용할 수 있는 형식: - 정수, rgb(), rgba(), rgb() 비율, rgba() 비율, + 정수, rgb(), rgba(), rgb() 비율, rgba() 비율, 3자리 16진법, 6자리 16진법, * @param {Number} [a] * @chainable diff --git a/contributor_docs/project_wrapups/slominski_gsoc_2022.md b/contributor_docs/project_wrapups/slominski_gsoc_2022.md index 4d00fc32e2..195f347136 100644 --- a/contributor_docs/project_wrapups/slominski_gsoc_2022.md +++ b/contributor_docs/project_wrapups/slominski_gsoc_2022.md @@ -47,6 +47,6 @@ The tutorials can be found on the p5.js websites Learn section here (to be added And the code and commits for these contributions can be found at (to be added): -##Acknowledgements +## Acknowledgements I want to express my gratitude towards my mentor Kate Hollenbach for her guidance throughout this project, as well as towards the p5.js community for its openness and helpfulness. diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index 8e2a9d8e82..a3dc0be40b 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -37,7 +37,7 @@ const map = (n, start1, stop1, start2, stop2, clamp) => { result = Math.min(result, Math.max(start2, stop2)); } return result; -} +}; const serializationMap = {}; @@ -547,11 +547,11 @@ class Color { let coords = structuredClone(to(this._color, 'srgb').coords); coords.push(this._color.alpha); - const rangeMaxes = maxes.map((v) => { + const rangeMaxes = maxes.map(v => { if(!Array.isArray(v)){ return [0, v]; }else{ - return v + return v; } }); diff --git a/src/core/friendly_errors/sketch_verifier.js b/src/core/friendly_errors/sketch_verifier.js index b8f6e70db6..c56c84b6de 100644 --- a/src/core/friendly_errors/sketch_verifier.js +++ b/src/core/friendly_errors/sketch_verifier.js @@ -24,7 +24,7 @@ const ignoreFunction = [ 'keyPressed', 'keyReleased', 'keyTyped', - 'windowResized', + 'windowResized' // 'name', // 'parent', // 'toString', diff --git a/src/image/filterRenderer2D.js b/src/image/filterRenderer2D.js index cd0a97fe0a..af3edbd1cc 100644 --- a/src/image/filterRenderer2D.js +++ b/src/image/filterRenderer2D.js @@ -257,9 +257,9 @@ class FilterRenderer2D { const identityMatrix = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]; + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; this._shader.setUniform('uModelViewMatrix', identityMatrix); this._shader.setUniform('uProjectionMatrix', identityMatrix); diff --git a/src/shape/curves.js b/src/shape/curves.js index b83a9dbfe0..d8c1c4a3a2 100644 --- a/src/shape/curves.js +++ b/src/shape/curves.js @@ -517,22 +517,22 @@ function curves(p5, fn){ * function setup() { * createCanvas(200, 200); * background(245); - * + * * // Ensure the curve includes both end spans p0->p1 and p2->p3 * splineProperty('ends', INCLUDE); - * + * * // Control / anchor points * const p0 = createVector(30, 160); * const p1 = createVector(60, 40); * const p2 = createVector(140, 40); * const p3 = createVector(170, 160); - * + * * // Draw the spline that passes through ALL four points (INCLUDE) * noFill(); * stroke(0); * strokeWeight(2); * spline(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - * + * * // Draw markers + labels * fill(255); * stroke(0); @@ -541,19 +541,19 @@ function curves(p5, fn){ * circle(p1.x, p1.y, r); * circle(p2.x, p2.y, r); * circle(p3.x, p3.y, r); - * + * * noStroke(); * fill(0); * text('p0', p0.x - 14, p0.y + 14); * text('p1', p1.x - 14, p1.y - 8); * text('p2', p2.x + 4, p2.y - 8); * text('p3', p3.x + 4, p3.y + 14); - * + * * describe('A black Catmull-Rom spline passes through p0, p1, p2, p3 with endpoints included.'); * } * * - * + * *
* * function setup() { @@ -848,45 +848,45 @@ function curves(p5, fn){ * } * *
- * + * *
* * let p0, p1, p2, p3; - * + * * function setup() { * createCanvas(200, 200); * splineProperty('ends', INCLUDE); // make endpoints part of the curve - * + * * // Four points forming a gentle arch * p0 = createVector(30, 160); * p1 = createVector(60, 50); * p2 = createVector(140, 50); * p3 = createVector(170, 160); - * + * * describe('Black spline through p0–p3. A red dot marks the location at parameter t on p1->p2 using splinePoint.'); * } - * + * * function draw() { * background(245); - * + * * // Draw the spline for context * noFill(); * stroke(0); * strokeWeight(2); * spline(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - * + * * // Map mouse X to t in [0, 1] (span p1->p2) * let t = constrain(map(mouseX, 0, width, 0, 1), 0, 1); - * + * * // Evaluate the curve point by axis (splinePoint works one axis at a time) * let x = splinePoint(p0.x, p1.x, p2.x, p3.x, t); * let y = splinePoint(p0.y, p1.y, p2.y, p3.y, t); - * + * * // Marker at the evaluated position * noStroke(); * fill('red'); * circle(x, y, 8); - * + * * // Draw control/anchor points * stroke(0); * strokeWeight(1); @@ -896,7 +896,7 @@ function curves(p5, fn){ * circle(p1.x, p1.y, r); * circle(p2.x, p2.y, r); * circle(p3.x, p3.y, r); - * + * * // Labels + UI hint * noStroke(); * fill(20); @@ -909,7 +909,7 @@ function curves(p5, fn){ * } * *
- * + * */ fn.splinePoint = function(a, b, c, d, t) { diff --git a/src/shape/custom_shapes.js b/src/shape/custom_shapes.js index f9b2da245d..076c7987cb 100644 --- a/src/shape/custom_shapes.js +++ b/src/shape/custom_shapes.js @@ -1823,7 +1823,7 @@ function customShapes(p5, fn) { * } * * - * + * * @example *
* @@ -1833,44 +1833,44 @@ function customShapes(p5, fn) { * let vertexD; * let vertexE; * let vertexF; - * + * * let markerRadius; - * + * * let vectorAB; * let vectorFE; - * + * * let endOfTangentB; * let endOfTangentE; - * + * * function setup() { * createCanvas(100, 100); - * + * * // Initialize variables * // Adjusting vertices A and F affects the slopes at B and E - * + * * vertexA = createVector(35, 85); * vertexB = createVector(25, 70); * vertexC = createVector(30, 30); * vertexD = createVector(70, 30); * vertexE = createVector(75, 70); * vertexF = createVector(65, 85); - * + * * markerRadius = 4; - * + * * vectorAB = p5.Vector.sub(vertexB, vertexA); * vectorFE = p5.Vector.sub(vertexE, vertexF); - * + * * endOfTangentB = p5.Vector.add(vertexC, vectorAB); * endOfTangentE = p5.Vector.add(vertexD, vectorFE); - * + * * splineProperty(`ends`, EXCLUDE); - * + * * // Draw figure - * + * * background(220); - * + * * noFill(); - * + * * beginShape(); * splineVertex(vertexA.x, vertexA.y); * splineVertex(vertexB.x, vertexB.y); @@ -1879,15 +1879,15 @@ function customShapes(p5, fn) { * splineVertex(vertexE.x, vertexE.y); * splineVertex(vertexF.x, vertexF.y); * endShape(); - * + * * stroke('red'); * line(vertexA.x, vertexA.y, vertexC.x, vertexC.y); * line(vertexB.x, vertexB.y, endOfTangentB.x, endOfTangentB.y); - * + * * stroke('blue'); * line(vertexD.x, vertexD.y, vertexF.x, vertexF.y); * line(vertexE.x, vertexE.y, endOfTangentE.x, endOfTangentE.y); - * + * * fill('white'); * stroke('black'); * circle(vertexA.x, vertexA.y, markerRadius); @@ -1896,7 +1896,7 @@ function customShapes(p5, fn) { * circle(vertexD.x, vertexD.y, markerRadius); * circle(vertexE.x, vertexE.y, markerRadius); * circle(vertexF.x, vertexF.y, markerRadius); - * + * * fill('black'); * noStroke(); * text('A', vertexA.x - 15, vertexA.y + 5); @@ -1905,7 +1905,7 @@ function customShapes(p5, fn) { * text('D', vertexD.x - 5, vertexD.y - 5); * text('E', vertexE.x + 5, vertexE.y + 5); * text('F', vertexF.x + 5, vertexF.y + 5); - * + * * describe('On a gray background, a black spline passes through vertices A, B, C, D, E, and F, shown as white circles. A red line segment joining vertices A and C has the same slope as the red tangent segment at B. Similarly, the blue line segment joining vertices D and F has the same slope as the blue tangent at E.'); * } * @@ -2069,7 +2069,7 @@ function customShapes(p5, fn) { * spline(25, 46, 93, 44, 93, 81, 35, 85); * ``` * - * + * * In all cases, the splines in p5.js are cardinal splines. * When tightness is 0, these splines are often known as * Catmull-Rom splines @@ -2185,9 +2185,9 @@ function customShapes(p5, fn) { * } * *
- * + * * @example - * + * *
* * let vertexA; @@ -2196,44 +2196,44 @@ function customShapes(p5, fn) { * let vertexD; * let vertexE; * let vertexF; - * + * * let markerRadius; - * + * * let vectorAB; * let vectorFE; - * + * * let endOfTangentB; * let endOfTangentE; - * + * * function setup() { * createCanvas(100, 100); - * + * * // Initialize variables * // Adjusting vertices A and F affects the slopes at B and E - * + * * vertexA = createVector(35, 85); * vertexB = createVector(25, 70); * vertexC = createVector(30, 30); * vertexD = createVector(70, 30); * vertexE = createVector(75, 70); * vertexF = createVector(65, 85); - * + * * markerRadius = 4; - * + * * vectorAB = p5.Vector.sub(vertexB, vertexA); * vectorFE = p5.Vector.sub(vertexE, vertexF); - * + * * endOfTangentB = p5.Vector.add(vertexC, vectorAB); * endOfTangentE = p5.Vector.add(vertexD, vectorFE); - * + * * splineProperty(`ends`, EXCLUDE); - * + * * // Draw figure - * + * * background(220); - * + * * noFill(); - * + * * beginShape(); * splineVertex(vertexA.x, vertexA.y); * splineVertex(vertexB.x, vertexB.y); @@ -2242,15 +2242,15 @@ function customShapes(p5, fn) { * splineVertex(vertexE.x, vertexE.y); * splineVertex(vertexF.x, vertexF.y); * endShape(); - * + * * stroke('red'); * line(vertexA.x, vertexA.y, vertexC.x, vertexC.y); * line(vertexB.x, vertexB.y, endOfTangentB.x, endOfTangentB.y); - * + * * stroke('blue'); * line(vertexD.x, vertexD.y, vertexF.x, vertexF.y); * line(vertexE.x, vertexE.y, endOfTangentE.x, endOfTangentE.y); - * + * * fill('white'); * stroke('black'); * circle(vertexA.x, vertexA.y, markerRadius); @@ -2259,7 +2259,7 @@ function customShapes(p5, fn) { * circle(vertexD.x, vertexD.y, markerRadius); * circle(vertexE.x, vertexE.y, markerRadius); * circle(vertexF.x, vertexF.y, markerRadius); - * + * * fill('black'); * noStroke(); * text('A', vertexA.x - 15, vertexA.y + 5); @@ -2268,12 +2268,12 @@ function customShapes(p5, fn) { * text('D', vertexD.x - 5, vertexD.y - 5); * text('E', vertexE.x + 5, vertexE.y + 5); * text('F', vertexF.x + 5, vertexF.y + 5); - * + * * describe('On a gray background, a black spline passes through vertices A, B, C, D, E, and F, shown as white circles. A red line segment joining vertices A and C has the same slope as the red tangent segment at B. Similarly, the blue line segment joining vertices D and F has the same slope as the blue tangent at E.'); * } * *
- * + * */ /** diff --git a/src/type/textCore.js b/src/type/textCore.js index 5e0efbe8fe..203642a846 100644 --- a/src/type/textCore.js +++ b/src/type/textCore.js @@ -755,7 +755,7 @@ function textCore(p5, fn) { * * For example, if the text contains multiple lines due to wrapping or explicit line breaks, textWidth() * will return the width of the longest line. - * + * * **Note:** In p5.js 2.0+, leading and trailing spaces are ignored. * `textWidth(" Hello ")` returns the same width as `textWidth("Hello")`. * diff --git a/src/webgl/ShaderGenerator.js b/src/webgl/ShaderGenerator.js index 2e716ce39f..a15bd4c597 100644 --- a/src/webgl/ShaderGenerator.js +++ b/src/webgl/ShaderGenerator.js @@ -1,9 +1,9 @@ /** -* @module 3D -* @submodule Material -* @for p5 -* @requires core -*/ + * @module 3D + * @submodule Material + * @for p5 + * @requires core + */ import { parse } from 'acorn'; import { ancestor } from 'acorn-walk'; import escodegen from 'escodegen'; @@ -1759,13 +1759,13 @@ if (typeof p5 !== 'undefined') { * @method getWorldInputs * @description * Registers a callback to modify the world-space properties of each vertex in a shader. This hook can be used inside baseColorShader().modify() and similar shader modify() calls to customize vertex positions, normals, texture coordinates, and colors before rendering. "World space" refers to the coordinate system of the 3D scene, before any camera or projection transformations are applied. - * + * * The callback receives a vertex object with the following properties: * - `position`: a three-component vector representing the original position of the vertex. * - `normal`: a three-component vector representing the direction the surface is facing. * - `texCoord`: a two-component vector representing the texture coordinates. * - `color`: a four-component vector representing the color of the vertex (red, green, blue, alpha). - * + * * This hook is available in: * - baseMaterialShader() * - baseNormalShader() @@ -1786,7 +1786,7 @@ if (typeof p5 !== 'undefined') { * getWorldInputs(inputs => { * // Move the vertex up and down in a wave in world space * // In world space, moving the object (e.g., with translate()) will affect these coordinates -* // The sphere is ~50 units tall here, so 20 gives a noticeable wave + * // The sphere is ~50 units tall here, so 20 gives a noticeable wave * inputs.position.y += 20 * sin(t * 0.001 + inputs.position.x * 0.05); * return inputs; * }); @@ -2166,7 +2166,7 @@ if (typeof p5 !== 'undefined') { * @method getObjectInputs * @description * Registers a callback to modify the properties of each vertex before any transformations are applied in the vertex shader. This hook can be used inside baseColorShader().modify() and similar shader modify() calls to move, color, or otherwise modify the raw model data. The callback receives an object with the following properties: - * + * * - `position`: a three-component vector representing the original position of the vertex. * - `normal`: a three-component vector representing the direction the surface is facing. * - `texCoord`: a two-component vector representing the texture coordinates. @@ -2213,7 +2213,7 @@ if (typeof p5 !== 'undefined') { * @method getCameraInputs * @description * Registers a callback to adjust vertex properties after the model has been transformed by the camera, but before projection, in the vertex shader. This hook can be used inside baseColorShader().modify() and similar shader modify() calls to create effects that depend on the camera's view. The callback receives an object with the following properties: - * + * * - `position`: a three-component vector representing the position after camera transformation. * - `normal`: a three-component vector representing the normal after camera transformation. * - `texCoord`: a two-component vector representing the texture coordinates. diff --git a/test/unit/assets/array.js b/test/unit/assets/array.js index 9e3ff56f24..54a39fa812 100644 --- a/test/unit/assets/array.js +++ b/test/unit/assets/array.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line no-undef + jsonpCallbackFunction([ { id: 0, diff --git a/test/unit/assets/object.js b/test/unit/assets/object.js index 25738a7a5c..84f31fc172 100644 --- a/test/unit/assets/object.js +++ b/test/unit/assets/object.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line no-undef + jsonpCallbackFunction({ id: 0, species: 'Panthera leo', diff --git a/utils/helper.mjs b/utils/helper.mjs index 6d6bc0a953..91517591ce 100644 --- a/utils/helper.mjs +++ b/utils/helper.mjs @@ -278,11 +278,7 @@ export function organizeData(data) { const { module, submodule, forEntry } = getModuleInfo(entry); const className = normalizeClassName(forEntry || entry.memberof || 'p5'); -<<<<<<< HEAD switch (entry.kind) { -======= - switch(entry.kind) { ->>>>>>> upstream/dev-2.0 case 'class': organized.classes[className] = { name: entry.name, @@ -297,11 +293,7 @@ export function organizeData(data) { extends: entry.tags?.find(tag => tag.title === 'extends')?.name || null }; break; case 'function': -<<<<<<< HEAD case 'property': { -======= - case 'property': ->>>>>>> upstream/dev-2.0 const overloads = entry.overloads?.map(overload => ({ params: overload.params, returns: overload.returns, @@ -323,13 +315,9 @@ export function organizeData(data) { class: className, isStatic: entry.path?.[0]?.scope === 'static', overloads -<<<<<<< HEAD }); break; } -======= - }); break; ->>>>>>> upstream/dev-2.0 case 'constant': case 'typedef': organized.consts[entry.name] = { @@ -340,12 +328,8 @@ export function organizeData(data) { module, submodule, class: forEntry || 'p5' -<<<<<<< HEAD }; break; -======= - }; break; ->>>>>>> upstream/dev-2.0 } }); return organized; @@ -392,19 +376,12 @@ export function generateTypeFromTag(param) { .join(', '); return `${baseType}<${typeParams}>`; } -<<<<<<< HEAD case 'UnionType': { -======= - case 'UnionType': ->>>>>>> upstream/dev-2.0 const unionTypes = param.type.elements .map(el => generateTypeFromTag({ type: el })) .join(' | '); return unionTypes; -<<<<<<< HEAD } -======= ->>>>>>> upstream/dev-2.0 case 'OptionalType': return generateTypeFromTag({ type: param.type.expression }); case 'AllLiteral': @@ -416,12 +393,8 @@ export function generateTypeFromTag(param) { case 'UndefinedLiteralType': return 'undefined'; case 'ArrayType': { -<<<<<<< HEAD - const innerTypeStrs = param.type.elements.map(e => generateTypeFromTag({ type: e })); -======= const innerTypeStrs = param.type.elements .map(e => generateTypeFromTag({ type: e })); ->>>>>>> upstream/dev-2.0 return `[${innerTypeStrs.join(', ')}]`; } case 'RestType': @@ -472,10 +445,6 @@ export function generateParamDeclaration(param) { } export function generateFunctionDeclaration(funcDoc) { -<<<<<<< HEAD -======= - ->>>>>>> upstream/dev-2.0 let output = ''; if (funcDoc.description || funcDoc.tags?.length > 0) { @@ -510,15 +479,11 @@ export function generateFunctionDeclaration(funcDoc) { return output; } -<<<<<<< HEAD -export function generateMethodDeclarations(item, isStatic = false, isGlobal = false) { -======= export function generateMethodDeclarations( item, isStatic = false, isGlobal = false ) { ->>>>>>> upstream/dev-2.0 let output = ''; if (item.description) { @@ -609,11 +574,7 @@ export function generateClassDeclaration(classDoc, organizedData) { const classItems = organizedData.classitems.filter(item => item.class === fullClassName || -<<<<<<< HEAD - item.class === fullClassName.replace('p5.', '') -======= item.class === fullClassName.replace('p5.', '') ->>>>>>> upstream/dev-2.0 ); const staticItems = classItems.filter(item => item.isStatic); const instanceItems = classItems.filter(item => !item.isStatic); diff --git a/utils/patch.mjs b/utils/patch.mjs index da7f0089cc..e90d81d097 100644 --- a/utils/patch.mjs +++ b/utils/patch.mjs @@ -1,9 +1,9 @@ -import fs from "fs"; +import fs from 'fs'; const replace = (path, src, dest) => { try { const data = fs - .readFileSync(path, { encoding: "utf-8" }) + .readFileSync(path, { encoding: 'utf-8' }) .replace(src, dest); fs.writeFileSync(path, data); } catch (err) { @@ -12,14 +12,14 @@ const replace = (path, src, dest) => { }; replace( - "./types/core/structure.d.ts", - "function p5(sketch: object, node: string | HTMLElement): void;", - "function p5: typeof p5", + './types/core/structure.d.ts', + 'function p5(sketch: object, node: string | HTMLElement): void;', + 'function p5: typeof p5' ); replace( - "./types/webgl/p5.Geometry.d.ts", - "constructor(detailX?: number, detailY?: number, callback?: function);", + './types/webgl/p5.Geometry.d.ts', + 'constructor(detailX?: number, detailY?: number, callback?: function);', `constructor( detailX?: number, detailY?: number, @@ -33,7 +33,7 @@ replace( // https://github.com/p5-types/p5.ts/issues/31 replace( - "./types/math/random.d.ts", - "function random(choices: Array): any;", - "function random(choices: T[]): T;", + './types/math/random.d.ts', + 'function random(choices: Array): any;', + 'function random(choices: T[]): T;' );