diff --git a/cypress/e2e/misc/editor.spec.ts b/cypress/e2e/misc/editor.spec.ts deleted file mode 100644 index 0a1b64294..000000000 --- a/cypress/e2e/misc/editor.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {createFakeUserAndLogin} from '../../support/authenticateUser' - -import {TaskFactory} from '../../factories/task' -import {ProjectFactory} from '../../factories/project' -import {UserProjectFactory} from '../../factories/users_project' -import {BucketFactory} from '../../factories/bucket' - -describe('Editor', () => { - createFakeUserAndLogin() - - beforeEach(() => { - ProjectFactory.create(1) - BucketFactory.create(1) - TaskFactory.truncate() - UserProjectFactory.truncate() - }) - - it('Has a preview with checkable checkboxes', () => { - const tasks = TaskFactory.create(1, { - description: `# Test Heading -* Bullet 1 -* Bullet 2 - -* [ ] Checklist -* [x] Checklist checked -`, - bucket_id: 1, - }) - - cy.visit(`/tasks/${tasks[0].id}`) - cy.get('input[type=checkbox][data-checkbox-num=0]') - .click() - - cy.get('.task-view .details.content.description h3 span.is-small.has-text-success') - .contains('Saved!') - .should('exist') - cy.get('.preview.content') - .should('contain', 'Test Heading') - }) -}) \ No newline at end of file diff --git a/cypress/e2e/task/task.spec.ts b/cypress/e2e/task/task.spec.ts index 5963a7597..c2019f08b 100644 --- a/cypress/e2e/task/task.spec.ts +++ b/cypress/e2e/task/task.spec.ts @@ -24,7 +24,7 @@ function addLabelToTaskAndVerify(labelTitle: string) { .first() .click() - cy.get('.global-notification', { timeout: 4000 }) + cy.get('.global-notification', {timeout: 4000}) .should('contain', 'Success') cy.get('.task-view .details.labels-list .multiselect .input-wrapper span.tag') .should('exist') @@ -122,7 +122,7 @@ describe('Task', () => { const tasks = TaskFactory.create(1, { id: 1, index: 1, - description: 'Lorem ipsum dolor sit amet.' + description: 'Lorem ipsum dolor sit amet.', }) cy.visit(`/tasks/${tasks[0].id}`) @@ -143,7 +143,7 @@ describe('Task', () => { id: 1, index: 1, done: true, - done_at: new Date().toISOString() + done_at: new Date().toISOString(), }) cy.visit(`/tasks/${tasks[0].id}`) @@ -196,13 +196,13 @@ describe('Task', () => { it('Can edit the description', () => { const tasks = TaskFactory.create(1, { id: 1, - description: 'Lorem ipsum dolor sit amet.' + description: 'Lorem ipsum dolor sit amet.', }) cy.visit(`/tasks/${tasks[0].id}`) - cy.get('.task-view .details.content.description .editor button') + cy.get('.task-view .details.content.description .tiptap button.done-edit') .click() - cy.get('.task-view .details.content.description .editor .vue-easymde .EasyMDEContainer .CodeMirror-scroll') + cy.get('.task-view .details.content.description .tiptap__editor .tiptap.ProseMirror') .type('{selectall}New Description') cy.get('[data-cy="saveEditor"]') .contains('Save') @@ -219,7 +219,7 @@ describe('Task', () => { }) cy.visit(`/tasks/${tasks[0].id}`) - cy.get('.task-view .comments .media.comment .editor .vue-easymde .EasyMDEContainer .CodeMirror-scroll') + cy.get('.task-view .comments .media.comment .tiptap__editor .tiptap.ProseMirror') .should('be.visible') .type('{selectall}New Comment') cy.get('.task-view .comments .media.comment .button:not([disabled])') @@ -227,7 +227,7 @@ describe('Task', () => { .should('be.visible') .click() - cy.get('.task-view .comments .media.comment .editor') + cy.get('.task-view .comments .media.comment .tiptap__editor') .should('contain', 'New Comment') cy.get('.global-notification') .should('contain', 'Success') @@ -236,7 +236,7 @@ describe('Task', () => { it('Can move a task to another project', () => { const projects = ProjectFactory.create(2) BucketFactory.create(2, { - project_id: '{increment}' + project_id: '{increment}', }) const tasks = TaskFactory.create(1, { id: 1, @@ -380,7 +380,7 @@ describe('Task', () => { addLabelToTaskAndVerify(labels[0].title) }) - + it('Can add a label to a task and it shows up on the kanban board afterwards', () => { const tasks = TaskFactory.create(1, { id: 1, @@ -389,18 +389,18 @@ describe('Task', () => { }) const labels = LabelFactory.create(1) LabelTaskFactory.truncate() - + cy.visit(`/projects/${projects[0].id}/kanban`) - + cy.get('.bucket .task') .contains(tasks[0].title) .click() - + addLabelToTaskAndVerify(labels[0].title) - + cy.get('.modal-content .close') .click() - + cy.get('.bucket .task') .should('contain.text', labels[0].title) }) @@ -461,7 +461,7 @@ describe('Task', () => { cy.get('.global-notification') .should('contain', 'Success') }) - + it('Can set a reminder', () => { TaskReminderFactory.truncate() const tasks = TaskFactory.create(1, { @@ -543,7 +543,7 @@ describe('Task', () => { cy.get('.global-notification') .should('contain', 'Success') }) - + it('Allows to set a custom relative reminder when the task already has a due date', () => { TaskReminderFactory.truncate() const tasks = TaskFactory.create(1, { @@ -579,7 +579,7 @@ describe('Task', () => { cy.get('.global-notification') .should('contain', 'Success') }) - + it('Allows to set a fixed reminder when the task already has a due date', () => { TaskReminderFactory.truncate() const tasks = TaskFactory.create(1, { @@ -609,7 +609,7 @@ describe('Task', () => { cy.get('.global-notification') .should('contain', 'Success') }) - + it('Can set a priority for a task', () => { const tasks = TaskFactory.create(1, { id: 1, @@ -647,7 +647,7 @@ describe('Task', () => { .select('50%') cy.get('.global-notification') .should('contain', 'Success') - + cy.wait(200) cy.get('.task-view .columns.details .column') @@ -656,7 +656,7 @@ describe('Task', () => { .should('be.visible') .should('have.value', '0.5') }) - + it('Can add an attachment to a task', () => { TaskAttachmentFactory.truncate() const tasks = TaskFactory.create(1, { @@ -691,35 +691,119 @@ describe('Task', () => { cy.get('.bucket .task .footer .icon svg.fa-paperclip') .should('exist') }) - + it('Can check items off a checklist', () => { const tasks = TaskFactory.create(1, { id: 1, description: ` -This is a checklist: - -* [ ] one item -* [ ] another item -* [ ] third item -* [ ] fourth item -* [x] and this one is already done -`, +`, }) cy.visit(`/tasks/${tasks[0].id}`) - + cy.get('.task-view .checklist-summary') .should('contain.text', '1 of 5 tasks') - cy.get('.editor .content ul > li input[type=checkbox]') + cy.get('.tiptap__editor ul > li input[type=checkbox]') .eq(2) .click() - - cy.get('.editor .content ul > li input[type=checkbox]') + + cy.get('.task-view .details.content.description h3 span.is-small.has-text-success') + .contains('Saved!') + .should('exist') + cy.get('.tiptap__editor ul > li input[type=checkbox]') .eq(2) .should('be.checked') - cy.get('.editor .content input[type=checkbox]') + cy.get('.tiptap__editor input[type=checkbox]') .should('have.length', 5) cy.get('.task-view .checklist-summary') .should('contain.text', '2 of 5 tasks') }) + + it('Should use the editor to render description', () => { + const tasks = TaskFactory.create(1, { + id: 1, + description: ` +

Lorem Ipsum

+

Dolor sit amet

+`, + }) + cy.visit(`/tasks/${tasks[0].id}`) + + cy.get('.tiptap__editor ul > li input[type=checkbox]') + .should('exist') + cy.get('.tiptap__editor h1') + .contains('Lorem Ipsum') + .should('exist') + cy.get('.tiptap__editor p') + .contains('Dolor sit amet') + .should('exist') + }) + + it.only('Should render an image from attachment', async () => { + + TaskAttachmentFactory.truncate() + + const tasks = TaskFactory.create(1, { + id: 1, + description: '', + }) + + cy.readFile('cypress/fixtures/image.jpg', null).then(file => { + + const formData = new FormData() + formData.append('files', new Blob([file]), 'image.jpg') + + cy.request({ + method: 'PUT', + url: `${Cypress.env('API_URL')}/tasks/${tasks[0].id}/attachments`, + headers: { + 'Authorization': `Bearer ${window.localStorage.getItem('token')}`, + 'Content-Type': 'multipart/form-data', + }, + body: formData, + }) + .then(({body}) => { + const dec = new TextDecoder('utf-8') + const {success} = JSON.parse(dec.decode(body)) + + TaskFactory.create(1, { + id: 1, + description: `test image`, + }) + + cy.visit(`/tasks/${tasks[0].id}`) + + cy.get('.tiptap__editor img') + .should('be.visible') + .and(($img) => { + // "naturalWidth" and "naturalHeight" are set when the image loads + expect($img[0].naturalWidth).to.be.greaterThan(0) + }) + + }) + }) + }) }) }) diff --git a/package.json b/package.json index e48f74baa..8e579381b 100644 --- a/package.json +++ b/package.json @@ -55,30 +55,64 @@ "@kyvg/vue3-notification": "3.0.2", "@sentry/tracing": "7.74.0", "@sentry/vue": "7.74.0", + "@tiptap/core": "2.1.12", + "@tiptap/extension-blockquote": "2.1.12", + "@tiptap/extension-bold": "2.1.12", + "@tiptap/extension-bullet-list": "2.1.12", + "@tiptap/extension-code": "2.1.12", + "@tiptap/extension-code-block-lowlight": "2.0.3", + "@tiptap/extension-document": "2.0.3", + "@tiptap/extension-dropcursor": "2.1.12", + "@tiptap/extension-gapcursor": "2.1.12", + "@tiptap/extension-hard-break": "2.1.12", + "@tiptap/extension-heading": "2.1.12", + "@tiptap/extension-history": "2.1.12", + "@tiptap/extension-horizontal-rule": "2.1.12", + "@tiptap/extension-image": "2.0.3", + "@tiptap/extension-italic": "2.1.12", + "@tiptap/extension-link": "2.0.3", + "@tiptap/extension-list-item": "2.1.12", + "@tiptap/extension-ordered-list": "2.1.12", + "@tiptap/extension-paragraph": "2.1.12", + "@tiptap/extension-placeholder": "2.1.12", + "@tiptap/extension-strike": "2.1.12", + "@tiptap/extension-table": "2.0.3", + "@tiptap/extension-table-cell": "2.0.3", + "@tiptap/extension-table-header": "2.0.3", + "@tiptap/extension-table-row": "2.0.3", + "@tiptap/extension-task-item": "2.0.3", + "@tiptap/extension-task-list": "2.0.3", + "@tiptap/extension-text": "2.1.12", + "@tiptap/extension-typography": "2.0.3", + "@tiptap/extension-underline": "2.1.12", + "@tiptap/pm": "2.1.12", + "@tiptap/suggestion": "2.1.12", + "@tiptap/vue-3": "2.0.3", + "@types/is-touch-device": "1.0.0", + "@types/lodash.clonedeep": "4.5.7", + "@types/sortablejs": "1.15.0", "@vueuse/core": "10.5.0", "@vueuse/router": "10.5.0", "axios": "1.5.1", "blurhash": "2.0.5", "bulma-css-variables": "0.9.33", "camel-case": "4.1.2", - "codemirror": "5.65.15", "date-fns": "2.30.0", "dayjs": "1.11.10", "dompurify": "3.0.6", - "easymde": "2.18.0", "fast-deep-equal": "3.1.3", "flatpickr": "4.6.13", "flexsearch": "0.7.31", "floating-vue": "2.0.0-beta.24", - "highlight.js": "11.9.0", "is-touch-device": "1.0.1", "klona": "2.0.6", "lodash.debounce": "4.0.8", - "marked": "9.1.2", + "lowlight": "2.7.0", "pinia": "2.1.7", "register-service-worker": "1.7.2", "snake-case": "3.0.4", "sortablejs": "1.15.0", + "tippy.js": "6.3.7", "ufo": "1.3.1", "vue": "3.3.6", "vue-advanced-cropper": "2.8.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c54e6d2c..ab5e7e74f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,6 +40,114 @@ dependencies: '@sentry/vue': specifier: 7.74.0 version: 7.74.0(vue@3.3.6) + '@tiptap/core': + specifier: 2.1.12 + version: 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/extension-blockquote': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-bold': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-bullet-list': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-code': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-code-block-lowlight': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/extension-code-block@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-document': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-dropcursor': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-gapcursor': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-hard-break': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-heading': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-history': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-horizontal-rule': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-image': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-italic': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-link': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-list-item': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-ordered-list': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-paragraph': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-placeholder': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-strike': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-table': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-table-cell': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-table-header': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-table-row': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-task-item': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-task-list': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-text': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/extension-typography': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12) + '@tiptap/extension-underline': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12) + '@tiptap/pm': + specifier: 2.1.12 + version: 2.1.12 + '@tiptap/suggestion': + specifier: 2.1.12 + version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/vue-3': + specifier: 2.0.3 + version: 2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)(vue@3.3.6) + '@types/is-touch-device': + specifier: 1.0.0 + version: 1.0.0 + '@types/lodash.clonedeep': + specifier: 4.5.7 + version: 4.5.7 + '@types/sortablejs': + specifier: 1.15.0 + version: 1.15.0 '@vueuse/core': specifier: 10.5.0 version: 10.5.0(vue@3.3.6) @@ -58,9 +166,6 @@ dependencies: camel-case: specifier: 4.1.2 version: 4.1.2 - codemirror: - specifier: 5.65.15 - version: 5.65.15 date-fns: specifier: 2.30.0 version: 2.30.0 @@ -70,9 +175,6 @@ dependencies: dompurify: specifier: 3.0.6 version: 3.0.6 - easymde: - specifier: 2.18.0 - version: 2.18.0 fast-deep-equal: specifier: 3.1.3 version: 3.1.3 @@ -85,9 +187,6 @@ dependencies: floating-vue: specifier: 2.0.0-beta.24 version: 2.0.0-beta.24(vue@3.3.6) - highlight.js: - specifier: 11.9.0 - version: 11.9.0 is-touch-device: specifier: 1.0.1 version: 1.0.1 @@ -97,9 +196,9 @@ dependencies: lodash.debounce: specifier: 4.0.8 version: 4.0.8 - marked: - specifier: 9.1.2 - version: 9.1.2 + lowlight: + specifier: 2.7.0 + version: 2.7.0 pinia: specifier: 2.1.7 version: 2.1.7(typescript@5.2.2)(vue@3.3.6) @@ -112,6 +211,9 @@ dependencies: sortablejs: specifier: 1.15.0 version: 1.15.0 + tippy.js: + specifier: 6.3.7 + version: 6.3.7 ufo: specifier: 1.3.1 version: 1.3.1 @@ -171,9 +273,6 @@ devDependencies: '@types/flexsearch': specifier: 0.7.5 version: 0.7.5 - '@types/is-touch-device': - specifier: 1.0.1 - version: 1.0.1 '@types/lodash.debounce': specifier: 4.0.8 version: 4.0.8 @@ -186,9 +285,6 @@ devDependencies: '@types/postcss-preset-env': specifier: 7.7.0 version: 7.7.0 - '@types/sortablejs': - specifier: 1.15.4 - version: 1.15.4 '@typescript-eslint/eslint-plugin': specifier: 6.8.0 version: 6.8.0(@typescript-eslint/parser@6.8.0)(eslint@8.51.0)(typescript@5.2.2) @@ -3882,6 +3978,38 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true + /@popperjs/core@2.11.8: + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + dev: false + + /@remirror/core-constants@2.0.2: + resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==} + dev: false + + /@remirror/core-helpers@3.0.0: + resolution: {integrity: sha512-tusEgQJIqg4qKj6HSBUFcyRnWnziw3neh4T9wOmsPGHFC3w9kl5KSrDb9UAgE8uX6y32FnS7vJ955mWOl3n50A==} + dependencies: + '@remirror/core-constants': 2.0.2 + '@remirror/types': 1.0.1 + '@types/object.omit': 3.0.2 + '@types/object.pick': 1.3.3 + '@types/throttle-debounce': 2.1.0 + case-anything: 2.1.13 + dash-get: 1.0.2 + deepmerge: 4.3.1 + fast-deep-equal: 3.1.3 + make-error: 1.3.6 + object.omit: 3.0.0 + object.pick: 1.3.0 + throttle-debounce: 3.0.1 + dev: false + + /@remirror/types@1.0.1: + resolution: {integrity: sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==} + dependencies: + type-fest: 2.19.0 + dev: false + /@remusao/guess-url-type@1.2.1: resolution: {integrity: sha512-rbOqre2jW8STjheOsOaQHLgYBaBZ9Owbdt8NO7WvNZftJlaG3y/K9oOkl8ZUpuFBisIhmBuMEW6c+YrQl5inRA==} dev: true @@ -4113,6 +4241,346 @@ packages: defer-to-connect: 1.1.3 dev: true + /@tiptap/core@2.1.12(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==} + peerDependencies: + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-blockquote@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-Qb3YRlCfugx9pw7VgLTb+jY37OY4aBJeZnqHzx4QThSm13edNYjasokbX0nTwL1Up4NPTcY19JUeHt6fVaVVGg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-bold@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-AZGxIxcGU1/y6V2YEbKsq6BAibL8yQrbRm6EdcBnby41vj1WziewEKswhLGmZx5IKM2r2ldxld03KlfSIlKQZg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-bubble-menu@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-gAGi21EQ4wvLmT7klgariAc2Hf+cIjaNU2NWze3ut6Ku9gUo5ZLqj1t9SKHmNf4d5JG63O8GxpErqpA7lHlRtw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + tippy.js: 6.3.7 + dev: false + + /@tiptap/extension-bullet-list@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-vtD8vWtNlmAZX8LYqt2yU9w3mU9rPCiHmbp4hDXJs2kBnI0Ju/qAyXFx6iJ3C3XyuMnMbJdDI9ee0spAvFz7cQ==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-code-block-lowlight@2.0.3(@tiptap/core@2.1.12)(@tiptap/extension-code-block@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-thFXcFdFyHF0/dr9sqBedjj0Vt14k3m52YVc4l65+d65wRuHp4f8suu8T2ZGRJwqLCE3NIrvwQTSHhzjIqJVxQ==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/extension-code-block': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/extension-code-block': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-code-block@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-RXtSYCVsnk8D+K80uNZShClfZjvv1EgO42JlXLVGWQdIgaNyuOv/6I/Jdf+ZzhnpsBnHufW+6TJjwP5vJPSPHA==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-code@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-CRiRq5OTC1lFgSx6IMrECqmtb93a0ZZKujEnaRhzWliPBjLIi66va05f/P1vnV6/tHaC3yfXys6dxB5A4J8jxw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-document@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-PsYeNQQBYIU9ayz1R11Kv/kKNPFNIV8tApJ9pxelXjzcAhkjncNUazPN/dyho60mzo+WpsmS3ceTj/gK3bCtWA==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-dropcursor@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-0tT/q8nL4NBCYPxr9T0Brck+RQbWuczm9nV0bnxgt0IiQXoRHutfPWdS7GA65PTuVRBS/3LOco30fbjFhkfz/A==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-floating-menu@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-uo0ydCJNg6AWwLT6cMUJYVChfvw2PY9ZfvKRhh9YJlGfM02jS4RUG/bJBts6R37f+a5FsOvAVwg8EvqPlNND1A==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + tippy.js: 6.3.7 + dev: false + + /@tiptap/extension-gapcursor@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-zFYdZCqPgpwoB7whyuwpc8EYLYjUE5QYKb8vICvc+FraBUDM51ujYhFSgJC3rhs8EjI+8GcK8ShLbSMIn49YOQ==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-hard-break@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-nqKcAYGEOafg9D+2cy1E4gHNGuL12LerVa0eS2SQOb+PT8vSel9OTKU1RyZldsWSQJ5rq/w4uIjmLnrSR2w6Yw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-heading@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-MoANP3POAP68Ko9YXarfDKLM/kXtscgp6m+xRagPAghRNujVY88nK1qBMZ3JdvTVN6b/ATJhp8UdrZX96TLV2w==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-history@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-6b7UFVkvPjq3LVoCTrYZAczt5sQrQUaoDWAieVClVZoFLfjga2Fwjcfgcie8IjdPt8YO2hG/sar/c07i9vM0Sg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-horizontal-rule@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-RRuoK4KxrXRrZNAjJW5rpaxjiP0FJIaqpi7nFbAua2oHXgsCsG8qbW2Y0WkbIoS8AJsvLZ3fNGsQ8gpdliuq3A==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-image@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-hS9ZJwz0md07EHsC+o4NuuJkhCZsZn7TuRz/2CvRSj2fWFIz+40CyNAHf/2J0qNugG9ommXaemetsADeEZP9ag==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-italic@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-/XYrW4ZEWyqDvnXVKbgTXItpJOp2ycswk+fJ3vuexyolO6NSs0UuYC6X4f+FbHYL5VuWqVBv7EavGa+tB6sl3A==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-link@2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-H72tXQ5rkVCkAhFaf08fbEU7EBUCK0uocsqOF+4th9sOlrhfgyJtc8Jv5EXPDpxNgG5jixSqWBo0zKXQm9s9eg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + linkifyjs: 4.1.1 + dev: false + + /@tiptap/extension-list-item@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-Gk7hBFofAPmNQ8+uw8w5QSsZOMEGf7KQXJnx5B022YAUJTYYxO3jYVuzp34Drk9p+zNNIcXD4kc7ff5+nFOTrg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-ordered-list@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-tF6VGl+D2avCgn9U/2YLJ8qVmV6sPE/iEzVAFZuOSe6L0Pj7SQw4K6AO640QBob/d8VrqqJFHCb6l10amJOnXA==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-paragraph@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-hoH/uWPX+KKnNAZagudlsrr4Xu57nusGekkJWBcrb5MCDE91BS+DN2xifuhwXiTHxnwOMVFjluc0bPzQbkArsw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-placeholder@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-K52o7B1zkP4vaVy3z4ZwHn+tQy6KlXtedj1skLg+796ImwH2GYS5z6MFOTfKzBO2hLncUzLco/s0C5PLCD6SDw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-strike@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-HlhrzIjYUT8oCH9nYzEL2QTTn8d1ECnVhKvzAe6x41xk31PjLMHTUy8aYjeQEkWZOWZ34tiTmslV1ce6R3Dt8g==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-table-cell@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-d0vpwQfRIOhqKJdoiOJybwWhjnug3QA4Mkgccp378moDRyOer3hPKavG1Ljgz087qHrN4WfdUlMGEvasYsWE7w==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-table-header@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-SnGl1U6usRRS6LyAjSdhaCYLF6NWbGhjVFSmiPrjb0pOzsiVeDOiUNCyUAIYaDNnjAF2pfK6+H+uHzYPqTi+/w==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-table-row@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-tyqeXmQLNSBsYyiNsnQuJMxNbz6dYt+P5W58+h10mjbt+hERA5+alQQyP06O2DggsT3Z0LPt7QRAlNmOBe7cyQ==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-table@2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-8swHqm8vRM1w9WzaAhLmY24gGoTozctz4KHKBjvFY/Ka0yXabT0+hoCCdkZLnXWi15H3pbHs2HnDBaTGL9bZTw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-task-item@2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-13u1Q769WiSNcjFieYAMuJyWXNaY9yOdw6WFg9tQg4EZ5h6+2DaxB0qmu6I3pH+wwSn2UkCkXIirAo/k7wnzbw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/extension-task-list@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-NdW0RtMF2L96qy+j946mTB5Av6Qn5L3vGVWFmJA6/JPXr9Uj/grItCmqUQKHfPBSFow7UqBY82ODblP+GQFgew==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-text@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-rCNUd505p/PXwU9Jgxo4ZJv4A3cIBAyAqlx/dtcY6cjztCQuXJhuQILPhjGhBTOLEEL4kW2wQtqzCmb7O8i2jg==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-typography@2.0.3(@tiptap/core@2.1.12): + resolution: {integrity: sha512-5U91O2dffYOvwenWG+zT1N/pnt+RppSlocxs1KaNWFLlI2fgzDTyUyjzygIHGmskStqay2MuvmPnfVABoC+1Gw==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/extension-underline@2.1.12(@tiptap/core@2.1.12): + resolution: {integrity: sha512-NwwdhFT8gDD0VUNLQx85yFBhP9a8qg8GPuxlGzAP/lPTV8Ubh3vSeQ5N9k2ZF/vHlEvnugzeVCbmYn7wf8vn1g==} + peerDependencies: + '@tiptap/core': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + dev: false + + /@tiptap/pm@2.1.12: + resolution: {integrity: sha512-Q3MXXQABG4CZBesSp82yV84uhJh/W0Gag6KPm2HRWPimSFELM09Z9/5WK9RItAYE0aLhe4Krnyiczn9AAa1tQQ==} + dependencies: + prosemirror-changeset: 2.2.1 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.5.2 + prosemirror-dropcursor: 1.8.1 + prosemirror-gapcursor: 1.3.2 + prosemirror-history: 1.3.2 + prosemirror-inputrules: 1.2.1 + prosemirror-keymap: 1.2.2 + prosemirror-markdown: 1.11.2 + prosemirror-menu: 1.2.4 + prosemirror-model: 1.19.3 + prosemirror-schema-basic: 1.2.2 + prosemirror-schema-list: 1.3.0 + prosemirror-state: 1.4.3 + prosemirror-tables: 1.3.4 + prosemirror-trailing-node: 2.0.7(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.1) + prosemirror-transform: 1.8.0 + prosemirror-view: 1.32.1 + dev: false + + /@tiptap/suggestion@2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12): + resolution: {integrity: sha512-rhlLWwVkOodBGRMK0mAmE34l2a+BqM2Y7q1ViuQRBhs/6sZ8d83O4hARHKVwqT5stY4i1l7d7PoemV3uAGI6+g==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + dev: false + + /@tiptap/vue-3@2.0.3(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)(vue@3.3.6): + resolution: {integrity: sha512-2CtNUzt+e7sgvIjxPOyBwoiRcuCHNeJzW+XGxNK2uCWlAKp/Yw3boJ51d51UuIbj9RitGHJ5GpCdLJoL7SDiQA==} + peerDependencies: + '@tiptap/core': ^2.0.0 + '@tiptap/pm': ^2.0.0 + vue: ^3.0.0 + dependencies: + '@tiptap/core': 2.1.12(@tiptap/pm@2.1.12) + '@tiptap/extension-bubble-menu': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/extension-floating-menu': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12) + '@tiptap/pm': 2.1.12 + vue: 3.3.6(typescript@5.2.2) + dev: false + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} @@ -4148,6 +4616,7 @@ packages: resolution: {integrity: sha512-SFSj5Tb/mtQoVgaltsipdRGG1PkcFu/L0OXPNBGCXYUQtwsNoAGRNNHOTl1jYcQUcEI77EiUfk94bgETTbSo/A==} dependencies: '@types/tern': 0.23.4 + dev: true /@types/dompurify@3.0.4: resolution: {integrity: sha512-1Jk8S/IRzNSbwQRbuGuLFHviwxQ8pX81ZEW3INY9432Cwb4VedkBYan8gSIXVLOLHBtimOmUTEYphjRVmo+30g==} @@ -4190,9 +4659,15 @@ packages: resolution: {integrity: sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg==} dev: true - /@types/is-touch-device@1.0.1: - resolution: {integrity: sha512-Hvjx/zLnZF9AVHNcFZEluntFA59OWUYbmrkS7oDWoHnibO86n0nTrCI7wBGR0u8Y/E8XIj3nuUrK8hNQmqiZ7Q==} - dev: true + /@types/hast@2.3.7: + resolution: {integrity: sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /@types/is-touch-device@1.0.0: + resolution: {integrity: sha512-/rErV0NuroAR9EZF1xK0TrihQ/7BbVckGfSr/suq/E4tJQLr4TrADR0qAUpDs/hxtl1NiP0V/ho+fSA/5EIO9Q==} + dev: false /@types/json-schema@7.0.12: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} @@ -4208,6 +4683,12 @@ packages: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} dev: true + /@types/lodash.clonedeep@4.5.7: + resolution: {integrity: sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw==} + dependencies: + '@types/lodash': 4.14.185 + dev: false + /@types/lodash.debounce@4.0.8: resolution: {integrity: sha512-REumepIJjQFSOaBUoj81U5ZzF9YIhovzE2Lm6ejUbycmwx597k2ivG1cVfPtAj4eVuSbGoZDkJR0sRIahsE6/Q==} dependencies: @@ -4216,7 +4697,6 @@ packages: /@types/lodash@4.14.185: resolution: {integrity: sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA==} - dev: true /@types/markdown-it@12.2.3: resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} @@ -4225,10 +4705,6 @@ packages: '@types/mdurl': 1.0.2 dev: true - /@types/marked@4.3.1: - resolution: {integrity: sha512-vSSbKZFbNktrQ15v7o1EaH78EbWV+sPQbPjHG+Cp8CaNcPFUEfjZ0Iml/V0bFDwsTlYe8o6XC5Hfdp91cqPV2g==} - dev: false - /@types/marked@5.0.2: resolution: {integrity: sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg==} dev: true @@ -4253,6 +4729,14 @@ packages: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true + /@types/object.omit@3.0.2: + resolution: {integrity: sha512-BxWU36cMP+FKD3OLFluQaj2cBev2sx2LJaHELuphHwnleq+xnEhTmuYYYx4pOT/1U/ZoR6B+RdvxWh2FD6lGGA==} + dev: false + + /@types/object.pick@1.3.3: + resolution: {integrity: sha512-qZqHmdGEALeSATMB1djT1S5szv6Wtpb7DKpHrt2XG4iyKlV7C2Xk8GmDXr1KXakOqUfX6ohw7ceruYt4NVmB1Q==} + dev: false + /@types/postcss-preset-env@7.7.0: resolution: {integrity: sha512-biD8MwSiZo1Nztn1cIBPMcKNKzgFyU05AB96HIF9y3G4f9vdx2O60DHCSpWXChTp6mOEGu15fqIw2DetVVjghw==} dependencies: @@ -4284,19 +4768,28 @@ packages: resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==} dev: true - /@types/sortablejs@1.15.4: - resolution: {integrity: sha512-7oL7CcPSfoyoNx3Ba1+79ykJzpEKVhHUyfAiN5eT/FoeDXOR3eBDLXf9ndDNuxaExmjpI+zVi2dMMuaoXUOzNA==} - dev: true + /@types/sortablejs@1.15.0: + resolution: {integrity: sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==} + dev: false /@types/tern@0.23.4: resolution: {integrity: sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==} dependencies: '@types/estree': 1.0.0 + dev: true + + /@types/throttle-debounce@2.1.0: + resolution: {integrity: sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==} + dev: false /@types/trusted-types@2.0.2: resolution: {integrity: sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==} dev: true + /@types/unist@2.0.9: + resolution: {integrity: sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==} + dev: false + /@types/web-bluetooth@0.0.16: resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} dev: false @@ -5467,6 +5960,11 @@ packages: - utf-8-validate dev: true + /case-anything@2.1.13: + resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==} + engines: {node: '>=12.13'} + dev: false + /caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} dev: true @@ -5639,16 +6137,6 @@ packages: engines: {node: '>=0.8'} dev: true - /codemirror-spell-checker@1.1.2: - resolution: {integrity: sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=} - dependencies: - typo-js: 1.2.1 - dev: false - - /codemirror@5.65.15: - resolution: {integrity: sha512-YC4EHbbwQeubZzxLl5G4nlbLc1T21QTrKGaOal/Pkm9dVDMZXMH7+ieSPEOZCtO9I68i8/oteJKOxzHC2zR+0g==} - dev: false - /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -5777,7 +6265,6 @@ packages: /crelt@1.0.5: resolution: {integrity: sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==} - dev: true /cross-fetch@3.1.5: resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} @@ -5968,6 +6455,10 @@ packages: yauzl: 2.10.0 dev: true + /dash-get@1.0.2: + resolution: {integrity: sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==} + dev: false + /dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} @@ -6086,6 +6577,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: false + /defaults@1.0.3: resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} dependencies: @@ -6233,16 +6729,6 @@ packages: resolution: {integrity: sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==} dev: false - /easymde@2.18.0: - resolution: {integrity: sha512-IxVVUxNWIoXLeqtBU4BLc+eS/ScYhT1Dcb6yF5Wchoj1iXAV+TIIDWx+NCaZhY7RcSHqDPKllbYq7nwGKILnoA==} - dependencies: - '@types/codemirror': 5.60.12 - '@types/marked': 4.3.1 - codemirror: 5.65.15 - codemirror-spell-checker: 1.1.2 - marked: 4.3.0 - dev: false - /ecc-jsbn@0.1.2: resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} dependencies: @@ -6307,6 +6793,11 @@ packages: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: true + /entities@3.0.1: + resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} + engines: {node: '>=0.12'} + dev: false + /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -6435,7 +6926,6 @@ packages: /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: true /escodegen@2.0.0: resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} @@ -6697,6 +7187,12 @@ packages: dependencies: reusify: 1.0.4 + /fault@2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + dependencies: + format: 0.2.2 + dev: false + /fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} dependencies: @@ -6852,6 +7348,11 @@ packages: combined-stream: 1.0.8 mime-types: 2.1.35 + /format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + dev: false + /formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} @@ -7156,8 +7657,8 @@ packages: tslib: 2.3.1 dev: true - /highlight.js@11.9.0: - resolution: {integrity: sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==} + /highlight.js@11.6.0: + resolution: {integrity: sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==} engines: {node: '>=12.0.0'} dev: false @@ -7441,6 +7942,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: false + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -7522,6 +8030,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true @@ -7596,6 +8111,11 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: false + /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} dev: true @@ -7853,6 +8373,16 @@ packages: uc.micro: 1.0.6 dev: true + /linkify-it@4.0.1: + resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} + dependencies: + uc.micro: 1.0.6 + dev: false + + /linkifyjs@4.1.1: + resolution: {integrity: sha512-zFN/CTVmbcVef+WaDXT63dNzzkfRBKT1j464NJQkV7iSgJU0sLBus9W0HBwnXK13/hf168pbrx/V/bjEHOXNHA==} + dev: false + /listr2@3.14.0(enquirer@2.3.6): resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} engines: {node: '>=10.0.0'} @@ -7956,6 +8486,14 @@ packages: engines: {node: '>=8'} dev: true + /lowlight@2.7.0: + resolution: {integrity: sha512-RRdrHalFfjpxL91ITTX7KhJYH3QmX5bW9Uie2D2E5GPIR3XBYDYhScBjE291ewFZkStz/k2PN9KC+8deNLiI3Q==} + dependencies: + '@types/hast': 2.3.7 + fault: 2.0.1 + highlight.js: 11.6.0 + dev: false + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: @@ -7993,6 +8531,10 @@ packages: semver: 6.3.1 dev: true + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: false + /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -8041,16 +8583,15 @@ packages: uc.micro: 1.0.6 dev: true - /marked@4.3.0: - resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} - engines: {node: '>= 12'} - hasBin: true - dev: false - - /marked@9.1.2: - resolution: {integrity: sha512-qoKMJqK0w6vkLk8+KnKZAH6neUZSNaQqVZ/h2yZ9S7CbLuFHyS2viB0jnqcWF9UKjwsAbMrQtnQhdmdvOVOw9w==} - engines: {node: '>= 16'} + /markdown-it@13.0.2: + resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==} hasBin: true + dependencies: + argparse: 2.0.1 + entities: 3.0.1 + linkify-it: 4.0.1 + mdurl: 1.0.1 + uc.micro: 1.0.6 dev: false /mdn-data@2.0.28: @@ -8063,7 +8604,6 @@ packages: /mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - dev: true /meow@7.1.1: resolution: {integrity: sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==} @@ -8330,6 +8870,20 @@ packages: object-keys: 1.1.1 dev: true + /object.omit@3.0.0: + resolution: {integrity: sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 1.0.1 + dev: false + + /object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: false + /on-finished@2.3.0: resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} engines: {node: '>= 0.8'} @@ -8397,6 +8951,10 @@ packages: wcwidth: 1.0.1 dev: true + /orderedmap@2.1.1: + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + dev: false + /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -9044,6 +9602,149 @@ packages: engines: {node: '>=0.4.0'} dev: true + /prosemirror-changeset@2.2.1: + resolution: {integrity: sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==} + dependencies: + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-collab@1.3.1: + resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} + dependencies: + prosemirror-state: 1.4.3 + dev: false + + /prosemirror-commands@1.5.2: + resolution: {integrity: sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==} + dependencies: + prosemirror-model: 1.19.3 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-dropcursor@1.8.1: + resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==} + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.32.1 + dev: false + + /prosemirror-gapcursor@1.3.2: + resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==} + dependencies: + prosemirror-keymap: 1.2.2 + prosemirror-model: 1.19.3 + prosemirror-state: 1.4.3 + prosemirror-view: 1.32.1 + dev: false + + /prosemirror-history@1.3.2: + resolution: {integrity: sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==} + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.32.1 + rope-sequence: 1.3.4 + dev: false + + /prosemirror-inputrules@1.2.1: + resolution: {integrity: sha512-3LrWJX1+ULRh5SZvbIQlwZafOXqp1XuV21MGBu/i5xsztd+9VD15x6OtN6mdqSFI7/8Y77gYUbQ6vwwJ4mr6QQ==} + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-keymap@1.2.2: + resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} + dependencies: + prosemirror-state: 1.4.3 + w3c-keyname: 2.2.6 + dev: false + + /prosemirror-markdown@1.11.2: + resolution: {integrity: sha512-Eu5g4WPiCdqDTGhdSsG9N6ZjACQRYrsAkrF9KYfdMaCmjIApH75aVncsWYOJvEk2i1B3i8jZppv3J/tnuHGiUQ==} + dependencies: + markdown-it: 13.0.2 + prosemirror-model: 1.19.3 + dev: false + + /prosemirror-menu@1.2.4: + resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} + dependencies: + crelt: 1.0.5 + prosemirror-commands: 1.5.2 + prosemirror-history: 1.3.2 + prosemirror-state: 1.4.3 + dev: false + + /prosemirror-model@1.19.3: + resolution: {integrity: sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ==} + dependencies: + orderedmap: 2.1.1 + dev: false + + /prosemirror-schema-basic@1.2.2: + resolution: {integrity: sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==} + dependencies: + prosemirror-model: 1.19.3 + dev: false + + /prosemirror-schema-list@1.3.0: + resolution: {integrity: sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==} + dependencies: + prosemirror-model: 1.19.3 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + + /prosemirror-state@1.4.3: + resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} + dependencies: + prosemirror-model: 1.19.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.32.1 + dev: false + + /prosemirror-tables@1.3.4: + resolution: {integrity: sha512-z6uLSQ1BLC3rgbGwZmpfb+xkdvD7W/UOsURDfognZFYaTtc0gsk7u/t71Yijp2eLflVpffMk6X0u0+u+MMDvIw==} + dependencies: + prosemirror-keymap: 1.2.2 + prosemirror-model: 1.19.3 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + prosemirror-view: 1.32.1 + dev: false + + /prosemirror-trailing-node@2.0.7(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.1): + resolution: {integrity: sha512-8zcZORYj/8WEwsGo6yVCRXFMOfBo0Ub3hCUvmoWIZYfMP26WqENU0mpEP27w7mt8buZWuGrydBewr0tOArPb1Q==} + peerDependencies: + prosemirror-model: ^1.19.0 + prosemirror-state: ^1.4.2 + prosemirror-view: ^1.31.2 + dependencies: + '@remirror/core-constants': 2.0.2 + '@remirror/core-helpers': 3.0.0 + escape-string-regexp: 4.0.0 + prosemirror-model: 1.19.3 + prosemirror-state: 1.4.3 + prosemirror-view: 1.32.1 + dev: false + + /prosemirror-transform@1.8.0: + resolution: {integrity: sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==} + dependencies: + prosemirror-model: 1.19.3 + dev: false + + /prosemirror-view@1.32.1: + resolution: {integrity: sha512-9SnB4HBgRczzTyIMZLPE1iszegL04hNfUyS8uPtP1RPxNM2NTCiIs8KwNsJU4nbZO9rxJTwVTv7Jm3zU4CR78A==} + dependencies: + prosemirror-model: 1.19.3 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.8.0 + dev: false + /proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} dev: true @@ -9367,6 +10068,10 @@ packages: optionalDependencies: fsevents: 2.3.2 + /rope-sequence@1.3.4: + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + dev: false + /run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -9881,6 +10586,11 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true + /throttle-debounce@3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + dev: false + /throttleit@1.0.0: resolution: {integrity: sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==} dev: true @@ -9903,6 +10613,12 @@ packages: engines: {node: '>=14.0.0'} dev: true + /tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + dependencies: + '@popperjs/core': 2.11.8 + dev: false + /tldts-core@5.7.104: resolution: {integrity: sha512-8vhSgc2nzPNT0J7XyCqcOtQ6+ySBn+gsPmj5h95YytIZ7L2Xl40paUmj0T6Uko42HegHGQxXieunHIQuABWSmQ==} dev: true @@ -10062,6 +10778,11 @@ packages: engines: {node: '>=8'} dev: true + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + /typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} dependencies: @@ -10073,13 +10794,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - /typo-js@1.2.1: - resolution: {integrity: sha512-bTGLjbD3WqZDR3CgEFkyi9Q/SS2oM29ipXrWfDb4M74ea69QwKAECVceYpaBu0GfdnASMg9Qfl67ttB23nePHg==} - dev: false - /uc.micro@1.0.6: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} - dev: true /ufo@1.3.1: resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} @@ -10594,7 +11310,6 @@ packages: /w3c-keyname@2.2.6: resolution: {integrity: sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==} - dev: true /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} diff --git a/renovate.json b/renovate.json index b27d66ecb..11e6826c1 100644 --- a/renovate.json +++ b/renovate.json @@ -27,6 +27,13 @@ "histoire" ] }, + { + "groupName": "tiptap", + "matchPackagePrefixes": [ + "@tiptap/", + "tiptap" + ] + }, { "matchDepTypes": ["devDependencies"], "groupName": "dev-dependencies", diff --git a/src/components/input/AsyncEditor.ts b/src/components/input/AsyncEditor.ts index f80015229..4196baf57 100644 --- a/src/components/input/AsyncEditor.ts +++ b/src/components/input/AsyncEditor.ts @@ -1,3 +1,5 @@ import {createAsyncComponent} from '@/helpers/createAsyncComponent' -export default createAsyncComponent(() => import('@/components/input/editor.vue')) \ No newline at end of file +const TipTap = createAsyncComponent(() => import('@/components/input/editor/TipTap.vue')) + +export default TipTap diff --git a/src/components/input/editor.vue b/src/components/input/editor.vue deleted file mode 100644 index e4fe87a0c..000000000 --- a/src/components/input/editor.vue +++ /dev/null @@ -1,444 +0,0 @@ - - - - - diff --git a/src/components/input/editor/CommandsList.vue b/src/components/input/editor/CommandsList.vue new file mode 100644 index 000000000..6221f3914 --- /dev/null +++ b/src/components/input/editor/CommandsList.vue @@ -0,0 +1,144 @@ + + + + + \ No newline at end of file diff --git a/src/components/input/editor/EditorToolbar.vue b/src/components/input/editor/EditorToolbar.vue new file mode 100644 index 000000000..5173899e9 --- /dev/null +++ b/src/components/input/editor/EditorToolbar.vue @@ -0,0 +1,439 @@ + + + + + diff --git a/src/components/input/editor/TipTap.vue b/src/components/input/editor/TipTap.vue new file mode 100644 index 000000000..62b73b985 --- /dev/null +++ b/src/components/input/editor/TipTap.vue @@ -0,0 +1,854 @@ + + + + + diff --git a/src/components/input/editor/commands.ts b/src/components/input/editor/commands.ts new file mode 100644 index 000000000..f72de756a --- /dev/null +++ b/src/components/input/editor/commands.ts @@ -0,0 +1,28 @@ +import {Extension} from '@tiptap/core' +import Suggestion from '@tiptap/suggestion' + +// Copied and adjusted from https://github.com/ueberdosis/tiptap/tree/252acb32d27a0f9af14813eeed83d8a50059a43a/demos/src/Experiments/Commands/Vue + +export default Extension.create({ + name: 'slash-menu-commands', + + addOptions() { + return { + suggestion: { + char: '/', + command: ({editor, range, props}) => { + props.command({editor, range}) + }, + }, + } + }, + + addProseMirrorPlugins() { + return [ + Suggestion({ + editor: this.editor, + ...this.options.suggestion, + }), + ] + }, +}) \ No newline at end of file diff --git a/src/components/input/editor/suggestion.ts b/src/components/input/editor/suggestion.ts new file mode 100644 index 000000000..9ae6182a7 --- /dev/null +++ b/src/components/input/editor/suggestion.ts @@ -0,0 +1,214 @@ +import {VueRenderer} from '@tiptap/vue-3' +import tippy from 'tippy.js' + +import CommandsList from './CommandsList.vue' + +export default function suggestionSetup(t) { + return { + items: ({query}: { query: string }) => { + return [ + { + title: t('input.editor.text'), + description: t('input.editor.textTooltip'), + icon: 'fa-font', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .setNode('paragraph', {level: 1}) + .run() + }, + }, + { + title: t('input.editor.heading1'), + description: t('input.editor.heading1Tooltip'), + icon: 'fa-header', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .setNode('heading', {level: 1}) + .run() + }, + }, + { + title: t('input.editor.heading2'), + description: t('input.editor.heading2Tooltip'), + icon: 'fa-header', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .setNode('heading', {level: 2}) + .run() + }, + }, + { + title: t('input.editor.heading3'), + description: t('input.editor.heading3Tooltip'), + icon: 'fa-header', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .setNode('heading', {level: 2}) + .run() + }, + }, + { + title: t('input.editor.bulletList'), + description: t('input.editor.bulletListTooltip'), + icon: 'fa-list-ul', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .toggleBulletList() + .run() + }, + }, + { + title: t('input.editor.orderedList'), + description: t('input.editor.orderedListTooltip'), + icon: 'fa-list-ol', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .toggleOrderedList() + .run() + }, + }, + { + title: t('input.editor.taskList'), + description: t('input.editor.taskListTooltip'), + icon: 'fa-list-check', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .toggleTaskList() + .run() + }, + }, + { + title: t('input.editor.quote'), + description: t('input.editor.quoteTooltip'), + icon: 'fa-quote-right', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .toggleBlockquote() + .run() + }, + }, + { + title: t('input.editor.code'), + description: t('input.editor.codeTooltip'), + icon: 'fa-code', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .toggleCodeBlock() + .run() + }, + }, + { + title: t('input.editor.image'), + description: t('input.editor.imageTooltip'), + icon: 'fa-image', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .run() + document.getElementById('tiptap__image-upload').click() + }, + }, + { + title: t('input.editor.horizontalRule'), + description: t('input.editor.horizontalRuleTooltip'), + icon: 'fa-ruler-horizontal', + command: ({editor, range}) => { + editor + .chain() + .focus() + .deleteRange(range) + .setHorizontalRule() + .run() + }, + }, + ].filter(item => item.title.toLowerCase().startsWith(query.toLowerCase())) + }, + + render: () => { + let component: VueRenderer + let popup + + return { + onStart: props => { + component = new VueRenderer(CommandsList, { + // using vue 2: + // parent: this, + // propsData: props, + props, + editor: props.editor, + }) + + if (!props.clientRect) { + return + } + + popup = tippy('body', { + getReferenceClientRect: props.clientRect, + appendTo: () => document.body, + content: component.element, + showOnCreate: true, + interactive: true, + trigger: 'manual', + placement: 'bottom-start', + }) + }, + + onUpdate(props) { + component.updateProps(props) + + if (!props.clientRect) { + return + } + + popup[0].setProps({ + getReferenceClientRect: props.clientRect, + }) + }, + + onKeyDown(props) { + if (props.event.key === 'Escape') { + popup[0].hide() + + return true + } + + return component.ref?.onKeyDown(props) + }, + + onExit() { + popup[0].destroy() + component.destroy() + }, + } + }, + } +} \ No newline at end of file diff --git a/src/components/input/editor/types.ts b/src/components/input/editor/types.ts new file mode 100644 index 000000000..5fa5b3a87 --- /dev/null +++ b/src/components/input/editor/types.ts @@ -0,0 +1,6 @@ +export type UploadCallback = (files: File[] | FileList) => Promise + +export interface BottomAction { + title: string + action: () => void, +} diff --git a/src/components/input/editorConfig.ts b/src/components/input/editorConfig.ts deleted file mode 100644 index e50e9aecc..000000000 --- a/src/components/input/editorConfig.ts +++ /dev/null @@ -1,135 +0,0 @@ -import EasyMDE from 'easymde' -import {i18n} from '@/i18n' - -export function createEasyMDEConfig({ placeholder, uploadImage, imageUploadFunction }) { - return { - autoDownloadFontAwesome: false, - spellChecker: false, - placeholder, - uploadImage, - imageUploadFunction, - minHeight: '150px', - sideBySideFullscreen: false, - toolbar: [ - { - name: 'heading-1', - action: EasyMDE.toggleHeading1, - title: i18n.global.t('input.editor.heading1'), - icon: '', - }, - { - name: 'heading-2', - action: EasyMDE.toggleHeading2, - title: i18n.global.t('input.editor.heading2'), - icon: '', - }, - { - name: 'heading-3', - action: EasyMDE.toggleHeading3, - title: i18n.global.t('input.editor.heading3'), - icon: '', - }, - { - name: 'heading-smaller', - action: EasyMDE.toggleHeadingSmaller, - title: i18n.global.t('input.editor.headingSmaller'), - icon: '', - }, - { - name: 'heading-bigger', - action: EasyMDE.toggleHeadingBigger, - title: i18n.global.t('input.editor.headingBigger'), - icon: '', - }, - '|', - { - name: 'bold', - action: EasyMDE.toggleBold, - title: i18n.global.t('input.editor.bold'), - icon: '', - }, - { - name: 'italic', - action: EasyMDE.toggleItalic, - title: i18n.global.t('input.editor.italic'), - icon: '', - }, - { - name: 'strikethrough', - action: EasyMDE.toggleStrikethrough, - title: i18n.global.t('input.editor.strikethrough'), - icon: '', - }, - { - name: 'code', - action: EasyMDE.toggleCodeBlock, - title: i18n.global.t('input.editor.code'), - icon: '', - }, - { - name: 'quote', - action: EasyMDE.toggleBlockquote, - title: i18n.global.t('input.editor.quote'), - icon: '', - }, - { - name: 'unordered-list', - action: EasyMDE.toggleUnorderedList, - title: i18n.global.t('input.editor.unorderedList'), - icon: '', - }, - { - name: 'ordered-list', - action: EasyMDE.toggleOrderedList, - title: i18n.global.t('input.editor.orderedList'), - icon: '', - }, - '|', - { - name: 'clean-block', - action: EasyMDE.cleanBlock, - title: i18n.global.t('input.editor.cleanBlock'), - icon: '', - }, - { - name: 'link', - action: EasyMDE.drawLink, - title: i18n.global.t('input.editor.link'), - icon: '', - }, - { - name: 'image', - action: EasyMDE.drawImage, - title: i18n.global.t('input.editor.image'), - icon: '', - }, - { - name: 'table', - action: EasyMDE.drawTable, - title: i18n.global.t('input.editor.table'), - icon: '', - }, - { - name: 'horizontal-rule', - action: EasyMDE.drawHorizontalRule, - title: i18n.global.t('input.editor.horizontalRule'), - icon: '', - }, - '|', - { - name: 'side-by-side', - action: EasyMDE.toggleSideBySide, - title: i18n.global.t('input.editor.sideBySide'), - icon: '', - }, - { - name: 'guide', - action() { - window.open('https://www.markdownguide.org/basic-syntax/', '_blank') - }, - title: i18n.global.t('input.editor.guide'), - icon: '', - }, - ], - } -} \ No newline at end of file diff --git a/src/components/input/vue-easymde.vue b/src/components/input/vue-easymde.vue deleted file mode 100644 index 208c3da5f..000000000 --- a/src/components/input/vue-easymde.vue +++ /dev/null @@ -1,522 +0,0 @@ -