Skip to content

Commit 324d644

Browse files
authored
Merge branch 'develop' into fix/hi-translation
2 parents ac69619 + 7e119ec commit 324d644

File tree

12 files changed

+210
-27
lines changed

12 files changed

+210
-27
lines changed

client/modules/IDE/components/Preferences/index.jsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,8 @@ import {
2121
setLinewrap,
2222
setPreferencesTab
2323
} from '../../actions/preferences';
24-
import {
25-
majorVersion,
26-
p5SoundURL,
27-
p5URL,
28-
useP5Version
29-
} from '../../hooks/useP5Version';
24+
import { majorVersion, p5URL, useP5Version } from '../../hooks/useP5Version';
25+
import p5SoundURL from '../../../../../common/p5URLs';
3026
import VersionPicker from '../VersionPicker';
3127
import { updateFileContent } from '../../actions/files';
3228
import { CmControllerContext } from '../../pages/IDEView';

client/modules/IDE/hooks/useP5Version.jsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,22 @@ import React, { useContext, useMemo } from 'react';
33
import { useSelector } from 'react-redux';
44
import PropTypes from 'prop-types';
55
import { currentP5Version, p5Versions } from '../../../../common/p5Versions';
6+
import {
7+
p5SoundURLOldTemplate,
8+
p5SoundURL,
9+
p5PreloadAddonURL,
10+
p5ShapesAddonURL,
11+
p5DataAddonURL,
12+
p5URLTemplate
13+
} from '../../../../common/p5URLs';
614

715
export const majorVersion = (version) => version.split('.')[0];
816

9-
export const p5SoundURLOldTemplate =
10-
'https://cdnjs.cloudflare.com/ajax/libs/p5.js/$VERSION/addons/p5.sound.min.js';
1117
export const p5SoundURLOld = p5SoundURLOldTemplate.replace(
1218
'$VERSION',
1319
currentP5Version
1420
);
15-
export const p5SoundURL =
16-
'https://cdn.jsdelivr.net/npm/[email protected]/dist/p5.sound.min.js';
17-
export const p5PreloadAddonURL =
18-
'https://cdn.jsdelivr.net/npm/[email protected]/src/preload.js';
19-
export const p5ShapesAddonURL =
20-
'https://cdn.jsdelivr.net/npm/[email protected]/src/shapes.js';
21-
export const p5DataAddonURL =
22-
'https://cdn.jsdelivr.net/npm/[email protected]/src/data.js';
23-
export const p5URL = `https://cdn.jsdelivr.net/npm/p5@${currentP5Version}/lib/p5.js`;
21+
export const p5URL = p5URLTemplate.replace('$VERSION', currentP5Version);
2422

2523
const P5VersionContext = React.createContext({});
2624

client/modules/IDE/reducers/files.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import {
55
defaultCSS,
66
defaultHTML
77
} from '../../../../server/domain-objects/createDefaultFiles';
8+
import { parseUrlParams } from '../../../utils/parseURLParams';
89

910
export const initialState = () => {
1011
const a = objectID().toHexString();
1112
const b = objectID().toHexString();
1213
const c = objectID().toHexString();
1314
const r = objectID().toHexString();
15+
const params = parseUrlParams(window.location.href);
1416
return [
1517
{
1618
name: 'root',
@@ -32,7 +34,7 @@ export const initialState = () => {
3234
},
3335
{
3436
name: 'index.html',
35-
content: defaultHTML,
37+
content: defaultHTML(params),
3638
id: b,
3739
_id: b,
3840
fileType: 'file',

client/utils/parseURLParams.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { p5Versions, currentP5Version } from '../../common/p5Versions';
2+
3+
const DEFAULTS = {
4+
sound: true,
5+
preload: false,
6+
shapes: false,
7+
data: false
8+
};
9+
10+
/**
11+
* Sorts version strings in descending order and returns the highest version
12+
* @param {string[]} versions - Array of version strings (e.g., ['1.11.2', '1.11.1'])
13+
* @returns {string} The highest version from the array
14+
*/
15+
function getNewestVersion(versions) {
16+
return versions.sort((a, b) => {
17+
const pa = a.split('.').map((n) => parseInt(n, 10));
18+
const pb = b.split('.').map((n) => parseInt(n, 10));
19+
for (let i = 0; i < 3; i++) {
20+
const na = pa[i] || 0;
21+
const nb = pb[i] || 0;
22+
if (na !== nb) return nb - na;
23+
}
24+
return 0;
25+
})[0];
26+
}
27+
28+
function validateVersion(version) {
29+
if (!version) return currentP5Version;
30+
31+
const ver = String(version).trim();
32+
33+
if (p5Versions.includes(ver)) return ver;
34+
35+
// if only major.minor provided like "1.11"
36+
const majorMinorMatch = /^(\d+)\.(\d+)$/.exec(ver);
37+
if (majorMinorMatch) {
38+
const [, major, minor] = majorMinorMatch;
39+
const matches = p5Versions.filter((v) => {
40+
const parts = v.split('.');
41+
return parts[0] === major && parts[1] === minor;
42+
});
43+
if (matches.length) {
44+
return getNewestVersion(matches);
45+
}
46+
}
47+
48+
// if only major provided like "1"
49+
const majorOnlyMatch = /^(\d+)$/.exec(ver);
50+
if (majorOnlyMatch) {
51+
const [, major] = majorOnlyMatch;
52+
const matches = p5Versions.filter((v) => v.split('.')[0] === major);
53+
if (matches.length) {
54+
return getNewestVersion(matches);
55+
}
56+
}
57+
58+
return currentP5Version;
59+
}
60+
61+
function validateBool(value, defaultValue) {
62+
if (!value) return defaultValue;
63+
64+
const v = String(value).trim().toLowerCase();
65+
66+
const TRUTHY = new Set(['on', 'true', '1']);
67+
const FALSY = new Set(['off', 'false', '0']);
68+
69+
if (TRUTHY.has(v)) return true;
70+
if (FALSY.has(v)) return false;
71+
72+
return defaultValue;
73+
}
74+
75+
export function parseUrlParams(url) {
76+
const params = new URLSearchParams(
77+
new URL(url, 'https://dummy.origin').search
78+
);
79+
80+
return {
81+
version: validateVersion(params.get('version')),
82+
sound: validateBool(params.get('sound'), DEFAULTS.sound),
83+
preload: validateBool(params.get('preload'), DEFAULTS.preload),
84+
shapes: validateBool(params.get('shapes'), DEFAULTS.shapes),
85+
data: validateBool(params.get('data'), DEFAULTS.data)
86+
};
87+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { parseUrlParams } from './parseURLParams';
2+
import { currentP5Version } from '../../common/p5Versions';
3+
4+
describe('parseUrlParams', () => {
5+
test('returns defaults when no params are provided', () => {
6+
const url = 'https://example.com';
7+
const result = parseUrlParams(url);
8+
9+
expect(result).toEqual({
10+
version: currentP5Version,
11+
sound: true,
12+
preload: false,
13+
shapes: false,
14+
data: false
15+
});
16+
});
17+
18+
test('parses a valid p5 version and falls back for invalid versions', () => {
19+
const good = parseUrlParams('https://example.com?version=1.4.0');
20+
expect(good.version).toBe('1.4.0');
21+
22+
const bad = parseUrlParams('https://example.com?version=9.9.9');
23+
expect(bad.version).toBe(currentP5Version);
24+
});
25+
26+
test('parses boolean-like params for sound/preload/shapes/data (true variants)', () => {
27+
const trueVariants = ['on', 'true', '1', 'ON', 'True'];
28+
29+
trueVariants.forEach((v) => {
30+
const url = `https://example.com?sound=${v}&preload=${v}&shapes=${v}&data=${v}`;
31+
const result = parseUrlParams(url);
32+
expect(result.sound).toBe(true);
33+
expect(result.preload).toBe(true);
34+
expect(result.shapes).toBe(true);
35+
expect(result.data).toBe(true);
36+
});
37+
});
38+
39+
test('parses boolean-like params for sound/preload/shapes/data (false variants)', () => {
40+
const falseVariants = ['off', 'false', '0', 'OFF', 'False'];
41+
42+
falseVariants.forEach((v) => {
43+
const url = `https://example.com?sound=${v}&preload=${v}&shapes=${v}&data=${v}`;
44+
const result = parseUrlParams(url);
45+
expect(result.sound).toBe(false);
46+
expect(result.preload).toBe(false);
47+
expect(result.shapes).toBe(false);
48+
expect(result.data).toBe(false);
49+
});
50+
});
51+
});

common/p5URLs.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const p5SoundURLOldTemplate =
2+
'https://cdnjs.cloudflare.com/ajax/libs/p5.js/$VERSION/addons/p5.sound.min.js';
3+
export const p5SoundURL =
4+
'https://cdn.jsdelivr.net/npm/[email protected]/dist/p5.sound.min.js';
5+
export const p5PreloadAddonURL =
6+
'https://cdn.jsdelivr.net/npm/[email protected]/src/preload.js';
7+
export const p5ShapesAddonURL =
8+
'https://cdn.jsdelivr.net/npm/[email protected]/src/shapes.js';
9+
export const p5DataAddonURL =
10+
'https://cdn.jsdelivr.net/npm/[email protected]/src/data.js';
11+
export const p5URLTemplate =
12+
'https://cdn.jsdelivr.net/npm/p5@$VERSION/lib/p5.js';

common/p5Versions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const currentP5Version = '1.11.11'; // Don't update to 2.x until 2026
55
// JSON.stringify([...document.querySelectorAll('._132722c7')].map(n => n.innerText), null, 2)
66
// TODO: use their API for this to grab these at build time?
77
export const p5Versions = [
8+
'2.1.1',
89
'2.0.5',
910
'2.0.4',
1011
'2.0.3',

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "p5.js-web-editor",
3-
"version": "2.19.0",
3+
"version": "2.19.1",
44
"description": "The web editor for p5.js.",
55
"scripts": {
66
"clean": "rimraf dist",

server/domain-objects/createDefaultFiles.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
import { currentP5Version } from '../../common/p5Versions';
2+
import {
3+
p5SoundURLOldTemplate,
4+
p5SoundURL,
5+
p5PreloadAddonURL,
6+
p5ShapesAddonURL,
7+
p5DataAddonURL,
8+
p5URLTemplate
9+
} from '../../common/p5URLs';
210

311
export const defaultSketch = `function setup() {
412
createCanvas(400, 400);
@@ -8,11 +16,34 @@ function draw() {
816
background(220);
917
}`;
1018

11-
export const defaultHTML = `<!DOCTYPE html>
19+
const majorVersion = (version) => version.split('.')[0];
20+
21+
export function defaultHTML({
22+
version = currentP5Version,
23+
sound = true,
24+
preload = false,
25+
shapes = false,
26+
data = false
27+
} = {}) {
28+
const p5URL = p5URLTemplate.replace('$VERSION', version);
29+
30+
const soundURL =
31+
majorVersion(version) === '2'
32+
? p5SoundURL
33+
: p5SoundURLOldTemplate.replace('$VERSION', version);
34+
35+
const libraries = [
36+
`<script src="${p5URL}"></script>`,
37+
sound ? `<script src="${soundURL}"></script>` : '',
38+
preload ? `<script src="${p5PreloadAddonURL}"></script>` : '',
39+
shapes ? `<script src="${p5ShapesAddonURL}"></script>` : '',
40+
data ? `<script src="${p5DataAddonURL}"></script>` : ''
41+
].join('\n ');
42+
43+
return `<!DOCTYPE html>
1244
<html lang="en">
1345
<head>
14-
<script src="https://cdn.jsdelivr.net/npm/p5@${currentP5Version}/lib/p5.js"></script>
15-
<script src="https://cdn.jsdelivr.net/npm/p5@${currentP5Version}/lib/addons/p5.sound.min.js"></script>
46+
${libraries}
1647
<link rel="stylesheet" type="text/css" href="style.css">
1748
<meta charset="utf-8" />
1849
@@ -24,6 +55,7 @@ export const defaultHTML = `<!DOCTYPE html>
2455
</body>
2556
</html>
2657
`;
58+
}
2759

2860
export const defaultCSS = `html, body {
2961
margin: 0;
@@ -37,7 +69,7 @@ canvas {
3769
export default function createDefaultFiles() {
3870
return {
3971
'index.html': {
40-
content: defaultHTML
72+
content: defaultHTML()
4173
},
4274
'style.css': {
4375
content: defaultCSS

0 commit comments

Comments
 (0)