import Document from '@tiptap/extension-document'; import Paragraph from '@tiptap/extension-paragraph'; import Text from '@tiptap/extension-text'; import Bold from '@tiptap/extension-bold'; import Italic from '@tiptap/extension-italic'; import { TextEffects, UnderlineStyled, StrikeStyled } from './extensions/textEffects'; import Subscript from '@tiptap/extension-subscript'; import Superscript from '@tiptap/extension-superscript'; import Highlight from '@tiptap/extension-highlight'; import { Link } from './extensions/link'; import { Bookmark } from './extensions/bookmark'; import { Comment } from './extensions/comment'; import { TextStyle, FontFamily, FontSize } from '@tiptap/extension-text-style'; import { FontWeight } from './extensions/fontWeight'; import { FontColor } from './extensions/fontColor'; import HardBreak from '@tiptap/extension-hard-break'; import Heading, { type Level } from '@tiptap/extension-heading'; import { BulletList } from './extensions/bulletList'; import { OrderedList } from './extensions/orderedList'; import ListItem from '@tiptap/extension-list-item'; import { ListMarker } from './extensions/listMarker'; import { ListStyle } from './extensions/listStyle'; import { Table, TableHeader, TableCell } from '@tiptap/extension-table'; import { ResizableTableRow } from './extensions/tableRow'; import History from '@tiptap/extension-history'; import Placeholder from '@tiptap/extension-placeholder'; import TextAlign from '@tiptap/extension-text-align'; import { PageBreaks } from './extensions/pageBreaks'; import { LineHeight } from './extensions/lineHeight'; import { ParagraphSpacing } from './extensions/paragraphSpacing'; import { ParagraphBox } from './extensions/paragraphBox'; import { BlockFontSize } from './extensions/blockFontSize'; import { ParagraphStyle } from './extensions/paragraphStyle'; import { CharacterStyle } from './extensions/characterStyle'; import { PageBreak } from './extensions/pageBreak'; import { TextDirection } from './extensions/textDirection'; import { Indent } from './extensions/indent'; import { TabStops } from './extensions/tabStops'; import { FormattingMarks } from './extensions/formattingMarks'; import { SpellCheck } from './extensions/spellCheck'; import { SearchReplace } from './extensions/searchReplace'; import { TableView } from './extensions/tableView'; import { TableColumnResize } from './extensions/tableColumnResize'; import { TableRowResize } from './extensions/tableRowResize'; import { TableSplit } from './extensions/tableSplit'; import { TableFormula } from './extensions/tableFormula'; import { TableSort } from './extensions/tableSort'; import { TableCellBackground } from './extensions/tableCellBackground'; import { TableCellAlign } from './extensions/tableCellAlign'; import { TableCellBorders } from './extensions/tableCellBorders'; import { TableCellPadding } from './extensions/tableCellPadding'; import { TableHeaderRow } from './extensions/tableHeaderRow'; import { TableStyle } from './extensions/tableStyle'; import { TrailingNode } from './extensions/trailingNode'; import { Image } from './extensions/image'; import { DateTimeField } from './extensions/dateTimeField'; import { PlaceholderField } from './extensions/placeholderField'; import { SequenceField } from './extensions/caption'; import { IndexEntry } from './extensions/indexEntry'; import { BibliographyEntry } from './extensions/bibliographyEntry'; import { CrossReference } from './extensions/crossReference'; import { Ruby } from './extensions/ruby'; import { Formula } from './extensions/formula'; import { TextBox } from './extensions/textBox'; import { Columns } from './extensions/columns'; import { ColumnsFlow } from './extensions/columnsFlow'; import { TableOfContents } from './extensions/tableOfContents'; import { Outline } from './extensions/outline'; import { Note, NoteRef, NoteSection, Notes } from './extensions/notes'; import { Shortcuts } from './extensions/shortcuts'; import { AutoCorrect } from './extensions/autoCorrect'; import { WordCompletion } from './extensions/wordCompletion'; import { AutoText } from './extensions/autoText'; import { HEADING_LEVELS, MAX_HEADING_LEVEL } from '../export/odt'; import { styleSheet } from '../styles/sheet.svelte'; import { noteSettings } from '../storage/notes.svelte'; import { recordChanges } from '../storage/trackChanges.svelte'; import { loadDocProperties } from '../storage/docProperties'; import { Insertion, Deletion, TrackChanges } from './extensions/trackChanges'; export const extensions = [ // textBox and columns have their own groups so only the document (not // cells/lists/boxes) admits them; the note section is last or nowhere. // Spelled as an alternation, not `… + noteSection?`: with the trailing optional the // match state after the first block offers noteSection first, and that is the type // TipTap's clearNodes converts a block into (`contentMatchAt(i).defaultType`). Document.extend({ content: '((block | textBox | columns)+ noteSection) | (block | textBox | columns)+', }), Paragraph, Text, Bold, Italic, UnderlineStyled, StrikeStyled, Link, // Named range of text, the target of a cross-reference or an internal link; // round-trips to ODF text:bookmark-start/-end and DOCX w:bookmarkStart/End. Bookmark, // An annotation on a range of text; round-trips to ODF office:annotation and DOCX // w:commentRangeStart/-End + word/comments.xml. Comment, Subscript, Superscript, TextStyle, FontFamily, FontSize, FontWeight, FontColor, // Letter case, raised/lowered runs and the line styles of underline/strikethrough. TextEffects, // multicolor stores the chosen color on the `highlight` mark's `color` attr; // odf-kit exports that natively to fo:background-color. See export/odt.ts // applyRuns for the custom-attr-paragraph export path. Highlight.configure({ multicolor: true }), // Shift+Enter line breaks; round-trips to ODF (export/odt.ts // replaceHardBreaks, import/odt.ts). HardBreak, // Inline, as-character image; round-trips to ODF / // (export/odt.ts replaceImages/applyImages, import/odt.ts). Image, // Inline date/time field (fixed or auto-updating); round-trips to ODF // / and DOCX DATE/TIME fields. DateTimeField, // A template placeholder the user clicks and types over; round-trips to ODF // and a tagged DOCX content control. PlaceholderField, // A caption's running number, one counter per category in document order. Round-trips // to an ODF and a DOCX SEQ field. SequenceField, // A place marked for the alphabetical index. Round-trips to ODF // and a Word XE field. IndexEntry, // A citation carrying its whole source record. Round-trips to ODF // and a Word CITATION field over a custom-XML source. BibliographyEntry, // Inline reference to a bookmark, showing its text or its page; kept live by its // node view. Round-trips to ODF and DOCX REF/PAGEREF fields. CrossReference, // A reading printed over its base text; round-trips to ODF and DOCX w:ruby. Ruby, // Mathematical formula; stores LaTeX, renders native MathML, round-trips to an ODF // embedded formula object and DOCX OMML. See docs/architecture/formulas.md. Formula, // Block-level text box / basic shape with editable content; round-trips to ODF // draw:frame/draw:text-box + draw:custom-shape and DOCX wps:wsp/wps:txbx. TextBox, // Multi-column (newspaper) section; round-trips to ODF + // style:columns and DOCX continuous sections with w:cols. ColumnsFlow splits a // section into per-page fragments so the text flows across page breaks. Columns, ColumnsFlow, // Generated table of contents from headings; round-trips to ODF // (export/odt.ts, import/odt.ts) and a DOCX TOC field. TableOfContents, // The document's chapters for the Navigator pane, plus LibreOffice's move and // promote/demote of a whole chapter. Outline.configure({ maxLevel: MAX_HEADING_LEVEL }), // Footnotes and endnotes: the anchor rides the text, the note text lives in the one // noteSection at the document end. pageBreaks.ts lifts a footnote to the foot of its // anchor's page. Round-trips to ODF and DOCX word/footnotes.xml. NoteRef, Note, NoteSection, Notes.configure({ settings: () => noteSettings() }), LineHeight, ParagraphSpacing, // Paragraph background ("colored field") + borders ("colored rule line"); round-trips // to ODF fo:background-color/fo:border-* and DOCX w:shd/w:pBdr. ParagraphBox, // Paragraph-mark font size: sizes empty lines (and text typed into them). BlockFontSize, // Named paragraph style (LibreOffice style:style / Word w:pStyle); the document // stylesheet in Editor.svelte renders it, direct formatting still wins. ParagraphStyle.configure({ sheet: styleSheet }), // Named character style on a run (LibreOffice style:family="text" / Word w:rStyle). CharacterStyle, PageBreak, // Per-block base direction, overriding the page's (storage/writingMode.ts). TextDirection, Indent, TabStops, // Its own Mod-Alt-N is dropped: a keymap plugin runs ahead of every plugin from // addProseMirrorPlugins, so it would beat the code-based binding in shortcuts.ts // and set the level without the heading's named style. Heading.extend({ addKeyboardShortcuts: () => ({}) }).configure({ levels: HEADING_LEVELS as Level[] }), BulletList, OrderedList, ListItem, // Bullet/number formatting: it follows the item's first text portion, as in // LibreOffice (the sheet resolves a character style on that portion). ListMarker.configure({ sheet: styleSheet }), // Named list style on the outermost list (LibreOffice Listenformatvorlage / Word // numbering style); also owns the effective-marker walk both list types render by. ListStyle.configure({ sheet: styleSheet }), // resizable:false keeps TipTap's columnResizing plugin off; TableView, the two // resize plugins, and ResizableTableRow supply the drag handling instead. Table // (unlike TableKit) doesn't auto-add children, so ResizableTableRow is listed here. Table.configure({ resizable: false, View: TableView }), ResizableTableRow, TableHeader, TableCell, TableColumnResize, TableRowResize, // "Split Cells…" (N×M); merge uses extension-table's built-in mergeCells. TableSplit, TableFormula, TableSort, // Cell shading: backgroundColor attr on tableCell/tableHeader (→ fo:background-color). TableCellBackground, // Cell content set against the middle/bottom of its box (→ style:vertical-align). TableCellAlign, // Border presets: per-side border attrs on cells (→ fo:border-*). TableCellBorders, // The table's cell margins (→ w:tblCellMar / fo:padding on the cell style). TableCellPadding, // "Header row" styling preset: bold + light shading on the first row (toggle). TableHeaderRow, // Named table style (Word table style / LibreOffice AutoFormat): paints the table's // conditional regions into cell attrs and re-bands on structural changes. TableStyle.configure({ styles: () => styleSheet().table }), // Guarantees a paragraph after a trailing table so the cursor isn't trapped // and the user can keep writing below a table at the document's end. TrailingNode, History, Placeholder.configure({ placeholder: 'Start typing…' }), // No defaultAlignment: it would put textAlign:'left' on every block, and that inline // style beats the paragraph style's alignment. Unset = follow the style; an explicit // 'left' stays direct formatting that overrides it, as in Word/LibreOffice. TextAlign.configure({ types: ['paragraph', 'heading'], alignments: ['left', 'center', 'right', 'justify'], }), PageBreaks, FormattingMarks, SpellCheck, // Last of the typing extensions: its handleTextInput runs after every input rule. // Recorded revisions: an insertion is marked text, a deletion is text kept and // marked. Round-trips to ODF and DOCX w:ins/w:del. Insertion, Deletion, TrackChanges.configure({ recording: recordChanges, author: () => loadDocProperties().author.trim() }), AutoCorrect, WordCompletion, // Named blocks of text kept beside the documents; F3 expands a typed shortcut. AutoText, SearchReplace.configure({ sheet: styleSheet }), // Word/LibreOffice key bindings that aren't TipTap defaults; body:true adds the // ones the header/footer schema has no commands for (headings, line spacing, fields). Shortcuts.configure({ body: true }), ];