diff --git a/rollup.config.mjs b/rollup.config.mjs index e2928ad207..245cefac3b 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -36,60 +36,13 @@ const bundleSize = (name, sourcemap) => { }); }; -const modules = ['math']; -const generateModuleBuild = () => { - return modules.map(module => { - return { - input: `src/${module}/index.js`, - output: [ - { - file: `./lib/p5.${module}.js`, - format: 'iife', - plugins: [ - bundleSize(`p5.${module}.js`) - ] - }, - { - file: `./lib/p5.${module}.min.js`, - format: 'iife', - sourcemap: 'hidden', - plugins: [ - terser({ - compress: { - global_defs: { - IS_MINIFIED: true - } - }, - format: { - comments: false - } - }), - bundleSize(`p5.${module}.min.js`) - ] - }, - { - file: `./lib/p5.${module}.esm.js`, - format: 'esm', - plugins: [ - bundleSize(`p5.${module}.esm.js`) - ] - } - ], - external: ['../core/main'], - plugins: [ - ...plugins - ] - }; - }); -}; - rmSync('./dist', { force: true, recursive: true }); export default [ - //// Library builds (IIFE and ESM) //// + // Library builds (IIFE and ESM) //// { input: 'src/app.js', output: [ @@ -137,7 +90,7 @@ export default [ ...plugins ] }, - //// Minified build //// + // Minified build //// { input: 'src/app.js', output: [ @@ -168,13 +121,13 @@ export default [ plugins: [ alias({ entries: [ - { find: './core/friendly_errors', replacement: './core/noop' } + { find: './friendly_errors', replacement: './core/noop' } ] }), ...plugins ] }, - //// ESM source build //// + // ESM source build //// { input: Object.fromEntries( globSync('src/**/*.js').map(file => [ @@ -196,6 +149,4 @@ export default [ external: /node_modules/, plugins } - // NOTE: comment to NOT build standalone math module - // ...generateModuleBuild() ]; diff --git a/rollup.modules.mjs b/rollup.modules.mjs new file mode 100644 index 0000000000..2ad680677e --- /dev/null +++ b/rollup.modules.mjs @@ -0,0 +1,97 @@ +import { readdirSync, mkdirSync, rmSync } from 'node:fs'; +import { writeFile } from 'node:fs/promises'; +import { rollup } from 'rollup'; +import commonjs from '@rollup/plugin-commonjs'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import json from '@rollup/plugin-json'; +import { string } from 'rollup-plugin-string'; +import replace from '@rollup/plugin-replace'; +import pkg from './package.json' with { type: 'json' }; +import terser from '@rollup/plugin-terser'; + +const coreModules = ['accessibility', 'color', 'friendly_errors']; +const modules = + readdirSync('./src', { withFileTypes: true }) + .filter(dirent => { + return dirent.isDirectory() && + !coreModules.includes(dirent.name); + }) + .map(dirent => dirent.name); + +await buildModules(modules); + +// Build modules given by array of module name strings +export async function buildModules(modules){ + const plugins = [ + commonjs(), + nodeResolve(), + json(), + string({ + include: 'src/webgl/shaders/**/*' + }), + replace({ + values: { + 'VERSION_WILL_BE_REPLACED_BY_BUILD': pkg.version + }, + preventAssignment: true + }) + ]; + + const builds = modules.map(mod => { + const inputOptions = { + input: `src/${mod}/index.js`, + plugins + }; + + const outputOptions = [ + { + file: `./lib/modules/p5.${mod}.js`, + format: 'iife', + name: mod === 'core' ? 'p5' : undefined + }, + { + file: `./lib/modules/p5.${mod}.min.js`, + format: 'iife', + name: mod === 'core' ? 'p5' : undefined, + sourcemap: 'hidden', + plugins: [ + terser({ + compress: { + global_defs: { + IS_MINIFIED: true + } + }, + format: { + comments: false + } + }) + ] + } + ]; + + rmSync('./lib/modules', { recursive: true, force: true }); + mkdirSync('./lib/modules', { recursive: true }); + return build(inputOptions, outputOptions); + }); + + await Promise.all(builds); +} + +// Rollup build simple pipeline +async function build(inputOptions, outputOptionsList){ + let bundle; + try { + bundle = await rollup(inputOptions); + + for(const outputOptions of outputOptionsList){ + const { output } = await bundle.generate(outputOptions); + await writeFile(outputOptions.file, output[0].code); + } + } catch(err) { + console.error(err); + } + + if(bundle){ + await bundle.close(); + } +} diff --git a/src/app.js b/src/app.js index ce3d1fcd4a..9e5de2470d 100644 --- a/src/app.js +++ b/src/app.js @@ -15,7 +15,7 @@ color(p5); // core // currently, it only contains the test for parameter validation -import friendlyErrors from './core/friendly_errors'; +import friendlyErrors from './friendly_errors'; friendlyErrors(p5); // data diff --git a/src/color/color_conversion.js b/src/color/color_conversion.js index 850d24918b..d2841e7abd 100644 --- a/src/color/color_conversion.js +++ b/src/color/color_conversion.js @@ -13,8 +13,8 @@ * interchangeably. */ -import p5 from '../core/main'; -p5.ColorConversion = { +// import p5 from '../core/main'; +const ColorConversion = { /** * Convert an HSBA array to HSLA. */ @@ -267,4 +267,4 @@ p5.ColorConversion = { return [hue / 6, sat, li / 2, rgba[3]]; } }; -export default p5.ColorConversion; +export default ColorConversion; diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index 888c9606d6..049caf6fde 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -932,5 +932,6 @@ export default color; export { Color }; if(typeof p5 !== 'undefined'){ - color(p5, p5.prototype); + // color(p5, p5.prototype); + p5.registerAddon(color); } diff --git a/src/core/index.js b/src/core/index.js new file mode 100644 index 0000000000..9419ddd484 --- /dev/null +++ b/src/core/index.js @@ -0,0 +1,20 @@ +// core +import p5 from './main'; + +// color +import color from '../color'; +color(p5); + +// accessibility +import accessibility from '../accessibility'; +accessibility(p5); + +// FES +import friendlyErrors from '../friendly_errors'; +friendlyErrors(p5); + +import { waitForDocumentReady, waitingForTranslator, _globalInit } from './init'; +Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); + +export default p5; + diff --git a/src/core/init.js b/src/core/init.js index 764437b1ff..fb197ade11 100644 --- a/src/core/init.js +++ b/src/core/init.js @@ -1,4 +1,4 @@ -import p5 from '../core/main'; +// import p5 from '../core/main'; import { initialize as initTranslator } from './internationalization'; /** diff --git a/src/core/friendly_errors/browser_errors.js b/src/friendly_errors/browser_errors.js similarity index 100% rename from src/core/friendly_errors/browser_errors.js rename to src/friendly_errors/browser_errors.js diff --git a/src/core/friendly_errors/fes_core.js b/src/friendly_errors/fes_core.js similarity index 99% rename from src/core/friendly_errors/fes_core.js rename to src/friendly_errors/fes_core.js index 41e40f2755..e82ef03918 100644 --- a/src/core/friendly_errors/fes_core.js +++ b/src/friendly_errors/fes_core.js @@ -22,9 +22,9 @@ * sequence of each function, please look at the FES Reference + Dev Notes: * https://github.com/processing/p5.js/blob/main/contributor_docs/fes_reference_dev_notes.md */ -import { translator } from '../internationalization'; +import { translator } from '../core/internationalization'; import errorTable from './browser_errors'; -import * as contants from '../constants'; +import * as contants from '../core/constants'; function fesCore(p5, fn){ // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta @@ -52,8 +52,6 @@ function fesCore(p5, fn){ } else { let doFriendlyWelcome = false; // TEMP until we get it all working LM - // const errorTable = require('./browser_errors').default; - // -- Borrowed from jQuery 1.11.3 -- const class2type = {}; const toString = class2type.toString; diff --git a/src/core/friendly_errors/file_errors.js b/src/friendly_errors/file_errors.js similarity index 97% rename from src/core/friendly_errors/file_errors.js rename to src/friendly_errors/file_errors.js index 8f212c8355..8316074d32 100644 --- a/src/core/friendly_errors/file_errors.js +++ b/src/friendly_errors/file_errors.js @@ -2,7 +2,7 @@ * @for p5 * @requires core */ -import { translator } from '../internationalization'; +import { translator } from '../core/internationalization'; function fileErrors(p5, fn){ // mapping used by `_friendlyFileLoadError` diff --git a/src/core/friendly_errors/index.js b/src/friendly_errors/index.js similarity index 100% rename from src/core/friendly_errors/index.js rename to src/friendly_errors/index.js diff --git a/src/core/friendly_errors/param_validator.js b/src/friendly_errors/param_validator.js similarity index 98% rename from src/core/friendly_errors/param_validator.js rename to src/friendly_errors/param_validator.js index d2c813a940..0991a9246f 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/friendly_errors/param_validator.js @@ -2,9 +2,9 @@ * @for p5 * @requires core */ -import * as constants from '../constants.js'; +import * as constants from '../core/constants.js'; import { z } from 'zod/v4'; -import dataDoc from '../../../docs/parameterData.json'; +import dataDoc from '../../docs/parameterData.json'; function validateParams(p5, fn, lifecycles) { // Cache for Zod schemas @@ -174,6 +174,8 @@ function validateParams(p5, fn, lifecycles) { // All p5 objects start with `p5` in the documentation, i.e. `p5.Camera`. else if (/^p5\.[a-zA-Z0-9]+$/.exec(baseType) || baseType === 'p5') { const className = baseType.substring(baseType.indexOf('.') + 1); + // NOTE: Will need to refactor to account for classes not imported + if(!p5Constructors[className]) return z.any(); typeSchema = z.instanceof(p5Constructors[className]); } // For primitive types and web API objects. diff --git a/src/core/friendly_errors/sketch_verifier.js b/src/friendly_errors/sketch_verifier.js similarity index 98% rename from src/core/friendly_errors/sketch_verifier.js rename to src/friendly_errors/sketch_verifier.js index b8f6e70db6..3f20797225 100644 --- a/src/core/friendly_errors/sketch_verifier.js +++ b/src/friendly_errors/sketch_verifier.js @@ -1,6 +1,6 @@ import { parse } from 'acorn'; import { simple as walk } from 'acorn-walk'; -import * as constants from '../constants'; +import * as constants from '../core/constants'; // List of functions to ignore as they either are meant to be re-defined or // generate false positive outputs. @@ -24,17 +24,10 @@ const ignoreFunction = [ 'keyPressed', 'keyReleased', 'keyTyped', - 'windowResized', - // 'name', - // 'parent', - // 'toString', - // 'print', - // 'stop', - // 'onended' + 'windowResized' ]; export const verifierUtils = { - /** * Fetches the contents of a script element in the user's sketch. * diff --git a/src/core/friendly_errors/stacktrace.js b/src/friendly_errors/stacktrace.js similarity index 100% rename from src/core/friendly_errors/stacktrace.js rename to src/friendly_errors/stacktrace.js diff --git a/test/unit/core/param_errors.js b/test/unit/core/param_errors.js index e37d2c4d8e..ac4d468617 100644 --- a/test/unit/core/param_errors.js +++ b/test/unit/core/param_errors.js @@ -1,4 +1,4 @@ -import validateParams from '../../../src/core/friendly_errors/param_validator.js'; +import validateParams from '../../../src/friendly_errors/param_validator.js'; import * as constants from '../../../src/core/constants.js'; suite('Validate Params', function () { diff --git a/test/unit/core/sketch_overrides.js b/test/unit/core/sketch_overrides.js index 1d3893372d..eaaeb3ee96 100644 --- a/test/unit/core/sketch_overrides.js +++ b/test/unit/core/sketch_overrides.js @@ -1,6 +1,6 @@ import { verifierUtils -} from '../../../src/core/friendly_errors/sketch_verifier.js'; +} from '../../../src/friendly_errors/sketch_verifier.js'; suite('Sketch Verifier', function () { const mockP5 = {