@sobree/core 0.1.8 → 0.1.10

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.
@@ -1,9 +1,9 @@
1
- import { Sobree, SobreeEvent, SobreeEventPayload, SobreeUnsubscribe } from './sobree';
2
- import { Editor, CommandBus } from './editor';
1
+ import { SobreeDocument } from './doc/types';
2
+ import { CommandBus, Editor } from './editor';
3
3
  import { Viewport } from './embed/viewport';
4
- import { SobreePlugin } from './plugin';
5
4
  import { PageSetup } from './paperStack/pageSetup';
6
- import { SobreeDocument } from './doc/types';
5
+ import { SobreePlugin } from './plugin';
6
+ import { Sobree, SobreeEvent, SobreeEventPayload, SobreeUnsubscribe } from './sobree';
7
7
  /**
8
8
  * Initial content. Type detection is automatic:
9
9
  * - `string` → seed-quality Markdown (see `parseMarkdown`)
@@ -5,10 +5,11 @@ import { NamedStyle, ParagraphProperties, RunProperties, SobreeDocument } from '
5
5
  * renderer should apply (block element inherits these to its runs)
6
6
  * and what the toolbar's font / mark dropdowns should reflect.
7
7
  *
8
- * Falls back to the document's `Normal` style at the end of the chain
9
- * so a paragraph with no explicit style still picks up the document's
10
- * baseline run / paragraph defaults (see `defaultStyles()` in
11
- * `./builders`).
8
+ * Anchors in `DocDefaults` (the document-wide base) for every style.
9
+ * The `Normal` default-paragraph style is added ONLY for a paragraph
10
+ * with no explicit style a style that exists but declares no
11
+ * `basedOn` inherits DocDefaults alone, matching OOXML (Normal is
12
+ * threaded in only via an explicit `basedOn`).
12
13
  *
13
14
  * Cycles in `basedOn` are tolerated — we de-dupe by id and stop
14
15
  * walking. Missing styles are silently skipped.
@@ -218,21 +218,36 @@ export type AnchoredContent = {
218
218
  };
219
219
  } | {
220
220
  kind: "shape";
221
- geometry: "rect" | "ellipse" | "roundedRect" | "line";
221
+ geometry: "rect" | "ellipse" | "roundedRect" | "line" | "custom";
222
222
  fill?: string;
223
223
  border?: {
224
224
  color: string;
225
225
  widthEmu: number;
226
226
  style: "solid" | "dashed" | "dotted" | "double";
227
227
  };
228
+ /** Present when `geometry === "custom"`: a DrawingML `<a:custGeom>`
229
+ * outline as an SVG path in its own `widthEmu × heightEmu` box,
230
+ * rendered as a scaled `<svg><path>`. Absent for preset geometry. */
231
+ path?: {
232
+ widthEmu: number;
233
+ heightEmu: number;
234
+ d: string;
235
+ };
228
236
  } | {
229
237
  kind: "group";
230
238
  children: AnchoredFrame[];
231
- /** Local coordinate system extent children's offsets are
232
- * scaled `(width / childCoordSystemCx) × (height / childCoordSystemCy)`
233
- * to fit the group's actual rendered size. */
239
+ /** Local coordinate system extent (`<a:chExt>`). A child at offset
240
+ * `P` maps into the group's rendered box as
241
+ * `(P childCoordOffset) × (size / childCoordSystem)` — the
242
+ * extent gives the scale. */
234
243
  childCoordSystemCx: number;
235
244
  childCoordSystemCy: number;
245
+ /** Local coordinate system ORIGIN (`<a:chOff>`). Child offsets are
246
+ * measured from this point, not from 0 — so it must be subtracted
247
+ * before scaling, or the children shift by `chOff × scale`.
248
+ * Absent ⇒ origin is `(0, 0)` (the common case). */
249
+ childCoordOffsetX?: number;
250
+ childCoordOffsetY?: number;
236
251
  };
237
252
  export interface Comment {
238
253
  id: number;
@@ -753,9 +768,26 @@ export interface SectionProperties {
753
768
  columns?: SectionColumns;
754
769
  }
755
770
  export interface SectionColumns {
756
- /** Number of equal-width columns. */
771
+ /** Number of columns. */
757
772
  count: number;
758
- /** Inter-column gap in twips (Word's `<w:cols w:space>` attribute). */
773
+ /** Default inter-column gap in twips (Word's `<w:cols w:space>`). Used
774
+ * for equal columns and as the fallback gap when a per-column space
775
+ * is absent. */
776
+ spaceTwips?: number;
777
+ /** `false` when the section declares explicit per-column widths
778
+ * (Word's `<w:cols w:equalWidth="0">`). Absent/`true` → equal columns,
779
+ * which the renderer flows with CSS multi-column. */
780
+ equalWidth?: boolean;
781
+ /** Per-column geometry from `<w:col w:w w:space>`, present only for the
782
+ * unequal case. `length === count`. Each entry's `spaceTwips` is the
783
+ * gap AFTER that column (the last column's is usually absent). The
784
+ * renderer flows blocks across these tracks at their true widths. */
785
+ columns?: SectionColumn[];
786
+ }
787
+ export interface SectionColumn {
788
+ /** Column width in twips (`<w:col w:w>`). */
789
+ widthTwips: number;
790
+ /** Trailing gap after this column in twips (`<w:col w:space>`). */
759
791
  spaceTwips?: number;
760
792
  }
761
793
  export interface PageSize {
@@ -1,5 +1,5 @@
1
- import { ExportContext } from './context';
2
1
  import { Block, SobreeDocument } from '../../doc/types';
2
+ import { ExportContext } from './context';
3
3
  /**
4
4
  * Render the SobreeDocument body into `word/document.xml` (string form).
5
5
  *
@@ -1,5 +1,5 @@
1
- import { ExportContext } from './context';
2
1
  import { SectionProperties, SobreeDocument } from '../../doc/types';
2
+ import { ExportContext } from './context';
3
3
  /**
4
4
  * Build the OOXML scaffolding for every section in `doc`: header/footer
5
5
  * XML parts, relationships, content-type overrides — and a parallel
@@ -1,5 +1,5 @@
1
- import { ExportContext } from './context';
2
1
  import { InlineRun, SobreeDocument } from '../../doc/types';
2
+ import { ExportContext } from './context';
3
3
  /**
4
4
  * Render a list of InlineRuns into concatenated `<w:r>` / `<w:fldSimple>`
5
5
  * / `<w:drawing>` XML. Drawings use `ctx` to allocate a relationship id
@@ -1,3 +1,3 @@
1
- import { ConvertContext } from './paragraph';
2
1
  import { Comment } from '../../doc/types';
2
+ import { ConvertContext } from './paragraph';
3
3
  export declare function parseCommentsXml(xml: string | undefined, ctx: ConvertContext, extendedXml?: string | undefined): Record<number, Comment>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * DrawingML custom geometry → SVG path.
3
+ *
4
+ * Word draws wordmarks, logo cuts, and other bespoke shapes as a
5
+ * `<a:custGeom>` whose `<a:pathLst>` holds one or more `<a:path w h>`
6
+ * coordinate boxes filled with move / line / curve commands. We translate
7
+ * those commands straight into an SVG path `d` string in the path's own
8
+ * coordinate units; the renderer drops it into an `<svg>` sized to the
9
+ * shape's box (`preserveAspectRatio="none"`), so the mark scales to
10
+ * wherever the shape resolves on the page.
11
+ *
12
+ * Supported: moveTo, lnTo, cubicBezTo, quadBezTo, close — the commands
13
+ * authored shapes actually use. Subpaths (a glyph with a counter, e.g.
14
+ * the "O" in a wordmark) come through as separate `M…Z` runs in one `d`,
15
+ * so an even-odd fill punches the holes. An unrecognised command (e.g.
16
+ * the rare arcTo) is skipped rather than aborting the whole path.
17
+ *
18
+ * Pure: XML in, plain data out. No DOM, no side effects.
19
+ */
20
+ /** A custom-geometry outline as an SVG path in its own coordinate box. */
21
+ export interface ShapePath {
22
+ /** Path-space width (`<a:path w>`), the viewBox x-extent. */
23
+ widthEmu: number;
24
+ /** Path-space height (`<a:path h>`), the viewBox y-extent. */
25
+ heightEmu: number;
26
+ /** SVG path data in the `widthEmu × heightEmu` coordinate box. */
27
+ d: string;
28
+ }
29
+ /**
30
+ * Parse a `<a:custGeom>` into an SVG path, or `null` when it carries no
31
+ * usable outline (no `<a:path>`, a zero-area box, or only unsupported
32
+ * commands).
33
+ */
34
+ export declare function parseCustomGeometry(custGeom: Element): ShapePath | null;
@@ -1,5 +1,5 @@
1
- import { ConvertContext } from './paragraph';
2
1
  import { Block } from '../../doc/types';
2
+ import { ConvertContext } from './paragraph';
3
3
  export { type ConvertContext, convertParagraph } from './paragraph';
4
4
  export interface DocumentImport {
5
5
  body: Block[];
@@ -1,3 +1,3 @@
1
- import { ConvertContext } from './paragraph';
2
1
  import { Block } from '../../doc/types';
2
+ import { ConvertContext } from './paragraph';
3
3
  export declare function parseFootnotesXml(xml: string | undefined, ctx: ConvertContext): Record<number, Block[]>;
@@ -1,6 +1,6 @@
1
- import { wVal } from '../shared/xml';
2
- import { PageZoneText } from '../../paperStack/pageSetup';
3
1
  import { SectionProperties } from '../../doc/types';
2
+ import { PageZoneText } from '../../paperStack/pageSetup';
3
+ import { wVal } from '../shared/xml';
4
4
  /** Zone text extracted from the docx, with `{page}`/`{pages}` placeholders. */
5
5
  export interface ImportedZones {
6
6
  header: PageZoneText;
@@ -1,7 +1,7 @@
1
- import { templateToBlocks } from '../../doc/pageSetupBridge';
2
- import { DocxImportResult } from '../types';
3
1
  import { emptyDocument } from '../../doc/builders';
2
+ import { templateToBlocks } from '../../doc/pageSetupBridge';
4
3
  import { Block, SobreeDocument } from '../../doc/types';
4
+ import { DocxImportResult } from '../types';
5
5
  /**
6
6
  * Top-level entry point for importing a .docx file. Returns a native
7
7
  * `SobreeDocument` plus any warnings surfaced by the conversion.
@@ -1,5 +1,5 @@
1
- import { ImportedRun } from './runs';
2
1
  import { ParagraphFormat } from '../types';
2
+ import { ImportedRun } from './runs';
3
3
  /** Source-order paragraph item: either a flat run or a hyperlink-wrapped group. */
4
4
  export type ImportedItem = {
5
5
  kind: "run";
@@ -1,5 +1,5 @@
1
- import { ConvertContext } from './paragraph';
2
1
  import { Table } from '../../doc/types';
2
+ import { ConvertContext } from './paragraph';
3
3
  /**
4
4
  * Convert a `<w:tbl>` element into a native Table block. Handles:
5
5
  * - Column widths from `<w:tblGrid>` (twips).
@@ -0,0 +1,9 @@
1
+ import { History } from '../history';
2
+ import { CommandBus, EditorLike } from './types';
3
+ /**
4
+ * Register history + mark commands on the bus. `editor` is the
5
+ * structural {@link EditorLike} the mark helpers operate on — typing it
6
+ * that way (not the concrete `Editor` from ./index) keeps this module a
7
+ * leaf and avoids an index ↔ coreCommands import cycle.
8
+ */
9
+ export declare function registerCoreCommands(commands: CommandBus, editor: EditorLike, history: History): void;
@@ -88,20 +88,14 @@ export declare class Editor {
88
88
  * in the Y.Doc.
89
89
  */
90
90
  private readonly pendingPartRefMigrations;
91
- /** Listener that re-projects + re-renders on remote Y.Doc updates.
92
- * Removed on `destroy()`. */
93
- private ydocUpdateListener;
91
+ /** Removes every DOM/document listener + the Y.Doc subscription wired
92
+ * by `wireEditorDom`. Called once from `destroy()`. */
93
+ private domTeardown;
94
94
  private doc;
95
95
  private readonly registry;
96
96
  private readonly debounceMs;
97
97
  private readonly getContentHosts;
98
98
  private debounceHandle;
99
- private detachImageResize;
100
- private inputListener;
101
- private beforeInputListener;
102
- private pasteListener;
103
- private dragOverListener;
104
- private dropListener;
105
99
  private revision;
106
100
  /** The editor's observable event surface (change / selection / keydown
107
101
  * / track-changes-change). See `./events.ts`. */
@@ -121,15 +115,6 @@ export declare class Editor {
121
115
  * `ops/trackedInput`.
122
116
  */
123
117
  private trackedInput;
124
- private compositionStartListener;
125
- private compositionEndListener;
126
- /** Document-level `selectionchange` listener. Funnels every cursor
127
- * movement (typing, click, arrows, programmatic restore) into the
128
- * `selection` event so plugins don't each register their own. */
129
- private selectionChangeListener;
130
- /** Host-level `keydown` listener. Funnels every key press into the
131
- * `keydown` event for plugins (mark shortcuts, navigation, etc.). */
132
- private keydownListener;
133
118
  /** Cached last-seen per-block JSON strings, for diff-based version bumps. */
134
119
  private lastSerialisedBlocks;
135
120
  /** Tracks `@font-face` registrations for the document's embedded fonts. */
@@ -159,6 +144,16 @@ export declare class Editor {
159
144
  */
160
145
  private readonly ctx;
161
146
  constructor(host: HTMLElement, options?: EditorOptions);
147
+ /**
148
+ * Initialise `this.doc` + registry from the Y.Doc. Two paths, run
149
+ * after the context exists so the adopt path can resolve cached part
150
+ * refs through it:
151
+ * A. Empty Y.Doc (or none provided) → seed it from `initialDocument`
152
+ * (solo embedder, the v0.1 default).
153
+ * B. Y.Doc already has body content → adopt it (a provider populated
154
+ * the doc before construction; trust what's there).
155
+ */
156
+ private initDocumentState;
162
157
  /**
163
158
  * Assemble the {@link EditorContext} the behaviour modules operate on.
164
159
  * Closes over `this` so the kernel methods (`commit`, `checkRefs`, …)
@@ -1,6 +1,6 @@
1
+ import { RunPropertiesPatch } from '../../doc/runs';
1
2
  import { Block, ParagraphProperties, RunProperties, SectionProperties, SobreeDocument } from '../../doc/types';
2
3
  import { ParagraphPropertiesPatch, WrapTag } from '../types';
3
- import { RunPropertiesPatch } from '../../doc/runs';
4
4
  /**
5
5
  * One registry-level operation produced by a mutation. The caller
6
6
  * applies these to the BlockRegistry after committing the new doc:
@@ -1,4 +1,4 @@
1
- import { InlinePosition, Range as ApiRange, Selection } from '../../doc/api';
1
+ import { Range as ApiRange, InlinePosition, Selection } from '../../doc/api';
2
2
  import { BlockRegistry } from './blockRegistry';
3
3
  /**
4
4
  * Resolve a DOM point `(node, offset)` to an `InlinePosition`, or null
@@ -0,0 +1,41 @@
1
+ import { History } from '../history';
2
+ import { EditorContext } from './context';
3
+ import { TrackedInput } from './ops/trackedInput';
4
+ /**
5
+ * DOM event wiring for the Editor.
6
+ *
7
+ * The Editor needs a fixed set of `host` / `document` listeners —
8
+ * input, beforeinput, IME composition, selectionchange, keydown, paste,
9
+ * drag/drop — plus the image-resize handles and a remote-Y.Doc-update
10
+ * subscription. Keeping them here (out of the constructor) does two
11
+ * things: it drops the constructor's length and nesting, and it makes
12
+ * teardown a single returned function instead of seven nullable fields
13
+ * the destructor has to remember to clear.
14
+ *
15
+ * `wireEditorDom` takes the small set of editor hooks the listeners
16
+ * actually call and returns one teardown that removes everything.
17
+ */
18
+ import type * as Y from "yjs";
19
+ export interface EditorDomHooks {
20
+ host: HTMLElement;
21
+ ctx: EditorContext;
22
+ ydoc: Y.Doc;
23
+ history: History;
24
+ trackedInput: TrackedInput;
25
+ /** Tracked-changes authoring mode is on right now. */
26
+ isTrackedEnabled: () => boolean;
27
+ /** Mark the DOM dirty + schedule a debounced change. */
28
+ onInput: () => void;
29
+ /** Fire the editor's `selection` event. */
30
+ fireSelection: () => void;
31
+ /** Fire the editor's `keydown` event. */
32
+ fireKeyDown: (e: KeyboardEvent) => void;
33
+ /** Re-project + re-render after a remote Y.Doc update. */
34
+ adoptYDocState: () => void;
35
+ }
36
+ /**
37
+ * Attach every DOM/document listener the editor relies on and return a
38
+ * teardown that removes them all (listeners, image-resize handles, and
39
+ * the Y.Doc subscription). Idempotent teardown — safe to call once.
40
+ */
41
+ export declare function wireEditorDom(hooks: EditorDomHooks): () => void;
@@ -1,5 +1,5 @@
1
- import { ExportContext } from '../docx/export/context';
2
1
  import { SobreeDocument } from '../doc/types';
2
+ import { ExportContext } from '../docx/export/context';
3
3
  interface FontTableEmission {
4
4
  /** Inner XML of `word/fontTable.xml`. */
5
5
  fontTableXml: string;
@@ -1,7 +1,7 @@
1
1
  import { BlobCache, BlobStore } from './blob';
2
2
  import { BlockRef, EditError, EditResult, Selection } from './doc/api';
3
- import { ParagraphPropertiesPatch, BlockInfo, CommandBus, OutlineItem } from './editor';
4
3
  import { Block, ParagraphAlignment, ParagraphProperties, SobreeDocument } from './doc/types';
4
+ import { ParagraphPropertiesPatch, BlockInfo, CommandBus, OutlineItem } from './editor';
5
5
  import { History } from './history';
6
6
  /**
7
7
  * HeadlessSobree — a no-DOM Sobree peer for LLM agents, automation,
@@ -56,7 +56,7 @@ import { History } from './history';
56
56
  * per-peer origin string (e.g. `"agent:gpt-4-2024-05"`) if you want
57
57
  * post-hoc telemetry to identify the author.
58
58
  */
59
- import * as Y from "yjs";
59
+ import type * as Y from "yjs";
60
60
  export interface HeadlessSobreeOptions {
61
61
  /**
62
62
  * Origin string used for this peer's Y.Doc mutations. Identifies
package/dist/index.css CHANGED
@@ -1 +1 @@
1
- .paper-stack{display:flex;flex-direction:column;padding:48px;gap:28px;outline:none}.paper-row{display:flex;flex-direction:row;align-items:flex-start;gap:24px}.paper{position:relative;background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 2px #00000014,0 18px 60px #0000001f;padding-top:var(--margin-top, 25mm);padding-right:var(--margin-right, 20mm);padding-bottom:var(--margin-bottom, 25mm);padding-left:var(--margin-left, 20mm);overflow:hidden;flex:none}.paper-header,.paper-footer{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);font-size:10pt;color:#555;white-space:pre-wrap}.paper-header{top:0;min-height:var(--margin-top, 25mm);padding-top:var(--header-offset-mm, 12.7mm);padding-bottom:4mm;border-bottom:1px dashed transparent}.paper-footer{bottom:0;min-height:var(--margin-bottom, 25mm);padding-top:4mm;text-align:center;border-top:1px dashed transparent}.paper-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:1}.paper-anchors.is-empty{display:none}.paper-anchors-behind{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:0}.paper-anchors-behind.is-empty{display:none}.paper-zone-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:2}.paper-zone-anchors.is-empty{display:none}.paper-anchor{position:absolute;box-sizing:border-box;overflow:hidden}.paper-header>p,.paper-footer>p,.paper-header>ul,.paper-header>ol,.paper-footer>ul,.paper-footer>ol{margin:0}.paper-footnotes{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);bottom:var(--margin-bottom, 25mm);font-size:.85em;padding-top:.5em;border-top:1pt solid currentColor;background:#fffffff5;z-index:1;max-height:40%;overflow:hidden}.paper-footnotes.is-empty{display:none}.paper-comments{flex:0 0 70mm;max-width:70mm;font-size:.85em;padding:0 .5em;align-self:stretch;overflow-y:auto}.paper-comments.is-empty{display:none}.paper-footnotes .sobree-footnotes__list{margin:0;padding-left:1.5em}.paper-footnotes .sobree-footnotes__item{margin:.25em 0}.paper-content a{color:inherit;text-decoration:none}.paper-content{position:relative;height:100%;min-height:100px;display:flow-root}.paper-content td p:not([style*=line-height]),.paper-content td li:not([style*=line-height]),.paper-content th p:not([style*=line-height]),.paper-content th li:not([style*=line-height]){line-height:1}.paper-content td p:not([style*=margin]),.paper-content th p:not([style*=margin]){margin:0}.paper-content .sobree-hang>li{list-style:none}.paper-content .sobree-hang>li:before{display:inline-block;box-sizing:border-box;width:var(--sobree-list-hang, 0);margin-left:calc(-1 * var(--sobree-list-hang, 0));white-space:nowrap;color:var(--sobree-marker-color, currentColor);font-family:var(--sobree-marker-font, inherit);font-size:var(--sobree-marker-size, inherit)}.paper-content .sobree-hang.lst-bullet>li:before{content:var(--sobree-bullet, "•")}.paper-content .sobree-hang.lst-decimal>li:before{content:var(--mk-pre, "") counter(list-item,decimal) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-decimal-zero>li:before{content:var(--mk-pre, "") counter(list-item,decimal-leading-zero) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-latin>li:before{content:var(--mk-pre, "") counter(list-item,lower-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-latin>li:before{content:var(--mk-pre, "") counter(list-item,upper-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-roman>li:before{content:var(--mk-pre, "") counter(list-item,lower-roman) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-roman>li:before{content:var(--mk-pre, "") counter(list-item,upper-roman) var(--mk-suf, ".")}.paper-content .sobree-tab-spread{display:flex;justify-content:space-between;align-items:baseline;gap:1em;white-space:nowrap}.paper-content .sobree-tab-spread .sobree-tab-spread__before,.paper-content .sobree-tab-spread .sobree-tab-spread__after{white-space:pre-wrap;min-width:0}.paper-content table.sobree-table-bordered td,.paper-content table.sobree-table-bordered th{border:var(--table-cell-border, none);padding:0 4px}.sobree-editor{position:relative;outline:none}.sobree-editor>:first-child{margin-top:0}.sobree-editor p,.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6,.sobree-editor ul,.sobree-editor ol,.sobree-editor li,.sobree-editor blockquote,.sobree-editor pre{margin:0;padding:0}.sobree-editor ul,.sobree-editor ol{padding-left:1.5em}.sobree-editor li.sobree-li-continuation{list-style-type:none}.sobree-editor li.sobree-li-continuation::marker{content:""}.sobree-editor .sobree-fragment-continued{text-align-last:justify}.sobree-editor .sobree-footnote-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-footnote-ref a:hover{text-decoration:underline}.sobree-editor .sobree-footnotes{margin-top:2em;padding-top:.5em;border-top:1pt solid currentColor;font-size:.85em}.sobree-editor .sobree-footnotes__list{padding-left:1.5em}.sobree-editor .sobree-footnotes__item{margin:.25em 0}.sobree-editor ins.sobree-revision-ins{text-decoration:underline}.sobree-editor del.sobree-revision-del{text-decoration:line-through}.sobree-editor .sobree-revision-format{text-decoration:underline dashed var(--sobree-format-revision-color, currentColor);text-underline-offset:3px}.sobree-editor [data-block-revision=ins]:after,.sobree-editor [data-block-revision=del]:after{content:" ¶";color:var(--sobree-block-revision-color, currentColor);opacity:.65;font-weight:600;-webkit-user-select:none;user-select:none}.sobree-editor [data-block-revision=del]:after{text-decoration:line-through}.sobree-editor .sobree-comment-range{background:var(--sobree-comment-range-bg, rgba(255, 217, 0, .25));border-bottom:1px dotted var(--sobree-comment-range-border, rgba(180, 130, 0, .5))}.sobree-editor .sobree-comment-ref{display:inline;font-size:.85em;margin:0 .1em}.sobree-editor .sobree-comment-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-comment-ref a:hover{filter:brightness(.7)}.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6{font-size:inherit;font-weight:inherit}.sobree-editor table{border-collapse:collapse;width:100%;position:relative}.sobree-editor th,.sobree-editor td{border:none;padding:0 .08in;vertical-align:top;transition:border-color .12s ease}.sobree-editor .sobree-section-break{display:flex;align-items:center;gap:8px;margin:8px 0;color:var(--fg-subtle, #7c7764);font-size:11px;letter-spacing:.04em;text-transform:uppercase;-webkit-user-select:none;user-select:none}.sobree-editor .sobree-section-break--continuous{visibility:hidden;height:0;margin:0;padding:0;border:none;overflow:hidden;font-size:0;line-height:0}.sobree-editor .sobree-section-break:before,.sobree-editor .sobree-section-break:after{content:"";flex:1;border-top:1px dashed var(--border, #dedbd0)}.sobree-editor .sobree-section-break__label{flex:none;padding:0 6px;background:var(--bg-elevated, #fff)}.sobree-editor .sobree-textbox-frame p{line-height:1.2}.sobree-editor .paper-content p,.sobree-editor .paper-content li,.sobree-editor .paper-header p,.sobree-editor .paper-header li,.sobree-editor .paper-footer p,.sobree-editor .paper-footer li,.sobree-editor .sobree-textbox-frame p{white-space:pre-wrap}.sobree-editor .sobree-section-trailer-empty{height:0;line-height:0;font-size:0;margin:0;padding:0;overflow:hidden}.sobree-editor .sobree-textbox-frame--placeholder{border:1px solid var(--border, #c8c4b8)}.sobree-editor .sobree-textbox-frame--placeholder.sobree-textbox-frame--filled{border:none;z-index:-1}.sobree-editor img.is-selected{outline:2px solid var(--sobree-primary, #d4521f);outline-offset:2px}.sobree-image-resize-handle{position:absolute;width:16px;height:16px;background:var(--sobree-primary, #d4521f);border:2px solid #fff;border-radius:3px;cursor:nwse-resize;z-index:1000;-webkit-user-select:none;user-select:none}.sobree-viewport{position:relative;overflow:hidden;overscroll-behavior:contain;touch-action:none;background:#ececee}.sobree-viewport__stage{position:absolute;top:0;left:0;transform-origin:0 0}.sobree-viewport__stage.is-gesturing,.sobree-viewport__stage.is-animating{will-change:transform}.sobree-viewport__stage.is-animating{transition:transform .32s cubic-bezier(.2,.7,.2,1)}.sobree-viewport__slot{display:block}.paper-stack .paper-content,.paper-stack .paper-header,.paper-stack .paper-footer{transition:opacity .2s ease}.paper-stack.is-zone-editing .paper-content,.paper-stack.is-zone-editing .paper-header,.paper-stack.is-zone-editing .paper-footer{opacity:.2}.paper-stack.is-zone-editing .paper-header[contenteditable=true],.paper-stack.is-zone-editing .paper-footer[contenteditable=true]{opacity:1}.paper-header[contenteditable=true],.paper-footer[contenteditable=true]{outline:2px dotted var(--primary, #c96f22);outline-offset:4px;background:var(--primary-soft, #fdf6ee);color:var(--fg-strong, #14130f);border-radius:2px}
1
+ .sobree-viewport{position:relative;overflow:hidden;overscroll-behavior:contain;touch-action:none;background:#ececee}.sobree-viewport__stage{position:absolute;top:0;left:0;transform-origin:0 0}.sobree-viewport__stage.is-gesturing,.sobree-viewport__stage.is-animating{will-change:transform}.sobree-viewport__stage.is-animating{transition:transform .32s cubic-bezier(.2,.7,.2,1)}.sobree-viewport__slot{display:block}.sobree-editor{position:relative;outline:none}.sobree-editor>:first-child{margin-top:0}.sobree-editor p,.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6,.sobree-editor ul,.sobree-editor ol,.sobree-editor li,.sobree-editor blockquote,.sobree-editor pre{margin:0;padding:0}.sobree-editor ul,.sobree-editor ol{padding-left:1.5em}.sobree-editor li.sobree-li-continuation{list-style-type:none}.sobree-editor li.sobree-li-continuation::marker{content:""}.sobree-editor .sobree-fragment-continued{text-align-last:justify}.sobree-editor .sobree-footnote-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-footnote-ref a:hover{text-decoration:underline}.sobree-editor .sobree-footnotes{margin-top:2em;padding-top:.5em;border-top:1pt solid currentColor;font-size:.85em}.sobree-editor .sobree-footnotes__list{padding-left:1.5em}.sobree-editor .sobree-footnotes__item{margin:.25em 0}.sobree-editor ins.sobree-revision-ins{text-decoration:underline}.sobree-editor del.sobree-revision-del{text-decoration:line-through}.sobree-editor .sobree-revision-format{text-decoration:underline dashed var(--sobree-format-revision-color, currentColor);text-underline-offset:3px}.sobree-editor [data-block-revision=ins]:after,.sobree-editor [data-block-revision=del]:after{content:" ¶";color:var(--sobree-block-revision-color, currentColor);opacity:.65;font-weight:600;-webkit-user-select:none;user-select:none}.sobree-editor [data-block-revision=del]:after{text-decoration:line-through}.sobree-editor .sobree-comment-range{background:var(--sobree-comment-range-bg, rgba(255, 217, 0, .25));border-bottom:1px dotted var(--sobree-comment-range-border, rgba(180, 130, 0, .5))}.sobree-editor .sobree-comment-ref{display:inline;font-size:.85em;margin:0 .1em}.sobree-editor .sobree-comment-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-comment-ref a:hover{filter:brightness(.7)}.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6{font-size:inherit;font-weight:inherit}.sobree-editor table{border-collapse:collapse;width:100%;position:relative}.sobree-editor th,.sobree-editor td{border:none;padding:0 .08in;vertical-align:top;transition:border-color .12s ease}.sobree-editor .sobree-section-break{display:flex;align-items:center;gap:8px;margin:8px 0;color:var(--fg-subtle, #7c7764);font-size:11px;letter-spacing:.04em;text-transform:uppercase;-webkit-user-select:none;user-select:none}.sobree-editor .sobree-section-break--continuous{visibility:hidden;height:0;margin:0;padding:0;border:none;overflow:hidden;font-size:0;line-height:0}.sobree-editor .sobree-section-break:before,.sobree-editor .sobree-section-break:after{content:"";flex:1;border-top:1px dashed var(--border, #dedbd0)}.sobree-editor .sobree-section-break__label{flex:none;padding:0 6px;background:var(--bg-elevated, #fff)}.sobree-editor .sobree-textbox-frame p{line-height:1.2}.sobree-editor .paper-content p,.sobree-editor .paper-content li,.sobree-editor .paper-header p,.sobree-editor .paper-header li,.sobree-editor .paper-footer p,.sobree-editor .paper-footer li,.sobree-editor .sobree-textbox-frame p{white-space:pre-wrap}.sobree-editor .sobree-section-trailer-empty{height:0;line-height:0;font-size:0;margin:0;padding:0;overflow:hidden}.sobree-editor .sobree-textbox-frame--placeholder{border:1px solid var(--border, #c8c4b8)}.sobree-editor .sobree-textbox-frame--placeholder.sobree-textbox-frame--filled{border:none;z-index:-1}.sobree-editor img.is-selected{outline:2px solid var(--sobree-primary, #d4521f);outline-offset:2px}.sobree-image-resize-handle{position:absolute;width:16px;height:16px;background:var(--sobree-primary, #d4521f);border:2px solid #fff;border-radius:3px;cursor:nwse-resize;z-index:1000;-webkit-user-select:none;user-select:none}.paper-stack{display:flex;flex-direction:column;padding:48px;gap:28px;outline:none}.paper-row{display:flex;flex-direction:row;align-items:flex-start;gap:24px}.paper{position:relative;background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 2px #00000014,0 18px 60px #0000001f;padding-top:var(--margin-top, 25mm);padding-right:var(--margin-right, 20mm);padding-bottom:var(--margin-bottom, 25mm);padding-left:var(--margin-left, 20mm);overflow:hidden;flex:none}.paper-header,.paper-footer{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);font-size:10pt;color:#555;white-space:pre-wrap}.paper-header{top:0;min-height:var(--margin-top, 25mm);padding-top:var(--header-offset-mm, 12.7mm);padding-bottom:4mm;border-bottom:1px dashed transparent}.paper-footer{bottom:0;min-height:var(--margin-bottom, 25mm);padding-top:4mm;text-align:center;border-top:1px dashed transparent}.paper-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:1}.paper-anchors.is-empty{display:none}.paper-anchors-behind{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:0}.paper-anchors-behind.is-empty{display:none}.paper-zone-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:2}.paper-zone-anchors.is-empty{display:none}.paper-anchor{position:absolute;box-sizing:border-box;overflow:hidden}.paper-header>p,.paper-footer>p,.paper-header>ul,.paper-header>ol,.paper-footer>ul,.paper-footer>ol{margin:0}.paper-footnotes{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);bottom:var(--margin-bottom, 25mm);font-size:.85em;padding-top:.5em;border-top:1pt solid currentColor;background:#fffffff5;z-index:1;max-height:40%;overflow:hidden}.paper-footnotes.is-empty{display:none}.paper-comments{flex:0 0 70mm;max-width:70mm;font-size:.85em;padding:0 .5em;align-self:stretch;overflow-y:auto}.paper-comments.is-empty{display:none}.paper-footnotes .sobree-footnotes__list{margin:0;padding-left:1.5em}.paper-footnotes .sobree-footnotes__item{margin:.25em 0}.paper-content a{color:inherit;text-decoration:none}.paper-content{position:relative;height:100%;min-height:100px;display:flow-root}.paper-content td p:not([style*=line-height]),.paper-content td li:not([style*=line-height]),.paper-content th p:not([style*=line-height]),.paper-content th li:not([style*=line-height]){line-height:1}.paper-content td p:not([style*=margin]),.paper-content th p:not([style*=margin]){margin:0}.paper-content .sobree-hang>li{list-style:none}.paper-content .sobree-hang>li:before{display:inline-block;box-sizing:border-box;width:var(--sobree-list-hang, 0);margin-left:calc(-1 * var(--sobree-list-hang, 0));white-space:nowrap;color:var(--sobree-marker-color, currentColor);font-family:var(--sobree-marker-font, inherit);font-size:var(--sobree-marker-size, inherit)}.paper-content .sobree-hang.lst-bullet>li:before{content:var(--sobree-bullet, "•")}.paper-content .sobree-hang.lst-decimal>li:before{content:var(--mk-pre, "") counter(list-item,decimal) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-decimal-zero>li:before{content:var(--mk-pre, "") counter(list-item,decimal-leading-zero) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-latin>li:before{content:var(--mk-pre, "") counter(list-item,lower-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-latin>li:before{content:var(--mk-pre, "") counter(list-item,upper-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-roman>li:before{content:var(--mk-pre, "") counter(list-item,lower-roman) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-roman>li:before{content:var(--mk-pre, "") counter(list-item,upper-roman) var(--mk-suf, ".")}.paper-content .sobree-tab-spread{display:flex;justify-content:space-between;align-items:baseline;gap:1em;white-space:nowrap}.paper-content .sobree-tab-spread .sobree-tab-spread__before,.paper-content .sobree-tab-spread .sobree-tab-spread__after{white-space:pre-wrap;min-width:0}.paper-content table.sobree-table-bordered td,.paper-content table.sobree-table-bordered th{border:var(--table-cell-border, none);padding:0 4px}.paper-content .sobree-cols-unequal{display:flex;align-items:flex-start}.paper-content .sobree-cols-unequal .sobree-col{flex:0 0 auto}.paper-stack .paper-content,.paper-stack .paper-header,.paper-stack .paper-footer{transition:opacity .2s ease}.paper-stack.is-zone-editing .paper-content,.paper-stack.is-zone-editing .paper-header,.paper-stack.is-zone-editing .paper-footer{opacity:.2}.paper-stack.is-zone-editing .paper-header[contenteditable=true],.paper-stack.is-zone-editing .paper-footer[contenteditable=true]{opacity:1}.paper-header[contenteditable=true],.paper-footer[contenteditable=true]{outline:2px dotted var(--primary, #c96f22);outline-offset:4px;background:var(--primary-soft, #fdf6ee);color:var(--fg-strong, #14130f);border-radius:2px}
package/dist/index.d.ts CHANGED
@@ -30,7 +30,7 @@ export type { Selection, BlockRef, InlinePosition, Range } from './doc/api';
30
30
  export { PaperStack } from './paperStack/paperStack';
31
31
  export { Paper } from './paperStack/paper';
32
32
  export { PAGE_SIZES, DEFAULT_PAGE_SETUP } from './paperStack/pageSetup';
33
- export type { PageSetup, PageSizeKey, PageZoneText, VerticalAlign, Orientation, Margins } from './paperStack/pageSetup';
33
+ export type { PageSetup, PageSizeKey, PageZoneText, VerticalAlign, Orientation, Margins, } from './paperStack/pageSetup';
34
34
  export { Viewport } from './embed/viewport';
35
35
  export type { ViewportOptions } from './embed/viewport';
36
36
  export { getFloatingCorner } from './embed/floatingCorner';