Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable26] Fixes and additions to editor API #4839

Merged
merged 10 commits into from Oct 10, 2023
4 changes: 2 additions & 2 deletions js/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/editor.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/files-modal.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/files-modal.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions js/text-editors.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-editors.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-files.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-files.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-public.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-public.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-text.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-text.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/text-viewer.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/text-viewer.js.map

Large diffs are not rendered by default.

20 changes: 13 additions & 7 deletions src/components/Editor.vue
Expand Up @@ -42,13 +42,15 @@
<MainContainer v-if="hasEditor">
<!-- Readonly -->
<div v-if="readOnly" class="text-editor--readonly-bar">
<ReadonlyBar>
<Status :document="document"
:dirty="dirty"
:sessions="filteredSessions"
:sync-error="syncError"
:has-connection-issue="hasConnectionIssue" />
</ReadonlyBar>
<slot name="readonlyBar">
<ReadonlyBar>
<Status :document="document"
:dirty="dirty"
:sessions="filteredSessions"
:sync-error="syncError"
:has-connection-issue="hasConnectionIssue" />
</ReadonlyBar>
</slot>
</div>
<!-- Rich Menu -->
<template v-else>
Expand Down Expand Up @@ -649,6 +651,10 @@ export default {
this.emit('delete-image-node', imageUrl)
},

async save() {
await this.$syncService.save()
},

async close() {
if (this.currentSession && this.$syncService) {
try {
Expand Down
23 changes: 16 additions & 7 deletions src/components/Editor/MarkdownContentEditor.vue
Expand Up @@ -20,10 +20,14 @@
-->

<template>
<Wrapper :content-loaded="true">
<Wrapper :content-loaded="true"
:show-outline-outside="showOutlineOutside"
@outline-toggled="outlineToggled">
<MainContainer>
<MenuBar v-if="!readOnly" :autohide="false" />
<ReadonlyBar v-else />
<slot v-else name="readonlyBar">
<ReadonlyBar />
</slot>
<ContentContainer />
</MainContainer>
</Wrapper>
Expand All @@ -33,7 +37,6 @@
import Wrapper from './Wrapper.vue'
import MainContainer from './MainContainer.vue'
import MenuBar from '../Menu/MenuBar.vue'
import { useOutlineActions, useOutlineStateMixin } from './Wrapper.provider.js'
import { Editor } from '@tiptap/core'
/* eslint-disable import/no-named-as-default */
import History from '@tiptap/extension-history'
Expand All @@ -47,7 +50,7 @@ import ContentContainer from './ContentContainer.vue'
export default {
name: 'MarkdownContentEditor',
components: { ContentContainer, ReadonlyBar, MenuBar, MainContainer, Wrapper },
mixins: [useOutlineStateMixin, useOutlineActions, useLinkClickHook],
mixins: [useLinkClickHook],
provide() {
const val = {}

Expand All @@ -72,16 +75,17 @@ export default {
type: Boolean,
default: false,
},
showOutlineOutside: {
type: Boolean,
default: false,
},
},
emits: ['update:content'],

computed: {
htmlContent() {
return this.renderHtml(this.content)
},
showOutline() {
return this.$outlineState.visible
},
},

watch: {
Expand Down Expand Up @@ -137,6 +141,11 @@ export default {
updateContent() {
this.$editor.commands.setContent(this.htmlContent, true)
},

outlineToggled(visible) {
this.$emit('outline-toggled', visible)
this.$parent.$emit('outline-toggled', visible)
},
},
}
</script>
Expand Down
55 changes: 51 additions & 4 deletions src/editor.js
Expand Up @@ -46,6 +46,10 @@ class TextEditorEmbed {
return this
}

#getEditorComponent() {
return this.#vm.$children[0]
}

onLoaded(onLoadedCallback = () => {}) {
this.#vm.$on('ready', () => {
onLoadedCallback()
Expand All @@ -60,6 +64,13 @@ class TextEditorEmbed {
return this
}

onOutlineToggle(onOutlineToggleCallback = () => {}) {
this.#vm.$on('outline-toggled', (visible) => {
onOutlineToggleCallback(visible)
})
return this
}

render(el) {
el.innerHTML = ''
const element = document.createElement('div')
Expand All @@ -77,7 +88,16 @@ class TextEditorEmbed {
// Update reactive prop for MarkdownContentEditor
this.#vm.$set(this.#data, 'content', content)
// Call setContent for file based Editor
this.#vm.$children[0]?.setContent?.(content)
this.#getEditorComponent()?.setContent?.(content)
return this
}

async save() {
return this.#getEditorComponent().save?.()
}

setShowOutline(value) {
this.#vm.$set(this.#data, 'showOutlineOutside', value)
return this
}

Expand All @@ -87,11 +107,11 @@ class TextEditorEmbed {
}

insertAtCursor(content) {
this.#vm.$children[0].$editor.chain().insertContent(content).focus().run()
this.#getEditorComponent().$editor.chain().insertContent(content).focus().run()
}

focus() {
this.#vm.$children[0].$editor.focus()
this.#getEditorComponent().$editor.commands.focus()
}

#registerDebug() {
Expand All @@ -113,12 +133,20 @@ window.OCA.Text.createEditor = async function({
// File mode is enabled by setting the fileId, otherwise content needs to be provided
fileId = undefined,
filePath = undefined,
shareToken = null,

content = '',

readOnly = false,
autofocus = true,
readonlyBar = {
component: null,
props: null,
},

onLoaded = () => {},
onUpdate = ({ markdown }) => {},
onOutlineToggle = (visible) => {},
onLinkClick = undefined,
onFileInsert = undefined,
onMentionSearch = undefined,
Expand All @@ -128,6 +156,7 @@ window.OCA.Text.createEditor = async function({
const { default: Editor } = await import(/* webpackChunkName: "editor" */'./components/Editor.vue')

const data = Vue.observable({
showOutlineOutside: false,
readOnly,
content,
})
Expand All @@ -154,25 +183,43 @@ window.OCA.Text.createEditor = async function({
return data
},
render: h => {
const scopedSlots = readonlyBar?.component
? {
readonlyBar: () => {
return h(readonlyBar.component, {
props: readonlyBar.props,
})
},
}
: {}

return fileId
? h(Editor, {
props: {
fileId,
relativePath: filePath,
shareToken,
mime: 'text/markdown',
active: true,
relativePath: filePath,
autofocus,
showOutlineOutside: data.showOutlineOutside,
},
scopedSlots,
})
: h(MarkdownContentEditor, {
props: {
content: data.content,
readOnly: data.readOnly,
showOutlineOutside: data.showOutlineOutside,
},
scopedSlots,
})
},
store,
})
return new TextEditorEmbed(vm, data)
.onLoaded(onLoaded)
.onUpdate(onUpdate)
.onOutlineToggle(onOutlineToggle)
.render(el)
}