Merge branch 'main' of github.com:ueberdosis/tiptap
This commit is contained in:
7
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
7
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -11,6 +11,13 @@ body:
|
|||||||
placeholder: "I’m always frustrated when …"
|
placeholder: "I’m always frustrated when …"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: environment
|
||||||
|
attributes:
|
||||||
|
label: Which browser was this experienced in? Are any special extensions installed?
|
||||||
|
description: Please give us more information about your browser environment so we can reproduce the bug faster.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: reproduction
|
id: reproduction
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
@@ -24,15 +24,15 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@v2.4.0
|
- uses: actions/checkout@v3.0.0
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v2.5.1
|
uses: actions/setup-node@v3.1.1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Load cached dependencies
|
- name: Load cached dependencies
|
||||||
uses: actions/cache@v2.1.7
|
uses: actions/cache@v3.0.2
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -80,10 +80,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@v2.4.0
|
- uses: actions/checkout@v3.0.0
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v2.5.1
|
uses: actions/setup-node@v3.1.1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ jobs:
|
|||||||
quiet: true
|
quiet: true
|
||||||
|
|
||||||
- name: Export screenshots (on failure only)
|
- name: Export screenshots (on failure only)
|
||||||
uses: actions/upload-artifact@v2.3.1
|
uses: actions/upload-artifact@v3.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: cypress-screenshots
|
name: cypress-screenshots
|
||||||
@@ -107,7 +107,7 @@ jobs:
|
|||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
- name: Export screen recordings (on failure only)
|
- name: Export screen recordings (on failure only)
|
||||||
uses: actions/upload-artifact@v2.3.1
|
uses: actions/upload-artifact@v3.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: cypress-videos
|
name: cypress-videos
|
||||||
@@ -136,15 +136,15 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@v2.4.0
|
- uses: actions/checkout@v3.0.0
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v2.5.1
|
uses: actions/setup-node@v3.1.1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Load cached dependencies
|
- name: Load cached dependencies
|
||||||
uses: actions/cache@v2.1.7
|
uses: actions/cache@v3.0.2
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Tiptap demos in Google Chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "chrome",
|
||||||
|
"url": "http://localhost:3000",
|
||||||
|
"webRoot": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
87
demos/package-lock.json
generated
87
demos/package-lock.json
generated
@@ -24,8 +24,8 @@
|
|||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"iframe-resizer": "^4.3.2",
|
"iframe-resizer": "^4.3.2",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.6",
|
||||||
"react": "^17.0.2",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.0.0",
|
||||||
"sass": "^1.49.7",
|
"sass": "^1.49.7",
|
||||||
"tailwindcss": "^2.2.19",
|
"tailwindcss": "^2.2.19",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
@@ -2345,9 +2345,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/modern-normalize": {
|
"node_modules/modern-normalize": {
|
||||||
@@ -2424,15 +2424,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/object-assign": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
|
||||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/object-hash": {
|
"node_modules/object-hash": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
||||||
@@ -2703,30 +2694,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "17.0.2",
|
"version": "18.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.0.0.tgz",
|
||||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
"integrity": "sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0"
|
||||||
"object-assign": "^4.1.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "18.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.0.0.tgz",
|
||||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
"integrity": "sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"object-assign": "^4.1.1",
|
"scheduler": "^0.21.0"
|
||||||
"scheduler": "^0.20.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "17.0.2"
|
"react": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
@@ -2917,13 +2906,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.20.2",
|
"version": "0.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz",
|
||||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
"integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0"
|
||||||
"object-assign": "^4.1.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
@@ -5338,9 +5326,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"modern-normalize": {
|
"modern-normalize": {
|
||||||
@@ -5396,12 +5384,6 @@
|
|||||||
"path-key": "^3.0.0"
|
"path-key": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object-assign": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
|
||||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"object-hash": {
|
"object-hash": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
||||||
@@ -5576,24 +5558,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react": {
|
"react": {
|
||||||
"version": "17.0.2",
|
"version": "18.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.0.0.tgz",
|
||||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
"integrity": "sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0"
|
||||||
"object-assign": "^4.1.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
"version": "17.0.2",
|
"version": "18.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.0.0.tgz",
|
||||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
"integrity": "sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"object-assign": "^4.1.1",
|
"scheduler": "^0.21.0"
|
||||||
"scheduler": "^0.20.2"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-refresh": {
|
"react-refresh": {
|
||||||
@@ -5735,13 +5715,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scheduler": {
|
"scheduler": {
|
||||||
"version": "0.20.2",
|
"version": "0.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz",
|
||||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
"integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0"
|
||||||
"object-assign": "^4.1.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"iframe-resizer": "^4.3.2",
|
"iframe-resizer": "^4.3.2",
|
||||||
"postcss": "^8.4.6",
|
"postcss": "^8.4.6",
|
||||||
"react": "^17.0.2",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.0.0",
|
||||||
"sass": "^1.49.7",
|
"sass": "^1.49.7",
|
||||||
"tailwindcss": "^2.2.19",
|
"tailwindcss": "^2.2.19",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import { createRoot } from 'react-dom/client'
|
||||||
import 'iframe-resizer/js/iframeResizer.contentWindow'
|
import 'iframe-resizer/js/iframeResizer.contentWindow'
|
||||||
import { debug, splitName } from './helper'
|
import { debug, splitName } from './helper'
|
||||||
import './style.scss'
|
import './style.scss'
|
||||||
@@ -13,7 +13,11 @@ export default function init(name: string, source: any) {
|
|||||||
|
|
||||||
import(`../src/${demoCategory}/${demoName}/React/index.jsx`)
|
import(`../src/${demoCategory}/${demoName}/React/index.jsx`)
|
||||||
.then(module => {
|
.then(module => {
|
||||||
ReactDOM.render(React.createElement(module.default), document.getElementById('app'))
|
const root = document.getElementById('app')
|
||||||
|
|
||||||
|
if (root) {
|
||||||
|
createRoot(root).render(React.createElement(module.default))
|
||||||
|
}
|
||||||
debug()
|
debug()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
3
demos/src/Examples/CSSModules/Vue/index.css
Normal file
3
demos/src/Examples/CSSModules/Vue/index.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
h1 {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
0
demos/src/Examples/CSSModules/Vue/index.html
Normal file
0
demos/src/Examples/CSSModules/Vue/index.html
Normal file
17
demos/src/Examples/CSSModules/Vue/index.spec.js
Normal file
17
demos/src/Examples/CSSModules/Vue/index.spec.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
context('/src/Examples/CSSModules/Vue/', () => {
|
||||||
|
before(() => {
|
||||||
|
cy.visit('/src/Examples/CSSModules/Vue/')
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.get('.ProseMirror').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<h1>Example Text</h1>')
|
||||||
|
cy.get('.ProseMirror').type('{selectall}')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should apply a red headline style to h1', () => {
|
||||||
|
cy.get('.ProseMirror h1').should('exist')
|
||||||
|
cy.get('.ProseMirror h1').should('have.css', 'color', '#f00');
|
||||||
|
})
|
||||||
|
})
|
||||||
187
demos/src/Examples/CSSModules/Vue/index.vue
Normal file
187
demos/src/Examples/CSSModules/Vue/index.vue
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="editor">
|
||||||
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
|
bold
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
|
italic
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
|
strike
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
|
code
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
|
clear marks
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
|
clear nodes
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
|
paragraph
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
|
h1
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
|
h2
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
|
h3
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
|
h4
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
|
h5
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
|
h6
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
|
bullet list
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
|
ordered list
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
|
code block
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
|
blockquote
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
|
horizontal rule
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
|
hard break
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().undo().run()">
|
||||||
|
undo
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().redo().run()">
|
||||||
|
redo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<editor-content :editor="editor" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Editor, EditorContent } from '@tiptap/vue-3'
|
||||||
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
EditorContent,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
editor: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.editor = new Editor({
|
||||||
|
extensions: [
|
||||||
|
StarterKit,
|
||||||
|
],
|
||||||
|
content: `
|
||||||
|
<h1>
|
||||||
|
This is a red headline
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
this is a <em>basic</em> example of <strong>tiptap</strong>. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
That’s a bullet list with one …
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
… or two list items.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block:
|
||||||
|
</p>
|
||||||
|
<pre><code class="language-css">body {
|
||||||
|
display: none;
|
||||||
|
}</code></pre>
|
||||||
|
<p>
|
||||||
|
I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too.
|
||||||
|
</p>
|
||||||
|
<blockquote>
|
||||||
|
Wow, that’s amazing. Good work, boy! 👏
|
||||||
|
<br />
|
||||||
|
— Mom
|
||||||
|
</blockquote>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeUnmount() {
|
||||||
|
this.editor.destroy()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
/* Basic editor styles */
|
||||||
|
.ProseMirror {
|
||||||
|
> * + * {
|
||||||
|
margin-top: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: rgba(#616161, 0.1);
|
||||||
|
color: #616161;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #0D0D0D;
|
||||||
|
color: #FFF;
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
background: none;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
padding-left: 1rem;
|
||||||
|
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -16,7 +16,7 @@ export default () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return null
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the initial content …
|
// Get the initial content …
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return null
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the initial content …
|
// Get the initial content …
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return null
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.setEditable(editable)
|
editor.setEditable(editable)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ We provide [an official PHP package to work with Tiptap content](/api/utilities/
|
|||||||
|
|
||||||
## Laravel Livewire
|
## Laravel Livewire
|
||||||
|
|
||||||
### editor.blade.php
|
### my-livewire-component.blade.php
|
||||||
```html
|
```html
|
||||||
<!--
|
<!--
|
||||||
In your livewire component you could add an
|
In your livewire component you could add an
|
||||||
@@ -25,7 +25,7 @@ We provide [an official PHP package to work with Tiptap content](/api/utilities/
|
|||||||
></x-editor>
|
></x-editor>
|
||||||
```
|
```
|
||||||
|
|
||||||
### my-livewire-component.blade.php
|
### editor.blade.php
|
||||||
```html
|
```html
|
||||||
<div
|
<div
|
||||||
x-data="setupEditor(
|
x-data="setupEditor(
|
||||||
|
|||||||
28461
package-lock.json
generated
Normal file
28461
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -60,8 +60,6 @@ export const Keymap = Extension.create({
|
|||||||
|
|
||||||
const pcKeymap = {
|
const pcKeymap = {
|
||||||
...baseKeymap,
|
...baseKeymap,
|
||||||
Home: () => this.editor.commands.selectTextblockStart(),
|
|
||||||
End: () => this.editor.commands.selectTextblockEnd(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const macKeymap = {
|
const macKeymap = {
|
||||||
|
|||||||
@@ -32,5 +32,6 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ueberdosis/tiptap",
|
"url": "https://github.com/ueberdosis/tiptap",
|
||||||
"directory": "packages/extension-bubble-menu"
|
"directory": "packages/extension-bubble-menu"
|
||||||
}
|
},
|
||||||
|
"sideEffects": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export class BubbleMenuView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.tippy?.setProps({
|
this.tippy?.setProps({
|
||||||
getReferenceClientRect: () => {
|
getReferenceClientRect: this.tippyOptions?.getReferenceClientRect || (() => {
|
||||||
if (isNodeSelection(state.selection)) {
|
if (isNodeSelection(state.selection)) {
|
||||||
const node = view.nodeDOM(from) as HTMLElement
|
const node = view.nodeDOM(from) as HTMLElement
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ export class BubbleMenuView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return posToDOMRect(view, from, to)
|
return posToDOMRect(view, from, to)
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
this.show()
|
this.show()
|
||||||
|
|||||||
@@ -21,8 +21,7 @@
|
|||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "^2.0.0-beta.1",
|
"@tiptap/core": "^2.0.0-beta.1"
|
||||||
"@tiptap/extension-text-style": "^2.0.0-beta.1"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prosemirror-model": "^1.16.1",
|
"prosemirror-model": "^1.16.1",
|
||||||
|
|||||||
@@ -32,5 +32,6 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ueberdosis/tiptap",
|
"url": "https://github.com/ueberdosis/tiptap",
|
||||||
"directory": "packages/extension-floating-menu"
|
"directory": "packages/extension-floating-menu"
|
||||||
}
|
},
|
||||||
|
"sideEffects": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ export class FloatingMenuView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.tippy?.setProps({
|
this.tippy?.setProps({
|
||||||
getReferenceClientRect: () => posToDOMRect(view, from, to),
|
getReferenceClientRect: this.tippyOptions?.getReferenceClientRect || (() => posToDOMRect(view, from, to)),
|
||||||
})
|
})
|
||||||
|
|
||||||
this.show()
|
this.show()
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export const Link = Mark.create<LinkOptions>({
|
|||||||
|
|
||||||
parseHTML() {
|
parseHTML() {
|
||||||
return [
|
return [
|
||||||
{ tag: 'a[href]' },
|
{ tag: 'a[href]:not([href *= "javascript:" i])' },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export interface TaskItemOptions {
|
|||||||
HTMLAttributes: Record<string, any>,
|
HTMLAttributes: Record<string, any>,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const inputRegex = /^\s*(\[([ |x])\])\s$/
|
export const inputRegex = /^\s*(\[([( |x])?\])\s$/
|
||||||
|
|
||||||
export const TaskItem = Node.create<TaskItemOptions>({
|
export const TaskItem = Node.create<TaskItemOptions>({
|
||||||
name: 'taskItem',
|
name: 'taskItem',
|
||||||
|
|||||||
@@ -21,15 +21,15 @@
|
|||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^17.0.39",
|
"@types/react": "^18.0.1",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^18.0.0",
|
||||||
"react": "^17.0.0",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^17.0.0"
|
"react-dom": "^18.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tiptap/core": "^2.0.0-beta.1",
|
"@tiptap/core": "^2.0.0-beta.1",
|
||||||
"react": "^17.0.0",
|
"react": "^17.0.0 || ^18.0.0",
|
||||||
"react-dom": "^17.0.0"
|
"react-dom": "^17.0.0 || ^18.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tiptap/extension-bubble-menu": "^2.0.0-beta.55",
|
"@tiptap/extension-bubble-menu": "^2.0.0-beta.55",
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
|
|||||||
|
|
||||||
export type BubbleMenuProps = Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'> & {
|
export type BubbleMenuProps = Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'> & {
|
||||||
className?: string,
|
className?: string,
|
||||||
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BubbleMenu: React.FC<BubbleMenuProps> = props => {
|
export const BubbleMenu = (props: BubbleMenuProps) => {
|
||||||
const [element, setElement] = useState<HTMLDivElement | null>(null)
|
const [element, setElement] = useState<HTMLDivElement | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>
|
|||||||
|
|
||||||
export type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element'> & {
|
export type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element'> & {
|
||||||
className?: string,
|
className?: string,
|
||||||
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FloatingMenu: React.FC<FloatingMenuProps> = props => {
|
export const FloatingMenu = (props: FloatingMenuProps) => {
|
||||||
const [element, setElement] = useState<HTMLDivElement | null>(null)
|
const [element, setElement] = useState<HTMLDivElement | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ export function Suggestion({
|
|||||||
|
|
||||||
// Apply changes to the plugin state from a view transaction.
|
// Apply changes to the plugin state from a view transaction.
|
||||||
apply(transaction, prev, oldState, state) {
|
apply(transaction, prev, oldState, state) {
|
||||||
|
const { isEditable } = editor
|
||||||
const { composing } = editor.view
|
const { composing } = editor.view
|
||||||
const { selection } = transaction
|
const { selection } = transaction
|
||||||
const { empty, from } = selection
|
const { empty, from } = selection
|
||||||
@@ -176,9 +177,10 @@ export function Suggestion({
|
|||||||
|
|
||||||
next.composing = composing
|
next.composing = composing
|
||||||
|
|
||||||
// We can only be suggesting if there is no selection
|
// We can only be suggesting if the view is editable, and:
|
||||||
// or a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
|
// * there is no selection, or
|
||||||
if (empty || editor.view.composing) {
|
// * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
|
||||||
|
if (isEditable && (empty || editor.view.composing)) {
|
||||||
// Reset active state if we just left the previous suggestion range
|
// Reset active state if we just left the previous suggestion range
|
||||||
if (
|
if (
|
||||||
(from < prev.range.from || from > prev.range.to)
|
(from < prev.range.from || from > prev.range.to)
|
||||||
|
|||||||
@@ -15,35 +15,35 @@ import { VueRenderer } from './VueRenderer'
|
|||||||
export const nodeViewProps = {
|
export const nodeViewProps = {
|
||||||
editor: {
|
editor: {
|
||||||
type: Object as PropType<NodeViewProps['editor']>,
|
type: Object as PropType<NodeViewProps['editor']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
type: Object as PropType<NodeViewProps['node']>,
|
type: Object as PropType<NodeViewProps['node']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
decorations: {
|
decorations: {
|
||||||
type: Object as PropType<NodeViewProps['decorations']>,
|
type: Object as PropType<NodeViewProps['decorations']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
selected: {
|
selected: {
|
||||||
type: Boolean as PropType<NodeViewProps['selected']>,
|
type: Boolean as PropType<NodeViewProps['selected']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
extension: {
|
extension: {
|
||||||
type: Object as PropType<NodeViewProps['extension']>,
|
type: Object as PropType<NodeViewProps['extension']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
getPos: {
|
getPos: {
|
||||||
type: Function as PropType<NodeViewProps['getPos']>,
|
type: Function as PropType<NodeViewProps['getPos']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
updateAttributes: {
|
updateAttributes: {
|
||||||
type: Function as PropType<NodeViewProps['updateAttributes']>,
|
type: Function as PropType<NodeViewProps['updateAttributes']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
deleteNode: {
|
deleteNode: {
|
||||||
type: Function as PropType<NodeViewProps['deleteNode']>,
|
type: Function as PropType<NodeViewProps['deleteNode']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,35 +21,35 @@ import { VueRenderer } from './VueRenderer'
|
|||||||
export const nodeViewProps = {
|
export const nodeViewProps = {
|
||||||
editor: {
|
editor: {
|
||||||
type: Object as PropType<NodeViewProps['editor']>,
|
type: Object as PropType<NodeViewProps['editor']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
type: Object as PropType<NodeViewProps['node']>,
|
type: Object as PropType<NodeViewProps['node']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
decorations: {
|
decorations: {
|
||||||
type: Object as PropType<NodeViewProps['decorations']>,
|
type: Object as PropType<NodeViewProps['decorations']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
selected: {
|
selected: {
|
||||||
type: Boolean as PropType<NodeViewProps['selected']>,
|
type: Boolean as PropType<NodeViewProps['selected']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
extension: {
|
extension: {
|
||||||
type: Object as PropType<NodeViewProps['extension']>,
|
type: Object as PropType<NodeViewProps['extension']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
getPos: {
|
getPos: {
|
||||||
type: Function as PropType<NodeViewProps['getPos']>,
|
type: Function as PropType<NodeViewProps['getPos']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
updateAttributes: {
|
updateAttributes: {
|
||||||
type: Function as PropType<NodeViewProps['updateAttributes']>,
|
type: Function as PropType<NodeViewProps['updateAttributes']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
deleteNode: {
|
deleteNode: {
|
||||||
type: Function as PropType<NodeViewProps['deleteNode']>,
|
type: Function as PropType<NodeViewProps['deleteNode']>,
|
||||||
required: true,
|
required: true as const,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +101,10 @@ class VueNodeView extends NodeView<Component, Editor, VueNodeViewRendererOptions
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
__scopeId: this.component.__scopeId,
|
__scopeId: this.component.__scopeId,
|
||||||
|
// add support for CSS Modules
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line
|
||||||
|
__cssModules: this.component.__cssModules,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.renderer = new VueRenderer(extendedComponent, {
|
this.renderer = new VueRenderer(extendedComponent, {
|
||||||
|
|||||||
Reference in New Issue
Block a user