Merge branch 'main' of https://github.com/ueberdosis/tiptap-next
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
[](https://www.npmjs.com/package/@tiptap/core)
|
[](https://www.npmjs.com/package/@tiptap/core)
|
||||||
[](https://github.com/ueberdosis/tiptap-next/actions)
|
[](https://github.com/ueberdosis/tiptap-next/actions)
|
||||||
[](https://github.com/sponsors/ueberdosis)
|
[](https://github.com/sponsors/ueberdosis)
|
||||||
|
[](https://discord.gg/WtJ49jGshW)
|
||||||
|
|
||||||
A headless and extendable rich text editor, based on [ProseMirror](https://github.com/ProseMirror/prosemirror), which is already in use at many well-known companies such as *New York Times*, *The Guardian* or *Atlassian*.
|
A headless and extendable rich text editor, based on [ProseMirror](https://github.com/ProseMirror/prosemirror), which is already in use at many well-known companies such as *New York Times*, *The Guardian* or *Atlassian*.
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
This extension adds a text align attribute to a specified list of nodes. The attribute is used to align the text.
|
This extension adds a text align attribute to a specified list of nodes. The attribute is used to align the text.
|
||||||
|
|
||||||
|
:::warning Firefox bug
|
||||||
|
`text-align: justify` doesn't work together with `white-space: pre-wrap` in Firefox, [that’s a known issue](https://bugzilla.mozilla.org/show_bug.cgi?id=1253840).
|
||||||
|
:::
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
```bash
|
```bash
|
||||||
# with npm
|
# with npm
|
||||||
|
|||||||
@@ -9,107 +9,112 @@ title: Alpine WYSIWYG
|
|||||||
## Introduction
|
## Introduction
|
||||||
The following guide describes how to integrate tiptap with your [Alpine.js](https://github.com/alpinejs/alpine) project.
|
The following guide describes how to integrate tiptap with your [Alpine.js](https://github.com/alpinejs/alpine) project.
|
||||||
|
|
||||||
TODO
|
For the sake of this guide we’ll use [Vite](https://vitejs.dev/) to quickly set up a project, but you can use whatever you’re used to. Vite is just really fast and we love it.
|
||||||
|
|
||||||
## CodeSandbox
|
## Requirements
|
||||||
https://codesandbox.io/s/alpine-tiptap-2ro5e?file=/index.html:0-1419
|
* [Node](https://nodejs.org/en/download/) installed on your machine
|
||||||
|
* Experience with [Alpine.js](https://github.com/alpinejs/alpine)
|
||||||
|
|
||||||
## index.html
|
## 1. Create a project (optional)
|
||||||
```html
|
If you already have an existing Alpine.js project, that’s fine too. Just skip this step and proceed with the next step.
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Parcel Sandbox</title>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link
|
|
||||||
href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.8.0/dist/alpine.min.js"
|
|
||||||
defer
|
|
||||||
></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
For the sake of this guide, let’s start with a fresh [Vite](https://vitejs.dev/) project called `tiptap-example`. Vite sets up everything we need, just select the Vanilla JavaScript template.
|
||||||
<div
|
|
||||||
x-data="setupEditor('<p>My content goes here</p>')"
|
|
||||||
x-init="() => init($refs.editor)"
|
|
||||||
x-on:click.away="inFocus = false"
|
|
||||||
>
|
|
||||||
<template x-if="editor">
|
|
||||||
<nav class="space-x-1">
|
|
||||||
<button
|
|
||||||
class="bg-gray-200 rounded px-2 py-1"
|
|
||||||
x-bind:class="{ 'bg-gray-600 text-white': editor.isActive('bold') }"
|
|
||||||
@click="editor.chain().focus().toggleBold().run()"
|
|
||||||
>
|
|
||||||
Bold
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="bg-gray-200 rounded px-2 py-1"
|
|
||||||
x-bind:class="{ 'bg-gray-600 text-white': editor.isActive('italic') }"
|
|
||||||
@click="editor.chain().focus().toggleItalic().run()"
|
|
||||||
>
|
|
||||||
Italic
|
|
||||||
</button>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
<div x-ref="editor"></div>
|
|
||||||
<button
|
|
||||||
class="bg-indigo-500 text-white rounded px-3 py-1"
|
|
||||||
x-on:click="console.log(content)"
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
(view console for editor output)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="src/index.js"></script>
|
```bash
|
||||||
</body>
|
npm init @vitejs/app tiptap-example
|
||||||
</html>
|
cd tiptap-example
|
||||||
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
## index.js
|
## 2. Install the dependencies
|
||||||
|
Okay, enough of the boring boilerplate work. Let’s finally install tiptap! For the following example you’ll need `alpinejs`, the `@tiptap/core` package and the `@tiptap/starter-kit` which has the most common extensions to get started quickly.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# install with npm
|
||||||
|
npm install alpinejs @tiptap/core @tiptap/starter-kit
|
||||||
|
|
||||||
|
# install with Yarn
|
||||||
|
yarn add alpinejs @tiptap/core @tiptap/starter-kit
|
||||||
|
```
|
||||||
|
|
||||||
|
If you followed step 1, you can now start your project with `npm run dev` or `yarn dev`, and open [http://localhost:3000](http://localhost:3000) in your favorite browser. This might be different, if you’re working with an existing project.
|
||||||
|
|
||||||
|
## 3. Add a JavaScript file
|
||||||
|
To actually start using tiptap, you’ll need to write a little bit of JavaScript. Let’s put the following example code in a file called `main.js`.
|
||||||
|
|
||||||
|
This is the fastest way to get tiptap up and running with Alpine.js. It will give you a very basic version of tiptap. No worries, you will be able to add more functionality soon.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { Editor as TipTap } from "@tiptap/core"
|
import alpinejs from 'alpinejs'
|
||||||
import { defaultExtensions } from "@tiptap/starter-kit"
|
import { Editor } from '@tiptap/core'
|
||||||
|
import { defaultExtensions } from '@tiptap/starter-kit'
|
||||||
|
|
||||||
window.setupEditor = function (content) {
|
window.setupEditor = function(content) {
|
||||||
return {
|
return {
|
||||||
content: content,
|
|
||||||
inFocus: false,
|
|
||||||
// updatedAt is to force Alpine to
|
|
||||||
// rerender on selection change
|
|
||||||
updatedAt: Date.now(),
|
|
||||||
editor: null,
|
editor: null,
|
||||||
|
content: content,
|
||||||
init(el) {
|
init(element) {
|
||||||
let editor = new TipTap({
|
this.editor = new Editor({
|
||||||
element: el,
|
element: element,
|
||||||
extensions: defaultExtensions(),
|
extensions: defaultExtensions(),
|
||||||
content: this.content,
|
content: this.content,
|
||||||
editorProps: {
|
onUpdate: ({ editor }) => {
|
||||||
attributes: {
|
this.content = editor.getHTML()
|
||||||
class: "prose-sm py-4 focus:outline-none"
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
},
|
||||||
editor.on("update", () => {
|
|
||||||
this.content = this.editor.getHTML()
|
|
||||||
})
|
|
||||||
|
|
||||||
editor.on("focus", () => {
|
|
||||||
this.inFocus = true
|
|
||||||
})
|
|
||||||
|
|
||||||
editor.on("selection", () => {
|
|
||||||
this.updatedAt = Date.now()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.editor = editor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 4. Add it to your app
|
||||||
|
Now, let’s replace the content of the `index.html` with the following example code to use the editor in our app.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- index.html -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div x-data="setupEditor('<p>Hello World! :-)</p>')" x-init="() => init($refs.element)">
|
||||||
|
|
||||||
|
<template x-if="editor">
|
||||||
|
<div class="menu">
|
||||||
|
<button
|
||||||
|
@click="editor.chain().toggleHeading({ level: 1 }).focus().run()"
|
||||||
|
:class="{ 'is-active': editor.isActive('heading', { level: 1 }) }"
|
||||||
|
>
|
||||||
|
H1
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="editor.chain().toggleBold().focus().run()"
|
||||||
|
:class="{ 'is-active': editor.isActive('bold') }"
|
||||||
|
>
|
||||||
|
Bold
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="editor.chain().toggleItalic().focus().run()"
|
||||||
|
:class="{ 'is-active': editor.isActive('italic') }"
|
||||||
|
>
|
||||||
|
Italic
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div x-ref="element"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { margin: 2rem; font-family: sans-serif; }
|
||||||
|
button.is-active { background: black; color: white; }
|
||||||
|
.ProseMirror { padding: 0.5rem 1rem; margin: 1rem 0; border: 1px solid #ccc; }
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|||||||
@@ -20,3 +20,5 @@ For testing purposes or demos, use our [Skypack](https://www.skypack.dev/) CDN b
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ Now, let’s replace the content of `pages/index.vue` with the following example
|
|||||||
|
|
||||||
Note that tiptap needs to run in the client, not on the server. It’s required to wrap the editor in a `<client-only>` tag. [Read more about cient-only components.](https://nuxtjs.org/api/components-client-only)
|
Note that tiptap needs to run in the client, not on the server. It’s required to wrap the editor in a `<client-only>` tag. [Read more about cient-only components.](https://nuxtjs.org/api/components-client-only)
|
||||||
|
|
||||||
You should now see tiptap in your browser. You’ve successfully set up tiptap! Time to give yourself a pat on the back.
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|
||||||
## 5. Use v-model (optional)
|
## 5. Use v-model (optional)
|
||||||
You’re probably used to bind your data with `v-model` in forms, that’s also possible with tiptap. Here is a working example component, that you can integrate in your project:
|
You’re probably used to bind your data with `v-model` in forms, that’s also possible with tiptap. Here is a working example component, that you can integrate in your project:
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ const App = () => {
|
|||||||
export default App
|
export default App
|
||||||
```
|
```
|
||||||
|
|
||||||
You should now see tiptap in your browser. You’ve successfully set up tiptap! Time to give yourself a pat on the back.
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|
||||||
## 5. The complete setup (optional)
|
## 5. The complete setup (optional)
|
||||||
Ready to add more? Below is a demo that shows how you could set up what we call the default editor. Feel free to take this and start customizing it then:
|
Ready to add more? Below is a demo that shows how you could set up what we call the default editor. Feel free to take this and start customizing it then:
|
||||||
|
|||||||
@@ -116,4 +116,4 @@ Now, let’s replace the content of `src/routes/index.svelte` with the following
|
|||||||
</main>
|
</main>
|
||||||
```
|
```
|
||||||
|
|
||||||
You should now see tiptap in your browser. You’ve successfully set up tiptap! Time to give yourself a pat on the back.
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
You should now see tiptap in your browser. You’ve successfully set up tiptap! Time to give yourself a pat on the back.
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|
||||||
## 5. Use v-model (optional)
|
## 5. Use v-model (optional)
|
||||||
You’re probably used to bind your data with `v-model` in forms, that’s also possible with tiptap. Here is a working example component, that you can integrate in your project:
|
You’re probably used to bind your data with `v-model` in forms, that’s also possible with tiptap. Here is a working example component, that you can integrate in your project:
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
You should now see tiptap in your browser. You’ve successfully set up tiptap! Time to give yourself a pat on the back.
|
You should now see tiptap in your browser. Time to give yourself a pat on the back! :)
|
||||||
|
|
||||||
## 5. Use v-model (optional)
|
## 5. Use v-model (optional)
|
||||||
You’re probably used to bind your data with `v-model` in forms, that’s also possible with tiptap. Here is how that would work with tiptap:
|
You’re probably used to bind your data with `v-model` in forms, that’s also possible with tiptap. Here is how that would work with tiptap:
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
# skip: true
|
# skip: true
|
||||||
- title: Alpine.js
|
- title: Alpine.js
|
||||||
link: /installation/alpine
|
link: /installation/alpine
|
||||||
type: draft
|
type: new
|
||||||
skip: true
|
skip: true
|
||||||
- title: Livewire
|
- title: Livewire
|
||||||
link: /installation/livewire
|
link: /installation/livewire
|
||||||
|
|||||||
Reference in New Issue
Block a user