mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Improve handling of line breaks and style in rich text
This commit is contained in:
parent
66d5c99dcd
commit
1d415ee519
@ -156,7 +156,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#each content as { type, value }, i}
|
{#each content as { type, value }, i}
|
||||||
{#if type === "newline"}
|
{#if type === "newline" && i > 0}
|
||||||
{#each value as _}
|
{#each value as _}
|
||||||
<br />
|
<br />
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -3,81 +3,70 @@
|
|||||||
|
|
||||||
let input = null
|
let input = null
|
||||||
|
|
||||||
// Line breaks are wrapped in divs sometimes
|
const stripStyle = node => {
|
||||||
const isLineBreak = node => {
|
if (node instanceof HTMLElement) {
|
||||||
if (node.tagName === "BR") {
|
if (!node.dataset?.coracle) {
|
||||||
return true
|
node.removeAttribute("class")
|
||||||
}
|
node.removeAttribute("style")
|
||||||
|
node.removeAttribute("color")
|
||||||
if (node.tagName === "DIV" && !node.getAttribute?.("style")) {
|
node.removeAttribute("size")
|
||||||
return true
|
node.removeAttribute("face")
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const isFancy = node => node instanceof HTMLElement && !isLineBreak(node)
|
|
||||||
|
|
||||||
const onInput = e => {
|
|
||||||
const selection = window.getSelection()
|
|
||||||
const {focusNode: node, focusOffset: offset} = selection
|
|
||||||
|
|
||||||
for (const node of input.childNodes) {
|
|
||||||
if (isLineBreak(node)) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove gunk that gets copy/pasted, or bold/italic tags that can be added with hotkeys
|
for (const child of node.childNodes) {
|
||||||
if (node instanceof HTMLElement && !node.dataset.coracle) {
|
// @ts-ignore
|
||||||
const text = document.createTextNode(node.textContent)
|
if (!child.dataset?.coracle) {
|
||||||
|
stripStyle(child)
|
||||||
if (node.tagName === "DIV") {
|
|
||||||
const div = document.createElement("div")
|
|
||||||
|
|
||||||
div.appendChild(text)
|
|
||||||
node.replaceWith(div)
|
|
||||||
} else {
|
|
||||||
node.replaceWith(text)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInput = e => {
|
||||||
|
const selection = window.getSelection()
|
||||||
|
const {focusNode, focusOffset} = selection
|
||||||
|
|
||||||
|
// Remove gunk that gets copy/pasted, or bold/italic tags that can be added with hotkeys
|
||||||
|
for (const child of input.childNodes) {
|
||||||
|
stripStyle(child)
|
||||||
|
}
|
||||||
|
|
||||||
// If we're editing something we've already linked, un-link it
|
// If we're editing something we've already linked, un-link it
|
||||||
if (node !== input && node.parentNode !== input && isFancy(node.parentNode)) {
|
// @ts-ignore
|
||||||
|
if (focusNode.parentNode.dataset?.coracle) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
node.parentNode.replaceWith(node)
|
focusNode.parentNode.replaceWith(focusNode)
|
||||||
selection.collapse(node, offset)
|
selection.collapse(focusNode, focusOffset)
|
||||||
input.normalize()
|
input.normalize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getInput = () => input
|
export const getInput = () => input
|
||||||
|
|
||||||
const parseNode = node => {
|
const parseNode = (node, content = "", annotations = []) => {
|
||||||
let content = ""
|
|
||||||
let annotations = []
|
|
||||||
|
|
||||||
for (const child of node.childNodes) {
|
for (const child of node.childNodes) {
|
||||||
if (child.tagName === "BR") {
|
if (child.tagName === "BR") {
|
||||||
content += "\n"
|
content += "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child.tagName === "DIV" && !child.querySelector("br") && child.childNodes) {
|
if (child.tagName === "DIV" && !content.match(/\n\s*$/)) {
|
||||||
content += "\n"
|
content += "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
if (child.dataset?.coracle) {
|
if (child.dataset?.coracle) {
|
||||||
const {prefix, value} = JSON.parse(child.dataset.coracle)
|
const {prefix, value} = JSON.parse(child.dataset.coracle)
|
||||||
|
|
||||||
content += value
|
content += value
|
||||||
annotations = annotations.concat({prefix, value})
|
annotations.push({prefix, value})
|
||||||
} else if (child instanceof Text) {
|
} else if (child instanceof Text) {
|
||||||
content += child.textContent
|
content += child.textContent
|
||||||
} else {
|
} else {
|
||||||
const info = parseNode(child)
|
;({content, annotations} = parseNode(child, content, annotations))
|
||||||
|
}
|
||||||
|
|
||||||
content += info.content
|
if (child.tagName === "DIV" && !content.match(/\n\s*$/)) {
|
||||||
annotations = annotations.concat(info.annotations)
|
content += "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user