Skip to content

Commit

Permalink
Add a button to edit the raw HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiask committed Mar 12, 2024
1 parent 08c62a4 commit 4dd40a0
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 12 deletions.
1 change: 1 addition & 0 deletions django_prose_editor/static/django_prose_editor/editor.css

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

27 changes: 18 additions & 9 deletions django_prose_editor/static/django_prose_editor/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ esbuild
globalName: "DjangoProseEditor",
plugins: [postcss()],
outfile: "django_prose_editor/static/django_prose_editor/editor.js",
// sourcemap: true,
sourcemap: true,
watch,
})
.then((...args) => {
Expand Down
44 changes: 43 additions & 1 deletion src/commands.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getMarkRange } from "./extendMarkRange.js"
import { trimmedRangeFromSelection } from "./utils.js"
import { getHTML, parseHTML, trimmedRangeFromSelection } from "./utils.js"

const linkDialog = (attrs) => {
return new Promise((resolve) => {
Expand Down Expand Up @@ -80,3 +80,45 @@ export const removeLink = (state, dispatch) => {
}
return false
}

const htmlDialog = (html) => {
return new Promise((resolve) => {
const div = document.createElement("div")
div.innerHTML = `
<dialog>
<form>
<p><textarea name="html" cols="80" rows="30"></textarea></p>
<button type="submit">Speichern</button>
<button value="cancel" formmethod="dialog">Abbrechen</button>
</form>
</dialog>
`
document.body.append(div)
const dialog = div.querySelector("dialog")
const form = div.querySelector("form")
form.html.value = html

dialog.addEventListener("close", () => {
div.remove()
resolve(null)
})
div.querySelector("button[type=submit]").addEventListener("click", (e) => {
e.preventDefault()
div.remove()
resolve(form.html.value)
})
dialog.showModal()
})
}

export const updateHTML = (editorViewInstance) => (state, dispatch) => {
if (dispatch) {
htmlDialog(getHTML(editorViewInstance)).then((html) => {
if (html) {
const doc = parseHTML(editorViewInstance.state.schema, html)
dispatch(state.tr.replaceWith(0, state.tr.doc.content.size, doc))
}
})
}
return true
}
13 changes: 12 additions & 1 deletion src/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { undo, redo } from "prosemirror-history"
import { wrapInList } from "prosemirror-schema-list"
import { Plugin } from "prosemirror-state"

import { addLink, removeLink } from "./commands.js"
import { addLink, removeLink, updateHTML } from "./commands.js"
import { crel } from "./utils.js"

export function menuPlugin(items) {
Expand Down Expand Up @@ -142,8 +142,19 @@ export function historyMenuItems() {
]
}

export function htmlMenuItem(editorViewInstance) {
return [
{
command: updateHTML(editorViewInstance),
dom: menuButtonDOM("html"),
active: () => false,
},
]
}

class MenuView {
constructor(itemGroups, editorView) {
itemGroups.push(htmlMenuItem(editorView))
this.items = itemGroups.flatMap((group) => group)
this.editorView = editorView

Expand Down
8 changes: 8 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ export function parseHTML(schema, html) {
return DOMParser.fromSchema(schema).parse(container)
}

export function getHTML(editorViewInstance) {
const { schema, doc } = editorViewInstance.state
const serializer = DOMSerializer.fromSchema(schema)
const container = crel("article")
container.appendChild(serializer.serializeFragment(doc.content))
return container.innerHTML
}

export const createDebouncedBackWriter = (
schema,
editorViewInstance,
Expand Down

0 comments on commit 4dd40a0

Please sign in to comment.