UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

107 lines (90 loc) 2.81 kB
import { Fragment, Node as PMNode, Schema, } from '../../prosemirror'; import { Serializer } from '../serializer'; const HARDBREAK_NODE_TYPE = 'hardBreak'; const IGNORE_NODE_TYPES = [ 'bulletList', 'orderedList', 'heading', 'rule', 'panel', 'table', ]; interface Node { content?: Node[]; text?: string; } const getText = (node: PMNode): string => { return node.type.name === HARDBREAK_NODE_TYPE ? '\n' : node.attrs.text || node.attrs.shortName || node.text; }; const reduceTree = (fragment: Fragment): Node[] => { let fragmentContainsInlineNodes = false; let textChunks = ''; let childrenChunks: Node[] = []; let prevNodeType: string; fragment.forEach(node => { fragmentContainsInlineNodes = fragmentContainsInlineNodes || node.isInline; if (fragmentContainsInlineNodes) { if (prevNodeType === HARDBREAK_NODE_TYPE && node.type.name === HARDBREAK_NODE_TYPE) { // pass: ignore multiple hardBreaks } else { textChunks += getText(node); } } else { if (IGNORE_NODE_TYPES.indexOf(node.type.name) !== -1) { // pass: ignore these nodes } else if (!node.childCount) { childrenChunks.push({ text: getText(node) } as Node); } else if (node.type.name === 'mediaGroup') { // count children which are media files // ignore card links let childMediaFilesCount = 0; node.content.forEach(childNode => { if (childNode.attrs.type === 'file') { childMediaFilesCount += 1; } }); if (childMediaFilesCount) { const postfix = childMediaFilesCount > 1 ? 'Files' : 'File'; childrenChunks.push({ text: `📎 ${childMediaFilesCount} ${postfix}` } as Node); } } else if (node.type.name === 'blockquote') { childrenChunks.push({ content: reduceTree(node.content), text: '> ', }); } else { childrenChunks.push({ content: reduceTree(node.content) }); } } prevNodeType = node.type.name; }); return fragmentContainsInlineNodes ? [{ text: textChunks } as Node] : childrenChunks; }; const serializeTree = (node: Node): string => { if (node.content) { return node.content!.map(childNode => { return (node.text || '') + serializeTree(childNode); }).join('\n'); } return node.text!; }; const serializeFragment = (fragment: Fragment): string => { const tree: Node = { content: reduceTree(fragment) }; return serializeTree(tree); }; export default class TextSerializer implements Serializer<string> { serializeFragment(fragment: Fragment): string { return serializeFragment(fragment); } static fromSchema(schema: Schema<any, any>): TextSerializer { return new TextSerializer(); } }