import { nodes } from 'prosemirror-schema-basic'; import type { Node, NodeSpec } from 'prosemirror-model'; import { listItem as _listItem } from 'prosemirror-schema-list'; type Attr = Record; const orderedList: NodeSpec = { attrs: { order: { default: 1, }, listStyleType: { default: '', }, fontsize: { default: '', }, color: { default: '', }, }, content: 'list_item+', group: 'block', parseDOM: [ { tag: 'ol', getAttrs: (dom) => { const order = ((dom as HTMLElement).hasAttribute('start') ? (dom as HTMLElement).getAttribute('start') : 1) || 1; const attr: Attr = { order: +order }; const { listStyleType, fontSize, color } = (dom as HTMLElement).style; if (listStyleType) attr['listStyleType'] = listStyleType; if (fontSize) attr['fontsize'] = fontSize; if (color) attr['color'] = color; return attr; }, }, ], toDOM: (node: Node) => { const { order, listStyleType, fontsize, color } = node.attrs; let style = ''; if (listStyleType) style += `list-style-type: ${listStyleType};`; if (fontsize) style += `font-size: ${fontsize};`; if (color) style += `color: ${color};`; const attr: Attr = { style }; if (order !== 1) attr['start'] = order; return ['ol', attr, 0]; }, }; const bulletList: NodeSpec = { attrs: { listStyleType: { default: '', }, fontsize: { default: '', }, color: { default: '', }, }, content: 'list_item+', group: 'block', parseDOM: [ { tag: 'ul', getAttrs: (dom) => { const attr: Attr = {}; const { listStyleType, fontSize, color } = (dom as HTMLElement).style; if (listStyleType) attr['listStyleType'] = listStyleType; if (fontSize) attr['fontsize'] = fontSize; if (color) attr['color'] = color; return attr; }, }, ], toDOM: (node: Node) => { const { listStyleType, fontsize, color } = node.attrs; let style = ''; if (listStyleType) style += `list-style-type: ${listStyleType};`; if (fontsize) style += `font-size: ${fontsize};`; if (color) style += `color: ${color};`; return ['ul', { style }, 0]; }, }; const listItem: NodeSpec = { ..._listItem, content: 'paragraph block*', group: 'block', }; const paragraph: NodeSpec = { attrs: { align: { default: '', }, indent: { default: 0, }, textIndent: { default: 0, }, }, content: 'inline*', group: 'block', parseDOM: [ { tag: 'p', getAttrs: (dom) => { const { textAlign, textIndent } = (dom as HTMLElement).style; let align = (dom as HTMLElement).getAttribute('align') || textAlign || ''; align = /(left|right|center|justify)/.test(align) ? align : ''; let textIndentLevel = 0; if (textIndent) { if (/em/.test(textIndent)) { textIndentLevel = parseInt(textIndent); } else if (/px/.test(textIndent)) { textIndentLevel = Math.floor(parseInt(textIndent) / 16); if (!textIndentLevel) textIndentLevel = 1; } } const indent = +((dom as HTMLElement).getAttribute('data-indent') || 0); return { align, indent, textIndent: textIndentLevel }; }, }, { tag: 'img', ignore: true, }, { tag: 'pre', skip: true, }, ], toDOM: (node: Node) => { const { align, indent, textIndent } = node.attrs; let style = ''; if (align && align !== 'left') style += `text-align: ${align};`; if (textIndent) style += `text-indent: ${textIndent}em;`; const attr: Attr = { style }; if (indent) attr['data-indent'] = indent; return ['p', attr, 0]; }, }; const { doc, blockquote, text } = nodes; const schemaNodes = { doc, paragraph, blockquote, text, ordered_list: orderedList, bullet_list: bulletList, list_item: listItem, }; export default schemaNodes;