Signal drop!
Relay (operand.online) is unreachable.
Usually, a dropped signal means an upgrade is happening. Hold on!
Sorry, no connección.
Hang in there while we get back on track
gram: docs
> ./packages/core/src/prosemirror/commands/sectionBreak.ts
/**
* Section Break Commands
* @packageDocumentation
* @public
*/
import type { Command } from 'prosemirror-state';
import { TextSelection } from 'prosemirror-state';
type InsertableSectionBreak = 'nextPage' | 'continuous';
/**
* Insert a section break at the current cursor position.
*
* In OOXML a section break is the `sectPr` carried by the *last* paragraph of a
* section. So we split the current paragraph at the cursor, mark the first half
* with `sectionBreakType` (it becomes the section end), and leave the cursor in
* the second half (the first paragraph of the new section). Content after the
* cursor therefore flows into the new section — onto a new page for `nextPage`,
* or in place for `continuous`.
*/
function insertSectionBreakAtCursor(breakType: InsertableSectionBreak): Command {
return (state, dispatch) => {
const { schema } = state;
const paragraphType = schema.nodes.paragraph;
if (!paragraphType) return false;
const { $from } = state.selection;
// Section breaks only belong on top-level body paragraphs. Inside a table
// cell or block SDT a `w:sectPr` is invalid OOXML, so refuse to act there
// (the menu item becomes a no-op rather than corrupting the document).
const isTopLevel = $from.parent.isTextblock
? state.doc.resolve($from.before()).depth === 0
: $from.depth === 0;
if (!isTopLevel) return false;
if (dispatch) {
const tr = state.tr;
let cursorPos: number;
if ($from.parent.isTextblock) {
// Position of the paragraph node the cursor sits in. Unaffected by the
// split below, since the split happens at a later position.
const paraPos = $from.before();
tr.split($from.pos);
const firstPara = tr.doc.nodeAt(paraPos);
if (firstPara) {
tr.setNodeMarkup(paraPos, undefined, {
...firstPara.attrs,
sectionBreakType: breakType,
});
}
// The split position maps to the start of the second paragraph's
// content (the first paragraph of the new section) — put the cursor there.
cursorPos = tr.mapping.map($from.pos);
} else {
// Not in a textblock — insert a section-ending empty paragraph here.
const pos = $from.pos;
tr.insert(pos, paragraphType.create({ sectionBreakType: breakType }));
cursorPos = tr.mapping.map($from.pos);
}
tr.setSelection(TextSelection.create(tr.doc, cursorPos));
dispatch(tr.scrollIntoView());
}
return true;
};
}
/**
* Insert a "next page" section break at the cursor — starts a new section on a
* new page.
*/
export const insertSectionBreakNextPage: Command = insertSectionBreakAtCursor('nextPage');
/**
* Insert a "continuous" section break at the cursor — starts a new section on
* the same page.
*/
export const insertSectionBreakContinuous: Command = insertSectionBreakAtCursor('continuous');