mirror of
https://github.com/standardnotes/app
synced 2026-10-20 21:03:15 -04:00
85 lines
2.7 KiB
TypeScript
85 lines
2.7 KiB
TypeScript
import { $createParagraphNode, $getRoot, $insertNodes, $nodesOfType, LexicalNode } from 'lexical'
|
|
import { $generateNodesFromDOM } from '@lexical/html'
|
|
import { createHeadlessEditor } from '@lexical/headless'
|
|
import { BlockEditorNodes } from '../SuperEditor/Lexical/Nodes/AllNodes'
|
|
import BlocksEditorTheme from '../SuperEditor/Lexical/Theme/Theme'
|
|
import { ClipPayload } from '@standardnotes/clipper/src/types/message'
|
|
import { LinkNode } from '@lexical/link'
|
|
|
|
const AbsoluteLinkRegExp = new RegExp('^(?:[a-z+]+:)?//', 'i')
|
|
|
|
export const getSuperJSONFromClipPayload = async (clipPayload: ClipPayload) => {
|
|
const editor = createHeadlessEditor({
|
|
namespace: 'BlocksEditor',
|
|
theme: BlocksEditorTheme,
|
|
editable: false,
|
|
onError: (error: Error) => console.error(error),
|
|
nodes: [...BlockEditorNodes],
|
|
})
|
|
|
|
const clipURL = new URL(clipPayload.url)
|
|
|
|
await new Promise<void>((resolve) => {
|
|
editor.update(() => {
|
|
const parser = new DOMParser()
|
|
|
|
const clipSourceDOM = parser.parseFromString(
|
|
`<p>Clip source: <a href="${clipPayload.url}">${clipPayload.url}</a></p>`,
|
|
'text/html',
|
|
)
|
|
const clipSourceParagraphNode = $generateNodesFromDOM(editor, clipSourceDOM).concat(
|
|
$createParagraphNode(),
|
|
$createParagraphNode(),
|
|
)
|
|
$getRoot().select()
|
|
$insertNodes(clipSourceParagraphNode)
|
|
|
|
if (typeof clipPayload.content !== 'string') {
|
|
throw new Error('Clip payload content is not a string')
|
|
}
|
|
|
|
const dom = parser.parseFromString(clipPayload.content, 'text/html')
|
|
const generatedNodes = $generateNodesFromDOM(editor, dom)
|
|
const nodesToInsert: LexicalNode[] = []
|
|
generatedNodes.forEach((node) => {
|
|
const type = node.getType()
|
|
|
|
// Wrap text & link nodes with paragraph since they can't
|
|
// be top-level nodes in Super
|
|
if (type === 'text' || type === 'link') {
|
|
const paragraphNode = $createParagraphNode()
|
|
paragraphNode.append(node)
|
|
nodesToInsert.push(paragraphNode)
|
|
return
|
|
} else {
|
|
nodesToInsert.push(node)
|
|
}
|
|
|
|
nodesToInsert.push($createParagraphNode())
|
|
})
|
|
$getRoot().selectEnd()
|
|
$insertNodes(nodesToInsert.concat($createParagraphNode()))
|
|
|
|
resolve()
|
|
})
|
|
})
|
|
|
|
await new Promise<void>((resolve) => {
|
|
editor.update(() => {
|
|
$nodesOfType(LinkNode).forEach((linkNode) => {
|
|
const url = linkNode.getURL()
|
|
const isAbsoluteLink = AbsoluteLinkRegExp.test(url)
|
|
|
|
if (!isAbsoluteLink) {
|
|
const fixedURL = new URL(url, clipURL)
|
|
linkNode.setURL(fixedURL.toString())
|
|
}
|
|
})
|
|
|
|
resolve()
|
|
})
|
|
})
|
|
|
|
return JSON.stringify(editor.getEditorState().toJSON())
|
|
}
|