Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions .github/workflows/node.js.yml

This file was deleted.

17 changes: 11 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ jobs:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5

- name: Node setup
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
node-version: "18.20.8"
cache-dependency-path: package.json
node-version: "20.x"
cache: "npm"

- run: |
- name: Install and build
run: |
npm i
npm run typecheck
npm run build
- name: Publish package for testing branch
run: npx pkg-pr-new publish || echo "Have you set up pkg-pr-new for this repo?"
- name: Test
run: |
npm run test
cd example
npm i
npm run typecheck
npm run lint
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ node_modules
react/package.json
# npm pack output
*.tgz
*.tsbuildinfo
3 changes: 2 additions & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"trailingComma": "es5"
"trailingComma": "all",
"proseWrap": "always"
}
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
# Changelog

## 0.2.0

- Adds /test and /\_generated/component.js entrypoints
- Drops commonjs support
- Improves source mapping for generated files
- Changes to a statically generated component API

## 0.1.28

- Imports with file extensions to help module resolution for NodeNext

## 0.1.27

- Reduce the number of deltas in one round to avoid returning too long of arrays of steps
when catching up old clients
- Reduce the number of deltas in one round to avoid returning too long of arrays
of steps when catching up old clients

## 0.1.26

Expand All @@ -17,7 +24,6 @@

- Support BlockNote ^0.33


## 0.1.24

- Change the BlockNoteEditor to be a type parameter instead, as mismatched
Expand Down
34 changes: 8 additions & 26 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,39 @@

## Running locally

Setup:

```sh
npm i
cd example
npm i
npm run dev:convex -- --once
```

Run the frontend and backend:

```sh
npm run dev
```

## Testing

```sh
rm -rf dist/ && npm run build
npm run clean
npm run build
npm run typecheck
npm run test
cd example
npm run lint
cd ..
npm run test
```

## Deploying

### Building a one-off package

```sh
rm -rf dist/ && npm run build
npm run clean
npm ci
npm pack
```

### Deploying a new version

```sh
# this will change the version and commit it (if you run it in the root directory)
npm version patch
npm publish --dry-run
# sanity check files being included
npm publish
git push --tags
npm run release
```

#### Alpha release

The same as above, but it requires extra flags so the release is only installed with `@alpha`:
or for alpha release:

```sh
npm version prerelease --preid alpha
npm publish --tag alpha
npm run alpha
```
67 changes: 35 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ synced to the cloud. The data lives in your Convex database, and can be stored
alongside the rest of your app's data.

Just configure your editor features, add this component to your Convex backend,
and use the provided sync React hook.
Read this [Stack post](https://stack.convex.dev/add-a-collaborative-document-editor-to-your-app) for more details.
and use the provided sync React hook. Read this
[Stack post](https://stack.convex.dev/add-a-collaborative-document-editor-to-your-app)
for more details.

[![Example of editing](./blocknote.gif)](http://www.youtube.com/watch?v=TGd-Nl7PBYQ "Collaborative editing syncing")

Expand Down Expand Up @@ -62,16 +63,17 @@ Features:
- Transform the document server-side, enabling easy AI interoperation.

See [below](#future-features) for future feature ideas and
[CONTRIBUTING.md](./CONTRIBUTING.md) for how to contribute.
Found a bug? Feature request? [File it here](https://github.com/get-convex/prosemirror-sync/issues).
[CONTRIBUTING.md](./CONTRIBUTING.md) for how to contribute. Found a bug? Feature
request? [File it here](https://github.com/get-convex/prosemirror-sync/issues).

## Pre-requisite: Convex

You'll need an existing Convex project to use the component.
Convex is a hosted backend platform, including a database, serverless functions,
and a ton more you can learn about [here](https://docs.convex.dev/get-started).
You'll need an existing Convex project to use the component. Convex is a hosted
backend platform, including a database, serverless functions, and a ton more you
can learn about [here](https://docs.convex.dev/get-started).

Run `npm create convex` or follow any of the [quickstarts](https://docs.convex.dev/home) to set one up.
Run `npm create convex` or follow any of the
[quickstarts](https://docs.convex.dev/home) to set one up.

## Installation

Expand All @@ -81,12 +83,13 @@ Install the component package:
npm install @convex-dev/prosemirror-sync
```

Create a `convex.config.ts` file in your app's `convex/` folder and install the component by calling `use`:
Create a `convex.config.ts` file in your app's `convex/` folder and install the
component by calling `use`:

```ts
// convex/convex.config.ts
import { defineApp } from "convex/server";
import prosemirrorSync from "@convex-dev/prosemirror-sync/convex.config";
import prosemirrorSync from "@convex-dev/prosemirror-sync/convex.config.js";

const app = defineApp();
app.use(prosemirrorSync);
Expand All @@ -97,9 +100,8 @@ export default app;
## Usage

To use the component, you expose the API in a file in your `convex/` folder, and
use the editor-specific sync React hook, passing in a reference to
the API you defined. For this example, we'll create the API in
`convex/example.ts`.
use the editor-specific sync React hook, passing in a reference to the API you
defined. For this example, we'll create the API in `convex/example.ts`.

```ts
// convex/example.ts
Expand Down Expand Up @@ -194,21 +196,22 @@ See a working example in [example.ts](./example/convex/example.ts) and

### Configuring the snapshot debounce interval

The snapshot debounce interval is set to one second by default.
You can specify a different interval with the `snapshotDebounceMs` option when
calling `useTiptapSync` or `useBlockNoteSync`.
The snapshot debounce interval is set to one second by default. You can specify
a different interval with the `snapshotDebounceMs` option when calling
`useTiptapSync` or `useBlockNoteSync`.

A snapshot won't be sent until both of these are true:

- The document has been idle for the debounce interval.
- The current user was the last to make a change.

There can be races, but since each client will submit the snapshot for their
own change, they won't conflict with each other and are safe to apply.
There can be races, but since each client will submit the snapshot for their own
change, they won't conflict with each other and are safe to apply.

### Creating a new document

You can create a new document from the client by calling `sync.create(content)`, or on the server by calling `prosemirrorSync.create(ctx, id, content)`.
You can create a new document from the client by calling `sync.create(content)`,
or on the server by calling `prosemirrorSync.create(ctx, id, content)`.

The content should be a JSON object matching the
[Schema](https://tiptap.dev/docs/editor/core-concepts/schema). If you're using
Expand All @@ -229,8 +232,8 @@ For client-side document creation:

### Transforming the document server-side

You can transform the document server-side. It will give you the latest
version of the document, and you return a
You can transform the document server-side. It will give you the latest version
of the document, and you return a
[ProseMirror Transform](https://prosemirror.net/docs/ref/#transform.Transform).

You can make this transoform via `new Transform(doc)` or, if you are hydrating a
Expand Down Expand Up @@ -260,11 +263,11 @@ export const transformExample = action({

- The `extensions` should be the same as the ones used by your client editor,
for any extensions that affect the schema (not the sync extension).
- The `transform` function can be called multiple times if the document is
being modified concurrently. Ideally this callback doesn't do any slow
operations internally. Instead, do them beforehand.
- The `doc` may differ from the one returned from `getDoc`. You can compare
the `version` returned from `getDoc` to the second argument to the `transform`
- The `transform` function can be called multiple times if the document is being
modified concurrently. Ideally this callback doesn't do any slow operations
internally. Instead, do them beforehand.
- The `doc` may differ from the one returned from `getDoc`. You can compare the
`version` returned from `getDoc` to the second argument to the `transform`
function to see if the document has changed.
- The `transform` function can return a null value to abort making changes.
- If you're passing along a position to insert the text, be aware that changes
Expand Down Expand Up @@ -300,9 +303,9 @@ Features that could be added later:

- Offline editing support: cache the document and local changes in
`sessionStorage` and sync when back online (only for active browser tab).
- Also save snapshots (but not local edits) to `localStorage` so new tabs
can see and edit documents offline (but won't see edits from other tabs
until they're back online).
- Also save snapshots (but not local edits) to `localStorage` so new tabs can
see and edit documents offline (but won't see edits from other tabs until
they're back online).
- Configuration for debouncing syncing steps (to reduce function calls).
- Option to write the concrete value each time a delta is submitted.
- Pluggable storage for ReactNative, assuming single-session.
Expand All @@ -329,9 +332,9 @@ Missing features that aren't currently planned:
- Callback to confirm rebases and handle failures in the client (during sync).
- Optimization to sync a snapshot instead of many deltas when an old client
reconnects and doesn't have local changes.
- Handling multiple AsyncStorage instances that are restored from the same
cloud backup, leading to multiple clients with the same clientID. For now,
we'll assume that AsyncStorage is only used by one client at a time.
- Handling multiple AsyncStorage instances that are restored from the same cloud
backup, leading to multiple clients with the same clientID. For now, we'll
assume that AsyncStorage is only used by one client at a time.

<!-- END: Include on https://convex.dev/components -->

Expand Down
8 changes: 0 additions & 8 deletions commonjs.json

This file was deleted.

7 changes: 7 additions & 0 deletions convex.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "./node_modules/convex/schemas/convex.schema.json",
"functions": "example/convex",
"codegen": {
"legacyComponentApi": false
}
}
Loading
Loading