import { default as default_2 } from 'react'; import { Editor as Editor_2 } from '@tiptap/react'; import { Extension } from '@tiptap/core'; import { JSX } from 'react'; import { Mark } from '@tiptap/core'; import { Node as Node_2 } from '@tiptap/core'; import { NodeViewProps } from '@tiptap/react'; import { ReactNode } from 'react'; export declare const AxiomLike: Extension; export declare const Blocks: Extension; /** * The runtime safety guard. * * Answers: "if the user opens this document and immediately saves without * editing, is the file unchanged (apart from formatting)?" If not, some * construct in the document is outside the subset the editor can faithfully * represent, and enabling WYSIWYG editing would corrupt it. * * Never throws — every failure mode is folded into `{ safe: false }`: * - malformed XML (cleanPtx's parser throws), * - anything unexpected inside TipTap parsing, * - a round-trip result that differs from `formatPretext(input)`. * * Cost note: this performs one cleanPtx pass, one ProseMirror parse, one * serialize, and two formatPretext runs. For typical section-sized files * this is a few milliseconds; callers should still avoid running it more * often than content actually changes (VisualEditor runs it only on * external content updates, which are already debounced upstream). */ export declare function checkRoundTrip(ptx: string): RoundTripReport; export declare function cleanPtx(origXml: string): string; declare interface CursorPosition { pos: () => number; depth: () => number; inTextNode: () => boolean; prevNodeIsText: () => boolean; nextNodeIsText: () => boolean; parentType: () => string; anchor: () => any; nextNodeSize: () => number; prevNodeSize: () => number; } export declare const Definition: Node_2; export declare const Divisions: Extension; declare interface Editor { $pos: (pos: number) => any; state: { selection: { $anchor: { pos: number; depth: number; parent: { firstChild: { isText: boolean; } | null; type: { name: string; }; }; nodeBefore: { isText: boolean; nodeSize: number; } | null; nodeAfter: { type: { name: string; }; nodeSize: number; } | null; }; }; }; } /** * The full, canonical extension list: base nodes/marks plus attribute * preservation. This is what the live editor, the guard, and the tests all * consume. */ export declare const editorExtensions: (Node_2 | Extension)[]; /** * TipTap's JSON document shape. We keep this loose (rather than importing * TipTap's `JSONContent`) because `json2ptx` has its own structural type and * everything here just passes the JSON through opaquely. */ export declare type EditorJson = Record; /** * The set of source tags the editor schema can genuinely represent — every * node and mark, translated to its PreTeXt tag name (tt2ptx maps the * TipTap-native names: bulletList→ul etc.). * * This is what cleanPtx's "known tags" list MUST equal: a tag listed as * known but missing from the schema gets destroyed by the parser instead of * being safely rawptx-wrapped (that bug shipped four times: conclusion, * part, worksheet, pre). KNOWN_TAGS in knownTags.ts stays a static list so * utils.ts needn't import this module (which would be circular — the * extension files import utils.ts), and a test in roundtrip.spec.ts asserts * the two sets are identical, so any drift fails CI. */ export declare const editorSourceTags: ReadonlySet; export declare const Emph: Node_2; export declare const ExampleLike: Extension; export declare const getCursorPos: (editor: Editor) => CursorPosition; export declare const Inline: Extension; /** * Serialize a TipTap/ProseMirror document (as JSON) back to PreTeXt XML. * * @param json The editor document; its top node must be `ptxFragment` * (see editorExtensions.ts). * @param inlineTags Node type names to serialize inline (no injected * newlines). Defaults to DEFAULT_INLINE_TAGS; roundtrip.ts * passes the set derived from the actual editor schema. */ export declare function json2ptx(json: JsonNode, inlineTags?: ReadonlySet): string; declare interface JsonNode { type: string; content?: JsonNode[]; /** * ProseMirror attributes. `ptxAttrs` is special: it is the catch-all * record of the node's original SOURCE attributes, captured by the * PtxSourceAttributes extension (editorExtensions.ts); attrString expands * it back into individual XML attributes. Any other key is an attribute * some TipTap extension declared directly (e.g. codeBlock's `language`). */ attrs?: Record; text?: string; /** * Marks attached to this node. Present on text nodes AND on inline * element nodes (a chip or inside an span carries the em mark). * ProseMirror stores marks in schema-rank order (see Inline.ts for the * rank ordering), which processChildren relies on for its run-merging. * Mark attributes are ignored — none of the PreTeXt marks we model * (em/term/alert/c) carry attributes. */ marks?: Array<{ type: string; }>; } export declare const KeyboardCommands: Extension; /** * The PreTeXt source tags the visual editor can represent. * * CONTRACT: this list must contain exactly the tags backed by the editor * schema (nodes + marks, translated to their PreTeXt tag names). cleanPtx * (utils.ts) passes tags on this list through to the TipTap parser and * wraps everything else in the rawptx escape hatch. A tag listed here * WITHOUT a schema node behind it is the worst kind of bug: cleanPtx skips * the safety wrapper and ProseMirror then silently destroys the element * (this shipped four times: conclusion, part, worksheet, pre). * * The authoritative set is derived from the real schema as * `editorSourceTags` in editorExtensions.ts; this static copy exists only * because utils.ts cannot import editorExtensions.ts (the extension files * import utils.ts — it would be a cycle). A test in roundtrip.spec.ts * asserts the two sets are identical, so any drift fails CI. * * When you add a new element extension: register it in editorExtensions.ts * AND add its tag here (the sync test will remind you), plus a green * fixture in roundtrip.spec.ts proving it round-trips. */ export declare const KNOWN_TAGS: string[]; export declare const MathDisplay: Node_2; export declare const MathEquation: Node_2; export declare const MathInline: Node_2; export declare const MenuBar: (props: MenuBarProps) => JSX.Element; export declare interface MenuBarProps { isChecked: boolean; onChange: () => void; title?: string; onTitleChange?: (value: string) => void; onSaveButton?: () => void; saveButtonLabel?: string; onCancelButton?: () => void; cancelButtonLabel?: string; showPreviewModeToggle?: boolean; feedbackControl?: ReactNode; } /** Result of parsing a PreTeXt string into editor state. */ export declare interface ParsedPtx { /** * The XML declaration (``) from the top of the input, if any. * The editor cannot represent it (it is not an element), so we capture it * here and `serializeEditorJson` re-prepends it. Without this, every save * would strip the declaration — which the round-trip guard would then * (correctly) flag on every ordinary PreTeXt file. */ xmlDecl: string | null; /** * The cleaned XML actually handed to the TipTap parser: declaration * stripped, wrapped in ``, unknown tags wrapped in ``. */ cleanedXml: string; /** The TipTap/ProseMirror document JSON produced by parsing `cleanedXml`. */ json: EditorJson; } /** * Parse a PreTeXt XML string into TipTap editor JSON. * * This is the exact parse the live editor performs (same `cleanPtx` * preprocessing, same extension list), factored out so the guard and the * tests can run it headlessly. VisualEditor.tsx also feeds the returned * `json` straight into `editor.commands.setContent`, which guarantees the * editor holds precisely the state the guard verified — no second parse * that could diverge. * * Throws if the input is not well-formed XML (`cleanPtx`'s parser throws); * `checkRoundTrip` catches that and reports it as an unsafe document. */ export declare function parsePtx(ptx: string): ParsedPtx; export declare const ProofComponent: () => JSX.Element; export declare const PtxBubbleMenu: ({ editor }: { editor: Editor_2; }) => default_2.JSX.Element; export declare const PtxFloatingMenu: ({ editor }: { editor: Editor_2; }) => default_2.JSX.Element; export declare const RawPtx: Node_2; export declare const RawPtxInline: Node_2; /** * Run a full editor round-trip on a PreTeXt string: parse it exactly as the * editor would, then serialize it exactly as a save would. No editing in * between — so for a lossless document the result equals * `formatPretext(input)`. * * Exposed primarily for the test harness; `checkRoundTrip` wraps it with * error handling and the comparison. */ export declare function roundTripPtx(ptx: string): string; /** Verdict returned by {@link checkRoundTrip}. */ export declare interface RoundTripReport { /** * true → the document survives parse+serialize unchanged (modulo * formatting); editing can be enabled with confidence. * false → the round-trip alters the document (or the document could not * be processed at all); the editor must stay read-only. */ safe: boolean; /** * Human-readable explanation when `safe` is false. Shown to the user in * the VisualEditor warning banner. */ reason?: string; /** * `formatPretext(input)` — what an untouched save *should* produce. * Present whenever the comparison ran (i.e. parsing succeeded). */ expected?: string; /** * The actual round-trip output. Diffing `expected` vs `actual` pinpoints * exactly which construct was lost; the test harness prints both on * failure for the same reason. */ actual?: string; /** * The parse result, when parsing succeeded — returned so the caller * (VisualEditor) can reuse it for `setContent` instead of parsing the * document a second time. This both saves work and guarantees the state * loaded into the editor is the state the guard verified. */ parsed?: ParsedPtx; } /** * Serialize TipTap editor JSON back to formatted PreTeXt XML. * * This is the write-back path: `json2ptx` turns the ProseMirror document * into PreTeXt tags, `formatPretext` normalizes the result, and the XML * declaration captured at parse time (if any) is restored on top. * * VisualEditor.tsx calls this from `onUpdate`, and `roundTripPtx` calls it * to complete the parse→serialize loop, so what the guard checks is * byte-for-byte the same function the editor saves with. */ export declare function serializeEditorJson(json: EditorJson, xmlDecl?: string | null): string; export declare const Statement: Node_2; export declare const TheoremLikeComponent: (props: NodeViewProps) => JSX.Element; export declare const TheoremLikeExtension: Extension; export declare const Title: Node_2; export declare const UnknownMark: Mark; export declare const Url: Node_2; export declare const VisualEditor: ({ content, onChange, canEdit, editDisabledReason, }: VisualEditorProps) => JSX.Element; declare interface VisualEditorProps { /** PreTeXt XML string to render and (optionally) edit. */ content: string; /** * Called (debounced 500 ms) with updated PreTeXt XML whenever the user edits * content. Only fired when editing is enabled. */ onChange: (html: string) => void; /** * Whether editing is allowed. Defaults to `true`. * When `false`, the editor stays read-only and the "Edit" toggle is hidden. */ canEdit?: boolean; /** * Message shown when editing is disabled. */ editDisabledReason?: string; } export { }