import { v4 as uuidv4 } from 'uuid'; import { toggleMark } from 'prosemirror-commands'; const setBlockType = (nodeType, attrs = {}) => { return (state, dispatch) => { const { tr } = state; const { from, to } = state.selection; state.doc.nodesBetween(from, to, (node, pos) => { if (!node.isTextblock || node.hasMarkup(nodeType, attrs)) return; let applicable = false; if (node.type === nodeType) { applicable = true; } else { const $pos = state.doc.resolve(pos); const index = $pos.index(); applicable = $pos.parent.canReplaceWith(index, index + 1, nodeType); } if (applicable) { tr.setBlockType( from, to, nodeType, Object.assign({}, node.attrs, attrs), ); } }); if (!tr.steps.length) return false; if (dispatch) dispatch(tr.scrollIntoView()); return true; }; }; const markActive = type => state => { const { from, $from, to, empty } = state.selection; const mark = empty ? type.isInSet(state.storedMarks || $from.marks()) : state.doc.rangeHasMark(from, to, type); if (mark) return true; return false; }; const blockActive = (nodeType, attrs = {}) => { return (state, dispatch) => { const { from, to } = state.selection; let isActive = false; state.doc.nodesBetween(from, to, (node, pos) => { if (!node.isTextblock || node.hasMarkup(nodeType, attrs)) return; if (node.type === nodeType) { isActive = true; } }); return isActive; }; }; // // const blockActive = (type, attrs = {}) => state => { // const { $from, to, node } = state.selection; // // if (node) { // return node.hasMarkup(type, attrs); // } // // return to <= $from.end() && $from.parent.hasMarkup(type, attrs); // }; const canInsert = type => state => { const { $from } = state.selection; for (let d = $from.depth; d >= 0; d--) { const index = $from.index(d); if ($from.node(d).canReplaceWith(index, index, type)) { return true; } } return false; }; const createTable = (colsRows, state, dispatch) => { const cells = []; while (colsRows.cols--) { cells.push(state.config.schema.nodes.table_cell.createAndFill()); } const rows = []; while (colsRows.rows--) { rows.push(state.config.schema.nodes.table_row.createAndFill(null, cells)); } const table = state.config.schema.nodes.table.createAndFill(null, rows); dispatch(state.tr.replaceSelectionWith(table)); }; const createLink = (state, dispatch) => { const { selection: { $from, $to }, } = state; dispatch( state.tr .setMeta('addToHistory', false) .addMark( $from.pos, $to.pos, state.schema.marks.link.create({ href: '' }), ), ); }; const isOnSameTextBlock = state => { const { selection: { $from, $to, from, to }, } = state; if (from !== to && $from.parent === $to.parent && $from.parent.isTextblock) { return true; } return false; }; const createComment = (state, dispatch, group, viewid) => { const { selection: { $from, $to }, } = state; let footnote = false; state.doc.nodesBetween($from.pos, $to.pos, (node, from) => { if (node.type.name === 'footnote') { footnote = true; createCommentOnFootnote(state, dispatch, group, viewid); } }); if (footnote) return; toggleMark(state.config.schema.marks.comment, { id: uuidv4(), group, conversation: [], viewid, })(state, dispatch); }; const createCommentOnFootnote = (state, dispatch, group, viewid) => { const { selection: { $from, $to }, } = state; console.log('dldldld', $from.pos, $to.pos); const { content } = $from.parent; console.log('dkdd', content.content); content.content.forEach(contentNode => { console.log(contentNode); const $pos = state.doc.resolve($from.pos); const commentStart = $from.pos - $pos.textOffset; const commentEnd = commentStart + $pos.parent.child($pos.index()).nodeSize; console.log(commentStart, commentEnd); if (contentNode.type.name === 'footnote') { console.log('footnote'); } else { console.log('content'); } }); // dispatch( // state.tr.addMark( // $from.pos, // $to.pos, // state.config.schema.marks.comment.create({ // id: uuidv4(), // group, // conversation: [], // viewid, // }), // ), // ); }; export default { setBlockType, blockActive, canInsert, createComment, createLink, createTable, markActive, isOnSameTextBlock, };