Skip to content

Commit 15e426c

Browse files
committed
Initial version detection
1 parent c7d835e commit 15e426c

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed

client/modules/IDE/components/Header/Toolbar.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import PlayIcon from '../../../../images/play.svg';
2020
import StopIcon from '../../../../images/stop.svg';
2121
import PreferencesIcon from '../../../../images/preferences.svg';
2222
import ProjectName from './ProjectName';
23+
import VersionPicker from '../VersionPicker';
2324

2425
const Toolbar = (props) => {
2526
const { isPlaying, infiniteLoop, preferencesIsVisible } = useSelector(
@@ -97,6 +98,9 @@ const Toolbar = (props) => {
9798
{t('Toolbar.Auto-refresh')}
9899
</label>
99100
</div>
101+
<div className="toolbar__version-picker">
102+
<VersionPicker />
103+
</div>
100104
<div className="toolbar__project-name-container">
101105
<ProjectName />
102106
{(() => {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
import { useP5Version } from '../hooks/useP5Version';
3+
4+
const VersionPicker = () => {
5+
const versionInfo = useP5Version();
6+
7+
return <p>{versionInfo?.version || 'custom'}</p>;
8+
};
9+
10+
VersionPicker.popTypes = {};
11+
12+
export default VersionPicker;
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import { useMemo } from 'react';
2+
import { useSelector } from 'react-redux';
3+
4+
// Generated from https://www.npmjs.com/package/p5?activeTab=versions
5+
// Run this in the console:
6+
// JSON.stringify([...document.querySelectorAll('._132722c7')].map(n => n.innerText), null, 2)
7+
// TODO: use their API for this to grab these at build time?
8+
export const p5Versions = [
9+
'1.11.3',
10+
'2.0.0-beta.2',
11+
'1.11.3',
12+
'1.11.2',
13+
'1.11.1',
14+
'1.11.0',
15+
'1.10.0',
16+
'1.9.4',
17+
'1.9.3',
18+
'1.9.2',
19+
'1.9.1',
20+
'1.9.0',
21+
'1.8.0',
22+
'1.7.0',
23+
'1.6.0',
24+
'1.5.0',
25+
'1.4.2',
26+
'1.4.1',
27+
'1.4.0',
28+
'1.3.1',
29+
'1.3.0',
30+
'1.2.0',
31+
'1.1.9',
32+
'1.1.8',
33+
'1.1.7',
34+
'1.1.5',
35+
'1.1.4',
36+
'1.1.3',
37+
'1.1.2',
38+
'1.1.1',
39+
'1.1.0',
40+
'1.0.0',
41+
'0.10.2',
42+
'0.10.1',
43+
'0.10.0',
44+
'0.9.0',
45+
'0.8.0',
46+
'0.7.3',
47+
'0.7.2',
48+
'0.7.1',
49+
'0.7.0',
50+
'0.6.1',
51+
'0.6.0',
52+
'0.5.16',
53+
'0.5.15',
54+
'0.5.14',
55+
'0.5.13',
56+
'0.5.12',
57+
'0.5.11',
58+
'0.5.10',
59+
'0.5.9',
60+
'0.5.8',
61+
'0.5.7',
62+
'0.5.6',
63+
'0.5.5',
64+
'0.5.4',
65+
'0.5.3',
66+
'0.5.2',
67+
'0.5.1',
68+
'0.5.0',
69+
'0.4.24',
70+
'0.4.23',
71+
'0.4.22',
72+
'0.4.21',
73+
'0.4.20',
74+
'0.4.19',
75+
'0.4.18',
76+
'0.4.17',
77+
'0.4.16',
78+
'0.4.15',
79+
'0.4.14',
80+
'0.4.13',
81+
'0.4.12',
82+
'0.4.11',
83+
'0.4.10',
84+
'0.4.9',
85+
'0.4.8',
86+
'0.4.7',
87+
'0.4.6',
88+
'0.4.5',
89+
'0.4.4',
90+
'0.4.3',
91+
'0.4.2',
92+
'0.4.1',
93+
'0.4.0',
94+
'0.3.16',
95+
'0.3.15',
96+
'0.3.14',
97+
'0.3.13',
98+
'0.3.12',
99+
'0.3.11',
100+
'0.3.10',
101+
'0.3.9',
102+
'0.3.8',
103+
'0.3.7',
104+
'0.3.6',
105+
'0.3.5',
106+
'0.3.4',
107+
'0.3.3',
108+
'0.3.2',
109+
'0.3.1',
110+
'0.3.0',
111+
'0.2.23',
112+
'0.2.22',
113+
'0.2.21',
114+
'0.2.20',
115+
'0.2.19',
116+
'0.2.18',
117+
'0.2.17',
118+
'0.2.16',
119+
'0.2.15',
120+
'0.2.14',
121+
'0.2.13',
122+
'0.2.12',
123+
'0.2.11',
124+
'0.2.10',
125+
'0.2.9',
126+
'0.2.8',
127+
'0.2.7',
128+
'0.2.6',
129+
'0.2.5',
130+
'0.2.4',
131+
'0.2.3',
132+
'0.2.2',
133+
'0.2.1'
134+
];
135+
136+
export function useP5Version() {
137+
const files = useSelector((state) => state.files);
138+
const indexSrc = files.find(
139+
(file) =>
140+
file.fileType === 'file' &&
141+
file.name === 'index.html' &&
142+
file.filePath === ''
143+
)?.content;
144+
145+
// { version: string, minified: boolean, replaceVersion: (version: string) => string } | null
146+
const versionInfo = useMemo(() => {
147+
if (!indexSrc) return null;
148+
const dom = new DOMParser().parseFromString(indexSrc, 'text/html');
149+
const usedP5Versions = [...dom.documentElement.querySelectorAll('script')]
150+
.map((scriptNode) => {
151+
const src = scriptNode.getAttribute('src') || '';
152+
const matches = [
153+
/^https?:\/\/cdnjs.cloudflare.com\/ajax\/libs\/p5.js\/(.+)\/p5\.(?:min\.)?js$/,
154+
/^https?:\/\/cdn.jsdelivr.net\/npm\/p5@(.+)\/lib\/p5\.(min\.)?js$/
155+
].map((regex) => regex.exec(src));
156+
const match = matches.find((m) => m); // Find first that matched
157+
if (!match) return null;
158+
159+
// See if this is a version we recognize
160+
if (p5Versions.includes(match[1])) {
161+
return { version: match[1], minified: !!match[2], scriptNode };
162+
}
163+
return null;
164+
})
165+
.filter((version) => version !== null);
166+
167+
// We only know for certain which one we've got if
168+
if (usedP5Versions.length === 1) {
169+
const { version, minified, scriptNode } = usedP5Versions[0];
170+
const replaceVersion = function (newVersion) {
171+
const file = minified ? 'p5.min.js' : 'p5.js';
172+
scriptNode.setAttribute(
173+
'src',
174+
`https://cdnjs.cloudflare.com/ajax/libs/p5.js/${newVersion}/${file}`
175+
);
176+
return dom.documentElement.outerHTML;
177+
};
178+
return { version, minified, replaceVersion };
179+
}
180+
return null;
181+
}, [indexSrc]);
182+
183+
return versionInfo;
184+
}

0 commit comments

Comments
 (0)