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 `