/* * << * Davinci * == * Copyright (C) 2016 - 2017 EDP * == * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * >> */ import escapeHtml from 'escape-html' import { Node, Text } from 'slate' import { jsx } from 'slate-hyperscript' import { ElementTags, TextStyles, TextTags } from './Element' import { TextProperties, ElementTypes } from './Element/constants' const serializeNode = (node: Node) => { if (Text.isText(node)) { let text = escapeHtml(node.text) if (node[TextStyles.Bold]) { text = `${text}` } if (node[TextStyles.Italic]) { text = `${text}` } if (node[TextStyles.Underline]) { text = `${text}` } if (node[TextStyles.StrikeThrough]) { text = `${text}` } if (node[TextStyles.Code]) { text = `${text}` } TextProperties var span = document.createElement('span') if (node[TextProperties.BackgroundColor]) { span.style.backgroundColor = node[TextProperties.BackgroundColor] } if (node[TextProperties.Color]) { span.style.color = node[TextProperties.Color] } if (node[TextProperties.FontFamily]) { span.style.fontFamily = node[TextProperties.FontFamily] } if (node[TextProperties.FontSize]) { span.style.fontSize = `${node[TextProperties.FontSize]}px` } span.innerHTML = text text = span.outerHTML return text } const children = node.children.map((n) => serializeNode(n)).join('') switch (node.type) { case ElementTypes.Paragraph: return `

${children}

` case ElementTypes.BlockQuote: return `
${children}
` case ElementTypes.Code: return `
${children}
` case ElementTypes.BulletedList: return `` case ElementTypes.NumberedList: return `
    ${children}
` case ElementTypes.ListItem: return `
  • ${children}
  • ` case ElementTypes.HeadingOne: return `

    ${children}

    ` case ElementTypes.HeadingTwo: return `

    ${children}

    ` case ElementTypes.HeadingThree: return `

    ${children}

    ` case ElementTypes.HeadingFour: return `

    ${children}

    ` case ElementTypes.HeadingFive: return `
    ${children}
    ` case ElementTypes.HeadingSix: return `
    ${children}
    ` case ElementTypes.Link: return `${children}` case ElementTypes.Image: return `
    ${children}
    ` case ElementTypes.Table: return `${children}
    ` case ElementTypes.TableRow: return `${children}` case ElementTypes.TableCell: return `${children}` case ElementTypes.Marquee: throw new Error( 'Marquee Element can not be serialized as simple html tag!' ) default: return children } } export const serialize = (nodes: Node[]) => { const html = nodes.map((n) => serializeNode(n)).join('') return html } export const deserialize = (el: HTMLElement): Node[] => { if (el.nodeType === 3) { const textElement = [{ text: el.textContent }] if (el.parentElement.nodeName === 'BODY') { return [jsx('element', ElementTags['P'](null), textElement)] } return textElement } if (el.nodeType !== 1) { return null } if (el.nodeName === 'BR') { return [{ text: '\n' }] } const { nodeName, childNodes } = el let parent: HTMLElement | ChildNode = el if ( nodeName === 'PRE' && childNodes[0] && childNodes[0].nodeName === 'CODE' ) { parent = el.childNodes[0] } const children: any[] = Array.from(parent.childNodes).map(deserialize).flat() if (el.nodeName === 'BODY') { return jsx('fragment', {}, children) } if (ElementTags[nodeName]) { const attrs = ElementTags[nodeName](el) ALIGN_CLASS_SUFFIXES.some((suffix) => { if (el.classList.contains(`${ALIGN_CLASS_PREFIX}${suffix}`)) { attrs.textAlign = suffix return true } }) return [jsx('element', attrs, children.length ? children : [{ text: '' }])] } if (TextTags[nodeName]) { const attrs = TextTags[nodeName]() if (el.style) { const { fontSize, color, backgroundColor } = el.style if (fontSize) { attrs.fontSize = +fontSize.substring(0, fontSize.length - 2) } if (color) { attrs.color = color } if (backgroundColor) { attrs.backgroundColor = backgroundColor } } return children.map((child) => jsx('text', attrs, child)) } return children } const ALIGN_CLASS_PREFIX = 'ql-align-' const ALIGN_CLASS_SUFFIXES = ['left', 'center', 'right']