From 84b58267b11e9969bf20ff972f15a767617f584f Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Mon, 22 Jun 2026 17:13:59 -0400 Subject: [PATCH] chore: add ai agent guidance --- .github/CONTRIBUTING.md | 23 ++++- .github/copilot-instructions.md | 154 +++++++++++++++++++++++----- .gitignore | 1 + .prettierignore | 5 + AGENTS.md | 173 ++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + packages/blockly/AGENTS.md | 151 ++++++++++++++++++++++++++++ packages/blockly/CLAUDE.md | 1 + packages/docs/AGENTS.md | 29 ++++++ packages/docs/CLAUDE.md | 1 + packages/plugins/AGENTS.md | 134 +++++++++++++++++++++++++ packages/plugins/CLAUDE.md | 1 + 12 files changed, 646 insertions(+), 28 deletions(-) create mode 100644 AGENTS.md create mode 120000 CLAUDE.md create mode 100644 packages/blockly/AGENTS.md create mode 120000 packages/blockly/CLAUDE.md create mode 100644 packages/docs/AGENTS.md create mode 120000 packages/docs/CLAUDE.md create mode 100644 packages/plugins/AGENTS.md create mode 120000 packages/plugins/CLAUDE.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index cc045f46aaf..828cf344f45 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,3 +1,24 @@ # Contributing to Blockly -Want to contribute? Great! Head over to the [Blockly Developers site](https://developers.google.com/blockly/guides/modify/contributing) for information on how to contribute. +Want to contribute? Great! The full contributor documentation lives on the +[Blockly docs site](https://docs.blockly.com/guides/contribute/). + +That documentation is generated from this repository, so you can also read the source +directly under [`packages/docs/docs/guides/contribute/`](../packages/docs/docs/guides/contribute/). +The pages you are most likely to need: + +| Topic | Source file | +| ------------------------ | ------------------------------------------------------------------------------------------------------------------------ | +| Style guide | [`core/style_guide.mdx`](../packages/docs/docs/guides/contribute/core/style_guide.mdx) | +| Commit messages | [`get-started/commits.mdx`](../packages/docs/docs/guides/contribute/get-started/commits.mdx) | +| Writing a good PR | [`get-started/write_a_good_pr.mdx`](../packages/docs/docs/guides/contribute/get-started/write_a_good_pr.mdx) | +| Writing a good issue | [`get-started/write_a_good_issue.mdx`](../packages/docs/docs/guides/contribute/get-started/write_a_good_issue.mdx) | +| Building and compiling | [`core/building_and_compilation/building.mdx`](../packages/docs/docs/guides/contribute/core/building_and_compilation/building.mdx) | +| Unit testing | [`core/testing/unit_testing.mdx`](../packages/docs/docs/guides/contribute/core/testing/unit_testing.mdx) | +| Localization | [`core/localization_and_translation.mdx`](../packages/docs/docs/guides/contribute/core/localization_and_translation.mdx) | +| A tour of core | [`core/core-architecture/core-tour.mdx`](../packages/docs/docs/guides/contribute/core/core-architecture/core-tour.mdx) | +| Adding a plugin | [`core/plugins/add_a_plugin.mdx`](../packages/docs/docs/guides/contribute/core/plugins/add_a_plugin.mdx) | +| Plugin naming | [`core/plugins/naming.mdx`](../packages/docs/docs/guides/contribute/core/plugins/naming.mdx) | + +For a short orientation to the repository layout, commands, and conventions, see +[`AGENTS.md`](../AGENTS.md). diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ae24fa445a0..334a65fa633 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,38 +1,138 @@ # Code review guidelines +Repository layout, commands, and coding conventions are documented in +[`AGENTS.md`](../AGENTS.md) and the per-package `AGENTS.md` files under `packages/`. +Read those for context; this file covers only what is specific to reviewing a pull +request. + +Note that this is a monorepo. Paths below are given in full, because the same filename +can exist in more than one package. + ## General principles -- **Style:** Suggest `npm run format` or `npm run lint:fix` for formatting issues; do not comment on individual style nits. + +- **Style:** Suggest `npm run format` (from the repo root) or `npm run lint:fix` for + formatting issues; do not comment on individual style nits. - **Patterns:** Enforce existing Blockly patterns and official docs over new conventions. -- **Documentation:** Prefer linking to [Blockly Dev Docs](https://developers.google.com/blockly) over duplicating content in comments. -- **TSDoc:** Public APIs require TSDoc for behavior, params, and returns. Do not include implementation details or historical context unless essential. +- **Documentation:** Prefer linking to the [Blockly docs](https://docs.blockly.com) over + duplicating content in comments. Flag any **new** link to + `developers.google.com/blockly`; that site is stale. Existing ones are legacy and + can be left alone unless the PR is already touching them. +- **TSDoc:** Public APIs require TSDoc for behavior, params, and returns. Do not include + implementation details or historical context unless essential. + +## Project ownership + +This repository is the canonical upstream, maintained by the Raspberry Pi Foundation. It +is not a fork of `google/blockly`. Do not suggest changes on the basis that this is a +fork, that upstream should be consulted, or that a change belongs in a Google-maintained +repository. + +`Copyright Google LLC` headers on existing files are correct and historical — +never ask for them to be changed. Only new files use the Raspberry Pi Foundation +copyright. See [`AGENTS.md`](../AGENTS.md#project-ownership). + +## Pull request descriptions + +The description should be concise: what changed, why, and anything a reviewer genuinely +needs, such as breaking changes or how to verify non-obvious behavior. + +Do not ask authors to expand a description that already covers those things. A short, +complete description is correct and preferable. In particular, do not request a +rationale narrative, a file-by-file walkthrough, or a restatement of the diff. + +Do flag a description that is genuinely missing the *why*, or one that omits a breaking +change. + +## Generated files + +None of these are hand-written, so do not review their contents line by line or ask for +edits to them directly. If one looks wrong, the fix belongs in its source. + +The question to ask is not "is this file generated?" but **"should this file be in this +pull request at all, and does it look regenerated rather than hand-edited?"** + +### Expected to appear — review the source, not the file + +| File | Regenerated by | +| ----------------------------- | ------------------- | +| `packages/blockly/msg/json/*` | `npm run messages` | +| `package-lock.json` | npm | + +Do not nitpick their contents. **Do** flag them if they look hand-edited rather than +regenerated — for example `msg/json/en.json` changing without a corresponding change to +`packages/blockly/msg/messages.js`, an edit to a non-English locale file (those come from +TranslateWiki), or a lockfile change in a PR that touches no dependencies. In those cases +ask for the file to be regenerated, not patched. + +### Should not appear at all — flag if present + +| File | Why | +| ------------------------------- | ------------------------------------------------------- | +| `**/CHANGELOG.md` | Written by Lerna at release time, not in feature PRs | +| `packages/docs/docs/reference/**` | Generated from core TSDoc; gitignored | +| `**/dist/**`, `**/build/**` | Build output; gitignored | + +A change to any of these in a normal pull request means something has gone wrong, and is +worth a comment. A hand-written `CHANGELOG.md` entry in particular should be flagged: +release notes come from conventional commit messages, so the fix is to write a good +commit message rather than to edit the changelog. The last three are gitignored +entirely, so their presence means they were force-added. + +The exception is a release pull request, where these files changing is the whole point. ## Localization + - All user-visible strings must use `Blockly.Msg`. -- New strings must be added to `msg/messages.js`, `msg/json/qqq.json`, and `msg/json/en.json`. -- Link [this guide](https://developers.google.com/blockly/guides/contribute/core/add_localization_token) if strings are missing or misplaced. -- PRs that attempt to add translations for non-English strings should be redirected to TranslateWiki via the ([translation guide](hhttps://developers.google.com/blockly/guides/contribute/core/translating)). +- New strings are hand-written **only** in `packages/blockly/msg/messages.js`. + `packages/blockly/msg/json/en.json` and `packages/blockly/msg/json/qqq.json` are then + regenerated by `npm run messages`. +- A pull request that adds a string should therefore contain changes to all three files. + If `en.json` or `qqq.json` is missing, the author likely forgot to run + `npm run messages`; if they were edited by hand, ask for them to be regenerated + instead. +- Link the + [localization guide](../packages/docs/docs/guides/contribute/core/localization_and_translation.mdx) + if strings are missing or misplaced. +- PRs that attempt to add translations for non-English strings should be redirected to + TranslateWiki, using the same guide. + +## Plugins (`packages/plugins/*`) + +- **Test files must be named `*.mocha.js`.** The plugin test runner silently finds no + tests and exits successfully if they are named anything else, so a green CI run does + not prove the tests ran. Flag any new plugin test file that does not use this suffix. +- **New plugins must be TypeScript.** Flag a newly added plugin written in JavaScript; + the scaffolding generator defaults to JS, so this is an easy one to miss + (`npx @blockly/create-package plugin --typescript`). Existing JavaScript plugins + are legacy — do not ask for them to be converted. +- `blockly` must be a **peer** dependency, never a direct dependency. Flag imports that + reach into deep paths inside the core package rather than its public entry points. +- Package names follow the type-based convention in + [the plugin naming guide](../packages/docs/docs/guides/contribute/core/plugins/naming.mdx). Flag new packages that do not + follow it. +- Hand-edited `version` fields or `CHANGELOG.md` entries should be flagged; both are + managed by Lerna. ## Breaking changes + ### Policy -- A breaking change is any non-backwards-compatible change to public APIs, behavior, UI, or browser requirements. -- **Avoid:** Prefer deprecation with migration paths over removal. + +- The definition of a breaking change, and the full list of what does and does not count, + is in + [`packages/blockly/AGENTS.md`](../packages/blockly/AGENTS.md#breaking-changes). + Use that list rather than a separate one here, so the two cannot drift apart. +- **Avoid:** Prefer deprecation with migration paths over removal. - **Compatibility:** Must support Safari 15.4+, latest Chrome, and latest Firefox. -- **Identification:** Flag breaking changes unless all of the following are true: - 1. PR description explicitly notes it. - 2. Commit type includes `!` (e.g., `feat!:`). - 3. Target branch is not `main`. - -### Breaking -- Removing/renaming public methods, properties, or classes. -- Changing signatures or behavior of existing public methods. -- Adding required methods to public interfaces. -- New keyboard shortcuts or context menu items (potential developer conflicts). -- DOM restructures affecting external CSS/JS. -- Changes to build output/consumption (e.g., ESM-only). -- Changes that affect the output of serialization. - -### Non-breaking (do not flag) -- Additive changes (new methods/properties). -- Internal refactoring (including items marked `@internal`). -- Tooling/workflow changes. -- Changes to unreleased code (non-`main` feature branches). \ No newline at end of file + +### Identification + +Flag breaking changes unless **all** of the following are true: + +1. The PR description explicitly notes it. +2. The commit type includes `!` (e.g., `feat!:`). +3. The target branch is not `main`. + +All three are required. Breaking changes are never merged straight to `main`: they land +on a version branch (for example `v14`) and are merged to `main` together when that +version is released. So a properly labelled breaking change that still targets `main` is +worth flagging — it is almost always aimed at the wrong branch. diff --git a/.gitignore b/.gitignore index 2829927cb72..10986068e31 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ build-debug.log /nbproject/private/ tsdoc-metadata.json .vscode +.claude/ # All packages build/ diff --git a/.prettierignore b/.prettierignore index 2360c172078..a6da4bad242 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,6 +3,11 @@ .prettierrc.js eslint.config.mjs package.json +.claude/ + +# Symlinks to AGENTS.md. Formatting these in place would replace the symlink +# with a regular file. +**/CLAUDE.md # Package build aritifacts, etc. **/dist/* diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..9ebc5f470b2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,173 @@ +# AGENTS.md + +## Project ownership + +Blockly is maintained by the **Raspberry Pi Foundation**. This repository, +`RaspberryPiFoundation/blockly`, is the canonical upstream. It is **not** a fork of +`google/blockly`, and there is no separate Google-maintained version that this one tracks +or defers to. + +Blockly was originally developed at Google, so a lot of legacy remains and it is easy to +conclude otherwise. Two things in particular are not evidence of ownership: + +- Most existing files carry a `Copyright Google LLC` header. **Leave them alone.** + Only new files get the Raspberry Pi Foundation copyright. +- Several hundred links to `developers.google.com/blockly` are still embedded in TSDoc + and comments. They are stale. Do not add new ones. + +When adding a reference or link, use the current locations: + +| For | Use | +| ----------------- | --------------------------------------------------------- | +| Source repository | `https://github.com/RaspberryPiFoundation/blockly` | +| Issues | `https://github.com/RaspberryPiFoundation/blockly/issues` | +| Documentation | `https://docs.blockly.com` | +| Project home | `https://blockly.com` | + +The npm package name is unchanged: the core library is still published as `blockly`. + +## Repository structure + +This is an npm + Nx monorepo. Workspaces are `packages/*` and `packages/plugins/*`. + +| Path | Package name | What it is | +| -------------------- | -------------- | ------------------------------------------------------------------------------- | +| `packages/blockly/` | `blockly` | The core library | +| `packages/plugins/*` | `@blockly/*` | First-party plugins (fields, themes, workspace add-ons) and their build tooling | +| `packages/docs/` | `blockly-docs` | The Docusaurus developer documentation site | + +Detailed guidance lives next to the code it describes. Read the relevant one before working in that area, rather than loading all of them: + +- [`packages/blockly/AGENTS.md`](packages/blockly/AGENTS.md) — core library +- [`packages/plugins/AGENTS.md`](packages/plugins/AGENTS.md) — plugins +- [`packages/docs/AGENTS.md`](packages/docs/AGENTS.md) — documentation site + +## Commands + +Run these from the repo root. Root scripts fan out across workspaces via Nx. + +```bash +npm ci # Install. Re-run after any pull that changes package-lock.json. + +npm run build # Build every package except the docs site +npm run build:all # Build everything, including the docs site +npm run build:docs # Docs site only + +npm run test # Full test suite across all packages. Slow. + +npm run lint # ESLint across all workspaces +npm run lint:fix +npm run format # Prettier write, whole repo +npm run format:check + +npm run clean # Reset the Nx cache and clean every package +``` + +To work on a single package, either `cd` into it and use its own scripts, or target it +with Nx from the root. The Nx project name is the package's `name` field, which for +plugins is often not the same as the directory name — run `npx nx show projects` to list +them rather than guessing. + +```bash +npx nx show projects +npx nx run blockly:test +npx nx run @blockly/field-slider:test +npx nx run-many -t build --projects=@blockly/field-slider +``` + +Two things to watch out for: + +- `format` and `format:check` exist **only** at the root. Prettier is configured once + for the whole repo, so there is no per-package equivalent. +- `build`, `test`, `clean`, `lint`, and `start` exist at both levels and mean different + things. At the root they fan out through Nx; inside a package they run that package's + own tooling. + +## Shared configuration + +Tooling is configured once at the root and covers every package. Do not add per-package +copies of these: + +- `eslint.config.mjs` — a single flat config with per-package `files` sections +- `.prettierrc.js` — shared base plus `overrides` for core, plugins, and docs, which + each use different settings +- `nx.json` — target defaults and caching +- `lerna.json` — versioning and publishing +- `commitlint.config.mjs` — conventional commit rules + +## Commits and pull requests + +Commits follow the conventional commit spec, enforced by commitlint. The type should be +one of `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `refactor`, `release`, `revert`, +or `test`. + +Breaking changes must append `!` to the type (for example `feat!:`) **and** be called out +in the pull request description. See [`packages/blockly/AGENTS.md`](packages/blockly/AGENTS.md) +for what counts as a breaking change. + +## Pull request descriptions + +Keep them short. A reviewer should be able to read the description in well under a +minute. The template in `.github/PULL_REQUEST_TEMPLATE.md` asks for the right things — +fill it in briefly rather than expanding it. + +Cover: + +- **What changed** — a short summary of the change. +- **Why** — the problem it solves. Link the issue rather than restating it. +- Anything a reviewer genuinely needs: breaking changes, migration notes, or how to + verify behavior that isn't obvious from the diff. + +Do not write a narrative. Leave out the story of how you arrived at the solution, the +approaches you tried and rejected, a file-by-file walkthrough of the diff, and any +restatement of what the code already says. Where the reasoning behind a non-obvious +decision matters, a sentence or two is enough — and it often belongs in a code comment +instead, where it will still be there in a year. + +## Versioning and publishing + +All packages share a single version line, managed by Lerna from the root +(`.github/workflows/publish.yml`). A release bumps only the packages that actually +changed, but they all move to the same version number. Git tags use the `blockly-v` +prefix. + +Never hand-edit a `version` field in a `package.json`. + +## Code conventions + +These apply to every package. The code style has changed over time; use these +conventions even where the surrounding code does not. + +- **New files** get the Apache-2.0 header with a Raspberry Pi Foundation copyright: + + ```ts + /** + * @license + * Copyright 2026 Raspberry Pi Foundation + * SPDX-License-Identifier: Apache-2.0 + */ + ``` + + Leave the copyright line alone on existing files. + +- **Optional parameters** take plain names — `workspace`, not `opt_workspace`. The + linter still permits the `opt_` prefix so that legacy code keeps passing, but do not + add new uses of it. +- **Test-only exports** should be avoided. Where they are unavoidable, prefix them with + `testOnly_`. +- **Private and internal methods** do not take a trailing `_` suffix. +- **TSDoc** is required on all public APIs, covering behavior, params, and returns. + Implementation details belong in inline comments, not in TSDoc. +- **Inline comments** explain complex implementation details or gotchas. They are not a + changelog: do not record how the code used to work unless it explains a + backwards-compatibility workaround. + +## Further reading + +The contributor documentation is in this repository under +[`packages/docs/docs/guides/contribute/`](packages/docs/docs/guides/contribute/). Read +those files directly rather than following links out to the published site. Most useful: + +- [Style guide](packages/docs/docs/guides/contribute/core/style_guide.mdx) +- [Commit messages](packages/docs/docs/guides/contribute/get-started/commits.mdx) +- [Writing a good PR](packages/docs/docs/guides/contribute/get-started/write_a_good_pr.mdx) diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/packages/blockly/AGENTS.md b/packages/blockly/AGENTS.md new file mode 100644 index 00000000000..16cd7a471f9 --- /dev/null +++ b/packages/blockly/AGENTS.md @@ -0,0 +1,151 @@ +# packages/blockly — core library + +The Blockly library itself. Source is TypeScript in `core/`; the build runs through Gulp +and the Closure Compiler. + +Repo-wide conventions (commits, licence headers, naming) are in the +[root `AGENTS.md`](../../AGENTS.md) and are not repeated here. + +## Commands + +Run from `packages/blockly/`, or from the repo root as `npx nx run blockly:`. + +```bash +npm run build # Full build via Gulp +npm run tsc # TypeScript compilation only +npm run clean # Remove build artifacts + +npm run start # Dev server, watches for changes and serves the playground + # at /tests/playground.html + +npm run test # The full CI suite. Slow — see below. +npm run test:mocha:node # Unit tests headless under Node + jsdom. The fast inner loop. +npm run test:mocha:interactive # Unit tests in a real browser, hot reloads on change +npm run test:browser # Webdriver tests in a real browser +npm run test:generators # Code generator golden-file tests + +npm run lint # ESLint check +npm run lint:fix # ESLint auto-fix +``` + +Prettier is configured at the repo root only — run `npm run format` from there. + +`npm run test` runs the entire CI suite in series: eslint, build, renamings, mocha, +generators, type definitions, and two advanced-compilation passes. Prefer +`test:mocha:node` while iterating and save the full suite for a final check. + +### Running a single test + +```bash +npx mocha --config tests/mocha/.mocharc.node.cjs tests/mocha/block_test.js +npx mocha --config tests/mocha/.mocharc.node.cjs tests/mocha/block_test.js --grep "myTestName" +``` + +Test console output is suppressed by default. Set `BLOCKLY_TEST_CONSOLE=1` to see it. + +Mocha tests use the `tdd` UI (`suite` / `test`), not BDD. + +## Further reading + +In-repo contributor documentation, which is more detailed than this file: + +- [A tour of core](../docs/docs/guides/contribute/core/core-architecture/core-tour.mdx) +- [Render management](../docs/docs/guides/contribute/core/core-architecture/render-management.mdx) +- [Style guide](../docs/docs/guides/contribute/core/style_guide.mdx) +- [Unit testing](../docs/docs/guides/contribute/core/testing/unit_testing.mdx) +- [Building and compilation](../docs/docs/guides/contribute/core/building_and_compilation/building.mdx) +- [Localization and translation](../docs/docs/guides/contribute/core/localization_and_translation.mdx) + +## Architecture + +### Core modules (`core/`) + +- **Block model:** `block.ts` — data model; `block_svg.ts` — SVG rendering and UI +- **Workspace:** `workspace.ts` — data container; `workspace_svg.ts` — rendered workspace with drag/zoom +- **Fields:** `field.ts` — base class for all block input fields (text, dropdown, checkbox, etc.) +- **Connections:** `connection.ts`, `connection_checker.ts`, `connection_db.ts` — typed connection points between blocks +- **Events:** `core/events/` — pub/sub event system with 20+ event types (block create/delete/move, UI events, etc.) +- **Keyboard navigation:** `core/keyboard_nav/` — keyboard-driven navigation and the navigation policies that define traversal order +- **Renderers:** `core/renderers/` — pluggable rendering engines; Thrasos is the current default, with Geras and Zelos also available +- **Toolbox:** `core/toolbox/` — the block picker panel and flyout +- **Serialization:** `core/serialization/` — JSON and XML block state serialization +- **Registry:** `registry.ts` — central registration for plugins, renderers, fields, and other extensible types +- **Gesture:** `gesture.ts` — unified mouse/touch/pointer event handling for drag, click, and zoom + +### Standard blocks and generators + +- `blocks/` — built-in block definitions (logic, loops, math, text, lists, variables, procedures) +- `generators/` — code generators for JavaScript, Python, Dart, Lua, and PHP; each has a subdirectory mirroring the block categories + +### Localization + +All user-visible strings must go through `Blockly.Msg`. When adding a new string: + +1. Add the key and English value to `msg/messages.js`. +2. Run `npm run messages`, which regenerates `msg/json/en.json` and `msg/json/qqq.json`. + +Never hand-edit files in `msg/json/` — they are generated, and your changes will be +overwritten. A pull request that adds a string will legitimately contain changes to all +three files. + +Do not add translations for non-English locales directly. Those come in through +TranslateWiki. + +## Public API surface + +### Default to the narrowest visibility + +New APIs should be `private` or `@internal`, unless there is a specific reason for them +to be public. Good reasons include: + +- The API was deliberately added for external developers to call. +- It represents a new behavior we are okay with developers overriding in order to customize. + +"A user could conceivably want this" is not one of them. Without a known use case, keep +it closed. Widening visibility later is easy and backwards-compatible; narrowing it later +is a breaking change, so anything made public by default is a commitment that is +expensive to walk back. + +### Marking internals + +`@internal` marks the rough equivalent of Java's package-private: a member that other +files inside the library legitimately use, but that is not part of the public API and +that code outside Blockly should not depend on. + +- Mark a member `@internal` when it has to be reachable from elsewhere in the library — + so, public in TypeScript terms — but is not something external developers should call. + In practice this means members with no visibility modifier. +- **A `private` member does not need `@internal`.** It already cannot be reached outside + its own class, so the tag adds nothing. +- Do **not** mark something `@internal` if it is expected to be overridden in a subclass, + or if it is needed for expected customization such as writing a custom field. Those are + part of the public API even though most consumers never call them directly. + +## Breaking changes + +A breaking change is any non-backwards-compatible change to public APIs, behavior, UI, +or browser requirements. Changing internal-only methods is not a breaking change. + +Prefer deprecation with a migration path over removal. Core must keep supporting Safari +15.4+, the latest Chrome, and the latest Firefox. + +Breaking changes must be noted in the pull request description, and the commit type must +include `!` (for example `feat!:`). + +### What counts as a breaking change + +- Removing or renaming public methods, properties, or classes +- Changing the signature or behavior of existing public methods +- Adding required methods to public interfaces +- New keyboard shortcuts or context menu items (they can collide with ones developers + have already bound) +- DOM restructures that would affect external CSS/JS +- Changes to serialization output +- Changes to build output or how the package is consumed (for example going ESM-only) + +### What does not count + +- Purely additive changes, such as a new method or property +- Internal refactoring, including anything marked `@internal` +- Tooling and workflow changes +- Changes to code that has not been released yet diff --git a/packages/blockly/CLAUDE.md b/packages/blockly/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/packages/blockly/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/packages/docs/AGENTS.md b/packages/docs/AGENTS.md new file mode 100644 index 00000000000..5e16333a17b --- /dev/null +++ b/packages/docs/AGENTS.md @@ -0,0 +1,29 @@ +# packages/docs — developer documentation site + +A Docusaurus site. Built as the `blockly-docs` Nx project; it is not released to npm. + +Repo-wide conventions are in the [root `AGENTS.md`](../../AGENTS.md). + +## Commands + +Run from `packages/docs/`, or from the repo root as `npm run build:docs`. + +```bash +npm start # build the API reference, then serve the site locally +npm run build # production build +npm run serve # serve an already-built site +npm run clear # clear the Docusaurus cache +npm run lint # ESLint over docs/**/*.mdx +npm run lint:fix +``` + +## Things to know + +- **`docs/reference/` is generated** from the core library's TSDoc by + `npx nx run blockly:docs`, and is gitignored. Never edit those files directly — fix the + TSDoc in `packages/blockly/core/` instead. +- **Markdown and MDX here are linted, not Prettier-formatted.** `packages/docs/**/*.md` + and `*.mdx` are listed in `.prettierignore` and handled by ESLint with + `eslint-plugin-mdx` instead, so `npm run format` will not touch them. +- Prose wrapping is preserved rather than reflowed, so existing line breaks in prose are + intentional — don't rewrap paragraphs you aren't otherwise changing. diff --git a/packages/docs/CLAUDE.md b/packages/docs/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/packages/docs/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/packages/plugins/AGENTS.md b/packages/plugins/AGENTS.md new file mode 100644 index 00000000000..80f68df5f94 --- /dev/null +++ b/packages/plugins/AGENTS.md @@ -0,0 +1,134 @@ +# packages/plugins — first-party plugins + +Most subdirectories here are self-contained plugins published to npm — fields, themes, +and workspace add-ons that an app developer loads into a Blockly workspace. Most are +TypeScript, and new ones must be; the remaining JavaScript plugins are legacy. + +The rest are tooling, test fixtures, and example apps that happen to live alongside them. +Check the table below before assuming a directory is a plugin. + +Repo-wide conventions (commits, licence headers, naming) are in the +[root `AGENTS.md`](../../AGENTS.md) and are not repeated here. + +## Layout + +Every actual plugin follows the same shape: + +``` +packages/plugins// + src/ + index.ts # public entry point (or index.js for JS plugins) + test/ + *.mocha.js # unit tests — the suffix is required, see below + index.html # playground page served by `npm start` + index.ts # playground setup + package.json + tsconfig.json # present only for TypeScript plugins + README.md +``` + +## Directories that are not plugins + +Several packages live here for convenience but are not plugins you load into a workspace. +Don't treat them as examples of how a plugin should look: + +| Directory | Package | What it actually is | +| ------------------------------- | ------------------------- | ----------------------------------------------------------------------- | +| `dev-scripts/` | `@blockly/dev-scripts` | The `blockly-scripts` CLI that every plugin's npm scripts call | +| `dev-tools/` | `@blockly/dev-tools` | Shared playground and test helpers that plugins import | +| `dev-create/` | `@blockly/create-package` | The scaffolding generator for new plugins | +| `block-test/` | `@blockly/block-test` | Test blocks used by our own test suites — not blocks for app developers | +| `migration/` | `@blockly/migrate` | A CLI that migrates apps to newer versions of Blockly | +| `sample-app/`, `sample-app-ts/` | private, unpublished | Example applications | + +`block-test` deserves particular care: `packages/blockly` takes it as a devDependency and +loads it from the Mocha setup, so editing those blocks can break the **core** test suite, +not just this package's. + +## Commands + +Run these from inside a plugin's directory: + +```bash +npm start # webpack dev server serving test/index.html, with hot reload. + # The port is chosen automatically and printed on startup. +npm test # bundle test/*.mocha.js with webpack, then run them under Mocha +npm run build # production webpack build into dist/ +npm run clean +npm run lint +``` + +All of these shell out to `blockly-scripts`, the shared CLI in `dev-scripts`. If a plugin +needs custom Mocha settings, add `test/.mocharc.js` and it will be used instead of the +default. + +To run a target from the repo root instead, use Nx. **The Nx project name is the `name` +field in the plugin's `package.json`, which is often not the directory name.** Package +names follow a type-based convention, so a generic plugin in `modal/` publishes as +`@blockly/plugin-modal`: + +| Plugin type | Package name | +| --------------- | ----------------------------------------- | +| Field | `@blockly/field-*` | +| Theme | `@blockly/theme-*` | +| Block | `@blockly/block-*` or `@blockly/blocks-*` | +| Block extension | `@blockly/extension-*` | +| Workspace | `@blockly/workspace-*` | +| Anything else | `@blockly/plugin-*` | + +Look the name up rather than guessing it from the directory: + +```bash +npx nx show projects # list every project name +npx nx run @blockly/field-slider:test +``` + +The full convention, including the tags to put in `package.json`, is in +[the plugin naming guide](../docs/docs/guides/contribute/core/plugins/naming.mdx). + +## Plugin-specific conventions + +- **Test files must be named `*.mocha.js`.** `blockly-scripts test` looks only for that + pattern; if it finds nothing it prints a warning and exits **0**. A misnamed test file + therefore fails silently and CI stays green, so double-check the suffix when adding + tests. +- Tests use the `tdd` UI (`suite` / `test`), not BDD. +- **New plugins are TypeScript.** Some existing ones are JavaScript; those are legacy + and are not the pattern to copy. +- **`blockly` is a peer dependency**, never a direct dependency. Import from the public + entry points; do not reach into deep paths inside the core package. +- **Stricter TypeScript linting than core.** `packages/plugins/**/src/*.ts` enforces + `@typescript-eslint/naming-convention`, forbids interface names starting with `I`, and + sets `explicit-member-accessibility` to `no-public` (so do not write `public`). +- **Different Prettier settings than core.** Plugins use `quoteProps: 'consistent'`, so + if any one property in an object literal needs quotes, every property gets quoted. Core + uses `preserve`. Run `npm run format` from the root and let it sort this out. +- Reuse `@blockly/dev-tools` for playground and test scaffolding instead of + reimplementing it. + +## Adding a new plugin + +Scaffold from a template rather than copying an existing plugin by hand. **New plugins +must be written in TypeScript**, and the generator defaults to JavaScript, so pass +`--typescript` explicitly — it selects the `typescript-*` template and adds the +TypeScript devDependency and `tsconfig.json`: + +```bash +npx @blockly/create-package plugin my-plugin --type plugin --typescript +``` + +Available types are `field`, `block`, `theme`, and `plugin` (the default). The generator +lives in `dev-create/templates/`. + +The remaining JavaScript plugins are legacy. Don't use one as the model for a new plugin, +and don't convert one to TypeScript as a drive-by change — that churns the public type +surface and belongs in its own pull request. + +See [Add a plugin](../docs/docs/guides/contribute/core/plugins/add_a_plugin.mdx) for the +full process, including what to put in the README and how the plugin gets published. + +## Versioning + +Versions are managed by Lerna from the repo root. Never hand-edit the `version` field in +a plugin's `package.json`, and do not add a changelog entry by hand — `CHANGELOG.md` is +generated from conventional commits. diff --git a/packages/plugins/CLAUDE.md b/packages/plugins/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/packages/plugins/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file