diff --git a/.eslintrc.js b/.eslintrc.js
index 1ca8091ca7..db32ceab95 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -10,29 +10,13 @@ module.exports = {
ecmaVersion: 'latest'
},
globals: {
+ Blockly: 'readonly',
Scratch: 'readonly',
+ ScratchBlocks: 'readonly',
ScratchExtensions: 'readonly',
scaffolding: 'readonly'
},
rules: {
- // Here is where we enforce rules to have somewhat consistent code style without being overbearing
- 'semi': [
- 'warn',
- 'always'
- ],
- 'brace-style': 'warn',
- 'key-spacing': 'warn',
- 'keyword-spacing': 'warn',
- 'new-parens': 'warn',
- 'no-trailing-spaces': [
- 'warn',
- {
- ignoreComments: true
- }
- ],
- 'space-infix-ops': 'warn',
- 'no-tabs': 'warn',
-
'no-unused-vars': 'off',
// Allow while (true) { }
'no-constant-condition': [
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index bd20acc560..2db07a1930 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -4,7 +4,7 @@ on:
pull_request:
jobs:
- build:
+ validate:
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -12,10 +12,39 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
- node-version: 16
+ node-version: '14.x'
+ cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Validate
run: npm run validate
- - name: Lint
+
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Install Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '14.x'
+ cache: 'npm'
+ - name: Install dependencies
+ run: npm ci
+ - name: Validate
run: npm run lint
+
+ format:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Install Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '14.x'
+ cache: 'npm'
+ - name: Install dependencies
+ run: npm ci
+ - name: Validate
+ run: npm run check-format
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000000..0a39a3b587
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,9 @@
+build
+images
+licenses
+website
+.eslintrc.js
+*.json
+*.yml
+*.md
+extensions/docs-examples
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000000..37cdf9afd4
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,4 @@
+{
+ "trailingComma": "es5",
+ "endOfLine": "auto"
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 96b706319c..e522ab1276 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,6 @@
# Contributing extensions
-Before you submit extensions, please read the NEW custom extension tutorial in full:
+Before you submit extensions, please read the custom extension tutorial **in full**:
- https://docs.turbowarp.org/development/extensions/introduction
@@ -10,76 +10,74 @@ Please pay special attention to:
- Maintaining backward compatibility: https://docs.turbowarp.org/development/extensions/compatibility
- A better development server: https://docs.turbowarp.org/development/extensions/better-development-server
-Pull requests that don't follow the guidelines outlined in these documents tend to take much longer to be reviewed and merged.
+Read this document **in full** too. Pull requests that don't follow the guidelines will take *much* longer to be reviewed.
-## Local development server
+## Acceptance criteria
-We recommend using our local development server:
+Strictly, nothing is banned, but the following are *highly* discouraged:
-```bash
-# Clone the repository
-git clone https://github.com/TurboWarp/extensions.git
-cd extensions
-
-# Install dependencies
-npm ci
+ - 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)
+ - Joke extensions (they aren't funny when they cause us to get bug reports)
-# Start development server
-npm run dev
-```
+Some extensions were added before these rules existed. That doesn't mean you will be exempted too.
-This starts an HTTP server on [http://localhost:8000/](http://localhost:8000/) in development mode which adds a couple of extra tools to the homepage.
+## Important context
-After installing npm dependencies, TypeScript aware editors such as Visual Studio Code will give you smart autocomplete suggestions for most Scratch and extension APIs based on [@turbowarp/types](https://github.com/TurboWarp/types) and [@turbowarp/types-tw](https://github.com/TurboWarp/types-tw). Note that these types are not perfect; some methods are missing or incorrect. Please report any issues you find.
+Every merged extension is more code that we will be expected to maintain indefinitely, even if you disappear. Remember: broken extensions mean that real projects by real people no longer work. If the renderer is rewritten one day, we will have to ensure that extensions like Clipping & Blending, RGB Channels, and Augmented Reality still work. That's not a small commitment.
-If you encounter a TypeScript error, as long as you understand the error, feel free to add `// @ts-ignore`, `// @ts-expect-error`, or just ignore the error entirely. We currently do not require extensions to pass type checking.
+We're all volunteers who all have lives outside of Scratch extensions. Many have full time jobs or are full time students. We'll get to you as soon as we can, so please be patient.
-## Alternative development server
-
-If for some reason you can't set up our local development server, you can start any other HTTP server in the `extensions` folder. You won't get some of the nice things our server has, but it may be good enough. If you have Python 3 installed this is very simple:
+## Writing extensions
-```bash
-cd extensions
-python3 -m http.server
-```
+Extension source code goes in the [`extensions`](extensions) folder. For example, an extension placed at `extensions/hello-world.js` would be accessible at [http://localhost:8000/hello-world.js](http://localhost:8000/hello-world.js) using our development server.
-Note that browsers tend to aggressively cache JavaScript files that don't opt out of caching as our development server does, so you may have to do hard reloads to ensure that changes to your scripts are applied.
+New extensions should be added in a user folder. You can name your folder anything you want; common choices are your GitHub username or your Scratch username. If your username is `TestMuffin123`, then `TestMuffin123`, `TestMuffin`, or even just `Muffin` would all be accepted -- we are very lenient about this. Do note that user folders are just for organization; other people are still allowed to edit your extension. Renaming your folder later is only allowed in very rare circumstances, so please get it right the first time.
-## Types of extensions we accept
+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.
-We strive to be tolerant of accepting almost any extension, including one-use novelty extensions or extensions that are similar to ones that already exist.
+## Website stuff
-Extensions end up in one of these categories depending on various qualities:
+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.
- - Extensions that are in the repository, but not listed on the website
- - Extensions that are listed on the website
- - Extensions that are listed in the editor's builtin extension library
+The header comments look like this:
-## Writing extensions
+```js
+// Name: Example Extension
+// ID: extensionid
+// Description: Does a very cool thing. This must have punctuation at the end!
+// By: GarboMuffin
+// Original: TestMuffin
+```
-Extension source code goes in the `extensions` folder. For example, an extension placed at `extensions/hello-world.js` would be accessible at [http://localhost:8000/hello-world.js](http://localhost:8000/hello-world.js).
+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. The parser is pretty loose, but try not to deviate too far from this format.
-New extensions should be added in a user folder. You can name your folder your GitHub username, your Scratch username, or something else. For example, if your GitHub username is "TestMuffin", you could make a `TestMuffin` folder inside of the `extensions` folder and put your extensions inside there. You could then access a file placed at `extensions/TestMuffin/hello-world.js` at [http://localhost:8000/TestMuffin/hello-world.js](http://localhost:8000/TestMuffin/hello-world.js).
+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.
-Static resources go in the `website` folder. This is where some example resources used by extensions such as fetch are placed. It works similarly to the `extensions` folder.
+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`.
-Extensions must not use `eval()`, `new Function()`, untrusted `
+
+ <% } %>
+