diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000000..bce33191f8 --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +export NX_SELF_HOSTED_REMOTE_CACHE_SERVER=https://cache.nickthesick.com +export NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN=g8@ucL8em4*Z9TKXDY9OEX@!upf^Nz9 \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..e9511bbf61 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,42 @@ +{ + "root": true, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "react-app", + "react-app/jest" + ], + "parser": "@typescript-eslint/parser", + "plugins": ["import", "@typescript-eslint"], + "settings": { + "import/extensions": [".ts", ".cts", ".mts", ".tsx", ".js", ".jsx"], + "import/external-module-folders": ["node_modules", "node_modules/@types"], + "import/parsers": { + "@typescript-eslint/parser": [".ts", ".cts", ".mts", ".tsx"] + }, + "import/resolver": { + "node": { + "extensions": [".ts", ".cts", ".mts", ".tsx", ".js", ".jsx"] + } + } + }, + "ignorePatterns": ["**/ui/*"], + "rules": { + "no-console": "error", + "curly": 1, + "import/extensions": ["error", "always", { "ignorePackages": true }], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": true, + "peerDependencies": true, + "optionalDependencies": false, + "bundledDependencies": false + } + ], + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "import/no-cycle": "error" + } +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..372e429b34 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,101 @@ +name: Bug report +description: Report a bug or broken behavior in BlockNote +labels: + - bug + - needs-triage +body: + - type: markdown + attributes: + value: | + Thanks for reporting a bug! + Please use this template to describe **broken or incorrect behavior**. + + Feature ideas or questions should go to **Discussions**. + + - type: textarea + id: problem + attributes: + label: What’s broken? + description: > + Describe the problem clearly and concisely. + What is happening that should not be happening? + placeholder: > + Example: + When editing a table cell and pressing Enter, the editor crashes and the document cannot be recovered. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What did you expect to happen? + description: > + Describe the expected or correct behavior. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: > + Provide clear steps so we can reproduce the issue. + If possible, an online reproduction (e.g. StackBlitz) is extremely helpful. + placeholder: | + 1. Create a new document + 2. Insert a table + 3. Click inside a cell + 4. Press Enter + + Optional: If you can, provide a minimal online reproduction. + You can use this starter sandbox: + https://stackblitz.com/github/TypeCellOS/BlockNote/tree/main/examples/01-basic/01-minimal?file=App.tsx + validations: + required: false + + - type: input + id: version + attributes: + label: BlockNote version + description: > + Optional — specify the version you’re using, if known. + placeholder: e.g. v0.18.2 + validations: + required: false + + - type: input + id: environment + attributes: + label: Environment + description: > + Browser, OS, framework, or other relevant environment details. + placeholder: e.g. Chrome 121, macOS 14, React 18 + validations: + required: false + + - type: textarea + id: additional + attributes: + label: Additional context + description: > + Screenshots, videos, logs, or any other context that might help. + validations: + required: false + + - type: checkboxes + id: contribute + attributes: + label: Contribution + options: + - label: "I'd be interested in contributing a fix for this issue" + required: false + + - type: checkboxes + id: sponsor + attributes: + label: Sponsor + description: > + Optional — helps us prioritize first response according to our SLA. + options: + - label: "I'm a [sponsor](https://www.blocknotejs.org/pricing) and would appreciate if you could look into this sooner than later 💖" + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..f258f05126 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,6 @@ +blank_issues_enabled: false + +contact_links: + - name: Share an idea or suggest an enhancement + url: https://github.com/TypeCellOS/BlockNote/discussions/categories/ideas-enhancements + about: Share feature ideas, enhancement suggestions, or other ideas for the BlockNote project. \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..165dad4e01 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,57 @@ +version: 2 +updates: + - package-ecosystem: "npm" + versioning-strategy: "lockfile-only" + directories: + - "/" + - "/packages/*" + schedule: + interval: "weekly" + labels: + - "npm dependencies" + commit-message: + prefix: "chore" + allow: + # @tiptap packages + - dependency-name: "@tiptap/core" + - dependency-name: "@tiptap/pm" + - dependency-name: "@tiptap/react" + - dependency-name: "@tiptap/extensions" + - dependency-name: "@tiptap/extension-bold" + - dependency-name: "@tiptap/extension-code" + - dependency-name: "@tiptap/extension-horizontal-rule" + - dependency-name: "@tiptap/extension-italic" + + - dependency-name: "@tiptap/extension-paragraph" + - dependency-name: "@tiptap/extension-strike" + - dependency-name: "@tiptap/extension-text" + - dependency-name: "@tiptap/extension-underline" + # prosemirror packages + - dependency-name: "prosemirror-changeset" + - dependency-name: "prosemirror-highlight" + - dependency-name: "prosemirror-model" + - dependency-name: "prosemirror-state" + - dependency-name: "prosemirror-tables" + - dependency-name: "prosemirror-transform" + - dependency-name: "prosemirror-view" + # react packages + - dependency-name: "react" + - dependency-name: "react-dom" + # yjs packages + - dependency-name: "yjs" + - dependency-name: "y-prosemirror" + ignore: + # Hono packages are used only in the demo AI server and are not part of + # the main editor/runtime surface area. + - dependency-name: "hono" + - dependency-name: "@hono/node-server" + - dependency-name: "@hono/*" + groups: + editor-dependencies: + patterns: + - "@tiptap/*" + - "prosemirror-*" + - "react" + - "react-dom" + - "yjs" + - "y-prosemirror" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..9870532e04 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,34 @@ +# Summary + + + +## Rationale + + + +## Changes + + + +## Impact + + + +## Testing + + + +## Screenshots/Video + + + +## Checklist + +- [ ] Code follows the project's coding standards. +- [ ] Unit tests covering the new feature have been added. +- [ ] All existing tests pass. +- [ ] The documentation has been updated to reflect the new feature + +## Additional Notes + + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bef6fe05f7..91b5ca0414 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,76 +5,203 @@ on: - main pull_request: types: [opened, synchronize, reopened, edited] - branches: - - main - - "project/**" + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN }} + NX_SELF_HOSTED_REMOTE_CACHE_SERVER: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_SERVER }} + pnpm_config_store_dir: ./node_modules/.pnpm-store jobs: build: name: Build runs-on: ubuntu-latest + timeout-minutes: 60 steps: - - uses: actions/checkout@v2 - - - uses: actions/setup-node@v2 + - uses: actions/checkout@v6 with: - node-version: "18.x" + fetch-depth: 100 - - name: Cache node modules - uses: actions/cache@v2 - env: - cache-name: cache-node-modules + - name: Install pnpm + uses: pnpm/action-setup@v5 + + - uses: nrwl/nx-set-shas@v5 + + - uses: actions/setup-node@v6 with: - # npm cache files are stored in `~/.npm` on Linux/macOS - path: ~/.npm - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- + cache: "pnpm" + cache-dependency-path: "**/pnpm-lock.yaml" + node-version-file: ".nvmrc" - - name: cache playwright - id: playwright-cache - uses: actions/cache@v2 + - name: Cache NX + uses: actions/cache@v5 with: - path: ~/.cache/ms-playwright - key: pw-new-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} + path: .nx/cache + key: nx-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }} + restore-keys: | + nx-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}- + nx-${{ env.NX_BRANCH }}- + nx- - name: Install Dependencies - run: npm install - - - name: Bootstrap packages - run: npm run bootstrap + run: pnpm install - name: Lint packages - run: npm run lint - env: - CI: true + run: pnpm run lint - name: Build packages - run: npm run build - env: - CI: true + run: pnpm run build - name: Run unit tests - run: npm run test - env: - CI: true + run: pnpm run test + + - name: Run Next.js integration test (production build) + run: NEXTJS_TEST_MODE=build npx vitest run tests/src/unit/nextjs/serverUtil.test.ts + + - name: Upload webpack stats artifact (editor) + uses: relative-ci/agent-upload-artifact-action@v2 + with: + webpackStatsFile: ./playground/dist/webpack-stats.json + artifactName: relative-ci-artifacts-editor + + - name: Soft release + id: soft-release + run: pnpx pkg-pr-new publish './packages/*' # TODO disabled only for AI branch--compact + + playwright-build: + name: "Playwright Build" + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 100 + + - name: Install pnpm + uses: pnpm/action-setup@v5 + + - uses: nrwl/nx-set-shas@v5 + + - uses: actions/setup-node@v6 + with: + cache: "pnpm" + cache-dependency-path: "**/pnpm-lock.yaml" + node-version-file: ".nvmrc" + + - name: Cache NX + uses: actions/cache@v5 + with: + path: .nx/cache + key: nx-playwright-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }} + restore-keys: | + nx-playwright-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}- + nx-playwright-${{ env.NX_BRANCH }}- + nx- + + - name: Install dependencies + run: pnpm install + + - name: Build packages + run: pnpm run build + + - name: Upload build artifacts + uses: actions/upload-artifact@v7 + with: + name: playwright-build + path: | + packages/*/dist + playground/dist + retention-days: 1 + + playwright: + name: "Playwright Tests - ${{ matrix.browser }} (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})" + runs-on: ubuntu-latest + needs: playwright-build + timeout-minutes: 30 + container: + image: mcr.microsoft.com/playwright:v1.51.1-noble + strategy: + fail-fast: false + matrix: + browser: [chromium, firefox, webkit] + shardIndex: [1, 2] + shardTotal: [2] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 100 + + - name: Install pnpm + uses: pnpm/action-setup@v5 + + - uses: actions/setup-node@v6 + with: + cache: "pnpm" + cache-dependency-path: "**/pnpm-lock.yaml" + node-version-file: ".nvmrc" + + - name: Download build artifacts + uses: actions/download-artifact@v8 + with: + name: playwright-build + + - name: Install dependencies + run: pnpm install - - name: Run server - run: npm run start:built & npx wait-on http://localhost:3000 - env: - CI: true + - name: Run server and Playwright tests + run: | + HOME=/root PLAYWRIGHT_CONFIG="--project ${{ matrix.browser }} --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}" pnpm run e2e - - name: Install Playwright - run: npx playwright install --with-deps + - name: Upload blob report + uses: actions/upload-artifact@v7 + if: ${{ !cancelled() }} + with: + name: blob-report-${{ matrix.browser }}-${{ matrix.shardIndex }} + path: tests/blob-report/ + retention-days: 1 + + - name: Upload HTML report + uses: actions/upload-artifact@v7 + if: ${{ !cancelled() }} + with: + name: playwright-report-${{ matrix.browser }}-${{ matrix.shardIndex }} + path: tests/playwright-report/ + retention-days: 30 + + merge-reports: + name: "Merge Playwright Reports" + if: ${{ !cancelled() }} + needs: playwright + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Install pnpm + uses: pnpm/action-setup@v5 + + - uses: actions/setup-node@v6 + with: + cache: "pnpm" + cache-dependency-path: "**/pnpm-lock.yaml" + node-version-file: ".nvmrc" + + - name: Install dependencies + run: pnpm install + + - name: Download blob reports + uses: actions/download-artifact@v8 + with: + path: tests/all-blob-reports + pattern: blob-report-* + merge-multiple: true - - name: Run Playwright tests - run: npx playwright test + - name: Merge reports + run: npx playwright merge-reports --reporter html ./all-blob-reports + working-directory: tests - - uses: actions/upload-artifact@v2 - if: always() + - name: Upload merged HTML report + uses: actions/upload-artifact@v7 with: - name: playwright-report - path: playwright-report/ + name: playwright-report-merged + path: tests/playwright-report/ retention-days: 30 diff --git a/.github/workflows/fresh-install-tests.yml b/.github/workflows/fresh-install-tests.yml new file mode 100644 index 0000000000..6d6ed4a452 --- /dev/null +++ b/.github/workflows/fresh-install-tests.yml @@ -0,0 +1,144 @@ +name: Fresh Install Tests + +# Periodically tests BlockNote with the latest versions of its production +# dependencies (within declared semver ranges). This catches breakage when a +# new release of a dep like @tiptap/* or prosemirror-* ships and conflicts +# with BlockNote's declared ranges — the kind of failure a user would hit when +# running `npm install @blocknote/react` in a fresh project. +# +# Only production dependencies of published (non-private) packages are updated. +# DevDependencies (vitest, vite, typescript, etc.) stay pinned to the lockfile, +# so test tooling churn doesn't cause false positives. + +on: + schedule: + - cron: "0 2 * * *" # Daily at 02:00 UTC + workflow_dispatch: # Allow manual runs + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + pnpm_config_store_dir: ./node_modules/.pnpm-store + +jobs: + fresh-install-unit-tests: + name: Unit Tests (Fresh Dep Resolution) + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - id: checkout + uses: actions/checkout@v6 + + - id: install_pnpm + name: Install pnpm + uses: pnpm/action-setup@v5 + + - id: setup_node + uses: actions/setup-node@v6 + with: + node-version-file: ".nvmrc" + # Intentionally no pnpm cache — we want fresh prod dep resolution + + - id: install_dependencies + name: Install dependencies + run: pnpm install + + - id: update_prod_deps + name: Update prod deps of published packages + # Resolves production dependencies of every published (non-private) + # workspace package to the latest version within their declared semver + # ranges. This simulates what a user gets when running + # `npm install @blocknote/react` in a fresh project. + # DevDependencies are left at their lockfile versions. + run: | + FILTERS=$(node -e " + const fs = require('fs'); + const path = require('path'); + fs.readdirSync('packages').forEach(dir => { + try { + const pkg = JSON.parse(fs.readFileSync(path.join('packages', dir, 'package.json'), 'utf8')); + if (!pkg.private && pkg.name) process.stdout.write('--filter ' + pkg.name + ' '); + } catch {} + }); + ") + echo "Updating prod deps for: $FILTERS" + eval pnpm update --prod $FILTERS + + - id: dedupe_deps + name: Dedupe transitive dependencies + # After bumping the publishable packages' prod deps, collapse any + # duplicate transitive resolutions (e.g. @tiptap/core + @tiptap/pm) + # that would otherwise differ between the updated publishable packages + # and the un-updated examples/playground. Without this, TypeScript + # treats the two copies' exports as unrelated types and example-editor + # fails to build (TS2322 on Extension vs AnyExtension). + # Dedupe only rewrites the lockfile — it does NOT modify package.json, + # so the examples' "@blocknote/*": "latest" specs (which is what + # CodeSandbox users see) stay intact. + run: pnpm dedupe + + - id: build_packages + name: Build packages + run: pnpm run build + env: + NX_SKIP_NX_CACHE: "true" + + - id: run_unit_tests + name: Run unit tests + run: pnpm run test + env: + NX_SKIP_NX_CACHE: "true" + + - name: Notify Slack on workflow failure + if: ${{ failure() }} + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + REPOSITORY: ${{ github.repository }} + WORKFLOW: ${{ github.workflow }} + RUN_ID: ${{ github.run_id }} + RUN_NUMBER: ${{ github.run_number }} + RUN_ATTEMPT: ${{ github.run_attempt }} + BRANCH: ${{ github.ref_name }} + run: | + if [ -z "$SLACK_WEBHOOK_URL" ]; then + echo "SLACK_WEBHOOK_URL is not configured; skipping Slack notification." + exit 0 + fi + + failed_step="Unknown step" + if [ "${{ steps.checkout.outcome }}" = "failure" ]; then + failed_step="Checkout repository" + elif [ "${{ steps.install_pnpm.outcome }}" = "failure" ]; then + failed_step="Install pnpm" + elif [ "${{ steps.setup_node.outcome }}" = "failure" ]; then + failed_step="Setup Node.js" + elif [ "${{ steps.install_dependencies.outcome }}" = "failure" ]; then + failed_step="Install dependencies" + elif [ "${{ steps.update_prod_deps.outcome }}" = "failure" ]; then + failed_step="Update prod deps of published packages" + elif [ "${{ steps.dedupe_deps.outcome }}" = "failure" ]; then + failed_step="Dedupe transitive dependencies" + elif [ "${{ steps.build_packages.outcome }}" = "failure" ]; then + failed_step="Build packages" + elif [ "${{ steps.run_unit_tests.outcome }}" = "failure" ]; then + failed_step="Run unit tests" + fi + + run_url="https://github.com/${REPOSITORY}/actions/runs/${RUN_ID}" + message=$(printf '%s\n%s\n%s\n%s' \ + ":warning: Fresh Install Tests failed in *${REPOSITORY}* on branch *${BRANCH}*." \ + "*Workflow:* ${WORKFLOW}" \ + "*Run:* <${run_url}|#${RUN_NUMBER} (attempt ${RUN_ATTEMPT})>" \ + "*Failed step:* ${failed_step}") + payload=$(jq --compact-output --null-input --arg text "$message" '{text: $text}') + + curl -sS -X POST \ + --fail \ + --retry 4 \ + --retry-all-errors \ + --retry-max-time 60 \ + --connect-timeout 10 \ + --max-time 30 \ + -H "Content-type: application/json" \ + --data "$payload" \ + "$SLACK_WEBHOOK_URL" diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000000..280d5a5af1 --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,74 @@ +# ./.github/workflows/publish.yml +name: Publish + +on: + push: + tags: + - v*.*.* + - v*.*.*-* + workflow_dispatch: + inputs: + version: + description: "Version tag to publish (e.g., v0.x.x-hotfix)" + required: true + type: string + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN }} + NX_SELF_HOSTED_REMOTE_CACHE_SERVER: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_SERVER }} + pnpm_config_store_dir: ./node_modules/.pnpm-store + +jobs: + publish: + name: Publish + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write # needed for provenance data generation + attestations: write + timeout-minutes: 10 + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ inputs.version }} + fetch-depth: 100 + - name: Display version being published + run: | + echo "Publishing version: ${{ inputs.version }}" + + - run: jq '.packageManager' package.json | tr -d '"pnpm@' + id: package-manager-version + + - name: Install pnpm + uses: pnpm/action-setup@v5 + with: + version: ${{ steps.package-manager-version.outputs.stdout }} + + - uses: nrwl/nx-set-shas@v5 + + - uses: actions/setup-node@v6 + with: + cache: "pnpm" + cache-dependency-path: "**/pnpm-lock.yaml" + node-version-file: ".nvmrc" + + - name: Cache NX + uses: actions/cache@v5 + with: + path: .nx/cache + key: nx-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }} + restore-keys: | + nx-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}- + nx-${{ env.NX_BRANCH }}- + nx- + + - name: Install Dependencies & Build + run: pnpm install && pnpm build + + - name: Print Environment Info + run: pnpm exec nx report + + - name: Publish packages + # Ensure npm 11.5.1 or later for trusted publishing + run: npm install -g npm@latest && pnpm exec nx release publish --access public diff --git a/.github/workflows/relative-ci.yaml b/.github/workflows/relative-ci.yaml new file mode 100644 index 0000000000..c2b848e202 --- /dev/null +++ b/.github/workflows/relative-ci.yaml @@ -0,0 +1,18 @@ +name: RelativeCI + +on: + workflow_run: + workflows: ["build"] + types: + - completed + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Send bundle stats and build information to RelativeCI (editor) + uses: relative-ci/agent-action@v2 + with: + artifactName: relative-ci-artifacts-editor + key: ${{ secrets.RELATIVE_CI_KEY }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index ef4e11d35d..898dcdcc62 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ packages/*/types examples/*/types /.pnp .pnp.js - +tsconfig.tsbuildinfo # testing coverage @@ -29,4 +29,15 @@ yarn-error.log* .vercel test-results/ playwright-report/ -release \ No newline at end of file +blob-report/ +release +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +.env +*.pem +.nx/ +# Nightshift plan artifacts (keep out of version control) +.nightshift-plan +.claude \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index b1215e8764..c5ddcef4e7 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18.16.0 \ No newline at end of file +v22.14.0 \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..0f4e5b7d67 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "$schema": "http://json.schemastore.org/prettierrc", + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "printWidth": 80, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf", + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/.resources/release-workflow.excalidraw.svg b/.resources/release-workflow.excalidraw.svg new file mode 100644 index 0000000000..635f94e031 --- /dev/null +++ b/.resources/release-workflow.excalidraw.svg @@ -0,0 +1,2 @@ +eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1daVPjSNL+Pr+CYL+Oa+rIuiZiY4OzuZrmhu53N1xiYVx1MDAwYqzGV9sy18b8981cdTAwMTJgyTp8imNe8MTQINlyqSrzyefJyir997eFhcXwvuMv/rmw6N9VvUZQ63q3i7+74zd+t1x1MDAxN7RbeIpHf/fa/W41emc9XGY7vT//+KPpda/9sNPwqj65XHR6fa/RXHUwMDBi+7WgTart5lx1MDAxZkHoN3v/cj93vab/z067WVx1MDAwYrsk/pKKX1x1MDAwYsJ29/G7/Ibf9FthXHUwMDBmr/5/+PfCwn+jn3gmqLlvXFxcdTAwMGVXL+9cdTAwMWL74deNfT/o9b7p063aTvTR6E3Pt9D1q6HXumr48ak7134lidSGcTk4fI+HXHUwMDA1N1x1MDAwNFx1MDAxNFx1MDAxOFx1MDAxMDo+cVx1MDAxYtTCuvuMXHUwMDE1xFIuhk7W/eCqXHUwMDFl4lmlXHRcdTAwMDdFbfLk41x1MDAxN/+5QFx1MDAwN0d6Ybd97a+0XHUwMDFieJvYun8w3/1cdTAwMTe37cKrXl912/1WbfCesOu1elx1MDAxZK+LnVx1MDAxMb/vMmg0XHUwMDBlw/vo6jhcZth/i6nvOH1udep40afwS6/qLb/nOpxcco62O141XGJd1zBcdTAwMWHfhWthZ7NcdTAwMTaNzX/iNnVxVDfd4LT6jcbgcNCq+a7LXHUwMDE3PTr0ba3a07c9XHUwMDBmbDxq4unIX3Hbfd9dmFkrgWqgcVx1MDAxZsc2yZRIXHUwMDFm3W23XCL7xHHGQbVg4s9cdTAwMDW9VTSxMLrsJZqpXHUwMDFmj4Fr21ra/JImOGRhoX9cdTAwMTdcdTAwMGZMwkCPw35nacfQtt23ZziGrTNxfb44eN9fv+df9vHDv3rypiFXetXuxY538O3LxuaZTn3L8/d73W77dtLrNreXz+g9rVxcb8neRTXo0rsjXHUwMDAzJVxcV5/srS6F96dL/pa3bWti46Z9/TDZdZ9+i+2o36l5j+PCNFx1MDAwMOWWO7eKbbJcdTAwMTG0rtNG1mhXr+Oh/C3R4Fx1MDAxNGzkj0pcdTAwMDY2hlx1MDAwNjVCXGYhKaHYXHUwMDBlYYQ2lqo0coAl0qTPPENcdTAwMDfaXHUwMDFmocJapqzlzOThXHUwMDA3/4SNXCLYOMnHjaG3P1x1MDAwM1x1MDAwNDNUXHUwMDE5yIFcdTAwMDI8qU0hPlxihFx1MDAwNisk2FnwYYTpMsqYhSlMN7ZEZ4F4+1x1MDAxODibQbiwgueDu8RItlvhYfDgXHUwMDFhz+nQ0XWvXHUwMDE5NFxc18uhay01gqtWdEFstt9dTHZFXHUwMDE4YFxiXHUwMDFlvKFcdTAwMTnUasl4WcWLekHL725OXHUwMDEyeNvd4CpoeY2j0e33+mH7wO893kHY7fvJPvI3nr2CXHUwMDExLkd48/fdS6heVM9Pjyu/NpYqv1x1MDAwZU6aS/UpSFx1MDAwMFx1MDAwNnRuVdJcdTAwMWYjm5VcdTAwMWGPp+jBJ1x1MDAwYijJnfn8LEBcdTAwMWIhhTEmz8lcck9cdTAwMWZ8dnKjhaWG2pl8fDZcdTAwMGVw9KXe8S3oy/2ls/Pj/ZtcdTAwMDPYvDyeNKYurff36O6vk2D/y4p3sNLwf57c8Vx1MDAxMmL1V1x1MDAxYjZ3fj7Q70fy/PzI6zbY8a54W24xnlx1MDAwMyCOakWTIDE7XHUwMDA3yFx1MDAxZpVJOIAwRFx1MDAwYmqpUI5QJuwv8lxybVx0xaM8XHUwMDE3N1x1MDAxOFx1MDAwMOFcdTAwMTYpXHUwMDAwXHUwMDAzXHUwMDFi4UdcdTAwMWNcdTAwMTU+OcB40JiCXHUwMDAzIM1cdTAwMDfNKctDXHUwMDA3y9JcdTAwMDef0Vx1MDAwMYWFtpKVzlx1MDAwMDBcdTAwMTZIY6Yw3FwiXHUwMDA2sIznfS98XHUwMDBmXHUwMDE0YEzYLaBcdTAwMDCZXHUwMDFiKIdcdTAwMDNshNtnle+Vo4fK2t7xXHUwMDE19I6q99ss681+o1x1MDAxMXR6KVx1MDAwNqCFJFx1MDAwMrSSaTqPzI1cYqYgn81cdTAwMDMlSlxmu/nAh1liLCZwYqtZlX9cdTAwMTAnhkkjPy+K/Kjh0bcxXHUwMDE05Li24JmjsfxH2aUgKVwiXzz0d8N1OLqtmO3T41x1MDAwNvVbXHUwMDA3/uqVXHUwMDE3vLX8V8u6d3xQv+339/yHcK3XU3VcdTAwMWGUXHUwMDE1opnSIEtcbtH5vTdBiNZcdTAwMWFcYlx1MDAwMDdGXG5upUiJdCaIMVx1MDAxOISRn1x1MDAxYkM1y/q2YiQ6b2w6XHI48PDpqP1HcnA5eZDWXHUwMDE01bbUuTqdM1royZpKishLS1x1MDAxN+rTXHUwMDFhbyZMX+AwVuv/bv271cRQ+Vx1MDAxZcL0mMiYXHUwMDBl00U3UE6YXHUwMDFlXHJpKdhJXHUwMDA1aUHAglVI6UDLlFhHJUioUlYxtCipKI159SBeo86XiimrLXJ0XHUwMDEwSuVQb2KAXHUwMDAz8lx1MDAwMIH/akhEmE8mPuTjau4gjtpHOVx0n1x1MDAxZsRcdTAwMGJz+ILiXHUwMDEwKuRqpXu+YiCTNj2p53faQZpcIsS/LcRcdTAwMDZcdTAwMTP9Mfj9P7/nvrtSbKXulbHP+HqZyNzweuFKxLnxRvdcXCMzIFx1MDAxY3rdcFx1MDAxOVx1MDAwNzVoXVxyXHUwMDBm3tO02yRcdTAwMDBcdTAwMTKhWLXvOqDicuOGWsVd0Fx1MDAxNFx1MDAxNFisjZ2peZ1cYiCMYVx1MDAxMsUzuitHkWazXHUwMDE24rdq41s1Olx1MDAwMZlqXHUwMDE1clx1MDAwMNdcdTAwMWPgkmrBIdsoSlxmXHUwMDAyXHUwMDBiXHUwMDAztEeOtECorNm6zlpyuFT3vYxnYJOT59JcdTAwMDDmNy7at1x1MDAxM1FcdTAwMWVdu+xe337bkltcdTAwMWK791x1MDAwN3qn3vmxVp1Ux3BLXHUwMDE0gFx1MDAxNOlcdM1cblx1MDAxNyRvLrNEXHTDL61cdTAwMGbwQdBPz49+XHUwMDE0XHUwMDE0N0LlJi+FLYQ/TlGlXHUwMDFhIWfDv3xRME7DtE62WbtnVH/J7Jz/guPNze2mP6nWuLz+Unvo6dsl7V3IXHUwMDFlX1x1MDAxNvubbKk8rcE5jzngXFxaI/8uJ9FcdTAwMWFcdTAwMDbBQ1gtpGVcdTAwMTJ02vXwJEU/U1x1MDAwNlx1MDAwNavlKEgyXig00Sg2jNbpaYjZxMaHckUzudhAWMfxwciUJzaMLXI5JSmaXHUwMDE5XHUwMDA249JcdTAwMTnHlMab0Vx1MDAxYaF35Xj6XHIj9D1cYo0xoSstNHJbX47KWPd27+12pbtz5/HNL5WNm23a/zL5hKC0RDKbXHKjkqT88yVnXHUwMDAzP5RcdTAwMTcvzz9cdTAwMWLIUFx1MDAxM1xilkzmxN6tIH0wnvI3XFxcYmAyliEvXHUwMDFlT+XP7vH9WVx1MDAwNUT7un7g1Vx1MDAwM73SPdp4hXg68rpzTFx1MDAwN75unM7vvVx04rRwJFhQLTVcdTAwMDPGmFx1MDAxOJ6244pcdTAwMDBLl+XEqVx1MDAwM0W4tsYyq7TW88/afSznnqZyxzjcpTZcdTAwMWKOXHUwMDE3R1XuXHUwMDAwZVx1MDAwNj86U2L/RUP006TX0p9cdTAwMGJdbI+XVGxvXHUwMDE3qMeEx4KJu7x7KCdcXI/GtJFJQS5cdOpdKjTjXHUwMDFj0HmHfFx1MDAxYVxmXHUwMDExXGbAaODUXCJcdI8xfignaCXFXHUwMDEwgMBgOc1xbEZcdTAwMTQzyliM4C5LhG/+dPR8R1+dW1x1MDAxNlx1MDAwYq2NQefLzM+7XHUwMDBmQeHMXHUwMDFlXHUwMDAwXHUwMDE3XFxcdDZTXHUwMDEwf1x1MDAxMf9/gaRgrpk+ns5YaHzFTHAuLS04mu4vXGYl4LDFWmilXHUwMDE0XHUwMDE1IJmU2VxmXHUwMDFj+jE1SMRcdTAwMDTqM6Yo11x1MDAxOVx1MDAxM5koKzhcdTAwMWHaXHUwMDEyjaKEoa1cdTAwMDFcbneuXHUwMDA150pnWmRcYlxixTjqdjDcXHUwMDFh+mYpwdHUbFx1MDAxNDyiXHJcdTAwMTOlQOFNcoP2bGJ4cy6vgXAuJEZO5DVKmCzxoURcdTAwMWGlmZbSgkZ1k6iaXHUwMDFi4KNcdTAwMTHYUVZTXHUwMDFjY86YSlx1MDAwNOnPOZMheFxcm1x1MDAxYlx1MDAxZTUyI8CAlps0zFxin4HGQXTAMVx1MDAwNF3+nFx0wzF/c3gsNlL3ypjna2DjXHUwMDE0MIRQp1x1MDAxNVx1MDAxOGw8OqlAmMlio1wiij8uKZhcclx1MDAxNEdcdTAwMTdqXHIjNZWMcqDKWoWkSiqWaVxyI+yxJuKt8HB0heloPFx1MDAwNFwiJJfCoIrjianHSFx1MDAwMaJcdTAwMDTEIIV3XHJUuLiQzdQyXCKBSoxcdTAwMWFWMyOtkjnZXHUwMDFla13ClzlTRKlJ2VRlXCJcdTAwMWZcdFx1MDAwZddLmERcdTAwMTGSMitEXHUwMDFlXWS8MOnDKXpcdTAwMWNcYlM6IFJXYjbNXHUwMDEypZfii4V26l5cdTAwMTlcdTAwMGJ9XHJEnFx1MDAxOINcdTAwMTCCkOQqI5VBRYeoLU3iXc+AXHUwMDE45WlmQ8OpJo6VdbzaLfYyTFKdZYmaPNd6v1x1MDAxNVx1MDAxY95cdTAwMDS97dOf2lx1MDAwYq9XjsTlSXDZuvxxMElCjJHMSrVcYlx1MDAwNylBtlx1MDAwYrmJbqZcdTAwMTWRSmPkN9rV4sdwMsA/8ZlcdTAwMDcrXHUwMDAwvK1p0mBOL1mRW1x1MDAxOKdcbte2oFx1MDAxNTKOjv1cdTAwMGVcdTAwMTNhO1xiJFx1MDAwYlx1MDAwN6NyYGbo6LhcdTAwMWNYw79M2EMmXHUwMDAzXHUwMDE2tjtF6a+hVqdzXfnNLCfN5Ymzr/T8q9e/Ovy5utbZOPxS9/cncVSuXHRqY1x1MDAxY1x1MDAwMCSHXHUwMDE23GTykMNKalx0itjc1eouc410xrpqm+Ey9tlcdTAwMWP2Q1x1MDAxNbJuT+6wnFx1MDAxYc2NhuzKkmhcdTAwMTCKl5wyytySYPH+Kll3/du/gcPmtrJcdTAwMWN/vTlXW3dqr3/X037zgVx1MDAxZepcdTAwMTV/+evks8hcbpClXGbP+kZJaSuJXHUwMDEw9lx1MDAxNTeX+EguuzOpqCicSEZSTKnkuTlcdTAwMTam0lx1MDAwN1x1MDAwN35MXWJcdTAwMTaUeMV55J/7XHUwMDA3nZ1qe6m7ut9onVx1MDAxZv+4P6vUq6+wXHUwMDA2ZOR1w29cdTAwMWR2dlC/XFzV9zW//sP7erZ5XFwv4bp/m60l8kdlgigvuELizZFqoSyTKNuGk7WSYSR/zlx1MDAwM+XEeUOEtFx1MDAwNrHBPuqRLHxMt670Q6HGNDPUyKOAS23zXG5NxIi9JThQK3X5zHzeOP80vbv6rqaox8TeginqvHsoh1x1MDAwYoyGy5FT1JJcdTAwMTO3q0h6wVxu0oBC0m6AXHUwMDE0UFx1MDAwMMZcclEowIfU+ac3XHUwMDBmefPu3IlFhmCrtVx1MDAwM+M8XHUwMDEyIFxu9TdnQii3XHUwMDA0XCImXHUwMDBmL7/CdP2wfb6lwffs/b7mXHUwMDFk7/5qlU5cdTAwMTf9hEJ9OFx1MDAwYoSUnLWkXHUwMDA2de4wM3YvIYlcdTAwMDWbzPiNuEbaddwr6TTxXHUwMDE1Mlx1MDAxZPMmXHUwMDBiZlx1MDAwNFNSaC2pKy/TYLKzP4IwbZGRamDSWFfmkjHbifKeoyF1IZmBNdggN02iolx1MDAxY5/OWcRDXHQ8yZSsXHUwMDBmvU7aM9/uJ+BZ0jCCNyVcdTAwMTWzkiojhpMpXHUwMDAwmjCqoaBcdTAwMTDQ7Vx0xKzRSFx1MDAxOI1bOfPJsqbA5al28Fx1MDAwMldcYpQrwlxuOVx1MDAxNrdcdTAwMTJcZpdlp1K4S+zMtXtXp9VpLnT7rffEsMYwmjTDKr6Fclxi1sP99mazXt168E63Tpa+Nk7XvtR+ZN25YP9cdTAwMGVcdTAwMDR9V1x1MDAwMpDewlx1MDAwYoVcdTAwMTSRqKWMNoDjmKhV+NzE4+nojL78bX6ORVx1MDAxNWhcdTAwMGL523dBoufTQsoq9Eg3zfF6XHUwMDFji+uTQJ1snV57u5tnUKtcdTAwMWZddZbEW2dExIlpVi+WvodVXHUwMDA2P07Ob46vT/SE11x1MDAxZM9cdJGWKFVSxX5+701cdTAwMTCptdFEgVs15+pcdTAwMDZcdTAwMTVNVfdaQ5hbQUzR8bRgXCJb3itcdTAwMDRB2mc1Uqdoy82c6rVPXHUwMDE5VeTie5NHa+DalS7JPLkkstv0XGbW8lx1MDAwM45cZv5fdk5kauPNXHUwMDA07HhtXHUwMDFhe1x1MDAwZrF6THAsXlnHylx1MDAwZdOjwWxsqb7RVKCZXGIuXHUwMDEyXCI66jhgXHUwMDA0LIpcctRB2iiet31cdTAwMDcl0lx1MDAxNfcpVNnozDQ2q8T2XHUwMDFkkqJcXFx1MDAxMUjqmUJVNVWp/ody7v354zdDdoVcdTAwMWFI5K3UUYXh2zDn8Xq2PbhexOfLLtUvMtPodNZC4ytmonJpXHSJ0fixMJSQQMUv0FxypVsxIy3PXHUwMDE2X1mCXHUwMDExXHUwMDE5vdRKN29NXz5cdTAwMWLBOZduR2fKjEDZXHUwMDBlKtMkTSj25Fx1MDAxYtZgjZ6dXHUwMDFhV6JPucJ709zV/FxmU1x1MDAxY4rGpPAnSlx1MDAxYorGkqNfkOBQXHUwMDE3RSlV2khGczY1spHE0VZcYlx1MDAwNcJtW/5cdIr5oHgwNyhq5VxmXHUwMDE1VFx1MDAxZVx1MDAxMSpevmQ1cFx1MDAwZbb03cyQlTH79phYbKPulbHO11x1MDAwMMSJa0ApcfP6hlwiXluqkbtAYnHBXHUwMDEz+lx1MDAwMDFSRJWikY9SeGFEdHWpIJFKcW4lgp6UOShccoSBoCCwOW7ZMnsrZNyonO38Wl+j3V5Xra3/4Fx1MDAxN/fNu7MsMtZcdTAwMDKv2W7VhrFcdTAwMTFjXGbqP7fVXHUwMDE1MHBUY5gyMvfwXHUwMDE2St1uysKF3Cw4gibGuM3gLLjiXGaVt7pcdTAwMTNcZuHKXG5AhVx0LsjEePSJjkPoeFhcdTAwMDJldMFcZiBXJ1x1MDAxNlNGXHUwMDA2yKUw+s+Gj4PmTZXxXHTv+M/L83brst7cqNfMr93m2faPV8jMjLxuuLZ1uVFdXtvX4nD7tn5cdTAwMTP0b+4vS8v4XGJjbVx1MDAxY6Lmyvjk917G6XNK0im4qnSJ/uxSNql0rtSaMKFBXHUwMDAw+rw0POvxXFxcdTAwMTBA7p0uX/+cnFx1MDAxOevdR1PMzXDGrCyYXHUwMDFkL66QXHUwMDEzhmm3XHUwMDE1VtnKj1smXHUwMDEzXHUwMDBisWbI9qxsvockz5hImU7yJFx1MDAxYl1ObuebZUtcdTAwMWLfVi5Pu0bX91x1MDAxYms3P+8qtazX5k7BME5cdTAwMTlcdTAwMDHmNltWXHUwMDFhhzlVvKasJNYghUJZyalKTOFccmI1M8hcdTAwMDO1dNXtbvo1sUtXXHUwMDFjq5lcIlx1MDAxY1x1MDAxOY1cdTAwMDFcdTAwMTDKcPPpzUXefDx3rObI1Fx1MDAxMWJ1bpXbiFx1MDAwNSiKuqWTiZ1UXzxUr8C328PW8ZatLCn4Zfs/tzf3vf93ITX/LidcdKlcXFiCXHUwMDAzSfFfit5ph1NcZlx1MDAxYVx1MDAwM66k6JpWI8tiOXuh41x1MDAxYlBAINy7x1jJ3CUkn45Y5IhTlDxwiUFVstx8amHqgEfyx8jSo6rbU0fMXHUwMDE1VXf3vr6HsDomqmXWkyRbXU5cXFx1MDAxZC1cdTAwMDdGJVx1MDAwN3FcXIlcdTAwMTbouyApQitcZlx1MDAwN1VUtYRS4Z5zXHUwMDA3Qlids72Rta4qXFwpYcE9/ILnZFx1MDAwN1xy6l/U2FxiXHUwMDAxWridV+LveNeuXFxru1x1MDAxY9Cr+vLp/Fx1MDAwMljgMLD8RWJcIltcYpGgzmCVYOZcdTAwMTVcdTAwMWZcXLJ5u37Uu9r7Xv1F61x1MDAwZqZ3fPv94JxNXHUwMDE5/VDDzfTIo3Kzj1RcdTAwMTOtmNJcdTAwMTj8XHUwMDEwXWGoMrRcIlFuXCLoaoxtxlAux1aYXHUwMDE2u5R7XHRFXHUwMDA0XHUwMDE4hTRYgfuyV0lmTjW749JhXHUwMDFhXHUwMDFixiW4jHPOVuhcdTAwMTnjnSh7OVq9LCQzqm41vWTcXGKDI5JT8GqJ5MxYhYTF9fDb7cWe71x1MDAwM1x1MDAxM3AuS1x1MDAwNbFcdTAwMTI7mUpwe1rFIT1cbnTCZZVR5Vx1MDAxOM0szYFtraJccqFcdTAwMDE1lVKOc/19XHUwMDE511x1MDAxYsD02eSUXHUwMDBikYpGWd88lVO4ITTjXHUwMDBlT6icbc/YkXPYruh6XHUwMDFlztXyb1x1MDAxN0Lv6j3wrjGsJ827Mi0vqV5lpL5cdTAwMWLFvVx1MDAxOHVL6txT4YREL5R2OFx1MDAxN6lcdTAwMTRGXHUwMDBldF6FtExTw2JjXHUwMDFlkC8hSbRcdTAwMTRPcmO0wlxinnVjq92us04lKiO50vFb3rVXv76O+j4/90I0NkIolffAmeJcdTAwMDcuMOv2pJR0ti01ZuNeO+c77crh3sny7nrb2/zZv12p7+5Nx73chmJvv6RcdTAwMDc4oShf0EWYckWcdogsaeN2XHUwMDFiM1x1MDAxOFx1MDAwNjXHXHUwMDFmg1xyXHUwMDE2i7lXoUe5V8aXXoN7TUF7XHUwMDA0Ui5rqEUxh4pcdTAwMWRsdlWNdeTRlaK7XHUwMDE1plrZ563qpqRio1x1MDAxNe8wXHUwMDFm5EjCXHUwMDEwyoybmrdKZtvEidRIXHUwMDE1XHUwMDE109Hz8CC7L+crkbF8p5iAjDHmdn2zeFx1MDAwN247KVx1MDAwZTC84Fx1MDAwN7uZuH27XHUwMDFjOlx1MDAxOKNcdTAwMTJPXHUwMDA1XHUwMDFiPFxmXHUwMDEwP4537yaiU89cYv3b0bHXXHUwMDA37lx1MDAxZlOwMbR7p8KyO1mOYmNu+y0+VNVUXHUwMDEyXHUwMDE5XHUwMDAzMHYuMtbpXzSCXv09kLExNCiz2Cfd8qnJ2G9PaLvodTqHIfbsXHUwMDAwr9CQglqqXHUwMDE3XHUwMDFlj4V+J+6B6NDXds1fa3lcdTAwMTeNdC8v3lx1MDAwNP7tctZv/nFcdTAwMTm9XFysjFDE+YxcdTAwMWZcdTAwMTGFv37763+eXHJeiiJ9commit C: fixcommit B: featbranchmaintagv1.0commit A: releaseLast ReleaseNew Releasecommit D: releasepnpm run releasetagv1.1CINPMnew tagpublish \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index f46e5ae865..7c24081186 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,12 +2,24 @@ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "search.exclude": { - "packages/editor/public/types": true + "packages/editor/public/types": true, + "packages/website/docs/.vitepress": false, + "**/.*": false }, - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "[xml]": { + "editor.defaultFormatter": "redhat.vscode-xml" + }, + "scm.defaultViewMode": "tree", + "search.defaultViewMode": "tree", + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[mdx]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..112608f8ff --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,862 @@ +## 0.51.0 (2026-05-14) + +### 🚀 Features + +- Trailing block extension rewrite ([#2733](https://github.com/TypeCellOS/BlockNote/pull/2733)) +- **markdown:** replace unified.js with custom markdown parser/serializer ([#2624](https://github.com/TypeCellOS/BlockNote/pull/2624)) +- **react:** configurable portal targets for floating UI ([#2729](https://github.com/TypeCellOS/BlockNote/pull/2729), [#2692](https://github.com/TypeCellOS/BlockNote/issues/2692)) + +### 🩹 Fixes + +- Pasting plain text from VSCode (BLO-366) ([#2713](https://github.com/TypeCellOS/BlockNote/pull/2713)) +- Parse new lines in `text/plain` as line breaks (BLO-1170) ([#2712](https://github.com/TypeCellOS/BlockNote/pull/2712)) +- Code block PDF export (BLO-987) ([#2725](https://github.com/TypeCellOS/BlockNote/pull/2725)) +- Formatting toolbar opening when inserting file block with `trailingBlock: false` (BLO-860) ([#2704](https://github.com/TypeCellOS/BlockNote/pull/2704)) +- numbered list item decorations missed on initial render ([#2734](https://github.com/TypeCellOS/BlockNote/pull/2734)) +- flicker-free mobile formatting toolbar via CSS custom properties ([#2617](https://github.com/TypeCellOS/BlockNote/pull/2617), [#2616](https://github.com/TypeCellOS/BlockNote/issues/2616)) +- add `bn-thread-orphaned` CSS class to distinguish orphaned threads ([#2737](https://github.com/TypeCellOS/BlockNote/pull/2737), [#2735](https://github.com/TypeCellOS/BlockNote/issues/2735)) +- set width attribute on image and video elements in editor render ([#2740](https://github.com/TypeCellOS/BlockNote/pull/2740), [#2726](https://github.com/TypeCellOS/BlockNote/issues/2726)) +- **a11y:** use figure/figcaption for media block captions ([#2717](https://github.com/TypeCellOS/BlockNote/pull/2717)) +- **ai:** loosen serialization of blocks in columns ([#2716](https://github.com/TypeCellOS/BlockNote/pull/2716), [#2718](https://github.com/TypeCellOS/BlockNote/pull/2718)) +- **core:** trigger codeblock input rule on Enter and place cursor inside ([#2686](https://github.com/TypeCellOS/BlockNote/pull/2686)) +- **core:** preserve list item type when pasting into empty list items ([#2722](https://github.com/TypeCellOS/BlockNote/pull/2722), [#2330](https://github.com/TypeCellOS/BlockNote/issues/2330)) +- **core:** unmount editors in transformPasted tests to prevent unhandled error ([e62880b21](https://github.com/TypeCellOS/BlockNote/commit/e62880b21)) +- **drag-n-drop:** support PDF block drag & drop (BLO-893) ([#2714](https://github.com/TypeCellOS/BlockNote/pull/2714)) +- **i18:** improve french translation for empty toggle list ([#2721](https://github.com/TypeCellOS/BlockNote/pull/2721)) +- **markdown:** emit tight lists when serializing blocks to markdown ([#2715](https://github.com/TypeCellOS/BlockNote/pull/2715)) +- **markdown:** skip placeholder text for empty files ([#434](https://github.com/TypeCellOS/BlockNote/pull/434), [#2719](https://github.com/TypeCellOS/BlockNote/pull/2719)) +- **markdown:** stable round-trip for tables, captions, and audio ([#2720](https://github.com/TypeCellOS/BlockNote/pull/2720)) +- **tests:** stabilize webkit keyboard handler tests with programmatic cursor positioning ([#2746](https://github.com/TypeCellOS/BlockNote/pull/2746)) + +### ❤️ Thank You + +- Cyril G +- Manuel Raynaud @lunika +- Matthew Lipski @matthewlipski +- Movm +- Nick Perez +- Nick the Sick @nperez0111 + +## 0.50.0 (2026-05-04) + +### 🚀 Features + +- Dark mode styling for file block wrapper component (BLO-866) ([#2680](https://github.com/TypeCellOS/BlockNote/pull/2680)) +- Drag hendle menu delete button removes all other blocks in selection (BLO-1007) ([#2683](https://github.com/TypeCellOS/BlockNote/pull/2683)) +- Enter moves selection to cell below in tables (BLO-1006) ([#2685](https://github.com/TypeCellOS/BlockNote/pull/2685)) +- additional heading top padding (BLO-1008) ([#2690](https://github.com/TypeCellOS/BlockNote/pull/2690)) +- Code mark input rule edge case (BLO-938) ([#2698](https://github.com/TypeCellOS/BlockNote/pull/2698)) +- **mantine:** upgrade @mantine/core and @mantine/hooks to v9.0.2 ([#2655](https://github.com/TypeCellOS/BlockNote/pull/2655)) + +### 🩹 Fixes + +- Hardcoded strings in comment components (BLO-1033) ([#2681](https://github.com/TypeCellOS/BlockNote/pull/2681)) +- Color naming & CSS (BLO-946) ([#2684](https://github.com/TypeCellOS/BlockNote/pull/2684)) +- link HTML attributes (BLO-915) ([#2687](https://github.com/TypeCellOS/BlockNote/pull/2687)) +- guard hideMenuIfNotFrozen against undefined view state ([#2694](https://github.com/TypeCellOS/BlockNote/pull/2694), [#2699](https://github.com/TypeCellOS/BlockNote/pull/2699)) +- Clicking comment overlapping link opens link (BLO-1091) ([#2696](https://github.com/TypeCellOS/BlockNote/pull/2696)) +- prevent table row drag from moving an extra adjacent row ([#2703](https://github.com/TypeCellOS/BlockNote/pull/2703)) +- **clipboard:** use ProseMirror selection state for Shadow DOM compatibility ([#2677](https://github.com/TypeCellOS/BlockNote/pull/2677)) + +### ❤️ Thank You + +- jt_fox @LimChaeJune +- Matthew Lipski @matthewlipski +- Nick Perez +- Wieland Lindenthal +- Yousef + +## 0.49.0 (2026-04-24) + +### 🚀 Features + +- simplify links by inlining it to BlockNote ([#2623](https://github.com/TypeCellOS/BlockNote/pull/2623)) +- add Unicode quotation mark input rule for quote blocks ([#2673](https://github.com/TypeCellOS/BlockNote/pull/2673)) + +### 🩹 Fixes + +- Inserting link removes comment & add comment button click buggy ([#2620](https://github.com/TypeCellOS/BlockNote/pull/2620), [#2573](https://github.com/TypeCellOS/BlockNote/issues/2573)) +- `useEditorDOMElement` hook ([#2619](https://github.com/TypeCellOS/BlockNote/pull/2619)) +- text color was not applying to table block ([#2663](https://github.com/TypeCellOS/BlockNote/pull/2663)) +- Drag preview blocking drops when overlapping the editor (BLO-996) ([#2670](https://github.com/TypeCellOS/BlockNote/pull/2670)) +- Drag & drop of blocks without inline content opens formatting toolbar (BLO-1116) ([#2628](https://github.com/TypeCellOS/BlockNote/pull/2628), [#2603](https://github.com/TypeCellOS/BlockNote/issues/2603)) +- save file caption/name on every keystroke instead of on close ([#2575](https://github.com/TypeCellOS/BlockNote/pull/2575)) +- prevent FloatingFocusManager from resetting editor selection ([#2525](https://github.com/TypeCellOS/BlockNote/pull/2525), [#2664](https://github.com/TypeCellOS/BlockNote/pull/2664)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- miadnguyen @miadnguyen +- mianguyen +- Nick Perez +- Yousef + +## 0.48.1 (2026-04-16) + +### 🩹 Fixes + +- make CustomChange compatible with prosemirror-changeset 2.4.1 ([#2647](https://github.com/TypeCellOS/BlockNote/pull/2647)) +- **deps:** upgrade nx to 22.6.5 to resolve axios security vulnerability (CVE-2025-62718) ([c1ef3018a](https://github.com/TypeCellOS/BlockNote/commit/c1ef3018a)) +- **deps:** upgrade nx to 22.6.5 to resolve axios security vulnerability ([#2653](https://github.com/TypeCellOS/BlockNote/pull/2653)) +- **docx-exporter:** omit w:lang when no locale provided instead of defaulting to en-US ([#2651](https://github.com/TypeCellOS/BlockNote/pull/2651)) + +### ❤️ Thank You + +- Claude Opus 4.6 (1M context) +- Nick Perez +- Nick the Sick +- Stephan Meijer @StephanMeijer + +## 0.48.0 (2026-04-13) + +### 🚀 Features + +- upgrade shiki to v4 and prosemirror-highlight to v0.15.1 ([#2625](https://github.com/TypeCellOS/BlockNote/pull/2625)) +- upgrade nx to 22.6.4 and liveblocks to 3.17.0 ([#2627](https://github.com/TypeCellOS/BlockNote/pull/2627)) + +### 🩹 Fixes + +- Image block selection clears on mouse leave in Safari ([#2613](https://github.com/TypeCellOS/BlockNote/pull/2613)) +- Backspace bug when current block is empty and previous block's last child is empty ([#2610](https://github.com/TypeCellOS/BlockNote/pull/2610)) +- allow using latest @tiptap/extension-link version ([1ae8de713](https://github.com/TypeCellOS/BlockNote/commit/1ae8de713)) +- restore depth guard in getParentBlockInfo to prevent RangeError (blo-1103) ([#2585](https://github.com/TypeCellOS/BlockNote/pull/2585)) +- pin better-auth to ~1.4.x to fix docs build ([bda30458a](https://github.com/TypeCellOS/BlockNote/commit/bda30458a)) +- hide side menu on scroll instead of overflow hacks ([#2630](https://github.com/TypeCellOS/BlockNote/pull/2630), [#2043](https://github.com/TypeCellOS/BlockNote/issues/2043)) +- disable default UI when no components context is found ([#2611](https://github.com/TypeCellOS/BlockNote/pull/2611)) +- add .js extension to fast-deep-equal ESM import ([#2641](https://github.com/TypeCellOS/BlockNote/pull/2641)) +- placeholder when overflowing now wraps ([#2291](https://github.com/TypeCellOS/BlockNote/pull/2291)) +- **core:** fix unnesting blocks with siblings (BLO-1017) ([#2601](https://github.com/TypeCellOS/BlockNote/pull/2601)) +- **core:** backspace mid-text next to columnList moves block BLO-1126 ([#2629](https://github.com/TypeCellOS/BlockNote/pull/2629)) + +### 🔥 Performance + +- optimize plugin traversals for large documents BLO-1111 ([#2600](https://github.com/TypeCellOS/BlockNote/pull/2600)) + +### ❤️ Thank You + +- Claude Opus 4.6 +- Claude Opus 4.6 (1M context) +- hedi-ghodhbane @hedi-ghodhbane +- Matthew Lipski @matthewlipski +- Nick Perez +- Nick the Sick @nperez0111 +- Yousef + +## 0.47.3 (2026-03-25) + +### 🩹 Fixes + +- **core:** preserve whitespace edge cases but collapse html formatting newlines (BLO-1065) ([#2551](https://github.com/TypeCellOS/BlockNote/pull/2551), [#2230](https://github.com/TypeCellOS/BlockNote/issues/2230)) + +### ❤️ Thank You + +- Yousef + +## 0.47.2 (2026-03-20) + +### 🩹 Fixes + +- use
/ for toggle block HTML export ([#2524](https://github.com/TypeCellOS/BlockNote/pull/2524)) +- remove @hocuspocus/provider peer dependency by inlining tiptap comment types BLO-1064 ([#2564](https://github.com/TypeCellOS/BlockNote/pull/2564)) +- **core:** slash menu fails in custom blocks after space BLO-1036 ([#2553](https://github.com/TypeCellOS/BlockNote/pull/2553)) +- **i18n:** fix typo in russian translation ([#2560](https://github.com/TypeCellOS/BlockNote/pull/2560)) + +### ❤️ Thank You + +- Claude Opus 4.6 +- Drone +- Yousef + +## 0.47.1 (2026-03-02) + +### 🩹 Fixes + +- typeerror cannot read properties of undefined ([#2522](https://github.com/TypeCellOS/BlockNote/pull/2522)) +- handle more delete key cases ([#2126](https://github.com/TypeCellOS/BlockNote/pull/2126)) +- add delay for `data-active` in collab cursors ([#2383](https://github.com/TypeCellOS/BlockNote/pull/2383)) +- disable slash menu in table content #2408 ([#2504](https://github.com/TypeCellOS/BlockNote/pull/2504), [#2408](https://github.com/TypeCellOS/BlockNote/issues/2408)) +- **ai:** selections broken due to floating-ui focus manager ([#2527](https://github.com/TypeCellOS/BlockNote/pull/2527)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez +- Yousef + +## 0.47.0 (2026-02-23) + +### 🚀 Features + +- update suggestion menu component ([#2397](https://github.com/TypeCellOS/BlockNote/pull/2397)) +- **i18n:** add Persian (fa) localization support ([#2447](https://github.com/TypeCellOS/BlockNote/pull/2447)) +- **i18n:** add Uzbek (uz) localization support ([#2506](https://github.com/TypeCellOS/BlockNote/pull/2506)) + +### 🩹 Fixes + +- prevent nested bullet list icon rendering as emoji on iOS 18+ ([#2394](https://github.com/TypeCellOS/BlockNote/pull/2394), [#2399](https://github.com/TypeCellOS/BlockNote/pull/2399)) +- ignore drag & drop from unrelated events #1968 ([#2346](https://github.com/TypeCellOS/BlockNote/pull/2346), [#1968](https://github.com/TypeCellOS/BlockNote/issues/1968)) +- disable checkbox when editor is not editable #2406 ([#2448](https://github.com/TypeCellOS/BlockNote/pull/2448), [#2406](https://github.com/TypeCellOS/BlockNote/issues/2406)) +- Backspace/enter behaviour in empty block with children ([#2451](https://github.com/TypeCellOS/BlockNote/pull/2451)) +- handle pasting into table cells better, by collapsing their content to inline #2410 ([#2449](https://github.com/TypeCellOS/BlockNote/pull/2449), [#2410](https://github.com/TypeCellOS/BlockNote/issues/2410)) +- **accessibility:** ai combobox aria-activedescendant ([#2413](https://github.com/TypeCellOS/BlockNote/pull/2413)) +- **ai:** no more scrolling to top when opening AI menu ([#2503](https://github.com/TypeCellOS/BlockNote/pull/2503)) +- **docs:** unicode char not rendered in bug template ([f13e270be](https://github.com/TypeCellOS/BlockNote/commit/f13e270be)) + +### ❤️ Thank You + +- Cyril G @Ovgodd +- Dex Devlon @bxff +- Matthew Lipski @matthewlipski +- MDSAM05 @MDSAM05 +- Mohammad RAHMANI @Mrahmani71 +- Nick Perez +- Ogabek @OgabekYuldoshev +- Wouter Vroege +- Yousef + +## 0.46.2 (2026-01-27) + +### 🩹 Fixes + +- deep merge floatingUIOptions using nested spread operators ([#2310](https://github.com/TypeCellOS/BlockNote/pull/2310)) +- Visual differences between live editor and rendered exported HTML ([#2348](https://github.com/TypeCellOS/BlockNote/pull/2348)) +- `BlockNoteViewEditor` mismatched editable value ([#2357](https://github.com/TypeCellOS/BlockNote/pull/2357)) +- add `font-synthesis` for italic & bold in fonts that don't have them specified #2325 ([#2354](https://github.com/TypeCellOS/BlockNote/pull/2354), [#2325](https://github.com/TypeCellOS/BlockNote/issues/2325)) +- disable code block language selector when editor is not editable ([#2351](https://github.com/TypeCellOS/BlockNote/pull/2351)) +- table handles would crash ([#2384](https://github.com/TypeCellOS/BlockNote/pull/2384)) +- update CreateLinkButton to be able to toggle popover visibility ([#2316](https://github.com/TypeCellOS/BlockNote/pull/2316), [#2313](https://github.com/TypeCellOS/BlockNote/issues/2313)) +- add context,nestingLevel to toExternalHTML ([#2373](https://github.com/TypeCellOS/BlockNote/pull/2373)) +- **ai:** re-enable flipping the AIMenu when there is not enough space #2245 ([#2247](https://github.com/TypeCellOS/BlockNote/pull/2247), [#2245](https://github.com/TypeCellOS/BlockNote/issues/2245)) +- **link-toolbar:** prevent Enter from submitting during IME composition ([#2361](https://github.com/TypeCellOS/BlockNote/pull/2361)) + +### ❤️ Thank You + +- hanios123 +- Jean-Baptiste PENRATH +- Matthew Lipski @matthewlipski +- Nick Perez +- Shohei Yoshida @ysds +- Yousef + +## 0.46.1 (2026-01-10) + +This was a version bump only, there were no code changes. + +## 0.46.0 (2026-01-08) + +### 🚀 Features + +- add data-nesting-level to HTML export ([#2329](https://github.com/TypeCellOS/BlockNote/pull/2329)) +- migrate to ai sdk 6 ([#2328](https://github.com/TypeCellOS/BlockNote/pull/2328)) + +### 🩹 Fixes + +- emojipicker can sometimes fail to mount ([575b81cec](https://github.com/TypeCellOS/BlockNote/commit/575b81cec)) +- LinkToolbar Event Listener leak ([#2335](https://github.com/TypeCellOS/BlockNote/pull/2335)) +- when you convert a block into checkListItem via inputRule, it should transfer its content into checkListItem content ([#2331](https://github.com/TypeCellOS/BlockNote/pull/2331)) +- do not return focus back to menu ([484d7da36](https://github.com/TypeCellOS/BlockNote/commit/484d7da36)) +- arrow up on a checklist item should move to the element above BLO-362 ([#2306](https://github.com/TypeCellOS/BlockNote/pull/2306)) +- getPos race condition in React StrictMode ([#2311](https://github.com/TypeCellOS/BlockNote/pull/2311)) +- adjust input rules to be more tolerant to starting whitespace ([#2341](https://github.com/TypeCellOS/BlockNote/pull/2341)) +- **ai:** make sure ShowSelection works ([#2297](https://github.com/TypeCellOS/BlockNote/pull/2297)) +- **xl-email-exporter:** remove redundant sections in email export ([#2323](https://github.com/TypeCellOS/BlockNote/pull/2323)) + +### ❤️ Thank You + +- Nick Perez +- Nick the Sick @nperez0111 +- supernova @tmpluto +- Yousef + +## 0.45.0 (2025-12-17) + +### 🚀 Features + +- **ai:** expand selections to contain words ([#2304](https://github.com/TypeCellOS/BlockNote/pull/2304)) +- **extensions:** extensions can now include other extensions for grouping into one extension ([#2284](https://github.com/TypeCellOS/BlockNote/pull/2284)) + +### 🩹 Fixes + +- an invalidly specified table should not crash the editor ([#2255](https://github.com/TypeCellOS/BlockNote/pull/2255)) +- filter out invalid heading items based on the current block schema in the slash menu #2253 ([#2259](https://github.com/TypeCellOS/BlockNote/pull/2259), [#2253](https://github.com/TypeCellOS/BlockNote/issues/2253)) +- relax shiki package requirements #2279 ([#2280](https://github.com/TypeCellOS/BlockNote/pull/2280), [#2279](https://github.com/TypeCellOS/BlockNote/issues/2279)) +- filter the default tiptap extensions #2282 ([#2283](https://github.com/TypeCellOS/BlockNote/pull/2283), [#2282](https://github.com/TypeCellOS/BlockNote/issues/2282)) +- always include the cursor extension #2244 ([#2260](https://github.com/TypeCellOS/BlockNote/pull/2260), [#2244](https://github.com/TypeCellOS/BlockNote/issues/2244)) +- make `onBeforeChange` return the correct type again ([9009369b1](https://github.com/TypeCellOS/BlockNote/commit/9009369b1)) +- if there is no table block, there is no table handles to show #1055 ([#2281](https://github.com/TypeCellOS/BlockNote/pull/2281), [#1055](https://github.com/TypeCellOS/BlockNote/issues/1055)) +- pass dragHandleMenu prop to DragHandleButton ([#2254](https://github.com/TypeCellOS/BlockNote/pull/2254)) +- html diff error with whitespace ([#2230](https://github.com/TypeCellOS/BlockNote/pull/2230)) +- update regex for checklist items #2288 ([#2305](https://github.com/TypeCellOS/BlockNote/pull/2305), [#2288](https://github.com/TypeCellOS/BlockNote/issues/2288)) +- **email-exporter:** ReadableByteStreamController for safari react-email ([#2295](https://github.com/TypeCellOS/BlockNote/pull/2295)) + +### ❤️ Thank You + +- Max @maqen +- Nick Perez +- Nick the Sick @nperez0111 +- Yousef + +## 0.44.2 (2025-12-09) + +### 🩹 Fixes + +- put back `onBeforeChange` method #2221 ([#2243](https://github.com/TypeCellOS/BlockNote/pull/2243), [#2221](https://github.com/TypeCellOS/BlockNote/issues/2221)) +- Improper accessing of editor DOM element ([#2234](https://github.com/TypeCellOS/BlockNote/pull/2234)) +- make validation errors recoverable by llm ([#2054](https://github.com/TypeCellOS/BlockNote/pull/2054)) +- shadowdom support and example ([#2223](https://github.com/TypeCellOS/BlockNote/pull/2223)) +- ensure numbered list start property always present ([#2241](https://github.com/TypeCellOS/BlockNote/pull/2241), [#2242](https://github.com/TypeCellOS/BlockNote/pull/2242)) +- Suggestion menu positioning ([#2232](https://github.com/TypeCellOS/BlockNote/pull/2232)) +- conditionally access the TableHandles extension from React ([#2248](https://github.com/TypeCellOS/BlockNote/pull/2248)) +- **ai:** upgrade prosemirror-suggest-changes ([#2235](https://github.com/TypeCellOS/BlockNote/pull/2235)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez +- wcyat @sdip15fa +- Yousef + +## 0.44.1 (2025-12-08) + +### 🩹 Fixes + +- clearing selection was not being called when create link button is no longer rendered ([#2217](https://github.com/TypeCellOS/BlockNote/pull/2217)) +- AI menu not updating position on new line ([#2233](https://github.com/TypeCellOS/BlockNote/pull/2233)) +- UI elements not scrolling when editor DOM element is scrollable ([#2231](https://github.com/TypeCellOS/BlockNote/pull/2231)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski + +## 0.44.0 (2025-12-02) + +### 🚀 Features + +- **ai:** Abort requests ([#2213](https://github.com/TypeCellOS/BlockNote/pull/2213)) + +### ❤️ Thank You + +- Yousef + +## 0.43.0 (2025-12-01) + +### 🚀 Features + +- Major Extensions & UI Refactor ([#2143](https://github.com/TypeCellOS/BlockNote/pull/2143)) + +### 🩹 Fixes + +- allow configuring the email body's styles ([#2182](https://github.com/TypeCellOS/BlockNote/pull/2182)) +- **xl-docx-exporter:** improve OOXML interoperability ([#2206](https://github.com/TypeCellOS/BlockNote/pull/2206)) + +### ❤️ Thank You + +- Nick Perez +- Stephan Meijer @StephanMeijer + +## 0.42.3 (2025-11-19) + +### 🩹 Fixes + +- disallow access to the `domElement` or `isFocused` if the editor is unmounted ([#2187](https://github.com/TypeCellOS/BlockNote/pull/2187)) + +### ❤️ Thank You + +- Nick Perez + +## 0.42.2 (2025-11-19) + +### 🩹 Fixes + +- put back mounting system ([#2183](https://github.com/TypeCellOS/BlockNote/pull/2183)) + +### ❤️ Thank You + +- Nick Perez + +## 0.42.1 (2025-11-18) + +### 🩹 Fixes + +- do not error on invalid `backgroundColor` or `textColor` #2176 ([#2179](https://github.com/TypeCellOS/BlockNote/pull/2179), [#2176](https://github.com/TypeCellOS/BlockNote/issues/2176)) +- remove dependency array from comments re-rendering ([#2177](https://github.com/TypeCellOS/BlockNote/pull/2177)) + +### ❤️ Thank You + +- Nick Perez + +## 0.42.0 (2025-11-11) + +### 🚀 Features + +- **yjs:** expose Y.js BlockNote conversion primitives #1866 ([#2166](https://github.com/TypeCellOS/BlockNote/pull/2166), [#1866](https://github.com/TypeCellOS/BlockNote/issues/1866)) + +### 🩹 Fixes + +- Emoji picker issues ([#2092](https://github.com/TypeCellOS/BlockNote/pull/2092)) +- set a default for `blocksToFullHTML` #2100 ([#2101](https://github.com/TypeCellOS/BlockNote/pull/2101), [#2100](https://github.com/TypeCellOS/BlockNote/issues/2100)) +- correctly index blocks that have children fixes #2115 ([#2116](https://github.com/TypeCellOS/BlockNote/pull/2116), [#2115](https://github.com/TypeCellOS/BlockNote/issues/2115)) +- add more lenient parsing for code blocks, to accept newlines #2105 ([#2108](https://github.com/TypeCellOS/BlockNote/pull/2108), [#2105](https://github.com/TypeCellOS/BlockNote/issues/2105)) +- Firefox invisible text cursor after dropping blocks ([#2128](https://github.com/TypeCellOS/BlockNote/pull/2128)) +- parsing `priority` for custom inline content and styles ([#2119](https://github.com/TypeCellOS/BlockNote/pull/2119)) +- `BlockTypeSelect` item filtering based on schema ([#2112](https://github.com/TypeCellOS/BlockNote/pull/2112)) +- deleting last block in column ([#2110](https://github.com/TypeCellOS/BlockNote/pull/2110)) +- **comments:** update the styles for the cursor to be the default cursor ([#2163](https://github.com/TypeCellOS/BlockNote/pull/2163)) +- **comments:** always surface the closest mark to the current position ([#2164](https://github.com/TypeCellOS/BlockNote/pull/2164)) +- **comments:** scrolling bug when clicking comment marks ([#2165](https://github.com/TypeCellOS/BlockNote/pull/2165)) +- **react:** destroy editor instances after two ticks ([#2121](https://github.com/TypeCellOS/BlockNote/pull/2121)) +- **schema-migration:** more robust migration of background-color & text-color attributes ([#2154](https://github.com/TypeCellOS/BlockNote/pull/2154)) +- **unique-id:** do not attempt to append to y-sync plugin transactions ([#2153](https://github.com/TypeCellOS/BlockNote/pull/2153)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez + +## 0.41.1 (2025-10-09) + +This was a version bump only, there were no code changes. + +## 0.41.0 (2025-10-08) + +### 🚀 Features + +- AI menu auto scrolling ([#2039](https://github.com/TypeCellOS/BlockNote/pull/2039)) +- Shortcut to delete empty table while cells are selected ([#2052](https://github.com/TypeCellOS/BlockNote/pull/2052)) +- **divider:** add a divider block ([#2014](https://github.com/TypeCellOS/BlockNote/pull/2014)) + +### 🩹 Fixes + +- Code block language select value not updating properly ([#2050](https://github.com/TypeCellOS/BlockNote/pull/2050)) +- disable input rules for numbered headings #1789 ([#2032](https://github.com/TypeCellOS/BlockNote/pull/2032), [#1789](https://github.com/TypeCellOS/BlockNote/issues/1789)) +- video parsing and export for markdown ([#1955](https://github.com/TypeCellOS/BlockNote/pull/1955)) +- Reaction picker shown for users who can't react ([#2061](https://github.com/TypeCellOS/BlockNote/pull/2061)) +- Add Mantine dependency to individual examples ([#2070](https://github.com/TypeCellOS/BlockNote/pull/2070)) +- allow listening to `onChange` and other events before the underlying editor is initialized ([#2063](https://github.com/TypeCellOS/BlockNote/pull/2063)) +- toggle and check list item blocks ([#2071](https://github.com/TypeCellOS/BlockNote/pull/2071)) +- added missing fields to implementations in editor schema block specs ([#2046](https://github.com/TypeCellOS/BlockNote/pull/2046)) + +### ❤️ Thank You + +- Héctor Zhuang @Hector-Zhuang +- Matthew Lipski @matthewlipski +- Nick Perez + +## 0.40.0 (2025-09-30) + +### 🚀 Features + +- Mantine v8 upgrade ([#2028](https://github.com/TypeCellOS/BlockNote/pull/2028), [#2029](https://github.com/TypeCellOS/BlockNote/issues/2029)) +- Update Mantine setup ([#2033](https://github.com/TypeCellOS/BlockNote/pull/2033)) +- **ai:** SDK 5, tool calling, custom backends ([#2007](https://github.com/TypeCellOS/BlockNote/pull/2007)) +- **core:** add the ability to autofocus on the editor element ([#2018](https://github.com/TypeCellOS/BlockNote/pull/2018)) + +### 🩹 Fixes + +- Block colors menu not always showing ([#2027](https://github.com/TypeCellOS/BlockNote/pull/2027)) +- Update remianing examples to Mantine v8 ([#2031](https://github.com/TypeCellOS/BlockNote/pull/2031)) +- ShadCN example Tailwind setup ([#2042](https://github.com/TypeCellOS/BlockNote/pull/2042)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez +- Yousef + +## 0.39.1 (2025-09-19) + +### 🩹 Fixes + +- cleanup accesses to prosemirrorView to account for tiptap 3 behavior ([#2017](https://github.com/TypeCellOS/BlockNote/pull/2017)) +- **core:** input rules can handle when a new block is empty now ([#2013](https://github.com/TypeCellOS/BlockNote/pull/2013)) + +### ❤️ Thank You + +- Nick Perez + +## 0.39.0 (2025-09-18) + +### 🚀 Features + +- move all blocks to use the custom blocks API ([#1904](https://github.com/TypeCellOS/BlockNote/pull/1904)) +- **core:** support for Tiptap V3 ([#2001](https://github.com/TypeCellOS/BlockNote/pull/2001)) + +### ❤️ Thank You + +- Nick Perez + +## 0.38.0 (2025-09-16) + +### 🚀 Features + +- Custom schemas for comment editors ([#1976](https://github.com/TypeCellOS/BlockNote/pull/1976)) + +### 🩹 Fixes + +- Suggestion menu positioning ([#1975](https://github.com/TypeCellOS/BlockNote/pull/1975)) +- doLLMRequest fails when deleting a non-existent block ([#1982](https://github.com/TypeCellOS/BlockNote/pull/1982)) +- file block resize handles not working with touch inputs ([#1981](https://github.com/TypeCellOS/BlockNote/pull/1981)) +- get pdf example working again ([a90ae4d58](https://github.com/TypeCellOS/BlockNote/commit/a90ae4d58)) +- better markdown & html paste, make methods synchronous ([#1957](https://github.com/TypeCellOS/BlockNote/pull/1957)) +- Improve setting text for custom file blocks ([#1984](https://github.com/TypeCellOS/BlockNote/pull/1984)) +- **react:** close link popover on submit in static formatting toolbar #1696 ([#1997](https://github.com/TypeCellOS/BlockNote/pull/1997), [#1696](https://github.com/TypeCellOS/BlockNote/issues/1696)) + +### ❤️ Thank You + +- dsriva03 @dsriva03 +- Héctor Zhuang @Hector-Zhuang +- Matthew Lipski @matthewlipski +- Nick the Sick + +## 0.37.0 (2025-08-29) + +### 🚀 Features + +- export `ShadCNComponentsContext` ([#1965](https://github.com/TypeCellOS/BlockNote/pull/1965)) + +### 🩹 Fixes + +- Typing in empty table cells ([#1973](https://github.com/TypeCellOS/BlockNote/pull/1973)) + +### ❤️ Thank You + +- Héctor Zhuang @Hector-Zhuang +- Matthew Lipski @matthewlipski + +## 0.36.1 (2025-08-27) + +### 🩹 Fixes + +- table column widths not being set in exported HTML ([#1947](https://github.com/TypeCellOS/BlockNote/pull/1947)) +- Minor change to formatting toolbar extension logic ([#1963](https://github.com/TypeCellOS/BlockNote/pull/1963)) +- **core:** report block moves in `getBlocksChangedByTransaction` #1924 ([#1960](https://github.com/TypeCellOS/BlockNote/pull/1960), [#1924](https://github.com/TypeCellOS/BlockNote/issues/1924)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez + +## 0.36.0 (2025-08-25) + +### 🚀 Features + +- **docx:** add locale configuration for docx export ([#1937](https://github.com/TypeCellOS/BlockNote/pull/1937)) + +### 🩹 Fixes + +- Editors in comments not inheriting theme ([#1890](https://github.com/TypeCellOS/BlockNote/pull/1890)) +- Minor drag & drop changes ([#1891](https://github.com/TypeCellOS/BlockNote/pull/1891)) +- Overflow on table blocks ([#1892](https://github.com/TypeCellOS/BlockNote/pull/1892)) +- Suggestion menu closing when clicking scroll bar ([#1899](https://github.com/TypeCellOS/BlockNote/pull/1899)) +- Table padding ([#1906](https://github.com/TypeCellOS/BlockNote/pull/1906)) +- Formatting toolbar getting wrong bounding box when updating React inline content ([#1908](https://github.com/TypeCellOS/BlockNote/pull/1908)) +- Vanilla blocks return true for editor.isEditable on initial render ([#1925](https://github.com/TypeCellOS/BlockNote/pull/1925)) +- table cell menu styling ([#1945](https://github.com/TypeCellOS/BlockNote/pull/1945)) +- Missing internationalization for toggle wrapper ([#1946](https://github.com/TypeCellOS/BlockNote/pull/1946)) +- parse image alt text for image blocks ([#1883](https://github.com/TypeCellOS/BlockNote/pull/1883)) +- initialize esm deps before copy extension uses it ([#1951](https://github.com/TypeCellOS/BlockNote/pull/1951)) +- error when dragging a block from one editor to another with multiple column extension ([#1950](https://github.com/TypeCellOS/BlockNote/pull/1950)) +- prevent infinite render loop when selecting all content ([#1956](https://github.com/TypeCellOS/BlockNote/pull/1956)) +- **core:** maintain text selection across table updates ([#1894](https://github.com/TypeCellOS/BlockNote/pull/1894)) +- **locales:** ko locale fix ([#1902](https://github.com/TypeCellOS/BlockNote/pull/1902)) +- **react:** add data attribute for correct react rendering ([#1954](https://github.com/TypeCellOS/BlockNote/pull/1954)) +- **xl-email-exporter:** better defaults, customize textStyles, output inline styles ([#1856](https://github.com/TypeCellOS/BlockNote/pull/1856)) + +### ❤️ Thank You + +- Brad Greenlee +- Cyril G @Ovgodd +- Héctor Zhuang @Hector-Zhuang +- Matthew Lipski @matthewlipski +- Nick Perez +- Nick the Sick + +## 0.35.0 (2025-07-25) + +### 🚀 Features + +- use fumadocs for website ([#1654](https://github.com/TypeCellOS/BlockNote/pull/1654)) +- llms.mdx routes ([cea93840e](https://github.com/TypeCellOS/BlockNote/commit/cea93840e)) + +### 🩹 Fixes + +- insert file upload before block if it is closer to the top of the block ([#1857](https://github.com/TypeCellOS/BlockNote/pull/1857)) +- rename albert model ([3b0ba8d25](https://github.com/TypeCellOS/BlockNote/commit/3b0ba8d25)) +- resolve some minor drag & drop regressions ([#1862](https://github.com/TypeCellOS/BlockNote/pull/1862)) +- blockquote HTML parsing #1762 ([#1877](https://github.com/TypeCellOS/BlockNote/pull/1877), [#1762](https://github.com/TypeCellOS/BlockNote/issues/1762)) + +### ❤️ Thank You + +- Brad Greenlee +- Nick Perez +- Nick the Sick +- yousefed + +## 0.34.0 (2025-07-17) + +### 🚀 Features + +- support multi-column block in PDF, DOCX & ODT exporters ([#1781](https://github.com/TypeCellOS/BlockNote/pull/1781)) +- support react 19 ([f7b3466d3](https://github.com/TypeCellOS/BlockNote/commit/f7b3466d3)) +- disable conversion of headings to list items ([#1799](https://github.com/TypeCellOS/BlockNote/pull/1799)) +- report `moves` (indents and outdents) as changes when using `getChanges` #1757 ([#1786](https://github.com/TypeCellOS/BlockNote/pull/1786), [#1757](https://github.com/TypeCellOS/BlockNote/issues/1757)) +- allow inline content to be `draggable` ([#1818](https://github.com/TypeCellOS/BlockNote/pull/1818)) +- added type guards, types, and `editor` prop to custom inline content rendering ([#1736](https://github.com/TypeCellOS/BlockNote/pull/1736)) +- **block-change:** adds a new API for blocking changes to editor state, by filtering transactions ([#1750](https://github.com/TypeCellOS/BlockNote/pull/1750)) + +### 🩹 Fixes + +- remove lookbehind regex for browser compat ([#1827](https://github.com/TypeCellOS/BlockNote/pull/1827)) +- `ToggleWrapper` button defaulting to `submit` type ([#1823](https://github.com/TypeCellOS/BlockNote/pull/1823)) +- disable $ref in AI schemas (html format) ([#1819](https://github.com/TypeCellOS/BlockNote/pull/1819)) +- re-evaluate side-menu on scroll ([#1830](https://github.com/TypeCellOS/BlockNote/pull/1830)) +- hide table extend buttons when not editable #1848 ([#1850](https://github.com/TypeCellOS/BlockNote/pull/1850), [#1848](https://github.com/TypeCellOS/BlockNote/issues/1848)) +- resolve several drag & drop issues ([#1845](https://github.com/TypeCellOS/BlockNote/pull/1845)) + +### ❤️ Thank You + +- Arek Nawo @areknawo +- Gonçalo Basto @gbasto +- Héctor Zhuang @Hector-Zhuang +- Matthew Lipski @matthewlipski +- Nick Perez +- Nick the Sick @nperez0111 +- Yousef + +## 0.33.0 (2025-07-03) + +### 🚀 Features + +- FloatingUI options prop for `BlockPositioner` ([#1801](https://github.com/TypeCellOS/BlockNote/pull/1801)) +- Support Google Gemini AI ([#1805](https://github.com/TypeCellOS/BlockNote/pull/1805)) + +### 🩹 Fixes + +- support multi-character suggestions ([#1734](https://github.com/TypeCellOS/BlockNote/pull/1734)) +- switch foreground color based on selected user color dynamically #1785 ([#1787](https://github.com/TypeCellOS/BlockNote/pull/1787), [#1785](https://github.com/TypeCellOS/BlockNote/issues/1785)) +- mark react package as external in email exporter ([#1807](https://github.com/TypeCellOS/BlockNote/pull/1807)) +- Duplicate `formatConversionTest` files ([#1798](https://github.com/TypeCellOS/BlockNote/pull/1798)) +- AI empty document handling ([#1810](https://github.com/TypeCellOS/BlockNote/pull/1810)) +- `bn-inline-content` class name getting duplicated ([#1794](https://github.com/TypeCellOS/BlockNote/pull/1794)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez +- Yousef + +## 0.32.0 (2025-06-24) + +### 🚀 Features + +- toggle blocks ([#1707](https://github.com/TypeCellOS/BlockNote/pull/1707)) +- **core:** support h4, h5, and h6 ([#1634](https://github.com/TypeCellOS/BlockNote/pull/1634)) +- **xl-email-exporter:** add email exporter ([#1768](https://github.com/TypeCellOS/BlockNote/pull/1768)) + +### 🩹 Fixes + +- react 19 strict mode compatibility ([#1726](https://github.com/TypeCellOS/BlockNote/pull/1726)) +- add keys to pdf exporter ([#1739](https://github.com/TypeCellOS/BlockNote/pull/1739)) +- only listten for left click on formatting toolbar ([#1774](https://github.com/TypeCellOS/BlockNote/pull/1774)) +- prevent formatting toolbar from closing if click was from inside the editor ([#1775](https://github.com/TypeCellOS/BlockNote/pull/1775)) +- **locales:** add Hebrew translations for various components ([#1779](https://github.com/TypeCellOS/BlockNote/pull/1779)) + +### ❤️ Thank You + +- Aslam @Aslam97 +- Drew Johnson +- Jonathan Marbutt @jmarbutt +- Matthew Lipski @matthewlipski +- Nick Perez +- Samuel Bisberg +- Yousef + +## 0.31.3 (2025-06-18) + +### 🩹 Fixes + +- AI generation with empty document ([#1740](https://github.com/TypeCellOS/BlockNote/pull/1740)) +- do not send a welcome email if magic link was used on an account older than a minute ago ([db88fe4aa](https://github.com/TypeCellOS/BlockNote/commit/db88fe4aa)) +- AI system messages should always be at start of prompt ([#1741](https://github.com/TypeCellOS/BlockNote/pull/1741)) +- Selection clicking editor padding ([#1717](https://github.com/TypeCellOS/BlockNote/pull/1717)) +- preserve marks across a shift+enter #1672 ([#1743](https://github.com/TypeCellOS/BlockNote/pull/1743), [#1672](https://github.com/TypeCellOS/BlockNote/issues/1672)) +- **ai:** undo-redo after accepting/rejecting changes will undo as expected ([#1752](https://github.com/TypeCellOS/BlockNote/pull/1752)) +- **locales:** add translations for some comment strings ([#1764](https://github.com/TypeCellOS/BlockNote/pull/1764)) +- **website:** log in bug fixes ([#1742](https://github.com/TypeCellOS/BlockNote/pull/1742)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez +- Nick the Sick +- Vinicius Fernandes @ViniCleFer +- Yousef + +## 0.31.2 (2025-06-05) + +### 🩹 Fixes + +- re-release ([0bc546e18](https://github.com/TypeCellOS/BlockNote/commit/0bc546e18)) +- ignore falsy values in boolean prop schema ([#1730](https://github.com/TypeCellOS/BlockNote/pull/1730)) + +### ❤️ Thank You + +- Nick Perez +- Nick the Sick + +## 0.31.1 (2025-05-23) + +### 🩹 Fixes + +- backwards-compat for `_extensions` ([#1708](https://github.com/TypeCellOS/BlockNote/pull/1708)) + +### ❤️ Thank You + +- Nick Perez + +## 0.31.0 (2025-05-20) + +### 🩹 Fixes + +- Playwright flaky keyboard handler test ([#1704](https://github.com/TypeCellOS/BlockNote/pull/1704)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski + +## 0.30.1 (2025-05-20) + +### 🩹 Fixes + +- better type-safety ([678086d4d](https://github.com/TypeCellOS/BlockNote/commit/678086d4d)) +- do not use `editor.dispatch` ([#1698](https://github.com/TypeCellOS/BlockNote/pull/1698)) +- re-added `display: flex` to blocks without inline content ([#1702](https://github.com/TypeCellOS/BlockNote/pull/1702)) +- **react:** add missing exports ([#1689](https://github.com/TypeCellOS/BlockNote/pull/1689)) + +### ❤️ Thank You + +- Matthew Lipski @matthewlipski +- Nick Perez +- Nick the Sick + +## 0.30.0 (2025-05-09) + +### 🚀 Features + +- expose `editor.prosemirrorState` again ([#1615](https://github.com/TypeCellOS/BlockNote/pull/1615)) +- add `undo` and `redo` methods to editor API ([#1592](https://github.com/TypeCellOS/BlockNote/pull/1592)) +- new auth & payment system ([#1617](https://github.com/TypeCellOS/BlockNote/pull/1617)) +- re-implement Y.js collaboration as BlockNote plugins ([#1638](https://github.com/TypeCellOS/BlockNote/pull/1638)) +- **file:** `previewWidth` prop now defaults to `undefined` ([#1664](https://github.com/TypeCellOS/BlockNote/pull/1664)) +- **locales:** add zh-TW i18n ([#1668](https://github.com/TypeCellOS/BlockNote/pull/1668)) + +### 🩹 Fixes + +- Formatting toolbar regression ([#1630](https://github.com/TypeCellOS/BlockNote/pull/1630)) +- provide `blockId` to `uploadFile` in UploadTab ([#1641](https://github.com/TypeCellOS/BlockNote/pull/1641)) +- do not close the menu on content/selection change ([#1644](https://github.com/TypeCellOS/BlockNote/pull/1644)) +- keep file panel open during collaboration ([#1646](https://github.com/TypeCellOS/BlockNote/pull/1646)) +- force pasting plain text into code block ([#1663](https://github.com/TypeCellOS/BlockNote/pull/1663)) +- updating HTML parsing rules to account for `prosemirror-model@1.25.1` ([#1661](https://github.com/TypeCellOS/BlockNote/pull/1661)) +- **code-block:** handle unknown languages better ([#1626](https://github.com/TypeCellOS/BlockNote/pull/1626)) +- **locales:** add slovak i18n ([#1649](https://github.com/TypeCellOS/BlockNote/pull/1649)) + +### ❤️ Thank You + +- l0st0 @l0st0 +- Lawrence Lin @linyiru +- Matthew Lipski @matthewlipski +- Nick Perez +- Quentin Nativel + +## 0.29.1 (2025-04-17) + +### 🩹 Fixes + +- try not to always use workspace version ([7af344ea9](https://github.com/TypeCellOS/BlockNote/commit/7af344ea9)) + +### ❤️ Thank You + +- Nick the Sick + +## 0.29.0 (2025-04-17) + +### 🚀 Features + +- `change` event allows getting a list of the block changed ([#1585](https://github.com/TypeCellOS/BlockNote/pull/1585)) + +### 🩹 Fixes + +- allow opening another suggestion menu if another is triggered #1473 ([#1591](https://github.com/TypeCellOS/BlockNote/pull/1591), [#1473](https://github.com/TypeCellOS/BlockNote/issues/1473)) +- add quote to schema ([aa16b15fe](https://github.com/TypeCellOS/BlockNote/commit/aa16b15fe)) +- update y-prosemirror to fix #1462 ([#1608](https://github.com/TypeCellOS/BlockNote/pull/1608), [#1462](https://github.com/TypeCellOS/BlockNote/issues/1462)) +- dispatch suggestion menu as a separate transaction ([#1614](https://github.com/TypeCellOS/BlockNote/pull/1614)) + +### ❤️ Thank You + +- Nick Perez +- Nick the Sick + +## 0.28.0 (2025-04-07) + +### 🚀 Features + +- position storage ([#1529](https://github.com/TypeCellOS/BlockNote/pull/1529)) + +### ❤️ Thank You + +- Nick Perez + +## 0.27.2 (2025-04-05) + +### 🩹 Fixes + +- minor update for publishing ([c2820fdac](https://github.com/TypeCellOS/BlockNote/commit/c2820fdac)) + +### ❤️ Thank You + +- Nick the Sick + +## 0.27.1 (2025-04-05) + +### 🚀 Features + +- **nx-cloud:** set up nx workspace ([#1586](https://github.com/TypeCellOS/BlockNote/pull/1586)) + +### 🩹 Fixes + +- update packages to use correct react versions ([ea11ebce0](https://github.com/TypeCellOS/BlockNote/commit/ea11ebce0)) + +### ❤️ Thank You + +- Nick Perez +- Nick the Sick + +## 0.27.0 (2025-04-04) + +### 🚀 Features + +- split out localization files for optimized bundle ([#1533](https://github.com/TypeCellOS/BlockNote/pull/1533)) +- remove shiki dep, add new @blocknote/code-block package for slim shiki build ([#1519](https://github.com/TypeCellOS/BlockNote/pull/1519)) +- Block quote ([#1563](https://github.com/TypeCellOS/BlockNote/pull/1563)) +- markdown pasting & custom paste handlers ([#1490](https://github.com/TypeCellOS/BlockNote/pull/1490)) + +### 🩹 Fixes + +- Backspace in empty block deletes previous block ([#1505](https://github.com/TypeCellOS/BlockNote/pull/1505)) +- Selection when clicking past end of inline content ([#1553](https://github.com/TypeCellOS/BlockNote/pull/1553)) +- better expose setting a draghandlemenu's items #1525 ([#1526](https://github.com/TypeCellOS/BlockNote/pull/1526), [#1525](https://github.com/TypeCellOS/BlockNote/issues/1525)) +- Multi-block links ([#1565](https://github.com/TypeCellOS/BlockNote/pull/1565)) +- Hard break keyboard shortcut not working in custom blocks ([#1554](https://github.com/TypeCellOS/BlockNote/pull/1554)) +- Overlapping marks in comments ([#1564](https://github.com/TypeCellOS/BlockNote/pull/1564)) +- some more sentry fixes ([#1577](https://github.com/TypeCellOS/BlockNote/pull/1577)) + +### ❤️ Thank You + +- Martinrsts @Martinrsts +- Matthew Lipski @matthewlipski +- Nick Perez + +## Previous Versions + +See [Github Releases](https://github.com/TypeCellOS/BlockNote/releases) for previous versions. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac57b6f132..8fe42686f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,29 +3,85 @@ Directory structure: ``` -blocknote -├── packages/core - The core of the editor -├── packages/react - The main library for use in React apps -├── examples/editor - Example React app that embeds the editor -├── examples/vanilla - An advanced example if you don't want to use React or want to build your own UI components -└── tests - Playwright end to end tests +BlockNote +├── packages/core - The core of the editor, which includes all logic to get the editor running in vanilla JS. +├── packages/react - A React wrapper and UI for the editor. Requires additional components for the UI. +├── packages/ariakit - UI components for the `react` package, made with Ariakit. +├── packages/mantine - UI components for the `react` package, made with Mantine. +├── packages/shadcn - UI components for the `react` package, made with Shadcn. +├── packages/server-util - Utilities for converting BlockNote documents into static HTML for server-side rendering. +├── packages/dev-scripts - A set of tools for converting example editor setups into components for the BlockNote website. +├── examples - Example editor setups used for demos in the BlockNote website and playground. +├── docs - Code for the BlockNote website. +├── playground - A basic page where you can quickly test each of the example editor setups. +└── tests - Playwright end to end tests. ``` -An introduction into the BlockNote Prosemirror schema can be found in [packages/core/ARCHITECTURE.md](https://github.com/TypeCellOS/BlockNote/blob/main/packages/core/ARCHITECTURE.md). +An introduction into the BlockNote Prosemirror schema can be found in [packages/core/src/pm-nodes/README.md](https://github.com/TypeCellOS/BlockNote/blob/main/packages/core/src/pm-nodes/README.md). ## Running To run the project, open the command line in the project's root directory and enter the following commands: - # Install all required npm modules for lerna, and bootstrap lerna packages - npm install - npm run bootstrap +```bash +# Install all required npm modules +pnpm install - # Start the example project - npm start +# Start the example project +pnpm start +``` ## Adding packages - Add the dependency to the relevant `package.json` file (packages/xxx/package.json) -- run `npm run install-new-packages` -- Double check `package-lock.json` to make sure only the relevant packages have been affected +- Double check `pnpm-lock.yaml` to make sure only the relevant packages have been affected + +## Packages + +| Package | Size | Version | +| ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| [@blocknote/core](https://github.com/TypeCellOS/BlockNote/tree/main/packages/core) | | | +| [@blocknote/react](https://github.com/TypeCellOS/BlockNote/tree/main/packages/react) | | | +| [@blocknote/ariakit](https://github.com/TypeCellOS/BlockNote/tree/main/packages/ariakit) | | | +| [@blocknote/mantine](https://github.com/TypeCellOS/BlockNote/tree/main/packages/mantine) | | | +| [@blocknote/shadcn](https://github.com/TypeCellOS/BlockNote/tree/main/packages/shadcn) | | | +| [@blocknote/server-util](https://github.com/TypeCellOS/BlockNote/tree/main/packages/server-util) | | | + +## Releasing + +This diagram illustrates the release workflow for the BlockNote monorepo. + +![Release Workflow](./.resources/release-workflow.excalidraw.svg) + +Essentially, when the maintainers have decided to release a new version of BlockNote, they will: + + 1. Check that the `main` branch is in a releasable state: + - CI status of main branch is green + - Builds are passing + 2. Bump the package versions using the `pnpm run deploy` command. This command will: + 1. Based on semantic versioning, determine the next version number. + 2. Apply the new version number to all publishable packages within the monorepo. + 3. Generate a changelog for the new version. + 4. Commit the changes to the `main` branch. + 5. Create a new git tag for the new version. + 6. Push the changes to the `origin` remote. + 7. Create a new GitHub Release with the same name as the new version. + 8. Trigger a release workflow. + +The release workflow will: + +1. Checkout the `main` branch. +2. Install the dependencies. +3. Build the project. +4. Login to npm. +5. Publish the packages to npm. + +### Publishing a new package + +From time to time, you may need to publish a new package to npm. To do this, you cannot just deploy the package to npm, you need to: + + 1. Run `nx release version --dry-run` and check that the version number is correct for the package. + - Once this is done, you can run `nx release version` to actually apply the version bump locally (staged to your local git repo). + 2. Run `nx release changelog --from --dry-run` and check that the changelog is correct for the package. + - Once this is done, you can run the same command without the `--dry-run` flag to actually apply the changelog, commit & push the changes to the `main` branch. + 3. The release workflow will automatically publish the package to npm. diff --git a/LICENSE b/LICENSE deleted file mode 100644 index a612ad9813..0000000000 --- a/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..35a742ce7e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,5 @@ +BlockNote is 100% Open Source Software. + +Source code in this repository is covered by the "Mozilla Public License Version 2.0" (MPL-2.0) license, except for the XL packages. The MPL-2.0 license allows you to use BlockNote in commercial (and closed-source) applications. If you make changes to the BlockNote source files, you're expected to publish these changes so the wider community can benefit as well. + +The XL packages (source code in the `packages/xl-*` directories and published in NPM as `@blocknote/xl-*`) are licensed under the "GNU General Public License Version 3" (GPL-3.0). Additionally, a commercial license is available. See our website (https://www.blocknotejs.org/pricing) for more information and the commercial license terms. \ No newline at end of file diff --git a/README.md b/README.md index 195917fd6b..f391efb3f3 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,42 @@

- TypeCell + TypeCell

Welcome to BlockNote! The open source Block-Based -rich text editor. Easily add a modern text editing experience to your app. -

- -

-Discord Matrix +React rich text editor. Easily add a modern text editing experience to your app.

Homepage - - - Introduction - - + - Documentation + - + Quickstart + - + Examples

# Live demo -Play with the editor @ [https://blocknote-main.vercel.app/](https://blocknote-main.vercel.app/). - -(Source in [examples/editor](/examples/editor)) +See our homepage @ [https://www.blocknotejs.org](https://www.blocknotejs.org/) or browse the [examples](https://www.blocknotejs.org/examples). # Example code (React) [![npm version](https://badge.fury.io/js/%40blocknote%2Freact.svg)](https://badge.fury.io/js/%40blocknote%2Freact) ```typescript -import { BlockNoteView, useBlockNote } from "@blocknote/react"; -import "@blocknote/core/style.css"; +import { useCreateBlockNote } from "@blocknote/react"; +import { BlockNoteView } from "@blocknote/mantine"; +import "@blocknote/core/fonts/inter.css"; +import "@blocknote/mantine/style.css"; function App() { - const editor = useBlockNote({ - onEditorContentChange: (editor) => { - // Log the document to console on every update - console.log(editor.getJSON()); - }, - }); + const editor = useCreateBlockNote(); return ; } @@ -51,8 +44,6 @@ function App() { `@blocknote/react` comes with a fully styled UI that makes it an instant, polished editor ready to use in your app. -If you prefer to create your own UI components (menus), or don't want to use React, you can use `@blocknote/core` (_advanced_, [see docs](https://www.blocknotejs.org/docs/vanilla-js)). - # Features BlockNote comes with a number of features and components to make it easy to embed a high-quality block-based editor in your app: @@ -87,24 +78,19 @@ BlockNote comes with a number of features and components to make it easy to embe # Feedback 🙋‍♂️🙋‍♀️ -We'd love to hear your thoughts and see your experiments, so [come and say hi on Discord](https://discord.gg/Qc2QTTH5dF) or [Matrix](https://matrix.to/#/#typecell-space:matrix.org). +We'd love to hear your thoughts and see your experiments, so [come and say hi on Discord](https://discord.gg/Qc2QTTH5dF). # Contributing 🙌 -See [CONTRIBUTING.md](CONTRIBUTING.md) for more info and guidance on how to run the project (TLDR: just use `npm start`). +See [CONTRIBUTING.md](CONTRIBUTING.md) for more info and guidance on how to run the project (TLDR: just use `pnpm start`). -Directory structure: +The codebase is automatically tested using Vitest and Playwright. -``` -blocknote -├── packages/core - The core of the editor -├── packages/react - The main library for use in React apps -├── examples/editor - Example React app that embeds the editor -├── examples/vanilla - An advanced example if you don't want to use React or want to build your own UI components -└── tests - Playwright end to end tests -``` +# License 📃 -The codebase is automatically tested using Vitest and Playwright. +BlockNote is 100% Open Source Software. The majority of BlockNote is licensed under the [MPL-2.0 license](LICENSE-MPL.txt), which allows you to use BlockNote in commercial (and closed-source) applications. If you make changes to the BlockNote source files, you're expected to publish these changes so the wider community can benefit as well. [Learn more](https://fossa.com/blog/open-source-software-licenses-101-mozilla-public-license-2-0/). + +The XL packages (source code in the `packages/xl-*` directories and published in NPM as `@blocknote/xl-*`) are licensed under the GPL-3.0. If you cannot comply with this license and want to use the XL libraries, you'll need a commercial license. Refer to [our website](https://www.blocknotejs.org/pricing) for more information. # Credits ❤️ @@ -117,3 +103,5 @@ BlockNote is built as part of [TypeCell](https://www.typecell.org). TypeCell is Hosting and deployments powered by Vercel: NLNet + +This project is tested with BrowserStack diff --git a/docs/.env.local.example b/docs/.env.local.example new file mode 100644 index 0000000000..a2dba36b4b --- /dev/null +++ b/docs/.env.local.example @@ -0,0 +1,35 @@ +AUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.vercel.app/32 + +# Better Auth Deployed URL +BETTER_AUTH_URL=http://localhost:3000 + +# ======= OPTIONAL ======= + +# # Polar Sandbox is used in dev mode: https://sandbox.polar.sh/ +# # You may need to delete your user in their dashboard if you get a "cannot attach new external ID error" +# POLAR_ACCESS_TOKEN= +# POLAR_WEBHOOK_SECRET= + +# # In production, we use postgres +# POSTGRES_URL= + +# # Email +# SMTP_HOST= +# SMTP_USER= +# SMTP_PASS= +# SMTP_PORT= +# # Insecure if false, secure if any other value +# SMTP_SECURE=false + +# # For GitHub Signin method +# AUTH_GITHUB_ID= +# AUTH_GITHUB_SECRET= + +# # The SENTRY_AUTH_TOKEN variable is picked up by the Sentry Build Plugin. +# # It's used for authentication when uploading source maps. +# SENTRY_AUTH_TOKEN= + +NEXT_PUBLIC_BLOCKNOTE_AI_SERVER_API_KEY= +NEXT_PUBLIC_BLOCKNOTE_AI_SERVER_BASE_URL= + +TURNSTILE_SECRET_KEY= \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000..c12953bff8 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,32 @@ +# deps +/node_modules + +# generated content +.source + +# test & build +/coverage +/.next/ +/out/ +/build +*.tsbuildinfo + +# misc +.DS_Store +*.pem +/.pnp +.pnp.js +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# others +.env*.local +.vercel +next-env.d.ts +# Sentry Config File +.env.sentry-build-plugin + +/content/examples/*/* +/components/example/generated/ +sqlite.db diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..b8e4860113 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,105 @@ +# Website Development + +This is the code for the [BlockNote documentation website](https://www.blocknotejs.org). If you're looking to work on BlockNote itself, check the [`packages`](/packages/) folder. + +To get started with development of the website, you can follow these steps: + +1. Initialize the DB + +If you haven't already, you can initialize the database with the following command: + +```bash +cd docs && pnpm run init-db +``` + +This will initialize an SQLite database at `./docs/sqlite.db`. + +2. Setup environment variables + +Copy the `.env.example` file to `.env.local` and set the environment variables. + +```bash +cp .env.example .env.local +``` + +If you want to test logging in, or payments see more information below [in the environment variables section](#environment-variables). + +3. Start the development server from within the `./docs` directory. + +```bash +pnpm run dev +``` + +This will start the development server on port 3000. + +## Environment Variables + +### Logging in + +To test logging in, you can set the following environment variables: + +```bash +AUTH_SECRET=test +# Github OAuth optionally +AUTH_GITHUB_ID=test +AUTH_GITHUB_SECRET=test +``` + +Note: the GITHUB_ID and GITHUB_SECRET are optional, but if you want to test logging in with Github you'll need to set them. For local development, you'll need to set the callback URL to `http://localhost:3000/api/auth/callback/github` + +### Payments + +To test payments, you can set the following environment variables: + +```bash +POLAR_ACCESS_TOKEN=test +POLAR_WEBHOOK_SECRET=test +``` + +For testing payments, you'll need access to the polar sandbox which needs to be configured to point a webhook to your local server. This can be configured at: + +You'll need something like [ngrok](https://ngrok.com/) to expose your local server to the internet. + +```bash +ngrok http http://localhost:3000 +``` + +You'll need the webhook to point to ngrok like so: + +``` +https://0000-00-00-000-00.ngrok-free.app/api/auth/polar/webhooks +``` + +With this webhook pointing to your local server, you should be able to test payments. + +### Email sending + +Note, this is not required, if email sending is not configured, the app will log the email it would send to the console. Often this is more convenient for development. + +To test email sending, you can set the following environment variables: + +```bash +SMTP_HOST= +SMTP_USER= +SMTP_PASS= +SMTP_PORT= +SMTP_SECURE=false +``` + +When configured, you'll be able to send emails to the email address you've configured. + +To setup with protonmail, you'll need to go to and create a new SMTP submission token. + +You'll need to set the following environment variables: + +```bash +SMTP_HOST=smtp.protonmail.com +SMTP_USER=my.email@protonmail.com +SMTP_PASS=my-smtp-token +SMTP_PORT=587 +SMTP_SECURE=false +``` + +# Contributing + +To submit your changes, open a pull request to the [BlockNote GitHub repo](https://github.com/TypeCellOS/BlockNote). Pull requests will automatically be deployed to a preview environment. diff --git a/docs/app/(auth)/layout.tsx b/docs/app/(auth)/layout.tsx new file mode 100644 index 0000000000..715e32a774 --- /dev/null +++ b/docs/app/(auth)/layout.tsx @@ -0,0 +1,10 @@ +import { HomeLayout } from "@/components/fumadocs/layout/home"; +import { baseOptions } from "@/lib/layout.shared"; + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + +
{children}
+
+ ); +} diff --git a/docs/app/(auth)/signin/page.tsx b/docs/app/(auth)/signin/page.tsx new file mode 100644 index 0000000000..b21d007847 --- /dev/null +++ b/docs/app/(auth)/signin/page.tsx @@ -0,0 +1,18 @@ +import AuthenticationPage from "@/components/AuthenticationPage"; +import { getFullMetadata } from "@/lib/getFullMetadata"; +import { Suspense } from "react"; + +export const metadata = getFullMetadata({ + title: "Sign In", + path: "/signin", +}); + +// Suspense + imported AuthenticationPage because AuthenticationPage is a client component +// https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering +export default function Page() { + return ( + + + + ); +} diff --git a/docs/app/(auth)/signin/password/page.tsx b/docs/app/(auth)/signin/password/page.tsx new file mode 100644 index 0000000000..d998c4db48 --- /dev/null +++ b/docs/app/(auth)/signin/password/page.tsx @@ -0,0 +1,17 @@ +import AuthenticationPage from "@/components/AuthenticationPage"; +import { Metadata } from "next"; +import { Suspense } from "react"; + +export const metadata: Metadata = { + title: "Password Login", +}; + +// Suspense + imported AuthenticationPage because AuthenticationPage is a client component +// https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering +export default function Page() { + return ( + + + + ); +} diff --git a/docs/app/(auth)/signup/page.tsx b/docs/app/(auth)/signup/page.tsx new file mode 100644 index 0000000000..04aceaa07a --- /dev/null +++ b/docs/app/(auth)/signup/page.tsx @@ -0,0 +1,18 @@ +import AuthenticationPage from "@/components/AuthenticationPage"; +import { getFullMetadata } from "@/lib/getFullMetadata"; +import { Suspense } from "react"; + +export const metadata = getFullMetadata({ + title: "Sign Up", + path: "/signup", +}); + +// Suspense + imported AuthenticationPage because AuthenticationPage is a client component +// https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering +export default function Page() { + return ( + + + + ); +} diff --git a/docs/app/(home)/_components/BlockCatalog.tsx b/docs/app/(home)/_components/BlockCatalog.tsx new file mode 100644 index 0000000000..72804ec79e --- /dev/null +++ b/docs/app/(home)/_components/BlockCatalog.tsx @@ -0,0 +1,108 @@ +"use client"; +import { + AudioWaveform, + ChevronRight, + Code2, + FileText, + Heading, + Image, + List, + ListOrdered, + ListTodo, + Minus, + Pilcrow, + Puzzle, + Quote, + Table, + Video, +} from "lucide-react"; +import React from "react"; + +const BlockCatalogItem: React.FC<{ name: string; icon: React.ReactNode }> = ({ + name, + icon, +}) => ( +
+
+
+ {icon} +
+ + {name} + +
+); + +export const BlockCatalog: React.FC = () => { + return ( +
+ {/* Subtle decorative elements */} +
+
+
+
+
+ +
+
+
+ 🧩 +
+

+ Build anything, block by block. +

+

+ Every BlockNote document is a collection of blocks—headings, lists, + images, and more. Use the built-in blocks, customize them to fit + your needs, or create entirely new ones. +

+
+ +
+ } + /> + } + /> + } /> + } + /> + } + /> + } + /> + } /> + } /> + } + /> + } /> + } /> + } /> + } + /> + } + /> + } + /> +
+
+
+ ); +}; diff --git a/docs/app/(home)/_components/DigitalCommons.tsx b/docs/app/(home)/_components/DigitalCommons.tsx new file mode 100644 index 0000000000..c4cc4e941e --- /dev/null +++ b/docs/app/(home)/_components/DigitalCommons.tsx @@ -0,0 +1,127 @@ +"use client"; +import Link from "next/link"; +import React, { useRef, useState } from "react"; + +export const DigitalCommons: React.FC = () => { + const videoRef = useRef(null); + const [isPlaying, setIsPlaying] = useState(false); + + const handlePlayPause = () => { + if (videoRef.current) { + if (isPlaying) { + videoRef.current.pause(); + } else { + videoRef.current.play(); + } + setIsPlaying(!isPlaying); + } + }; + + return ( +
+ {/* Warm gradient overlay to harmonize with cream hero */} +
+ {/* Top edge gradient for smoother transition */} +
+ +
+ {/* Asymmetric layout: content + video (vertically centered) */} +
+ {/* Left: Editorial content */} +
+ {/* Eyebrow with EU flag only */} +
+ 🇪🇺 + + Digital Commons + +
+ + {/* Headline - editorial style */} +

+ Three nations choose
+ + open source + {" "} + to power +
+ their digital future. +

+ + {/* Short punchy copy */} +

+ France, Germany, and the Netherlands partner to build{" "} + + Docs + + , a collaborative writing tool for thousands of public servants.{" "} + BlockNote is the engine. +

+ + {/* Compelling social proof - simpler */} +

+ "Building Digital Commons means better tools, data + sovereignty, and shared progress." +

+ + {/* CTA */} + + Partner with us + + +
+ + {/* Right: Video - vertically centered */} +
+ {/* Glow effect */} +
+ +
+ + + {/* Play button overlay */} + {!isPlaying && ( + + )} +
+
+
+
+
+ ); +}; diff --git a/docs/app/(home)/_components/FAQ.tsx b/docs/app/(home)/_components/FAQ.tsx new file mode 100644 index 0000000000..158c5c691a --- /dev/null +++ b/docs/app/(home)/_components/FAQ.tsx @@ -0,0 +1,51 @@ +import React from "react"; + +const faqs = [ + { + question: "Isn't it easier to use a Headless editor framework?", + answer: + "There are a number of really powerful headless text editor frameworks available. In fact, BlockNote is built on Prosemirror and TipTap. However, even when using a headless library, it takes several months and requires deep expertise to build a fully-featured editor with a polished UI that your users expect.", + }, + { + question: "Is BlockNote ready for production use?", + answer: + "BlockNote is used by dozens of companies in production, ranging from startups to large enterprises and public institutions. Also, we didn't reinvent the wheel. The core editor is built on top of Prosemirror - a battle tested framework that powers software from Atlassian, Gitlab, the New York Times, and many others.", + }, + { + question: "Can I add my own extensions to BlockNote?", + answer: + "BlockNote comes with lot of functionality out-of-the-box, but we understand that every use case is different. You can easily customize the built-in UI Components, or create your own custom Blocks, Inline Content, and Styles. If you want to go even further, you can extend the core editor with additional Prosemirror or TipTap plugins.", + }, + { + question: "Is BlockNote really free?", + answer: + "100% of BlockNote is open source. We offer consultancy, support services and commercial licenses for specific XL packages to help sustain BlockNote. Explore our pricing page for more details.", + }, +]; + +export const FAQ: React.FC = () => { + return ( +
+
+
+

+ Questions? +

+
+ +
+ {faqs.map((faq, index) => ( +
+

+ {faq.question} +

+

+ {faq.answer} +

+
+ ))} +
+
+
+ ); +}; diff --git a/docs/app/(home)/_components/FeatureAI.tsx b/docs/app/(home)/_components/FeatureAI.tsx new file mode 100644 index 0000000000..6f87e80e6b --- /dev/null +++ b/docs/app/(home)/_components/FeatureAI.tsx @@ -0,0 +1,63 @@ +"use client"; +import React, { useState } from "react"; +import { FeatureSection } from "./FeatureSection"; +import { ContentItem, FeatureWindow } from "./ui/FeatureWindow"; + +export const FeatureAI: React.FC = () => { + const [activeTab, setActiveTab] = useState<"toolbar" | "models" | "human">( + "toolbar", + ); + + const content: Record = { + toolbar: { + type: "video", + src: "/video/ai-select.mp4", + className: "px-4", + }, + models: { + type: "image", + src: "/img/screenshots/home/any_model.png", + alt: "Bring Any Model", + }, + human: { + type: "image", + src: "/img/screenshots/home/human_in_the_loop.png", + alt: "Human in the Loop", + }, + }; + + const tabs = [ + { + id: "toolbar", + icon: , + label: "AI in the Editor", + description: + "Context-aware completions and edits directly in the document.", + }, + { + id: "models", + icon: 🔌, + label: "Bring Any Model", + description: "Connect OpenAI, Anthropic, or your own endpoints.", + }, + { + id: "human", + icon: 🤝, + label: "Human in the Loop", + description: "Users accept, reject, or refine AI suggestions.", + }, + ]; + + return ( + setActiveTab(id as any)} + reverse={true} + > + + + ); +}; diff --git a/docs/app/(home)/_components/FeatureCollab.tsx b/docs/app/(home)/_components/FeatureCollab.tsx new file mode 100644 index 0000000000..3553d8255f --- /dev/null +++ b/docs/app/(home)/_components/FeatureCollab.tsx @@ -0,0 +1,65 @@ +"use client"; +import React, { useState } from "react"; +import { FeatureSection } from "./FeatureSection"; +import { ContentItem, FeatureWindow } from "./ui/FeatureWindow"; + +export const FeatureCollab: React.FC<{ + code: { realtime: string }; +}> = ({ code }) => { + const [activeTab, setActiveTab] = useState< + "realtime" | "comments" | "suggestions" + >("realtime"); + + const content: Record = { + realtime: { + type: "code", + file: "CollaborativeEditor.tsx", + code: code.realtime, + }, + comments: { + type: "image", + src: "/img/screenshots/home/comments.png", + alt: "Comments", + }, + suggestions: { + type: "image", + src: "/img/screenshots/home/versioning.png", + alt: "Versioning", + }, + }; + + const tabs = [ + { + id: "realtime", + icon: 👯, + label: "Real-Time Sync", + description: "Yjs-powered with automatic conflict resolution.", + }, + { + id: "comments", + icon: 💬, + label: "Comments", + description: "Inline threads and mentions keep conversations in context.", + }, + { + id: "suggestions", + icon: 📝, + label: "Suggestions & Versioning (coming soon)", + description: + "Track changes, accept or reject edits. Full document history.", + }, + ]; + + return ( + setActiveTab(id as any)} + reverse={false} + > + + + ); +}; diff --git a/docs/app/(home)/_components/FeatureDX.tsx b/docs/app/(home)/_components/FeatureDX.tsx new file mode 100644 index 0000000000..a98353e0e1 --- /dev/null +++ b/docs/app/(home)/_components/FeatureDX.tsx @@ -0,0 +1,64 @@ +"use client"; +import React, { useState } from "react"; +import { FeatureSection } from "./FeatureSection"; +import { ContentItem, FeatureWindow } from "./ui/FeatureWindow"; + +export const FeatureDX: React.FC<{ + code: { theming: string; extend: string }; +}> = ({ code }) => { + const [activeTab, setActiveTab] = useState<"types" | "theming" | "extend">( + "types", + ); + + const content: Record = { + types: { + type: "image", + src: "/img/screenshots/home/code-typescript-support.png", + alt: "Type-Safe Schema", + }, + theming: { + type: "code", + file: "Editor.tsx", + code: code.theming, + }, + extend: { + type: "code", + file: "CustomBlock.tsx", + code: code.extend, + }, + }; + + const tabs = [ + { + id: "types", + icon: 📐, + label: "Type-Safe", + description: "Full autocompletion and type inference for custom schemas.", + }, + { + id: "theming", + icon: 🎨, + label: "Bring your Design System", + description: "Works with Mantine, shadcn/ui, or go headless.", + }, + { + id: "extend", + icon: 🔧, + label: "Extend Everything", + description: "Create custom blocks, inline content, menus and more.", + }, + ]; + + return ( + setActiveTab(id as any)} + reverse={true} + > + + + ); +}; diff --git a/docs/app/(home)/_components/FeatureSection.tsx b/docs/app/(home)/_components/FeatureSection.tsx new file mode 100644 index 0000000000..ef2c62eea1 --- /dev/null +++ b/docs/app/(home)/_components/FeatureSection.tsx @@ -0,0 +1,101 @@ +import React from "react"; + +interface FeatureTab { + id: string; + icon: React.ReactNode; + label: string; + description: string; +} + +interface FeatureSectionProps { + title: string; + description: string; + tabs: FeatureTab[]; + activeTabId: string; + onTabChange: (id: string) => void; + // The content to display on the right side (Visual or Code) + children: React.ReactNode; + // Optional: Swap order for visual variety (Left/Right) + reverse?: boolean; +} + +export const FeatureSection: React.FC = ({ + title, + description, + tabs, + activeTabId, + onTabChange, + children, + reverse = false, +}) => { + return ( +
+ {/* Left Text & Tabs */} +
+

+ {title} +

+

+ {description} +

+ +
+ {tabs.map((tab) => { + const isActive = activeTabId === tab.id; + // Dynamic styles based on active state could be passed or handled here + // For simplicity, we'll use a generic active style or specific color logic if needed. + // But CodePlayground had specific colors (purple, amber, blue). + // Let's rely on the parent or use a generic active style here for now, + // or we can add a 'color' prop to FeatureTab if we want distinct colors per tab. + + return ( + + ); + })} +
+
+ + {/* Right Visual */} +
+ {/*
*/} +
+ {children} +
+
+
+ ); +}; diff --git a/docs/app/(home)/_components/FeatureUX.tsx b/docs/app/(home)/_components/FeatureUX.tsx new file mode 100644 index 0000000000..3bfe2d00ff --- /dev/null +++ b/docs/app/(home)/_components/FeatureUX.tsx @@ -0,0 +1,60 @@ +"use client"; +import React, { useState } from "react"; +import { FeatureSection } from "./FeatureSection"; +import { ContentItem, FeatureWindow } from "./ui/FeatureWindow"; +export const FeatureUX: React.FC = () => { + const [activeTab, setActiveTab] = useState<"components" | "ai" | "blocks">( + "components", + ); + + const content: Record = { + components: { + type: "video", + src: "/video/batteries-included.mp4", + }, + ai: { + type: "video", + src: "/video/ai-select.mp4", + className: "px-4", + }, + blocks: { + type: "video", + src: "/video/dragdrop.mp4", + }, + }; + + const tabs = [ + { + id: "components", + icon: 🔋, + label: "Ready to Use", + description: + "Slash menus, formatting toolbars, and drag handles work instantly.", + }, + { + id: "ai", + icon: , + label: "AI Assistance", + description: "Write and redact content with AI.", + }, + { + id: "blocks", + icon: 🧱, + label: "Block-Based", + description: "Drag, drop, and nest content blocks.", + }, + ]; + + return ( + setActiveTab(id as any)} + reverse={false} + > + + + ); +}; diff --git a/docs/app/(home)/_components/FrameworkPill.tsx b/docs/app/(home)/_components/FrameworkPill.tsx new file mode 100644 index 0000000000..eef63da2ba --- /dev/null +++ b/docs/app/(home)/_components/FrameworkPill.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +export const FrameworkPill: React.FC<{ + name: string; + color: string; + icon?: React.ReactNode; +}> = ({ name, color, icon }) => ( +
+ {icon ||
} + {name} +
+); diff --git a/docs/app/(home)/_components/Hero.tsx b/docs/app/(home)/_components/Hero.tsx new file mode 100644 index 0000000000..4e383ce2f3 --- /dev/null +++ b/docs/app/(home)/_components/Hero.tsx @@ -0,0 +1,69 @@ +import Link from "next/link"; +import React from "react"; +import { HeroVideo } from "./HeroVideo"; +import { TextLoop } from "./TextLoop"; + +export const Hero: React.FC = () => { + const BADGES = [ + { icon: "⭐️", text: "100k+ weekly installs" }, + { icon: "🛡️", text: "100% Open source & self-hostable" }, + { icon: "✨", text: "AI Ready" }, + ]; + + return ( +
+ {/* Hero Section */} +
+ {/* Passive Neural Background */} +
+ {/* Badge */} + + {BADGES.map((badge, index) => ( +
+ + {badge.icon} + {badge.text} + +
+ ))} +
+ +

+ Build a Notion-style{" "} + editor in minutes. +

+

+ The AI-native, open source rich + text editor for React. Add a{" "} + fully customizable modern block-based editing + experience to your product that users will love. +

+ +
+ + View Demo + + → + + + + Documentation + +
+
+
+ +
+
+
+ ); +}; diff --git a/docs/app/(home)/_components/HeroVideo.tsx b/docs/app/(home)/_components/HeroVideo.tsx new file mode 100644 index 0000000000..a36cccbe73 --- /dev/null +++ b/docs/app/(home)/_components/HeroVideo.tsx @@ -0,0 +1,77 @@ +"use client"; +import Link from "next/link"; +import React from "react"; + +export const HeroVideo: React.FC = () => { + return ( + <> + +
+ {/* Editor Placeholder */} + {/* Editor Preview */} + +
+
+ {/* Browser Chrome */} +