Merge in master, follow PR review suggestions

- @roschaefer suggested to 'Ask the user to type in the name of the resource that should be destroyed'
- he also showed concern for setting `wrapper.setData({ deleteEnabled: true })`, this commit allows interaction in the component tests with the input field that sets deleteEnabled to true if it matches the resource that should be destroyed
- this `PR` also removes the use of buefy and it's underlying bulma since we don't need a switch or check boxes
- german translations have also been added
This commit is contained in:
Matt Rider 2019-06-10 13:30:45 -03:00
commit 1c506bd21c
9 changed files with 186 additions and 115 deletions

View File

@ -16,6 +16,12 @@ describe('DeleteAccount.vue', () => {
let getters
let actions
let deleteAccountBtn
let enableDeletionInput
let enablePostDeletionInput
let enableCommentDeletionInput
const deleteAccountName = 'Delete MyAccount'
const deletePostsMessage = 'Delete my 2 posts'
const deleteCommentsMessage = 'Delete my 3 comments'
beforeEach(() => {
mocks = {
@ -44,7 +50,7 @@ describe('DeleteAccount.vue', () => {
}
getters = {
'auth/user': () => {
return { id: 'u343' }
return { id: 'u343', name: deleteAccountName, contributionsCount: 2, commentsCount: 3 }
},
}
actions = { 'auth/logout': jest.fn() }
@ -87,7 +93,8 @@ describe('DeleteAccount.vue', () => {
describe('calls the delete user mutation', () => {
beforeEach(() => {
wrapper.setData({ deleteEnabled: true })
enableDeletionInput = wrapper.find('.enable-deletion-input input')
enableDeletionInput.setValue(deleteAccountName)
deleteAccountBtn = wrapper.find('.ds-button-danger')
})
@ -104,7 +111,9 @@ describe('DeleteAccount.vue', () => {
})
it("deletes a user's posts if requested", () => {
wrapper.setData({ deleteContributions: true })
mocks.$t.mockImplementation(() => deletePostsMessage)
enablePostDeletionInput = wrapper.find('.enable-post-deletion-input input')
enablePostDeletionInput.setValue(deletePostsMessage)
deleteAccountBtn.trigger('click')
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(
expect.objectContaining({
@ -117,7 +126,9 @@ describe('DeleteAccount.vue', () => {
})
it("deletes a user's comments if requested", () => {
wrapper.setData({ deleteComments: true })
mocks.$t.mockImplementation(() => deleteCommentsMessage)
enableCommentDeletionInput = wrapper.find('.enable-comment-deletion-input input')
enableCommentDeletionInput.setValue(deleteCommentsMessage)
deleteAccountBtn.trigger('click')
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(
expect.objectContaining({
@ -130,7 +141,12 @@ describe('DeleteAccount.vue', () => {
})
it("deletes a user's posts and comments if requested", () => {
wrapper.setData({ deleteContributions: true, deleteComments: true })
mocks.$t.mockImplementation(() => deletePostsMessage)
enablePostDeletionInput = wrapper.find('.enable-post-deletion-input input')
enablePostDeletionInput.setValue(deletePostsMessage)
mocks.$t.mockImplementation(() => deleteCommentsMessage)
enableCommentDeletionInput = wrapper.find('.enable-comment-deletion-input input')
enableCommentDeletionInput.setValue(deleteCommentsMessage)
deleteAccountBtn.trigger('click')
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(
expect.objectContaining({
@ -155,7 +171,8 @@ describe('DeleteAccount.vue', () => {
describe('error handling', () => {
it('shows an error toaster when the mutation rejects', async () => {
wrapper.setData({ deleteEnabled: true })
enableDeletionInput = wrapper.find('.enable-deletion-input input')
enableDeletionInput.setValue(deleteAccountName)
deleteAccountBtn = wrapper.find('.ds-button-danger')
await deleteAccountBtn.trigger('click')
// second submission causes mutation to reject

View File

@ -1,70 +1,95 @@
<template>
<div>
<ds-card hover>
<ds-space />
<ds-space/>
<ds-container>
<ds-flex>
<ds-flex-item :width="{ base: '100%', sm: 0.75, md: 0.5, lg: 0.5 }">
<ds-icon name="warning" size="xxx-large" class="delete-warning-icon" />
<ds-icon name="warning" size="xxx-large" class="delete-warning-icon"/>
</ds-flex-item>
<ds-flex-item :width="{ base: '100%', sm: 5.25, md: 2.75, lg: 5.5 }">
<ds-heading>{{ $t('settings.delete.name') }}</ds-heading>
<ds-heading>{{ $t('settings.deleteUserAccount.name') }}</ds-heading>
</ds-flex-item>
<ds-space />
<ds-heading tag="h4">{{ $t('settings.delete.accountDescription') }}</ds-heading>
<ds-space/>
<ds-heading tag="h4">{{ $t('settings.deleteUserAccount.accountDescription') }}</ds-heading>
</ds-flex>
</ds-container>
<ds-space />
<ds-space/>
<ds-container>
<transition name="slide-up">
<div v-if="deleteEnabled">
<div class="field">
<div class="control">
<b-checkbox
type="is-danger"
:disabled="!currentUser.contributionsCount"
v-model="deleteContributions"
>
{{ $t('settings.delete.countPosts', { count: currentUser.contributionsCount }) }}
</b-checkbox>
</div>
</div>
<div class="field">
<div class="control">
<b-checkbox
type="is-danger"
:disabled="!currentUser.commentsCount"
v-model="deleteComments"
>
{{ $t('settings.delete.countComments', { count: currentUser.commentsCount }) }}
</b-checkbox>
</div>
</div>
<ds-flex :gutter="{ base: 'xx-small', md: 'small', lg: 'large' }">
<ds-flex-item
v-if="currentUser.contributionsCount"
:width="{ base: '100%', sm: '100%', md: '100%', lg: '100%' }"
>
<div
class="delete-input-label"
v-html="
$t('settings.deleteUserAccount.pleaseConfirm', {
confirm: $t('settings.deleteUserAccount.contributionsCount', {
count: currentUser.contributionsCount,
}),
})
"
></div>
<ds-input
v-model="deleteContributionsValue"
@input="enableDeletion"
class="enable-post-deletion-input"
/>
</ds-flex-item>
</ds-flex>
<ds-space margin-top="xx-small"/>
<ds-flex :gutter="{ base: 'xx-small', md: 'small', lg: 'large' }">
<ds-flex-item
v-if="currentUser.commentsCount"
:width="{ base: '100%', sm: '100%', md: '100%', lg: '100%' }"
>
<div
class="delete-input-label"
v-html="
$t('settings.deleteUserAccount.pleaseConfirm', {
confirm: $t('settings.deleteUserAccount.commentsCount', {
count: currentUser.commentsCount,
}),
})
"
></div>
<ds-input
v-model="deleteCommentsValue"
@input="enableDeletion"
class="enable-comment-deletion-input"
/>
</ds-flex-item>
</ds-flex>
<div class="message is-danger">
<div class="message-body" v-html="$t('settings.delete.accountWarning')"></div>
<div class="message-body" v-html="$t('settings.deleteUserAccount.accountWarning')"></div>
</div>
</div>
</transition>
</ds-container>
<template slot="footer">
<ds-container>
<ds-flex>
<ds-flex-item :width="{ base: '60%', sm: 1.25, md: 1.25, lg: 1.75 }">
<div class="columns is-mobile">
<div class="column">
<b-switch type="is-danger" v-model="deleteEnabled"></b-switch>
</div>
</div>
<ds-flex :gutter="{ base: 'xx-small', md: 'small', lg: 'large' }">
<ds-flex-item :width="{ base: '100%', sm: '100%', md: '100%', lg: 1.75 }">
<div
class="delete-input-label"
v-html="$t('settings.deleteUserAccount.pleaseConfirm', { confirm: currentUser.name })"
></div>
<ds-input
v-model="enableDeletionValue"
@input="enableDeletion"
class="enable-deletion-input"
/>
</ds-flex-item>
<ds-flex-item :width="{ base: '60%', sm: 2.75, md: 2.75, lg: 1 }">
<ds-flex-item :width="{ base: '100%', sm: '100%', md: '100%', lg: 1 }">
<ds-button
icon="trash"
danger
:disabled="isLoading || !deleteEnabled"
@click="handleSubmit"
>
{{ $t('settings.delete.name') }}
</ds-button>
>{{ $t('settings.deleteUserAccount.name') }}</ds-button>
</ds-flex-item>
</ds-flex>
</ds-container>
@ -84,6 +109,9 @@ export default {
deleteComments: false,
deleteEnabled: false,
isLoading: false,
enableDeletionValue: '',
deleteContributionsValue: '',
deleteCommentsValue: '',
}
},
computed: {
@ -95,6 +123,28 @@ export default {
...mapActions({
logout: 'auth/logout',
}),
enableDeletion() {
if (this.enableDeletionValue === this.currentUser.name) {
this.deleteEnabled = true
this.focused = false
}
if (
this.deleteContributionsValue ===
this.$t('settings.deleteUserAccount.contributionsCount', {
count: this.currentUser.contributionsCount,
})
) {
this.deleteContributions = true
}
if (
this.deleteCommentsValue ===
this.$t('settings.deleteUserAccount.commentsCount', {
count: this.currentUser.commentsCount,
})
) {
this.deleteComments = true
}
},
handleSubmit() {
let resourceArgs = []
if (this.deleteContributions) {
@ -115,7 +165,7 @@ export default {
variables: { id: this.currentUser.id, resource: resourceArgs },
})
.then(() => {
this.$toast.success(this.$t('settings.delete.success'))
this.$toast.success(this.$t('settings.deleteUserAccount.success'))
this.logout()
this.$router.history.push('/')
})
@ -130,4 +180,27 @@ export default {
.delete-warning-icon {
color: $color-danger;
}
.enable-deletion-input input:focus,
.enable-post-deletion-input input:focus,
.enable-comment-deletion-input input:focus {
border-color: $border-color-danger;
}
.ds-button-danger {
margin-top: 1.55rem;
}
.delete-input-label {
font-size: $font-size-base;
}
b.is-danger {
color: $text-color-danger;
}
.ds-card-footer {
border-top: $border-size-base solid $border-color-softest;
background-color: $background-color-warning-inverse;
}
</style>

View File

@ -73,8 +73,14 @@
"download": {
"name": "Daten herunterladen"
},
"delete": {
"name": "Konto löschen"
"deleteUserAccount": {
"name": "Mein Benutzerkonto löschen",
"contributionsCount": "Meine {count} Beiträge löschen",
"commentsCount": "Meine {count} Kommentare löschen",
"accountDescription": "Seien Sie sich bewusst, dass Ihre Beiträge und Kommentare für unsere Community wichtig sind. Wenn du sie trotzdem löschen möchtest, musst du dies unten auswählen.",
"accountWarning": "Dein Benutzerkonto, die Beiträge, etc. kannst Du nach dem Löschen <b>WEDER VERWALTEN NOCH WIEDERHERSTELLEN!</b>",
"success": "Konto erfolgreich gelöscht",
"pleaseConfirm": "<b class='is-danger'>Zerstörerische Aktion!</b> Geben Sie <b>{confirm}</b> ein, um zu bestätigen."
},
"organizations": {
"name": "Meine Organisationen"

View File

@ -73,13 +73,14 @@
"download": {
"name": "Download Data"
},
"delete": {
"deleteUserAccount": {
"name": "Delete my User Account",
"countPosts": "Delete my {count} posts",
"countComments": "Delete my {count} comments",
"accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete those you have to mark them below.",
"contributionsCount": "Delete my {count} posts",
"commentsCount": "Delete my {count} comments",
"accountDescription": "Be aware that your Post and Comments are important to our community. If you still want to delete them, you have to choose so below.",
"accountWarning": "You <b>CAN'T MANAGE</b> and <b>CAN'T RECOVER</b> your Account, Posts... after deleting your account!",
"success": "Account successfully deleted"
"success": "Account successfully deleted",
"pleaseConfirm": "<b class='is-danger'>Destructive action!</b> Type <b>{confirm}</b> to confirm"
},
"organizations": {
"name": "My Organizations"

View File

@ -81,7 +81,6 @@ module.exports = {
{ src: '~/plugins/v-tooltip.js', ssr: false },
{ src: '~/plugins/izi-toast.js', ssr: false },
{ src: '~/plugins/vue-filters.js' },
{ src: '~/plugins/buefy.js' },
],
router: {

View File

@ -56,9 +56,8 @@
"@nuxtjs/style-resources": "~0.1.2",
"accounting": "~0.4.1",
"apollo-cache-inmemory": "~1.5.1",
"apollo-client": "~2.6.1",
"buefy": "^0.7.7",
"cookie-universal-nuxt": "~2.0.14",
"apollo-client": "~2.6.2",
"cookie-universal-nuxt": "~2.0.16",
"cross-env": "~5.2.0",
"date-fns": "2.0.0-alpha.31",
"express": "~4.17.1",
@ -71,7 +70,7 @@
"stack-utils": "^1.0.2",
"string-hash": "^1.1.3",
"tiptap": "1.20.1",
"tiptap-extensions": "1.21.0",
"tiptap-extensions": "1.22.1",
"v-tooltip": "~2.0.2",
"vue-count-to": "~1.0.13",
"vue-izitoast": "1.1.2",
@ -105,9 +104,9 @@
"jest": "~24.8.0",
"node-sass": "~4.12.0",
"nodemon": "~1.19.1",
"prettier": "~1.18.0",
"prettier": "~1.18.2",
"sass-loader": "~7.1.0",
"tippy.js": "^4.3.3",
"tippy.js": "^4.3.4",
"vue-jest": "~3.0.4",
"vue-svg-loader": "~0.12.0"
}

View File

@ -3,11 +3,11 @@
<ds-heading tag="h1">{{ $t('settings.name') }}</ds-heading>
<ds-flex gutter="small">
<ds-flex-item :width="{ base: '100%', md: '200px' }">
<ds-menu :routes="routes" :is-exact="() => true" />
<ds-menu :routes="routes" :is-exact="() => true"/>
</ds-flex-item>
<ds-flex-item :width="{ base: '100%', md: 1 }">
<transition name="slide-up" appear>
<nuxt-child />
<nuxt-child/>
</transition>
</ds-flex-item>
</ds-flex>
@ -32,7 +32,7 @@ export default {
path: `/settings/my-social-media`,
},
{
name: this.$t('settings.delete.name'),
name: this.$t('settings.deleteUserAccount.name'),
path: `/settings/delete-account`,
},
// TODO implement

View File

@ -1,12 +0,0 @@
import Vue from 'vue'
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'
Vue.use(Buefy, {
defaultIconPack: 'fa',
defaultTooltipAnimated: true,
defaultTooltipType: 'is-black',
defaultToastDuration: 6000,
defaultSnackbarDuration: 5000,
defaultNoticeQueue: true,
})

View File

@ -1893,7 +1893,7 @@ apollo-cache@1.3.2, apollo-cache@^1.2.1:
apollo-utilities "^1.3.2"
tslib "^1.9.3"
apollo-client@^2.5.1, apollo-client@~2.6.1:
apollo-client@^2.5.1, apollo-client@~2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.6.2.tgz#03b6af651e09b6e413e486ddc87464c85bd6e514"
integrity sha512-oks1MaT5x7gHcPeC8vPC1UzzsKaEIC0tye+jg72eMDt5OKc7BobStTeS/o2Ib3e0ii40nKxGBnMdl/Xa/p56Yg==
@ -2696,13 +2696,6 @@ bser@^2.0.0:
dependencies:
node-int64 "^0.4.0"
buefy@^0.7.7:
version "0.7.7"
resolved "https://registry.yarnpkg.com/buefy/-/buefy-0.7.7.tgz#0e0dea84e776959bf2c23110541d67a94eaaa1de"
integrity sha512-UuPD+/749s6XzRL2INoJxykOygcBo1pVlLlSJ7wodY228LGOYsURXSkMrCxeemwhvWzSq/UJ+D8X9BkyIw6Tww==
dependencies:
bulma "0.7.5"
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
@ -2737,11 +2730,6 @@ builtin-status-codes@^3.0.0:
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
bulma@0.7.5:
version "0.7.5"
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.7.5.tgz#35066c37f82c088b68f94450be758fc00a967208"
integrity sha512-cX98TIn0I6sKba/DhW0FBjtaDpxTelU166pf7ICXpCCuplHWyu6C9LYZmL5PEsnePIeJaiorsTEzzNk3Tsm1hw==
busboy@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
@ -3317,18 +3305,18 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
cookie-universal-nuxt@~2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/cookie-universal-nuxt/-/cookie-universal-nuxt-2.0.14.tgz#6fdf8e928eadd7611c04a57614fe2e29b60eb971"
integrity sha512-ih9Z0Z2K6eLaugTttGCVN85nogKseIFF/dqup3klvYC4mQS3+1IloqBqzTL/N7degBBAols2oppwYNDmaRtVig==
cookie-universal-nuxt@~2.0.16:
version "2.0.16"
resolved "https://registry.yarnpkg.com/cookie-universal-nuxt/-/cookie-universal-nuxt-2.0.16.tgz#8d528098c973162b352199240e40da0e5429b13f"
integrity sha512-wRK2zw8w+a5xPehb5kLbgOic/4mbjl2exUCxWZwGuttcwsFgOymiwDrCOzmQslqrDevPDL2SsBbH6wtOm7dB9g==
dependencies:
"@types/cookie" "^0.3.1"
cookie-universal "^2.0.14"
cookie-universal "^2.0.16"
cookie-universal@^2.0.14:
version "2.0.14"
resolved "https://registry.yarnpkg.com/cookie-universal/-/cookie-universal-2.0.14.tgz#1b4f27cffccfc2e47703fa235c1f67f931213041"
integrity sha512-m6J0DQa4/RQvXhzUG37EY1ynK3Uq1BKzp5hotST9olrzjrRx+B0vNPx7azg0/X0XrYQvL7MMbPXwou8m0BNDwg==
cookie-universal@^2.0.16:
version "2.0.16"
resolved "https://registry.yarnpkg.com/cookie-universal/-/cookie-universal-2.0.16.tgz#ec8b55789b502a377ef02ad230923c1dfa5c1061"
integrity sha512-EHtQ5Tg3UoUHG7LmeV3rlV3iYthkhUuYZ0y86EseypxGcUuvzxuHExEb6mHKDhDPrIrdewAHdG/aCHuG/T4zEg==
dependencies:
"@types/cookie" "^0.3.1"
cookie "^0.3.1"
@ -8871,10 +8859,10 @@ prettier@1.16.3:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d"
integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==
prettier@^1.15.2, prettier@~1.18.0:
version "1.18.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.0.tgz#d1701ca9b2941864b52f3262b35946d2c9cd88f0"
integrity sha512-YsdAD29M0+WY2xXZk3i0PA16olY9qZss+AuODxglXcJ+2ZBwFv+6k5tE8GS8/HKAthaajlS/WqhdgcjumOrPlg==
prettier@^1.15.2, prettier@~1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
pretty-bytes@^5.2.0:
version "5.2.0"
@ -10570,10 +10558,10 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tippy.js@^4.3.3:
version "4.3.3"
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-4.3.3.tgz#396304bea577bbff03f2700a1761329e8c1fce86"
integrity sha512-2fPMlquzVQxpLoOd0eJA1sPZ86/R6zD/9985wV0d2zhhX52DiO3aeg7TTS/mBrUjgFwVZh19YLb4l2c8bJkQPw==
tippy.js@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-4.3.4.tgz#9a91fd5ce8c401f181b7adaa6b2c27f3d105f3ba"
integrity sha512-O2ukxHOJTLVYZ/TfHjNd8WgAWoefX9uk5QiWRdHfX2PR2lBpUU4BJQLl7U2Ykc8K7o16gTeHEElpuRfgD5b0aA==
dependencies:
popper.js "^1.14.7"
@ -10591,10 +10579,10 @@ tiptap-commands@^1.10.5, tiptap-commands@^1.10.7:
prosemirror-utils "^0.9.0"
tiptap-utils "^1.5.5"
tiptap-extensions@1.21.0:
version "1.21.0"
resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.21.0.tgz#c2f228144b6943755d2de4617e11febe08c78a42"
integrity sha512-dIm9Q/G1qL1+sEqQiPXElUzSBcRhXXPuyOdtHgMrncUaCbnaDxsHdkJl700OXfA/GCu7AlhUpd3R67Rmb+voCQ==
tiptap-extensions@1.22.1:
version "1.22.1"
resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.22.1.tgz#733e5215eb0ef59a3e13e450445bd4f52dc5284d"
integrity sha512-yTQP7A/ycCL22FHlU3gHkXzeajaX37LsTl1B265y4yfGYKHyvUrN57MjoHLfwojT1nLa5m9959BNTH9Kof9+Xg==
dependencies:
lowlight "^1.12.1"
prosemirror-collab "^1.1.2"
@ -10605,7 +10593,7 @@ tiptap-extensions@1.21.0:
prosemirror-transform "^1.1.3"
prosemirror-utils "^0.9.0"
prosemirror-view "^1.9.8"
tiptap "^1.21.1"
tiptap "^1.22.1"
tiptap-commands "^1.10.7"
tiptap-utils@^1.5.3:
@ -10644,10 +10632,10 @@ tiptap@1.20.1:
tiptap-commands "^1.10.5"
tiptap-utils "^1.5.3"
tiptap@^1.21.1:
version "1.21.1"
resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.21.1.tgz#c0340375795088b899541b64ce86ae45e98d0369"
integrity sha512-vCKT/UGorAx1SSX5+9vmtZa+WC+LKfJIArgkEJFXmxfZeyBhNXRSwR+rR+UtdPYi8V4CtmIwtv6eRPP+bH6SWA==
tiptap@^1.22.1:
version "1.22.1"
resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.22.1.tgz#c5bf87216176a8c52e808b611d744c4258447efe"
integrity sha512-34kuR26SmU2DDV79mtd8B9VjllZTVNOVTHlnQGhM4Wk7Psn294GYMnNIT7D+HGoo/nNptxjcj1+VfWOPKUgWEw==
dependencies:
prosemirror-commands "^1.0.8"
prosemirror-dropcursor "^1.1.1"