Skip to content

Commit

Permalink
refactor(EditorFactory): split createEditor in rich and plain variant
Browse files Browse the repository at this point in the history
Use two functions that do one thing
rather than one with a boolean flag.

Simplifies the functions use and signature a lot
in particular since plain and rich editor need different arguments.

Signed-off-by: Max <max@nextcloud.com>
  • Loading branch information
max-nextcloud committed Oct 8, 2024
1 parent a77c303 commit a87e233
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 92 deletions.
36 changes: 20 additions & 16 deletions src/EditorFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ const loadSyntaxHighlight = async (language) => {
}
}

const createEditor = ({ language, onCreate = () => {}, onUpdate = () => {}, extensions, enableRichEditing, session, relativePath, isEmbedded = false }) => {
let defaultExtensions
if (enableRichEditing) {
defaultExtensions = [
const editorProps = {
scrollMargin: 50,
scrollThreshold: 50,
}

const createRichEditor = ({ extensions = [], session, relativePath, isEmbedded = false } = {}) => {
return new Editor({
editorProps,
extensions: [
RichText.configure({
relativePath,
isEmbedded,
Expand All @@ -49,25 +54,24 @@ const createEditor = ({ language, onCreate = () => {}, onUpdate = () => {}, exte
],
}),
FocusTrap,
...extensions,
]

Check warning on line 58 in src/EditorFactory.js

View workflow job for this annotation

GitHub Actions / NPM lint

Missing trailing comma
} else {
defaultExtensions = [PlainText, CodeBlockLowlight.configure({ lowlight, defaultLanguage: language })]
}
})
}

const createPlainEditor = ({ language, extensions = [] } = {}) => {
return new Editor({
onCreate,
onUpdate,
editorProps: {
scrollMargin: 50,
scrollThreshold: 50,
},
extensions: defaultExtensions.concat(extensions || []),
editorProps,
extensions: [
PlainText,
CodeBlockLowlight.configure({ lowlight, defaultLanguage: language }),
...extensions,
]

Check warning on line 69 in src/EditorFactory.js

View workflow job for this annotation

GitHub Actions / NPM lint

Missing trailing comma
})
}

const serializePlainText = (doc) => {
return doc.textContent
}

export default createEditor
export { createEditor, serializePlainText, loadSyntaxHighlight }
export { createRichEditor, createPlainEditor, serializePlainText, loadSyntaxHighlight }
89 changes: 49 additions & 40 deletions src/components/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ import { SyncService, ERROR_TYPE, IDLE_TIMEOUT } from './../services/SyncService
import createSyncServiceProvider from './../services/SyncServiceProvider.js'
import AttachmentResolver from './../services/AttachmentResolver.js'
import { extensionHighlight } from '../helpers/mappings.js'
import { createEditor, serializePlainText, loadSyntaxHighlight } from './../EditorFactory.js'
import {
createRichEditor,
createPlainEditor,
serializePlainText,
loadSyntaxHighlight

Check warning on line 105 in src/components/Editor.vue

View workflow job for this annotation

GitHub Actions / NPM lint

Missing trailing comma
} from './../EditorFactory.js'
import { createMarkdownSerializer } from './../extensions/Markdown.js'
import markdownit from './../markdownit/index.js'

Expand Down Expand Up @@ -401,10 +406,15 @@ export default {
listenEditorEvents() {
this.$editor.on('focus', this.onFocus)
this.$editor.on('blur', this.onBlur)
this.$editor.on('create', this.onCreate)
this.$editor.on('update', this.onUpdate)
},

unlistenEditorEvents() {
this.$editor.off('focus', this.onFocus)
this.$editor.off('blur', this.onBlur)
this.$editor.off('create', this.onCreate)
this.$editor.off('update', this.onUpdate)
},

listenSyncServiceEvents() {
Expand Down Expand Up @@ -510,45 +520,28 @@ export default {
.then(() => {
const session = this.currentSession
if (!this.$editor) {
this.$editor = createEditor({
language,
relativePath: this.relativePath,
session,
onCreate: ({ editor }) => {
this.$syncService.startSync()
const proseMirrorMarkdown = this.$syncService.serialize(editor.state.doc)
this.emit('create:content', {
markdown: proseMirrorMarkdown,
})
},
onUpdate: ({ editor }) => {
// this.debugContent(editor)
const proseMirrorMarkdown = this.$syncService.serialize(editor.state.doc)
this.emit('update:content', {
markdown: proseMirrorMarkdown,
})
},
extensions: [
Autofocus.configure({
fileId: this.fileId,
}),
Collaboration.configure({
document: this.$ydoc,
}),
CollaborationCursor.configure({
provider: this.$providers[0],
user: {
name: session?.userId
? session.displayName
: (session?.guestName || t('text', 'Guest')),
color: session?.color,
clientId: this.$ydoc.clientID,
},
}),
],
enableRichEditing: this.isRichEditor,
isEmbedded: this.isEmbedded,
})
const extensions = [
Autofocus.configure({ fileId: this.fileId }),
Collaboration.configure({ document: this.$ydoc }),
CollaborationCursor.configure({
provider: this.$providers[0],
user: {
name: session?.userId
? session.displayName
: (session?.guestName || t('text', 'Guest')),
color: session?.color,
clientId: this.$ydoc.clientID,
},
}),
]
this.$editor = this.isRichEditor
? createRichEditor({
relativePath: this.relativePath,
session,
extensions,
isEmbedded: this.isEmbedded,
})
: createPlainEditor({ language, extensions })
this.hasEditor = true
this.listenEditorEvents()
} else {
Expand All @@ -571,6 +564,22 @@ export default {
}
},

onCreate({ editor }) {
this.$syncService.startSync()
const proseMirrorMarkdown = this.$syncService.serialize(editor.state.doc)
this.emit('create:content', {
markdown: proseMirrorMarkdown,
})
},

onUpdate({ editor }) {
// this.debugContent(editor)
const proseMirrorMarkdown = this.$syncService.serialize(editor.state.doc)
this.emit('update:content', {
markdown: proseMirrorMarkdown,
})
},

onSync({ steps, document }) {
this.hasConnectionIssue = this.$syncService.backend.fetcher === 0 || !this.$providers[0].wsconnected || this.$syncService.pushError > 0
this.$nextTick(() => {
Expand Down
9 changes: 5 additions & 4 deletions src/mixins/setContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Doc, encodeStateAsUpdate, XmlFragment, applyUpdate } from 'yjs'
import { generateJSON } from '@tiptap/core'
import { prosemirrorToYXmlFragment } from 'y-prosemirror'
import { Node } from '@tiptap/pm/model'
import { createEditor } from '../EditorFactory.js'
import { createRichEditor, createPlainEditor } from '../EditorFactory.js'

export default {
methods: {
Expand All @@ -31,9 +31,10 @@ export default {
? markdownit.render(content) + '<p/>'
: `<pre>${escapeHtml(content)}</pre>`

const editor = createEditor({
enableRichEditing: isRichEditor,
})
const editor = isRichEditor
? createRichEditor()
: createPlainEditor()

const json = generateJSON(html, editor.extensionManager.extensions)

const doc = Node.fromJSON(editor.schema, json)
Expand Down
9 changes: 3 additions & 6 deletions src/tests/builders.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@
import { expect } from '@jest/globals';
import { Mark, Node } from '@tiptap/pm/model'
import { builders } from 'prosemirror-test-builder'
import createEditor from '../EditorFactory'
import { createRichEditor } from '../EditorFactory'


export function getBuilders() {
const editor = createEditor({
content: '',
enableRichEditing: true
})
const editor = createRichEditor()
return builders(editor.schema, {
tr: { nodeType: 'tableRow' },
td: { nodeType: 'tableCell' },
Expand Down Expand Up @@ -84,7 +81,7 @@ function createDocumentString(node) {
* @param {Node} subject The editor document
* @param {Node} expected The expected document
* @example
* const editor = createEditor()
* const editor = createRichEditor()
* expectDocument(editor.state.doc, table(
* tr(
* td('foo')
Expand Down
14 changes: 4 additions & 10 deletions src/tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Document from '@tiptap/extension-document'
import Paragraph from '../nodes/Paragraph'
import Text from '@tiptap/extension-text'

import createEditor from '../EditorFactory'
import { createRichEditor } from '../EditorFactory'
import markdownit from '../markdownit'

export function createCustomEditor({ content, extensions }) {
Expand All @@ -32,9 +32,7 @@ export function createCustomEditor({ content, extensions }) {
* @returns {string}
*/
export function markdownThroughEditor(markdown) {
const tiptap = createEditor({
enableRichEditing: true
})
const tiptap = createRichEditor()
tiptap.commands.setContent(markdownit.render(markdown))
const serializer = createMarkdownSerializer(tiptap.schema)
return serializer.serialize(tiptap.state.doc)
Expand All @@ -47,9 +45,7 @@ export function markdownThroughEditor(markdown) {
* @returns {string}
*/
export function markdownThroughEditorHtml(html) {
const tiptap = createEditor({
enableRichEditing: true
})
const tiptap = createRichEditor()
tiptap.commands.setContent(html)
const serializer = createMarkdownSerializer(tiptap.schema)
return serializer.serialize(tiptap.state.doc)
Expand All @@ -62,9 +58,7 @@ export function markdownThroughEditorHtml(html) {
* @returns {string}
*/
export function markdownFromPaste(html) {
const tiptap = createEditor({
enableRichEditing: true
})
const tiptap = createRichEditor()
tiptap.commands.insertContent(html)
const serializer = createMarkdownSerializer(tiptap.schema)
return serializer.serialize(tiptap.state.doc)
Expand Down
6 changes: 2 additions & 4 deletions src/tests/markdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
markdownFromPaste
} from './helpers.js'
import { createMarkdownSerializer } from "../extensions/Markdown";
import createEditor from "../EditorFactory";
import { createRichEditor } from "../EditorFactory";

/*
* This file is for various markdown tests, mainly testing if input and output stays the same.
Expand Down Expand Up @@ -212,9 +212,7 @@ describe('Markdown serializer from html', () => {
describe('Trailing nodes', () => {
test('No extra transaction is added after loading', () => {
const source = "# My heading\n\n* test\n* test2"
const tiptap = createEditor({
enableRichEditing: true,
})
const tiptap = createRichEditor()
tiptap.commands.setContent(markdownit.render(source))

const jsonBefore = tiptap.getJSON()
Expand Down
6 changes: 2 additions & 4 deletions src/tests/nodes/Table.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { createEditor } from '../../EditorFactory'
import { createRichEditor } from '../../EditorFactory'
import { createMarkdownSerializer } from '../../extensions/Markdown'
import { builders } from 'prosemirror-test-builder'

Expand Down Expand Up @@ -75,9 +75,7 @@ describe('Table', () => {
})

function editorWithContent(content) {
const editor = createEditor({
enableRichEditing: true,
})
const editor = createRichEditor()
editor.commands.setContent(content)
return editor
}
Expand Down
6 changes: 2 additions & 4 deletions src/tests/plaintext.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { createEditor, serializePlainText } from './../EditorFactory';
import { createPlainEditor, serializePlainText } from './../EditorFactory';
import spec from "./fixtures/spec"
import xssFuzzVectors from './fixtures/xssFuzzVectors';

Expand All @@ -18,9 +18,7 @@ const escapeHTML = (s) => {

const plaintextThroughEditor = (markdown) => {
const content = '<pre>' + escapeHTML(markdown) + '</pre>'
const tiptap = createEditor({
enableRichEditing: false
})
const tiptap = createPlainEditor()
tiptap.commands.setContent(content)
return serializePlainText(tiptap.state.doc) || 'failed'
}
Expand Down
6 changes: 2 additions & 4 deletions src/tests/tiptap.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import createEditor from '../EditorFactory'
import { createRichEditor } from '../EditorFactory'
import markdownit from '../markdownit'

const renderedHTML = ( markdown ) => {
const editor = createEditor({
enableRichEditing: true
})
const editor = createRichEditor()
editor.commands.setContent(markdownit.render(markdown))
// Remove TrailingNode
return editor.getHTML().replace(/<p><\/p>$/, '')
Expand Down

0 comments on commit a87e233

Please sign in to comment.