@beyondwork/docx-react-component 1.0.38 → 1.0.39
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/package.json +41 -31
- package/src/api/public-types.ts +183 -6
- package/src/core/commands/table-structure-commands.ts +31 -2
- package/src/core/commands/text-commands.ts +122 -2
- package/src/io/docx-session.ts +1 -0
- package/src/io/export/serialize-numbering.ts +42 -8
- package/src/io/export/serialize-paragraph-formatting.ts +152 -0
- package/src/io/export/serialize-run-formatting.ts +90 -0
- package/src/io/export/serialize-styles.ts +212 -0
- package/src/io/ooxml/parse-fields.ts +10 -3
- package/src/io/ooxml/parse-numbering.ts +41 -1
- package/src/io/ooxml/parse-paragraph-formatting.ts +188 -0
- package/src/io/ooxml/parse-run-formatting.ts +129 -0
- package/src/io/ooxml/parse-styles.ts +31 -0
- package/src/io/ooxml/xml-attr-helpers.ts +60 -0
- package/src/io/ooxml/xml-element.ts +19 -0
- package/src/model/canonical-document.ts +83 -3
- package/src/runtime/collab/event-types.ts +165 -0
- package/src/runtime/collab/index.ts +22 -0
- package/src/runtime/collab/remote-cursor-awareness.ts +93 -0
- package/src/runtime/collab/runtime-collab-sync.ts +273 -0
- package/src/runtime/document-runtime.ts +134 -18
- package/src/runtime/layout/index.ts +2 -0
- package/src/runtime/layout/inert-layout-facet.ts +2 -0
- package/src/runtime/layout/layout-engine-instance.ts +69 -2
- package/src/runtime/layout/layout-invalidation.ts +14 -5
- package/src/runtime/layout/page-graph.ts +36 -0
- package/src/runtime/layout/paginate-paragraph-lines.ts +128 -0
- package/src/runtime/layout/paginated-layout-engine.ts +342 -28
- package/src/runtime/layout/project-block-fragments.ts +154 -20
- package/src/runtime/layout/public-facet.ts +40 -1
- package/src/runtime/layout/resolve-page-fields.ts +70 -0
- package/src/runtime/layout/resolve-page-previews.ts +185 -0
- package/src/runtime/layout/resolved-formatting-state.ts +30 -26
- package/src/runtime/layout/table-render-plan.ts +21 -1
- package/src/runtime/numbering-prefix.ts +5 -0
- package/src/runtime/paragraph-style-resolver.ts +194 -0
- package/src/runtime/render/render-kernel.ts +5 -1
- package/src/runtime/resolved-numbering-geometry.ts +9 -1
- package/src/runtime/surface-projection.ts +129 -9
- package/src/runtime/table-schema.ts +11 -0
- package/src/ui/WordReviewEditor.tsx +285 -5
- package/src/ui/editor-command-bag.ts +4 -0
- package/src/ui/editor-runtime-boundary.ts +16 -0
- package/src/ui/editor-shell-view.tsx +4 -0
- package/src/ui/editor-surface-controller.tsx +9 -1
- package/src/ui/headless/chrome-registry.ts +34 -5
- package/src/ui/headless/scoped-chrome-policy.ts +29 -0
- package/src/ui-tailwind/chrome/review-queue-bar.tsx +2 -14
- package/src/ui-tailwind/chrome/role-action-sets.ts +14 -8
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +7 -10
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +11 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +11 -0
- package/src/ui-tailwind/chrome/tw-table-border-picker.tsx +245 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +101 -21
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +284 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +5 -1
- package/src/ui-tailwind/chrome-overlay/index.ts +0 -6
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +27 -17
- package/src/ui-tailwind/editor-surface/page-slice-util.ts +15 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +28 -3
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +389 -0
- package/src/ui-tailwind/editor-surface/pm-schema.ts +40 -2
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +144 -62
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +179 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +559 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +224 -78
- package/src/ui-tailwind/editor-surface/tw-table-bands.css +61 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +19 -0
- package/src/ui-tailwind/index.ts +1 -5
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +122 -1
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +36 -3
- package/src/ui-tailwind/tw-review-workspace.tsx +132 -54
- package/src/runtime/collab-review-sync.ts +0 -254
- package/src/ui-tailwind/chrome-overlay/tw-workspace-view-switcher.tsx +0 -95
- package/src/ui-tailwind/editor-surface/pm-collab-plugins.ts +0 -40
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { MAIN_STORY_TARGET } from "../../core/selection/mapping.ts";
|
|
17
|
+
import { recordPerfSample } from "../../ui-tailwind/editor-surface/perf-probe.ts";
|
|
17
18
|
import type { EditorStoryTarget } from "../../api/public-types";
|
|
18
19
|
import type {
|
|
19
20
|
PublicPageNode,
|
|
@@ -165,6 +166,7 @@ export function createRenderKernel(input: CreateRenderKernelInput): RenderKernel
|
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
function buildFrame(options?: RenderFrameQueryOptions): RenderFrame {
|
|
169
|
+
const t0 = typeof performance !== "undefined" ? performance.now() : 0;
|
|
168
170
|
const activeStory = options?.story ?? getActiveStory();
|
|
169
171
|
const measurementFidelity = facet.getMeasurementFidelity();
|
|
170
172
|
const rawPages = facet.getPages();
|
|
@@ -211,7 +213,7 @@ export function createRenderKernel(input: CreateRenderKernelInput): RenderKernel
|
|
|
211
213
|
? Number(extractRevisionFromPageId(filteredPages[0].pageId))
|
|
212
214
|
: 0;
|
|
213
215
|
|
|
214
|
-
|
|
216
|
+
const frame: RenderFrame = {
|
|
215
217
|
revision: Number.isFinite(revision) ? revision : 0,
|
|
216
218
|
measurementFidelity,
|
|
217
219
|
activeStory,
|
|
@@ -220,6 +222,8 @@ export function createRenderKernel(input: CreateRenderKernelInput): RenderKernel
|
|
|
220
222
|
decorationIndex,
|
|
221
223
|
anchorIndex,
|
|
222
224
|
};
|
|
225
|
+
if (t0 > 0) recordPerfSample("render.frame_build", performance.now() - t0);
|
|
226
|
+
return frame;
|
|
223
227
|
}
|
|
224
228
|
|
|
225
229
|
return {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
CanonicalRunFormatting,
|
|
2
3
|
NumberingCatalog,
|
|
3
4
|
NumberingLevelDefinition,
|
|
4
5
|
NumberingLevelOverrideDefinition,
|
|
@@ -27,6 +28,7 @@ export interface ResolvedNumberingGeometry {
|
|
|
27
28
|
firstLine?: number;
|
|
28
29
|
hanging?: number;
|
|
29
30
|
};
|
|
31
|
+
markerRunProperties?: CanonicalRunFormatting;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export interface ResolvedNumberingDefinitionSet {
|
|
@@ -67,7 +69,7 @@ export function resolveNumberingDefinitionSet(
|
|
|
67
69
|
abstractDefinition,
|
|
68
70
|
effectiveLevels,
|
|
69
71
|
effectiveLevel,
|
|
70
|
-
geometry: resolveNumberingGeometry(effectiveLevel.paragraphGeometry, paragraph),
|
|
72
|
+
geometry: resolveNumberingGeometry(effectiveLevel.paragraphGeometry, paragraph, effectiveLevel.runProperties),
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -110,6 +112,8 @@ function mergeLevelDefinition(
|
|
|
110
112
|
base?.paragraphGeometry,
|
|
111
113
|
override?.paragraphGeometry,
|
|
112
114
|
);
|
|
115
|
+
const runProperties = override?.runProperties ?? base?.runProperties;
|
|
116
|
+
const restartAfterLevel = override?.restartAfterLevel ?? base?.restartAfterLevel;
|
|
113
117
|
|
|
114
118
|
return {
|
|
115
119
|
level,
|
|
@@ -124,6 +128,8 @@ function mergeLevelDefinition(
|
|
|
124
128
|
: {}),
|
|
125
129
|
...(override?.suffix ?? base?.suffix ? { suffix: override?.suffix ?? base?.suffix } : {}),
|
|
126
130
|
...(paragraphGeometry ? { paragraphGeometry } : {}),
|
|
131
|
+
...(runProperties ? { runProperties } : {}),
|
|
132
|
+
...(restartAfterLevel !== undefined ? { restartAfterLevel } : {}),
|
|
127
133
|
};
|
|
128
134
|
}
|
|
129
135
|
|
|
@@ -179,6 +185,7 @@ function mergeLevelParagraphGeometry(
|
|
|
179
185
|
function resolveNumberingGeometry(
|
|
180
186
|
levelGeometry: NumberingLevelParagraphGeometry | undefined,
|
|
181
187
|
paragraph: Pick<ParagraphNode, "spacing" | "indentation" | "tabStops"> | undefined,
|
|
188
|
+
levelRunProperties: CanonicalRunFormatting | undefined,
|
|
182
189
|
): ResolvedNumberingGeometry {
|
|
183
190
|
const spacing = mergeParagraphSpacing(levelGeometry?.spacing, paragraph?.spacing);
|
|
184
191
|
const indentation = mergeParagraphIndentation(levelGeometry?.indentation, paragraph?.indentation);
|
|
@@ -197,6 +204,7 @@ function resolveNumberingGeometry(
|
|
|
197
204
|
...(tabStops && tabStops.length > 0 ? { tabStops } : {}),
|
|
198
205
|
...(markerLane ? { markerLane } : {}),
|
|
199
206
|
...(textColumn ? { textColumn } : {}),
|
|
207
|
+
...(levelRunProperties ? { markerRunProperties: levelRunProperties } : {}),
|
|
200
208
|
};
|
|
201
209
|
}
|
|
202
210
|
|
|
@@ -46,6 +46,12 @@ import {
|
|
|
46
46
|
resolveSectionVariants,
|
|
47
47
|
} from "./story-context.ts";
|
|
48
48
|
import { resolveTableStyleResolution } from "./table-style-resolver.ts";
|
|
49
|
+
import {
|
|
50
|
+
resolveEffectiveParagraphFormatting,
|
|
51
|
+
resolveEffectiveRunFormatting,
|
|
52
|
+
resolveNumberingMarkerRunFormatting,
|
|
53
|
+
} from "./paragraph-style-resolver.ts";
|
|
54
|
+
import type { CanonicalParagraphFormatting, CanonicalRunFormatting } from "../model/canonical-document.ts";
|
|
49
55
|
|
|
50
56
|
interface ParagraphAccumulator {
|
|
51
57
|
blockId: string;
|
|
@@ -57,6 +63,7 @@ interface ParagraphAccumulator {
|
|
|
57
63
|
numberingPrefix?: string;
|
|
58
64
|
numberingSuffix?: "tab" | "space" | "nothing";
|
|
59
65
|
resolvedNumbering?: Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>["resolvedNumbering"];
|
|
66
|
+
resolvedParagraphFormatting?: CanonicalParagraphFormatting;
|
|
60
67
|
contextualSpacing?: boolean;
|
|
61
68
|
segments: SurfaceInlineSegment[];
|
|
62
69
|
}
|
|
@@ -341,6 +348,16 @@ function createTableBlock(
|
|
|
341
348
|
}
|
|
342
349
|
const resolvedCell = resolvedRow?.cells[cellIndex];
|
|
343
350
|
const cellBorders = resolveCellBorderStyles(resolvedCell?.borders ?? cell.borders);
|
|
351
|
+
// R2a: project the resolved conditional-format regions into CSS class
|
|
352
|
+
// names so the NodeView can paint band colors via theme vars instead of
|
|
353
|
+
// inline styles. Direct shading overrides still win at render time.
|
|
354
|
+
const bandClasses =
|
|
355
|
+
resolvedCell?.activeConditionalRegions &&
|
|
356
|
+
resolvedCell.activeConditionalRegions.length > 0
|
|
357
|
+
? resolvedCell.activeConditionalRegions
|
|
358
|
+
.map((region) => `band-${region}`)
|
|
359
|
+
.join(" ")
|
|
360
|
+
: null;
|
|
344
361
|
cells.push({
|
|
345
362
|
gridSpan: cell.gridSpan ?? 1,
|
|
346
363
|
verticalMerge: cell.verticalMerge ?? null,
|
|
@@ -352,6 +369,7 @@ function createTableBlock(
|
|
|
352
369
|
...(cellBorders.borderRight ? { borderRight: cellBorders.borderRight } : {}),
|
|
353
370
|
...(cellBorders.borderBottom ? { borderBottom: cellBorders.borderBottom } : {}),
|
|
354
371
|
...(cellBorders.borderLeft ? { borderLeft: cellBorders.borderLeft } : {}),
|
|
372
|
+
...(bandClasses ? { bandClasses } : {}),
|
|
355
373
|
content: cellContent,
|
|
356
374
|
});
|
|
357
375
|
}
|
|
@@ -365,6 +383,7 @@ function createTableBlock(
|
|
|
365
383
|
...(resolvedRow?.style.height !== undefined ? { height: resolvedRow.style.height } : {}),
|
|
366
384
|
...(resolvedRow?.style.heightRule ? { heightRule: resolvedRow.style.heightRule } : {}),
|
|
367
385
|
...(headerLike ? { isHeader: true } : {}),
|
|
386
|
+
...(row.cantSplit ? { cantSplit: true } : {}),
|
|
368
387
|
});
|
|
369
388
|
}
|
|
370
389
|
|
|
@@ -523,6 +542,26 @@ function createParagraphBlock(
|
|
|
523
542
|
const resolvedNumbering = effectiveNumbering
|
|
524
543
|
? numberingPrefixResolver.resolveDetailed(effectiveNumbering, paragraph)
|
|
525
544
|
: null;
|
|
545
|
+
|
|
546
|
+
// Task 11: compute cascaded paragraph formatting
|
|
547
|
+
const stylesCatalog = document.styles;
|
|
548
|
+
const directParagraphFormatting = buildDirectParagraphFormattingFromNode(paragraph);
|
|
549
|
+
const resolvedParagraphFormatting = resolveEffectiveParagraphFormatting(
|
|
550
|
+
{ styleId: paragraph.styleId, direct: directParagraphFormatting },
|
|
551
|
+
stylesCatalog,
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
// Task 11: compute cascaded marker run formatting
|
|
555
|
+
const markerRunProperties = effectiveNumbering
|
|
556
|
+
? resolveNumberingMarkerRunFormatting(
|
|
557
|
+
{
|
|
558
|
+
paragraphStyleId: paragraph.styleId,
|
|
559
|
+
levelRunProperties: resolvedNumbering?.markerRunProperties,
|
|
560
|
+
},
|
|
561
|
+
stylesCatalog,
|
|
562
|
+
)
|
|
563
|
+
: undefined;
|
|
564
|
+
|
|
526
565
|
const accumulator: ParagraphAccumulator = {
|
|
527
566
|
blockId: `paragraph-${paragraphIndex}`,
|
|
528
567
|
kind: "paragraph",
|
|
@@ -536,9 +575,17 @@ function createParagraphBlock(
|
|
|
536
575
|
...(resolvedNumbering.text !== null && resolvedNumbering.suffix
|
|
537
576
|
? { numberingSuffix: resolvedNumbering.suffix }
|
|
538
577
|
: {}),
|
|
539
|
-
resolvedNumbering:
|
|
578
|
+
resolvedNumbering: {
|
|
579
|
+
...toSurfaceResolvedNumbering(resolvedNumbering),
|
|
580
|
+
...(markerRunProperties && Object.keys(markerRunProperties).length > 0
|
|
581
|
+
? { markerRunProperties }
|
|
582
|
+
: {}),
|
|
583
|
+
},
|
|
540
584
|
}
|
|
541
585
|
: {}),
|
|
586
|
+
...(resolvedParagraphFormatting && Object.keys(resolvedParagraphFormatting).length > 0
|
|
587
|
+
? { resolvedParagraphFormatting }
|
|
588
|
+
: {}),
|
|
542
589
|
...(paragraph.alignment ? { alignment: paragraph.alignment } : {}),
|
|
543
590
|
...(paragraph.spacing ? { spacing: paragraph.spacing } : {}),
|
|
544
591
|
...(paragraph.contextualSpacing !== undefined
|
|
@@ -683,6 +730,48 @@ function resolveStyleLinkedNumberingLevel(
|
|
|
683
730
|
return undefined;
|
|
684
731
|
}
|
|
685
732
|
|
|
733
|
+
function buildDirectRunFormattingFromMarks(
|
|
734
|
+
marks: SurfaceTextMark[] | undefined,
|
|
735
|
+
markAttrs: {
|
|
736
|
+
backgroundColor?: string;
|
|
737
|
+
charSpacing?: number;
|
|
738
|
+
kerning?: number;
|
|
739
|
+
textFill?: string;
|
|
740
|
+
fontFamily?: string;
|
|
741
|
+
fontSize?: number;
|
|
742
|
+
textColor?: string;
|
|
743
|
+
} | undefined,
|
|
744
|
+
): CanonicalRunFormatting | undefined {
|
|
745
|
+
const direct: CanonicalRunFormatting = {};
|
|
746
|
+
if (marks) {
|
|
747
|
+
if (marks.includes("bold")) direct.bold = true;
|
|
748
|
+
if (marks.includes("italic")) direct.italic = true;
|
|
749
|
+
if (marks.includes("underline")) direct.underline = "single";
|
|
750
|
+
if (marks.includes("strikethrough")) direct.strikethrough = true;
|
|
751
|
+
if (marks.includes("doubleStrikethrough")) direct.doubleStrikethrough = true;
|
|
752
|
+
if (marks.includes("vanish")) direct.vanish = true;
|
|
753
|
+
if (marks.includes("allCaps")) direct.allCaps = true;
|
|
754
|
+
if (marks.includes("smallCaps")) direct.smallCaps = true;
|
|
755
|
+
}
|
|
756
|
+
if (markAttrs) {
|
|
757
|
+
if (markAttrs.fontFamily) {
|
|
758
|
+
direct.fontFamily = markAttrs.fontFamily;
|
|
759
|
+
direct.fontFamilyAscii = markAttrs.fontFamily;
|
|
760
|
+
}
|
|
761
|
+
if (typeof markAttrs.fontSize === "number") {
|
|
762
|
+
// markAttrs.fontSize is already in half-points from cloneMarks
|
|
763
|
+
direct.fontSizeHalfPoints = markAttrs.fontSize;
|
|
764
|
+
}
|
|
765
|
+
if (markAttrs.textColor) {
|
|
766
|
+
direct.colorHex = markAttrs.textColor.replace(/^#/, "");
|
|
767
|
+
}
|
|
768
|
+
if (markAttrs.backgroundColor) {
|
|
769
|
+
direct.highlight = markAttrs.backgroundColor;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return Object.keys(direct).length > 0 ? direct : undefined;
|
|
773
|
+
}
|
|
774
|
+
|
|
686
775
|
function appendInlineSegments(
|
|
687
776
|
paragraph: ParagraphAccumulator,
|
|
688
777
|
node: InlineNode,
|
|
@@ -692,23 +781,33 @@ function appendInlineSegments(
|
|
|
692
781
|
hyperlinkHref?: string,
|
|
693
782
|
): { nextCursor: number; lockedFragmentIds: string[] } {
|
|
694
783
|
switch (node.type) {
|
|
695
|
-
case "text":
|
|
784
|
+
case "text": {
|
|
785
|
+
const cloned = node.marks ? cloneMarks(node.marks) : { marks: [] as SurfaceTextMark[] };
|
|
786
|
+
const directRunFormatting = buildDirectRunFormattingFromMarks(
|
|
787
|
+
cloned.marks.length > 0 ? cloned.marks : undefined,
|
|
788
|
+
cloned.markAttrs,
|
|
789
|
+
);
|
|
790
|
+
const resolvedRunFormatting = resolveEffectiveRunFormatting(
|
|
791
|
+
{
|
|
792
|
+
paragraphStyleId: paragraph.styleId,
|
|
793
|
+
characterStyleId: undefined,
|
|
794
|
+
direct: directRunFormatting,
|
|
795
|
+
},
|
|
796
|
+
document.styles,
|
|
797
|
+
);
|
|
696
798
|
paragraph.segments.push({
|
|
697
799
|
segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
|
|
698
800
|
kind: "text",
|
|
699
801
|
from: start,
|
|
700
802
|
to: start + Array.from(node.text).length,
|
|
701
803
|
text: node.text,
|
|
702
|
-
...(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
...(result.marks.length > 0 ? { marks: result.marks } : {}),
|
|
706
|
-
...(result.markAttrs ? { markAttrs: result.markAttrs } : {}),
|
|
707
|
-
};
|
|
708
|
-
})() : {}),
|
|
804
|
+
...(cloned.marks.length > 0 ? { marks: cloned.marks } : {}),
|
|
805
|
+
...(cloned.markAttrs ? { markAttrs: cloned.markAttrs } : {}),
|
|
806
|
+
...(Object.keys(resolvedRunFormatting).length > 0 ? { resolvedRunFormatting } : {}),
|
|
709
807
|
...(hyperlinkHref ? { hyperlinkHref } : {}),
|
|
710
808
|
});
|
|
711
809
|
return { nextCursor: start + Array.from(node.text).length, lockedFragmentIds: [] };
|
|
810
|
+
}
|
|
712
811
|
case "tab":
|
|
713
812
|
paragraph.segments.push({
|
|
714
813
|
segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
|
|
@@ -1368,6 +1467,27 @@ function toSurfaceTabStop(
|
|
|
1368
1467
|
};
|
|
1369
1468
|
}
|
|
1370
1469
|
|
|
1470
|
+
function buildDirectParagraphFormattingFromNode(
|
|
1471
|
+
paragraph: ParagraphNode,
|
|
1472
|
+
): CanonicalParagraphFormatting | undefined {
|
|
1473
|
+
const direct: CanonicalParagraphFormatting = {};
|
|
1474
|
+
if (paragraph.spacing) direct.spacing = paragraph.spacing;
|
|
1475
|
+
if (paragraph.indentation) direct.indentation = paragraph.indentation;
|
|
1476
|
+
if (paragraph.alignment) direct.alignment = paragraph.alignment;
|
|
1477
|
+
if (paragraph.borders) direct.borders = paragraph.borders;
|
|
1478
|
+
if (paragraph.shading) direct.shading = paragraph.shading;
|
|
1479
|
+
if (paragraph.tabStops && paragraph.tabStops.length > 0) direct.tabStops = [...paragraph.tabStops];
|
|
1480
|
+
if (paragraph.contextualSpacing !== undefined) direct.contextualSpacing = paragraph.contextualSpacing;
|
|
1481
|
+
if (paragraph.keepNext !== undefined) direct.keepNext = paragraph.keepNext;
|
|
1482
|
+
if (paragraph.keepLines !== undefined) direct.keepLines = paragraph.keepLines;
|
|
1483
|
+
if (paragraph.widowControl !== undefined) direct.widowControl = paragraph.widowControl;
|
|
1484
|
+
if (paragraph.pageBreakBefore !== undefined) direct.pageBreakBefore = paragraph.pageBreakBefore;
|
|
1485
|
+
if (paragraph.outlineLevel !== undefined) direct.outlineLevel = paragraph.outlineLevel;
|
|
1486
|
+
if (paragraph.bidi !== undefined) direct.bidi = paragraph.bidi;
|
|
1487
|
+
if (paragraph.suppressLineNumbers !== undefined) direct.suppressLineNumbers = paragraph.suppressLineNumbers;
|
|
1488
|
+
return Object.keys(direct).length > 0 ? direct : undefined;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1371
1491
|
function toSurfaceResolvedNumbering(
|
|
1372
1492
|
numbering: NumberingPrefixResult,
|
|
1373
1493
|
): NonNullable<Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>["resolvedNumbering"]> {
|
|
@@ -42,6 +42,7 @@ type TableCellAttrs = {
|
|
|
42
42
|
borderRight?: string | null;
|
|
43
43
|
borderBottom?: string | null;
|
|
44
44
|
borderLeft?: string | null;
|
|
45
|
+
bandClasses?: string | null;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
function resolveRenderedColspan(attrs: {
|
|
@@ -96,6 +97,7 @@ function getCellAttrs(dom: HTMLElement): TableCellAttrs {
|
|
|
96
97
|
borderRight: dom.getAttribute("data-border-right"),
|
|
97
98
|
borderBottom: dom.getAttribute("data-border-bottom"),
|
|
98
99
|
borderLeft: dom.getAttribute("data-border-left"),
|
|
100
|
+
bandClasses: dom.getAttribute("data-band-classes"),
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
103
|
|
|
@@ -129,6 +131,11 @@ function setCellDomAttrs(nodeAttrs: TableCellAttrs, className: string): Record<s
|
|
|
129
131
|
if (nodeAttrs.borderRight) attrs["data-border-right"] = nodeAttrs.borderRight;
|
|
130
132
|
if (nodeAttrs.borderBottom) attrs["data-border-bottom"] = nodeAttrs.borderBottom;
|
|
131
133
|
if (nodeAttrs.borderLeft) attrs["data-border-left"] = nodeAttrs.borderLeft;
|
|
134
|
+
if (nodeAttrs.bandClasses) {
|
|
135
|
+
attrs["data-band-classes"] = nodeAttrs.bandClasses;
|
|
136
|
+
// Concatenate band classes onto the base `class` so Tailwind's @apply resolves at parse time.
|
|
137
|
+
attrs.class = `${attrs.class} ${nodeAttrs.bandClasses}`;
|
|
138
|
+
}
|
|
132
139
|
|
|
133
140
|
const styles: string[] = [];
|
|
134
141
|
const bgColor = safeCssColor(nodeAttrs.backgroundColor);
|
|
@@ -181,6 +188,8 @@ const tableCellSpecAttrs = {
|
|
|
181
188
|
borderRight: { default: null },
|
|
182
189
|
borderBottom: { default: null },
|
|
183
190
|
borderLeft: { default: null },
|
|
191
|
+
/** R2b: space-joined band classes ("band-firstRow band-band1Horz") from the resolved style. */
|
|
192
|
+
bandClasses: { default: null },
|
|
184
193
|
} as const;
|
|
185
194
|
|
|
186
195
|
export const tableNodeSpec: NodeSpec = {
|
|
@@ -199,6 +208,8 @@ export const tableNodeSpec: NodeSpec = {
|
|
|
199
208
|
tblLookLastColumn: { default: false },
|
|
200
209
|
tblLookNoHBand: { default: false },
|
|
201
210
|
tblLookNoVBand: { default: false },
|
|
211
|
+
/** R2d: raw `w:tblLook/@w:val` hex preserved verbatim so vendor-extended bits survive round-trip. */
|
|
212
|
+
tblLookVal: { default: null },
|
|
202
213
|
},
|
|
203
214
|
parseDOM: [{ tag: "table" }],
|
|
204
215
|
toDOM(node) {
|