superdoc 2.7.0-next.2 → 2.7.0-next.21

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.
Files changed (56) hide show
  1. package/dist/chunks/{create-super-doc-ui-C44xPZxz.cjs → create-super-doc-ui-B5nhSKqa.cjs} +11 -3
  2. package/dist/chunks/{create-super-doc-ui-BTNVc3UD.es.js → create-super-doc-ui-BJ6D4BfN.es.js} +11 -3
  3. package/dist/collaboration-upgrade-engine.cjs +1 -1
  4. package/dist/collaboration-upgrade-engine.es.js +1 -1
  5. package/dist/document-api/src/capabilities/capabilities.d.ts +3 -0
  6. package/dist/document-api/src/capabilities/html-markdown-support.d.ts +66 -0
  7. package/dist/document-api/src/content-projection/validation.d.ts +3 -0
  8. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  9. package/dist/document-api/src/contract/operation-definitions.d.ts +34 -1
  10. package/dist/document-api/src/contract/operation-registry.d.ts +20 -3
  11. package/dist/document-api/src/diff/diff.types.d.ts +19 -8
  12. package/dist/document-api/src/diff/index.d.ts +1 -1
  13. package/dist/document-api/src/get-html/get-html.d.ts +6 -6
  14. package/dist/document-api/src/get-markdown/get-markdown.d.ts +2 -4
  15. package/dist/document-api/src/index.d.ts +19 -4
  16. package/dist/document-api/src/insert/insert.d.ts +12 -2
  17. package/dist/document-api/src/project-html/project-html.d.ts +5 -0
  18. package/dist/document-api/src/project-markdown/project-markdown.d.ts +5 -0
  19. package/dist/document-api/src/ranges/ranges.types.d.ts +5 -2
  20. package/dist/document-api/src/replace/replace.d.ts +18 -6
  21. package/dist/document-api/src/types/address.d.ts +2 -0
  22. package/dist/document-api/src/types/content-projection.d.ts +129 -0
  23. package/dist/document-api/src/types/index.d.ts +1 -0
  24. package/dist/document-api/src/types/mutation-plan.types.d.ts +1 -1
  25. package/dist/document-api/src/types/receipt.d.ts +1 -1
  26. package/dist/document-api/src/types/sd-contract.d.ts +9 -3
  27. package/dist/document-api/src/types/structural-input.d.ts +18 -3
  28. package/dist/document-api/src/write/write.d.ts +8 -3
  29. package/dist/layout-engine/painters/dom/src/index.d.ts +2 -0
  30. package/dist/layout-engine/painters/dom/src/web-flow/index.d.ts +3 -0
  31. package/dist/layout-engine/painters/dom/src/web-flow/painter.d.ts +2 -0
  32. package/dist/layout-engine/painters/dom/src/web-flow/render.d.ts +8 -0
  33. package/dist/layout-engine/painters/dom/src/web-flow/styles.d.ts +10 -0
  34. package/dist/layout-engine/painters/dom/src/web-flow/types.d.ts +77 -0
  35. package/dist/public/ui-react.cjs +1 -1
  36. package/dist/public/ui-react.es.js +1 -1
  37. package/dist/public/ui.cjs +1 -1
  38. package/dist/public/ui.es.js +1 -1
  39. package/dist/style.css +10 -4
  40. package/dist/style.layered.css +10 -4
  41. package/dist/superdoc/src/composables/use-link-popover.d.ts +3 -14
  42. package/dist/superdoc/src/core/types/index.d.ts +12 -5
  43. package/dist/superdoc/src/public/index.d.cts +6 -0
  44. package/dist/superdoc/src/public/index.d.ts +1 -0
  45. package/dist/superdoc/src/public/ui/types.d.ts +1 -1
  46. package/dist/superdoc/src/public/ui.d.cts +4 -0
  47. package/dist/superdoc/src/public/ui.d.ts +1 -1
  48. package/dist/superdoc.cjs +49 -129
  49. package/dist/superdoc.es.js +49 -129
  50. package/dist/word-layout/src/index.d.ts +2 -0
  51. package/dist/word-layout/src/list-marker.d.ts +8 -0
  52. package/dist/word-layout/src/review-aware-numbering.d.ts +41 -0
  53. package/dist-cdn/style.layered.css +1 -1
  54. package/dist-cdn/superdoc.min.css +1 -1
  55. package/dist-cdn/superdoc.min.js +37 -37
  56. package/package.json +2 -2
@@ -1,19 +1,23 @@
1
- import { MutationOptions } from '../types/mutation-plan.types.js';
1
+ import { RichContentMutationOptions, WriteAdapter } from '../write/write.js';
2
2
  import { SelectionTarget, TargetLocator } from '../types/address.js';
3
3
  import { SDMutationReceipt } from '../types/sd-contract.js';
4
4
  import { SDReplaceInput } from '../types/structural-input.js';
5
- import { StoryLocator } from '../types/story.types.js';
5
+ import { BodyStoryLocator, StoryLocator } from '../types/story.types.js';
6
6
  import { BlockNodeAddress } from '../types/base.js';
7
7
  import { NestingPolicy } from '../types/placement.js';
8
8
  import { SelectionMutationAdapter } from '../selection-mutation.js';
9
- import { WriteAdapter } from '../write/write.js';
10
- /** Text replacement input: uses SelectionTarget / ref. */
11
- export type TextReplaceInput = TargetLocator & {
9
+ /** Text replacement input: uses SelectionTarget / ref, or the complete main body. */
10
+ export type TextReplaceInput = (TargetLocator & {
12
11
  target?: SelectionTarget;
13
12
  ref?: string;
14
13
  text: string;
15
14
  /** Target a specific document story (body, header, footer, footnote, endnote). */
16
15
  in?: StoryLocator;
16
+ }) | {
17
+ target: BodyStoryLocator;
18
+ text: string;
19
+ ref?: never;
20
+ in?: never;
17
21
  };
18
22
  /** HTML or Markdown replacement input for conversion and structured application. */
19
23
  export type RichContentReplaceInput = {
@@ -23,6 +27,13 @@ export type RichContentReplaceInput = {
23
27
  ref?: string;
24
28
  in?: StoryLocator;
25
29
  nestingPolicy?: NestingPolicy;
30
+ } | {
31
+ value: string;
32
+ type: 'html' | 'markdown';
33
+ target: BodyStoryLocator;
34
+ ref?: never;
35
+ in?: never;
36
+ nestingPolicy?: never;
26
37
  };
27
38
  /**
28
39
  * Input payload for the `doc.replace` operation.
@@ -33,4 +44,5 @@ export type ReplaceInput = TextReplaceInput | RichContentReplaceInput | SDReplac
33
44
  /** Returns true when the input uses the structural SDFragment shape. */
34
45
  export declare function isStructuralReplaceInput(input: ReplaceInput): input is SDReplaceInput;
35
46
  export declare function isRichContentReplaceInput(input: ReplaceInput): input is RichContentReplaceInput;
36
- export declare function executeReplace(selectionAdapter: SelectionMutationAdapter, writeAdapter: WriteAdapter, input: ReplaceInput, options?: MutationOptions): SDMutationReceipt;
47
+ export declare function validateReplaceInput(input: unknown): asserts input is ReplaceInput;
48
+ export declare function executeReplace(selectionAdapter: SelectionMutationAdapter, writeAdapter: WriteAdapter, input: ReplaceInput, options?: RichContentMutationOptions): SDMutationReceipt;
@@ -50,6 +50,8 @@ export type TextTarget = {
50
50
  segments: [TextSegment, ...TextSegment[]];
51
51
  /** Story containing this text target. Omit for body (backward compatible). */
52
52
  story?: StoryLocator;
53
+ /** Coordinate space for segment offsets. Omitted means `visible`. */
54
+ coordinateSpace?: TextCoordinateSpace;
53
55
  };
54
56
  /**
55
57
  * Block node types valid as `nodeEdge` selection anchors.
@@ -0,0 +1,129 @@
1
+ import { BlockNodeAddress, BlockNodeType } from './base.js';
2
+ import { Range, SelectionTarget, TextTarget } from './address.js';
3
+ import { StoryLocator } from './story.types.js';
4
+ import { SDDiagnostic, SDHtmlMarkdownOutcome } from './sd-contract.js';
5
+ export declare const SD_PROJECTION_FORMATS: readonly ["html", "markdown"];
6
+ export type SDProjectionFormat = (typeof SD_PROJECTION_FORMATS)[number];
7
+ export declare const SD_PROJECTION_REVIEW_MODES: readonly ["final", "original", "redline"];
8
+ export type SDProjectionReviewMode = (typeof SD_PROJECTION_REVIEW_MODES)[number];
9
+ export declare const SD_PROJECTION_STATUSES: readonly ["success", "warning", "failed"];
10
+ export type SDProjectionStatus = (typeof SD_PROJECTION_STATUSES)[number];
11
+ export declare const SD_PROJECTION_DIAGNOSTIC_CODES: readonly ["projection-normalized-construct", "projection-downgraded-construct", "projection-unsupported-construct", "projection-placeholder-emitted", "projection-annotation-omitted", "projection-numbering-unresolved", "projection-source-coverage-incomplete", "projection-scope-unsupported", "projection-limit-exceeded", "projection-revision-changed", "projection-malformed-source"];
12
+ export type SDProjectionDiagnosticCode = (typeof SD_PROJECTION_DIAGNOSTIC_CODES)[number];
13
+ export declare const SD_PROJECTION_CONSTRUCTS: readonly ["document", "source", "text", "paragraph", "emptyParagraph", "softBreak", "lineBreak", "heading", "bold", "italic", "underline", "strike", "hyperlink", "list", "listLabel", "table", "tableHeader", "tableRow", "tableCell", "colSpan", "rowSpan", "horizontalRule", "inlineCode", "codeBlock", "image", "field", "contentControl", "math", "drawing", "embeddedObject", "sectionBreak", "pageBreak", "columnBreak", "trackedChange", "comment", "scope", "placeholder"];
14
+ export type SDProjectionConstruct = (typeof SD_PROJECTION_CONSTRUCTS)[number];
15
+ export declare const SD_PROJECTION_DISPOSITIONS: readonly ["preserved", "normalized", "downgraded", "placeholder", "omitted", "rejected"];
16
+ export type SDProjectionDisposition = (typeof SD_PROJECTION_DISPOSITIONS)[number];
17
+ export type SDProjectionScope = BlockNodeAddress | SelectionTarget;
18
+ export interface SDProjectionReadInput {
19
+ in?: StoryLocator;
20
+ reviewMode?: SDProjectionReviewMode;
21
+ scope?: SDProjectionScope;
22
+ }
23
+ export interface ProjectHtmlInput extends SDProjectionReadInput {
24
+ includeSourceMap?: boolean;
25
+ }
26
+ export interface ProjectMarkdownInput extends SDProjectionReadInput {
27
+ includeSourceMap?: boolean;
28
+ }
29
+ export type SDResolvedProjectionScope = {
30
+ kind: 'story';
31
+ } | {
32
+ kind: 'block';
33
+ target: BlockNodeAddress;
34
+ } | {
35
+ kind: 'range';
36
+ target: SelectionTarget & {
37
+ coordinateSpace: 'tracked';
38
+ };
39
+ };
40
+ export type SDProjectionBlockMapEntry = {
41
+ nodeType: BlockNodeType;
42
+ output: Range;
43
+ parentBlockId?: string;
44
+ changeIds?: string[];
45
+ commentIds?: string[];
46
+ } & ({
47
+ identity: 'public';
48
+ blockId: string;
49
+ } | {
50
+ identity: 'unavailable';
51
+ identityUnavailableReason: 'positionDerivedFallback';
52
+ blockId?: never;
53
+ });
54
+ export type SDProjectionDiagnostic = Omit<SDDiagnostic, 'code' | 'construct' | 'disposition' | 'lossy' | 'source'> & {
55
+ code: SDProjectionDiagnosticCode;
56
+ construct: SDProjectionConstruct;
57
+ disposition: SDProjectionDisposition;
58
+ lossy: boolean;
59
+ source: {
60
+ story: StoryLocator;
61
+ blockId?: string;
62
+ range?: Range;
63
+ coordinateSpace?: 'tracked';
64
+ changeIds?: string[];
65
+ commentIds?: string[];
66
+ };
67
+ output?: {
68
+ format: SDProjectionFormat;
69
+ range?: Range;
70
+ };
71
+ };
72
+ export interface SDProjectionSourceMap {
73
+ version: 'sd-projection-source-map/1';
74
+ outputCoordinateSpace: 'utf16';
75
+ sourceCoordinateSpace: 'tracked';
76
+ entries: SDProjectionSourceMapEntry[];
77
+ }
78
+ export type SDProjectionSourceMapEntry = {
79
+ kind: 'text';
80
+ output: Range;
81
+ source: TextTarget & {
82
+ coordinateSpace: 'tracked';
83
+ };
84
+ blockId: string;
85
+ changeIds?: string[];
86
+ commentIds?: string[];
87
+ } | ({
88
+ kind: 'synthetic';
89
+ output: Range;
90
+ role: 'listLabel' | 'placeholder';
91
+ changeIds?: string[];
92
+ commentIds?: string[];
93
+ } & ({
94
+ identity: 'public';
95
+ blockId: string;
96
+ } | {
97
+ identity: 'unavailable';
98
+ identityUnavailableReason: 'positionDerivedFallback';
99
+ blockId?: never;
100
+ }));
101
+ export interface SDProjectionAnnotation {
102
+ kind: 'trackedChange' | 'comment';
103
+ id: string;
104
+ blockIds: string[];
105
+ sourceTarget?: TextTarget;
106
+ outputRanges: Range[];
107
+ status: 'emitted' | 'partiallyEmitted' | 'omitted';
108
+ omittedReason?: 'reviewMode' | 'unsupported';
109
+ side?: 'inserted' | 'deleted' | 'source' | 'destination' | 'formatting';
110
+ }
111
+ export interface SDContentProjectionResult<TFormat extends SDProjectionFormat = SDProjectionFormat> {
112
+ format: TFormat;
113
+ content: string;
114
+ status: SDProjectionStatus;
115
+ /** Fidelity outcome derived from the complete projection diagnostics. */
116
+ outcome: SDHtmlMarkdownOutcome;
117
+ reviewMode: SDProjectionReviewMode;
118
+ evaluatedRevision: string;
119
+ story: StoryLocator;
120
+ scope: SDResolvedProjectionScope;
121
+ lossy: boolean;
122
+ diagnostics: SDProjectionDiagnostic[];
123
+ blocks: SDProjectionBlockMapEntry[];
124
+ annotations: SDProjectionAnnotation[];
125
+ sourceMap?: SDProjectionSourceMap;
126
+ }
127
+ export declare function deriveSDHtmlMarkdownOutcome(diagnostics: readonly Pick<SDDiagnostic, 'severity' | 'lossy'>[]): SDHtmlMarkdownOutcome;
128
+ export declare function deriveSDProjectionStatus(diagnostics: readonly Pick<SDProjectionDiagnostic, 'severity' | 'lossy'>[]): SDProjectionStatus;
129
+ export declare function validateSDProjectionSourceMap(sourceMap: SDProjectionSourceMap, contentLength: number): boolean;
@@ -29,3 +29,4 @@ export * from './adapter-result.js';
29
29
  export * from './structural-input.js';
30
30
  export * from './story.types.js';
31
31
  export * from './clipboard.js';
32
+ export * from './content-projection.js';
@@ -264,4 +264,4 @@ export type PlanExecutionError = {
264
264
  stepId?: string;
265
265
  details?: unknown;
266
266
  };
267
- export type { RevisionGuardOptions, MutationOptions } from '../write/write.js';
267
+ export type { RevisionGuardOptions, MutationOptions, RichContentMutationOptions } from '../write/write.js';
@@ -9,7 +9,7 @@ export type AffectedRefRemapping = {
9
9
  from: AffectedRef;
10
10
  to: AffectedRef;
11
11
  };
12
- export type ReceiptFailureCode = 'NO_OP' | 'INVALID_TARGET' | 'TARGET_NOT_FOUND' | 'CAPABILITY_UNAVAILABLE' | 'PERMISSION_DENIED' | 'STALE_REVISION' | 'REVISION_MISMATCH' | 'MATCH_NOT_FOUND' | 'AMBIGUOUS_MATCH' | 'STYLE_CONFLICT' | 'PRECONDITION_FAILED' | 'COMMENT_CASCADE_PARTIAL' | 'INVALID_INPUT' | 'CROSS_BLOCK_MATCH' | 'SPAN_FRAGMENTED' | 'TARGET_MOVED' | 'PLAN_CONFLICT_OVERLAP' | 'INVALID_STEP_COMBINATION' | 'REVISION_CHANGED_SINCE_COMPILE' | 'INVALID_INSERTION_CONTEXT' | 'DOCUMENT_IDENTITY_CONFLICT' | 'UNSUPPORTED_ENVIRONMENT' | 'INTERNAL_ERROR' | 'PAGE_NUMBERS_NOT_MATERIALIZED' | 'INCOMPATIBLE_DEFINITIONS' | 'NO_COMPATIBLE_PREVIOUS' | 'ALREADY_CONTINUOUS' | 'NO_PREVIOUS_LIST' | 'NO_ADJACENT_SEQUENCE' | 'ALREADY_SAME_SEQUENCE' | 'LEVEL_OUT_OF_RANGE' | 'LEVEL_NOT_FOUND' | 'INVALID_NESTING' | 'INVALID_PLACEMENT' | 'EMPTY_FRAGMENT' | 'INVALID_FRAGMENT' | 'INVALID_PAYLOAD' | 'CAPABILITY_UNSUPPORTED' | 'ADDRESS_STALE' | 'DUPLICATE_ID' | 'INVALID_CONTEXT' | 'RAW_MODE_REQUIRED' | 'PRESERVE_ONLY_VIOLATION' | 'LOCK_VIOLATION' | 'TYPE_MISMATCH' | 'UNSUPPORTED_SOURCE' | 'INVALID_PACKAGE' | 'UNSUPPORTED_TEMPLATE_CONTENT';
12
+ export type ReceiptFailureCode = 'NO_OP' | 'INVALID_TARGET' | 'TARGET_NOT_FOUND' | 'CAPABILITY_UNAVAILABLE' | 'PERMISSION_DENIED' | 'STALE_REVISION' | 'REVISION_MISMATCH' | 'CHECK_MISMATCH' | 'MATCH_NOT_FOUND' | 'AMBIGUOUS_MATCH' | 'STYLE_CONFLICT' | 'PRECONDITION_FAILED' | 'COMMENT_CASCADE_PARTIAL' | 'INVALID_INPUT' | 'CROSS_BLOCK_MATCH' | 'SPAN_FRAGMENTED' | 'TARGET_MOVED' | 'PLAN_CONFLICT_OVERLAP' | 'INVALID_STEP_COMBINATION' | 'REVISION_CHANGED_SINCE_COMPILE' | 'INVALID_INSERTION_CONTEXT' | 'DOCUMENT_IDENTITY_CONFLICT' | 'UNSUPPORTED_ENVIRONMENT' | 'INTERNAL_ERROR' | 'PAGE_NUMBERS_NOT_MATERIALIZED' | 'INCOMPATIBLE_DEFINITIONS' | 'NO_COMPATIBLE_PREVIOUS' | 'ALREADY_CONTINUOUS' | 'NO_PREVIOUS_LIST' | 'NO_ADJACENT_SEQUENCE' | 'ALREADY_SAME_SEQUENCE' | 'LEVEL_OUT_OF_RANGE' | 'LEVEL_NOT_FOUND' | 'INVALID_NESTING' | 'INVALID_PLACEMENT' | 'EMPTY_FRAGMENT' | 'INVALID_FRAGMENT' | 'INVALID_PAYLOAD' | 'CAPABILITY_UNSUPPORTED' | 'ADDRESS_STALE' | 'DUPLICATE_ID' | 'INVALID_CONTEXT' | 'RAW_MODE_REQUIRED' | 'PRESERVE_ONLY_VIOLATION' | 'LOCK_VIOLATION' | 'TYPE_MISMATCH' | 'UNSUPPORTED_SOURCE' | 'INVALID_PACKAGE' | 'UNSUPPORTED_TEMPLATE_CONTENT';
13
13
  export type ReceiptFailure = {
14
14
  code: ReceiptFailureCode;
15
15
  message: string;
@@ -1,13 +1,16 @@
1
1
  import { BlockNodeAddress } from './base.js';
2
2
  import { SelectionTarget, TextAddress } from './address.js';
3
3
  import { ReceiptEffects, ReceiptSuccess, TextMutationRange } from './receipt.js';
4
- export type SDErrorCode = 'INVALID_PAYLOAD' | 'INVALID_TARGET' | 'TARGET_NOT_FOUND' | 'ADDRESS_STALE' | 'PRECONDITION_FAILED' | 'REVISION_MISMATCH' | 'INVALID_CONTEXT' | 'INVALID_NESTING' | 'INVALID_PLACEMENT' | 'DUPLICATE_ID' | 'CAPABILITY_UNSUPPORTED' | 'RAW_MODE_REQUIRED' | 'PRESERVE_ONLY_VIOLATION' | 'NO_OP' | 'UNSUPPORTED_ENVIRONMENT' | 'INTERNAL_ERROR';
4
+ import { BodyStoryLocator } from './story.types.js';
5
+ export type SDErrorCode = 'INVALID_PAYLOAD' | 'INVALID_TARGET' | 'TARGET_NOT_FOUND' | 'ADDRESS_STALE' | 'PRECONDITION_FAILED' | 'REVISION_MISMATCH' | 'CHECK_MISMATCH' | 'INVALID_CONTEXT' | 'INVALID_NESTING' | 'INVALID_PLACEMENT' | 'DUPLICATE_ID' | 'CAPABILITY_UNSUPPORTED' | 'RAW_MODE_REQUIRED' | 'PRESERVE_ONLY_VIOLATION' | 'NO_OP' | 'UNSUPPORTED_ENVIRONMENT' | 'INTERNAL_ERROR';
6
+ export declare const SD_HTML_MARKDOWN_OUTCOMES: readonly ["preserved", "preserved-with-warnings", "simplified", "rejected", "no-op", "invalid-target", "outdated"];
7
+ export type SDHtmlMarkdownOutcome = (typeof SD_HTML_MARKDOWN_OUTCOMES)[number];
5
8
  export interface SDError {
6
9
  code: SDErrorCode;
7
10
  message: string;
8
11
  path?: Array<string | number>;
9
12
  /** The target that caused the error, when available. */
10
- target?: BlockNodeAddress | TextAddress | SelectionTarget;
13
+ target?: BlockNodeAddress | TextAddress | SelectionTarget | BodyStoryLocator;
11
14
  details?: Record<string, unknown>;
12
15
  }
13
16
  /**
@@ -15,10 +18,13 @@ export interface SDError {
15
18
  *
16
19
  * - `TextAddress` (`kind: 'text'`): text-level insert/replace with block-relative offsets.
17
20
  * - `BlockNodeAddress` (`kind: 'block'`): structural insert/replace targeting a whole block.
21
+ * - `BodyStoryLocator` (`kind: 'story'`): explicit complete-main-body replacement.
18
22
  */
19
- export type MutationResolutionTarget = TextAddress | BlockNodeAddress;
23
+ export type MutationResolutionTarget = TextAddress | BlockNodeAddress | BodyStoryLocator;
20
24
  export interface SDMutationReceipt {
21
25
  success: boolean;
26
+ /** Rich HTML/Markdown fidelity outcome, when this receipt came from a rich write. */
27
+ outcome?: SDHtmlMarkdownOutcome;
22
28
  failure?: SDError;
23
29
  evaluatedRevision?: {
24
30
  before: string;
@@ -2,7 +2,7 @@ import { BlockNodeAddress } from './base.js';
2
2
  import { SelectionTarget } from './address.js';
3
3
  import { SDFragment } from './fragment.js';
4
4
  import { Placement, NestingPolicy } from './placement.js';
5
- import { StoryLocator } from './story.types.js';
5
+ import { BodyStoryLocator, StoryLocator } from './story.types.js';
6
6
  /** Structural shape for the insert operation. */
7
7
  export interface SDInsertInput {
8
8
  /** Optional insertion target. When omitted, inserts at the end of the document. */
@@ -27,14 +27,29 @@ type StructuralReplaceLocator = {
27
27
  ref: string;
28
28
  /** Target to replace. BlockNodeAddress replaces the entire block; SelectionTarget replaces a contiguous selection. */
29
29
  target?: undefined;
30
+ } | {
31
+ /** Replace the complete main body while preserving the destination DOCX package. */
32
+ target: BodyStoryLocator;
33
+ ref?: undefined;
30
34
  };
31
- /** Structural shape for the replace operation. */
32
- export type SDReplaceInput = StructuralReplaceLocator & {
35
+ type StructuralReplaceContent = {
33
36
  /** Structural content to replace with. */
34
37
  content: SDFragment;
38
+ };
39
+ /** Structural shape for the replace operation. */
40
+ export type SDReplaceInput = (Exclude<StructuralReplaceLocator, {
41
+ target: BodyStoryLocator;
42
+ }> & StructuralReplaceContent & {
35
43
  /** Target a specific document story (body, header, footer, footnote, endnote). */
36
44
  in?: StoryLocator;
37
45
  /** Nesting policy. Defaults to { tables: 'forbid' }. */
38
46
  nestingPolicy?: NestingPolicy;
47
+ }) | {
48
+ /** Replace the complete main body while preserving the destination DOCX package. */
49
+ target: BodyStoryLocator;
50
+ content: SDFragment;
51
+ ref?: never;
52
+ in?: never;
53
+ nestingPolicy?: never;
39
54
  };
40
55
  export {};
@@ -2,6 +2,7 @@ import { TextMutationReceipt, SDMutationReceipt } from '../types/index.js';
2
2
  import { InsertInput } from '../insert/insert.js';
3
3
  import { ReplaceInput } from '../replace/replace.js';
4
4
  import { StoryLocator } from '../types/story.types.js';
5
+ import { SDHtmlMarkdownCheckGuard } from '../capabilities/html-markdown-support.js';
5
6
  export type ChangeMode = 'direct' | 'tracked';
6
7
  /**
7
8
  * Shared semantic validation for the `changeMode` mutation option.
@@ -40,6 +41,10 @@ export interface MutationOptions extends RevisionGuardOptions {
40
41
  */
41
42
  dryRun?: boolean;
42
43
  }
44
+ export interface RichContentMutationOptions extends MutationOptions {
45
+ /** Guard returned by `doc.capabilities.check` for an exact rich write. */
46
+ supportCheck?: SDHtmlMarkdownCheckGuard;
47
+ }
43
48
  /**
44
49
  * Text insertion request: target-less insert at document end.
45
50
  *
@@ -65,9 +70,9 @@ export type WriteRequest = InsertWriteRequest;
65
70
  export interface WriteAdapter {
66
71
  write(request: InsertWriteRequest, options?: MutationOptions): TextMutationReceipt;
67
72
  /** Structured insert for SDFragment or markdown/html content. Returns SDMutationReceipt. */
68
- insertStructured(input: InsertInput, options?: MutationOptions): SDMutationReceipt;
73
+ insertStructured(input: InsertInput, options?: RichContentMutationOptions): SDMutationReceipt;
69
74
  /** Structured replace for SDFragment or markdown/html content. Returns SDMutationReceipt. */
70
- replaceStructured(input: ReplaceInput, options?: MutationOptions): SDMutationReceipt;
75
+ replaceStructured(input: ReplaceInput, options?: RichContentMutationOptions): SDMutationReceipt;
71
76
  }
72
- export declare function normalizeMutationOptions(options?: MutationOptions): MutationOptions;
77
+ export declare function normalizeMutationOptions(options?: MutationOptions | RichContentMutationOptions, supportCheckOperation?: 'insert' | 'replace'): RichContentMutationOptions;
73
78
  export declare function executeWrite(adapter: WriteAdapter, request: InsertWriteRequest, options?: MutationOptions): TextMutationReceipt;
@@ -3,6 +3,8 @@ import { PageStyles } from './styles.js';
3
3
  import { PositionValidationOptions, PositionValidationSummary } from './pm-position-validation.js';
4
4
  import { DomPainterInput, PageDecorationProvider, PaintSnapshot, PositionMapping, FlowMode } from './renderer.js';
5
5
  import { DomPainterPersistentPageInput } from './persistent-page-surface.js';
6
+ export { createWebFlowPainter, ensureWebFlowStyles, WEB_FLOW_CLASS_NAMES } from './web-flow/index.js';
7
+ export type { WebFlowAppliedPaint, WebFlowDomBinding, WebFlowPaintCommand, WebFlowPaintItem, WebFlowPaintSnapshot, WebFlowPaintTransaction, WebFlowPainterHandle, WebFlowPainterOptions, WebFlowPaintWorkSummary, WebFlowStableDomKey, } from './web-flow/index.js';
6
8
  export { DOM_CLASS_NAMES } from './constants.js';
7
9
  export type { DomClassName } from './constants.js';
8
10
  export { ensureDocumentSurfaceStyles } from './styles.js';
@@ -0,0 +1,3 @@
1
+ export { createWebFlowPainter } from './painter.js';
2
+ export { ensureWebFlowStyles, WEB_FLOW_CLASS_NAMES } from './styles.js';
3
+ export type { WebFlowAppliedPaint, WebFlowDomBinding, WebFlowPaintCommand, WebFlowPaintItem, WebFlowPaintSnapshot, WebFlowPaintTransaction, WebFlowPainterHandle, WebFlowPainterOptions, WebFlowPaintWorkSummary, WebFlowStableDomKey, } from './types.js';
@@ -0,0 +1,2 @@
1
+ import { WebFlowPainterHandle, WebFlowPainterOptions } from './types.js';
2
+ export declare function createWebFlowPainter(mount: HTMLElement, options?: WebFlowPainterOptions): WebFlowPainterHandle;
@@ -0,0 +1,8 @@
1
+ import { FlowBlock } from '../../../../contracts/src/index.js';
2
+ import { WebFlowPaintItem, WebFlowPainterOptions } from './types.js';
3
+ export declare function doesWebFlowBlockProduceDom(block: FlowBlock): boolean;
4
+ export declare function renderWebFlowItem(item: WebFlowPaintItem, doc: Document, options: WebFlowPainterOptions): HTMLElement | null;
5
+ /** Identity-only signature for deciding whether a retained node needs dataset rebasing. */
6
+ export declare function webFlowItemIdentityFingerprint(item: WebFlowPaintItem): string;
7
+ /** Rebase canonical identity datasets without replacing an unchanged retained node. */
8
+ export declare function rebaseWebFlowItemNode(node: HTMLElement, previous: WebFlowPaintItem, next: WebFlowPaintItem): () => void;
@@ -0,0 +1,10 @@
1
+ export declare const WEB_FLOW_CLASS_NAMES: {
2
+ readonly root: "superdoc-web-flow";
3
+ readonly block: "superdoc-web-flow-block";
4
+ readonly paragraph: "superdoc-web-flow-paragraph";
5
+ readonly run: "superdoc-web-flow-run";
6
+ readonly listMarker: "superdoc-web-flow-list-marker";
7
+ readonly table: "superdoc-web-flow-table";
8
+ readonly diagnostic: "superdoc-web-flow-diagnostic";
9
+ };
10
+ export declare function ensureWebFlowStyles(doc: Document): void;
@@ -0,0 +1,77 @@
1
+ import { FlowBlock, LayoutSourceIdentity } from '../../../../contracts/src/index.js';
2
+ /** Opaque adapter-issued identity. The painter never derives this value from DOM or block ids. */
3
+ export type WebFlowStableDomKey = string;
4
+ export interface WebFlowPaintItem {
5
+ readonly stableDomKey: WebFlowStableDomKey;
6
+ readonly renderFingerprint: string;
7
+ readonly block: FlowBlock;
8
+ readonly layoutEpoch?: number;
9
+ readonly layoutIdentities?: readonly LayoutSourceIdentity[];
10
+ readonly editable?: boolean;
11
+ }
12
+ export type WebFlowPaintCommand = {
13
+ readonly kind: 'replace-all';
14
+ readonly epoch: number;
15
+ readonly items: readonly WebFlowPaintItem[];
16
+ } | {
17
+ readonly kind: 'splice';
18
+ readonly expectedBaseEpoch: number;
19
+ readonly epoch: number;
20
+ readonly storyKey: string;
21
+ readonly expectedRemovedKeys: readonly WebFlowStableDomKey[];
22
+ readonly expectedLeftKey: WebFlowStableDomKey | null;
23
+ readonly expectedRightKey: WebFlowStableDomKey | null;
24
+ readonly items: readonly WebFlowPaintItem[];
25
+ /** Identity-only updates for retained nodes downstream of a structural splice. */
26
+ readonly retainedRebases?: readonly WebFlowPaintItem[];
27
+ };
28
+ export interface WebFlowPaintWorkSummary {
29
+ readonly kind: WebFlowPaintCommand['kind'];
30
+ readonly retainedNodes: number;
31
+ readonly createdNodes: number;
32
+ readonly removedNodes: number;
33
+ readonly rebasedNodes: number;
34
+ readonly touchedItems: number;
35
+ }
36
+ export interface WebFlowDomBinding {
37
+ readonly key: WebFlowStableDomKey;
38
+ readonly renderFingerprint: string;
39
+ readonly blockId: string;
40
+ readonly node: HTMLElement;
41
+ }
42
+ export interface WebFlowPaintSnapshot {
43
+ readonly epoch: number | null;
44
+ readonly version: number;
45
+ readonly bindings: readonly WebFlowDomBinding[];
46
+ }
47
+ export interface WebFlowAppliedPaint {
48
+ readonly work: WebFlowPaintWorkSummary;
49
+ /** Bindings directly owned by this command; localized splices never scan the retained root. */
50
+ readonly touchedBindings: readonly WebFlowDomBinding[];
51
+ /** Bindings whose DOM node or retained identity changed in this command. */
52
+ readonly changedBindings: readonly WebFlowDomBinding[];
53
+ }
54
+ export interface WebFlowPaintTransaction {
55
+ readonly command: WebFlowPaintCommand;
56
+ /** Installs the candidate synchronously. The caller must then finalize or roll it back. */
57
+ apply(): WebFlowAppliedPaint;
58
+ /** Publishes the applied state and releases the rollback journal. */
59
+ finalize(): WebFlowAppliedPaint;
60
+ /** Restores the exact pre-apply DOM and retained state. */
61
+ rollback(): void;
62
+ }
63
+ export interface WebFlowPainterHandle {
64
+ prepare(command: WebFlowPaintCommand): WebFlowPaintTransaction;
65
+ snapshot(): WebFlowPaintSnapshot;
66
+ /** Rebuilds the last committed derived DOM after an externally owned mutation. */
67
+ restoreCommittedDomAfterUnownedMutation(): WebFlowPaintSnapshot;
68
+ dispose(): void;
69
+ }
70
+ export interface WebFlowPainterOptions {
71
+ readonly resolvePhysical?: (cssFontFamily: string, face: {
72
+ weight: '400' | '700';
73
+ style: 'normal' | 'italic';
74
+ }) => string;
75
+ /** Fires synchronously when the mutation observer first detects unowned DOM. */
76
+ readonly onUnownedMutation?: (kind: 'text' | 'dom') => void;
77
+ }
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-C44xPZxz.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-B5nhSKqa.cjs");
3
3
  let react = require("react");
4
4
  //#region src/public/ui/react.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BTNVc3UD.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BJ6D4BfN.es.js";
2
2
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
3
3
  //#region src/public/ui/react.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-C44xPZxz.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-B5nhSKqa.cjs");
3
3
  exports.BUILT_IN_COMMAND_IDS = require_create_super_doc_ui.BUILT_IN_COMMAND_IDS;
4
4
  exports.createSuperDocUI = require_create_super_doc_ui.createSuperDocUI;
5
5
  exports.shallowEqual = require_create_super_doc_ui.shallowEqual;
@@ -1,2 +1,2 @@
1
- import { n as shallowEqual, r as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-BTNVc3UD.es.js";
1
+ import { n as shallowEqual, r as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-BJ6D4BfN.es.js";
2
2
  export { BUILT_IN_COMMAND_IDS, createSuperDocUI, shallowEqual };
package/dist/style.css CHANGED
@@ -185,14 +185,14 @@
185
185
  --sd-comments-selection-background: #1354ff55;
186
186
 
187
187
  /* Styles: tracked changes — old names honored via fallback */
188
- --sd-tracked-changes-insert-background: var(--sd-track-insert-bg, #1f6feb22);
188
+ --sd-tracked-changes-insert-background: var(--sd-track-insert-bg);
189
189
  --sd-tracked-changes-insert-border: var(--sd-track-insert-border, #1f6feb);
190
190
  --sd-tracked-changes-insert-border-width: 1px;
191
191
  --sd-tracked-changes-insert-text: currentColor;
192
192
  --sd-tracked-changes-insert-decoration-line: none;
193
193
  --sd-tracked-changes-insert-decoration-thickness: 1px;
194
194
  --sd-tracked-changes-insert-underline-offset: 0px;
195
- --sd-tracked-changes-delete-background: var(--sd-track-delete-bg, #cb0e4722);
195
+ --sd-tracked-changes-delete-background: var(--sd-track-delete-bg);
196
196
  --sd-tracked-changes-delete-border: var(--sd-track-delete-border, #cb0e47);
197
197
  --sd-tracked-changes-delete-border-width: 1px;
198
198
  --sd-tracked-changes-delete-text: currentColor;
@@ -206,8 +206,14 @@
206
206
  --sd-tracked-changes-move-from-background: var(--sd-tracked-changes-semantic-background, #00853d22);
207
207
  --sd-tracked-changes-move-from-background-focused: var(--sd-tracked-changes-semantic-background-focused, #00853d44);
208
208
  --sd-tracked-changes-move-from-text: var(--sd-tracked-changes-semantic-color, #00853d);
209
- --sd-tracked-changes-insert-background-focused: #1f6feb44;
210
- --sd-tracked-changes-delete-background-focused: #cb0e4744;
209
+ --sd-tracked-changes-insert-background-focused: var(
210
+ --sd-track-insert-bg-focused,
211
+ var(--sd-tracked-changes-insert-background, var(--sd-track-insert-bg, #1f6feb44))
212
+ );
213
+ --sd-tracked-changes-delete-background-focused: var(
214
+ --sd-track-delete-bg-focused,
215
+ var(--sd-tracked-changes-delete-background, var(--sd-track-delete-bg, #cb0e4744))
216
+ );
211
217
  --sd-tracked-changes-format-background-focused: #ffd70033;
212
218
 
213
219
  /* Styles: tracked table-structure changes (whole-table / table-row
@@ -185,14 +185,14 @@
185
185
  --sd-comments-selection-background: #1354ff55;
186
186
 
187
187
  /* Styles: tracked changes — old names honored via fallback */
188
- --sd-tracked-changes-insert-background: var(--sd-track-insert-bg, #1f6feb22);
188
+ --sd-tracked-changes-insert-background: var(--sd-track-insert-bg);
189
189
  --sd-tracked-changes-insert-border: var(--sd-track-insert-border, #1f6feb);
190
190
  --sd-tracked-changes-insert-border-width: 1px;
191
191
  --sd-tracked-changes-insert-text: currentColor;
192
192
  --sd-tracked-changes-insert-decoration-line: none;
193
193
  --sd-tracked-changes-insert-decoration-thickness: 1px;
194
194
  --sd-tracked-changes-insert-underline-offset: 0px;
195
- --sd-tracked-changes-delete-background: var(--sd-track-delete-bg, #cb0e4722);
195
+ --sd-tracked-changes-delete-background: var(--sd-track-delete-bg);
196
196
  --sd-tracked-changes-delete-border: var(--sd-track-delete-border, #cb0e47);
197
197
  --sd-tracked-changes-delete-border-width: 1px;
198
198
  --sd-tracked-changes-delete-text: currentColor;
@@ -206,8 +206,14 @@
206
206
  --sd-tracked-changes-move-from-background: var(--sd-tracked-changes-semantic-background, #00853d22);
207
207
  --sd-tracked-changes-move-from-background-focused: var(--sd-tracked-changes-semantic-background-focused, #00853d44);
208
208
  --sd-tracked-changes-move-from-text: var(--sd-tracked-changes-semantic-color, #00853d);
209
- --sd-tracked-changes-insert-background-focused: #1f6feb44;
210
- --sd-tracked-changes-delete-background-focused: #cb0e4744;
209
+ --sd-tracked-changes-insert-background-focused: var(
210
+ --sd-track-insert-bg-focused,
211
+ var(--sd-tracked-changes-insert-background, var(--sd-track-insert-bg, #1f6feb44))
212
+ );
213
+ --sd-tracked-changes-delete-background-focused: var(
214
+ --sd-track-delete-bg-focused,
215
+ var(--sd-tracked-changes-delete-background, var(--sd-track-delete-bg, #cb0e4744))
216
+ );
211
217
  --sd-tracked-changes-format-background-focused: #ffd70033;
212
218
 
213
219
  /* Styles: tracked table-structure changes (whole-table / table-row
@@ -127,10 +127,9 @@ export type HyperlinkGetResult = {
127
127
  };
128
128
  /**
129
129
  * Result of `doc.bookmarks.get()` as read here (Document API `BookmarkInfo`).
130
- * `range.from.blockId` is the bookmark's `w14:paraId`, used to find/reveal
131
- * the target paragraph. `address.story` is populated for non-body
132
- * bookmarks (omitted for body) used to scope this fix to body targets,
133
- * since `revealBodyTarget`/`pageIndexForBodyTarget` are body-only.
130
+ * `range.from.blockId` identifies the model paragraph sent to the viewport.
131
+ * `address.story` is populated for non-body bookmarks (omitted for body),
132
+ * which keeps anchor navigation scoped to body targets.
134
133
  */
135
134
  export type BookmarkGetResult = {
136
135
  address?: {
@@ -184,16 +183,6 @@ export type LinkPopoverDocumentApi = {
184
183
  }) => BookmarkGetResult | Promise<BookmarkGetResult | null | undefined> | null | undefined;
185
184
  } | null | undefined;
186
185
  };
187
- /**
188
- * Result of `activeEditor.pageMetrics.revealBodyTarget()` as read here
189
- * (`V2EditorHostRevealBodyTargetResult`). Only available in editing/
190
- * suggesting mode — the host rejects with `editing-not-mounted` in
191
- * viewing mode.
192
- */
193
- export type RevealBodyTargetResult = {
194
- status?: "rejected" | "revealed" | undefined;
195
- reason?: string | undefined;
196
- };
197
186
  /**
198
187
  * The `v2-link-click` payload the shell relays from the v2 host's
199
188
  * `onLinkClick` callback.
@@ -2543,7 +2543,11 @@ export type ViewLayout = 'print' | 'web';
2543
2543
  * Mirrors OOXML document view settings.
2544
2544
  */
2545
2545
  export interface ViewOptions {
2546
- /** Document view layout (OOXML ST_View compatible). */
2546
+ /**
2547
+ * Document view layout (OOXML ST_View compatible). In the browser editor,
2548
+ * `'web'` selects the retained semantic DOM surface. Browser normal flow
2549
+ * rewraps content as the editor container changes width.
2550
+ */
2547
2551
  layout?: ViewLayout;
2548
2552
  }
2549
2553
  export interface ExportParams {
@@ -3378,6 +3382,11 @@ export interface Config {
3378
3382
  experimental?: {
3379
3383
  unifiedHistory?: boolean;
3380
3384
  v2Host?: boolean;
3385
+ /**
3386
+ * Temporary V2 web-surface rollout control. The value is snapshotted at
3387
+ * mount and changing it requires a remount. This is not a stable renderer API.
3388
+ */
3389
+ v2WebSurface?: 'dense-control' | 'retained-dom';
3381
3390
  /**
3382
3391
  * Derived-invalidation deferral for direct single-paragraph edits (v2
3383
3392
  * engine only). Field display text settles off the keystroke path under
@@ -3605,10 +3614,8 @@ export interface Config {
3605
3614
  */
3606
3615
  workerStartupTimeoutMs?: number;
3607
3616
  /**
3608
- * Opt-in toggle for the layout engine. Auto-disabled when web layout is
3609
- * requested without `layoutEngineOptions.flowMode === 'semantic'`; the
3610
- * loader logs a warning and falls back to the legacy ProseMirror render
3611
- * path in that case.
3617
+ * Compatibility toggle retained for existing configurations. V2 always
3618
+ * uses the OOXML kernel; `viewOptions.layout` selects the mounted renderer.
3612
3619
  */
3613
3620
  useLayoutEngine?: boolean;
3614
3621
  /**
@@ -22,6 +22,9 @@ import type { ContextMenuSection as __Cjs_ContextMenuSection } from './index.js'
22
22
  import type { ContextMenuSelectContext as __Cjs_ContextMenuSelectContext } from './index.js' with { "resolution-mode": "import" };
23
23
  import type { ContextMenuSelectPayload as __Cjs_ContextMenuSelectPayload } from './index.js' with { "resolution-mode": "import" };
24
24
  import type { ContextMenuSelectReadiness as __Cjs_ContextMenuSelectReadiness } from './index.js' with { "resolution-mode": "import" };
25
+ import type { DiffApplyOperationReceipt as __Cjs_DiffApplyOperationReceipt } from './index.js' with { "resolution-mode": "import" };
26
+ import type { DiffApplyResult as __Cjs_DiffApplyResult } from './index.js' with { "resolution-mode": "import" };
27
+ import type { DiffApplyReviewItem as __Cjs_DiffApplyReviewItem } from './index.js' with { "resolution-mode": "import" };
25
28
  import type { DirectSurfaceRequest as __Cjs_DirectSurfaceRequest } from './index.js' with { "resolution-mode": "import" };
26
29
  import type { DocRange as __Cjs_DocRange } from './index.js' with { "resolution-mode": "import" };
27
30
  import type { Document as __Cjs_Document } from './index.js' with { "resolution-mode": "import" };
@@ -218,6 +221,9 @@ export type { __Cjs_ContextMenuSelectPayload as ContextMenuSelectPayload };
218
221
  export type { __Cjs_ContextMenuSelectReadiness as ContextMenuSelectReadiness };
219
222
  export declare const createTheme: typeof import('./index.js', { with: { "resolution-mode": "import" } }).createTheme;
220
223
  export declare const defineSuperDocExtension: typeof import('./index.js', { with: { "resolution-mode": "import" } }).defineSuperDocExtension;
224
+ export type { __Cjs_DiffApplyOperationReceipt as DiffApplyOperationReceipt };
225
+ export type { __Cjs_DiffApplyResult as DiffApplyResult };
226
+ export type { __Cjs_DiffApplyReviewItem as DiffApplyReviewItem };
221
227
  export type { __Cjs_DirectSurfaceRequest as DirectSurfaceRequest };
222
228
  export type { __Cjs_DocRange as DocRange };
223
229
  export type { __Cjs_Document as Document };