diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index db32ceab95..0000000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,63 +0,0 @@
-// eslint-disable-next-line no-undef
-module.exports = {
- env: {
- es2021: true
- },
- extends: 'eslint:recommended',
- overrides: [
- ],
- parserOptions: {
- ecmaVersion: 'latest'
- },
- globals: {
- Blockly: 'readonly',
- Scratch: 'readonly',
- ScratchBlocks: 'readonly',
- ScratchExtensions: 'readonly',
- scaffolding: 'readonly'
- },
- rules: {
- 'no-unused-vars': 'off',
- // Allow while (true) { }
- 'no-constant-condition': [
- 'error',
- {
- checkLoops: false
- }
- ],
- // Allow empty catch {} blocks
- 'no-empty': [
- 'error',
- {
- allowEmptyCatch: true
- }
- ],
- // Returning a value from a constructor() implies a mistake
- 'no-constructor-return': 'error',
- // new Promise(async () => {}) implies a mistake
- 'no-async-promise-executor': 'warn',
- // x === x implies a mistake
- 'no-self-compare': 'error',
- // Using ${...} in a non-template-string implies a mistake
- 'no-template-curly-in-string': 'error',
- // Loops that only iterate once imply a mistake
- 'no-unreachable-loop': 'error',
- // Detect some untrusted code execution
- 'no-eval': 'error',
- 'no-implied-eval': 'error',
- 'no-new-func': 'error',
- 'no-script-url': 'error',
- // Combinations of || and && are unreadable and may not do what you expect
- 'no-mixed-operators': [
- 'error',
- {
- groups: [
- ['&&', '||']
- ]
- }
- ],
- // Disallow async functions that don't need to be. This is important as a Promise and non-Promise return value
- // significantly impacts the behavior of projects.
- 'require-await': 'error'
- }
-};
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index d4e69ab358..f341519f05 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -19,11 +19,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 16
+ node-version: 20.x
- name: Install dependencies
run: npm ci
- name: Build for production
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index 2db07a1930..c02a81ea48 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -8,12 +8,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: '14.x'
- cache: 'npm'
+ node-version: 20.x
+ cache: npm
- name: Install dependencies
run: npm ci
- name: Validate
@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: '14.x'
- cache: 'npm'
+ node-version: 20.x
+ cache: npm
- name: Install dependencies
run: npm ci
- name: Validate
@@ -38,12 +38,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: '14.x'
- cache: 'npm'
+ node-version: 20.x
+ cache: npm
- name: Install dependencies
run: npm ci
- name: Validate
diff --git a/.gitignore b/.gitignore
index 03f6901597..b6b3ebdff6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,17 @@
# npm
node_modules
-# Final built website
+# Final built website and localizations
build
+build-l10n
+
+# Various operating system caches
+thumbs.db
+.DS_Store
+
+# Popular editors
+.vscode
+.idea
+*.sublime-workspace
+
+# Tip: .git/info/exclude is your personal gitignore for things that don't belong here
diff --git a/.prettierignore b/.prettierignore
index 0a39a3b587..1ac0f9e4c0 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -2,7 +2,7 @@ build
images
licenses
website
-.eslintrc.js
+eslint.config.js
*.json
*.yml
*.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 16779c139d..1f70025a76 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,6 +19,7 @@ Strictly, nothing is banned, but the following are *highly* discouraged:
- Broad "Utilities" extensions (break them up into multiple extensions, see https://github.com/TurboWarp/extensions/issues/674)
- Extensions that are very similar to existing ones (consider modifying the existing one instead)
- One-use personal extensions (load the extension as a local file instead)
+ - Extensions whose primary purpose is monetization (not in the spirit of an open source project)
- Joke extensions (they aren't funny when they cause us to get bug reports)
Some extensions were added before these rules existed. That doesn't mean you will be exempted too.
@@ -39,23 +40,51 @@ New extensions should be added in a user folder. You can name your folder anythi
Extensions must be self-contained. All libraries and hardcoded resources should be embedded into the extension's JavaScript file. If you include minified code, please link where to find the unminified code and include a copy of the original license.
-## Website stuff
+## License
+
+**We are not lawyers. This is not legal advice.**
+
+Everything in this repository must be available under an open source license. You can use any license you want, but we **STRONGLY** recommend using the [Mozilla Public License verison 2.0](licenses/MPL-2.0.txt) for all new extensions.
-To add an extension to the homepage, you need to add metadata comments at the very start of the extension's JavaScript, and add the extension's path (without .js) to `extensions/extensions.json`. The order of that list determines the order of the library. Don't worry about putting it in the right spot, we'll move it if we disagree.
+The following licenses are banned for being [incompatible the GPLv3](https://www.gnu.org/licenses/license-list.en.html), so do not use any code, images, etc. under them:
+
+ - Creative Commons Attribution-ShareAlike licenses prior to version 4.0
+ - This includes user-generated content on the Scratch website which [uses version 2.0](https://scratch.mit.edu/terms_of_use) of this license.
+ - This includes StackOverflow posts contributed before 2018-05-02 which [use several different versions](https://stackoverflow.com/help/licensing).
+ - Creative Commons Attribution-NoDerivs and similar "no derivatives" licenses
+ - Creative Commons Attribution-NonCommercial and similar "non commercial" or "personal use only" licenses
-The header comments look like this:
+Once you choose a license for your extension, [find its SPDX identifier from this table](https://spdx.org/licenses/). The "FSF Free/Libre?" and "OSI Approved?" columns should both contain "Y".
+
+## Metadata
+
+All extensions should need a metadata comment at the *very* start of the file, before any code. We have a script that will read these, so to make sure it understands what you write, use this exact format:
```js
-// Name: Example Extension
+// Name: My Cool Extension
// ID: extensionid
// Description: Does a very cool thing. This must have punctuation at the end!
// By: GarboMuffin
// Original: TestMuffin
+// License: MPL-2.0
```
-Remember, this has to be the *very first* thing in the JS file. `Name`, `Description`, and `ID` are required. Make sure that `ID` exactly matches what you return in `getInfo()`. You can have zero or more `By` and `Original`. Put credit links in `` if you have one. It must point to a Scratch user profile. This metadata is parsed by a script to generate the website and extension library. It tries to be pretty loose, but don't deviate too far. You must use `//`, not `/* */`.
+You must use line comments; block comments `/* */` will not work. These fields are **REQUIRED**:
+
+ - `Name` will appear on the website. It should be similar to the name returned by getInfo().
+ - `ID` should be identical to the id returned by getInfo().
+ - `Description` will appear on the website.
+ - `License` describes the license that the extension's code is under. It should be a valid [SPDX license](https://spdx.org/licenses/) expression. (use `MPL-2.0` if you are unsure)
-New extensions do not *need* images, but they are highly encouraged. Save the image in the `images` folder with the same folder name and file name (but different file extension) as the extension's source code. For example, if your extension is located in `extensions/TestMuffin/fetch.js`, save the image as `images/TestMuffin/fetch.svg` or `images/TestMuffin/fetch.png`. The homepage generator will detect it automatically. Images are displayed in a 2:1 aspect ratio. SVG (preferred), PNG, or JPG are accepted. PNG or JPG should be 600x300 in resolution. Please add proper attribution to `images/README.md` for *any* resources that were not made by you.
+`By` is optionally used to credit the author of the extension (you!). `Original` is used if the extension is based on or ported from somewhere else. They both use the same format of `Name` or `Name `. Links to places other than Scratch are not allowed at this time. You can repeat both of these as many times as needed, just add another `// By: ...` comment after.
+
+In addition to `// License: ...`, you can also add a larger block comment with more information if you want to.
+
+## Website stuff
+
+Add your extension's path (without `extensions/` and without `.js`) to `extensions/extensions.json`. The order of that list determines the order of the library. Don't worry about putting it in the right spot, we'll move it if we disagree.
+
+New extensions do not *need* images, but they are encouraged. Save the image in the `images` folder with the same folder name and file name (but different file extension) as the extension's source code. For example, if your extension is located in `extensions/TestMuffin/fetch.js`, save the image as `images/TestMuffin/fetch.svg` or `images/TestMuffin/fetch.png`. The homepage generator will detect it automatically. Images are displayed in a 2:1 aspect ratio. SVG (preferred), PNG, or JPG are accepted. PNG or JPG should be 600x300 in resolution. Please add proper attribution to `images/README.md` for *any* resources that were not made by you. The resulting image must be licensed under the [GNU General Public License version 3](licenses/GPL-3.0.txt).
Most extensions shouldn't need external documentation -- it should be obvious what to do just by looking at the blocks. That said, some do need more explanation. Documentation is written in markdown and placed in the `docs` folder with a similar layout to images. For example, documentation for `extensions/TestMuffin/fetch.js` would be saved as `docs/TestMuffin/fetch.md`. Our version of markdown is slightly extended to allow rendering [scratchblocks](https://scratchblocks.github.io/). Just look at the existing documentation for syntax examples. It's not a perfect experience: block colors have to be manually copied, and icons aren't supported, but it's better than what we had before. Once you put your markdown there, you can set a `docsURI` like `https://extensions.turbowarp.org/TestMuffin/fetch`.
@@ -63,58 +92,13 @@ Static resources such as example resources used by extensions go in the `website
## Banned APIs
-(subject to change)
+Don't use these:
- `eval()`
- `new Function()`
- untrusted or remote `