Skip to content

Commit

Permalink
feat: add transformations page to the guide
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskbx committed Apr 13, 2021
1 parent de53844 commit 81e0ddf
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 95 deletions.
2 changes: 1 addition & 1 deletion docs/src/docPages/extensions/webhook.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ When a user disconnects the onDisconnect webhook will be triggered with the foll

## Transformation

As you probably already know from [the guide](/guide/documents) the Y-Doc must be serialized into something readable by your application and when importing a document it must be converted into a Y-Doc respectively.
As you probably already know from [the guide](/guide/transformations) the Y-Doc must be serialized into something readable by your application and when importing a document it must be converted into a Y-Doc respectively.

Because hocuspocus doesn't know how your data is structured, you need to pass a transformer to the Webhook extension. You can use one of the transformers from the `@hocuspocus/transformer` package. Make sure to configure them properly. In this example we used the TiptapTransformer that needs the list of extensions:

Expand Down
100 changes: 6 additions & 94 deletions docs/src/docPages/guide/documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ or something else. If you want to send a webhook to an external API we already h

It's **highly recommended** to debounce extensive operations (like API calls) as this hook can be fired up to multiple times a second:

You need to serialize the Y-Doc that hocuspocus gives you to something you can actually display in your views. Check out the [transformers section](/guide/transformers) of the guide for more information.

```typescript
import { debounce } from 'debounce'
import { Server } from '@hocuspocus/server'
Expand Down Expand Up @@ -85,16 +87,19 @@ hocuspocus.listen()

If you want to alter the Y-Doc when hocuspocus creates it, you can use the `onCreateDocument` hook and apply updates directly to the given document. This way you can load your document from a database, an external API or even the file system if they are **not present** in your [primary storage](#using-a-primary-storage). For more information on the hook and it's payload checkout it's [API section](/api/on-create-document).

`onCreateDocument` expects a Y-Doc to be returned. Check out the [transformers section](/guide/transformers) of the guide for more information.

```typescript
import { readFileSync } from 'fs'
import { Server } from '@hocuspocus/server'
import { Doc } from 'yjs'
import { TiptapTransformer } from '@hocuspocus/transformer'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'

const hocuspocus = Server.configure({
async onCreateDocument(data) {
async onCreateDocument(data): Doc {
// The tiptap collaboration extension uses shared types of a single y-doc
// to store different fields in the same document.
// The default field in tiptap is simply called "default"
Expand Down Expand Up @@ -182,96 +187,3 @@ const hocuspocus = Server.configure({

hocuspocus.listen()
```
## Transformations

In the previous example we used the TiptapTransformer to transform the Yjs Document (short: Y-Doc) to the format the tiptap editor uses and vice versa.

hocuspocus doesn't care how you structure your data, you can use any Yjs Shared Types you want. You should check out the [Yjs documentation on Shared Types](https://docs.yjs.dev/getting-started/working-with-shared-types) and how to use them, especially if you don't use any of the editors below. But if you do, those examples should give you a head start:

### tiptap

**Convert a Y-Doc to prosemirror JSON:**

```typescript
import { TiptapTransformer } from '@hocuspocus/transformer'
import { Doc } from 'yjs'

const ydoc = new Doc()
const prosemirrorJSON = TiptapTransformer.fromYdoc(ydoc, 'field-name')
```

**Convert prosemirror JSON to a Y-Doc:**

```typescript
import { TiptapTransformer } from '@hocuspocus/transformer'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'

const prosemirrorJSON = {
type: 'doc',
content: [
// ...
],
}

// The TiptapTransformer requires you to pass the list of extensions you use in
// the frontend to create a valid document
const ydoc = TiptapTransformer.toYdoc(prosemirrorJSON, 'field-name', [ Document, Paragraph, Text ])

// Alternatively you can set the extensions on the Transformer instance directly
// and reuse them
const transformer = TiptapTransformer.extensions([ Document, Paragraph, Text ])
const ydoc2 = transformer.toYdoc(prosemirrorJSON, 'field-name')
const ydoc3 = transformer.toYdoc(prosemirrorJSON, 'field-name')
```

### Prosemirror

**Convert a Y-Doc to prosemirror JSON:**

```typescript
import { ProsemirrorTransformer } from '@hocuspocus/transformer'
import { Doc } from 'yjs'

const ydoc = new Doc()
const prosemirrorJSON = ProsemirrorTransformer.fromYdoc(ydoc, 'field-name')
```

**Convert prosemirror JSON to a Y-Doc:**

```typescript
import { ProsemirrorTransformer } from '@hocuspocus/transformer'
import { Schema } from 'prosemirror-model'

const prosemirrorJSON = {
type: 'doc',
content: [
// ...
],
}

const prosemirrorSchema = new Schema()

// The ProsemirrorTransformer requires you to pass the schema your editor uses
const ydoc = ProsemirrorTransformer.toYdoc(prosemirrorJSON, 'field-name', prosemirrorSchema)

// Alternatively you can set the schema on the Transformer instance directly
// and reuse it
const transformer = ProsemirrorTransformer.schema(prosemirrorSchema)
const ydoc2 = transformer.toYdoc(prosemirrorJSON, 'field-name')
const ydoc3 = transformer.toYdoc(prosemirrorJSON, 'field-name')
```


### Quill

```typescript
// TODO
```

### Monaco

```typescript
// TODO
```
2 changes: 2 additions & 0 deletions docs/src/docPages/guide/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ We already created some very useful extensions you should check out for sure:

**[@hocuspocus/extension-webhook](/extensions/webhook)**: Send document changes via webhook to your API.

**[@hocuspocus/extension-throttle](/extensions/throttle)**: Throttle connections by ips.

## Create your own extension

hocuspocus is written in TypeScript. You don't have to use TypeScript to write extensions, but it's highly recommended. We will only cover the TypeScript part in this documentation.
Expand Down
117 changes: 117 additions & 0 deletions docs/src/docPages/guide/transformations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Transformations

## toc

## What is a Y-Doc?

A [Y-Doc](https://docs.yjs.dev/api/y.doc) is the underlying object Yjs uses to store the collaboration history, the documents' fields as a so-called Shared Types and sync everything between clients.

hocuspocus doesn't care how you structure your data, so you need to transform your existing document to a Y-Doc when importing documents and vice versa when saving it for your views. You should check out the [Yjs documentation on Shared Types](https://docs.yjs.dev/getting-started/working-with-shared-types) and how to use them, especially if you don't use any of the editors below.

## Transformers

We already built a few easy to use transformers for you. Add the `@hocupocus/transformer` package:

```bash
# with npm
npm install @hocuspocus/transformer

# with Yarn
yarn add @hocuspocus/transformer
```

… and import them:

```typescript
import { TiptapTransformer, ProsemirrorTransformer } from '@hocuspocus/transformer'
```

## Examples

### tiptap

**Convert a Y-Doc to prosemirror JSON:**

```typescript
import { TiptapTransformer } from '@hocuspocus/transformer'
import { Doc } from 'yjs'

const ydoc = new Doc()
const prosemirrorJSON = TiptapTransformer.fromYdoc(ydoc, 'field-name')
```

**Convert prosemirror JSON to a Y-Doc:**

```typescript
import { TiptapTransformer } from '@hocuspocus/transformer'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'

const prosemirrorJSON = {
type: 'doc',
content: [
// ...
],
}

// The TiptapTransformer requires you to pass the list of extensions you use in
// the frontend to create a valid document
const ydoc = TiptapTransformer.toYdoc(prosemirrorJSON, 'field-name', [ Document, Paragraph, Text ])

// Alternatively you can set the extensions on the Transformer instance directly
// and reuse them
const transformer = TiptapTransformer.extensions([ Document, Paragraph, Text ])
const ydoc2 = transformer.toYdoc(prosemirrorJSON, 'field-name')
const ydoc3 = transformer.toYdoc(prosemirrorJSON, 'field-name')
```

### Prosemirror

**Convert a Y-Doc to prosemirror JSON:**

```typescript
import { ProsemirrorTransformer } from '@hocuspocus/transformer'
import { Doc } from 'yjs'

const ydoc = new Doc()
const prosemirrorJSON = ProsemirrorTransformer.fromYdoc(ydoc, 'field-name')
```

**Convert prosemirror JSON to a Y-Doc:**

```typescript
import { ProsemirrorTransformer } from '@hocuspocus/transformer'
import { Schema } from 'prosemirror-model'

const prosemirrorJSON = {
type: 'doc',
content: [
// ...
],
}

const prosemirrorSchema = new Schema()

// The ProsemirrorTransformer requires you to pass the schema your editor uses
const ydoc = ProsemirrorTransformer.toYdoc(prosemirrorJSON, 'field-name', prosemirrorSchema)

// Alternatively you can set the schema on the Transformer instance directly
// and reuse it
const transformer = ProsemirrorTransformer.schema(prosemirrorSchema)
const ydoc2 = transformer.toYdoc(prosemirrorJSON, 'field-name')
const ydoc3 = transformer.toYdoc(prosemirrorJSON, 'field-name')
```


### Quill

```typescript
// TODO
```

### Monaco

```typescript
// TODO
```
2 changes: 2 additions & 0 deletions docs/src/links.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
link: /guide/authentication-and-authorization
- title: Working with Documents
link: /guide/documents
- title: Transformations
link: /guide/transformations
- title: Framework integration
link: /guide/framework-integration
- title: Extensions
Expand Down

0 comments on commit 81e0ddf

Please sign in to comment.