@prisma-cms/front-editor
Version:
160 lines (117 loc) • 3.67 kB
text/typescript
import { EditorComponentObject, ElementWithReactComponent } from '../../../..'
import HtmlTag from '../../../Tag/HtmlTag'
import CSSTransform from '../../../Tag/HtmlTag/CSSTransform'
/**
* Convert HTML Node to EditorComponentObject JSON
*/
const nodeToEditorComponentObject = (
node: NonNullable<ElementWithReactComponent | Text | ChildNode>,
content?: EditorComponentObject
) => {
if (!content) {
content = {
name: 'HtmlTag',
component: 'HtmlTag',
props: {},
components: [],
}
}
/**
* Если это реакт-нода, то возвращаем его состояние
*/
if (node instanceof Element) {
const { reactComponent, editorComponentObject } = node
if (editorComponentObject) {
return editorComponentObject
}
if (reactComponent && !(reactComponent instanceof HtmlTag)) {
const component = reactComponent.getObjectWithMutations()
return component
}
}
const nodes = node.childNodes
let NodeName = node.nodeName.toLowerCase() as
| keyof JSX.IntrinsicElements
| '#text'
| undefined
if (NodeName === '#text') {
NodeName = undefined
}
if (node.nodeType === Node.TEXT_NODE) {
// https://stackoverflow.com/questions/12754256/removing-invalid-characters-in-javascript
content.props.text = node.textContent?.replace(/\uFFFD/g, '') || ''
} else if (node instanceof Element && node.nodeType === Node.ELEMENT_NODE) {
const attributes = node.attributes
node.getAttributeNames().map((name) => {
// let value = attributes[name].value;
let value: string | Record<string, any> | undefined =
attributes.getNamedItem(name)?.value ?? undefined
switch (name) {
// case "id":
// case "src":
// case "href":
// // case "editable":
// break;
case 'props':
case 'object':
case 'data':
return null
case 'contenteditable':
// name = "contentEditable";
// break;
return null
case 'class':
name = 'className'
break
case 'staticcontext':
name = 'staticContext'
break
case 'style':
try {
// console.log("CSSTransform style", value);
value = value ? CSSTransform(value) : undefined
// console.log("CSSTransform new style", value);
} catch (error) {
console.error(error)
value = undefined
}
break
default:
}
content &&
Object.assign(content.props, {
[name]: value,
})
return null
})
const components: EditorComponentObject['components'] = []
nodes.forEach((node) => {
const component = nodeToEditorComponentObject(node)
component && components.push(component)
})
Object.assign(content, {
components,
})
}
content.props.tag = NodeName
return content
}
/**
* Конвертируем содержимое HTML-ноды в компоненты
*/
export const nodeChildsToEditorComponentObjectComponents = (node: Node) => {
const nodes = node.childNodes
const components: EditorComponentObject['components'] = []
const content: Partial<EditorComponentObject> = {}
nodes.forEach((n) => {
// console.log('makeNewContent n', n)
const component = nodeToEditorComponentObject(n)
// console.log('makeNewContent component', component)
component && components.push(component)
})
Object.assign(content, {
components,
})
return content
}
export default nodeToEditorComponentObject