@scratch/scratch-gui 11.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,199 @@
1
+ {
2
+ "name": "@scratch/scratch-gui",
3
+ "version": "11.0.0-beta.1",
4
+ "description": "Graphical User Interface for creating and running Scratch 3.0 projects",
5
+ "author": "Massachusetts Institute of Technology",
6
+ "license": "AGPL-3.0-only",
7
+ "homepage": "https://github.com/scratchfoundation/scratch-gui#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/scratchfoundation/scratch-editor.git"
11
+ },
12
+ "main": "./dist/scratch-gui.js",
13
+ "types": "./dist/types/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/types/index.d.ts",
17
+ "default": "./dist/scratch-gui.js"
18
+ },
19
+ "./standalone": {
20
+ "types": "./dist/types/index-standalone.d.ts",
21
+ "default": "./dist/scratch-gui-standalone.js"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "npm run clean && BUILD_TYPE=dev webpack && BUILD_TYPE=dist webpack && BUILD_TYPE=dist-standalone webpack",
26
+ "clean": "rimraf ./build ./dist",
27
+ "deploy": "touch build/.nojekyll && gh-pages -t -d build -m \"[skip ci] Build for $(git log --pretty=format:%H -n1)\"",
28
+ "prepare": "node scripts/prepare.mjs",
29
+ "prune": "./prune-gh-pages.sh",
30
+ "i18n:push": "tx-push-src scratch-editor interface translations/en.json",
31
+ "i18n:src": "rimraf ./translations/messages/src && babel src > tmp.js && rimraf tmp.js && build-i18n-src ./translations/messages/src ./translations/",
32
+ "start": "webpack serve",
33
+ "test": "npm run test:lint && npm run test:unit && npm run build && npm run test:integration",
34
+ "test:integration": "cross-env JEST_JUNIT_OUTPUT_NAME=integration-tests-results.xml jest --maxWorkers=2 test[\\\\/]integration",
35
+ "test:lint": "eslint . --ext .js,.jsx,.ts,.tsx",
36
+ "test:unit": "cross-env JEST_JUNIT_OUTPUT_NAME=unit-tests-results.xml jest test[\\\\/]unit",
37
+ "test:smoke": "jest --runInBand test[\\\\/]smoke",
38
+ "watch": "webpack --watch"
39
+ },
40
+ "dependencies": {
41
+ "@microbit/microbit-universal-hex": "^0.2.2",
42
+ "@scratch/scratch-render": "11.0.0-beta.1",
43
+ "@scratch/scratch-svg-renderer": "11.0.0-beta.1",
44
+ "@scratch/scratch-vm": "11.0.0-beta.1",
45
+ "arraybuffer-loader": "^1.0.6",
46
+ "autoprefixer": "^9.0.1",
47
+ "balance-text": "^3.3.1",
48
+ "base64-loader": "^1.0.0",
49
+ "bowser": "^1.9.4",
50
+ "cat-blocks": "npm:scratch-blocks@0.1.0-prerelease.20220318143026",
51
+ "classnames": "^2.2.6",
52
+ "computed-style-to-inline-style": "^3.0.0",
53
+ "cookie": "^0.6.0",
54
+ "copy-webpack-plugin": "^6.4.1",
55
+ "core-js": "^2.5.7",
56
+ "css-loader": "5.2.7",
57
+ "dapjs": "^2.3.0",
58
+ "es6-object-assign": "^1.1.0",
59
+ "get-float-time-domain-data": "^0.1.0",
60
+ "get-user-media-promise": "^1.1.4",
61
+ "immutable": "^3.8.2",
62
+ "intl": "^1.2.5",
63
+ "js-base64": "^2.4.9",
64
+ "keymirror": "^0.1.1",
65
+ "lodash.bindall": "^4.4.0",
66
+ "lodash.debounce": "^4.0.8",
67
+ "lodash.defaultsdeep": "^4.6.1",
68
+ "lodash.omit": "^4.5.0",
69
+ "lodash.throttle": "^4.0.1",
70
+ "minilog": "^3.1.0",
71
+ "omggif": "^1.0.9",
72
+ "papaparse": "^5.3.0",
73
+ "postcss-import": "^12.0.0",
74
+ "postcss-loader": "4.3.0",
75
+ "postcss-simple-vars": "^5.0.1",
76
+ "prop-types": "^15.5.10",
77
+ "query-string": "^5.1.1",
78
+ "raw-loader": "^4.0.0",
79
+ "react-contextmenu": "^2.9.4",
80
+ "react-draggable": "^3.0.5",
81
+ "react-ga": "^2.5.3",
82
+ "react-intl": "^2.9.0",
83
+ "react-modal": "^3.9.1",
84
+ "react-popover": "^0.5.10",
85
+ "react-responsive": "^5.0.0",
86
+ "react-style-proptype": "^3.2.2",
87
+ "react-tabs": "^2.3.0",
88
+ "react-tooltip": "^4.5.1",
89
+ "react-virtualized": "^9.20.1",
90
+ "redux-throttle": "^0.1.1",
91
+ "scratch-audio": "^1.0.0",
92
+ "scratch-blocks": "^1.1.6",
93
+ "scratch-l10n": "^3.18.3",
94
+ "scratch-paint": "^2.2.151",
95
+ "scratch-render-fonts": "^1.0.2",
96
+ "scratch-storage": "^4.0.24",
97
+ "startaudiocontext": "^1.2.1",
98
+ "style-loader": "4.0.0",
99
+ "text-encoding": "^0.7.0",
100
+ "to-style": "^1.3.3",
101
+ "wav-encoder": "^1.3.0",
102
+ "xhr": "^2.5.0"
103
+ },
104
+ "peerDependencies": {
105
+ "react": "^16.0.0",
106
+ "react-dom": "^16.0.0",
107
+ "react-redux": "^5.0.7",
108
+ "redux": "^3.7.2"
109
+ },
110
+ "devDependencies": {
111
+ "@babel/cli": "7.24.8",
112
+ "@babel/core": "7.25.2",
113
+ "@babel/eslint-parser": "7.25.1",
114
+ "@babel/plugin-proposal-object-rest-spread": "7.20.7",
115
+ "@babel/plugin-syntax-dynamic-import": "7.8.3",
116
+ "@babel/plugin-transform-async-to-generator": "7.24.7",
117
+ "@babel/preset-env": "7.25.4",
118
+ "@babel/preset-react": "7.24.7",
119
+ "@types/prop-types": "^15.7.13",
120
+ "@types/react-modal": "^3.9.1",
121
+ "@typescript-eslint/eslint-plugin": "^8.7.0",
122
+ "@typescript-eslint/parser": "^8.7.0",
123
+ "babel-core": "7.0.0-bridge.0",
124
+ "babel-loader": "9.1.3",
125
+ "cheerio": "1.0.0-rc.3",
126
+ "cross-env": "^7.0.3",
127
+ "enzyme": "3.11.0",
128
+ "enzyme-adapter-react-16": "1.15.8",
129
+ "eslint": "8.57.0",
130
+ "eslint-config-scratch": "9.0.8",
131
+ "eslint-import-resolver-webpack": "0.11.1",
132
+ "eslint-plugin-import": "2.29.1",
133
+ "eslint-plugin-jest": "22.21.0",
134
+ "eslint-plugin-react": "7.35.0",
135
+ "file-loader": "6.2.0",
136
+ "gh-pages": "3.2.3",
137
+ "html-webpack-plugin": "5.6.0",
138
+ "jest": "21.2.1",
139
+ "jest-junit": "7.0.0",
140
+ "raf": "3.4.1",
141
+ "react": "^16.0.0",
142
+ "react-dom": "^16.0.0",
143
+ "react-test-renderer": "16.14.0",
144
+ "redux-mock-store": "1.5.4",
145
+ "rimraf": "2.7.1",
146
+ "scratch-semantic-release-config": "1.0.14",
147
+ "scratch-webpack-configuration": "1.6.0",
148
+ "selenium-webdriver": "3.6.0",
149
+ "semantic-release": "19.0.5",
150
+ "stream-browserify": "3.0.0",
151
+ "ts-jest": "^21.2.4",
152
+ "ts-loader": "9.5.1",
153
+ "url-loader": "4.1.1",
154
+ "web-audio-test-api": "0.5.2",
155
+ "webpack": "5.94.0",
156
+ "webpack-cli": "5.1.4",
157
+ "webpack-dev-server": "5.0.4",
158
+ "yauzl": "2.10.0"
159
+ },
160
+ "jest": {
161
+ "globals": {
162
+ "ts-jest": {
163
+ "isolatedModules": true,
164
+ "tsconfig": "<rootDir>/tsconfig.test.json"
165
+ }
166
+ },
167
+ "setupFiles": [
168
+ "raf/polyfill",
169
+ "<rootDir>/test/helpers/enzyme-setup.js"
170
+ ],
171
+ "reporters": [
172
+ "default",
173
+ [
174
+ "jest-junit",
175
+ {
176
+ "outputDirectory": "test-results"
177
+ }
178
+ ]
179
+ ],
180
+ "testPathIgnorePatterns": [
181
+ "src/test.js"
182
+ ],
183
+ "moduleNameMapper": {
184
+ "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)\\??$": "<rootDir>/test/__mocks__/fileMock.js",
185
+ "\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js",
186
+ "editor-msgs(\\.js)?$": "<rootDir>/test/__mocks__/editor-msgs-mock.js"
187
+ },
188
+ "moduleFileExtensions": [
189
+ "ts",
190
+ "js",
191
+ "tsx",
192
+ "jsx"
193
+ ],
194
+ "transform": {
195
+ "^.+\\.tsx?$": "ts-jest",
196
+ "^.+\\.jsx?$": "babel-jest"
197
+ }
198
+ }
199
+ }
@@ -0,0 +1,64 @@
1
+ #!/bin/bash
2
+ # gh-pages cleanup script: Switches to gh-pages branch, and removes all
3
+ # directories that aren't listed as remote branches
4
+
5
+ function deslash () {
6
+ # Recursively build a string of a directory's parents. E.g.,
7
+ # deslashed "feature/test/branch" returns feature/test feature
8
+ deslashed=$(dirname $1)
9
+ if [[ $deslashed =~ .*/.* ]]
10
+ then
11
+ echo $deslashed $(deslash $deslashed)
12
+ else
13
+ echo $deslashed
14
+ fi
15
+ }
16
+
17
+ repository=origin
18
+
19
+ if [[ $1 != "" ]]
20
+ then
21
+ repository=$1
22
+ fi
23
+
24
+ # Cache current branch
25
+ current=$(git rev-parse --abbrev-ref HEAD)
26
+
27
+ # Checkout most recent gh-pages
28
+ git fetch --force $repository gh-pages:gh-pages
29
+ git checkout gh-pages
30
+ git clean -fdx
31
+
32
+ # Make an array of directories to not delete, from the list of remote branches
33
+ branches=$(git ls-remote --refs --quiet $repository | awk '{print $2}' | sed -e 's/refs\/heads\///')
34
+
35
+ # Add parent directories of branches to the exclusion list (e.g. greenkeeper/)
36
+ for branch in $branches; do
37
+ if [[ $branch =~ .*/.* ]]; then
38
+ branches+=" $(deslash $branch)"
39
+ fi
40
+ done
41
+
42
+ # Dedupe all the greenkeepers (or other duplicate parent directories)
43
+ branches=$(echo "${branches[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
44
+
45
+ # Remove all directories that don't have corresponding branches
46
+ # It would be nice if we could exclude everything in .gitignore, but we're
47
+ # not on the branch with the .gitignore anymore... so we can't.
48
+ find . -type d \
49
+ \( \
50
+ -path ./.git -o \
51
+ -path ./node_modules \
52
+ $(printf " -o -path ./%s" $branches) \
53
+ \) -prune \
54
+ -o -mindepth 1 -type d \
55
+ -exec rm -rfv {} \;
56
+
57
+ # Push
58
+ git add -u
59
+ git commit -m "Remove stale directories"
60
+ git push $repository gh-pages
61
+
62
+ # Return to where we were
63
+ git checkout -f $current
64
+ exit
@@ -0,0 +1,19 @@
1
+ module.exports = {
2
+ extends: 'scratch-semantic-release-config',
3
+ branches: [
4
+ {
5
+ name: 'develop'
6
+ // default channel
7
+ },
8
+ {
9
+ name: 'hotfix/REPLACE', // replace with actual hotfix branch name
10
+ channel: 'hotfix',
11
+ prerelease: 'hotfix'
12
+ },
13
+ {
14
+ name: 'beta',
15
+ channel: 'beta',
16
+ prerelease: true
17
+ }
18
+ ]
19
+ };
@@ -0,0 +1,8 @@
1
+ const path = require('path');
2
+ module.exports = {
3
+ extends: [path.resolve(__dirname, '..', '.eslintrc.js')],
4
+ rules: {
5
+ // NPM scripts are allowed to use console.log & friends
6
+ 'no-console': 'off'
7
+ }
8
+ };
@@ -0,0 +1,125 @@
1
+ // From the NPM docs:
2
+ // "If you need to perform operations on your package before it is used, in a way that is not dependent on the
3
+ // operating system or architecture of the target system, use a prepare script."
4
+ // Once this step is complete, a developer should be able to work without an Internet connection.
5
+ // See also: https://docs.npmjs.com/cli/using-npm/scripts
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+
10
+ import yauzl from 'yauzl';
11
+ import {fileURLToPath} from 'url';
12
+
13
+ /** @typedef {import('yauzl').Entry} ZipEntry */
14
+ /** @typedef {import('yauzl').ZipFile} ZipFile */
15
+
16
+ // these aren't set in ESM mode
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = path.dirname(__filename);
19
+
20
+ // base/root path for the project
21
+ const basePath = path.join(__dirname, '..');
22
+
23
+ /**
24
+ * Extract the first matching file from a zip buffer.
25
+ * The path within the zip file is ignored: the destination path is `${destinationDirectory}/${basename(entry.name)}`.
26
+ * Prints warnings if more than one matching file is found.
27
+ * @param {function(ZipEntry): boolean} filter Returns true if the entry should be extracted.
28
+ * @param {string} relativeDestDir The directory to extract to, relative to `basePath`.
29
+ * @param {Buffer} zipBuffer A buffer containing the zip file.
30
+ * @returns {Promise<string>} A Promise for the base name of the written file (without directory).
31
+ */
32
+ const extractFirstMatchingFile = (filter, relativeDestDir, zipBuffer) => new Promise((resolve, reject) => {
33
+ try {
34
+ let extractedFileName;
35
+ yauzl.fromBuffer(zipBuffer, {lazyEntries: true}, (zipError, zipfile) => {
36
+ if (zipError) {
37
+ throw zipError;
38
+ }
39
+ zipfile.readEntry();
40
+ zipfile.on('end', () => {
41
+ resolve(extractedFileName);
42
+ });
43
+ zipfile.on('entry', entry => {
44
+ if (!filter(entry)) {
45
+ // ignore non-matching file
46
+ return zipfile.readEntry();
47
+ }
48
+ if (extractedFileName) {
49
+ console.warn(`Multiple matching files found. Ignoring: ${entry.fileName}`);
50
+ return zipfile.readEntry();
51
+ }
52
+ extractedFileName = entry.fileName;
53
+ console.info(`Found matching file: ${entry.fileName}`);
54
+ zipfile.openReadStream(entry, (fileError, readStream) => {
55
+ if (fileError) {
56
+ throw fileError;
57
+ }
58
+ const baseName = path.basename(entry.fileName);
59
+ const relativeDestFile = path.join(relativeDestDir, baseName);
60
+ console.info(`Extracting ${relativeDestFile}`);
61
+ const absoluteDestDir = path.join(basePath, relativeDestDir);
62
+ fs.mkdirSync(absoluteDestDir, {recursive: true});
63
+ const absoluteDestFile = path.join(basePath, relativeDestFile);
64
+ const outStream = fs.createWriteStream(absoluteDestFile);
65
+ readStream.on('end', () => {
66
+ outStream.close();
67
+ zipfile.readEntry();
68
+ });
69
+ readStream.pipe(outStream);
70
+ });
71
+ });
72
+ });
73
+ } catch (error) {
74
+ reject(error);
75
+ }
76
+ });
77
+
78
+ const downloadMicrobitHex = async () => {
79
+ const url = 'https://downloads.scratch.mit.edu/microbit/scratch-microbit.hex.zip';
80
+ console.info(`Downloading ${url}`);
81
+ const response = await fetch(url);
82
+ const zipBuffer = Buffer.from(await response.arrayBuffer());
83
+ const relativeHexDir = path.join('static', 'microbit');
84
+ const hexFileName = await extractFirstMatchingFile(
85
+ entry => /\.hex$/.test(entry.fileName),
86
+ path.join('static', 'microbit'),
87
+ zipBuffer
88
+ );
89
+ const relativeHexFile = path.join(relativeHexDir, hexFileName);
90
+ const relativeGeneratedDir = path.join('src', 'generated');
91
+ const relativeGeneratedFile = path.join(relativeGeneratedDir, 'microbit-hex-url.cjs');
92
+ const absoluteGeneratedDir = path.join(basePath, relativeGeneratedDir);
93
+ fs.mkdirSync(absoluteGeneratedDir, {recursive: true});
94
+ const absoluteGeneratedFile = path.join(basePath, relativeGeneratedFile);
95
+ const requirePath = `./${path
96
+ .relative(relativeGeneratedDir, relativeHexFile)
97
+ .split(path.win32.sep)
98
+ .join(path.posix.sep)}`;
99
+ fs.writeFileSync(
100
+ absoluteGeneratedFile,
101
+ [
102
+ '// This file is generated by scripts/prepare.mjs',
103
+ '// Do not edit this file directly',
104
+ '// This file relies on a loader to turn this `require` into a URL',
105
+ `module.exports = require('${requirePath}');`,
106
+ '' // final newline
107
+ ].join('\n')
108
+ );
109
+ console.info(`Wrote ${relativeGeneratedFile}`);
110
+ };
111
+
112
+ const prepare = async () => {
113
+ await downloadMicrobitHex();
114
+ };
115
+
116
+ prepare().then(
117
+ () => {
118
+ console.info('Prepare script complete');
119
+ process.exit(0);
120
+ },
121
+ e => {
122
+ console.error(e);
123
+ process.exit(1);
124
+ }
125
+ );
Binary file