application/components/common/rich-editor2/util/draft-serializer.js
import {Block, Mark, Node, Value} from 'slate';
import {Set} from 'immutable';
import uuid from 'uuid';
let inList = false;
let parentList;
function makeNodes(block, entityMap) {
const {key, text, entityRanges, inlineStyleRanges} = block;
let nodes = []
let type = 'paragraph';
switch (block.type) {
case 'header-one':
type = 'heading-one';
break;
case 'header-two':
type = 'heading-two';
break;
case 'header-three':
type = 'heading-three';
break;
case 'header-four':
type = 'heading-four';
break;
case 'header-five':
type = 'heading-five';
break;
case 'header-six':
type = 'heading-six';
break;
case 'unordered-list-item':
case 'ordered-list-item':
type = 'list-item';
break;
}
if (!inList && (block.type == 'unordered-list-item' || block.type == 'ordered-list-item')) {
inList = true;
parentList = {
object: 'block',
type: block.type == 'unordered-list-item' ? 'bulleted-list' : 'ordered-list',
data: {},
nodes: []
};
}
if (inList && block.type != 'unordered-list-item' && block.type != 'ordered-list-item') {
inList = false;
nodes = [];
nodes.push(parentList);
parentList = null;
}
let inlines = [];
let blocks = [];
let textPointer = 0;
if (entityRanges.length || inlineStyleRanges.length) {
entityRanges.forEach((range) => {
const {key, length, offset} = range;
const entity = entityMap[key];
if (length && entity.type == 'COPYQUOTE') {
const subStr = text.substring(offset, offset + length);
const cq = makeCqEntity(subStr, entity.data);
inlines[offset] = {
'offset': offset,
'next': offset + length,
'node': cq
};
} else if (length && entity.type == 'LINK') {
const subStr = text.substring(offset, offset + length);
const link = makeLinkEntity(subStr, entity.data);
inlines[offset] = {
'offset': offset,
'next': offset + length,
'node': link
};
} else if (length == 1 && entity.type == 'TOKEN' && entity.data.customType == 'embed') {
const content = entity.data.content;
blocks.push(makeEmbedEntity(content));
} else if (length == 1 && entity.type == 'TOKEN' && entity.data.customType == 'media') {
blocks.push(makeMediaEntity(entity.data));
} else {
console.log('ENTITY', entity);
}
});
const defaultStyles = [
'BOLD', 'ITALIC', 'UNDERLINE',
];
inlineStyleRanges.forEach((inline) => {
const {style, offset, length} = inline;
if (defaultStyles.indexOf(style) !== -1) {
const subStr = text.substring(offset, offset + length);
inlines[offset] = {
'offset': offset,
'next': offset + length,
'node': makeTextLeaf(subStr, [
{
object: 'mark',
type: style.toLowerCase()
}
])
}
}
});
let leaves = [];
inlines.forEach((inline) => {
const subStr = text.substring(textPointer, inline.offset);
leaves.push(makeTextLeaf(subStr));
textPointer = inline.next;
leaves.push(inline.node);
});
if (textPointer < text.length) {
leaves.push(makeTextLeaf(text.substring(textPointer)));
}
if (parentList) {
parentList.nodes.push(makeParagraph(leaves, type));
} else {
nodes.push(makeParagraph(leaves, type));
}
blocks.forEach((block) => {
if (parentList) {
parentList.nodes.push(block);
} else {
nodes.push(block);
}
});
} else {
if (parentList) {
parentList.nodes.push(makeParagraph([makeTextLeaf(text)], type));
} else {
nodes.push(makeParagraph([makeTextLeaf(text)], type));
}
}
return nodes;
}
function makeTextLeaf(text, marks = []) {
return {
object: 'text',
leaves: [
{
object: 'leaf',
text: text,
marks: marks
}
]
};
}
function makeParagraph(leaves, ofType = 'paragraph') {
return {
object: 'block',
type: ofType,
data: {},
nodes: leaves
}
}
function makeLinkEntity(text, data) {
return {
object: 'inline',
type: 'anchor',
data: {
href: data.url,
target: data.target
},
nodes: [makeTextLeaf(text)]
};
}
function makeEmbedEntity(text) {
return {
object: 'block',
type: 'embed',
nodes: [
{
object: 'text',
leaves: [
{
text: text
}
]
}
]
}
}
function makeNoteEntity() {
}
function makeCqEntity(text, data) {
return {
object: 'inline',
type: 'cq',
data: {
'name': data.user,
'date': data.created_at,
'version': data.version
},
nodes: [makeTextLeaf(text)]
};
}
function makeMediaEntity(data) {
let width = '100';
if (data.align == 'left' || data.align == 'right') {
width = '50';
}
return {
object: 'block',
type: 'media',
data: {
alignment: data.align ? data.align : '',
width: width,
link: data.linkTo ? data.linkTo : '',
uuid: data.mediaUuid ? data.mediaUuid : uuid.v4(),
src: data.origSrc
}
};
}
// https://github.com/ianstormtaylor/slate/blob/master/packages/slate-plain-serializer/src/index.js
function deserialize(json, options = {}) {
console.log(json);
let out = {
object: 'value',
document: {
object: 'document',
data: {},
nodes: []
}
};
json.blocks.forEach((block) => {
const nodes = makeNodes(block, json.entityMap);
nodes.map(node => out.document.nodes.push(node));
});
// let out = {
// object: 'value',
// document: {
// object: 'document',
// data: {},
// nodes: [
// {
// object: 'block',
// type: 'paragraph',
// data: {},
// nodes: [
// {
// object: 'text',
// leaves: [
// {
// object: 'leaf',
// text: 'Hello There',
// marks: []
// }
// ]
// }
// ]
// }
// ]
// }
// };
return Value.fromJSON(out);
};
function serialize(node, options = {}) {
return node;
}
export default {
deserialize,
serialize
};