js: add 'value' property on editor (#59608)
gitea/godo.js/pipeline/head This commit looks good Details

This commit is contained in:
Corentin Sechet 2024-01-08 18:10:54 +01:00
parent 2394f0184d
commit cc24f8ddf8
2 changed files with 45 additions and 19 deletions

View File

@ -45,6 +45,16 @@ function changeEventPlugin (editor) {
export default class Godo extends window.HTMLElement {
static observedAttributes = ['no-edit']
get value () {
return this.getHTML(this.state.doc.content)
}
set value (newValue) {
this._resetState(newValue)
this.textarea.value = this.value
this.view.updateState(this.state)
}
connectedCallback () {
const initialContent = this.innerHTML
this.innerHTML = ''
@ -53,7 +63,6 @@ export default class Godo extends window.HTMLElement {
this.textarea.hidden = true
this.textarea.style.display = 'none'
this.textarea.setAttribute('name', this.getAttribute('name'))
this.textarea.id = this.id
this.appendChild(this.textarea)
const options = {
@ -82,27 +91,18 @@ export default class Godo extends window.HTMLElement {
this.blocksMenu = menuPlugin(blocks(components, this.schema))
this.menuDialog = document.body.appendChild(dialog)
let pluginsList = [
this.pluginsList = [
history(),
keymap(buildKeymap(components, this.schema, null)),
keymap(baseKeymap),
this.marksMenu,
]
if (options.schema !== 'basic' && !this.readOnly) pluginsList.push(this.blocksMenu)
if (options.instantUpdate) pluginsList.push(changeEventPlugin(this))
if (options.schema !== 'basic' && !this.textarea.readOnly) this.pluginsList.push(this.blocksMenu)
if (options.instantUpdate) this.pluginsList.push(changeEventPlugin(this))
const stateConfig = (content) => {
const w = document.createElement('div')
w.innerHTML = content
return {
schema: this.schema,
doc: DOMParser.fromSchema(this.schema).parse(w),
plugins: pluginsList,
}
}
this.state = EditorState.create(stateConfig(initialContent))
this._resetState(initialContent)
this.textarea.value = this.value
const label = this.id ? document.querySelector(`label[for=${this.id}]`) : undefined
this.view = new EditorView(this.editorWrapper, {
@ -116,18 +116,16 @@ export default class Godo extends window.HTMLElement {
},
})
this.textarea.value = this.getHTML(this.view.state.doc.content)
if (this.textarea.form) {
this.textarea.form.addEventListener('submit', () => {
this.textarea.value = this.getHTML(this.view.state.doc.content)
this.textarea.value = this.value
})
}
const updateEvent = options.updateEvent
if (updateEvent) {
this.textarea.addEventListener(updateEvent, () => {
this.state = EditorState.create(stateConfig(this.textarea.value))
this.view.updateState(this.state)
this.value = this.textarea.value
})
}
}
@ -138,6 +136,16 @@ export default class Godo extends window.HTMLElement {
}
}
_resetState (htmlContent) {
const tempDiv = document.createElement('div')
tempDiv.innerHTML = htmlContent
this.state = EditorState.create({
schema: this.schema,
doc: DOMParser.fromSchema(this.schema).parse(tempDiv),
plugins: this.pluginsList,
})
}
getHTML (from) {
const div = document.createElement('div')
const fragment = DOMSerializer

View File

@ -65,3 +65,21 @@ domTest('no-edit attribute sets ProseMirror contenteditable', async ({appendToDo
expect(editor.view.editable).toBe(true)
})
domTest('value property get and sets HTML content', async ({appendToDom}) => {
const dom = appendToDom(`
<godo-editor>
<invalid-tag>Initial content</invalid-tag>
</godo-editor>
`)
const editor = dom.querySelector('godo-editor')
expect(editor.value).toBe('<p>Initial content</p>')
// check that the content is processed by the schema before being set
editor.value = '<invalid-tag>Modified content</invalid-tag>'
expect(editor.value).toBe('<p>Modified content</p>')
expect(editor.querySelector('textarea').value).toBe('<p>Modified content</p>')
expect(editor.querySelector('.ProseMirror').innerHTML).toBe('<p>Modified content</p>')
})