import type {Editor} from "../../types.js"
// General Fallback handler for paste
export class GeneralPasteHandler {
editor: Editor
htmlDoc: HTMLElement
pmType: string
footnoteMarkers: HTMLElement[]
footnotes: HTMLElement[]
dom: HTMLElement
inHTML: string
outHTML: string
constructor(editor: Editor, htmlDoc: HTMLElement, pmType: string) {
this.editor = editor
this.htmlDoc = htmlDoc
this.pmType = pmType
this.footnoteMarkers = []
this.footnotes = []
this.dom = document.createElement("body")
this.inHTML = ""
this.outHTML = ""
}
// Iterate over each node in the body of the pasted content.
getOutput(): string {
this.dom = this.htmlDoc.getElementsByTagName("body")[0]
this.inHTML = this.dom.innerHTML
this.iterateNode(this.dom)
this.cleanDOM()
this.convertFootnotes()
this.outHTML = this.dom.innerHTML
return this.outHTML
}
// Remove unused content
cleanDOM(): void {}
// Iterate over pasted nodes and their children
iterateNode(node: ChildNode): boolean {
if ((node as HTMLElement).tagName === "P" && !node.firstChild) {
node.parentNode?.removeChild(node)
return true
} else if (node.nodeType === 8) {
// comment node
node.parentNode?.removeChild(node)
return true
} else if (node.nodeType === 1) {
// element node
let childNode = node.firstChild
while (childNode) {
const nextChildNode = childNode.nextSibling
this.iterateNode(childNode)
childNode = nextChildNode
}
node = this.convertNode(node as HTMLElement)
}
return true
}
// Convert an existing node to a different node, if needed.
convertNode(node: HTMLElement): HTMLElement {
if (
node.tagName === "TABLE" &&
node.firstElementChild?.tagName !== "CAPTION"
) {
const caption = document.createElement("caption")
caption.innerHTML = ""
node.insertBefore(caption, node.firstChild)
}
return node
}
// Move footnotes into their markers and turn footnote markers into the
// required format.
convertFootnotes(): void {
this.footnoteMarkers.forEach((fnM, index) => {
const footnote = this.footnotes[index]
const newFnM = document.createElement("span")
newFnM.classList.add("footnote-marker")
const footnoteContents = footnote.innerHTML.replace(/\s+/g, " ")
// Remove linebreaks in string (not
)
// Turn multiple white spaces into single space
newFnM.dataset.footnote = footnoteContents
fnM.parentNode?.replaceChild(newFnM, fnM)
})
// Remove all footnotes from document. Some footnotes may have several
// markers, so only remove each footnote once.
this.footnotes.forEach(fn => {
if (fn.parentNode) {
fn.parentNode.removeChild(fn)
}
})
}
}