diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-28 09:16:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-28 09:16:06 +0300 |
commit | 203b3660158829b85a49e045bf53d62da62aa88d (patch) | |
tree | 1dfb8e9544a7cb8227b5a2cbf0bc45b0fb6ce979 /app/assets/javascripts/content_editor | |
parent | ae4e46452b8799acd538fb96edfc60ba3214cefb (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/content_editor')
4 files changed, 46 insertions, 32 deletions
diff --git a/app/assets/javascripts/content_editor/services/content_editor.js b/app/assets/javascripts/content_editor/services/content_editor.js index 1fc05c434ca..e0995a5974c 100644 --- a/app/assets/javascripts/content_editor/services/content_editor.js +++ b/app/assets/javascripts/content_editor/services/content_editor.js @@ -1,9 +1,12 @@ +import { TextSelection } from 'prosemirror-state'; import { LOADING_CONTENT_EVENT, LOADING_SUCCESS_EVENT, LOADING_ERROR_EVENT } from '../constants'; + /* eslint-disable no-underscore-dangle */ export class ContentEditor { - constructor({ tiptapEditor, serializer, eventHub }) { + constructor({ tiptapEditor, serializer, deserializer, eventHub }) { this._tiptapEditor = tiptapEditor; this._serializer = serializer; + this._deserializer = deserializer; this._eventHub = eventHub; } @@ -31,15 +34,22 @@ export class ContentEditor { } async setSerializedContent(serializedContent) { - const { _tiptapEditor: editor, _serializer: serializer, _eventHub: eventHub } = this; + const { _tiptapEditor: editor, _deserializer: deserializer, _eventHub: eventHub } = this; + const { doc, tr } = editor.state; + const selection = TextSelection.create(doc, 0, doc.content.size); try { eventHub.$emit(LOADING_CONTENT_EVENT); - const document = await serializer.deserialize({ + const newDoc = await deserializer.deserialize({ schema: editor.schema, content: serializedContent, }); - editor.commands.setContent(document); + if (newDoc) { + tr.setSelection(selection) + .replaceSelectionWith(newDoc, false) + .setMeta('preventUpdate', true); + editor.view.dispatch(tr); + } eventHub.$emit(LOADING_SUCCESS_EVENT); } catch (e) { eventHub.$emit(LOADING_ERROR_EVENT, e); diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js index e26fc5ca8c9..354244b85ff 100644 --- a/app/assets/javascripts/content_editor/services/create_content_editor.js +++ b/app/assets/javascripts/content_editor/services/create_content_editor.js @@ -55,6 +55,7 @@ import Video from '../extensions/video'; import WordBreak from '../extensions/word_break'; import { ContentEditor } from './content_editor'; import createMarkdownSerializer from './markdown_serializer'; +import createMarkdownDeserializer from './markdown_deserializer'; import trackInputRulesAndShortcuts from './track_input_rules_and_shortcuts'; const createTiptapEditor = ({ extensions = [], ...options } = {}) => @@ -138,7 +139,8 @@ export const createContentEditor = ({ const allExtensions = [...builtInContentEditorExtensions, ...extensions]; const trackedExtensions = allExtensions.map(trackInputRulesAndShortcuts); const tiptapEditor = createTiptapEditor({ extensions: trackedExtensions, ...tiptapOptions }); - const serializer = createMarkdownSerializer({ render: renderMarkdown, serializerConfig }); + const serializer = createMarkdownSerializer({ serializerConfig }); + const deserializer = createMarkdownDeserializer({ render: renderMarkdown }); - return new ContentEditor({ tiptapEditor, serializer, eventHub }); + return new ContentEditor({ tiptapEditor, serializer, eventHub, deserializer }); }; diff --git a/app/assets/javascripts/content_editor/services/markdown_deserializer.js b/app/assets/javascripts/content_editor/services/markdown_deserializer.js new file mode 100644 index 00000000000..ccffcd4cee8 --- /dev/null +++ b/app/assets/javascripts/content_editor/services/markdown_deserializer.js @@ -0,0 +1,27 @@ +import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model'; + +export default ({ render }) => { + /** + * Converts a Markdown string into a ProseMirror JSONDocument based + * on a ProseMirror schema. + * @param {ProseMirror.Schema} params.schema A ProseMirror schema that defines + * the types of content supported in the document + * @param {String} params.content An arbitrary markdown string + * @returns A ProseMirror JSONDocument + */ + return { + deserialize: async ({ schema, content }) => { + const html = await render(content); + + if (!html) return null; + + const parser = new DOMParser(); + const { body } = parser.parseFromString(html, 'text/html'); + + // append original source as a comment that nodes can access + body.append(document.createComment(content)); + + return ProseMirrorDOMParser.fromSchema(schema).parse(body); + }, + }; +}; diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js index 925b411e51c..eaaf69c3068 100644 --- a/app/assets/javascripts/content_editor/services/markdown_serializer.js +++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js @@ -1,4 +1,3 @@ -import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model'; import { MarkdownSerializer as ProseMirrorMarkdownSerializer, defaultMarkdownSerializer, @@ -237,31 +236,7 @@ const defaultSerializerConfig = { * that parses the Markdown and converts it into HTML. * @returns a markdown serializer */ -export default ({ render = () => null, serializerConfig = {} } = {}) => ({ - /** - * Converts a Markdown string into a ProseMirror JSONDocument based - * on a ProseMirror schema. - * @param {ProseMirror.Schema} params.schema A ProseMirror schema that defines - * the types of content supported in the document - * @param {String} params.content An arbitrary markdown string - * @returns A ProseMirror JSONDocument - */ - deserialize: async ({ schema, content }) => { - const html = await render(content); - - if (!html) return null; - - const parser = new DOMParser(); - const { body } = parser.parseFromString(html, 'text/html'); - - // append original source as a comment that nodes can access - body.append(document.createComment(content)); - - const state = ProseMirrorDOMParser.fromSchema(schema).parse(body); - - return state.toJSON(); - }, - +export default ({ serializerConfig = {} } = {}) => ({ /** * Converts a ProseMirror JSONDocument based * on a ProseMirror schema into Markdown |