Commit d2ddb757 authored by Enrique Alcántara's avatar Enrique Alcántara Committed by Paul Slaughter
parent f1a40767
<script>
import { EditorContent, Editor } from 'tiptap';
import { EditorContent as TiptapEditorContent } from '@tiptap/vue-2';
import { ContentEditor } from '../services/content_editor';
import TopToolbar from './top_toolbar.vue';
export default {
components: {
EditorContent,
TiptapEditorContent,
TopToolbar,
},
props: {
editor: {
type: Object,
contentEditor: {
type: ContentEditor,
required: true,
validator: (editor) => editor instanceof Editor,
},
},
};
</script>
<template>
<div class="md md-area" :class="{ 'is-focused': editor.focused }">
<top-toolbar class="gl-mb-4" :editor="editor" />
<editor-content :editor="editor" />
<div class="md md-area" :class="{ 'is-focused': contentEditor.tiptapEditor.isFocused }">
<top-toolbar class="gl-mb-4" :content-editor="contentEditor" />
<tiptap-editor-content :editor="contentEditor.tiptapEditor" />
</div>
</template>
<script>
import { GlButton, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
import { Editor as TiptapEditor } from '@tiptap/vue-2';
export default {
components: {
......@@ -13,8 +14,8 @@ export default {
type: String,
required: true,
},
editor: {
type: Object,
tiptapEditor: {
type: TiptapEditor,
required: true,
},
contentType: {
......@@ -25,23 +26,23 @@ export default {
type: String,
required: true,
},
executeCommand: {
type: Boolean,
editorCommand: {
type: String,
required: false,
default: true,
default: '',
},
},
computed: {
isActive() {
return this.editor.isActive[this.contentType]() && this.editor.focused;
return this.tiptapEditor.isActive(this.contentType) && this.tiptapEditor.isFocused;
},
},
methods: {
execute() {
const { contentType } = this;
if (this.executeCommand) {
this.editor.commands[contentType]();
if (this.editorCommand) {
this.tiptapEditor.chain()[this.editorCommand]().focus().run();
}
this.$emit('click', { contentType });
......
<script>
import { ContentEditor } from '../services/content_editor';
import Divider from './divider.vue';
import ToolbarButton from './toolbar_button.vue';
......@@ -8,8 +9,8 @@ export default {
Divider,
},
props: {
editor: {
type: Object,
contentEditor: {
type: ContentEditor,
required: true,
},
},
......@@ -23,44 +24,50 @@ export default {
data-testid="bold"
content-type="bold"
icon-name="bold"
editor-command="toggleBold"
:label="__('Bold text')"
:editor="editor"
:tiptap-editor="contentEditor.tiptapEditor"
/>
<toolbar-button
data-testid="italic"
content-type="italic"
icon-name="italic"
editor-command="toggleItalic"
:label="__('Italic text')"
:editor="editor"
:tiptap-editor="contentEditor.tiptapEditor"
/>
<toolbar-button
data-testid="code"
content-type="code"
icon-name="code"
editor-command="toggleCode"
:label="__('Code')"
:editor="editor"
:tiptap-editor="contentEditor.tiptapEditor"
/>
<divider />
<toolbar-button
data-testid="blockquote"
content-type="blockquote"
icon-name="quote"
editor-command="toggleBlockquote"
:label="__('Insert a quote')"
:editor="editor"
:tiptap-editor="contentEditor.tiptapEditor"
/>
<toolbar-button
data-testid="bullet-list"
content-type="bullet_list"
content-type="bulletList"
icon-name="list-bulleted"
editor-command="toggleBulletList"
:label="__('Add a bullet list')"
:editor="editor"
:tiptap-editor="contentEditor.tiptapEditor"
/>
<toolbar-button
data-testid="ordered-list"
content-type="ordered_list"
content-type="orderedList"
icon-name="list-numbered"
editor-command="toggleOrderedList"
:label="__('Add a numbered list')"
:editor="editor"
:tiptap-editor="contentEditor.tiptapEditor"
/>
</div>
</template>
import { CodeBlockHighlight as BaseCodeBlockHighlight } from 'tiptap-extensions';
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight';
export default class GlCodeBlockHighlight extends BaseCodeBlockHighlight {
get schema() {
const baseSchema = super.schema;
const extractLanguage = (element) => element.firstElementChild?.getAttribute('lang');
export default CodeBlockLowlight.extend({
addAttributes() {
return {
...baseSchema,
attrs: {
params: {
default: null,
...this.parent(),
/* `params` is the name of the attribute that
prosemirror-markdown uses to extract the language
of a codeblock.
https://github.com/ProseMirror/prosemirror-markdown/blob/master/src/to_markdown.js#L62
*/
params: {
parseHTML: (element) => {
return {
params: extractLanguage(element),
};
},
},
parseDOM: [
{
tag: 'pre',
preserveWhitespace: 'full',
getAttrs: (node) => {
const code = node.querySelector('code');
if (!code) {
return null;
}
return {
/* `params` is the name of the attribute that
prosemirror-markdown uses to extract the language
of a codeblock.
https://github.com/ProseMirror/prosemirror-markdown/blob/master/src/to_markdown.js#L62
*/
params: code.getAttribute('lang'),
};
},
},
],
};
}
}
},
});
export { default as createEditor } from './services/create_editor';
export * from './services/create_content_editor';
export { default as ContentEditor } from './components/content_editor.vue';
/* eslint-disable no-underscore-dangle */
export class ContentEditor {
constructor({ tiptapEditor, serializer }) {
this._tiptapEditor = tiptapEditor;
this._serializer = serializer;
}
get tiptapEditor() {
return this._tiptapEditor;
}
async setSerializedContent(serializedContent) {
const { _tiptapEditor: editor, _serializer: serializer } = this;
editor.commands.setContent(
await serializer.deserialize({ schema: editor.schema, content: serializedContent }),
);
}
getSerializedContent() {
const { _tiptapEditor: editor, _serializer: serializer } = this;
return serializer.serialize({ schema: editor.schema, content: editor.getJSON() });
}
}
import Blockquote from '@tiptap/extension-blockquote';
import Bold from '@tiptap/extension-bold';
import BulletList from '@tiptap/extension-bullet-list';
import Code from '@tiptap/extension-code';
import Document from '@tiptap/extension-document';
import Dropcursor from '@tiptap/extension-dropcursor';
import Gapcursor from '@tiptap/extension-gapcursor';
import HardBreak from '@tiptap/extension-hard-break';
import Heading from '@tiptap/extension-heading';
import History from '@tiptap/extension-history';
import HorizontalRule from '@tiptap/extension-horizontal-rule';
import Image from '@tiptap/extension-image';
import Italic from '@tiptap/extension-italic';
import Link from '@tiptap/extension-link';
import ListItem from '@tiptap/extension-list-item';
import OrderedList from '@tiptap/extension-ordered-list';
import Paragraph from '@tiptap/extension-paragraph';
import Text from '@tiptap/extension-text';
import { Editor } from '@tiptap/vue-2';
import { isFunction } from 'lodash';
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
import CodeBlockHighlight from '../extensions/code_block_highlight';
import { ContentEditor } from './content_editor';
import createMarkdownSerializer from './markdown_serializer';
const createTiptapEditor = ({ extensions = [], options } = {}) =>
new Editor({
extensions: [
Dropcursor,
Gapcursor,
History,
Document,
Text,
Paragraph,
Bold,
Italic,
Code,
Link,
Heading,
HardBreak,
Blockquote,
HorizontalRule,
BulletList,
OrderedList,
ListItem,
Image.configure({ inline: true }),
CodeBlockHighlight,
...extensions,
],
editorProps: {
attributes: {
class: 'gl-outline-0!',
},
},
...options,
});
export const createContentEditor = ({ renderMarkdown, extensions = [], tiptapOptions } = {}) => {
if (!isFunction(renderMarkdown)) {
throw new Error(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
}
const tiptapEditor = createTiptapEditor({ extensions, options: tiptapOptions });
const serializer = createMarkdownSerializer({ render: renderMarkdown });
return new ContentEditor({ tiptapEditor, serializer });
};
import { isFunction, isString } from 'lodash';
import { Editor } from 'tiptap';
import {
Bold,
Italic,
Code,
Link,
Image,
Heading,
Blockquote,
HorizontalRule,
BulletList,
OrderedList,
ListItem,
HardBreak,
} from 'tiptap-extensions';
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
import CodeBlockHighlight from '../extensions/code_block_highlight';
import createMarkdownSerializer from './markdown_serializer';
const createEditor = async ({
content,
renderMarkdown,
serializer: customSerializer,
...options
} = {}) => {
if (!customSerializer && !isFunction(renderMarkdown)) {
throw new Error(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
}
const editor = new Editor({
extensions: [
new Bold(),
new Italic(),
new Code(),
new Link(),
new Image(),
new Heading({ levels: [1, 2, 3, 4, 5, 6] }),
new Blockquote(),
new HorizontalRule(),
new BulletList(),
new ListItem(),
new OrderedList(),
new CodeBlockHighlight(),
new HardBreak(),
],
editorProps: {
attributes: {
class: 'gl-outline-0!',
},
},
...options,
});
const serializer = customSerializer || createMarkdownSerializer({ render: renderMarkdown });
editor.setSerializedContent = async (serializedContent) => {
editor.setContent(
await serializer.deserialize({ schema: editor.schema, content: serializedContent }),
);
};
editor.getSerializedContent = () => {
return serializer.serialize({ schema: editor.schema, content: editor.getJSON() });
};
if (isString(content)) {
await editor.setSerializedContent(content);
}
return editor;
};
export default createEditor;
......@@ -54,14 +54,24 @@ const create = ({ render = () => null }) => {
*/
serialize: ({ schema, content }) => {
const document = schema.nodeFromJSON(content);
const serializer = new ProseMirrorMarkdownSerializer(defaultMarkdownSerializer.nodes, {
...defaultMarkdownSerializer.marks,
bold: {
// creates a bold alias for the strong mark converter
...defaultMarkdownSerializer.marks.strong,
const { nodes, marks } = defaultMarkdownSerializer;
const serializer = new ProseMirrorMarkdownSerializer(
{
...defaultMarkdownSerializer.nodes,
horizontalRule: nodes.horizontal_rule,
bulletList: nodes.bullet_list,
listItem: nodes.list_item,
orderedList: nodes.ordered_list,
codeBlock: nodes.code_block,
hardBreak: nodes.hard_break,
},
italic: { open: '_', close: '_', mixable: true, expelEnclosingWhitespace: true },
});
{
...defaultMarkdownSerializer.marks,
bold: marks.strong,
italic: { open: '_', close: '_', mixable: true, expelEnclosingWhitespace: true },
},
);
return serializer.serialize(document, {
tightLists: true,
......
......@@ -39,7 +39,7 @@ export default {
isContentEditorLoading: true,
useContentEditor: false,
commitMessage: '',
editor: null,
contentEditor: null,
isDirty: false,
};
},
......@@ -102,7 +102,7 @@ export default {
handleFormSubmit() {
if (this.useContentEditor) {
this.content = this.editor.getSerializedContent();
this.content = this.contentEditor.getSerializedContent();
}
this.isDirty = false;
......@@ -136,16 +136,18 @@ export default {
this.isContentEditorLoading = true;
this.useContentEditor = true;
const createEditor = await import(
/* webpackChunkName: 'content_editor' */ '~/content_editor/services/create_editor'
const { createContentEditor } = await import(
/* webpackChunkName: 'content_editor' */ '~/content_editor/services/create_content_editor'
);
this.editor =
this.editor ||
(await createEditor.default({
this.contentEditor =
this.contentEditor ||
createContentEditor({
renderMarkdown: (markdown) => this.getContentHTML(markdown),
onUpdate: () => this.handleContentChange(),
}));
await this.editor.setSerializedContent(this.content);
tiptapOptions: {
onUpdate: () => this.handleContentChange(),
},
});
await this.contentEditor.setSerializedContent(this.content);
this.isContentEditorLoading = false;
},
......@@ -296,7 +298,7 @@ export default {
<div v-if="isContentEditorActive">
<gl-loading-icon v-if="isContentEditorLoading" class="bordered-box gl-w-full gl-py-6" />
<content-editor v-else :editor="editor" />
<content-editor v-else :content-editor="contentEditor" />
<input id="wiki_content" v-model.trim="content" type="hidden" name="wiki[content]" />
</div>
......
......@@ -307,11 +307,11 @@ module.exports = {
chunks: 'initial',
minChunks: autoEntriesCount * 0.9,
}),
tiptap: {
prosemirror: {
priority: 17,
name: 'tiptap',
name: 'prosemirror',
chunks: 'all',
test: /[\\/]node_modules[\\/](tiptap|prosemirror)-?\w*[\\/]/,
test: /[\\/]node_modules[\\/]prosemirror.*?[\\/]/,
minChunks: 2,
reuseExistingChunk: true,
},
......
import { mount } from '@vue/test-utils';
import { EditorContent } from 'tiptap';
import waitForPromises from 'helpers/wait_for_promises';
import { EditorContent } from '@tiptap/vue-2';
import { shallowMount } from '@vue/test-utils';
import ContentEditor from '~/content_editor/components/content_editor.vue';
import TopToolbar from '~/content_editor/components/top_toolbar.vue';
import createEditor from '~/content_editor/services/create_editor';
import { createContentEditor } from '~/content_editor/services/create_content_editor';
describe('ContentEditor', () => {
let wrapper;
let editor;
const createWrapper = async (_editor) => {
wrapper = mount(ContentEditor, {
const createWrapper = async (contentEditor) => {
wrapper = shallowMount(ContentEditor, {
propsData: {
editor: _editor,
contentEditor,
},
});
};
beforeEach(async () => {
editor = await createEditor({ renderMarkdown: () => 'sample text' });
createWrapper(editor);
await waitForPromises();
beforeEach(() => {
editor = createContentEditor({ renderMarkdown: () => true });
});
afterEach(() => {
wrapper.destroy();
});
it('renders editor content component and attaches editor instance', async () => {
expect(wrapper.findComponent(EditorContent).props().editor).toBe(editor);
it('renders editor content component and attaches editor instance', () => {
createWrapper(editor);
expect(wrapper.findComponent(EditorContent).props().editor).toBe(editor.tiptapEditor);
});
it('renders top toolbar component and attaches editor instance', () => {
createWrapper(editor);
expect(wrapper.findComponent(TopToolbar).props().contentEditor).toBe(editor);
});
it('renders top toolbar component and attaches editor instance', async () => {
expect(wrapper.findComponent(TopToolbar).props().editor).toBe(editor);
it.each`
isFocused | classes
${true} | ${['md', 'md-area', 'is-focused']}
${false} | ${['md', 'md-area']}
`(
'has $classes class selectors when tiptapEditor.isFocused = $isFocused',
({ isFocused, classes }) => {
editor.tiptapEditor.isFocused = isFocused;
createWrapper(editor);
expect(wrapper.classes()).toStrictEqual(classes);
},
);
it('adds isFocused class when tiptapEditor is focused', () => {
editor.tiptapEditor.isFocused = true;
createWrapper(editor);
expect(wrapper.classes()).toContain('is-focused');
});
});
import { GlButton } from '@gitlab/ui';
import { Extension } from '@tiptap/core';
import { shallowMount } from '@vue/test-utils';
import ToolbarButton from '~/content_editor/components/toolbar_button.vue';
import { createContentEditor } from '~/content_editor/services/create_content_editor';
describe('content_editor/components/toolbar_button', () => {
let wrapper;
let editor;
let tiptapEditor;
let toggleFooSpy;
const CONTENT_TYPE = 'bold';
const ICON_NAME = 'bold';
const LABEL = 'Bold';
const buildEditor = () => {
editor = {
isActive: {
[CONTENT_TYPE]: jest.fn(),
},
commands: {
[CONTENT_TYPE]: jest.fn(),
},
};
toggleFooSpy = jest.fn();
tiptapEditor = createContentEditor({
extensions: [
Extension.create({
addCommands() {
return {
toggleFoo: () => toggleFooSpy,
};
},
}),
],
renderMarkdown: () => true,
}).tiptapEditor;
jest.spyOn(tiptapEditor, 'isActive');
};
const buildWrapper = (propsData = {}) => {
......@@ -26,7 +36,7 @@ describe('content_editor/components/toolbar_button', () => {
GlButton,
},
propsData: {
editor,
tiptapEditor,
contentType: CONTENT_TYPE,
iconName: ICON_NAME,
label: LABEL,
......@@ -51,34 +61,35 @@ describe('content_editor/components/toolbar_button', () => {
});
it.each`
editorState | outcomeDescription | outcome
${{ isActive: true, focused: true }} | ${'button is active'} | ${true}
${{ isActive: false, focused: true }} | ${'button is not active'} | ${false}
${{ isActive: true, focused: false }} | ${'button is not active '} | ${false}
editorState | outcomeDescription | outcome
${{ isActive: true, isFocused: true }} | ${'button is active'} | ${true}
${{ isActive: false, isFocused: true }} | ${'button is not active'} | ${false}
${{ isActive: true, isFocused: false }} | ${'button is not active '} | ${false}
`('$outcomeDescription when when editor state is $editorState', ({ editorState, outcome }) => {
editor.isActive[CONTENT_TYPE].mockReturnValueOnce(editorState.isActive);
editor.focused = editorState.focused;
tiptapEditor.isActive.mockReturnValueOnce(editorState.isActive);
tiptapEditor.isFocused = editorState.isFocused;
buildWrapper();
expect(findButton().classes().includes('active')).toBe(outcome);
expect(tiptapEditor.isActive).toHaveBeenCalledWith(CONTENT_TYPE);
});
describe('when button is clicked', () => {
it('executes the content type command when executeCommand = true', async () => {
buildWrapper({ executeCommand: true });
buildWrapper({ editorCommand: 'toggleFoo' });
await findButton().trigger('click');
expect(editor.commands[CONTENT_TYPE]).toHaveBeenCalled();
expect(toggleFooSpy).toHaveBeenCalled();
expect(wrapper.emitted().click).toHaveLength(1);
});
it('does not executes the content type command when executeCommand = false', async () => {
buildWrapper({ executeCommand: false });
buildWrapper();
await findButton().trigger('click');
expect(editor.commands[CONTENT_TYPE]).not.toHaveBeenCalled();
expect(toggleFooSpy).not.toHaveBeenCalled();
expect(wrapper.emitted().click).toHaveLength(1);
});
});
......
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import TopToolbar from '~/content_editor/components/top_toolbar.vue';
import { createContentEditor } from '~/content_editor/services/create_content_editor';
describe('content_editor/components/top_toolbar', () => {
let wrapper;
let editor;
let contentEditor;
const buildEditor = () => {
editor = {};
contentEditor = createContentEditor({ renderMarkdown: () => true });
};
const buildWrapper = () => {
wrapper = extendedWrapper(
shallowMount(TopToolbar, {
propsData: {
editor,
contentEditor,
},
}),
);
......@@ -29,18 +30,18 @@ describe('content_editor/components/top_toolbar', () => {
});
it.each`
testId | button
${'bold'} | ${{ contentType: 'bold', iconName: 'bold', label: 'Bold' }}
${'italic'} | ${{ contentType: 'italic', iconName: 'italic', label: 'Italic' }}
${'code'} | ${{ contentType: 'code', iconName: 'code', label: 'Code' }}
${'blockquote'} | ${{ contentType: 'blockquote', iconName: 'quote', label: 'Insert a quote' }}
${'bullet-list'} | ${{ contentType: 'bullet_list', iconName: 'list-bulleted', label: 'Add a bullet list' }}
${'ordered-list'} | ${{ contentType: 'ordered_list', iconName: 'list-numbered', label: 'Add a numbered list' }}
testId | buttonProps
${'bold'} | ${{ contentType: 'bold', iconName: 'bold', label: 'Bold text', editorCommand: 'toggleBold' }}
${'italic'} | ${{ contentType: 'italic', iconName: 'italic', label: 'Italic text', editorCommand: 'toggleItalic' }}
${'code'} | ${{ contentType: 'code', iconName: 'code', label: 'Code', editorCommand: 'toggleCode' }}
${'blockquote'} | ${{ contentType: 'blockquote', iconName: 'quote', label: 'Insert a quote', editorCommand: 'toggleBlockquote' }}
${'bullet-list'} | ${{ contentType: 'bulletList', iconName: 'list-bulleted', label: 'Add a bullet list', editorCommand: 'toggleBulletList' }}
${'ordered-list'} | ${{ contentType: 'orderedList', iconName: 'list-numbered', label: 'Add a numbered list', editorCommand: 'toggleOrderedList' }}
`('renders $testId button', ({ testId, buttonProps }) => {
buildWrapper();
expect(wrapper.findByTestId(testId).props()).toMatchObject({
expect(wrapper.findByTestId(testId).props()).toEqual({
...buttonProps,
editor,
tiptapEditor: contentEditor.tiptapEditor,
});
});
});
import { createEditor } from '~/content_editor';
import { createContentEditor } from '~/content_editor';
import { loadMarkdownApiExamples, loadMarkdownApiResult } from './markdown_processing_examples';
describe('markdown processing', () => {
// Ensure we generate same markdown that was provided to Markdown API.
it.each(loadMarkdownApiExamples())('correctly handles %s', async (testName, markdown) => {
const { html } = loadMarkdownApiResult(testName);
const editor = await createEditor({ content: markdown, renderMarkdown: () => html });
const contentEditor = createContentEditor({ renderMarkdown: () => html });
await contentEditor.setSerializedContent(markdown);
expect(editor.getSerializedContent()).toBe(markdown);
expect(contentEditor.getSerializedContent()).toBe(markdown);
});
});
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '~/content_editor/constants';
import { createContentEditor } from '~/content_editor/services/create_content_editor';
describe('content_editor/services/create_editor', () => {
let renderMarkdown;
let editor;
beforeEach(() => {
renderMarkdown = jest.fn();
editor = createContentEditor({ renderMarkdown });
});
it('sets gl-outline-0! class selector to the tiptapEditor instance', () => {
expect(editor.tiptapEditor.options.editorProps).toMatchObject({
attributes: {
class: 'gl-outline-0!',
},
});
});
it('provides the renderMarkdown function to the markdown serializer', async () => {
const serializedContent = '**bold text**';
renderMarkdown.mockReturnValueOnce('<p><b>bold text</b></p>');
await editor.setSerializedContent(serializedContent);
expect(renderMarkdown).toHaveBeenCalledWith(serializedContent);
});
it('throws an error when a renderMarkdown fn is not provided', () => {
expect(() => createContentEditor()).toThrow(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
});
});
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '~/content_editor/constants';
import createEditor from '~/content_editor/services/create_editor';
import createMarkdownSerializer from '~/content_editor/services/markdown_serializer';
jest.mock('~/content_editor/services/markdown_serializer');
describe('content_editor/services/create_editor', () => {
const renderMarkdown = () => true;
const buildMockSerializer = () => ({
serialize: jest.fn(),
deserialize: jest.fn(),
});
it('sets gl-outline-0! class selector to editor attributes', async () => {
const editor = await createEditor({ renderMarkdown });
expect(editor.options.editorProps).toMatchObject({
attributes: {
class: 'gl-outline-0!',
},
});
});
describe('creating an editor', () => {
it('uses markdown serializer when a renderMarkdown function is provided', async () => {
const mockSerializer = buildMockSerializer();
createMarkdownSerializer.mockReturnValueOnce(mockSerializer);
await createEditor({ renderMarkdown });
expect(createMarkdownSerializer).toHaveBeenCalledWith({ render: renderMarkdown });
});
it('uses custom serializer when it is provided', async () => {
const mockSerializer = buildMockSerializer();
const serializedContent = '**bold**';
mockSerializer.serialize.mockReturnValueOnce(serializedContent);
const editor = await createEditor({ serializer: mockSerializer });
expect(editor.getSerializedContent()).toBe(serializedContent);
});
it('throws an error when neither a serializer or renderMarkdown fn are provided', async () => {
await expect(createEditor()).rejects.toThrow(PROVIDE_SERIALIZER_OR_RENDERER_ERROR);
});
});
});
......@@ -337,7 +337,10 @@ describe('WikiForm', () => {
// wait for content editor to load
await waitForPromises();
wrapper.vm.editor.setContent('<p>hello __world__ from content editor</p>', true);
wrapper.vm.contentEditor.tiptapEditor.commands.setContent(
'<p>hello __world__ from content editor</p>',
true,
);
await waitForPromises();
......@@ -378,7 +381,10 @@ describe('WikiForm', () => {
// wait for content editor to load
await waitForPromises();
wrapper.vm.editor.setContent('<p>hello __world__ from content editor</p>', true);
wrapper.vm.contentEditor.tiptapEditor.commands.setContent(
'<p>hello __world__ from content editor</p>',
true,
);
wrapper.findComponent(GlAlert).findComponent(GlButton).trigger('click');
await wrapper.vm.$nextTick();
......
......@@ -1170,6 +1170,11 @@
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.12.tgz#431ec342a7195622f86688bbda82e3166ce8cb28"
integrity sha512-6RglhutqrGFMO1MNUXp95RBuYIuc8wTnMAV5MUhLmjTOy78ncwOw7RgeQ/HeymkKXRhZd0s2DNrM1rL7unk3MQ==
"@popperjs/core@^2.8.3":
version "2.9.2"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
"@rails/actioncable@^6.0.3-4":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.0.tgz#f336f25450b1bc43b99bc60557a70b6e6bb1d3d2"
......@@ -1291,6 +1296,190 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
"@tiptap/core@^2.0.0-beta.38":
version "2.0.0-beta.38"
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.38.tgz#b0ded8d6ced0a345cc8739f6d86dec3d96636987"
integrity sha512-5ZbFQjJoyFtpUbjvSxjlb5NB8MIgaP1jNKiceG/aDt0wEf7vLgPalcfu76e+iITTjHU9VruaKINN1T+QA0fIZw==
dependencies:
"@types/prosemirror-commands" "^1.0.4"
"@types/prosemirror-inputrules" "^1.0.4"
"@types/prosemirror-keymap" "^1.0.4"
"@types/prosemirror-model" "^1.13.0"
"@types/prosemirror-schema-list" "^1.0.3"
"@types/prosemirror-state" "^1.2.6"
"@types/prosemirror-transform" "^1.1.2"
"@types/prosemirror-view" "^1.17.1"
prosemirror-commands "^1.1.7"
prosemirror-inputrules "^1.1.3"
prosemirror-keymap "^1.1.3"
prosemirror-model "^1.14.0"
prosemirror-schema-list "^1.1.4"
prosemirror-state "^1.3.4"
prosemirror-transform "^1.3.2"
prosemirror-view "^1.18.2"
"@tiptap/extension-blockquote@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.6.tgz#7670998307e88a0d0edf59558355a9328a6acec7"
integrity sha512-DOtr1Iy+wdyX2lrSX9KF6BaHvi0Sxg5tWfrAVHxPU7tCfxt33Xp6Ym97fyuZLlwUIbrzsy/DqBkdTYQ5v+CPMA==
dependencies:
prosemirror-inputrules "^1.1.3"
"@tiptap/extension-bold@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.6.tgz#347ddb7ad726d369337299b3800367815106de7f"
integrity sha512-hFxVQZcXWBCaCTCG3PJONhvTwoVGq/fJAQuPrYlI18z124Rhx6DeBkPG0FSwQgBeuJyezi4Jz61onkc48jwmSA==
"@tiptap/extension-bubble-menu@^2.0.0-beta.9":
version "2.0.0-beta.9"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.9.tgz#bbf6b819c7edd78f1dbc347f3d102f316928c385"
integrity sha512-GGxHwurQ6PediGy2b6q5at73CRznD6M6f1OSSuFVoIm2Q+FQMOECXKqLHpIOuHke6zYJpaAp1SfdX87/Zs5qaQ==
dependencies:
prosemirror-state "^1.3.4"
prosemirror-view "^1.18.2"
tippy.js "^6.3.1"
"@tiptap/extension-bullet-list@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.6.tgz#3830f4a6355f84061929085603f5423ae448d346"
integrity sha512-uO2t1CUc2Puq23c06xJvK9Imh895j1fsTJKJfEiSPDVMGrS3+tGOnQ2f9Fc5IOJITZZzFOpKnxRHC9AS5DySmg==
dependencies:
prosemirror-inputrules "^1.1.3"
"@tiptap/extension-code-block-lowlight@^2.0.0-beta.9":
version "2.0.0-beta.9"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.9.tgz#96095ca9e00553c488e5f10b2eedd904c1d5ed9e"
integrity sha512-EwDcARAxj8ZowpUQlhM/8aGlw+jmOtuov96Wg9KVmLJbUVmhETivhhlD31WVjyFdDB3nOA6bHqygjy+GP1/jAQ==
dependencies:
"@tiptap/extension-code-block" "^2.0.0-beta.6"
"@types/lowlight" "^0.0.1"
lowlight "^1.20.0"
prosemirror-model "^1.14.0"
prosemirror-state "^1.3.4"
prosemirror-view "^1.18.2"
"@tiptap/extension-code-block@^2.0.0-beta.6":
version "2.0.0-beta.8"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.8.tgz#f26d8992be6ea78f34a7db52b0a706293d19922d"
integrity sha512-lSeC98qJ8szMUgp/hFZFMqDfV/boGpMN3kek98BR6dCI8QSHvZWpHrQ8n9dyc8NEGAuvBhP/lu0PSD1TzYwkig==
dependencies:
prosemirror-inputrules "^1.1.3"
"@tiptap/extension-code@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.6.tgz#c35f0a8b1f3fe05b5ec9ced5aea6c9b093073d09"
integrity sha512-i0s3yTSdONUOp0fM/VrdSQfdj0SsqTPyP2ev2Ji1KgzGQ49Rw8gewT6RorHMwvMdv+F5+wE47wI2rcdUjpNwMQ==
"@tiptap/extension-document@^2.0.0-beta.5":
version "2.0.0-beta.5"
resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.5.tgz#595c25879eb39f26cdb58e9b01ff5e48d65b2e4b"
integrity sha512-6GAZ7gA3vzStkASe+Qsd/OqqQ9QnDTjBKpXVxMZZnqutUmWjPau9e0kLEFYoU57f5bJa2w/TCWICSp+o4ka3jg==
"@tiptap/extension-dropcursor@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.6.tgz#9a7569c970010c47424e93f67f907ce7f0c3c429"
integrity sha512-EUmagYkamxuxZprKCXcSrwqUZkOW6edxIb7iyL0RQLYAcJ2jwCe9hJU0G6a8ILDr027W7fXd6LDbrzPMcVK/ug==
dependencies:
"@types/prosemirror-dropcursor" "^1.0.1"
prosemirror-dropcursor "^1.3.4"
"@tiptap/extension-floating-menu@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.6.tgz#617290bd0533412e40c09dde7ecadc4a8c3cf960"
integrity sha512-2j73cDaN+flG8mF/PHd8OrZjaG62r3Kbskzpdsa2Oa6fV3laNg0jMhFzcuBJwFKFa0l8RHB/zMXNpacxCHa9vw==
dependencies:
prosemirror-state "^1.3.4"
prosemirror-view "^1.18.2"
tippy.js "^6.3.1"
"@tiptap/extension-gapcursor@^2.0.0-beta.10":
version "2.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.10.tgz#f045d90def63559797576a299f904f539c304fe9"
integrity sha512-q5S3AjDTBi5WHwl1V7iYSk32t3mk/Z/ZYAViLDsqffzurx6KIxq9Yw6Ad1L+h04wXq/rJiFeaMeCnGs4DmWa3w==
dependencies:
"@types/prosemirror-gapcursor" "^1.0.3"
prosemirror-gapcursor "^1.1.5"
"@tiptap/extension-hard-break@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.6.tgz#37bee563b06a528d6b72ea875de7645f97a43656"
integrity sha512-FZ/wpC9YQY50rt85DuPl+Dxe157LtHAhKW08BRAds/o6zrwcBpbg7zzVPxnu1wH1L0ObhyxCjNFXUyKalLnk8g==
"@tiptap/extension-heading@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.6.tgz#077919803ed4d8c729a72cc122cfca851bfaeff3"
integrity sha512-zM5zaWGbJDYDmuHZ+YHTZK2nncDs+tlhfYKTKPK+0iIFCO4iTkvs7ERUO9qdbuQKjHGp28Q3RhS7YORss2bOhA==
dependencies:
prosemirror-inputrules "^1.1.3"
"@tiptap/extension-history@^2.0.0-beta.5":
version "2.0.0-beta.5"
resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.5.tgz#bb9b257c110b0ad324407443972a623efa71816d"
integrity sha512-ej0QtStZVm8QInWHEtyduK9WQcYpfPN2EtIkwtPL9HFm9u7xgouBVdj1TqIABV3vJVGL28KKpGVVg8ZuBF4h7g==
dependencies:
"@types/prosemirror-history" "^1.0.2"
prosemirror-history "^1.1.3"
"@tiptap/extension-horizontal-rule@^2.0.0-beta.7":
version "2.0.0-beta.7"
resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.7.tgz#6e75336a0316bef1a359de7d1888c8fb97d5e659"
integrity sha512-TOxoVyKL3qF0e+VCQ5B7BpdtspvvY0TdU6/AJVIatPK9rXXXcJTM68k0O4koXgeuu33CSPXWVNwgm3QcxMi3Dg==
dependencies:
prosemirror-state "^1.3.4"
"@tiptap/extension-image@^2.0.0-beta.4":
version "2.0.0-beta.4"
resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.4.tgz#91151af0268b2de911ba9ea22099f00638f08d1e"
integrity sha512-NKqTmrxh8SmWUGex4QBq9Mjv7gIaJ8QlG//CXSW5s6QtLhjRbY9QFtBWK2FYOgyk2UBU6gmUA4wX6Eb0KGa4XQ==
"@tiptap/extension-italic@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.6.tgz#497cc5aac4077b27d6c548896601dd240771401a"
integrity sha512-HjB6YCm4oQ04peQ9M2zi4101JSgNfOLTkyfbDhpQv+B61sZtuweJx27SxYDOB34dA+i513orCVZdI6AgSSCEHA==
"@tiptap/extension-link@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.6.tgz#8e0051593d24ee232387535de716f87d4c388062"
integrity sha512-zV7AJTgvGfYqtKYeywLg0lDLkYFynRW6Llh6C+hYw2w9Wq0fSZfTtpkcQPYv+jOcOoAFi2Ea02jyGQ+VthGZKg==
dependencies:
prosemirror-state "^1.3.4"
"@tiptap/extension-list-item@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.6.tgz#69850d2d9242e213a24a7e10baecb0f0933f3cbe"
integrity sha512-zhssny5W2Q7CvB9qZT1Wc7k0V+R7IqCbNBmoijwF9a+uehBpJcxdN1DFB1v0qdmIEdDLU9dnBUfIpWPnLwiAXw==
"@tiptap/extension-ordered-list@^2.0.0-beta.6":
version "2.0.0-beta.6"
resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.6.tgz#ce214854946284c7ff2d458c7f4b3ac6ae33a9b8"
integrity sha512-dUiTO9bV3cuxWedp164KVufW3BzIwY/beQ64aQjnRyA3TPyiPrhp4qvHrxQujm31XPJy4zUY0PO/VafJ+69cGw==
dependencies:
prosemirror-inputrules "^1.1.3"
"@tiptap/extension-paragraph@^2.0.0-beta.7":
version "2.0.0-beta.7"
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.7.tgz#5dca1524247a57e98a60eb394ae66cd30072b9f4"
integrity sha512-bk9/KNbJ4wAvaAwrPLwp89QtEyef9VxbbaPd2+Q21EArTP2SGPNTWrjARq1Flc41fERo+2A23K5AcbNDBID9DA==
"@tiptap/extension-strike@^2.0.0-beta.7":
version "2.0.0-beta.7"
resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.7.tgz#cee0f3c087d2914f8435dc2cc4580c9aec0a42bb"
integrity sha512-GBctBeHSkDW4ivXAUaEBtOgQXJgT2q2iqWuI8kTHCO1z7c/mns4J19U24dx8bPFhJBw++sDDd8yBkLQH2lP/Pw==
"@tiptap/extension-text@^2.0.0-beta.5":
version "2.0.0-beta.5"
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.5.tgz#cce1f9b22a5e0ad35b081774059b8c2ec6c92ae3"
integrity sha512-WCavPVqi+tndW8tAQ4KBq98ZnkLgKW9nc/T8wE3oKQ+df9YBauIl3OxxMA6At/oK+vlcFfubBpzFRAg9iygRAA==
"@tiptap/vue-2@^2.0.0-beta.21":
version "2.0.0-beta.21"
resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.21.tgz#838257ef91bbd54995aa7d34e4682fc9c69cec6a"
integrity sha512-WTL6iw6cgMkQQ2b++kClQOxsByAUKYLcjO1UsjmrrWnaSDmfMO1ZpkmKKSp1SsuQAk7W0t9aybeyWrDzjxfU3g==
dependencies:
"@tiptap/extension-bubble-menu" "^2.0.0-beta.9"
"@tiptap/extension-floating-menu" "^2.0.0-beta.6"
prosemirror-view "^1.18.2"
"@toast-ui/editor@^2.5.2":
version "2.5.2"
resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.5.2.tgz#0637e1bbdb205c1ab53b6d3722ced26399b2f0ca"
......@@ -1411,6 +1600,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/lowlight@^0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@types/lowlight/-/lowlight-0.0.1.tgz#221bc67a6c517bae71e6f200fa1cad0feaeeb965"
integrity sha512-yPpbpV1KfpFOZ0ZZbsgwWumraiAKoX7/Ng75Ah//w+ZBt4j0xwrQ2aHSlk2kPzQVK4LiPbNFE1LjC00IL4nl/A==
"@types/mdast@^3.0.0":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.3.tgz#2d7d671b1cd1ea3deb306ea75036c2a0407d2deb"
......@@ -1438,6 +1632,11 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
"@types/orderedmap@*":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/orderedmap/-/orderedmap-1.0.0.tgz#807455a192bba52cbbb4517044bc82bdbfa8c596"
integrity sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw==
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
......@@ -1453,6 +1652,97 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3"
integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA==
"@types/prosemirror-commands@*", "@types/prosemirror-commands@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz#d08551415127d93ae62e7239d30db0b5e7208e22"
integrity sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-view" "*"
"@types/prosemirror-dropcursor@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.1.tgz#3ba98dd861ff2a62559e70f453f996a1ef5ec55d"
integrity sha512-nHokhFypOZjknolZBm2XShlR7fx1IUcCiA3S2fBwmAraWu6zv3gboDSwwFpoS9UB2xKc4ismAmBxh2bpL3YNkg==
dependencies:
"@types/prosemirror-state" "*"
"@types/prosemirror-gapcursor@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.3.tgz#989e98c734e01e2ed4cab39992e60a1b0646cab6"
integrity sha512-kBVjjbMmUk7ZsgpI1NOyY15makulu1skEGr+V9GgY7GQnT9vqjo8/XiNSgSj9s9vRTsTb/KAaTI9KJwWlhbhxQ==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-history@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/prosemirror-history/-/prosemirror-history-1.0.2.tgz#f90a009a0dcd71393faa69ce705593dec76347a1"
integrity sha512-AcfpWo+HkIuvq/H2zYjIMi2jxa2GWfYaTNiFTB2sigjkpWNM93CIlb7Cimy/4vNH8lVPp0GwLBjYIMRX6zOUyA==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-inputrules@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@types/prosemirror-inputrules/-/prosemirror-inputrules-1.0.4.tgz#4cb75054d954aa0f6f42099be05eb6c0e6958bae"
integrity sha512-lJIMpOjO47SYozQybUkpV6QmfuQt7GZKHtVrvS+mR5UekA8NMC5HRIVMyaIauJLWhKU6oaNjpVaXdw41kh165g==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-keymap@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz#f73c79810e8d0e0a20d153d84f998f02e5afbc0c"
integrity sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==
dependencies:
"@types/prosemirror-commands" "*"
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-view" "*"
"@types/prosemirror-model@*", "@types/prosemirror-model@^1.13.0":
version "1.13.0"
resolved "https://registry.yarnpkg.com/@types/prosemirror-model/-/prosemirror-model-1.13.0.tgz#d05937e918c3cac2cf49630ccab04a65fc5fffd6"
integrity sha512-EIUr2R38Zh9n1eA8BQ1C3NX/XLV9U44DhNVk8x3Sth2RW+wa7jNA82XHMPOoapsOTfmpnh32xaHBOzREiBqdPQ==
dependencies:
"@types/orderedmap" "*"
"@types/prosemirror-schema-list@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz#bdf1893a7915fbdc5c49b3cac9368e96213d70de"
integrity sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==
dependencies:
"@types/orderedmap" "*"
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-state@*", "@types/prosemirror-state@^1.2.6":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@types/prosemirror-state/-/prosemirror-state-1.2.6.tgz#bb0169084239a8393b354c6fda5420fc347d6bab"
integrity sha512-tJo0wC+/cQvbrPDVx01Fnng9Fs41bAMVxgJY1KLOyIsUPN0otUN1KdoQurLMmHNHTvIna9ZXxjZD//xJKLYfJw==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-transform" "*"
"@types/prosemirror-view" "*"
"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.2.tgz#fe883c19a5a9f1882346a294efd09d55c6764c7a"
integrity sha512-Ozyvs5Dquc49gaFysmC4gNhv6E65r569HSzw4RXdZgIljZ5Y9K4kHFlDvsWBBDH19+1178X9LMmM9J620O6Bug==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-view@*", "@types/prosemirror-view@^1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.17.1.tgz#0895df5a57ae6e68d4f3f8020d9be4ef52192980"
integrity sha512-PNiGGc6BffxHQzMR09UUilsBR8xFPDsKiPIXb4K/g56voPIvqq1pqySnWFfSR50Vo4ZL0tss3VBLWiiiKzVahQ==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
"@types/prosemirror-transform" "*"
"@types/stack-utils@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
......@@ -5858,10 +6148,10 @@ he@^1.1.0, he@^1.1.1, he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
highlight.js@^10.6.0, highlight.js@~10.6.0:
version "10.6.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.6.0.tgz#0073aa71d566906965ba6e1b7be7b2682f5e18b6"
integrity sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ==
highlight.js@^10.6.0, highlight.js@~10.7.0:
version "10.7.2"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360"
integrity sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg==
hmac-drbg@^1.0.1:
version "1.0.1"
......@@ -7862,13 +8152,13 @@ lowercase-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
lowlight@^1.17.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.19.0.tgz#b8544199cafcf10c5731b21c7458c358f79a2a97"
integrity sha512-NIskvQ1d1ovKyUytkMpT8+8Bhq3Ub54os1Xp4RAC9uNbXH1YVRf5NERq7JNzapEe5BzUc1Cj4F0I+eLBBFj6hA==
lowlight@^1.17.0, lowlight@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888"
integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==
dependencies:
fault "^1.0.0"
highlight.js "~10.6.0"
highlight.js "~10.7.0"
lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.5:
version "4.1.5"
......@@ -9570,7 +9860,7 @@ prosemirror-collab@^1.2.2:
dependencies:
prosemirror-state "^1.0.0"
prosemirror-commands@^1.1.4:
prosemirror-commands@^1.1.4, prosemirror-commands@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.7.tgz#5b31ae0fe82835d36d22c780641c0b651f27dd03"
integrity sha512-tuQr8q5euDjE+WAHWmu1JMLYWsPfUDH80QLLpnQrPYOPysO26FZyyHwEvA0+hUzvF8fOt1oMj0+/YM9UsPkZiA==
......@@ -9579,10 +9869,10 @@ prosemirror-commands@^1.1.4:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-dropcursor@^1.3.2:
version "1.3.3"
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.3.tgz#583d6a82b4960d468132c07c40803cc1d697fda4"
integrity sha512-zavE+wh+qkDcP7LaWn+jXVujGyQzBYSmM8E2HSngQ3KaaR+HJYgEBYGs9ynLHqKWLlLCXsxWdVYPV49v4caFyg==
prosemirror-dropcursor@^1.3.2, prosemirror-dropcursor@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.4.tgz#a7f799ff9ecb520d3e1dbb3cb39d27ce41066618"
integrity sha512-eVmpMG5+fmvANT3xDzRirmG240rB/piI31ExIfW0Mkvo5/cYC/lm1fFMAOzjO22uc5OQXiodRqOnyE05+g3UqA==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
......@@ -9615,7 +9905,7 @@ prosemirror-inputrules@^1.1.2, prosemirror-inputrules@^1.1.3:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.4:
prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.3, prosemirror-keymap@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.4.tgz#8b481bf8389a5ac40d38dbd67ec3da2c7eac6a6d"
integrity sha512-Al8cVUOnDFL4gcI5IDlG6xbZ0aOD/i3B17VT+1JbHWDguCgt/lBHVTHUBcKvvbSg6+q/W4Nj1Fu6bwZSca3xjg==
......@@ -9631,10 +9921,10 @@ prosemirror-markdown@^1.5.1:
markdown-it "^10.0.0"
prosemirror-model "^1.0.0"
prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.13.1, prosemirror-model@^1.13.3, prosemirror-model@^1.8.1:
version "1.13.3"
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.13.3.tgz#3ccfde73b9c9e706933c72bdf7462906509ff1c9"
integrity sha512-wujIYYQEcxdkbKmIJiekVjqtylKxuoEcc+w2PnN7Itc58m/75J4rCUz2dibygVQJFi3gZrD2DNFLjOS6LP4w1g==
prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.13.1, prosemirror-model@^1.13.3, prosemirror-model@^1.14.0, prosemirror-model@^1.8.1:
version "1.14.0"
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.14.0.tgz#44042a16942dfc5dcd79daf6ec37b0efcfef53c8"
integrity sha512-+9J7YE2qD2lsRgaI5aF7u6LynBoHxb/8sW1gaMKRAhK+yeQ+motBIaxb2GxRWSadDWMOq5haAImSTBo6jDkv2A==
dependencies:
orderedmap "^1.1.0"
......@@ -9646,7 +9936,7 @@ prosemirror-schema-list@^1.1.4:
prosemirror-model "^1.0.0"
prosemirror-transform "^1.0.0"
prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.3.3:
prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.3.3, prosemirror-state@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.3.4.tgz#4c6b52628216e753fc901c6d2bfd84ce109e8952"
integrity sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==
......@@ -9665,17 +9955,17 @@ prosemirror-tables@^1.1.1:
prosemirror-transform "^1.2.1"
prosemirror-view "^1.13.3"
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.2.8:
version "1.2.12"
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.2.12.tgz#4398b568faf75a1540fbf5c659ca436a8657ed6f"
integrity sha512-S73syqLcGBq6QiPaF7vriB8kpvK/aIFsnErrriKaFLSiE/GxMgBc62TPhNQAeGQr7/9GCDApIReTsJFcMt4o2w==
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.2.8, prosemirror-transform@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.3.2.tgz#5620ebe7379e6fae4f34ecc881886cb22ce96579"
integrity sha512-/G6d/u9Mf6Bv3H1XR8VxhpjmUO75LYmnvj+s3ZfZpakU1hnQbsvCEybml1B3f2IWUAAQRFkbO1PnsbFhLZsYsw==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5:
version "1.18.0"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.18.0.tgz#92d27b2583877938c529e173e6e3a0f3f6aa0e1c"
integrity sha512-UoY29oeWruT6RKhH7wGytUBVrlaszNx43wvOxZPCMjYPvKBT21EIXR8Ezr/3XstvFVBQAWdDh6Ke0qHmF43y/A==
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.18.2:
version "1.18.3"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.18.3.tgz#cfc70169cb300e9503d97362463ea870efffd3ef"
integrity sha512-B0zlzjBI0cHadpghyvAA+JgqLGbkNU9Vxywqkfaa+AdmOZUZImBKH6ufhpK+AEZn97WWgSIkr/MT9RmGpaboAA==
dependencies:
prosemirror-model "^1.1.0"
prosemirror-state "^1.0.0"
......@@ -11460,6 +11750,13 @@ tiny-emitter@^2.0.0:
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==
tippy.js@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.1.tgz#3788a007be7015eee0fd589a66b98fb3f8f10181"
integrity sha512-JnFncCq+rF1dTURupoJ4yPie5Cof978inW6/4S6kmWV7LL9YOSEVMifED3KdrVPEG+Z/TFH2CDNJcQEfaeuQww==
dependencies:
"@popperjs/core" "^2.8.3"
tiptap-commands@^1.17.1:
version "1.17.1"
resolved "https://registry.yarnpkg.com/tiptap-commands/-/tiptap-commands-1.17.1.tgz#a8974a26d87db57b2fd4fc56a552520c69e43a4a"
......@@ -11474,9 +11771,9 @@ tiptap-commands@^1.17.1:
tiptap-utils "^1.13.1"
tiptap-extensions@^1.35.1:
version "1.35.1"
resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.35.1.tgz#6227362b08dbad8d0ab0141b508876deca276c55"
integrity sha512-aCYvEKPUUtHBALBFQ9n70Iy/nfu/8DHHYkeXMgUJuwLLJ6LrJQBqUnV5EGRwPxNalNdqTdXjV+2z5flZfisovQ==
version "1.35.2"
resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.35.2.tgz#83dd6ee703ae8c83b58c7608f97253fcc4f1a94c"
integrity sha512-TIMbHVJe0/3aVeTeCmqGbatDkfxduPYFOffNCmuKR+h6oQNzTu6rLVhRzoNqktfxIoi/b44SiDPorTjSN72dCw==
dependencies:
lowlight "^1.17.0"
prosemirror-collab "^1.2.2"
......@@ -11486,7 +11783,7 @@ tiptap-extensions@^1.35.1:
prosemirror-tables "^1.1.1"
prosemirror-transform "^1.2.8"
prosemirror-view "^1.16.5"
tiptap "^1.32.1"
tiptap "^1.32.2"
tiptap-commands "^1.17.1"
tiptap-utils "^1.13.1"
......@@ -11499,10 +11796,10 @@ tiptap-utils@^1.13.1:
prosemirror-state "^1.3.3"
prosemirror-tables "^1.1.1"
tiptap@^1.32.1:
version "1.32.1"
resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.32.1.tgz#92b47008d163e31d25d44dc18809a7e928fe1daf"
integrity sha512-jXET6IAuvE67GdpcGdNE/RQ7I1eoeULXSrbriAa5fnyTUJQsDICd31/8LVaCh10OV1qkvQVCg/6oL1lQdakBLA==
tiptap@^1.32.1, tiptap@^1.32.2:
version "1.32.2"
resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.32.2.tgz#cd6259e853652bfc6860758ff44ebb695d5edd1c"
integrity sha512-5IwVj8nGo8y5V3jbdtoEd7xNUsi8Q0N6WV2Nfs70olqz3fldXkiImBrDhZJ4Anx8vhyP6PIBttrg0prFVmwIvw==
dependencies:
prosemirror-commands "^1.1.4"
prosemirror-dropcursor "^1.3.2"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment