@sobree/core 0.1.1 → 0.1.3
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/styles.d.ts +12 -0
- package/dist/doc/types.d.ts +68 -31
- package/dist/docx/export/contentTypes.d.ts +1 -0
- package/dist/docx/export/context.d.ts +1 -1
- package/dist/docx/export/numbering.d.ts +2 -0
- package/dist/docx/import/anchoredFrames.d.ts +4 -0
- package/dist/docx/import/borders.d.ts +12 -0
- package/dist/docx/import/floatFrames.d.ts +11 -0
- package/dist/docx/import/inlineFrames.d.ts +4 -0
- package/dist/docx/import/paragraphs.d.ts +6 -1
- package/dist/docx/import/styles.d.ts +13 -0
- package/dist/docx/shared/drawingColor.d.ts +30 -0
- package/dist/docx/shared/units.d.ts +3 -2
- package/dist/docx/shared/xml.d.ts +12 -0
- package/dist/docx/types.d.ts +4 -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/fontFallback.d.ts +18 -5
- package/dist/editor/view/docRenderer/inline.d.ts +2 -2
- package/dist/editor/view/docRenderer/lists.d.ts +22 -11
- 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 +5481 -5060
- 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/runs.d.ts +14 -18
- 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/styles.d.ts
CHANGED
|
@@ -17,3 +17,15 @@ export declare function resolveStyleCascade(styles: readonly NamedStyle[] | Sobr
|
|
|
17
17
|
runDefaults: RunProperties;
|
|
18
18
|
paragraphDefaults: ParagraphProperties;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a RUN character style (`<w:rStyle>`) to the run properties it
|
|
22
|
+
* contributes: its own rPr merged up its `basedOn` chain — but WITHOUT
|
|
23
|
+
* the Normal / DocDefaults anchor that `resolveStyleCascade` appends.
|
|
24
|
+
*
|
|
25
|
+
* A character style layers on top of the run's INHERITED paragraph
|
|
26
|
+
* formatting; folding the document defaults back in here would reset the
|
|
27
|
+
* run's font / size to the doc default (e.g. a colour-only "Blue" char
|
|
28
|
+
* style must not drag Times/12pt onto a Helvetica/10pt contact line). So
|
|
29
|
+
* we walk only the explicit `basedOn` chain and stop — no Normal anchor.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveRunStyle(styles: readonly NamedStyle[], styleId: string): RunProperties;
|
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`. */
|
|
@@ -129,6 +138,20 @@ export interface AnchoredFrame {
|
|
|
129
138
|
* floats over text and reserves nothing. Absent ⇒ unknown (treated
|
|
130
139
|
* as non-displacing). */
|
|
131
140
|
wrap?: "square" | "topAndBottom" | "tight" | "through" | "none";
|
|
141
|
+
/** `wrapText` side from `<wp:wrapSquare|Tight|Through wrapText="…">` —
|
|
142
|
+
* which sides of the frame body text flows on. Default `bothSides`.
|
|
143
|
+
* Only meaningful for the displacing wrap modes; drives whether a
|
|
144
|
+
* floated image goes `float: left` (text on the right) or `right`. */
|
|
145
|
+
wrapText?: "bothSides" | "left" | "right" | "largest";
|
|
146
|
+
/** Text-distance insets — `distT/B/L/R` on `<wp:anchor>`, in EMU. The
|
|
147
|
+
* gap Word keeps between the frame and the text wrapping around it;
|
|
148
|
+
* rendered as margins on the floated frame. */
|
|
149
|
+
textDistancesEmu?: {
|
|
150
|
+
topEmu: number;
|
|
151
|
+
rightEmu: number;
|
|
152
|
+
bottomEmu: number;
|
|
153
|
+
leftEmu: number;
|
|
154
|
+
};
|
|
132
155
|
/** What this frame contains. */
|
|
133
156
|
content: AnchoredContent;
|
|
134
157
|
}
|
|
@@ -271,6 +294,31 @@ export interface SectionBreak {
|
|
|
271
294
|
* **Status**: type declared (Phase 1.0). Importer does not yet emit
|
|
272
295
|
* this; renderer treats it as a no-op. Wiring lands in Phase 1.1-1.2.
|
|
273
296
|
*/
|
|
297
|
+
/** One textbox shape inside an inline-frame group: its intra-group
|
|
298
|
+
* position + size and recursive body, plus optional chrome (fill /
|
|
299
|
+
* border / text insets) and vertical text anchor. */
|
|
300
|
+
export interface InlineFrameTextbox {
|
|
301
|
+
offsetEmu: {
|
|
302
|
+
xEmu: number;
|
|
303
|
+
yEmu: number;
|
|
304
|
+
};
|
|
305
|
+
sizeEmu: {
|
|
306
|
+
wEmu: number;
|
|
307
|
+
hEmu: number;
|
|
308
|
+
};
|
|
309
|
+
body: Block[];
|
|
310
|
+
fill?: string;
|
|
311
|
+
border?: FrameBorder;
|
|
312
|
+
/** `<wps:bodyPr>` text insets (lIns/tIns/rIns/bIns) → CSS padding. */
|
|
313
|
+
padding?: {
|
|
314
|
+
topEmu: number;
|
|
315
|
+
rightEmu: number;
|
|
316
|
+
bottomEmu: number;
|
|
317
|
+
leftEmu: number;
|
|
318
|
+
};
|
|
319
|
+
/** Vertical text anchor from `<wps:bodyPr anchor>`; defaults to "top". */
|
|
320
|
+
vAlign?: "top" | "center" | "bottom";
|
|
321
|
+
}
|
|
274
322
|
export interface InlineFrame {
|
|
275
323
|
kind: "inline_frame";
|
|
276
324
|
/** From the containing `<w:p>`'s `<w:pPr>`. The paginator emits a
|
|
@@ -304,36 +352,12 @@ export interface InlineFrame {
|
|
|
304
352
|
wEmu: number;
|
|
305
353
|
hEmu: number;
|
|
306
354
|
};
|
|
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
|
-
};
|
|
355
|
+
/** The group's textbox SHAPES, in document (child) order. Most groups
|
|
356
|
+
* have one (a section "pill" heading: a centred line over a background
|
|
357
|
+
* picture), but a "Project: X" entry has two — a title textbox and a
|
|
358
|
+
* details textbox — and the renderer must show BOTH. Empty when the
|
|
359
|
+
* group carries only pictures / shapes (no textbox content). */
|
|
360
|
+
textboxes: InlineFrameTextbox[];
|
|
337
361
|
/** Decorative pictures inside the group. Each carries its own
|
|
338
362
|
* intra-group position. The renderer paints them as
|
|
339
363
|
* absolute-positioned `<img>` children of the frame wrapper,
|
|
@@ -443,10 +467,23 @@ export interface DrawingRun {
|
|
|
443
467
|
* - "inline" — flows in the paragraph like a tall character.
|
|
444
468
|
* - "anchor" — positioned absolutely (`<wp:anchor>`); `anchor`
|
|
445
469
|
* carries the offset + frame-of-reference.
|
|
470
|
+
* - "floatLeft" / "floatRight" — a `<wp:anchor>` image with a
|
|
471
|
+
* displacing wrap (square/tight/through), converted to a
|
|
472
|
+
* CSS float at the head of its anchor paragraph so body
|
|
473
|
+
* text flows around it. `floatMarginsEmu` carries the
|
|
474
|
+
* `distT/B/L/R` clearance.
|
|
446
475
|
*/
|
|
447
|
-
placement: "inline" | "anchor";
|
|
476
|
+
placement: "inline" | "anchor" | "floatLeft" | "floatRight";
|
|
448
477
|
/** Set when `placement === "anchor"`. */
|
|
449
478
|
anchor?: DrawingAnchor;
|
|
479
|
+
/** Set for `floatLeft` / `floatRight` — the text-clearance margins
|
|
480
|
+
* (from the frame's `distT/B/L/R`), applied as CSS margins. */
|
|
481
|
+
floatMarginsEmu?: {
|
|
482
|
+
topEmu: number;
|
|
483
|
+
rightEmu: number;
|
|
484
|
+
bottomEmu: number;
|
|
485
|
+
leftEmu: number;
|
|
486
|
+
};
|
|
450
487
|
/**
|
|
451
488
|
* Vertical alignment for an `inline` image relative to the text on
|
|
452
489
|
* its line. Defaults to the browser baseline (image bottom on the
|
|
@@ -4,6 +4,7 @@ declare const REL_TYPES: {
|
|
|
4
4
|
readonly image: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
5
5
|
readonly hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
|
|
6
6
|
readonly fontTable: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
|
|
7
|
+
readonly numbering: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering";
|
|
7
8
|
readonly font: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font";
|
|
8
9
|
};
|
|
9
10
|
type RelKind = keyof typeof REL_TYPES;
|
|
@@ -13,7 +13,7 @@ export interface ExportContext {
|
|
|
13
13
|
/** Rels to append to `word/_rels/document.xml.rels`. */
|
|
14
14
|
relationships: Array<{
|
|
15
15
|
id: string;
|
|
16
|
-
type: "header" | "footer" | "image" | "hyperlink" | "fontTable";
|
|
16
|
+
type: "header" | "footer" | "image" | "hyperlink" | "fontTable" | "numbering";
|
|
17
17
|
target: string;
|
|
18
18
|
/** External targets (URLs) need `TargetMode="External"`. */
|
|
19
19
|
external?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AnchoredFrame, Block } from '../../doc/types';
|
|
2
|
+
import { ThemePalette } from '../shared/drawingColor';
|
|
2
3
|
export interface AnchoredFramesContext {
|
|
3
4
|
/** RelationshipId → part path lookup, e.g. `"rId4" → "media/image1.png"`. */
|
|
4
5
|
rels: Map<string, string>;
|
|
@@ -20,6 +21,9 @@ export interface AnchoredFramesContext {
|
|
|
20
21
|
* its true layout. When absent, falls back to flat text (tests).
|
|
21
22
|
*/
|
|
22
23
|
parseBlockBody?: (txbxContent: Element) => Block[];
|
|
24
|
+
/** Theme colour palette (from `word/theme/theme1.xml`) so shape fills /
|
|
25
|
+
* strokes declared as `<a:schemeClr>` resolve instead of vanishing. */
|
|
26
|
+
theme?: ThemePalette;
|
|
23
27
|
}
|
|
24
28
|
/**
|
|
25
29
|
* Walk every `<w:drawing>/<wp:anchor>` in the document and return one
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ParagraphBorders } from '../../doc/types';
|
|
2
|
+
/**
|
|
3
|
+
* Read a `<w:pBdr>` paragraph-border element into `ParagraphBorders`.
|
|
4
|
+
*
|
|
5
|
+
* Shared by the direct-paragraph parser AND the named-style parser: Word
|
|
6
|
+
* puts the divider rules of letterhead / résumé headers on a STYLE (e.g. a
|
|
7
|
+
* "Name" style's `<w:top>` rule), not on each paragraph. Reading it only
|
|
8
|
+
* for direct paragraphs dropped those rules entirely (the renderer's
|
|
9
|
+
* `effective.borders` cascade had nothing to apply). `none` / `nil` sides
|
|
10
|
+
* are skipped (Word's explicit "no border on this side").
|
|
11
|
+
*/
|
|
12
|
+
export declare function readParagraphBorders(pPr: Element): ParagraphBorders | undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnchoredFrame, Block, SectionProperties } from '../../doc/types';
|
|
2
|
+
/**
|
|
3
|
+
* Prepend a float `DrawingRun` to each floatable frame's anchor paragraph
|
|
4
|
+
* and drop those frames from the overlay set. Pure — inputs untouched.
|
|
5
|
+
* Body indices are stable (we modify paragraphs in place, never insert),
|
|
6
|
+
* so it composes after `flowDisplacingTextboxes` without an index remap.
|
|
7
|
+
*/
|
|
8
|
+
export declare function floatWrappingImages(body: readonly Block[], frames: readonly AnchoredFrame[], sections: readonly SectionProperties[]): {
|
|
9
|
+
body: Block[];
|
|
10
|
+
frames: AnchoredFrame[];
|
|
11
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Block, InlineFrame } from '../../doc/types';
|
|
2
|
+
import { ThemePalette } from '../shared/drawingColor';
|
|
2
3
|
export interface InlineFramesContext {
|
|
3
4
|
/** RelationshipId → part path lookup. */
|
|
4
5
|
rels: Map<string, string>;
|
|
@@ -26,6 +27,9 @@ export interface InlineFramesContext {
|
|
|
26
27
|
* Without this flag, only explicit directives count.
|
|
27
28
|
*/
|
|
28
29
|
honorLastRenderedPageBreaks?: boolean;
|
|
30
|
+
/** Theme colour palette (from `word/theme/theme1.xml`) so textbox /
|
|
31
|
+
* shape fills declared as `<a:schemeClr>` resolve instead of vanishing. */
|
|
32
|
+
theme?: ThemePalette;
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* One InlineFrame plus the source DOM nodes it came from.
|
|
@@ -4,9 +4,14 @@ import { ParagraphFormat } from '../types';
|
|
|
4
4
|
export type ImportedItem = {
|
|
5
5
|
kind: "run";
|
|
6
6
|
run: ImportedRun;
|
|
7
|
-
}
|
|
7
|
+
}
|
|
8
|
+
/** `href` is set for HYPERLINK *fields* (the target lives in the field
|
|
9
|
+
* instruction); `relId` for `<w:hyperlink r:id>` elements (resolved
|
|
10
|
+
* against the rels table downstream). */
|
|
11
|
+
| {
|
|
8
12
|
kind: "hyperlink";
|
|
9
13
|
relId?: string;
|
|
14
|
+
href?: string;
|
|
10
15
|
runs: ImportedRun[];
|
|
11
16
|
};
|
|
12
17
|
export interface ImportedParagraph {
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import { NamedStyle } from '../../doc/types';
|
|
2
2
|
import { DocSettings } from './settings';
|
|
3
|
+
/**
|
|
4
|
+
* Canonicalise a heading style id to `HeadingN`.
|
|
5
|
+
*
|
|
6
|
+
* Word and OpenOffice name the heading styles inconsistently across docs:
|
|
7
|
+
* `Heading2`, `Heading 2`, `heading 2`. The paragraph importer already
|
|
8
|
+
* maps a heading PARAGRAPH's styleId to the canonical `HeadingN` (so it
|
|
9
|
+
* renders as `<hN>` and joins the `HeadingN` convention used by builders /
|
|
10
|
+
* serialize / markdown). The STYLE definition must canonicalise the same
|
|
11
|
+
* way, or `resolveStyleCascade` looks up `HeadingN` and misses the
|
|
12
|
+
* actual style — dropping its colour, caps, etc. Non-heading ids pass
|
|
13
|
+
* through unchanged.
|
|
14
|
+
*/
|
|
15
|
+
export declare function canonicalStyleId(id: string): string;
|
|
3
16
|
export declare function parseStylesXml(xml: string | undefined, settings?: DocSettings): NamedStyle[] | null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DrawingML colour resolution — literal AND theme colours.
|
|
3
|
+
*
|
|
4
|
+
* A DrawingML colour container (`<a:solidFill>`, the children of
|
|
5
|
+
* `<a:ln>`, …) holds either a literal `<a:srgbClr val="RRGGBB">` or a
|
|
6
|
+
* theme reference `<a:schemeClr val="accent1">`. Both can carry child
|
|
7
|
+
* TRANSFORM elements that adjust the base colour (`hueOff`, `satOff`,
|
|
8
|
+
* `lumOff`, `lumMod`, `shade`, `tint`, …). Word resolves the scheme slot
|
|
9
|
+
* against `word/theme/theme1.xml`'s `<a:clrScheme>` and applies the
|
|
10
|
+
* transforms in document order — reading only `srgbClr` renders every
|
|
11
|
+
* theme-coloured shape invisible (no fill, no stroke).
|
|
12
|
+
*
|
|
13
|
+
* Transform units (ECMA-376 §20.1.2.3):
|
|
14
|
+
* - `hueOff` — 60000ths of a degree, added to the hue.
|
|
15
|
+
* - `satOff` / `lumOff` — 1000ths of a percent-POINT, added to S / L.
|
|
16
|
+
* - `satMod` / `lumMod` — 100000ths, multiplied onto S / L.
|
|
17
|
+
* - `shade` — scale toward black (val/100000).
|
|
18
|
+
* - `tint` — scale toward white (val/100000).
|
|
19
|
+
*/
|
|
20
|
+
/** Theme slot → `#RRGGBB`. Slots: dk1/lt1/dk2/lt2/accent1-6/hlink/folHlink. */
|
|
21
|
+
export type ThemePalette = Record<string, string>;
|
|
22
|
+
/** Parse `word/theme/theme1.xml` into the colour-scheme palette.
|
|
23
|
+
* Returns undefined when the part is absent or malformed. */
|
|
24
|
+
export declare function parseThemeXml(xml: string | undefined): ThemePalette | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the colour child of `parent` (an `<a:solidFill>` or `<a:ln>`-
|
|
27
|
+
* style container): literal `srgbClr` or theme `schemeClr`, transforms
|
|
28
|
+
* applied. Returns `#RRGGBB` or undefined when no resolvable colour.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readDrawingColor(parent: Element, theme?: ThemePalette): string | undefined;
|
|
@@ -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
|
/**
|
package/dist/docx/types.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export interface DocxExportResult {
|
|
|
18
18
|
}
|
|
19
19
|
/** A single inline run's formatting flags — what `<w:rPr>` tells us. */
|
|
20
20
|
export interface RunFormat {
|
|
21
|
+
/** `<w:rStyle w:val="…">` — a character style applied to the run. Its
|
|
22
|
+
* rPr (colour, underline, …) is resolved against the style cascade at
|
|
23
|
+
* render time, under any direct run formatting. */
|
|
24
|
+
styleId?: string;
|
|
21
25
|
bold?: boolean;
|
|
22
26
|
italic?: boolean;
|
|
23
27
|
underline?: boolean;
|
|
@@ -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
|
+
}
|