@sobree/core 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/doc/types.d.ts +40 -30
- package/dist/docx/shared/units.d.ts +3 -2
- package/dist/docx/shared/xml.d.ts +12 -0
- package/dist/editor/commands.d.ts +14 -0
- package/dist/editor/context.d.ts +71 -0
- package/dist/editor/dom.d.ts +21 -0
- package/dist/editor/events.d.ts +29 -0
- package/dist/editor/index.d.ts +85 -663
- package/dist/editor/internal/mutations.d.ts +1 -1
- package/dist/editor/ops/blocks.d.ts +42 -0
- package/dist/editor/ops/comments.d.ts +12 -0
- package/dist/editor/ops/parts.d.ts +71 -0
- package/dist/editor/ops/review.d.ts +67 -0
- package/dist/editor/ops/runs.d.ts +83 -0
- package/dist/editor/ops/trackedInput.d.ts +44 -0
- package/dist/editor/query.d.ts +22 -0
- package/dist/editor/revisionRuns.d.ts +56 -0
- package/dist/editor/selection.d.ts +34 -0
- package/dist/editor/types.d.ts +292 -0
- package/dist/editor/view/docRenderer/anchorPosition.d.ts +18 -0
- package/dist/editor/view/docRenderer/sectionFlow.d.ts +23 -0
- package/dist/editor/view/docRenderer/table.d.ts +11 -2
- package/dist/index.css +1 -1
- package/dist/index.js +6099 -6020
- package/dist/index.js.map +1 -1
- package/dist/paperStack/paginationV2/apply.d.ts +18 -0
- package/dist/paperStack/paginationV2/engine.d.ts +7 -0
- package/dist/paperStack/paginationV2/measure.d.ts +9 -0
- package/dist/paperStack/paginationV2/types.d.ts +273 -0
- package/dist/paperStack/paper.d.ts +31 -9
- package/dist/paperStack/paperStack.d.ts +13 -1
- package/dist/paperStack/paperZone.d.ts +35 -0
- package/dist/plugins/marks.d.ts +4 -4
- package/dist/ydoc/schema.d.ts +5 -0
- package/package.json +1 -1
- package/dist/__vite-browser-external-DYxpcVy9.js +0 -5
- package/dist/__vite-browser-external-DYxpcVy9.js.map +0 -1
package/dist/doc/types.d.ts
CHANGED
|
@@ -30,6 +30,15 @@ export interface SobreeDocument {
|
|
|
30
30
|
* emits each body to its own OOXML part at export time.
|
|
31
31
|
*/
|
|
32
32
|
headerFooterBodies: Record<string, Block[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Floating objects that live inside a header/footer part, keyed by the
|
|
35
|
+
* SAME `HeaderFooterRef.partId` as `headerFooterBodies`. A header part
|
|
36
|
+
* is a self-contained sub-document: its flow blocks live in
|
|
37
|
+
* `headerFooterBodies[partId]`, its anchored frames here. The renderer
|
|
38
|
+
* paints these into a per-zone overlay exactly like body `anchoredFrames`.
|
|
39
|
+
* Empty/absent for the common header-without-floats case.
|
|
40
|
+
*/
|
|
41
|
+
headerFooterFrames?: Record<string, AnchoredFrame[]>;
|
|
33
42
|
/** Named styles (Heading1, Quote, Body Text, …) defined at the doc level. */
|
|
34
43
|
styles: NamedStyle[];
|
|
35
44
|
/** List/numbering definitions referenced by `Paragraph.properties.numbering`. */
|
|
@@ -271,6 +280,31 @@ export interface SectionBreak {
|
|
|
271
280
|
* **Status**: type declared (Phase 1.0). Importer does not yet emit
|
|
272
281
|
* this; renderer treats it as a no-op. Wiring lands in Phase 1.1-1.2.
|
|
273
282
|
*/
|
|
283
|
+
/** One textbox shape inside an inline-frame group: its intra-group
|
|
284
|
+
* position + size and recursive body, plus optional chrome (fill /
|
|
285
|
+
* border / text insets) and vertical text anchor. */
|
|
286
|
+
export interface InlineFrameTextbox {
|
|
287
|
+
offsetEmu: {
|
|
288
|
+
xEmu: number;
|
|
289
|
+
yEmu: number;
|
|
290
|
+
};
|
|
291
|
+
sizeEmu: {
|
|
292
|
+
wEmu: number;
|
|
293
|
+
hEmu: number;
|
|
294
|
+
};
|
|
295
|
+
body: Block[];
|
|
296
|
+
fill?: string;
|
|
297
|
+
border?: FrameBorder;
|
|
298
|
+
/** `<wps:bodyPr>` text insets (lIns/tIns/rIns/bIns) → CSS padding. */
|
|
299
|
+
padding?: {
|
|
300
|
+
topEmu: number;
|
|
301
|
+
rightEmu: number;
|
|
302
|
+
bottomEmu: number;
|
|
303
|
+
leftEmu: number;
|
|
304
|
+
};
|
|
305
|
+
/** Vertical text anchor from `<wps:bodyPr anchor>`; defaults to "top". */
|
|
306
|
+
vAlign?: "top" | "center" | "bottom";
|
|
307
|
+
}
|
|
274
308
|
export interface InlineFrame {
|
|
275
309
|
kind: "inline_frame";
|
|
276
310
|
/** From the containing `<w:p>`'s `<w:pPr>`. The paginator emits a
|
|
@@ -304,36 +338,12 @@ export interface InlineFrame {
|
|
|
304
338
|
wEmu: number;
|
|
305
339
|
hEmu: number;
|
|
306
340
|
};
|
|
307
|
-
/** The
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
xEmu: number;
|
|
314
|
-
yEmu: number;
|
|
315
|
-
};
|
|
316
|
-
sizeEmu: {
|
|
317
|
-
wEmu: number;
|
|
318
|
-
hEmu: number;
|
|
319
|
-
};
|
|
320
|
-
body: Block[];
|
|
321
|
-
fill?: string;
|
|
322
|
-
border?: FrameBorder;
|
|
323
|
-
/** `<wps:bodyPr>` text insets (lIns/tIns/rIns/bIns). The renderer
|
|
324
|
-
* paints these as the region's CSS padding. */
|
|
325
|
-
padding?: {
|
|
326
|
-
topEmu: number;
|
|
327
|
-
rightEmu: number;
|
|
328
|
-
bottomEmu: number;
|
|
329
|
-
leftEmu: number;
|
|
330
|
-
};
|
|
331
|
-
/** Vertical text anchor from `<wps:bodyPr anchor>`. Word centers a
|
|
332
|
-
* single heading line by sizing a short textbox and centering its
|
|
333
|
-
* text; this carries that intent into the renderer's flex column.
|
|
334
|
-
* Defaults to "top" when the attribute is absent. */
|
|
335
|
-
vAlign?: "top" | "center" | "bottom";
|
|
336
|
-
};
|
|
341
|
+
/** The group's textbox SHAPES, in document (child) order. Most groups
|
|
342
|
+
* have one (a section "pill" heading: a centred line over a background
|
|
343
|
+
* picture), but a "Project: X" entry has two — a title textbox and a
|
|
344
|
+
* details textbox — and the renderer must show BOTH. Empty when the
|
|
345
|
+
* group carries only pictures / shapes (no textbox content). */
|
|
346
|
+
textboxes: InlineFrameTextbox[];
|
|
337
347
|
/** Decorative pictures inside the group. Each carries its own
|
|
338
348
|
* intra-group position. The renderer paints them as
|
|
339
349
|
* absolute-positioned `<img>` children of the frame wrapper,
|
|
@@ -28,8 +28,9 @@ export declare const twipsToPt: (t: number) => number;
|
|
|
28
28
|
/** pt → twips. */
|
|
29
29
|
export declare const ptToTwips: (pt: number) => number;
|
|
30
30
|
/**
|
|
31
|
-
* `w:line`
|
|
32
|
-
*
|
|
31
|
+
* `w:line` value (in "auto" line-rule mode) for single line spacing.
|
|
32
|
+
* Word treats 240 as 1.0×, so `line-height: 1.5` → `240 * 1.5 = 360`.
|
|
33
33
|
*/
|
|
34
|
+
export declare const SINGLE_SPACING_LINE = 240;
|
|
34
35
|
export declare const lineHeightToOoxml: (lineHeight: number) => number;
|
|
35
36
|
export declare const ooxmlLineHeightToCss: (line: number) => number;
|
|
@@ -17,6 +17,18 @@ export declare function wChildren(parent: Element, localName: string): Element[]
|
|
|
17
17
|
* serialised documents differ.
|
|
18
18
|
*/
|
|
19
19
|
export declare function wVal(el: Element | null): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* Read an OOXML on/off toggle property (`CT_OnOff`: `<w:pageBreakBefore>`,
|
|
22
|
+
* `<w:b>`, `<w:keepNext>`, …). Absent → false. Present with no `w:val` →
|
|
23
|
+
* true (a bare element means "on"). Present with `w:val` →
|
|
24
|
+
* "false"/"0"/"off" mean OFF; anything else ON.
|
|
25
|
+
*
|
|
26
|
+
* Reading these by mere presence is a classic OOXML bug: Word writes the
|
|
27
|
+
* explicit-off form (`<w:pageBreakBefore w:val="0"/>`) in DocDefaults and
|
|
28
|
+
* styles, so presence-only flips the property ON for every consumer — e.g.
|
|
29
|
+
* a page break before every paragraph.
|
|
30
|
+
*/
|
|
31
|
+
export declare function wOnOff(root: Document | Element, localName: string): boolean;
|
|
20
32
|
/** Build an XML declaration header + root element. Used by the exporter. */
|
|
21
33
|
export declare function xmlDocument(rootXml: string): string;
|
|
22
34
|
/**
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CommandBus, CommandDefinition, CommandSnapshot } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Default {@link CommandBus} implementation. Plain in-memory map; no
|
|
4
|
+
* editor coupling beyond the closure plugins use when registering.
|
|
5
|
+
* Replacing it would mean swapping a field on Editor — the rest of
|
|
6
|
+
* the surface stays the same.
|
|
7
|
+
*/
|
|
8
|
+
export declare class EditorCommands implements CommandBus {
|
|
9
|
+
private readonly commands;
|
|
10
|
+
register<Args = void>(def: CommandDefinition<Args>): () => void;
|
|
11
|
+
execute<Args = void>(name: string, args?: Args): void;
|
|
12
|
+
list(): CommandSnapshot[];
|
|
13
|
+
has(name: string): boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { BlobCache, BlobStore } from '../blob';
|
|
2
|
+
import { Range as ApiRange, BlockRef, EditResult } from '../doc/api';
|
|
3
|
+
import { SobreeDocument } from '../doc/types';
|
|
4
|
+
import { FontFaceRegistry } from '../fonts';
|
|
5
|
+
import { History } from '../history';
|
|
6
|
+
import { BlockRegistry } from './internal/blockRegistry';
|
|
7
|
+
import { Mutation } from './internal/mutations';
|
|
8
|
+
import { EditorSelection } from './selection';
|
|
9
|
+
import { TrackChangesState } from './types';
|
|
10
|
+
import type * as Y from "yjs";
|
|
11
|
+
/**
|
|
12
|
+
* The kernel seam between the `Editor` (which owns mutable state, the
|
|
13
|
+
* `commit()` transaction pipeline, DOM-listener wiring, and Y.Doc
|
|
14
|
+
* mirroring) and the behaviour modules (`ops/*`, `query`) that implement
|
|
15
|
+
* each editing concern as free functions over this context.
|
|
16
|
+
*
|
|
17
|
+
* The `Editor` builds one `EditorContext` once in its constructor,
|
|
18
|
+
* closing over its own privates — so `commit` / `checkRefs` / `ensureCurrent`
|
|
19
|
+
* stay private to the class while the behaviour modules get exactly the
|
|
20
|
+
* surface they need and nothing more. This is the state/behaviour split
|
|
21
|
+
* that lets the central editor decompose without Host-seam slicing
|
|
22
|
+
* (which would have to expose nearly everything).
|
|
23
|
+
*
|
|
24
|
+
* Members are named to match the `Editor`'s own field/method names so a
|
|
25
|
+
* behaviour body reads identically whether it lives on the class or in a
|
|
26
|
+
* module: `this.commit(...)` becomes `ctx.commit(...)`.
|
|
27
|
+
*/
|
|
28
|
+
export interface EditorContext {
|
|
29
|
+
readonly host: HTMLElement;
|
|
30
|
+
readonly selection: EditorSelection;
|
|
31
|
+
readonly registry: BlockRegistry;
|
|
32
|
+
readonly history: History;
|
|
33
|
+
readonly ydoc: Y.Doc;
|
|
34
|
+
readonly blobStore: BlobStore | null;
|
|
35
|
+
readonly blobCache: BlobCache | null;
|
|
36
|
+
readonly fontFaces: FontFaceRegistry;
|
|
37
|
+
/** Live view of the editor's current document (re-read on every access). */
|
|
38
|
+
readonly doc: SobreeDocument;
|
|
39
|
+
/** Replace the cached document wholesale (rare — most paths use `commit`). */
|
|
40
|
+
setDoc(doc: SobreeDocument): void;
|
|
41
|
+
/** Full document replace: reset registry, re-render, mirror, emit change. */
|
|
42
|
+
setDocument(doc: SobreeDocument): void;
|
|
43
|
+
/** Re-render the current `doc` into the hosts (no selection restore, no emit). */
|
|
44
|
+
renderCurrent(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Soft-revert the in-memory doc to `snapshot` and re-render (resets the
|
|
47
|
+
* serialised-block cache + dom-dirty flag; no registry reset, mirror, or
|
|
48
|
+
* emit). Used to roll back the browser's native IME mutations before a
|
|
49
|
+
* tracked re-insert.
|
|
50
|
+
*/
|
|
51
|
+
restoreSnapshot(snapshot: SobreeDocument): void;
|
|
52
|
+
/** The content host(s) the renderer paints into (may differ from `host`). */
|
|
53
|
+
getContentHosts(): HTMLElement[];
|
|
54
|
+
/** The host(s) a DOM selection may live in. */
|
|
55
|
+
_hosts(): HTMLElement[];
|
|
56
|
+
readonly trackChanges: TrackChangesState;
|
|
57
|
+
/** Set tracked-changes state WITHOUT firing the change event (internal). */
|
|
58
|
+
setTrackChangesRaw(state: TrackChangesState): void;
|
|
59
|
+
readonly lastPartRefs: Record<string, string>;
|
|
60
|
+
setLastPartRefs(refs: Record<string, string>): void;
|
|
61
|
+
readonly pendingPartRefMigrations: Set<string>;
|
|
62
|
+
commit<T = void>(update: Partial<SobreeDocument>, mutations: readonly Mutation[], value?: T, reason?: string): EditResult<T>;
|
|
63
|
+
ensureCurrent(): SobreeDocument;
|
|
64
|
+
syncFromDom(): SobreeDocument;
|
|
65
|
+
checkRefs(refs: readonly BlockRef[]): EditResult<never> | null;
|
|
66
|
+
checkRange(range: ApiRange, expect: Record<string, number> | undefined): EditResult<never> | null;
|
|
67
|
+
emitChangeNow(): void;
|
|
68
|
+
mirrorToYDoc(): void;
|
|
69
|
+
scheduleChange(): void;
|
|
70
|
+
setDomDirty(value: boolean): void;
|
|
71
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM utilities for the editor — selection geometry, block-element
|
|
3
|
+
* lookup, drag/drop image detection, image sizing. Browser-only
|
|
4
|
+
* (no model state); kept apart from `editor/index.ts` so the editor
|
|
5
|
+
* module stays about editing, not DOM plumbing.
|
|
6
|
+
*/
|
|
7
|
+
/** Nearest ancestor (or self) that is a direct block child of a host. */
|
|
8
|
+
export declare function closestBlockElement(node: Node, hosts: HTMLElement[]): HTMLElement | null;
|
|
9
|
+
/** The live DOM selection range, but only if both ends are inside a host. */
|
|
10
|
+
export declare function currentDomRangeInsideHosts(hosts: HTMLElement[]): Range | null;
|
|
11
|
+
/** True when a drag/paste DataTransfer carries at least one image file. */
|
|
12
|
+
export declare function hasImageInDataTransfer(dt: DataTransfer | null): boolean;
|
|
13
|
+
/** Cross-browser caret range at viewport (x, y) — drop-point resolution. */
|
|
14
|
+
export declare function caretRangeFromPoint(x: number, y: number): Range | null;
|
|
15
|
+
/** Decode an image file's natural dimensions (falls back to 200×150). */
|
|
16
|
+
export declare function readImageDimensions(file: File): Promise<{
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
}>;
|
|
20
|
+
/** Replace an element with its children (lift contents up one level). */
|
|
21
|
+
export declare function unwrap(el: HTMLElement): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Selection } from '../doc/api';
|
|
2
|
+
import { ChangePayload, EditorEvent, EditorEventPayload, TrackChangesState, Unsubscribe } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* The editor's observable event surface — `change`, `selection`,
|
|
5
|
+
* `keydown`, `track-changes-change`. Owns the four listener sets and the
|
|
6
|
+
* dispatch loops; the Editor keeps the *triggers* (the DOM listeners and
|
|
7
|
+
* the commit pipeline) and forwards built payloads here. Each dispatch
|
|
8
|
+
* isolates listener exceptions so one bad subscriber can't break the
|
|
9
|
+
* others or the edit that fired the event.
|
|
10
|
+
*/
|
|
11
|
+
export declare class EditorEvents {
|
|
12
|
+
private readonly listeners;
|
|
13
|
+
on<E extends EditorEvent>(event: E, cb: (p: EditorEventPayload[E]) => void): Unsubscribe;
|
|
14
|
+
/** Whether any `change` subscriber exists — lets the caller skip
|
|
15
|
+
* building the (cloned) payload when nobody's listening. */
|
|
16
|
+
hasChangeListeners(): boolean;
|
|
17
|
+
emitChange(payload: ChangePayload): void;
|
|
18
|
+
/** Compose a {@link SelectionPayload} from `sel` and dispatch. */
|
|
19
|
+
emitSelection(sel: Selection): void;
|
|
20
|
+
/**
|
|
21
|
+
* Normalise a DOM `KeyboardEvent` into a {@link KeyDownPayload} and
|
|
22
|
+
* dispatch in registration order. Subscribers can `preventDefault()`
|
|
23
|
+
* (browser default) and/or `stopPropagation()` (further subscribers).
|
|
24
|
+
*/
|
|
25
|
+
emitKeyDown(e: KeyboardEvent): void;
|
|
26
|
+
emitTrackChanges(state: TrackChangesState): void;
|
|
27
|
+
/** Drop all subscribers on editor destroy. */
|
|
28
|
+
clear(): void;
|
|
29
|
+
}
|