mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-11-24 03:39:01 +08:00
Merge branch 'develop' into feature/once
This commit is contained in:
commit
b873b36f11
8
.changeset/README.md
Normal file
8
.changeset/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Changesets
|
||||||
|
|
||||||
|
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||||
|
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||||
|
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||||
|
|
||||||
|
We have a quick list of common questions to get you started engaging with this project in
|
||||||
|
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
5
.changeset/chatty-monkeys-hear.md
Normal file
5
.changeset/chatty-monkeys-hear.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/extension-list-keymap": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix backspace behavior when selection is not collapsed
|
5
.changeset/chatty-pianos-learn.md
Normal file
5
.changeset/chatty-pianos-learn.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
preserve existing node attributes when running setNode
|
14
.changeset/config.json
Normal file
14
.changeset/config.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json",
|
||||||
|
"changelog": "@changesets/cli/changelog",
|
||||||
|
"commit": false,
|
||||||
|
"fixed": [["@tiptap/*"]],
|
||||||
|
"linked": [],
|
||||||
|
"access": "public",
|
||||||
|
"baseBranch": "main",
|
||||||
|
"updateInternalDependencies": "patch",
|
||||||
|
"ignore": [],
|
||||||
|
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
|
||||||
|
"onlyUpdatePeerDependentsWhenOutOfRange": true
|
||||||
|
}
|
||||||
|
}
|
5
.changeset/five-flowers-eat.md
Normal file
5
.changeset/five-flowers-eat.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/vue-3": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix editor destruction before transition end if editor is nested
|
5
.changeset/five-mice-turn.md
Normal file
5
.changeset/five-mice-turn.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/extension-bubble-menu": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `element: HTMLElement` to `shouldShow` options within the BubbleMenu options.
|
5
.changeset/fresh-coats-relate.md
Normal file
5
.changeset/fresh-coats-relate.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/core": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Previously, only a json representation of the node could be inserted into the editor. This change allows for the insertion of Prosemirror `Node`s and `Fragment`s directly into the editor through the `insertContentAt`, `setContent` and `insertContent` commands.
|
5
.changeset/funny-otters-protect.md
Normal file
5
.changeset/funny-otters-protect.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Addresses a bug with `insertContentAt`'s `simulatedPasteRules` option where it could only accept text and not Prosemirror `Node` and `Content`
|
5
.changeset/happy-vans-smash.md
Normal file
5
.changeset/happy-vans-smash.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Updates the types of `addOptions` and `addStorage` to have the parent be possibly undefined which is the most accurate typing
|
5
.changeset/mean-moose-bow.md
Normal file
5
.changeset/mean-moose-bow.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/vue-2": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Pin vue-ts-types to a working version for vue-2
|
5
.changeset/polite-buttons-wash.md
Normal file
5
.changeset/polite-buttons-wash.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/react": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
React 19 is now allowed as a peer dep, we did not have to make any changes for React 19
|
5
.changeset/serious-coins-fail.md
Normal file
5
.changeset/serious-coins-fail.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/extension-mention": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
add zero-width space to resolve cursor selection issue
|
5
.changeset/swift-keys-collect.md
Normal file
5
.changeset/swift-keys-collect.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve handling of selections with `updateAttributes`. Should no longer modify parent nodes of the same type.
|
5
.changeset/two-rats-watch.md
Normal file
5
.changeset/two-rats-watch.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/extension-table": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
enforce cellMinWidth even on column not resized by the user, fixes #5435
|
6
.changeset/witty-olives-protect.md
Normal file
6
.changeset/witty-olives-protect.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/extension-link": patch
|
||||||
|
"tiptap-demos": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
The link extension's `validate` option now applies to both auto-linking and XSS mitigation. While, the new `shouldAutoLink` option is used to disable auto linking on an otherwise valid url.
|
@ -8,6 +8,15 @@ module.exports = {
|
|||||||
node: true,
|
node: true,
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'./**/*.ts',
|
||||||
|
'./**/*.tsx',
|
||||||
|
'./**/*.js',
|
||||||
|
'./**/*.jsx',
|
||||||
|
],
|
||||||
|
extends: ['plugin:react-hooks/recommended'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
'./**/*.ts',
|
'./**/*.ts',
|
||||||
|
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
@ -1,9 +1,6 @@
|
|||||||
# Global
|
# Global
|
||||||
* @bdbch @svenadlung
|
* @bdbch @svenadlung
|
||||||
|
|
||||||
# docs
|
|
||||||
/docs/ @svenadlung
|
|
||||||
|
|
||||||
# demos
|
# demos
|
||||||
/demos/ @bdbch
|
/demos/ @bdbch
|
||||||
|
|
||||||
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@ -14,7 +14,7 @@
|
|||||||
<!-- Add any other notes or screenshots about the PR here. -->
|
<!-- Add any other notes or screenshots about the PR here. -->
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
- [ ] I have renamed my PR according to the naming conventions. (e.g. `feat: Implement new feature` or `chore(deps): Update dependencies`)
|
- [ ] I have created a [changeset](https://github.com/changesets/changesets) for this PR if necessary.
|
||||||
- [ ] My changes do not break the library.
|
- [ ] My changes do not break the library.
|
||||||
- [ ] I have added tests where applicable.
|
- [ ] I have added tests where applicable.
|
||||||
- [ ] I have followed the project guidelines.
|
- [ ] I have followed the project guidelines.
|
||||||
|
25
.github/workflows/build.yml
vendored
25
.github/workflows/build.yml
vendored
@ -3,16 +3,22 @@
|
|||||||
|
|
||||||
name: build
|
name: build
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- develop
|
- develop
|
||||||
|
- next
|
||||||
- release/*
|
- release/*
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- develop
|
- develop
|
||||||
|
- next
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
@ -20,7 +26,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [16]
|
node-version: [20]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.4
|
- uses: actions/checkout@v4.1.4
|
||||||
@ -31,11 +37,12 @@ jobs:
|
|||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Load cached dependencies
|
- name: Load cached dependencies
|
||||||
uses: actions/cache@v4.0.2
|
uses: actions/cache@v4.1.2
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
**/.turbo
|
||||||
/home/runner/.cache/Cypress
|
/home/runner/.cache/Cypress
|
||||||
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
|
||||||
@ -64,7 +71,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [16]
|
node-version: [20]
|
||||||
test-spec:
|
test-spec:
|
||||||
- { name: "Integration", spec: "./tests/cypress/integration/**/*.spec.{js,ts}" }
|
- { name: "Integration", spec: "./tests/cypress/integration/**/*.spec.{js,ts}" }
|
||||||
#- { name: "Demos/Commands", spec: "./demos/src/Commands/**/*.spec.{js,ts}" }
|
#- { name: "Demos/Commands", spec: "./demos/src/Commands/**/*.spec.{js,ts}" }
|
||||||
@ -96,10 +103,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Test ${{ matrix.test-spec.name }}
|
- name: Test ${{ matrix.test-spec.name }}
|
||||||
id: cypress
|
id: cypress
|
||||||
uses: cypress-io/github-action@v6.6.0
|
uses: cypress-io/github-action@v6.7.6
|
||||||
with:
|
with:
|
||||||
cache-key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
cache-key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
start: npm run start
|
start: npm run serve
|
||||||
wait-on: 'http://localhost:3000'
|
wait-on: 'http://localhost:3000'
|
||||||
spec: ${{ matrix.test-spec.spec }}
|
spec: ${{ matrix.test-spec.spec }}
|
||||||
project: ./tests
|
project: ./tests
|
||||||
@ -107,7 +114,7 @@ jobs:
|
|||||||
quiet: true
|
quiet: true
|
||||||
|
|
||||||
- name: Export screenshots (on failure only)
|
- name: Export screenshots (on failure only)
|
||||||
uses: actions/upload-artifact@v4.3.3
|
uses: actions/upload-artifact@v4.4.3
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: cypress-screenshots
|
name: cypress-screenshots
|
||||||
@ -115,7 +122,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@v4.3.3
|
uses: actions/upload-artifact@v4.4.3
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: cypress-videos
|
name: cypress-videos
|
||||||
@ -129,7 +136,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [16]
|
node-version: [20]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.4
|
- uses: actions/checkout@v4.1.4
|
||||||
@ -140,7 +147,7 @@ jobs:
|
|||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Load cached dependencies
|
- name: Load cached dependencies
|
||||||
uses: actions/cache@v4.0.2
|
uses: actions/cache@v4.1.2
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
21
.github/workflows/deploy.yml
vendored
21
.github/workflows/deploy.yml
vendored
@ -1,21 +0,0 @@
|
|||||||
# Automate, customize, and execute your software development workflows right in your repository with GitHub Actions.
|
|
||||||
# Documentation: https://docs.github.com/en/actions
|
|
||||||
|
|
||||||
name: deploy
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: Update the documentation
|
|
||||||
run: curl ${{ secrets.TRIGGER_DEPLOYMENT }}
|
|
27
.github/workflows/docsearch.yml
vendored
27
.github/workflows/docsearch.yml
vendored
@ -1,27 +0,0 @@
|
|||||||
# Automate, customize, and execute your software development workflows right in your repository with GitHub Actions.
|
|
||||||
# Documentation: https://docs.github.com/en/actions
|
|
||||||
|
|
||||||
name: docsearch
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '5 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
docsearch:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4.1.4
|
|
||||||
|
|
||||||
- name: Run DocSearch Scraper
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
docker run \
|
|
||||||
-e TYPESENSE_API_KEY=${{ secrets.TYPESENSE_API_KEY }} \
|
|
||||||
-e TYPESENSE_HOST="${{ secrets.TYPESENSE_HOST }}" \
|
|
||||||
-e TYPESENSE_PORT="${{ secrets.TYPESENSE_PORT }}" \
|
|
||||||
-e TYPESENSE_PROTOCOL="${{ secrets.TYPESENSE_PROTOCOL }}" \
|
|
||||||
-e CONFIG="$(cat docsearch.config.json | jq -r tostring)" \
|
|
||||||
typesense/docsearch-scraper
|
|
88
.github/workflows/publish.yml
vendored
Normal file
88
.github/workflows/publish.yml
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
name: Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
# manual trigger for other branches
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [20]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
registry-url: 'https://registry.npmjs.org/'
|
||||||
|
|
||||||
|
- name: Load cached dependencies
|
||||||
|
uses: actions/cache@v4.1.2
|
||||||
|
id: cache
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
**/node_modules
|
||||||
|
**/.turbo
|
||||||
|
/home/runner/.cache/Cypress
|
||||||
|
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Create Release PR or publish stable version to npm
|
||||||
|
id: changesets
|
||||||
|
uses: changesets/action@v1
|
||||||
|
with:
|
||||||
|
createGithubReleases: false
|
||||||
|
publish: npm run publish
|
||||||
|
version: npm run version
|
||||||
|
title: ${{ github.ref_name == 'main' && 'Publish a new stable version' || 'Publish a new pre-release version' }}
|
||||||
|
commit: >-
|
||||||
|
${{ github.ref_name == 'main' && 'chore(release): publish a new release version' || 'chore(release): publish a new pre-release version' }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||||
|
|
||||||
|
- name: Send release notification
|
||||||
|
if: steps.changesets.outputs.published == 'true'
|
||||||
|
id: slack
|
||||||
|
uses: slackapi/slack-github-action@v1.27.0
|
||||||
|
with:
|
||||||
|
payload: |
|
||||||
|
{
|
||||||
|
"message": "[Tiptap Editor Release]: New Tiptap Editor version has been released to NPM."
|
||||||
|
}
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||||
|
|
||||||
|
- name: Send failure notification
|
||||||
|
if: failure()
|
||||||
|
id: slack_failure
|
||||||
|
uses: slackapi/slack-github-action@v1.27.0
|
||||||
|
with:
|
||||||
|
payload: |
|
||||||
|
{
|
||||||
|
"message": "[Tiptap Editor Release]: There was an issue publishing a new version. You can find the logs here: https://github.com/ueberdosis/tiptap/actions/runs/${{ github.run_id }}"
|
||||||
|
}
|
||||||
|
env:
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
31
.github/workflows/release.yml
vendored
31
.github/workflows/release.yml
vendored
@ -1,31 +0,0 @@
|
|||||||
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
||||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
|
|
||||||
|
|
||||||
name: Release new version
|
|
||||||
|
|
||||||
# on github release published or workflow_dispatch
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish-npm:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4.1.4
|
|
||||||
- uses: actions/setup-node@v4.0.0
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
registry-url: https://registry.npmjs.org/
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm run publish
|
|
||||||
name: "Publish release (current) to NPM"
|
|
||||||
if: "!github.event.release.prerelease"
|
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
||||||
- run: npm run publish:pre
|
|
||||||
name: "Publish release (next) to NPM"
|
|
||||||
if: "github.event.release.prerelease"
|
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,6 +17,9 @@ yarn-error.log*
|
|||||||
# parcel-bundler cache (https://parceljs.org/)
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
.cache
|
.cache
|
||||||
|
|
||||||
|
# Turbo cache
|
||||||
|
.turbo
|
||||||
|
|
||||||
.rpt2_cache
|
.rpt2_cache
|
||||||
.rts2_cache
|
.rts2_cache
|
||||||
.rts2_cache_cjs
|
.rts2_cache_cjs
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
npx --no -- commitlint --edit "$1"
|
|
@ -1,5 +1,11 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
> **Important information**
|
||||||
|
>
|
||||||
|
> As of version 2.4.1 Tiptap uses **Changesets** which don't allow the generation of one generic CHANGELOG file.
|
||||||
|
> If you want to check changes of a specific package version, check the **CHANGELOG.md** file in the specific package
|
||||||
|
> directory or out [Github Releases](https://github.com/ueberdosis/tiptap/releases)
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ Before submitting a pull request:
|
|||||||
- Check the codebase to ensure that your feature doesn't already exist.
|
- Check the codebase to ensure that your feature doesn't already exist.
|
||||||
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
|
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
|
||||||
|
|
||||||
Before commiting:
|
Before committing:
|
||||||
|
|
||||||
- Make sure to run the tests and linter before committing your changes.
|
- Make sure to run the tests and linter before committing your changes.
|
||||||
- Write [conventional commit messages](https://www.conventionalcommits.org/en). You can use `npm run cz` for that.
|
- If you are making changes to one of the packages, make sure to **always** include a [changeset](https://github.com/changesets/changesets) in your PR describing **what changed** with a **description** of the change. Those are responsible for changelog creation
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2023, Tiptap GmbH
|
Copyright (c) 2024, Tiptap GmbH
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -86,6 +86,12 @@ For help, discussion about best practices, or any other conversation that would
|
|||||||
<strong>Basewell</strong>
|
<strong>Basewell</strong>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td align="center" width="100">
|
||||||
|
<a href="https://poggio.io">
|
||||||
|
<img src="https://unavatar.io/github/poggiolabs" width="25"><br>
|
||||||
|
<strong>Poggio</strong>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -93,7 +99,7 @@ For help, discussion about best practices, or any other conversation that would
|
|||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
[iFixit](https://www.ifixit.com/), [ApostropheCMS](https://apostrophecms.com/), [Novadiscovery](http://www.novadiscovery.com/), [Omics Data Automation](https://www.omicsautomation.com), [Flow Mobile](https://www.flowmobile.app/), [DocIQ](https://www.dociq.io/) and [hundreds of awesome inviduals](https://github.com/sponsors/ueberdosis).
|
[iFixit](https://www.ifixit.com/), [ApostropheCMS](https://apostrophecms.com/), [Novadiscovery](http://www.novadiscovery.com/), [Omics Data Automation](https://www.omicsautomation.com), [Flow Mobile](https://www.flowmobile.app/), [DocIQ](https://www.dociq.io/) and [hundreds of awesome individuals](https://github.com/sponsors/ueberdosis).
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
Feel like adding some magic of your own to Tiptap Editor Core? We welcome contributions! Please see our [CONTRIBUTING](CONTRIBUTING.md) guidelines for how to get started.
|
Feel like adding some magic of your own to Tiptap Editor Core? We welcome contributions! Please see our [CONTRIBUTING](CONTRIBUTING.md) guidelines for how to get started.
|
||||||
|
@ -1,5 +1,31 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 2.5.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 6834a7f: Bundling of packages no longer includes tiptap dependency type definitions
|
||||||
|
|
||||||
|
## 2.4.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- d6e56c4: declare lowlight to be a peer dep of extension-code-block-lowlight, update usage to v3
|
||||||
|
|
||||||
|
## 2.4.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 85d21ca: Updated demos and reverted vue specific performance enhancements until we know they work
|
||||||
|
|
||||||
|
> in commit ff04353b3ee0e6fc63733a673e2b27d2272a3355 revert: "fix(vue-3): faster component rendering (#5206)"
|
||||||
|
> This reverts commit 31f37464912b7b21f3a565ca63222b9f5b6cce00.
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
> in commit dbab8e42eac893a0237566fb30c14b4ed0f3674a revert: "fix(vue-3): fix editor.state updating too late during a transaction due to reactiveState fixes #4870 (#5252)"
|
||||||
|
> This reverts commit 509676ed4a63b84b904a98c1e34d18449d25c2a7.
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
@ -7,868 +33,480 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
|||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.3.2](https://github.com/ueberdosis/tiptap/compare/v2.3.1...v2.3.2) (2024-05-08)
|
## [2.3.2](https://github.com/ueberdosis/tiptap/compare/v2.3.1...v2.3.2) (2024-05-08)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* NodePos querySelectorAll function ([#5094](https://github.com/ueberdosis/tiptap/issues/5094)) ([4900a27](https://github.com/ueberdosis/tiptap/commit/4900a27c5389d9a2d0d69f407ca3db0155304315))
|
- NodePos querySelectorAll function ([#5094](https://github.com/ueberdosis/tiptap/issues/5094)) ([4900a27](https://github.com/ueberdosis/tiptap/commit/4900a27c5389d9a2d0d69f407ca3db0155304315))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.3.1](https://github.com/ueberdosis/tiptap/compare/v2.3.0...v2.3.1) (2024-04-30)
|
## [2.3.1](https://github.com/ueberdosis/tiptap/compare/v2.3.0...v2.3.1) (2024-04-30)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.3.0](https://github.com/ueberdosis/tiptap/compare/v2.2.6...v2.3.0) (2024-04-09)
|
# [2.3.0](https://github.com/ueberdosis/tiptap/compare/v2.2.6...v2.3.0) (2024-04-09)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** fix nodepos child lookup ([#5038](https://github.com/ueberdosis/tiptap/issues/5038)) ([22ced31](https://github.com/ueberdosis/tiptap/commit/22ced318723003365fbfd8f59b8dac79c7563017))
|
- **core:** fix nodepos child lookup ([#5038](https://github.com/ueberdosis/tiptap/issues/5038)) ([22ced31](https://github.com/ueberdosis/tiptap/commit/22ced318723003365fbfd8f59b8dac79c7563017))
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **core:** apply input and paste rules when using insertContent methods ([#5046](https://github.com/ueberdosis/tiptap/issues/5046)) ([96b6abc](https://github.com/ueberdosis/tiptap/commit/96b6abcf6edbc6cac03a391130d9feebb6de3a04))
|
- **core:** apply input and paste rules when using insertContent methods ([#5046](https://github.com/ueberdosis/tiptap/issues/5046)) ([96b6abc](https://github.com/ueberdosis/tiptap/commit/96b6abcf6edbc6cac03a391130d9feebb6de3a04))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.2.6](https://github.com/ueberdosis/tiptap/compare/v2.2.5...v2.2.6) (2024-04-06)
|
## [2.2.6](https://github.com/ueberdosis/tiptap/compare/v2.2.5...v2.2.6) (2024-04-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.2.5](https://github.com/ueberdosis/tiptap/compare/v2.2.4...v2.2.5) (2024-04-05)
|
## [2.2.5](https://github.com/ueberdosis/tiptap/compare/v2.2.4...v2.2.5) (2024-04-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.2.4](https://github.com/ueberdosis/tiptap/compare/v2.2.3...v2.2.4) (2024-02-23)
|
## [2.2.4](https://github.com/ueberdosis/tiptap/compare/v2.2.3...v2.2.4) (2024-02-23)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.2.3](https://github.com/ueberdosis/tiptap/compare/v2.2.2...v2.2.3) (2024-02-15)
|
## [2.2.3](https://github.com/ueberdosis/tiptap/compare/v2.2.2...v2.2.3) (2024-02-15)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* fix test path ([21aa96d](https://github.com/ueberdosis/tiptap/commit/21aa96dee8deab1f439b7f655b8ed266a516a4cd))
|
- fix test path ([21aa96d](https://github.com/ueberdosis/tiptap/commit/21aa96dee8deab1f439b7f655b8ed266a516a4cd))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.2.2](https://github.com/ueberdosis/tiptap/compare/v2.2.1...v2.2.2) (2024-02-07)
|
## [2.2.2](https://github.com/ueberdosis/tiptap/compare/v2.2.1...v2.2.2) (2024-02-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.2.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0...v2.2.1) (2024-01-31)
|
## [2.2.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0...v2.2.1) (2024-01-31)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0](https://github.com/ueberdosis/tiptap/compare/v2.1.16...v2.2.0) (2024-01-29)
|
# [2.2.0](https://github.com/ueberdosis/tiptap/compare/v2.1.16...v2.2.0) (2024-01-29)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([b7a2504](https://github.com/ueberdosis/tiptap/commit/b7a2504f16f46563537c890930cb2c332c256175))
|
- **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([b7a2504](https://github.com/ueberdosis/tiptap/commit/b7a2504f16f46563537c890930cb2c332c256175))
|
||||||
* fix imports, fix demos, unpin y-prosemirror ([681aa57](https://github.com/ueberdosis/tiptap/commit/681aa577bff500015c3f925e300c55a71c73efaf))
|
- fix imports, fix demos, unpin y-prosemirror ([681aa57](https://github.com/ueberdosis/tiptap/commit/681aa577bff500015c3f925e300c55a71c73efaf))
|
||||||
* fix newline stripping via insertContent ([8954007](https://github.com/ueberdosis/tiptap/commit/8954007b2b92b040d69b26a0866ae58fabf5e512))
|
- fix newline stripping via insertContent ([8954007](https://github.com/ueberdosis/tiptap/commit/8954007b2b92b040d69b26a0866ae58fabf5e512))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.2.0-rc.8) (2024-01-08)
|
# [2.2.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.2.0-rc.8) (2024-01-08)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.6...v2.2.0-rc.7) (2023-11-27)
|
# [2.2.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.6...v2.2.0-rc.7) (2023-11-27)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.5...v2.2.0-rc.6) (2023-11-23)
|
# [2.2.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.5...v2.2.0-rc.6) (2023-11-23)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.2.0-rc.4) (2023-10-10)
|
# [2.2.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.2.0-rc.4) (2023-10-10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.2...v2.2.0-rc.3) (2023-08-18)
|
# [2.2.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.2...v2.2.0-rc.3) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18)
|
# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18)
|
# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58))
|
- **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.16](https://github.com/ueberdosis/tiptap/compare/v2.1.15...v2.1.16) (2024-01-10)
|
## [2.1.16](https://github.com/ueberdosis/tiptap/compare/v2.1.15...v2.1.16) (2024-01-10)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([2235908](https://github.com/ueberdosis/tiptap/commit/2235908c28f388eda041d1d5d017554d513fe909))
|
- **core:** fix new lines being added via elementFromString ([#4767](https://github.com/ueberdosis/tiptap/issues/4767)) ([2235908](https://github.com/ueberdosis/tiptap/commit/2235908c28f388eda041d1d5d017554d513fe909))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.15](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.1.15) (2024-01-08)
|
## [2.1.15](https://github.com/ueberdosis/tiptap/compare/v2.1.14...v2.1.15) (2024-01-08)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** fix insertContentAt keeping new lines in html content ([#4465](https://github.com/ueberdosis/tiptap/issues/4465)) ([135a12f](https://github.com/ueberdosis/tiptap/commit/135a12f7aa2df839a0b619704110a360b980c738))
|
- **core:** fix insertContentAt keeping new lines in html content ([#4465](https://github.com/ueberdosis/tiptap/issues/4465)) ([135a12f](https://github.com/ueberdosis/tiptap/commit/135a12f7aa2df839a0b619704110a360b980c738))
|
||||||
* **link:** fix tests ([d495d92](https://github.com/ueberdosis/tiptap/commit/d495d92a1f7b1c51e09ac8f4934e15a2d1cf070d))
|
- **link:** fix tests ([d495d92](https://github.com/ueberdosis/tiptap/commit/d495d92a1f7b1c51e09ac8f4934e15a2d1cf070d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.14](https://github.com/ueberdosis/tiptap/compare/v2.1.13...v2.1.14) (2024-01-08)
|
## [2.1.14](https://github.com/ueberdosis/tiptap/compare/v2.1.13...v2.1.14) (2024-01-08)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **typography:** require spaces after divisions to not break date formats ([#4696](https://github.com/ueberdosis/tiptap/issues/4696)) ([f6d7e00](https://github.com/ueberdosis/tiptap/commit/f6d7e00a746a67fa440a3fa0f5362295959873d2))
|
- **typography:** require spaces after divisions to not break date formats ([#4696](https://github.com/ueberdosis/tiptap/issues/4696)) ([f6d7e00](https://github.com/ueberdosis/tiptap/commit/f6d7e00a746a67fa440a3fa0f5362295959873d2))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.13](https://github.com/ueberdosis/tiptap/compare/v2.1.12...v2.1.13) (2023-11-30)
|
## [2.1.13](https://github.com/ueberdosis/tiptap/compare/v2.1.12...v2.1.13) (2023-11-30)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.12](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.1.12) (2023-10-11)
|
## [2.1.12](https://github.com/ueberdosis/tiptap/compare/v2.1.11...v2.1.12) (2023-10-11)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.11](https://github.com/ueberdosis/tiptap/compare/v2.1.10...v2.1.11) (2023-09-20)
|
## [2.1.11](https://github.com/ueberdosis/tiptap/compare/v2.1.10...v2.1.11) (2023-09-20)
|
||||||
|
|
||||||
|
|
||||||
### Reverts
|
### Reverts
|
||||||
|
|
||||||
* Revert "v2.2.11" ([6aa755a](https://github.com/ueberdosis/tiptap/commit/6aa755a04b9955fc175c7ab33dee527d0d5deef0))
|
- Revert "v2.2.11" ([6aa755a](https://github.com/ueberdosis/tiptap/commit/6aa755a04b9955fc175c7ab33dee527d0d5deef0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.10](https://github.com/ueberdosis/tiptap/compare/v2.1.9...v2.1.10) (2023-09-15)
|
## [2.1.10](https://github.com/ueberdosis/tiptap/compare/v2.1.9...v2.1.10) (2023-09-15)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.9](https://github.com/ueberdosis/tiptap/compare/v2.1.8...v2.1.9) (2023-09-14)
|
## [2.1.9](https://github.com/ueberdosis/tiptap/compare/v2.1.8...v2.1.9) (2023-09-14)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.7...v2.1.8) (2023-09-04)
|
## [2.1.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.7...v2.1.8) (2023-09-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.7](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.6...v2.1.7) (2023-09-04)
|
## [2.1.7](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.6...v2.1.7) (2023-09-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.6](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.1.6) (2023-08-18)
|
## [2.1.6](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.1.6) (2023-08-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.2](https://github.com/ueberdosis/tiptap/compare/v2.1.6...v2.2.0-rc.2) (2023-08-18)
|
# [2.2.0-rc.2](https://github.com/ueberdosis/tiptap/compare/v2.1.6...v2.2.0-rc.2) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18)
|
# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18)
|
# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58))
|
- **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18)
|
# [2.2.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.2.0-rc.0...v2.2.0-rc.1) (2023-08-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18)
|
# [2.2.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.2.0-rc.0) (2023-08-18)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58))
|
- **placeholder:** allow editor-is-empty class on any node ([#4335](https://github.com/ueberdosis/tiptap/issues/4335)) ([ff929b1](https://github.com/ueberdosis/tiptap/commit/ff929b179de930619005a773bb4186ae2aa2ec58))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.6](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.1.6) (2023-08-18)
|
## [2.1.6](https://github.com/ueberdosis/tiptap/compare/v2.1.5...v2.1.6) (2023-08-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.5](https://github.com/ueberdosis/tiptap/compare/v2.1.4...v2.1.5) (2023-08-18)
|
## [2.1.5](https://github.com/ueberdosis/tiptap/compare/v2.1.4...v2.1.5) (2023-08-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.4](https://github.com/ueberdosis/tiptap/compare/v2.1.3...v2.1.4) (2023-08-18)
|
## [2.1.4](https://github.com/ueberdosis/tiptap/compare/v2.1.3...v2.1.4) (2023-08-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.3](https://github.com/ueberdosis/tiptap/compare/v2.1.2...v2.1.3) (2023-08-18)
|
## [2.1.3](https://github.com/ueberdosis/tiptap/compare/v2.1.2...v2.1.3) (2023-08-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.2](https://github.com/ueberdosis/tiptap/compare/v2.1.1...v2.1.2) (2023-08-17)
|
## [2.1.2](https://github.com/ueberdosis/tiptap/compare/v2.1.1...v2.1.2) (2023-08-17)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** fix error when merging class attributes ([#4340](https://github.com/ueberdosis/tiptap/issues/4340)) ([a251946](https://github.com/ueberdosis/tiptap/commit/a2519468589e2baa44901a66a3a06b24dc8626d6))
|
- **core:** fix error when merging class attributes ([#4340](https://github.com/ueberdosis/tiptap/issues/4340)) ([a251946](https://github.com/ueberdosis/tiptap/commit/a2519468589e2baa44901a66a3a06b24dc8626d6))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.1.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0...v2.1.1) (2023-08-16)
|
## [2.1.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0...v2.1.1) (2023-08-16)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.14...v2.1.0) (2023-08-16)
|
# [2.1.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.14...v2.1.0) (2023-08-16)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.14](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.13...v2.1.0-rc.14) (2023-08-11)
|
# [2.1.0-rc.14](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.13...v2.1.0-rc.14) (2023-08-11)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.13](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.4...v2.1.0-rc.13) (2023-08-11)
|
# [2.1.0-rc.13](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.4...v2.1.0-rc.13) (2023-08-11)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **demos:** add missing extensions ([6383fd5](https://github.com/ueberdosis/tiptap-workspace/commit/6383fd54080b2ad555286cd0e7c4ad880200200f))
|
- **demos:** add missing extensions ([6383fd5](https://github.com/ueberdosis/tiptap-workspace/commit/6383fd54080b2ad555286cd0e7c4ad880200200f))
|
||||||
* **demos:** update deps ([05a2edf](https://github.com/ueberdosis/tiptap-workspace/commit/05a2edfc16e297effa86d1583fb1680be0320f25))
|
- **demos:** update deps ([05a2edf](https://github.com/ueberdosis/tiptap-workspace/commit/05a2edfc16e297effa86d1583fb1680be0320f25))
|
||||||
* **strikethrough:** update strikethrough shortcut ([#4288](https://github.com/ueberdosis/tiptap-workspace/issues/4288)) ([fd35db4](https://github.com/ueberdosis/tiptap-workspace/commit/fd35db4d090d9fdfef1196fb1f6f858f13cf53d1))
|
- **strikethrough:** update strikethrough shortcut ([#4288](https://github.com/ueberdosis/tiptap-workspace/issues/4288)) ([fd35db4](https://github.com/ueberdosis/tiptap-workspace/commit/fd35db4d090d9fdfef1196fb1f6f858f13cf53d1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14)
|
# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07)
|
# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap-workspace/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920))
|
- **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap-workspace/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07)
|
# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap-workspace/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap-workspace/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3))
|
- **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap-workspace/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap-workspace/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15)
|
# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25)
|
# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25)
|
# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap-workspace/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0))
|
- add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap-workspace/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27)
|
# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26)
|
# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26)
|
# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap-workspace/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap-workspace/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee))
|
- **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap-workspace/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap-workspace/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12)
|
# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap-workspace/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap-workspace/commit/e8cef0404b5039ec2657536976b8b31931afd337))
|
- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap-workspace/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap-workspace/commit/e8cef0404b5039ec2657536976b8b31931afd337))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05)
|
# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap-workspace/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap-workspace/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap-workspace/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb))
|
- clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap-workspace/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap-workspace/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb))
|
||||||
* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap-workspace/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap-workspace/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46))
|
- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap-workspace/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap-workspace/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14)
|
# [2.1.0-rc.12](https://github.com/ueberdosis/tiptap-workspace/compare/v2.1.0-rc.11...v2.1.0-rc.12) (2023-07-14)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07)
|
# [2.1.0-rc.11](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.10...v2.1.0-rc.11) (2023-07-07)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920))
|
- **tests:** fix link rel tests ([c1d1854](https://github.com/ueberdosis/tiptap/commit/c1d18543b03b1fb6b99a2f3546aa5da10c919920))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07)
|
# [2.1.0-rc.10](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.9...v2.1.0-rc.10) (2023-07-07)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3))
|
- **react:** check props.clientRect before creating ReactRenderer ([#4138](https://github.com/ueberdosis/tiptap/issues/4138)) ([d710846](https://github.com/ueberdosis/tiptap/commit/d710846ecb6a3059dfbc21300b9a4b887a8defa3))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15)
|
# [2.1.0-rc.9](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.8...v2.1.0-rc.9) (2023-06-15)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25)
|
# [2.1.0-rc.8](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.7...v2.1.0-rc.8) (2023-05-25)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.6...v2.1.0-rc.7) (2023-05-25)
|
# [2.1.0-rc.7](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.6...v2.1.0-rc.7) (2023-05-25)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.5...v2.1.0-rc.6) (2023-05-25)
|
# [2.1.0-rc.6](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.5...v2.1.0-rc.6) (2023-05-25)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25)
|
# [2.1.0-rc.5](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.4...v2.1.0-rc.5) (2023-05-25)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0))
|
- add tiptap class ([614fc80](https://github.com/ueberdosis/tiptap/commit/614fc8082c376bf3c40a05c23ceda6b4a6fbf8d0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27)
|
# [2.1.0-rc.4](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.3...v2.1.0-rc.4) (2023-04-27)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26)
|
# [2.1.0-rc.3](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.2...v2.1.0-rc.3) (2023-04-26)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26)
|
# [2.1.0-rc.2](https://github.com/ueberdosis/tiptap/compare/v2.0.3...v2.1.0-rc.2) (2023-04-26)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee))
|
- **extension-link:** fix link not being kept when pasting url with link ([#3975](https://github.com/ueberdosis/tiptap/issues/3975)) ([e7d7d49](https://github.com/ueberdosis/tiptap/commit/e7d7d496376c8c11e24c342e20bd179a6ea7dcee))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12)
|
# [2.1.0-rc.1](https://github.com/ueberdosis/tiptap/compare/v2.1.0-rc.0...v2.1.0-rc.1) (2023-04-12)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337))
|
- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05)
|
# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb))
|
- clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb))
|
||||||
* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46))
|
- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0c1bba3](https://github.com/ueberdosis/tiptap/commit/0c1bba3137b535776bcef95ff3c55e13f5a2db46))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05)
|
# [2.1.0-rc.0](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.1.0-rc.0) (2023-04-05)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb))
|
- clear nodes when cursor at start of empty isolating parent ([#3943](https://github.com/ueberdosis/tiptap/issues/3943)) ([7278ee2](https://github.com/ueberdosis/tiptap/commit/7278ee2b05de2f96efddf3b1dc3bfd3d52262cbb))
|
||||||
* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([a78f8cd](https://github.com/ueberdosis/tiptap/commit/a78f8cd9646008e4db938fa3c22b0714c8bb5849))
|
- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([a78f8cd](https://github.com/ueberdosis/tiptap/commit/a78f8cd9646008e4db938fa3c22b0714c8bb5849))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.0.3](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.0.3) (2023-04-13)
|
## [2.0.3](https://github.com/ueberdosis/tiptap/compare/v2.0.2...v2.0.3) (2023-04-13)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337))
|
- **bubble-menu:** fix debounce not working with collab/collaboration cursor ([#3956](https://github.com/ueberdosis/tiptap/issues/3956)) ([e8cef04](https://github.com/ueberdosis/tiptap/commit/e8cef0404b5039ec2657536976b8b31931afd337))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.0.2](https://github.com/ueberdosis/tiptap/compare/v2.0.1...v2.0.2) (2023-04-03)
|
## [2.0.2](https://github.com/ueberdosis/tiptap/compare/v2.0.1...v2.0.2) (2023-04-03)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* add box-shadow to collab demo ([c5496c1](https://github.com/ueberdosis/tiptap/commit/c5496c1b27783150dafb5ebdf6bda43648a46316))
|
- add box-shadow to collab demo ([c5496c1](https://github.com/ueberdosis/tiptap/commit/c5496c1b27783150dafb5ebdf6bda43648a46316))
|
||||||
* landingpage demo ([#3925](https://github.com/ueberdosis/tiptap/issues/3925)) ([958925f](https://github.com/ueberdosis/tiptap/commit/958925f2560ca786cd0cf52b83b7ae51deb7dd77))
|
- landingpage demo ([#3925](https://github.com/ueberdosis/tiptap/issues/3925)) ([958925f](https://github.com/ueberdosis/tiptap/commit/958925f2560ca786cd0cf52b83b7ae51deb7dd77))
|
||||||
* Tiptap collab demo styling ([87840b0](https://github.com/ueberdosis/tiptap/commit/87840b0f0821ca65d9f104d9c90512021aa70113))
|
- Tiptap collab demo styling ([87840b0](https://github.com/ueberdosis/tiptap/commit/87840b0f0821ca65d9f104d9c90512021aa70113))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [2.0.1](https://github.com/ueberdosis/tiptap/compare/v2.0.0...v2.0.1) (2023-03-30)
|
## [2.0.1](https://github.com/ueberdosis/tiptap/compare/v2.0.0...v2.0.1) (2023-03-30)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0534f76](https://github.com/ueberdosis/tiptap/commit/0534f76401bf5399c01ca7f39d87f7221d91b4f7))
|
- Update peerDependencies to fix lerna version tasks ([#3914](https://github.com/ueberdosis/tiptap/issues/3914)) ([0534f76](https://github.com/ueberdosis/tiptap/commit/0534f76401bf5399c01ca7f39d87f7221d91b4f7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.220](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.219...v2.0.0-beta.220) (2023-02-28)
|
# [2.0.0-beta.220](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.219...v2.0.0-beta.220) (2023-02-28)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** fix destroyed view causing errors on dispatchTransaction ([#3799](https://github.com/ueberdosis/tiptap/issues/3799)) ([3c07ca0](https://github.com/ueberdosis/tiptap/commit/3c07ca0b9c48cef60d56acdd44812e20e05fc928))
|
- **core:** fix destroyed view causing errors on dispatchTransaction ([#3799](https://github.com/ueberdosis/tiptap/issues/3799)) ([3c07ca0](https://github.com/ueberdosis/tiptap/commit/3c07ca0b9c48cef60d56acdd44812e20e05fc928))
|
||||||
* **tests:** fix tests for lists ([02eec8a](https://github.com/ueberdosis/tiptap/commit/02eec8aaefc2709dc20f91c3c8f9eca84cddc12d))
|
- **tests:** fix tests for lists ([02eec8a](https://github.com/ueberdosis/tiptap/commit/02eec8aaefc2709dc20f91c3c8f9eca84cddc12d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.219](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.218...v2.0.0-beta.219) (2023-02-27)
|
# [2.0.0-beta.219](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.218...v2.0.0-beta.219) (2023-02-27)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** allow insertContentAt and insertContent text node arrays ([#3790](https://github.com/ueberdosis/tiptap/issues/3790)) ([0300630](https://github.com/ueberdosis/tiptap/commit/0300630a5b04b61d4eef8155f24ca0ef2d683966))
|
- **core:** allow insertContentAt and insertContent text node arrays ([#3790](https://github.com/ueberdosis/tiptap/issues/3790)) ([0300630](https://github.com/ueberdosis/tiptap/commit/0300630a5b04b61d4eef8155f24ca0ef2d683966))
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* [#3540](https://github.com/ueberdosis/tiptap/issues/3540) Ability to preserve marks on lists ([#3541](https://github.com/ueberdosis/tiptap/issues/3541)) ([36bb1e1](https://github.com/ueberdosis/tiptap/commit/36bb1e1041f91da6437272e7196702df868eae0f))
|
- [#3540](https://github.com/ueberdosis/tiptap/issues/3540) Ability to preserve marks on lists ([#3541](https://github.com/ueberdosis/tiptap/issues/3541)) ([36bb1e1](https://github.com/ueberdosis/tiptap/commit/36bb1e1041f91da6437272e7196702df868eae0f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.218](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.217...v2.0.0-beta.218) (2023-02-18)
|
# [2.0.0-beta.218](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.217...v2.0.0-beta.218) (2023-02-18)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.217](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.216...v2.0.0-beta.217) (2023-02-09)
|
# [2.0.0-beta.217](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.216...v2.0.0-beta.217) (2023-02-09)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.216](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.215...v2.0.0-beta.216) (2023-02-08)
|
# [2.0.0-beta.216](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.215...v2.0.0-beta.216) (2023-02-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.215](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.214...v2.0.0-beta.215) (2023-02-08)
|
# [2.0.0-beta.215](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.214...v2.0.0-beta.215) (2023-02-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.214](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.213...v2.0.0-beta.214) (2023-02-08)
|
# [2.0.0-beta.214](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.213...v2.0.0-beta.214) (2023-02-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.213](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.212...v2.0.0-beta.213) (2023-02-07)
|
# [2.0.0-beta.213](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.212...v2.0.0-beta.213) (2023-02-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.212](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.211...v2.0.0-beta.212) (2023-02-03)
|
# [2.0.0-beta.212](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.211...v2.0.0-beta.212) (2023-02-03)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.211](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.210...v2.0.0-beta.211) (2023-02-02)
|
# [2.0.0-beta.211](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.210...v2.0.0-beta.211) (2023-02-02)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.210](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.209...v2.0.0-beta.210) (2023-02-02)
|
# [2.0.0-beta.210](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.209...v2.0.0-beta.210) (2023-02-02)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **pm:** new prosemirror package for dependency resolving ([f387ad3](https://github.com/ueberdosis/tiptap/commit/f387ad3dd4c2b30eaea33fb0ba0b42e0cd39263b))
|
- **pm:** new prosemirror package for dependency resolving ([f387ad3](https://github.com/ueberdosis/tiptap/commit/f387ad3dd4c2b30eaea33fb0ba0b42e0cd39263b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.209](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.208...v2.0.0-beta.209) (2022-12-16)
|
# [2.0.0-beta.209](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.208...v2.0.0-beta.209) (2022-12-16)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.208](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.207...v2.0.0-beta.208) (2022-12-16)
|
# [2.0.0-beta.208](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.207...v2.0.0-beta.208) (2022-12-16)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.207](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.206...v2.0.0-beta.207) (2022-12-08)
|
# [2.0.0-beta.207](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.206...v2.0.0-beta.207) (2022-12-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.206](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.205...v2.0.0-beta.206) (2022-12-08)
|
# [2.0.0-beta.206](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.205...v2.0.0-beta.206) (2022-12-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.205](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.204...v2.0.0-beta.205) (2022-12-05)
|
# [2.0.0-beta.205](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.204...v2.0.0-beta.205) (2022-12-05)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.204](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.203...v2.0.0-beta.204) (2022-11-25)
|
# [2.0.0-beta.204](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.203...v2.0.0-beta.204) (2022-11-25)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **tests:** fix autolink validation test ([5150095](https://github.com/ueberdosis/tiptap/commit/5150095c6b510c080f4aa35f54d2387543f86da8))
|
- **tests:** fix autolink validation test ([5150095](https://github.com/ueberdosis/tiptap/commit/5150095c6b510c080f4aa35f54d2387543f86da8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.203](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.202...v2.0.0-beta.203) (2022-11-24)
|
# [2.0.0-beta.203](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.202...v2.0.0-beta.203) (2022-11-24)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **extension/table:** move dependency from @_ueberdosis to [@tiptap](https://github.com/tiptap) ([#3448](https://github.com/ueberdosis/tiptap/issues/3448)) ([31c3a9a](https://github.com/ueberdosis/tiptap/commit/31c3a9aad9eb37f445eadcd27135611291178ca6))
|
- **extension/table:** move dependency from @\_ueberdosis to [@tiptap](https://github.com/tiptap) ([#3448](https://github.com/ueberdosis/tiptap/issues/3448)) ([31c3a9a](https://github.com/ueberdosis/tiptap/commit/31c3a9aad9eb37f445eadcd27135611291178ca6))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.202](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.201...v2.0.0-beta.202) (2022-11-04)
|
# [2.0.0-beta.202](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.201...v2.0.0-beta.202) (2022-11-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.201](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.200...v2.0.0-beta.201) (2022-11-04)
|
# [2.0.0-beta.201](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.200...v2.0.0-beta.201) (2022-11-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.200](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.199...v2.0.0-beta.200) (2022-11-04)
|
# [2.0.0-beta.200](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.199...v2.0.0-beta.200) (2022-11-04)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.199](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.198...v2.0.0-beta.199) (2022-09-30)
|
# [2.0.0-beta.199](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.198...v2.0.0-beta.199) (2022-09-30)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.198](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.197...v2.0.0-beta.198) (2022-09-29)
|
# [2.0.0-beta.198](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.197...v2.0.0-beta.198) (2022-09-29)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.197](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.196...v2.0.0-beta.197) (2022-09-26)
|
# [2.0.0-beta.197](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.196...v2.0.0-beta.197) (2022-09-26)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **core:** Can() does not work for setting marks ([#3223](https://github.com/ueberdosis/tiptap/issues/3223)) ([17a41da](https://github.com/ueberdosis/tiptap/commit/17a41da5a7a14879cf490c81914084791c4c494c))
|
- **core:** Can() does not work for setting marks ([#3223](https://github.com/ueberdosis/tiptap/issues/3223)) ([17a41da](https://github.com/ueberdosis/tiptap/commit/17a41da5a7a14879cf490c81914084791c4c494c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.196](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.195...v2.0.0-beta.196) (2022-09-20)
|
# [2.0.0-beta.196](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.195...v2.0.0-beta.196) (2022-09-20)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.195](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.194...v2.0.0-beta.195) (2022-09-14)
|
# [2.0.0-beta.195](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.194...v2.0.0-beta.195) (2022-09-14)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **extension/bubble-menu:** :bug: fix bubble menu and floating menu being available when editor not editable ([#3195](https://github.com/ueberdosis/tiptap/issues/3195)) ([fa96749](https://github.com/ueberdosis/tiptap/commit/fa96749ce22ec67125da491cfeeb38623b9f0d6e))
|
- **extension/bubble-menu:** :bug: fix bubble menu and floating menu being available when editor not editable ([#3195](https://github.com/ueberdosis/tiptap/issues/3195)) ([fa96749](https://github.com/ueberdosis/tiptap/commit/fa96749ce22ec67125da491cfeeb38623b9f0d6e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.194](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.193...v2.0.0-beta.194) (2022-09-11)
|
# [2.0.0-beta.194](https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.193...v2.0.0-beta.194) (2022-09-11)
|
||||||
|
|
||||||
**Note:** Version bump only for package tiptap-demos
|
**Note:** Version bump only for package tiptap-demos
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [2.0.0-beta.193](https://github.com/ueberdosis/tiptap/compare/v0.1.2...v2.0.0-beta.193) (2022-09-10)
|
# [2.0.0-beta.193](https://github.com/ueberdosis/tiptap/compare/v0.1.2...v2.0.0-beta.193) (2022-09-10)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* bump documents ([43611ea](https://github.com/ueberdosis/tiptap/commit/43611ea2e70d3dc66ff907ba7ca377bf74814543))
|
- bump documents ([43611ea](https://github.com/ueberdosis/tiptap/commit/43611ea2e70d3dc66ff907ba7ca377bf74814543))
|
||||||
* disable broken tests for experiements with further todo message ([b8ae9e2](https://github.com/ueberdosis/tiptap/commit/b8ae9e27622857093c6ca539901956da5cc291e5))
|
- disable broken tests for experiements with further todo message ([b8ae9e2](https://github.com/ueberdosis/tiptap/commit/b8ae9e27622857093c6ca539901956da5cc291e5))
|
||||||
* don’t check for active node in wrapIn command, fix [#1059](https://github.com/ueberdosis/tiptap/issues/1059) ([170ec4b](https://github.com/ueberdosis/tiptap/commit/170ec4be5b3c8362890ca3100a223b505f788381))
|
- don’t check for active node in wrapIn command, fix [#1059](https://github.com/ueberdosis/tiptap/issues/1059) ([170ec4b](https://github.com/ueberdosis/tiptap/commit/170ec4be5b3c8362890ca3100a223b505f788381))
|
||||||
* **extension/collaboration:** :ambulance: pin y-prosemirror version to 1.0.20 to fix broken functionality with vue ([5989f3b](https://github.com/ueberdosis/tiptap/commit/5989f3b780bb64b2884d81dcd41a95d98a0714b2))
|
- **extension/collaboration:** :ambulance: pin y-prosemirror version to 1.0.20 to fix broken functionality with vue ([5989f3b](https://github.com/ueberdosis/tiptap/commit/5989f3b780bb64b2884d81dcd41a95d98a0714b2))
|
||||||
* fix RangeError bug when selecting all text, fix [#2490](https://github.com/ueberdosis/tiptap/issues/2490) ([70422dd](https://github.com/ueberdosis/tiptap/commit/70422dd107ed1ecdd8dfe41a8a93297124d2f1e0))
|
- fix RangeError bug when selecting all text, fix [#2490](https://github.com/ueberdosis/tiptap/issues/2490) ([70422dd](https://github.com/ueberdosis/tiptap/commit/70422dd107ed1ecdd8dfe41a8a93297124d2f1e0))
|
||||||
* **maintainment:** fix cjs issues with prosemirror-tables ([eb92597](https://github.com/ueberdosis/tiptap/commit/eb925976038fbf59f6ba333ccc57ea84113da00e))
|
- **maintainment:** fix cjs issues with prosemirror-tables ([eb92597](https://github.com/ueberdosis/tiptap/commit/eb925976038fbf59f6ba333ccc57ea84113da00e))
|
||||||
* remove some magic strings ([6c34dec](https://github.com/ueberdosis/tiptap/commit/6c34dec33ac39c9f037a0a72e4525f3fc6d422bf))
|
- remove some magic strings ([6c34dec](https://github.com/ueberdosis/tiptap/commit/6c34dec33ac39c9f037a0a72e4525f3fc6d422bf))
|
||||||
* **suggestion:** :bug: make clientrect prop optional as it can potentially be undefined ([#2813](https://github.com/ueberdosis/tiptap/issues/2813)) ([f019f70](https://github.com/ueberdosis/tiptap/commit/f019f70a19c34715e2d5c3921d348e11c7ac51a3)), closes [#2795](https://github.com/ueberdosis/tiptap/issues/2795)
|
- **suggestion:** :bug: make clientrect prop optional as it can potentially be undefined ([#2813](https://github.com/ueberdosis/tiptap/issues/2813)) ([f019f70](https://github.com/ueberdosis/tiptap/commit/f019f70a19c34715e2d5c3921d348e11c7ac51a3)), closes [#2795](https://github.com/ueberdosis/tiptap/issues/2795)
|
||||||
* temp fix collaboration demo ([4528756](https://github.com/ueberdosis/tiptap/commit/45287563f3cfb389095a2794cb2001d65e56d633))
|
- temp fix collaboration demo ([4528756](https://github.com/ueberdosis/tiptap/commit/45287563f3cfb389095a2794cb2001d65e56d633))
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* Add extension storage ([#2069](https://github.com/ueberdosis/tiptap/issues/2069)) ([7ffabf2](https://github.com/ueberdosis/tiptap/commit/7ffabf251c408a652eec1931cc78a8bd43cccb67))
|
- Add extension storage ([#2069](https://github.com/ueberdosis/tiptap/issues/2069)) ([7ffabf2](https://github.com/ueberdosis/tiptap/commit/7ffabf251c408a652eec1931cc78a8bd43cccb67))
|
||||||
* add getText() and generateText() methods (fix [#1428](https://github.com/ueberdosis/tiptap/issues/1428)) ([#1875](https://github.com/ueberdosis/tiptap/issues/1875)) ([fe6a3e7](https://github.com/ueberdosis/tiptap/commit/fe6a3e7491f6a42123d3d8a92ab588f2a40d7799))
|
- add getText() and generateText() methods (fix [#1428](https://github.com/ueberdosis/tiptap/issues/1428)) ([#1875](https://github.com/ueberdosis/tiptap/issues/1875)) ([fe6a3e7](https://github.com/ueberdosis/tiptap/commit/fe6a3e7491f6a42123d3d8a92ab588f2a40d7799))
|
||||||
* add some improvements to `CharacterCount` extension ([#2256](https://github.com/ueberdosis/tiptap/issues/2256)), fix [#1049](https://github.com/ueberdosis/tiptap/issues/1049), fix [#1550](https://github.com/ueberdosis/tiptap/issues/1550), fix [#1839](https://github.com/ueberdosis/tiptap/issues/1839), fix [#2245](https://github.com/ueberdosis/tiptap/issues/2245) ([5daa870](https://github.com/ueberdosis/tiptap/commit/5daa870b0906f0387fe07041681bc6f5b3774617))
|
- add some improvements to `CharacterCount` extension ([#2256](https://github.com/ueberdosis/tiptap/issues/2256)), fix [#1049](https://github.com/ueberdosis/tiptap/issues/1049), fix [#1550](https://github.com/ueberdosis/tiptap/issues/1550), fix [#1839](https://github.com/ueberdosis/tiptap/issues/1839), fix [#2245](https://github.com/ueberdosis/tiptap/issues/2245) ([5daa870](https://github.com/ueberdosis/tiptap/commit/5daa870b0906f0387fe07041681bc6f5b3774617))
|
||||||
* Add support for autolink ([#2226](https://github.com/ueberdosis/tiptap/issues/2226)) ([3d68981](https://github.com/ueberdosis/tiptap/commit/3d68981b47d087fff40549d2143eb952fc9e0a50))
|
- Add support for autolink ([#2226](https://github.com/ueberdosis/tiptap/issues/2226)) ([3d68981](https://github.com/ueberdosis/tiptap/commit/3d68981b47d087fff40549d2143eb952fc9e0a50))
|
||||||
* **extension-link:** :sparkles: add validate option to link extension ([23e67ad](https://github.com/ueberdosis/tiptap/commit/23e67adfa730df7364bc31220d0ed0e8ea522593)), closes [#2779](https://github.com/ueberdosis/tiptap/issues/2779)
|
- **extension-link:** :sparkles: add validate option to link extension ([23e67ad](https://github.com/ueberdosis/tiptap/commit/23e67adfa730df7364bc31220d0ed0e8ea522593)), closes [#2779](https://github.com/ueberdosis/tiptap/issues/2779)
|
||||||
* **extension/youtube:** :sparkles: new youtube embed extension ([#2814](https://github.com/ueberdosis/tiptap/issues/2814)) ([1c0554b](https://github.com/ueberdosis/tiptap/commit/1c0554b7c06d80145274353e58d56608b097fbe4))
|
- **extension/youtube:** :sparkles: new youtube embed extension ([#2814](https://github.com/ueberdosis/tiptap/issues/2814)) ([1c0554b](https://github.com/ueberdosis/tiptap/commit/1c0554b7c06d80145274353e58d56608b097fbe4))
|
||||||
* Integrate input rules and paste rules into the core ([#1997](https://github.com/ueberdosis/tiptap/issues/1997)) ([723b955](https://github.com/ueberdosis/tiptap/commit/723b955cecc5c92c8aad897ce16c60fb62976571))
|
- Integrate input rules and paste rules into the core ([#1997](https://github.com/ueberdosis/tiptap/issues/1997)) ([723b955](https://github.com/ueberdosis/tiptap/commit/723b955cecc5c92c8aad897ce16c60fb62976571))
|
||||||
* parseHTML for attributes should return the value instead of an object now, fix [#1863](https://github.com/ueberdosis/tiptap/issues/1863) ([8a3b47a](https://github.com/ueberdosis/tiptap/commit/8a3b47a529d28b28b50d634c6ff69b8e5aad3080))
|
- parseHTML for attributes should return the value instead of an object now, fix [#1863](https://github.com/ueberdosis/tiptap/issues/1863) ([8a3b47a](https://github.com/ueberdosis/tiptap/commit/8a3b47a529d28b28b50d634c6ff69b8e5aad3080))
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
d3
|
d3
|
||||||
|
highlight.js/lib/languages/css
|
||||||
|
highlight.js/lib/languages/javascript
|
||||||
|
highlight.js/lib/languages/typescript
|
||||||
|
highlight.js/lib/languages/xml
|
||||||
|
highlight.js/lib/core
|
||||||
linkifyjs
|
linkifyjs
|
||||||
lowlight
|
lowlight
|
||||||
lowlight/lib/core
|
|
||||||
prosemirror-commands
|
prosemirror-commands
|
||||||
prosemirror-dropcursor
|
prosemirror-dropcursor
|
||||||
prosemirror-gapcursor
|
prosemirror-gapcursor
|
||||||
@ -16,9 +20,13 @@ prosemirror-view
|
|||||||
react
|
react
|
||||||
react-dom
|
react-dom
|
||||||
react-dom/client
|
react-dom/client
|
||||||
|
use-sync-external-store/shim
|
||||||
|
use-sync-external-store/shim/with-selector
|
||||||
shiki
|
shiki
|
||||||
simplify-js
|
simplify-js
|
||||||
tippy.js
|
tippy.js
|
||||||
uuid
|
uuid
|
||||||
y-webrtc
|
y-webrtc
|
||||||
yjs
|
yjs
|
||||||
|
@hocuspocus/provider
|
||||||
|
@lifeomic/attempt
|
||||||
|
7330
demos/package-lock.json
generated
7330
demos/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "tiptap-demos",
|
"name": "tiptap-demos",
|
||||||
"version": "2.4.0",
|
"version": "2.5.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite --host",
|
"start": "vite --host",
|
||||||
"build:demos": "npm run ts && vite build",
|
"build:demos": "npm run ts && vite build",
|
||||||
@ -9,26 +10,28 @@
|
|||||||
"ts": "tsc --project tsconfig.base.json --noEmit && tsc --project tsconfig.react.json --noEmit && tsc --project tsconfig.vue-2.json --noEmit && tsc --project tsconfig.vue-3.json --noEmit"
|
"ts": "tsc --project tsconfig.base.json --noEmit && tsc --project tsconfig.react.json --noEmit && tsc --project tsconfig.vue-2.json --noEmit && tsc --project tsconfig.vue-3.json --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hocuspocus/provider": "^2.9.0",
|
"@hocuspocus/provider": "2.13.5",
|
||||||
"@lexical/react": "^0.11.1",
|
"@lexical/react": "^0.11.1",
|
||||||
|
"@shikijs/core": "1.10.3",
|
||||||
"d3": "^7.3.0",
|
"d3": "^7.3.0",
|
||||||
"fast-glob": "^3.2.11",
|
"fast-glob": "^3.2.11",
|
||||||
"highlight.js": "^11.6.0",
|
"highlight.js": "^11.10.0",
|
||||||
"lexical": "^0.11.1",
|
"lexical": "^0.11.1",
|
||||||
"lowlight": "^2.7.0",
|
"lowlight": "^3.1.0",
|
||||||
"remixicon": "^2.5.0",
|
"remixicon": "^2.5.0",
|
||||||
"shiki": "^0.10.0",
|
"shiki": "^1.10.3",
|
||||||
"simplify-js": "^1.2.4",
|
"simplify-js": "^1.2.4",
|
||||||
"y-prosemirror": "^1.2.5",
|
"y-prosemirror": "1.2.11",
|
||||||
"y-webrtc": "^10.3.0",
|
"y-webrtc": "^10.3.0",
|
||||||
"yjs": "^13.6.11"
|
"yjs": "13.6.18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.49",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"@vitejs/plugin-react": "^1.3.1",
|
"@vitejs/plugin-react": "^1.3.2",
|
||||||
"@vitejs/plugin-vue": "^1.10.2",
|
"@vitejs/plugin-vue": "^5.0.0",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
|
"esbuild": "0.21.5",
|
||||||
"iframe-resizer": "^4.3.2",
|
"iframe-resizer": "^4.3.2",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"postcss-import": "^15.1.0",
|
"postcss-import": "^15.1.0",
|
||||||
@ -36,13 +39,13 @@
|
|||||||
"react": "^18.0.0",
|
"react": "^18.0.0",
|
||||||
"react-dom": "^18.0.0",
|
"react-dom": "^18.0.0",
|
||||||
"sass": "^1.49.7",
|
"sass": "^1.49.7",
|
||||||
"svelte": "^3.49.0",
|
"svelte": "^4.2.19",
|
||||||
"tailwindcss": "^3.3.2",
|
"tailwindcss": "^3.3.2",
|
||||||
"typescript": "4.7.4",
|
"typescript": "^5.4.5",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"vite": "^2.9.18",
|
"vite": "^5.4.6",
|
||||||
"vite-plugin-checker": "^0.3.4",
|
"vite-plugin-checker": "^0.6.4",
|
||||||
"vue": "^3.0.5",
|
"vue": "^3.0.0",
|
||||||
"vue-router": "^4.0.11"
|
"vue-router": "^4.0.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<div class="overflow-hidden">
|
<div class="overflow-hidden">
|
||||||
<div
|
<div
|
||||||
class="bg-white"
|
class="bg-white"
|
||||||
|
:class="[hidePreview ? 'hidden' : '']"
|
||||||
>
|
>
|
||||||
<demo-frame
|
<demo-frame
|
||||||
:src="currentIframeUrl"
|
:src="currentIframeUrl"
|
||||||
@ -140,6 +141,10 @@ export default {
|
|||||||
return this.query.hideSource || false
|
return this.query.hideSource || false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hidePreview() {
|
||||||
|
return this.query.hidePreview || false
|
||||||
|
},
|
||||||
|
|
||||||
githubUrl() {
|
githubUrl() {
|
||||||
return `https://github.com/ueberdosis/tiptap/tree/main/demos/src/${this.name}`
|
return `https://github.com/ueberdosis/tiptap/tree/main/demos/src/${this.name}`
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,26 @@
|
|||||||
<script>
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
const showDemoList = process.env.NODE_ENV === 'development'
|
||||||
|
|
||||||
|
const searchValue = ref('')
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ul v-if="$route.path === '/'">
|
<template v-if="$route.path === '/'">
|
||||||
|
<input
|
||||||
|
class="w-full p-3 my-3 focus:outline-none border-b"
|
||||||
|
type="search"
|
||||||
|
placeholder="Search for a demo..."
|
||||||
|
autofocus
|
||||||
|
v-model="searchValue"
|
||||||
|
>
|
||||||
|
<ul v-if="showDemoList || listing">
|
||||||
<li
|
<li
|
||||||
class="p-5 border-b-2 border-black"
|
class="p-5 border-b-2 border-black"
|
||||||
v-for="route in $router.options.routes"
|
v-for="route in $router.options.routes.filter(route => searchValue === ''? true : route.props.name.toLowerCase().includes(searchValue.toLowerCase()))"
|
||||||
:key="route.path"
|
:key="route.path"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
@ -28,5 +42,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div v-else>Nothing to see here :-)</div>
|
||||||
|
</template>
|
||||||
<router-view v-else />
|
<router-view v-else />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
fromString(value) {
|
||||||
|
if (value === null) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.match(/^\d*(\.\d+)?$/)) {
|
||||||
|
return Number(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === 'true') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === 'false') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === 'null') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
query() {
|
||||||
|
return Object.fromEntries(Object
|
||||||
|
.entries(this.$route.query)
|
||||||
|
.map(([key, value]) => [key, this.fromString(value)]))
|
||||||
|
},
|
||||||
|
|
||||||
|
listing() {
|
||||||
|
return this.query.listing || false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
@ -1,15 +1,4 @@
|
|||||||
import * as shiki from 'shiki'
|
import * as shiki from 'shiki'
|
||||||
import onigasm from 'shiki/dist/onig.wasm?url'
|
|
||||||
import langCSS from 'shiki/languages/css.tmLanguage.json'
|
|
||||||
import langHTML from 'shiki/languages/html.tmLanguage.json'
|
|
||||||
import langJS from 'shiki/languages/javascript.tmLanguage.json'
|
|
||||||
import langJSX from 'shiki/languages/jsx.tmLanguage.json'
|
|
||||||
import langSCSS from 'shiki/languages/scss.tmLanguage.json'
|
|
||||||
import langTSX from 'shiki/languages/tsx.tmLanguage.json'
|
|
||||||
import langTS from 'shiki/languages/typescript.tmLanguage.json'
|
|
||||||
import langVue from 'shiki/languages/vue.tmLanguage.json'
|
|
||||||
import langVueHTML from 'shiki/languages/vue-html.tmLanguage.json'
|
|
||||||
import theme from 'shiki/themes/material-darker.json'
|
|
||||||
|
|
||||||
let highlighter = null
|
let highlighter = null
|
||||||
|
|
||||||
@ -18,64 +7,18 @@ async function init() {
|
|||||||
return highlighter
|
return highlighter
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrayBuffer = await fetch(onigasm).then(response => response.arrayBuffer())
|
highlighter = await shiki.createHighlighter({
|
||||||
|
themes: ['material-theme-darker'],
|
||||||
shiki.setOnigasmWASM(arrayBuffer)
|
|
||||||
|
|
||||||
highlighter = await shiki.getHighlighter({
|
|
||||||
theme,
|
|
||||||
langs: [
|
langs: [
|
||||||
{
|
'html',
|
||||||
id: 'html',
|
'js',
|
||||||
scopeName: langHTML.scopeName,
|
'jsx',
|
||||||
grammar: langHTML,
|
'ts',
|
||||||
embeddedLangs: ['javascript', 'css'],
|
'tsx',
|
||||||
},
|
'css',
|
||||||
{
|
'vue-html',
|
||||||
id: 'javascript',
|
'vue',
|
||||||
scopeName: langJS.scopeName,
|
'scss',
|
||||||
grammar: langJS,
|
|
||||||
aliases: ['js'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'jsx',
|
|
||||||
scopeName: langJSX.scopeName,
|
|
||||||
grammar: langJSX,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'typescript',
|
|
||||||
scopeName: langTS.scopeName,
|
|
||||||
grammar: langTS,
|
|
||||||
aliases: ['ts'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'tsx',
|
|
||||||
scopeName: langTSX.scopeName,
|
|
||||||
grammar: langTSX,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'vue-html',
|
|
||||||
scopeName: langVueHTML.scopeName,
|
|
||||||
grammar: langVueHTML,
|
|
||||||
embeddedLangs: ['vue', 'javascript'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'vue',
|
|
||||||
scopeName: langVue.scopeName,
|
|
||||||
grammar: langVue,
|
|
||||||
embeddedLangs: ['json', 'markdown', 'pug', 'haml', 'vue-html', 'sass', 'scss', 'less', 'stylus', 'postcss', 'css', 'typescript', 'coffee', 'javascript'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'css',
|
|
||||||
scopeName: langCSS.scopeName,
|
|
||||||
grammar: langCSS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'scss',
|
|
||||||
scopeName: langSCSS.scopeName,
|
|
||||||
grammar: langSCSS,
|
|
||||||
embeddedLangs: ['css'],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -84,9 +27,12 @@ async function init() {
|
|||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
self.addEventListener('message', async event => {
|
self.addEventListener('message', async event => {
|
||||||
init().then(() => {
|
init().then(async () => {
|
||||||
const { code, language } = event.data
|
const { code, language } = event.data
|
||||||
const html = highlighter.codeToHtml(code, language)
|
|
||||||
|
await highlighter.loadLanguage(language)
|
||||||
|
|
||||||
|
const html = highlighter.codeToHtml(code, { lang: language, theme: 'material-theme-darker' })
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
self.postMessage({ code, language, html })
|
self.postMessage({ code, language, html })
|
||||||
|
@ -1,4 +1,24 @@
|
|||||||
$colorBlack: #000;
|
/* Base HTML and global element styles*/
|
||||||
|
:root {
|
||||||
|
--white: #FFF;
|
||||||
|
--black: #2E2B29;
|
||||||
|
--black-contrast: #110F0E;
|
||||||
|
--gray-1: rgba(61, 37, 20, 0.05);
|
||||||
|
--gray-2: rgba(61, 37, 20, 0.08);
|
||||||
|
--gray-3: rgba(61, 37, 20, 0.12);
|
||||||
|
--gray-4: rgba(53, 38, 28, 0.30);
|
||||||
|
--gray-5: rgba(28, 25, 23, 0.60);
|
||||||
|
--green: #22C55E;
|
||||||
|
--purple: #6A00F5;
|
||||||
|
--purple-contrast: #5800CC;
|
||||||
|
--purple-light: rgba(88, 5, 255, 0.05);
|
||||||
|
--yellow-contrast: #FACC15;
|
||||||
|
--yellow: rgba(250, 204, 21, 0.4);
|
||||||
|
--yellow-light: #FFFAE5;
|
||||||
|
--red: #FF5C33;
|
||||||
|
--red-light: #FFEBE5;
|
||||||
|
--shadow: 0px 12px 33px 0px rgba(0, 0, 0, 0.06), 0px 3.618px 9.949px 0px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
@ -9,32 +29,46 @@ $colorBlack: #000;
|
|||||||
html {
|
html {
|
||||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 1rem;
|
min-height: 25rem;
|
||||||
min-height: 10rem;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tiptap {
|
||||||
|
caret-color: var(--purple);
|
||||||
|
margin: 1.5rem;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom scrollbar styles */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
border: 4px solid transparent;
|
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
border-radius: 8px;
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
border: 4px solid rgba(0, 0, 0, 0);
|
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
border-radius: 8px;
|
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
border: 4px solid rgba(0, 0, 0, 0);
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:hover::-webkit-scrollbar-thumb {
|
:hover::-webkit-scrollbar-thumb {
|
||||||
@ -47,37 +81,302 @@ body {
|
|||||||
|
|
||||||
::-webkit-scrollbar-button {
|
::-webkit-scrollbar-button {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-corner {
|
::-webkit-scrollbar-corner {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specific element and component styles */
|
||||||
button,
|
button,
|
||||||
input,
|
input,
|
||||||
select {
|
select,
|
||||||
font-size: inherit;
|
textarea {
|
||||||
|
background: var(--gray-2);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: none;
|
||||||
|
color: var(--black);
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
color: black;
|
font-size: 0.875rem;
|
||||||
margin: 0.1rem;
|
font-weight: 500;
|
||||||
border: 1px solid black;
|
line-height: 1.15;
|
||||||
border-radius: 0.3rem;
|
margin: none;
|
||||||
padding: 0.1rem 0.4rem;
|
padding: 0.375rem 0.625rem;
|
||||||
background: white;
|
transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1);
|
||||||
accent-color: black;
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
color: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
&[disabled] {
|
&[disabled] {
|
||||||
opacity: 0.3;
|
background: var(--gray-1);
|
||||||
|
color: var(--gray-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
accent-color: var(--purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: var(--black);
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
background: var(--gray-1);
|
||||||
|
color: var(--gray-4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tiptap:focus {
|
&.is-active {
|
||||||
|
background: var(--purple);
|
||||||
|
color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--purple-contrast);
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not([disabled]),
|
||||||
|
select:not([disabled]) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
textarea {
|
||||||
|
background-color: unset;
|
||||||
|
border: 1px solid var(--gray-3);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--black);
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--gray-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: unset;
|
||||||
|
border-color: var(--gray-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible, &:focus {
|
||||||
|
border-color: var(--purple);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.is-active {
|
|
||||||
background: black;
|
select {
|
||||||
color: white;
|
/* reset */
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Gray" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 0.1rem center;
|
||||||
|
background-size: 1.25rem 1.25rem;
|
||||||
|
padding-right: 1.25rem;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--yellow-light);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
border: 1px solid var(--gray-2);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: 0.25rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
padding: 0.3rem 0.5rem;
|
||||||
|
|
||||||
|
&.purple-spinner,
|
||||||
|
&.error {
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
background-color: var(--gray-1);
|
||||||
|
border: 1px solid var(--gray-3);
|
||||||
|
border-radius: 2rem;
|
||||||
|
color: var(--gray-5);
|
||||||
|
font-size: 0.625rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.purple-spinner {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
background-image: url("data:image/svg+xml;utf8,<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='28px' height='30px' viewBox='0 0 24 30' style='enable-background:new 0 0 50 50;' xml:space='preserve'><rect x='0' y='10' width='6' height='10' fill='%236A00F5' rx='3' ry='3'><animateTransform attributeType='xml' attributeName='transform' type='translate' values='0 0; 0 5; 0 -5; 0 0' begin='0' dur='0.6s' repeatCount='indefinite'/></rect><rect x='10' y='10' width='6' height='10' fill='%236A00F5' rx='3' ry='3'><animateTransform attributeType='xml' attributeName='transform' type='translate' values='0 0; 0 5; 0 -5; 0 0' begin='0.2s' dur='0.6s' repeatCount='indefinite'/></rect><rect x='20' y='10' width='6' height='10' fill='%236A00F5' rx='3' ry='3'><animateTransform attributeType='xml' attributeName='transform' type='translate' values='0 0; 0 5; 0 -5; 0 0' begin='0.4s' dur='0.6s' repeatCount='indefinite'/></rect></svg>");
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background-color: var(--red-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label,
|
||||||
|
.label-small,
|
||||||
|
.label-large {
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-small {
|
||||||
|
color: var(--gray-5);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-large {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-3);
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
background-color: var(--gray-2);
|
||||||
|
border: 1px solid var(--gray-2);
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.6rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
padding: 0.1rem 0.25rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout and structure */
|
||||||
|
#app,
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
align-items: flex-start;
|
||||||
|
background-color: var(--white);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
.sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-node-view-wrapper] > .control-group {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-group {
|
||||||
|
align-items: center;
|
||||||
|
background: var(--gray-2);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 0.125rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
color: var(--gray-5);
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
gap: 0.25rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
padding: 0 0.375rem;
|
||||||
|
transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1);
|
||||||
|
|
||||||
|
&:has(input:checked) {
|
||||||
|
background-color: var(--white);
|
||||||
|
color: var(--black-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
display: none;
|
||||||
|
margin: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-group {
|
||||||
|
background-color: var(--gray-1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
label {
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,12 @@ export default function init(name: string, source: any) {
|
|||||||
|
|
||||||
import(`../src/${demoCategory}/${demoName}/${frameworkName}/index.vue`)
|
import(`../src/${demoCategory}/${demoName}/${frameworkName}/index.vue`)
|
||||||
.then(module => {
|
.then(module => {
|
||||||
createApp(module.default).mount('#app')
|
const app = createApp(module.default)
|
||||||
|
|
||||||
|
if (typeof module.configureApp === 'function') {
|
||||||
|
module.configureApp(app)
|
||||||
|
}
|
||||||
|
app.mount('#app')
|
||||||
debug()
|
debug()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,6 @@ import StarterKit from '@tiptap/starter-kit'
|
|||||||
import React, { useCallback } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
|
|
||||||
const MenuBar = ({ editor }) => {
|
const MenuBar = ({ editor }) => {
|
||||||
if (!editor) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const onCutToStart = useCallback(() => {
|
const onCutToStart = useCallback(() => {
|
||||||
editor.chain().cut({ from: editor.state.selection.$from.pos, to: editor.state.selection.$to.pos }, 1).run()
|
editor.chain().cut({ from: editor.state.selection.$from.pos, to: editor.state.selection.$to.pos }, 1).run()
|
||||||
}, [editor])
|
}, [editor])
|
||||||
@ -20,11 +16,17 @@ const MenuBar = ({ editor }) => {
|
|||||||
editor.chain().cut({ from: editor.state.selection.$from.pos, to: editor.state.selection.$to.pos }, editor.state.doc.nodeSize - 2).run()
|
editor.chain().cut({ from: editor.state.selection.$from.pos, to: editor.state.selection.$to.pos }, editor.state.doc.nodeSize - 2).run()
|
||||||
}, [editor])
|
}, [editor])
|
||||||
|
|
||||||
|
if (!editor) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={onCutToStart}>Cut content to start of document</button>
|
<button onClick={onCutToStart}>Cut content to start of document</button>
|
||||||
<button onClick={onCutToEnd}>Cut content to end of document</button>
|
<button onClick={onCutToEnd}>Cut content to end of document</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +51,7 @@ export default () => {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<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:
|
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>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -77,9 +79,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -21,41 +21,41 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -64,40 +64,40 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -109,35 +109,35 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import './styles.scss'
|
import './styles.scss'
|
||||||
|
|
||||||
import { Color } from '@tiptap/extension-color'
|
import { Color } from '@tiptap/extension-color'
|
||||||
|
import Link from '@tiptap/extension-link'
|
||||||
import ListItem from '@tiptap/extension-list-item'
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
import TextStyle from '@tiptap/extension-text-style'
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
import { EditorProvider, useCurrentEditor } from '@tiptap/react'
|
import { EditorProvider, useCurrentEditor } from '@tiptap/react'
|
||||||
@ -29,23 +30,26 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button data-test-id="html-content" onClick={() => editor.chain().insertContent(htmlContent).focus().run()}>
|
<button data-test-id="html-content" onClick={() => editor.chain().insertContent(htmlContent).focus().run()}>
|
||||||
Insert html content
|
Insert HTML content
|
||||||
</button>
|
</button>
|
||||||
<button data-test-id="html-content-spans" onClick={() => editor.chain().insertContent('<p><b>Hello</b> <i>World</i></p>').focus().run()}>
|
<button data-test-id="html-content-spans" onClick={() => editor.chain().insertContent('<p><b>Hello</b> <i>World</i></p>').focus().run()}>
|
||||||
Insert html with span tags content
|
Insert HTML with span tags content
|
||||||
</button>
|
</button>
|
||||||
<button data-test-id="text-content" onClick={() => editor.chain().insertContent(textContent).focus().run()}>
|
<button data-test-id="text-content" onClick={() => editor.chain().insertContent(textContent).focus().run()}>
|
||||||
Insert text content
|
Insert text content
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensions = [
|
const extensions = [
|
||||||
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||||
TextStyle.configure({ types: [ListItem.name] }),
|
TextStyle.configure({ types: [ListItem.name] }),
|
||||||
|
Link,
|
||||||
StarterKit.configure({
|
StarterKit.configure({
|
||||||
bulletList: {
|
bulletList: {
|
||||||
keepMarks: true,
|
keepMarks: true,
|
||||||
|
@ -11,7 +11,7 @@ context('/src/Commands/InsertContent/React/', () => {
|
|||||||
cy.get('button[data-test-id="html-content"]').click()
|
cy.get('button[data-test-id="html-content"]').click()
|
||||||
|
|
||||||
// check if the content html is correct
|
// check if the content html is correct
|
||||||
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p><p>This is a paragraph<br>with a break.</p><p>And this is some additional string content.</p>')
|
cy.get('.tiptap').should('contain.html', '<h1><a target="_blank" rel="noopener noreferrer nofollow" href="https://tiptap.dev/">Tiptap</a></h1><p><strong>Hello World</strong></p><p>This is a paragraph<br>with a break.</p><p>And this is some additional string content.</p>')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should keep spaces inbetween tags in html content', () => {
|
it('should keep spaces inbetween tags in html content', () => {
|
||||||
@ -41,4 +41,78 @@ context('/src/Commands/InsertContent/React/', () => {
|
|||||||
cy.get('.tiptap').should('contain.html', '<pre><code>foo\nbar</code></pre>')
|
cy.get('.tiptap').should('contain.html', '<pre><code>foo\nbar</code></pre>')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should keep newlines and tabs', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('<p>Hello\n\tworld\n\t\thow\n\t\t\tnice.\ntest\tOK</p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello\n\tworld\n\t\thow\n\t\t\tnice.\ntest\tOK</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should keep newlines and tabs', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('<h1>Tiptap</h1>\n<p><strong>Hello World</strong></p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting nothing', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('')
|
||||||
|
cy.get('.tiptap').should('contain.html', '')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting a partial HTML tag', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('<p>foo')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>foo</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting an incomplete HTML tag', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('foo<p')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>foo<p</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting a list', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('<ul><li>ABC</li><li>123</li></ul>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<ul><li><p>ABC</p></li><li><p>123</p></li></ul>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should remove newlines and tabs when parseOptions.preserveWhitespace=false', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.insertContent('\n<h1>Tiptap</h1><p><strong>Hello\n World</strong>\n</p>\n', { parseOptions: { preserveWhitespace: false } })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respect editor.options.parseOptions if defined to be `false`', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.options.parseOptions = { preserveWhitespace: false }
|
||||||
|
editor.commands.insertContent('\n<h1>Tiptap</h1><p><strong>Hello\n World</strong>\n</p>\n')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respect editor.options.parseOptions if defined to be `full`', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.options.parseOptions = { preserveWhitespace: 'full' }
|
||||||
|
editor.commands.insertContent('\n<h1>Tiptap</h1><p><strong>Hello\n World</strong>\n</p>\n')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello\n World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respect editor.options.parseOptions if defined to be `true`', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.options.parseOptions = { preserveWhitespace: true }
|
||||||
|
editor.commands.insertContent('<h1>Tiptap</h1><p><strong>Hello\n World</strong>\n</p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,30 +14,27 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<label>
|
||||||
onClick={() => setUseInputRules(prev => !prev)}
|
<input
|
||||||
style={{
|
type="checkbox"
|
||||||
color: useInputRules ? 'white' : 'inherit',
|
checked={useInputRules}
|
||||||
backgroundColor: useInputRules ? 'black' : 'transparent',
|
onChange={() => setUseInputRules(prev => !prev)}
|
||||||
}}
|
/>
|
||||||
>
|
Apply input rules
|
||||||
Apply Input Rules
|
</label>
|
||||||
</button>
|
<label>
|
||||||
<button
|
<input
|
||||||
onClick={() => setUsePasteRules(prev => !prev)}
|
type="checkbox"
|
||||||
style={{
|
checked={usePasteRules}
|
||||||
color: usePasteRules ? 'white' : 'inherit',
|
onChange={() => setUsePasteRules(prev => !prev)}
|
||||||
backgroundColor: usePasteRules ? 'black' : 'transparent',
|
/>
|
||||||
}}
|
Apply paste rules
|
||||||
>
|
</label>
|
||||||
Apply Paste Rules
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<div className="button-group">
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
editor
|
editor
|
||||||
@ -161,7 +158,8 @@ const MenuBar = () => {
|
|||||||
>
|
>
|
||||||
Insert "*this is a test*"
|
Insert "*this is a test*"
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
demos/src/Commands/SetContent/React/index.jsx
Normal file
31
demos/src/Commands/SetContent/React/index.jsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import './styles.scss'
|
||||||
|
|
||||||
|
import { Color } from '@tiptap/extension-color'
|
||||||
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
|
import Mentions from '@tiptap/extension-mention'
|
||||||
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
|
import { EditorProvider } from '@tiptap/react'
|
||||||
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const extensions = [
|
||||||
|
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||||
|
TextStyle.configure({ types: [ListItem.name] }),
|
||||||
|
StarterKit.configure({
|
||||||
|
bulletList: {
|
||||||
|
keepMarks: true,
|
||||||
|
},
|
||||||
|
orderedList: {
|
||||||
|
keepMarks: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Mentions,
|
||||||
|
]
|
||||||
|
|
||||||
|
const content = ''
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (
|
||||||
|
<EditorProvider extensions={extensions} content={content}></EditorProvider>
|
||||||
|
)
|
||||||
|
}
|
181
demos/src/Commands/SetContent/React/index.spec.js
Normal file
181
demos/src/Commands/SetContent/React/index.spec.js
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
context('/src/Commands/SetContent/React/', () => {
|
||||||
|
before(() => {
|
||||||
|
cy.visit('/src/Commands/SetContent/React/')
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should insert raw text content', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('Hello World.')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello World.</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should insert raw JSON content', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent({ type: 'paragraph', content: [{ type: 'text', text: 'Hello World.' }] })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello World.</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should insert a Prosemirror Node as content', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent(editor.schema.node('paragraph', null, editor.schema.text('Hello World.')))
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello World.</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should insert a Prosemirror Fragment as content', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent(editor.schema.node('doc', null, editor.schema.node('paragraph', null, editor.schema.text('Hello World.'))).content)
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello World.</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should emit updates', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
let updateCount = 0
|
||||||
|
const callback = () => {
|
||||||
|
updateCount += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.on('update', callback)
|
||||||
|
// emit an update
|
||||||
|
editor.commands.setContent('Hello World.', true)
|
||||||
|
expect(updateCount).to.equal(1)
|
||||||
|
|
||||||
|
updateCount = 0
|
||||||
|
// do not emit an update
|
||||||
|
editor.commands.setContent('Hello World again.', false)
|
||||||
|
expect(updateCount).to.equal(0)
|
||||||
|
editor.off('update', callback)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should insert more complex html content', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<h1>Welcome to Tiptap</h1><p>This is a paragraph.</p><ul><li><p>List Item A</p></li><li><p>List Item B</p><ul><li><p>Subchild</p></li></ul></li></ul>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Welcome to Tiptap</h1><p>This is a paragraph.</p><ul><li><p>List Item A</p></li><li><p>List Item B</p><ul><li><p>Subchild</p></li></ul></li></ul>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should remove newlines and tabs', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p>Hello\n\tworld\n\t\thow\n\t\t\tnice.</p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello world how nice.</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should keep newlines and tabs when preserveWhitespace = full', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p>Hello\n\tworld\n\t\thow\n\t\t\tnice.</p>', false, { preserveWhitespace: 'full' })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Hello\n\tworld\n\t\thow\n\t\t\tnice.</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should overwrite existing content', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p>Initial Content</p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Initial Content</p>')
|
||||||
|
})
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p>Overwritten Content</p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Overwritten Content</p>')
|
||||||
|
})
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('Content without tags')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>Content without tags</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should insert mentions', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p><span data-type="mention" data-id="1" data-label="John Doe">@John Doe</span></p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<span data-type="mention" data-id="1" data-label="John Doe" contenteditable="false">@John Doe</span>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should remove newlines and tabs between html fragments', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<h1>Tiptap</h1>\n\t<p><strong>Hello World</strong></p>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO I'm not certain about this behavior and what it should do...
|
||||||
|
// This exists in insertContentAt as well
|
||||||
|
it('should keep newlines and tabs between html fragments when preserveWhitespace = full', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<h1>Tiptap</h1>\n\t<p><strong>Hello World</strong></p>', false, { preserveWhitespace: 'full' })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p>\n\t</p><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting nothing', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('')
|
||||||
|
cy.get('.tiptap').should('contain.html', '')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting nothing when preserveWhitespace = full', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('', false, { preserveWhitespace: 'full' })
|
||||||
|
cy.get('.tiptap').should('contain.html', '')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting a partial HTML tag', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p>foo')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>foo</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting a partial HTML tag when preserveWhitespace = full', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<p>foo', false, { preserveWhitespace: 'full' })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>foo</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('will remove an incomplete HTML tag', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('foo<p')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>foo</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO I'm not certain about this behavior and what it should do...
|
||||||
|
// This exists in insertContentAt as well
|
||||||
|
it('should allow inserting an incomplete HTML tag when preserveWhitespace = full', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('foo<p', false, { preserveWhitespace: 'full' })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<p>foo<p</p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting a list', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<ul><li>ABC</li><li>123</li></ul>')
|
||||||
|
cy.get('.tiptap').should('contain.html', '<ul><li><p>ABC</p></li><li><p>123</p></li></ul>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should allow inserting a list when preserveWhitespace = full', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('<ul><li>ABC</li><li>123</li></ul>', false, { preserveWhitespace: 'full' })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<ul><li><p>ABC</p></li><li><p>123</p></li></ul>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should remove newlines and tabs when parseOptions.preserveWhitespace=false', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
editor.commands.setContent('\n<h1>Tiptap</h1><p><strong>Hello\n World</strong>\n</p>\n', false, { preserveWhitespace: false })
|
||||||
|
cy.get('.tiptap').should('contain.html', '<h1>Tiptap</h1><p><strong>Hello World</strong></p>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
56
demos/src/Commands/SetContent/React/styles.scss
Normal file
56
demos/src/Commands/SetContent/React/styles.scss
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* Basic editor styles */
|
||||||
|
.tiptap {
|
||||||
|
> * + * {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
209
demos/src/Demos/CollaborationSplitPane/React/Editor.jsx
Normal file
209
demos/src/Demos/CollaborationSplitPane/React/Editor.jsx
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import CharacterCount from '@tiptap/extension-character-count'
|
||||||
|
import Collaboration from '@tiptap/extension-collaboration'
|
||||||
|
import CollaborationCursor from '@tiptap/extension-collaboration-cursor'
|
||||||
|
import Highlight from '@tiptap/extension-highlight'
|
||||||
|
import TaskItem from '@tiptap/extension-task-item'
|
||||||
|
import TaskList from '@tiptap/extension-task-list'
|
||||||
|
import { EditorContent, useEditor } from '@tiptap/react'
|
||||||
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
const colors = [
|
||||||
|
'#958DF1',
|
||||||
|
'#F98181',
|
||||||
|
'#FBBC88',
|
||||||
|
'#FAF594',
|
||||||
|
'#70CFF8',
|
||||||
|
'#94FADB',
|
||||||
|
'#B9F18D',
|
||||||
|
'#C3E2C2',
|
||||||
|
'#EAECCC',
|
||||||
|
'#AFC8AD',
|
||||||
|
'#EEC759',
|
||||||
|
'#9BB8CD',
|
||||||
|
'#FF90BC',
|
||||||
|
'#FFC0D9',
|
||||||
|
'#DC8686',
|
||||||
|
'#7ED7C1',
|
||||||
|
'#F3EEEA',
|
||||||
|
'#89B9AD',
|
||||||
|
'#D0BFFF',
|
||||||
|
'#FFF8C9',
|
||||||
|
'#CBFFA9',
|
||||||
|
'#9BABB8',
|
||||||
|
'#E3F4F4',
|
||||||
|
]
|
||||||
|
const names = [
|
||||||
|
'Lea Thompson',
|
||||||
|
'Cyndi Lauper',
|
||||||
|
'Tom Cruise',
|
||||||
|
'Madonna',
|
||||||
|
'Jerry Hall',
|
||||||
|
'Joan Collins',
|
||||||
|
'Winona Ryder',
|
||||||
|
'Christina Applegate',
|
||||||
|
'Alyssa Milano',
|
||||||
|
'Molly Ringwald',
|
||||||
|
'Ally Sheedy',
|
||||||
|
'Debbie Harry',
|
||||||
|
'Olivia Newton-John',
|
||||||
|
'Elton John',
|
||||||
|
'Michael J. Fox',
|
||||||
|
'Axl Rose',
|
||||||
|
'Emilio Estevez',
|
||||||
|
'Ralph Macchio',
|
||||||
|
'Rob Lowe',
|
||||||
|
'Jennifer Grey',
|
||||||
|
'Mickey Rourke',
|
||||||
|
'John Cusack',
|
||||||
|
'Matthew Broderick',
|
||||||
|
'Justine Bateman',
|
||||||
|
'Lisa Bonet',
|
||||||
|
]
|
||||||
|
|
||||||
|
const defaultContent = `
|
||||||
|
<p>Hi 👋, this is a collaborative document.</p>
|
||||||
|
<p>Feel free to edit and collaborate in real-time!</p>
|
||||||
|
`
|
||||||
|
|
||||||
|
const getRandomElement = list => list[Math.floor(Math.random() * list.length)]
|
||||||
|
|
||||||
|
const getRandomColor = () => getRandomElement(colors)
|
||||||
|
const getRandomName = () => getRandomElement(names)
|
||||||
|
|
||||||
|
const getInitialUser = () => {
|
||||||
|
return {
|
||||||
|
name: getRandomName(),
|
||||||
|
color: getRandomColor(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Editor = ({
|
||||||
|
ydoc, provider, room,
|
||||||
|
}) => {
|
||||||
|
const [status, setStatus] = useState('connecting')
|
||||||
|
const [currentUser, setCurrentUser] = useState(getInitialUser)
|
||||||
|
|
||||||
|
const editor = useEditor({
|
||||||
|
enableContentCheck: true,
|
||||||
|
onContentError: ({ disableCollaboration }) => {
|
||||||
|
disableCollaboration()
|
||||||
|
},
|
||||||
|
onCreate: ({ editor: currentEditor }) => {
|
||||||
|
provider.on('synced', () => {
|
||||||
|
if (currentEditor.isEmpty) {
|
||||||
|
currentEditor.commands.setContent(defaultContent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
extensions: [
|
||||||
|
StarterKit.configure({
|
||||||
|
history: false,
|
||||||
|
}),
|
||||||
|
Highlight,
|
||||||
|
TaskList,
|
||||||
|
TaskItem,
|
||||||
|
CharacterCount.extend().configure({
|
||||||
|
limit: 10000,
|
||||||
|
}),
|
||||||
|
Collaboration.extend().configure({
|
||||||
|
document: ydoc,
|
||||||
|
}),
|
||||||
|
CollaborationCursor.extend().configure({
|
||||||
|
provider,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update status changes
|
||||||
|
const statusHandler = event => {
|
||||||
|
setStatus(event.status)
|
||||||
|
}
|
||||||
|
|
||||||
|
provider.on('status', statusHandler)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
provider.off('status', statusHandler)
|
||||||
|
}
|
||||||
|
}, [provider])
|
||||||
|
|
||||||
|
// Save current user to localStorage and emit to editor
|
||||||
|
useEffect(() => {
|
||||||
|
if (editor && currentUser) {
|
||||||
|
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
||||||
|
editor.chain().focus().updateUser(currentUser).run()
|
||||||
|
}
|
||||||
|
}, [editor, currentUser])
|
||||||
|
|
||||||
|
const setName = useCallback(() => {
|
||||||
|
const name = (window.prompt('Name', currentUser.name) || '').trim().substring(0, 32)
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
return setCurrentUser({ ...currentUser, name })
|
||||||
|
}
|
||||||
|
}, [currentUser])
|
||||||
|
|
||||||
|
if (!editor) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="column-half">
|
||||||
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
|
<button
|
||||||
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Bold
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Italic
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Strike
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Bullet list
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Code
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<EditorContent editor={editor} className="main-group" />
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="collab-status-group"
|
||||||
|
data-state={status === 'connected' ? 'online' : 'offline'}
|
||||||
|
>
|
||||||
|
<label>
|
||||||
|
{status === 'connected'
|
||||||
|
? `${editor.storage.collaborationCursor.users.length} user${
|
||||||
|
editor.storage.collaborationCursor.users.length === 1 ? '' : 's'
|
||||||
|
} online in ${room}`
|
||||||
|
: 'offline'}
|
||||||
|
</label>
|
||||||
|
<button style={{ '--color': currentUser.color }} onClick={setName}>
|
||||||
|
✎ {currentUser.name}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Editor
|
39
demos/src/Demos/CollaborationSplitPane/React/index.jsx
Normal file
39
demos/src/Demos/CollaborationSplitPane/React/index.jsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import './styles.scss'
|
||||||
|
|
||||||
|
import { TiptapCollabProvider } from '@hocuspocus/provider'
|
||||||
|
import * as Y from 'yjs'
|
||||||
|
|
||||||
|
import Editor from './Editor.jsx'
|
||||||
|
|
||||||
|
const appId = '7j9y6m10'
|
||||||
|
const room = `room.${new Date()
|
||||||
|
.getFullYear()
|
||||||
|
.toString()
|
||||||
|
.slice(-2)}${new Date().getMonth() + 1}${new Date().getDate()}-ok`
|
||||||
|
|
||||||
|
// ydoc and provider for Editor A
|
||||||
|
const ydocA = new Y.Doc()
|
||||||
|
const providerA = new TiptapCollabProvider({
|
||||||
|
appId,
|
||||||
|
name: room,
|
||||||
|
document: ydocA,
|
||||||
|
})
|
||||||
|
|
||||||
|
// ydoc and provider for Editor B
|
||||||
|
const ydocB = new Y.Doc()
|
||||||
|
const providerB = new TiptapCollabProvider({
|
||||||
|
appId,
|
||||||
|
name: room,
|
||||||
|
document: ydocB,
|
||||||
|
})
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return (
|
||||||
|
<div className="col-group">
|
||||||
|
<Editor provider={providerA} ydoc={ydocA} room={room} />
|
||||||
|
<Editor provider={providerB} ydoc={ydocB} room={room} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
24
demos/src/Demos/CollaborationSplitPane/React/index.spec.js
Normal file
24
demos/src/Demos/CollaborationSplitPane/React/index.spec.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
context('/src/Demos/CollaborationSplitPane/React/', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/src/Demos/CollaborationSplitPane/React/')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have a working tiptap instance', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
expect(editor).to.not.be.null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have a ydoc', () => {
|
||||||
|
cy.get('.tiptap').then(([{ editor }]) => {
|
||||||
|
/**
|
||||||
|
* @type {import('yjs').Doc}
|
||||||
|
*/
|
||||||
|
const yDoc = editor.extensionManager.extensions.find(a => a.name === 'collaboration').options.document
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
expect(yDoc).to.not.be.null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
280
demos/src/Demos/CollaborationSplitPane/React/styles.scss
Normal file
280
demos/src/Demos/CollaborationSplitPane/React/styles.scss
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/* Basic editor styles */
|
||||||
|
.tiptap {
|
||||||
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlight specific styles */
|
||||||
|
mark {
|
||||||
|
background-color: #FAF594;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Task list specific styles */
|
||||||
|
ul[data-type="taskList"] {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul[data-type="taskList"] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give a remote user a caret */
|
||||||
|
.collaboration-cursor__caret {
|
||||||
|
border-left: 1px solid #0d0d0d;
|
||||||
|
border-right: 1px solid #0d0d0d;
|
||||||
|
margin-left: -1px;
|
||||||
|
margin-right: -1px;
|
||||||
|
pointer-events: none;
|
||||||
|
position: relative;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Render the username above the caret */
|
||||||
|
.collaboration-cursor__label {
|
||||||
|
border-radius: 3px 3px 3px 0;
|
||||||
|
color: #0d0d0d;
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
left: -1px;
|
||||||
|
line-height: normal;
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
position: absolute;
|
||||||
|
top: -1.4em;
|
||||||
|
user-select: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
@media (max-width: 540px) {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Column-half */
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-half {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-left: 1px solid var(--gray-3);
|
||||||
|
|
||||||
|
@media (max-width: 540px) {
|
||||||
|
border-left: none;
|
||||||
|
border-top: 1px solid var(--gray-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .main-group {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collaboration status */
|
||||||
|
.collab-status-group {
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--white);
|
||||||
|
border-top: 1px solid var(--gray-3);
|
||||||
|
bottom: 0;
|
||||||
|
color: var(--gray-5);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 400;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.375rem 0.5rem 0.375rem 1rem;
|
||||||
|
position: sticky;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
button {
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
align-self: stretch;
|
||||||
|
background: none;
|
||||||
|
display: -webkit-box;
|
||||||
|
flex-shrink: 1;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0.25rem 0.375rem;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background-color: var(--color);
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
content: "";
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
opacity: 0.5;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
transition: all 0.2s cubic-bezier(0.65,0.05,0.36,1);
|
||||||
|
width: 100%;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-shrink: 0;
|
||||||
|
gap: 0.375rem;
|
||||||
|
line-height: 1.1;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
border-radius: 50%;
|
||||||
|
content: " ";
|
||||||
|
height: 0.35rem;
|
||||||
|
width: 0.35rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-state="online"] {
|
||||||
|
label {
|
||||||
|
&::before {
|
||||||
|
background-color: var(--green);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-state="offline"] {
|
||||||
|
label {
|
||||||
|
&::before {
|
||||||
|
background-color: var(--red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
context('/src/Examples/CollaborativeEditing/React/', () => {
|
context('/src/Demos/SingleRoomCollab/React/', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.visit('/src/Examples/CollaborativeEditing/React/')
|
cy.visit('/src/Demos/SingleRoomCollab/React/')
|
||||||
})
|
})
|
||||||
|
|
||||||
/* it('should show the current room with participants', () => {
|
/* it('should show the current room with participants', () => {
|
||||||
|
@ -50,22 +50,26 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={setLink}
|
onClick={setLink}
|
||||||
className={editor.isActive('link') ? 'is-active' : ''}
|
className={editor.isActive('link') ? 'is-active' : ''}
|
||||||
data-testid="setLink"
|
data-testid="setLink"
|
||||||
>
|
>
|
||||||
setLink
|
Set link
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().unsetLink().run()}
|
onClick={() => editor.chain().focus().unsetLink().run()}
|
||||||
disabled={!editor.isActive('link')}
|
disabled={!editor.isActive('link')}
|
||||||
data-testid="unsetLink"
|
data-testid="unsetLink"
|
||||||
>
|
>
|
||||||
unsetLink
|
Unset link
|
||||||
</button>
|
</button>
|
||||||
<EditorContent editor={editor} />
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditorContent editor={editor} />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,39 +24,78 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link styles */
|
||||||
|
a {
|
||||||
|
color: var(--purple);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--purple-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,116 +12,118 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().undo().run()}>
|
<button onClick={() => editor.chain().focus().undo().run()}>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().redo().run()}>
|
<button onClick={() => editor.chain().focus().redo().run()}>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,9 +141,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,39 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,70 +1,74 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -107,15 +111,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -123,40 +135,69 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,109 +17,109 @@ const MenuBar = ({ editor }) => {
|
|||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().undo().run()}>
|
<button onClick={() => editor.chain().focus().undo().run()}>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().redo().run()}>
|
<button onClick={() => editor.chain().focus().redo().run()}>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -135,7 +135,7 @@ export default () => {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<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:
|
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>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -163,9 +163,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,67 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor" class="toolbar" :class="styles.toolbar">
|
<div v-if="editor" class="toolbar" :class="styles.toolbar">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
@ -95,7 +95,7 @@ export default {
|
|||||||
This is a red headline
|
This is a red headline
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<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:
|
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>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -132,15 +132,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -148,41 +156,68 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
|
.tiptap {
|
||||||
.code-block {
|
.code-block {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
select {
|
select {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
background-color: var(--white);
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Black" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
top: 0.5rem;
|
top: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
// load specific languages only
|
|
||||||
// import { lowlight } from 'lowlight/lib/core'
|
|
||||||
// import javascript from 'highlight.js/lib/languages/javascript'
|
|
||||||
// lowlight.registerLanguage('javascript', javascript)
|
|
||||||
import './styles.scss'
|
import './styles.scss'
|
||||||
|
|
||||||
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
|
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
|
||||||
@ -13,16 +9,21 @@ import css from 'highlight.js/lib/languages/css'
|
|||||||
import js from 'highlight.js/lib/languages/javascript'
|
import js from 'highlight.js/lib/languages/javascript'
|
||||||
import ts from 'highlight.js/lib/languages/typescript'
|
import ts from 'highlight.js/lib/languages/typescript'
|
||||||
import html from 'highlight.js/lib/languages/xml'
|
import html from 'highlight.js/lib/languages/xml'
|
||||||
// load all highlight.js languages
|
// load all languages with "all" or common languages with "common"
|
||||||
import { lowlight } from 'lowlight'
|
import { all, createLowlight } from 'lowlight'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import CodeBlockComponent from './CodeBlockComponent.jsx'
|
// eslint-disable-next-line
|
||||||
|
import CodeBlockComponent from './CodeBlockComponent'
|
||||||
|
|
||||||
lowlight.registerLanguage('html', html)
|
// create a lowlight instance
|
||||||
lowlight.registerLanguage('css', css)
|
const lowlight = createLowlight(all)
|
||||||
lowlight.registerLanguage('js', js)
|
|
||||||
lowlight.registerLanguage('ts', ts)
|
// you can also register individual languages
|
||||||
|
lowlight.register('html', html)
|
||||||
|
lowlight.register('css', css)
|
||||||
|
lowlight.register('js', js)
|
||||||
|
lowlight.register('ts', ts)
|
||||||
|
|
||||||
const MenuBar = ({ editor }) => {
|
const MenuBar = ({ editor }) => {
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
@ -30,9 +31,13 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={() => editor.chain().focus().toggleCodeBlock().run()} className={editor.isActive('codeBlock') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleCodeBlock().run()} className={editor.isActive('codeBlock') ? 'is-active' : ''}>
|
||||||
code block
|
Toggle code block
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +57,7 @@ export default () => {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
That’s a boring paragraph followed by a fenced code block:
|
That's a boring paragraph followed by a fenced code block:
|
||||||
</p>
|
</p>
|
||||||
<pre><code class="language-javascript">for (var i=1; i <= 20; i++)
|
<pre><code class="language-javascript">for (var i=1; i <= 20; i++)
|
||||||
{
|
{
|
||||||
@ -72,9 +77,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ context('/src/Examples/CodeBlockLanguage/React/', () => {
|
|||||||
|
|
||||||
expect(initialCount).to.be.greaterThan(0)
|
expect(initialCount).to.be.greaterThan(0)
|
||||||
|
|
||||||
|
cy.wait(100)
|
||||||
cy.get('.tiptap select').select('java')
|
cy.get('.tiptap select').select('java')
|
||||||
cy.wait(500)
|
cy.wait(500)
|
||||||
|
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0d0d0d;
|
background: var(--black);
|
||||||
color: #fff;
|
|
||||||
font-family: "JetBrainsMono", monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code styling */
|
||||||
.hljs-comment,
|
.hljs-comment,
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
color: #616161;
|
color: #616161;
|
||||||
|
@ -46,13 +46,17 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.tiptap {
|
||||||
.code-block {
|
.code-block {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
select {
|
select {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.5rem;
|
background-color: var(--white);
|
||||||
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="Black" d="M7 10l5 5 5-5z"/></svg>');
|
||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
|
top: 0.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -15,6 +15,7 @@ context('/src/Examples/CodeBlockLanguage/Vue/', () => {
|
|||||||
|
|
||||||
expect(initialCount).to.be.greaterThan(0)
|
expect(initialCount).to.be.greaterThan(0)
|
||||||
|
|
||||||
|
cy.wait(100)
|
||||||
cy.get('.tiptap select').select('java')
|
cy.get('.tiptap select').select('java')
|
||||||
cy.wait(500)
|
cy.wait(500)
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-">
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Toggle code block
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -17,20 +21,19 @@ import css from 'highlight.js/lib/languages/css'
|
|||||||
import js from 'highlight.js/lib/languages/javascript'
|
import js from 'highlight.js/lib/languages/javascript'
|
||||||
import ts from 'highlight.js/lib/languages/typescript'
|
import ts from 'highlight.js/lib/languages/typescript'
|
||||||
import html from 'highlight.js/lib/languages/xml'
|
import html from 'highlight.js/lib/languages/xml'
|
||||||
// load all highlight.js languages
|
// load all languages with "all" or common languages with "common"
|
||||||
import { lowlight } from 'lowlight'
|
import { all, createLowlight } from 'lowlight'
|
||||||
|
|
||||||
import CodeBlockComponent from './CodeBlockComponent.vue'
|
import CodeBlockComponent from './CodeBlockComponent.vue'
|
||||||
|
|
||||||
lowlight.registerLanguage('html', html)
|
// create a lowlight instance
|
||||||
lowlight.registerLanguage('css', css)
|
const lowlight = createLowlight(all)
|
||||||
lowlight.registerLanguage('js', js)
|
|
||||||
lowlight.registerLanguage('ts', ts)
|
|
||||||
|
|
||||||
// load specific languages only
|
// you can also register languages
|
||||||
// import { lowlight } from 'lowlight/lib/core'
|
lowlight.register('html', html)
|
||||||
// import javascript from 'highlight.js/lib/languages/javascript'
|
lowlight.register('css', css)
|
||||||
// lowlight.registerLanguage('javascript', javascript)
|
lowlight.register('js', js)
|
||||||
|
lowlight.register('ts', ts)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -59,7 +62,7 @@ export default {
|
|||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
<p>
|
<p>
|
||||||
That’s a boring paragraph followed by a fenced code block:
|
That's a boring paragraph followed by a fenced code block:
|
||||||
</p>
|
</p>
|
||||||
<pre><code class="language-javascript">for (var i=1; i <= 20; i++)
|
<pre><code class="language-javascript">for (var i=1; i <= 20; i++)
|
||||||
{
|
{
|
||||||
@ -88,24 +91,26 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code styling */
|
||||||
.hljs-comment,
|
.hljs-comment,
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
color: #616161;
|
color: #616161;
|
||||||
@ -121,7 +126,7 @@ export default {
|
|||||||
.hljs-name,
|
.hljs-name,
|
||||||
.hljs-selector-id,
|
.hljs-selector-id,
|
||||||
.hljs-selector-class {
|
.hljs-selector-class {
|
||||||
color: #F98181;
|
color: #f98181;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-number,
|
.hljs-number,
|
||||||
@ -131,23 +136,23 @@ export default {
|
|||||||
.hljs-literal,
|
.hljs-literal,
|
||||||
.hljs-type,
|
.hljs-type,
|
||||||
.hljs-params {
|
.hljs-params {
|
||||||
color: #FBBC88;
|
color: #fbbc88;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-string,
|
.hljs-string,
|
||||||
.hljs-symbol,
|
.hljs-symbol,
|
||||||
.hljs-bullet {
|
.hljs-bullet {
|
||||||
color: #B9F18D;
|
color: #b9f18d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-title,
|
.hljs-title,
|
||||||
.hljs-section {
|
.hljs-section {
|
||||||
color: #FAF594;
|
color: #faf594;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-keyword,
|
.hljs-keyword,
|
||||||
.hljs-selector-tag {
|
.hljs-selector-tag {
|
||||||
color: #70CFF8;
|
color: #70cff8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hljs-emphasis {
|
.hljs-emphasis {
|
||||||
|
@ -59,25 +59,25 @@ export default ({ editor }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-unordered',
|
icon: 'list-unordered',
|
||||||
title: 'Bullet List',
|
title: 'Bullet list',
|
||||||
action: () => editor.chain().focus().toggleBulletList().run(),
|
action: () => editor.chain().focus().toggleBulletList().run(),
|
||||||
isActive: () => editor.isActive('bulletList'),
|
isActive: () => editor.isActive('bulletList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-ordered',
|
icon: 'list-ordered',
|
||||||
title: 'Ordered List',
|
title: 'Ordered list',
|
||||||
action: () => editor.chain().focus().toggleOrderedList().run(),
|
action: () => editor.chain().focus().toggleOrderedList().run(),
|
||||||
isActive: () => editor.isActive('orderedList'),
|
isActive: () => editor.isActive('orderedList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-check-2',
|
icon: 'list-check-2',
|
||||||
title: 'Task List',
|
title: 'Task list',
|
||||||
action: () => editor.chain().focus().toggleTaskList().run(),
|
action: () => editor.chain().focus().toggleTaskList().run(),
|
||||||
isActive: () => editor.isActive('taskList'),
|
isActive: () => editor.isActive('taskList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'code-box-line',
|
icon: 'code-box-line',
|
||||||
title: 'Code Block',
|
title: 'Code block',
|
||||||
action: () => editor.chain().focus().toggleCodeBlock().run(),
|
action: () => editor.chain().focus().toggleCodeBlock().run(),
|
||||||
isActive: () => editor.isActive('codeBlock'),
|
isActive: () => editor.isActive('codeBlock'),
|
||||||
},
|
},
|
||||||
@ -92,7 +92,7 @@ export default ({ editor }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'separator',
|
icon: 'separator',
|
||||||
title: 'Horizontal Rule',
|
title: 'Horizontal rule',
|
||||||
action: () => editor.chain().focus().setHorizontalRule().run(),
|
action: () => editor.chain().focus().setHorizontalRule().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -100,12 +100,12 @@ export default ({ editor }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'text-wrap',
|
icon: 'text-wrap',
|
||||||
title: 'Hard Break',
|
title: 'Hard break',
|
||||||
action: () => editor.chain().focus().setHardBreak().run(),
|
action: () => editor.chain().focus().setHardBreak().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'format-clear',
|
icon: 'format-clear',
|
||||||
title: 'Clear Format',
|
title: 'Clear format',
|
||||||
action: () => editor.chain().focus().clearNodes().unsetAllMarks()
|
action: () => editor.chain().focus().clearNodes().unsetAllMarks()
|
||||||
.run(),
|
.run(),
|
||||||
},
|
},
|
||||||
|
@ -78,25 +78,25 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-unordered',
|
icon: 'list-unordered',
|
||||||
title: 'Bullet List',
|
title: 'Bullet list',
|
||||||
action: () => this.editor.chain().focus().toggleBulletList().run(),
|
action: () => this.editor.chain().focus().toggleBulletList().run(),
|
||||||
isActive: () => this.editor.isActive('bulletList'),
|
isActive: () => this.editor.isActive('bulletList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-ordered',
|
icon: 'list-ordered',
|
||||||
title: 'Ordered List',
|
title: 'Ordered list',
|
||||||
action: () => this.editor.chain().focus().toggleOrderedList().run(),
|
action: () => this.editor.chain().focus().toggleOrderedList().run(),
|
||||||
isActive: () => this.editor.isActive('orderedList'),
|
isActive: () => this.editor.isActive('orderedList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'list-check-2',
|
icon: 'list-check-2',
|
||||||
title: 'Task List',
|
title: 'Task list',
|
||||||
action: () => this.editor.chain().focus().toggleTaskList().run(),
|
action: () => this.editor.chain().focus().toggleTaskList().run(),
|
||||||
isActive: () => this.editor.isActive('taskList'),
|
isActive: () => this.editor.isActive('taskList'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'code-box-line',
|
icon: 'code-box-line',
|
||||||
title: 'Code Block',
|
title: 'Code block',
|
||||||
action: () => this.editor.chain().focus().toggleCodeBlock().run(),
|
action: () => this.editor.chain().focus().toggleCodeBlock().run(),
|
||||||
isActive: () => this.editor.isActive('codeBlock'),
|
isActive: () => this.editor.isActive('codeBlock'),
|
||||||
},
|
},
|
||||||
@ -111,7 +111,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'separator',
|
icon: 'separator',
|
||||||
title: 'Horizontal Rule',
|
title: 'Horizontal rule',
|
||||||
action: () => this.editor.chain().focus().setHorizontalRule().run(),
|
action: () => this.editor.chain().focus().setHorizontalRule().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -119,12 +119,12 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'text-wrap',
|
icon: 'text-wrap',
|
||||||
title: 'Hard Break',
|
title: 'Hard break',
|
||||||
action: () => this.editor.chain().focus().setHardBreak().run(),
|
action: () => this.editor.chain().focus().setHardBreak().run(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'format-clear',
|
icon: 'format-clear',
|
||||||
title: 'Clear Format',
|
title: 'Clear format',
|
||||||
action: () => this.editor.chain()
|
action: () => this.editor.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.clearNodes()
|
.clearNodes()
|
||||||
|
@ -54,11 +54,11 @@ export const MentionList = forwardRef((props, ref) => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="items">
|
<div className="dropdown-menu">
|
||||||
{props.items.length
|
{props.items.length
|
||||||
? props.items.map((item, index) => (
|
? props.items.map((item, index) => (
|
||||||
<button
|
<button
|
||||||
className={`item ${index === selectedIndex ? 'is-selected' : ''}`}
|
className={index === selectedIndex ? 'is-selected' : ''}
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => selectItem(index)}
|
onClick={() => selectItem(index)}
|
||||||
>
|
>
|
||||||
|
@ -1,28 +1,31 @@
|
|||||||
.items {
|
/* Dropdown menu */
|
||||||
padding: 0.2rem;
|
.dropdown-menu {
|
||||||
|
background: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.4rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: #FFF;
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(0, 0, 0, 0.05),
|
|
||||||
0px 10px 20px rgba(0, 0, 0, 0.1),
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
button {
|
||||||
display: block;
|
align-items: center;
|
||||||
margin: 0;
|
background-color: transparent;
|
||||||
width: 100%;
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: transparent;
|
width: 100%;
|
||||||
border-radius: 0.4rem;
|
|
||||||
border: 1px solid transparent;
|
&:hover,
|
||||||
padding: 0.2rem 0.4rem;
|
&:hover.is-selected {
|
||||||
|
background-color: var(--gray-3);
|
||||||
|
}
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected {
|
||||||
border-color: #000;
|
background-color: var(--gray-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ export default () => {
|
|||||||
: 0
|
: 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
{editor
|
{editor
|
||||||
&& <div className={`character-count ${editor.storage.characterCount.characters() === limit ? 'character-count--warning' : ''}`}>
|
&& <div className={`character-count ${editor.storage.characterCount.characters() === limit ? 'character-count--warning' : ''}`}>
|
||||||
@ -48,7 +48,6 @@ export default () => {
|
|||||||
height="20"
|
height="20"
|
||||||
width="20"
|
width="20"
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
className="character-count__graph"
|
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
r="10"
|
r="10"
|
||||||
@ -74,11 +73,9 @@ export default () => {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div className="character-count__text">
|
|
||||||
{editor.storage.characterCount.characters()} / {limit} characters
|
{editor.storage.characterCount.characters()} / {limit} characters
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,32 +5,32 @@ context('/src/Examples/Community/React/', () => {
|
|||||||
|
|
||||||
it('should count the characters correctly', () => {
|
it('should count the characters correctly', () => {
|
||||||
// check if count text is "44 / 280 characters"
|
// check if count text is "44 / 280 characters"
|
||||||
cy.get('.character-count__text').should('have.text', '44/280 characters')
|
cy.get('.character-count').should('contain', '44 / 280 characters')
|
||||||
|
|
||||||
// type in .tiptap
|
// type in .tiptap
|
||||||
cy.get('.tiptap').type(' Hello World')
|
cy.get('.tiptap').type(' Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '56/280 characters')
|
cy.get('.character-count').should('contain', '56 / 280 characters')
|
||||||
|
|
||||||
// remove content from .tiptap and enter text
|
// remove content from .tiptap and enter text
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '11/280 characters')
|
cy.get('.character-count').should('contain', '11 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should mention a user', () => {
|
it('should mention a user', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||||
|
|
||||||
// check if the mention autocomplete is visible
|
// check if the mention autocomplete is visible
|
||||||
cy.get('.tippy-content .items').should('be.visible')
|
cy.get('.tippy-content .dropdown-menu').should('be.visible')
|
||||||
|
|
||||||
// select the first user
|
// select the first user
|
||||||
cy.get('.tippy-content .items .item').first().then($el => {
|
cy.get('.tippy-content .dropdown-menu button').first().then($el => {
|
||||||
const name = $el.text()
|
const name = $el.text()
|
||||||
|
|
||||||
$el.click()
|
$el.click()
|
||||||
|
|
||||||
// check if the user is mentioned
|
// check if the user is mentioned
|
||||||
cy.get('.tiptap').should('have.text', `@${name} `)
|
cy.get('.tiptap').should('have.text', `@${name} `)
|
||||||
cy.get('.character-count__text').should('have.text', '2/280 characters')
|
cy.get('.character-count').should('contain', '2 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,41 +1,33 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mention {
|
.mention {
|
||||||
border: 1px solid #000;
|
background-color: var(--purple-light);
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
box-decoration-break: clone;
|
box-decoration-break: clone;
|
||||||
|
color: var(--purple);
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Character count */
|
||||||
.character-count {
|
.character-count {
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #68CEF8;
|
color: var(--gray-5);
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: .5rem;
|
||||||
|
margin: 1.5rem;
|
||||||
|
|
||||||
&--warning {
|
svg {
|
||||||
color: #FB5151;
|
color: var(--purple);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__graph {
|
&--warning,
|
||||||
margin-right: 0.5rem;
|
&--warning svg {
|
||||||
}
|
color: var(--red);
|
||||||
|
|
||||||
&__text {
|
|
||||||
color: #868e96;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="items">
|
<div class="dropdown-menu">
|
||||||
<template v-if="items.length">
|
<template v-if="items.length">
|
||||||
<button
|
<button
|
||||||
class="item"
|
|
||||||
:class="{ 'is-selected': index === selectedIndex }"
|
:class="{ 'is-selected': index === selectedIndex }"
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -87,32 +86,35 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.items {
|
/* Dropdown menu */
|
||||||
padding: 0.2rem;
|
.dropdown-menu {
|
||||||
|
background: var(--white);
|
||||||
|
border: 1px solid var(--gray-1);
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.4rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: #FFF;
|
button {
|
||||||
color: rgba(0, 0, 0, 0.8);
|
align-items: center;
|
||||||
overflow: hidden;
|
background-color: transparent;
|
||||||
font-size: 0.9rem;
|
display: flex;
|
||||||
box-shadow:
|
gap: 0.25rem;
|
||||||
0 0 0 1px rgba(0, 0, 0, 0.05),
|
text-align: left;
|
||||||
0px 10px 20px rgba(0, 0, 0, 0.1),
|
width: 100%;
|
||||||
;
|
|
||||||
|
&:hover,
|
||||||
|
&:hover.is-selected {
|
||||||
|
background-color: var(--gray-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
text-align: left;
|
|
||||||
background: transparent;
|
|
||||||
border-radius: 0.4rem;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.2rem 0.4rem;
|
|
||||||
|
|
||||||
&.is-selected {
|
&.is-selected {
|
||||||
border-color: #000;
|
background-color: var(--gray-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -5,32 +5,32 @@ context('/src/Examples/Community/Vue/', () => {
|
|||||||
|
|
||||||
it('should count the characters correctly', () => {
|
it('should count the characters correctly', () => {
|
||||||
// check if count text is "44 / 280 characters"
|
// check if count text is "44 / 280 characters"
|
||||||
cy.get('.character-count__text').should('have.text', '44/280 characters')
|
cy.get('.character-count').should('contain', '44 / 280 characters')
|
||||||
|
|
||||||
// type in .tiptap
|
// type in .tiptap
|
||||||
cy.get('.tiptap').type(' Hello World')
|
cy.get('.tiptap').type(' Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '56/280 characters')
|
cy.get('.character-count').should('contain', '56 / 280 characters')
|
||||||
|
|
||||||
// remove content from .tiptap and enter text
|
// remove content from .tiptap and enter text
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
cy.get('.tiptap').type('{selectall}{backspace}Hello World')
|
||||||
cy.get('.character-count__text').should('have.text', '11/280 characters')
|
cy.get('.character-count').should('contain', '11 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should mention a user', () => {
|
it('should mention a user', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}@')
|
cy.get('.tiptap').type('{selectall}{backspace}@')
|
||||||
|
|
||||||
// check if the mention autocomplete is visible
|
// check if the mention autocomplete is visible
|
||||||
cy.get('.tippy-content .items').should('be.visible')
|
cy.get('.tippy-content .dropdown-menu').should('be.visible')
|
||||||
|
|
||||||
// select the first user
|
// select the first user
|
||||||
cy.get('.tippy-content .items .item').first().then($el => {
|
cy.get('.tippy-content .dropdown-menu button').first().then($el => {
|
||||||
const name = $el.text()
|
const name = $el.text()
|
||||||
|
|
||||||
$el.click()
|
$el.click()
|
||||||
|
|
||||||
// check if the user is mentioned
|
// check if the user is mentioned
|
||||||
cy.get('.tiptap').should('have.text', `@${name} `)
|
cy.get('.tiptap').should('have.text', `@${name} `)
|
||||||
cy.get('.character-count__text').should('have.text', '2/280 characters')
|
cy.get('.character-count').should('contain', '2 / 280 characters')
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
height="20"
|
height="20"
|
||||||
width="20"
|
width="20"
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
class="character-count__graph"
|
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
r="10"
|
r="10"
|
||||||
@ -32,7 +31,7 @@
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div class="character-count__text">{{ editor.storage.characterCount.characters() }}/{{ limit }} characters</div>
|
{{ editor.storage.characterCount.characters() }} / {{ limit }} characters
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -97,43 +96,35 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mention {
|
.mention {
|
||||||
border: 1px solid #000;
|
background-color: var(--purple-light);
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
padding: 0.1rem 0.3rem;
|
|
||||||
box-decoration-break: clone;
|
box-decoration-break: clone;
|
||||||
|
color: var(--purple);
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Character count */
|
||||||
.character-count {
|
.character-count {
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #68CEF8;
|
color: var(--gray-5);
|
||||||
|
display: flex;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
gap: .5rem;
|
||||||
|
margin: 1.5rem;
|
||||||
|
|
||||||
&--warning {
|
svg {
|
||||||
color: #FB5151;
|
color: var(--purple);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__graph {
|
&--warning,
|
||||||
margin-right: 0.5rem;
|
&--warning svg {
|
||||||
}
|
color: var(--red);
|
||||||
|
|
||||||
&__text {
|
|
||||||
color: #868e96;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,109 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder (at the top) */
|
/* Placeholder (at the top) */
|
||||||
/*.tiptap p.is-editor-empty:first-child::before {
|
/* p.is-editor-empty:first-child::before {
|
||||||
|
color: var(--gray-4);
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
float: left;
|
float: left;
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/* Placeholder (on every new line) */
|
/* Placeholder (on every new line) */
|
||||||
.tiptap .is-empty::before {
|
.is-empty::before {
|
||||||
|
color: var(--gray-4);
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
float: left;
|
float: left;
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,26 +60,111 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder (at the top) */
|
/* Placeholder (at the top) */
|
||||||
/*.tiptap p.is-editor-empty:first-child::before {
|
/* p.is-editor-empty:first-child::before {
|
||||||
|
color: var(--gray-4);
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
float: left;
|
float: left;
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/* Placeholder (on every new line) */
|
/* Placeholder (on every new line) */
|
||||||
.tiptap .is-empty::before {
|
.is-empty::before {
|
||||||
|
color: var(--gray-4);
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
float: left;
|
float: left;
|
||||||
color: #ced4da;
|
|
||||||
pointer-events: none;
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,91 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Placeholder (at the top) */
|
/* Heading styles */
|
||||||
/*.tiptap p.is-editor-empty:first-child::before {
|
h1,
|
||||||
content: attr(data-placeholder);
|
h2,
|
||||||
float: left;
|
h3,
|
||||||
color: #ced4da;
|
h4,
|
||||||
pointer-events: none;
|
h5,
|
||||||
height: 0;
|
h6 {
|
||||||
}*/
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
/* Placeholder (on every new line) */
|
text-wrap: pretty;
|
||||||
.tiptap .is-empty::before {
|
}
|
||||||
content: attr(data-placeholder);
|
|
||||||
float: left;
|
h1,
|
||||||
color: #ced4da;
|
h2 {
|
||||||
pointer-events: none;
|
margin-top: 3.5rem;
|
||||||
height: 0;
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
|
code {
|
||||||
|
background-color: var(--purple-light);
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: var(--black);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--gray-2);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||||
disabled={
|
disabled={
|
||||||
@ -27,7 +28,7 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('bold') ? 'is-active' : ''}
|
className={editor.isActive('bold') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||||
@ -40,7 +41,7 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('italic') ? 'is-active' : ''}
|
className={editor.isActive('italic') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||||
@ -53,7 +54,7 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('strike') ? 'is-active' : ''}
|
className={editor.isActive('strike') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||||
@ -66,85 +67,85 @@ const MenuBar = () => {
|
|||||||
}
|
}
|
||||||
className={editor.isActive('code') ? 'is-active' : ''}
|
className={editor.isActive('code') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
<button onClick={() => editor.chain().focus().unsetAllMarks().run()}>
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
<button onClick={() => editor.chain().focus().clearNodes().run()}>
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||||
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
className={editor.isActive('paragraph') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 4 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 5 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
onClick={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
className={editor.isActive('heading', { level: 6 }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
onClick={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
className={editor.isActive('bulletList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
className={editor.isActive('orderedList') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
className={editor.isActive('codeBlock') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
className={editor.isActive('blockquote') ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button onClick={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
<button onClick={() => editor.chain().focus().setHardBreak().run()}>
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().undo().run()}
|
onClick={() => editor.chain().focus().undo().run()}
|
||||||
@ -156,7 +157,7 @@ const MenuBar = () => {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().redo().run()}
|
onClick={() => editor.chain().focus().redo().run()}
|
||||||
@ -168,15 +169,16 @@ const MenuBar = () => {
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
redo
|
Redo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => editor.chain().focus().setColor('#958DF1').run()}
|
onClick={() => editor.chain().focus().setColor('#958DF1').run()}
|
||||||
className={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
className={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
||||||
>
|
>
|
||||||
purple
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +202,7 @@ const content = `
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<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:
|
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>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
@ -21,41 +21,41 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for cursor`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
it(`should disable ${m.label} when the code tag is enabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('be.disabled')
|
cy.get('button').contains(m.label).should('be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
it(`should enable ${m.label} when the code tag is disabled for selection`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains('code').click()
|
cy.get('button').contains('Code').click()
|
||||||
cy.get('button').contains(m.label).should('not.be.disabled')
|
cy.get('button').contains(m.label).should('not.be.disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -64,40 +64,40 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -109,35 +109,35 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,15 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -38,40 +38,40 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -83,35 +83,35 @@ context('/src/Examples/Default/React/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import "./styles.scss";
|
import "./styles.scss";
|
||||||
|
|
||||||
|
import { Color } from '@tiptap/extension-color'
|
||||||
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import { Editor } from "@tiptap/core";
|
import { Editor } from "@tiptap/core";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
@ -11,13 +14,17 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
editor = new Editor({
|
editor = new Editor({
|
||||||
element: element,
|
element: element,
|
||||||
extensions: [StarterKit],
|
extensions: [
|
||||||
|
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||||
|
TextStyle.configure({ types: [ListItem.name] }),
|
||||||
|
StarterKit,
|
||||||
|
],
|
||||||
content: `
|
content: `
|
||||||
<h2>
|
<h2>
|
||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<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:
|
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>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -51,119 +58,125 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if editor}
|
{#if editor}
|
||||||
<div>
|
<div class="control-group">
|
||||||
<div>
|
<div class="button-group">
|
||||||
<button
|
<button
|
||||||
on:click={() => console.log && editor.chain().focus().toggleBold().run()}
|
on:click={() => console.log && editor.chain().focus().toggleBold().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleBold().run()}
|
disabled={!editor.can().chain().focus().toggleBold().run()}
|
||||||
class={editor.isActive("bold") ? "is-active" : ""}
|
class={editor.isActive("bold") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleItalic().run()}
|
on:click={() => editor.chain().focus().toggleItalic().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
||||||
class={editor.isActive("italic") ? "is-active" : ""}
|
class={editor.isActive("italic") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleStrike().run()}
|
on:click={() => editor.chain().focus().toggleStrike().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
||||||
class={editor.isActive("strike") ? "is-active" : ""}
|
class={editor.isActive("strike") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleCode().run()}
|
on:click={() => editor.chain().focus().toggleCode().run()}
|
||||||
disabled={!editor.can().chain().focus().toggleCode().run()}
|
disabled={!editor.can().chain().focus().toggleCode().run()}
|
||||||
class={editor.isActive("code") ? "is-active" : ""}
|
class={editor.isActive("code") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button on:click={() => editor.chain().focus().unsetAllMarks().run()}> clear marks </button>
|
<button on:click={() => editor.chain().focus().unsetAllMarks().run()}>Clear marks</button>
|
||||||
<button on:click={() => editor.chain().focus().clearNodes().run()}> clear nodes </button>
|
<button on:click={() => editor.chain().focus().clearNodes().run()}>Clear nodes</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().setParagraph().run()}
|
on:click={() => editor.chain().focus().setParagraph().run()}
|
||||||
class={editor.isActive("paragraph") ? "is-active" : ""}
|
class={editor.isActive("paragraph") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||||
class={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||||
class={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||||
class={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
||||||
class={editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
||||||
class={editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
on:click={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
||||||
class={editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
|
class={editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleBulletList().run()}
|
on:click={() => editor.chain().focus().toggleBulletList().run()}
|
||||||
class={editor.isActive("bulletList") ? "is-active" : ""}
|
class={editor.isActive("bulletList") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleOrderedList().run()}
|
on:click={() => editor.chain().focus().toggleOrderedList().run()}
|
||||||
class={editor.isActive("orderedList") ? "is-active" : ""}
|
class={editor.isActive("orderedList") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleCodeBlock().run()}
|
on:click={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||||
class={editor.isActive("codeBlock") ? "is-active" : ""}
|
class={editor.isActive("codeBlock") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().toggleBlockquote().run()}
|
on:click={() => editor.chain().focus().toggleBlockquote().run()}
|
||||||
class={editor.isActive("blockquote") ? "is-active" : ""}
|
class={editor.isActive("blockquote") ? "is-active" : ""}
|
||||||
>
|
>
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button on:click={() => editor.chain().focus().setHorizontalRule().run()}>
|
<button on:click={() => editor.chain().focus().setHorizontalRule().run()}>
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button on:click={() => editor.chain().focus().setHardBreak().run()}> hard break </button>
|
<button on:click={() => editor.chain().focus().setHardBreak().run()}>Hard break</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().undo().run()}
|
on:click={() => editor.chain().focus().undo().run()}
|
||||||
disabled={!editor.can().chain().focus().undo().run()}
|
disabled={!editor.can().chain().focus().undo().run()}
|
||||||
>
|
>
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => editor.chain().focus().redo().run()}
|
on:click={() => editor.chain().focus().redo().run()}
|
||||||
disabled={!editor.can().chain().focus().redo().run()}
|
disabled={!editor.can().chain().focus().redo().run()}
|
||||||
>
|
>
|
||||||
redo
|
Redo
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => editor.chain().focus().setColor('#958DF1').run()}
|
||||||
|
class={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
||||||
|
>
|
||||||
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -16,41 +24,68 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,15 @@ context('/src/Examples/Default/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonMarks = [
|
const buttonMarks = [
|
||||||
{ label: 'bold', tag: 'strong' },
|
{ label: 'Bold', tag: 'strong' },
|
||||||
{ label: 'italic', tag: 'em' },
|
{ label: 'Italic', tag: 'em' },
|
||||||
{ label: 'strike', tag: 's' },
|
{ label: 'Strike', tag: 's' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonMarks.forEach(m => {
|
buttonMarks.forEach(m => {
|
||||||
it(`should apply ${m.label} when the button is pressed`, () => {
|
it(`should apply ${m.label} when the button is pressed`, () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains(m.label).click()
|
cy.get('button').contains(m.label).click()
|
||||||
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
cy.get(`.tiptap ${m.tag}`).should('exist').should('have.text', 'Hello world')
|
||||||
@ -38,40 +38,40 @@ context('/src/Examples/Default/Vue/', () => {
|
|||||||
|
|
||||||
it('should clear marks when the button is pressed', () => {
|
it('should clear marks when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}')
|
cy.get('.tiptap').type('{selectall}')
|
||||||
cy.get('button').contains('bold').click()
|
cy.get('button').contains('Bold').click()
|
||||||
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap strong').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('button').contains('clear marks').click()
|
cy.get('button').contains('Clear marks').click()
|
||||||
cy.get('.tiptap strong').should('not.exist')
|
cy.get('.tiptap strong').should('not.exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear nodes when the button is pressed', () => {
|
it('should clear nodes when the button is pressed', () => {
|
||||||
cy.get('.tiptap').type('{selectall}Hello world')
|
cy.get('.tiptap').type('{selectall}Hello world')
|
||||||
cy.get('button').contains('bullet list').click()
|
cy.get('button').contains('Bullet list').click()
|
||||||
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
cy.get('.tiptap ul').should('exist').should('have.text', 'Hello world')
|
||||||
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
cy.get('.tiptap').type('{enter}A second item{enter}A third item{selectall}')
|
||||||
cy.get('button').contains('clear nodes').click()
|
cy.get('button').contains('Clear nodes').click()
|
||||||
cy.get('.tiptap ul').should('not.exist')
|
cy.get('.tiptap ul').should('not.exist')
|
||||||
cy.get('.tiptap p').should('have.length', 3)
|
cy.get('.tiptap p').should('have.length', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonNodes = [
|
const buttonNodes = [
|
||||||
{ label: 'h1', tag: 'h1' },
|
{ label: 'H1', tag: 'h1' },
|
||||||
{ label: 'h2', tag: 'h2' },
|
{ label: 'H2', tag: 'h2' },
|
||||||
{ label: 'h3', tag: 'h3' },
|
{ label: 'H3', tag: 'h3' },
|
||||||
{ label: 'h4', tag: 'h4' },
|
{ label: 'H4', tag: 'h4' },
|
||||||
{ label: 'h5', tag: 'h5' },
|
{ label: 'H5', tag: 'h5' },
|
||||||
{ label: 'h6', tag: 'h6' },
|
{ label: 'H6', tag: 'h6' },
|
||||||
{ label: 'bullet list', tag: 'ul' },
|
{ label: 'Bullet list', tag: 'ul' },
|
||||||
{ label: 'ordered list', tag: 'ol' },
|
{ label: 'Ordered list', tag: 'ol' },
|
||||||
{ label: 'code block', tag: 'pre code' },
|
{ label: 'Code block', tag: 'pre code' },
|
||||||
{ label: 'blockquote', tag: 'blockquote' },
|
{ label: 'Blockquote', tag: 'blockquote' },
|
||||||
]
|
]
|
||||||
|
|
||||||
buttonNodes.forEach(n => {
|
buttonNodes.forEach(n => {
|
||||||
it(`should set ${n.label} when the button is pressed`, () => {
|
it(`should set ${n.label} when the button is pressed`, () => {
|
||||||
cy.get('button').contains('paragraph').click()
|
cy.get('button').contains('Paragraph').click()
|
||||||
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
cy.get('.tiptap').type('{selectall}Hello world{selectall}')
|
||||||
|
|
||||||
cy.get('button').contains(n.label).click()
|
cy.get('button').contains(n.label).click()
|
||||||
@ -83,35 +83,35 @@ context('/src/Examples/Default/Vue/', () => {
|
|||||||
|
|
||||||
it('should add a hr when on the same line as a node', () => {
|
it('should add a hr when on the same line as a node', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a hr when on a new line', () => {
|
it('should add a hr when on a new line', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}{enter}')
|
cy.get('.tiptap').type('{rightArrow}{enter}')
|
||||||
cy.get('button').contains('horizontal rule').click()
|
cy.get('button').contains('Horizontal rule').click()
|
||||||
cy.get('.tiptap hr').should('exist')
|
cy.get('.tiptap hr').should('exist')
|
||||||
cy.get('.tiptap h1').should('exist')
|
cy.get('.tiptap h1').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a br', () => {
|
it('should add a br', () => {
|
||||||
cy.get('.tiptap').type('{rightArrow}')
|
cy.get('.tiptap').type('{rightArrow}')
|
||||||
cy.get('button').contains('hard break').click()
|
cy.get('button').contains('Hard break').click()
|
||||||
cy.get('.tiptap h1 br').should('exist')
|
cy.get('.tiptap h1 br').should('exist')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should undo', () => {
|
it('should undo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should redo', () => {
|
it('should redo', () => {
|
||||||
cy.get('.tiptap').type('{selectall}{backspace}')
|
cy.get('.tiptap').type('{selectall}{backspace}')
|
||||||
cy.get('button').contains('undo').click()
|
cy.get('button').contains('Undo').click()
|
||||||
cy.get('.tiptap').should('contain', 'Hello world')
|
cy.get('.tiptap').should('contain', 'Hello world')
|
||||||
cy.get('button').contains('redo').click()
|
cy.get('button').contains('Redo').click()
|
||||||
cy.get('.tiptap').should('not.contain', 'Hello world')
|
cy.get('.tiptap').should('not.contain', 'Hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,73 +1,83 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :disabled="!editor.can().chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :disabled="!editor.can().chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :disabled="!editor.can().chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :disabled="!editor.can().chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :disabled="!editor.can().chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :disabled="!editor.can().chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCode().run()" :disabled="!editor.can().chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
<button @click="editor.chain().focus().toggleCode().run()" :disabled="!editor.can().chain().focus().toggleCode().run()" :class="{ 'is-active': editor.isActive('code') }">
|
||||||
code
|
Code
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
<button @click="editor.chain().focus().unsetAllMarks().run()">
|
||||||
clear marks
|
Clear marks
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().clearNodes().run()">
|
<button @click="editor.chain().focus().clearNodes().run()">
|
||||||
clear nodes
|
Clear nodes
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">
|
||||||
h4
|
H4
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">
|
||||||
h5
|
H5
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">
|
||||||
h6
|
H6
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
<button @click="editor.chain().focus().toggleBulletList().run()" :class="{ 'is-active': editor.isActive('bulletList') }">
|
||||||
bullet list
|
Bullet list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
<button @click="editor.chain().focus().toggleOrderedList().run()" :class="{ 'is-active': editor.isActive('orderedList') }">
|
||||||
ordered list
|
Ordered list
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
<button @click="editor.chain().focus().toggleCodeBlock().run()" :class="{ 'is-active': editor.isActive('codeBlock') }">
|
||||||
code block
|
Code block
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
<button @click="editor.chain().focus().toggleBlockquote().run()" :class="{ 'is-active': editor.isActive('blockquote') }">
|
||||||
blockquote
|
Blockquote
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
<button @click="editor.chain().focus().setHorizontalRule().run()">
|
||||||
horizontal rule
|
Horizontal rule
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setHardBreak().run()">
|
<button @click="editor.chain().focus().setHardBreak().run()">
|
||||||
hard break
|
Hard break
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().undo().run()" :disabled="!editor.can().chain().focus().undo().run()">
|
<button @click="editor.chain().focus().undo().run()" :disabled="!editor.can().chain().focus().undo().run()">
|
||||||
undo
|
Undo
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().redo().run()" :disabled="!editor.can().chain().focus().redo().run()">
|
<button @click="editor.chain().focus().redo().run()" :disabled="!editor.can().chain().focus().redo().run()">
|
||||||
redo
|
Redo
|
||||||
|
</button>
|
||||||
|
<button @click="editor.chain().focus().setColor('#958DF1').run()" :class="{ 'is-active': editor.isActive('textStyle', { color: '#958DF1' }) }">
|
||||||
|
Purple
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { Color } from '@tiptap/extension-color'
|
||||||
|
import ListItem from '@tiptap/extension-list-item'
|
||||||
|
import TextStyle from '@tiptap/extension-text-style'
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
import { Editor, EditorContent } from '@tiptap/vue-3'
|
import { Editor, EditorContent } from '@tiptap/vue-3'
|
||||||
|
|
||||||
@ -85,6 +95,8 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.editor = new Editor({
|
this.editor = new Editor({
|
||||||
extensions: [
|
extensions: [
|
||||||
|
Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
||||||
|
TextStyle.configure({ types: [ListItem.name] }),
|
||||||
StarterKit,
|
StarterKit,
|
||||||
],
|
],
|
||||||
content: `
|
content: `
|
||||||
@ -92,7 +104,7 @@ export default {
|
|||||||
Hi there,
|
Hi there,
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<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:
|
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>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@ -129,15 +141,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
> * + * {
|
:first-child {
|
||||||
margin-top: 0.75em;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -145,41 +165,68 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<node-view-wrapper class="draw">
|
<node-view-wrapper class="draw">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<input type="color" v-model="color">
|
<input type="color" v-model="color">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -8,8 +10,9 @@
|
|||||||
v-model="size"
|
v-model="size"
|
||||||
>
|
>
|
||||||
<button @click="clear">
|
<button @click="clear">
|
||||||
clear
|
Clear
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
<svg viewBox="0 0 500 250" ref="canvas">
|
<svg viewBox="0 0 500 250" ref="canvas">
|
||||||
<template v-for="item in node.attrs.lines">
|
<template v-for="item in node.attrs.lines">
|
||||||
<path
|
<path
|
||||||
@ -22,6 +25,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</svg>
|
</svg>
|
||||||
|
</div>
|
||||||
</node-view-wrapper>
|
</node-view-wrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -12,44 +12,46 @@ const MenuBar = ({ editor }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="control-group">
|
||||||
|
<div className="button-group">
|
||||||
<button onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} className={editor.isActive('heading', { level: 1 }) ? 'is-active' : ''}>
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} className={editor.isActive('heading', { level: 2 }) ? 'is-active' : ''}>
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}>
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setParagraph().run()} className={editor.isActive('paragraph') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setParagraph().run()} className={editor.isActive('paragraph') ? 'is-active' : ''}>
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleBold().run()} className={editor.isActive('bold') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleBold().run()} className={editor.isActive('bold') ? 'is-active' : ''}>
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleItalic().run()} className={editor.isActive('italic') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleItalic().run()} className={editor.isActive('italic') ? 'is-active' : ''}>
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleStrike().run()} className={editor.isActive('strike') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleStrike().run()} className={editor.isActive('strike') ? 'is-active' : ''}>
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().toggleHighlight().run()} className={editor.isActive('highlight') ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().toggleHighlight().run()} className={editor.isActive('highlight') ? 'is-active' : ''}>
|
||||||
highlight
|
Highlight
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('left').run()} className={editor.isActive({ textAlign: 'left' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('left').run()} className={editor.isActive({ textAlign: 'left' }) ? 'is-active' : ''}>
|
||||||
left
|
Left
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('center').run()} className={editor.isActive({ textAlign: 'center' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('center').run()} className={editor.isActive({ textAlign: 'center' }) ? 'is-active' : ''}>
|
||||||
center
|
Center
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('right').run()} className={editor.isActive({ textAlign: 'right' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('right').run()} className={editor.isActive({ textAlign: 'right' }) ? 'is-active' : ''}>
|
||||||
right
|
Right
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => editor.chain().focus().setTextAlign('justify').run()} className={editor.isActive({ textAlign: 'justify' }) ? 'is-active' : ''}>
|
<button onClick={() => editor.chain().focus().setTextAlign('justify').run()} className={editor.isActive({ textAlign: 'justify' }) ? 'is-active' : ''}>
|
||||||
justify
|
Justify
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,9 +93,9 @@ export default () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<MenuBar editor={editor} />
|
<MenuBar editor={editor} />
|
||||||
<EditorContent editor={editor} />
|
<EditorContent editor={editor} />
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ context('/src/Examples/Formatting/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const marks = [
|
const marks = [
|
||||||
{ label: 'highlight', mark: 'mark' },
|
{ label: 'Highlight', mark: 'mark' },
|
||||||
]
|
]
|
||||||
|
|
||||||
marks.forEach(m => {
|
marks.forEach(m => {
|
||||||
@ -20,10 +20,10 @@ context('/src/Examples/Formatting/React/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const alignments = [
|
const alignments = [
|
||||||
{ label: 'left', alignment: 'left' },
|
{ label: 'Left', alignment: 'left' },
|
||||||
{ label: 'center', alignment: 'center' },
|
{ label: 'Center', alignment: 'center' },
|
||||||
{ label: 'right', alignment: 'right' },
|
{ label: 'Right', alignment: 'right' },
|
||||||
{ label: 'justify', alignment: 'justify' },
|
{ label: 'Justify', alignment: 'justify' },
|
||||||
]
|
]
|
||||||
|
|
||||||
alignments.forEach(a => {
|
alignments.forEach(a => {
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin-top: 1rem;
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
> * + * {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -18,45 +24,75 @@
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
background-color: #FAF594;
|
background-color: #FAF594;
|
||||||
}
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
img {
|
padding: 0.1rem 0.3rem;
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ context('/src/Examples/Formatting/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const marks = [
|
const marks = [
|
||||||
{ label: 'highlight', mark: 'mark' },
|
{ label: 'Highlight', mark: 'mark' },
|
||||||
]
|
]
|
||||||
|
|
||||||
marks.forEach(m => {
|
marks.forEach(m => {
|
||||||
@ -20,10 +20,10 @@ context('/src/Examples/Formatting/Vue/', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const alignments = [
|
const alignments = [
|
||||||
{ label: 'left', alignment: 'left' },
|
{ label: 'Left', alignment: 'left' },
|
||||||
{ label: 'center', alignment: 'center' },
|
{ label: 'Center', alignment: 'center' },
|
||||||
{ label: 'right', alignment: 'right' },
|
{ label: 'Right', alignment: 'right' },
|
||||||
{ label: 'justify', alignment: 'justify' },
|
{ label: 'Justify', alignment: 'justify' },
|
||||||
]
|
]
|
||||||
|
|
||||||
alignments.forEach(a => {
|
alignments.forEach(a => {
|
||||||
|
@ -1,43 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="editor">
|
<div v-if="editor" class="container">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="button-group">
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">
|
||||||
h1
|
H1
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">
|
||||||
h2
|
H2
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">
|
||||||
h3
|
H3
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
<button @click="editor.chain().focus().setParagraph().run()" :class="{ 'is-active': editor.isActive('paragraph') }">
|
||||||
paragraph
|
Paragraph
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
<button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
|
||||||
bold
|
Bold
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
<button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
|
||||||
italic
|
Italic
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
<button @click="editor.chain().focus().toggleStrike().run()" :class="{ 'is-active': editor.isActive('strike') }">
|
||||||
strike
|
Strike
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().toggleHighlight().run()" :class="{ 'is-active': editor.isActive('highlight') }">
|
<button @click="editor.chain().focus().toggleHighlight().run()" :class="{ 'is-active': editor.isActive('highlight') }">
|
||||||
highlight
|
Highlight
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('left').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }">
|
<button @click="editor.chain().focus().setTextAlign('left').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }">
|
||||||
left
|
Left
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('center').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }">
|
<button @click="editor.chain().focus().setTextAlign('center').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }">
|
||||||
center
|
Center
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('right').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }">
|
<button @click="editor.chain().focus().setTextAlign('right').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }">
|
||||||
right
|
Right
|
||||||
</button>
|
</button>
|
||||||
<button @click="editor.chain().focus().setTextAlign('justify').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'justify' }) }">
|
<button @click="editor.chain().focus().setTextAlign('justify').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'justify' }) }">
|
||||||
justify
|
Justify
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -104,17 +108,23 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Basic editor styles */
|
/* Basic editor styles */
|
||||||
.tiptap {
|
.tiptap {
|
||||||
margin-top: 1rem;
|
:first-child {
|
||||||
|
margin-top: 0;
|
||||||
> * + * {
|
|
||||||
margin-top: 0.75em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* List styles */
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
margin: 1.25rem 1rem 1.25rem 0.4rem;
|
||||||
|
|
||||||
|
li p {
|
||||||
|
margin-top: 0.25em;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Heading styles */
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
@ -122,45 +132,75 @@ export default {
|
|||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-wrap: pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
margin-top: 3.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code and preformatted text styles */
|
||||||
code {
|
code {
|
||||||
background-color: rgba(#616161, 0.1);
|
background-color: var(--purple-light);
|
||||||
color: #616161;
|
border-radius: 0.4rem;
|
||||||
|
color: var(--black);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding: 0.25em 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background: #0D0D0D;
|
background: var(--black);
|
||||||
color: #FFF;
|
|
||||||
font-family: 'JetBrainsMono', monospace;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
color: var(--white);
|
||||||
|
font-family: 'JetBrainsMono', monospace;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: inherit;
|
|
||||||
padding: 0;
|
|
||||||
background: none;
|
background: none;
|
||||||
|
color: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
background-color: #FAF594;
|
background-color: #FAF594;
|
||||||
}
|
border-radius: 0.4rem;
|
||||||
|
box-decoration-break: clone;
|
||||||
img {
|
padding: 0.1rem 0.3rem;
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
|
border-left: 3px solid var(--gray-3);
|
||||||
|
margin: 1.5rem 0;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
border-top: 1px solid var(--gray-2);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,13 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<button onClick={addImage}>add image from URL</button>
|
<div className="control-group">
|
||||||
<EditorContent editor={editor} />
|
<div className="button-group">
|
||||||
|
<button onClick={addImage}>Add image from URL</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditorContent editor={editor} />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user