@superdoc-dev/cli 0.2.0-next.86 → 0.2.0-next.88

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 (2) hide show
  1. package/dist/index.js +2305 -148
  2. package/package.json +8 -8
package/dist/index.js CHANGED
@@ -886,13 +886,13 @@ var schemaBooleanOrNull = () => ({
886
886
  tracked: true,
887
887
  carrier: markCarrier(markName),
888
888
  schema: schemaBooleanOrNull()
889
- }), markTextStyleValue = (key, type, ooxmlElement, schema) => ({
889
+ }), markTextStyleValue = (key, type, ooxmlElement, schema, textStyleAttr) => ({
890
890
  key,
891
891
  type,
892
892
  ooxmlElement,
893
893
  storage: "mark",
894
894
  tracked: true,
895
- carrier: markCarrier("textStyle", key),
895
+ carrier: markCarrier("textStyle", textStyleAttr ?? key),
896
896
  schema
897
897
  }), runAttribute = (key, type, ooxmlElement, schema, runPropertyKey) => ({
898
898
  key,
@@ -957,7 +957,7 @@ var init_inline_run_patch = __esm(() => {
957
957
  markTextStyleValue("position", "number", "w:position", schemaNumberOrNull()),
958
958
  runAttribute("dstrike", "boolean", "w:dstrike", schemaBooleanOrNull()),
959
959
  runAttribute("smallCaps", "boolean", "w:smallCaps", schemaBooleanOrNull()),
960
- runAttribute("caps", "boolean", "w:caps", schemaBooleanOrNull()),
960
+ markTextStyleValue("caps", "boolean", "w:caps", schemaBooleanOrNull(), "textTransform"),
961
961
  runAttribute("shading", "object", "w:shd", schemaObjectOrNull({
962
962
  fill: { oneOf: [{ type: "string", minLength: 1 }, { type: "null" }] },
963
963
  color: { oneOf: [{ type: "string", minLength: 1 }, { type: "null" }] },
@@ -3549,6 +3549,216 @@ var init_operation_definitions = __esm(() => {
3549
3549
  referenceDocPath: "images/set-z-order.mdx",
3550
3550
  referenceGroup: "images"
3551
3551
  },
3552
+ "images.scale": {
3553
+ memberPath: "images.scale",
3554
+ description: "Scale an image by a uniform factor applied to both dimensions.",
3555
+ expectedResult: "Returns an ImagesMutationResult with the updated image address.",
3556
+ requiresDocumentContext: true,
3557
+ metadata: mutationOperation({
3558
+ idempotency: "non-idempotent",
3559
+ supportsDryRun: true,
3560
+ supportsTrackedMode: false,
3561
+ possibleFailureCodes: ["NO_OP"],
3562
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3563
+ }),
3564
+ referenceDocPath: "images/scale.mdx",
3565
+ referenceGroup: "images"
3566
+ },
3567
+ "images.setLockAspectRatio": {
3568
+ memberPath: "images.setLockAspectRatio",
3569
+ description: "Lock or unlock the aspect ratio for an image.",
3570
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if already set.",
3571
+ requiresDocumentContext: true,
3572
+ metadata: mutationOperation({
3573
+ idempotency: "conditional",
3574
+ supportsDryRun: true,
3575
+ supportsTrackedMode: false,
3576
+ possibleFailureCodes: ["NO_OP"],
3577
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3578
+ }),
3579
+ referenceDocPath: "images/set-lock-aspect-ratio.mdx",
3580
+ referenceGroup: "images"
3581
+ },
3582
+ "images.rotate": {
3583
+ memberPath: "images.rotate",
3584
+ description: "Set the absolute rotation angle for an image.",
3585
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if already set.",
3586
+ requiresDocumentContext: true,
3587
+ metadata: mutationOperation({
3588
+ idempotency: "conditional",
3589
+ supportsDryRun: true,
3590
+ supportsTrackedMode: false,
3591
+ possibleFailureCodes: ["NO_OP"],
3592
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3593
+ }),
3594
+ referenceDocPath: "images/rotate.mdx",
3595
+ referenceGroup: "images"
3596
+ },
3597
+ "images.flip": {
3598
+ memberPath: "images.flip",
3599
+ description: "Set horizontal and/or vertical flip state for an image.",
3600
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if already set.",
3601
+ requiresDocumentContext: true,
3602
+ metadata: mutationOperation({
3603
+ idempotency: "conditional",
3604
+ supportsDryRun: true,
3605
+ supportsTrackedMode: false,
3606
+ possibleFailureCodes: ["NO_OP"],
3607
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3608
+ }),
3609
+ referenceDocPath: "images/flip.mdx",
3610
+ referenceGroup: "images"
3611
+ },
3612
+ "images.crop": {
3613
+ memberPath: "images.crop",
3614
+ description: "Apply rectangular edge-percentage crop to an image.",
3615
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
3616
+ requiresDocumentContext: true,
3617
+ metadata: mutationOperation({
3618
+ idempotency: "conditional",
3619
+ supportsDryRun: true,
3620
+ supportsTrackedMode: false,
3621
+ possibleFailureCodes: ["NO_OP"],
3622
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3623
+ }),
3624
+ referenceDocPath: "images/crop.mdx",
3625
+ referenceGroup: "images"
3626
+ },
3627
+ "images.resetCrop": {
3628
+ memberPath: "images.resetCrop",
3629
+ description: "Remove all cropping from an image.",
3630
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if no crop is set.",
3631
+ requiresDocumentContext: true,
3632
+ metadata: mutationOperation({
3633
+ idempotency: "conditional",
3634
+ supportsDryRun: true,
3635
+ supportsTrackedMode: false,
3636
+ possibleFailureCodes: ["NO_OP"],
3637
+ throws: T_IMAGE_COMMAND
3638
+ }),
3639
+ referenceDocPath: "images/reset-crop.mdx",
3640
+ referenceGroup: "images"
3641
+ },
3642
+ "images.replaceSource": {
3643
+ memberPath: "images.replaceSource",
3644
+ description: "Replace the image source while preserving identity and placement.",
3645
+ expectedResult: "Returns an ImagesMutationResult with the updated image address.",
3646
+ requiresDocumentContext: true,
3647
+ metadata: mutationOperation({
3648
+ idempotency: "non-idempotent",
3649
+ supportsDryRun: true,
3650
+ supportsTrackedMode: false,
3651
+ possibleFailureCodes: ["NO_OP"],
3652
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3653
+ }),
3654
+ referenceDocPath: "images/replace-source.mdx",
3655
+ referenceGroup: "images"
3656
+ },
3657
+ "images.setAltText": {
3658
+ memberPath: "images.setAltText",
3659
+ description: "Set the accessibility description (alt text) for an image.",
3660
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
3661
+ requiresDocumentContext: true,
3662
+ metadata: mutationOperation({
3663
+ idempotency: "conditional",
3664
+ supportsDryRun: true,
3665
+ supportsTrackedMode: false,
3666
+ possibleFailureCodes: ["NO_OP"],
3667
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3668
+ }),
3669
+ referenceDocPath: "images/set-alt-text.mdx",
3670
+ referenceGroup: "images"
3671
+ },
3672
+ "images.setDecorative": {
3673
+ memberPath: "images.setDecorative",
3674
+ description: "Mark or unmark an image as decorative.",
3675
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
3676
+ requiresDocumentContext: true,
3677
+ metadata: mutationOperation({
3678
+ idempotency: "conditional",
3679
+ supportsDryRun: true,
3680
+ supportsTrackedMode: false,
3681
+ possibleFailureCodes: ["NO_OP"],
3682
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3683
+ }),
3684
+ referenceDocPath: "images/set-decorative.mdx",
3685
+ referenceGroup: "images"
3686
+ },
3687
+ "images.setName": {
3688
+ memberPath: "images.setName",
3689
+ description: "Set the object name for an image.",
3690
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
3691
+ requiresDocumentContext: true,
3692
+ metadata: mutationOperation({
3693
+ idempotency: "conditional",
3694
+ supportsDryRun: true,
3695
+ supportsTrackedMode: false,
3696
+ possibleFailureCodes: ["NO_OP"],
3697
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3698
+ }),
3699
+ referenceDocPath: "images/set-name.mdx",
3700
+ referenceGroup: "images"
3701
+ },
3702
+ "images.setHyperlink": {
3703
+ memberPath: "images.setHyperlink",
3704
+ description: "Set or remove the hyperlink attached to an image.",
3705
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
3706
+ requiresDocumentContext: true,
3707
+ metadata: mutationOperation({
3708
+ idempotency: "conditional",
3709
+ supportsDryRun: true,
3710
+ supportsTrackedMode: false,
3711
+ possibleFailureCodes: ["NO_OP"],
3712
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3713
+ }),
3714
+ referenceDocPath: "images/set-hyperlink.mdx",
3715
+ referenceGroup: "images"
3716
+ },
3717
+ "images.insertCaption": {
3718
+ memberPath: "images.insertCaption",
3719
+ description: "Insert a caption paragraph below the image.",
3720
+ expectedResult: "Returns an ImagesMutationResult with the image address.",
3721
+ requiresDocumentContext: true,
3722
+ metadata: mutationOperation({
3723
+ idempotency: "non-idempotent",
3724
+ supportsDryRun: true,
3725
+ supportsTrackedMode: false,
3726
+ possibleFailureCodes: ["NO_OP"],
3727
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3728
+ }),
3729
+ referenceDocPath: "images/insert-caption.mdx",
3730
+ referenceGroup: "images"
3731
+ },
3732
+ "images.updateCaption": {
3733
+ memberPath: "images.updateCaption",
3734
+ description: "Update the text of an existing caption paragraph.",
3735
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if text unchanged.",
3736
+ requiresDocumentContext: true,
3737
+ metadata: mutationOperation({
3738
+ idempotency: "conditional",
3739
+ supportsDryRun: true,
3740
+ supportsTrackedMode: false,
3741
+ possibleFailureCodes: ["NO_OP"],
3742
+ throws: [...T_IMAGE_COMMAND, "INVALID_INPUT"]
3743
+ }),
3744
+ referenceDocPath: "images/update-caption.mdx",
3745
+ referenceGroup: "images"
3746
+ },
3747
+ "images.removeCaption": {
3748
+ memberPath: "images.removeCaption",
3749
+ description: "Remove the caption paragraph from below the image.",
3750
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if no caption exists.",
3751
+ requiresDocumentContext: true,
3752
+ metadata: mutationOperation({
3753
+ idempotency: "conditional",
3754
+ supportsDryRun: true,
3755
+ supportsTrackedMode: false,
3756
+ possibleFailureCodes: ["NO_OP"],
3757
+ throws: T_IMAGE_COMMAND
3758
+ }),
3759
+ referenceDocPath: "images/remove-caption.mdx",
3760
+ referenceGroup: "images"
3761
+ },
3552
3762
  "hyperlinks.list": {
3553
3763
  memberPath: "hyperlinks.list",
3554
3764
  description: "List all hyperlinks in the document, with optional filtering by href, anchor, or display text.",
@@ -4720,6 +4930,17 @@ function arraySchema(items) {
4720
4930
  function ref(name) {
4721
4931
  return { $ref: `#/$defs/${name}` };
4722
4932
  }
4933
+ function imagesMutationSchemaSet(inputSchema) {
4934
+ return {
4935
+ input: inputSchema,
4936
+ output: objectSchema({ success: { type: "boolean" }, image: { type: "object" }, failure: { type: "object" } }),
4937
+ success: objectSchema({ success: { const: true }, image: { type: "object" } }, ["success", "image"]),
4938
+ failure: objectSchema({
4939
+ success: { const: false },
4940
+ failure: objectSchema({ code: { type: "string" }, message: { type: "string" } }, ["code", "message"])
4941
+ }, ["success", "failure"])
4942
+ };
4943
+ }
4723
4944
  function discoveryResultSchema(itemSchema, metaSchema) {
4724
4945
  const properties = {
4725
4946
  evaluatedRevision: { type: "string" },
@@ -7895,24 +8116,53 @@ var init_schemas = __esm(() => {
7895
8116
  failure: objectSchema({ code: { type: "string" }, message: { type: "string" } }, ["code", "message"])
7896
8117
  }, ["success", "failure"])
7897
8118
  },
7898
- "images.setZOrder": {
7899
- input: objectSchema({
7900
- imageId: { type: "string" },
7901
- zOrder: objectSchema({
7902
- relativeHeight: {
7903
- type: "integer",
7904
- minimum: Z_ORDER_RELATIVE_HEIGHT_MIN,
7905
- maximum: Z_ORDER_RELATIVE_HEIGHT_MAX
7906
- }
7907
- }, ["relativeHeight"])
7908
- }, ["imageId", "zOrder"]),
7909
- output: objectSchema({ success: { type: "boolean" }, image: { type: "object" }, failure: { type: "object" } }),
7910
- success: objectSchema({ success: { const: true }, image: { type: "object" } }, ["success", "image"]),
7911
- failure: objectSchema({
7912
- success: { const: false },
7913
- failure: objectSchema({ code: { type: "string" }, message: { type: "string" } }, ["code", "message"])
7914
- }, ["success", "failure"])
7915
- },
8119
+ "images.setZOrder": imagesMutationSchemaSet(objectSchema({
8120
+ imageId: { type: "string" },
8121
+ zOrder: objectSchema({
8122
+ relativeHeight: {
8123
+ type: "integer",
8124
+ minimum: Z_ORDER_RELATIVE_HEIGHT_MIN,
8125
+ maximum: Z_ORDER_RELATIVE_HEIGHT_MAX
8126
+ }
8127
+ }, ["relativeHeight"])
8128
+ }, ["imageId", "zOrder"])),
8129
+ "images.scale": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, factor: { type: "number", exclusiveMinimum: 0 } }, [
8130
+ "imageId",
8131
+ "factor"
8132
+ ])),
8133
+ "images.setLockAspectRatio": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, locked: { type: "boolean" } }, ["imageId", "locked"])),
8134
+ "images.rotate": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, angle: { type: "number", minimum: 0, maximum: 360 } }, [
8135
+ "imageId",
8136
+ "angle"
8137
+ ])),
8138
+ "images.flip": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, horizontal: { type: "boolean" }, vertical: { type: "boolean" } }, [
8139
+ "imageId"
8140
+ ])),
8141
+ "images.crop": imagesMutationSchemaSet(objectSchema({
8142
+ imageId: { type: "string" },
8143
+ crop: objectSchema({
8144
+ left: { type: "number", minimum: 0, maximum: 100 },
8145
+ top: { type: "number", minimum: 0, maximum: 100 },
8146
+ right: { type: "number", minimum: 0, maximum: 100 },
8147
+ bottom: { type: "number", minimum: 0, maximum: 100 }
8148
+ }, [])
8149
+ }, ["imageId", "crop"])),
8150
+ "images.resetCrop": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" } }, ["imageId"])),
8151
+ "images.replaceSource": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, src: { type: "string" }, resetSize: { type: "boolean" } }, [
8152
+ "imageId",
8153
+ "src"
8154
+ ])),
8155
+ "images.setAltText": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, description: { type: "string" } }, ["imageId", "description"])),
8156
+ "images.setDecorative": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, decorative: { type: "boolean" } }, ["imageId", "decorative"])),
8157
+ "images.setName": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, name: { type: "string" } }, ["imageId", "name"])),
8158
+ "images.setHyperlink": imagesMutationSchemaSet(objectSchema({
8159
+ imageId: { type: "string" },
8160
+ url: { type: ["string", "null"] },
8161
+ tooltip: { type: "string" }
8162
+ }, ["imageId", "url"])),
8163
+ "images.insertCaption": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, text: { type: "string" } }, ["imageId", "text"])),
8164
+ "images.updateCaption": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" }, text: { type: "string" } }, ["imageId", "text"])),
8165
+ "images.removeCaption": imagesMutationSchemaSet(objectSchema({ imageId: { type: "string" } }, ["imageId"])),
7916
8166
  "hyperlinks.list": {
7917
8167
  input: objectSchema({
7918
8168
  within: nodeAddressSchema,
@@ -9183,6 +9433,20 @@ function buildDispatchTable(api) {
9183
9433
  "images.setPosition": (input, options) => api.images.setPosition(input, options),
9184
9434
  "images.setAnchorOptions": (input, options) => api.images.setAnchorOptions(input, options),
9185
9435
  "images.setZOrder": (input, options) => api.images.setZOrder(input, options),
9436
+ "images.scale": (input, options) => api.images.scale(input, options),
9437
+ "images.setLockAspectRatio": (input, options) => api.images.setLockAspectRatio(input, options),
9438
+ "images.rotate": (input, options) => api.images.rotate(input, options),
9439
+ "images.flip": (input, options) => api.images.flip(input, options),
9440
+ "images.crop": (input, options) => api.images.crop(input, options),
9441
+ "images.resetCrop": (input, options) => api.images.resetCrop(input, options),
9442
+ "images.replaceSource": (input, options) => api.images.replaceSource(input, options),
9443
+ "images.setAltText": (input, options) => api.images.setAltText(input, options),
9444
+ "images.setDecorative": (input, options) => api.images.setDecorative(input, options),
9445
+ "images.setName": (input, options) => api.images.setName(input, options),
9446
+ "images.setHyperlink": (input, options) => api.images.setHyperlink(input, options),
9447
+ "images.insertCaption": (input, options) => api.images.insertCaption(input, options),
9448
+ "images.updateCaption": (input, options) => api.images.updateCaption(input, options),
9449
+ "images.removeCaption": (input, options) => api.images.removeCaption(input, options),
9186
9450
  "hyperlinks.list": (input) => api.hyperlinks.list(input),
9187
9451
  "hyperlinks.get": (input) => api.hyperlinks.get(input),
9188
9452
  "hyperlinks.wrap": (input, options) => api.hyperlinks.wrap(input, options),
@@ -9738,6 +10002,142 @@ function executeImagesSetZOrder(adapter, input, options) {
9738
10002
  requireUnsignedInt32(input.zOrder.relativeHeight, "zOrder.relativeHeight");
9739
10003
  return adapter.setZOrder(input, options);
9740
10004
  }
10005
+ function executeImagesScale(adapter, input, options) {
10006
+ requireImageId(input);
10007
+ if (typeof input.factor !== "number" || !Number.isFinite(input.factor) || input.factor <= 0) {
10008
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.scale requires factor as a finite positive number.", {
10009
+ field: "factor",
10010
+ value: input.factor
10011
+ });
10012
+ }
10013
+ return adapter.scale(input, options);
10014
+ }
10015
+ function executeImagesSetLockAspectRatio(adapter, input, options) {
10016
+ requireImageId(input);
10017
+ if (typeof input.locked !== "boolean") {
10018
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.setLockAspectRatio requires locked as a boolean.", {
10019
+ field: "locked"
10020
+ });
10021
+ }
10022
+ return adapter.setLockAspectRatio(input, options);
10023
+ }
10024
+ function executeImagesRotate(adapter, input, options) {
10025
+ requireImageId(input);
10026
+ if (typeof input.angle !== "number" || !Number.isFinite(input.angle) || input.angle < 0 || input.angle > 360) {
10027
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.rotate requires angle as a number in [0, 360].", {
10028
+ field: "angle",
10029
+ value: input.angle
10030
+ });
10031
+ }
10032
+ return adapter.rotate(input, options);
10033
+ }
10034
+ function executeImagesFlip(adapter, input, options) {
10035
+ requireImageId(input);
10036
+ if (input.horizontal === undefined && input.vertical === undefined) {
10037
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.flip requires at least one of horizontal or vertical.", { field: "horizontal|vertical" });
10038
+ }
10039
+ if (input.horizontal !== undefined && typeof input.horizontal !== "boolean") {
10040
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.flip horizontal must be a boolean.", {
10041
+ field: "horizontal"
10042
+ });
10043
+ }
10044
+ if (input.vertical !== undefined && typeof input.vertical !== "boolean") {
10045
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.flip vertical must be a boolean.", {
10046
+ field: "vertical"
10047
+ });
10048
+ }
10049
+ return adapter.flip(input, options);
10050
+ }
10051
+ function executeImagesCrop(adapter, input, options) {
10052
+ requireImageId(input);
10053
+ if (!input.crop || typeof input.crop !== "object") {
10054
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.crop requires a crop object.", { field: "crop" });
10055
+ }
10056
+ const { left = 0, top = 0, right = 0, bottom = 0 } = input.crop;
10057
+ for (const [name, value] of Object.entries({ left, top, right, bottom })) {
10058
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 100) {
10059
+ throw new DocumentApiValidationError("INVALID_INPUT", `crop.${name} must be a number in [0, 100].`, {
10060
+ field: `crop.${name}`,
10061
+ value
10062
+ });
10063
+ }
10064
+ }
10065
+ if (left + right >= 100) {
10066
+ throw new DocumentApiValidationError("INVALID_INPUT", "crop.left + crop.right must be less than 100.", {
10067
+ field: "crop"
10068
+ });
10069
+ }
10070
+ if (top + bottom >= 100) {
10071
+ throw new DocumentApiValidationError("INVALID_INPUT", "crop.top + crop.bottom must be less than 100.", {
10072
+ field: "crop"
10073
+ });
10074
+ }
10075
+ return adapter.crop(input, options);
10076
+ }
10077
+ function executeImagesResetCrop(adapter, input, options) {
10078
+ requireImageId(input);
10079
+ return adapter.resetCrop(input, options);
10080
+ }
10081
+ function executeImagesReplaceSource(adapter, input, options) {
10082
+ requireImageId(input);
10083
+ requireString(input.src, "src");
10084
+ return adapter.replaceSource(input, options);
10085
+ }
10086
+ function executeImagesSetAltText(adapter, input, options) {
10087
+ requireImageId(input);
10088
+ if (typeof input.description !== "string") {
10089
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.setAltText requires description as a string.", {
10090
+ field: "description"
10091
+ });
10092
+ }
10093
+ return adapter.setAltText(input, options);
10094
+ }
10095
+ function executeImagesSetDecorative(adapter, input, options) {
10096
+ requireImageId(input);
10097
+ if (typeof input.decorative !== "boolean") {
10098
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.setDecorative requires decorative as a boolean.", {
10099
+ field: "decorative"
10100
+ });
10101
+ }
10102
+ return adapter.setDecorative(input, options);
10103
+ }
10104
+ function executeImagesSetName(adapter, input, options) {
10105
+ requireImageId(input);
10106
+ if (typeof input.name !== "string") {
10107
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.setName requires name as a string.", {
10108
+ field: "name"
10109
+ });
10110
+ }
10111
+ return adapter.setName(input, options);
10112
+ }
10113
+ function executeImagesSetHyperlink(adapter, input, options) {
10114
+ requireImageId(input);
10115
+ if (input.url !== null && typeof input.url !== "string") {
10116
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.setHyperlink requires url as a string or null.", {
10117
+ field: "url"
10118
+ });
10119
+ }
10120
+ if (input.tooltip !== undefined && typeof input.tooltip !== "string") {
10121
+ throw new DocumentApiValidationError("INVALID_INPUT", "images.setHyperlink tooltip must be a string.", {
10122
+ field: "tooltip"
10123
+ });
10124
+ }
10125
+ return adapter.setHyperlink(input, options);
10126
+ }
10127
+ function executeImagesInsertCaption(adapter, input, options) {
10128
+ requireImageId(input);
10129
+ requireString(input.text, "text");
10130
+ return adapter.insertCaption(input, options);
10131
+ }
10132
+ function executeImagesUpdateCaption(adapter, input, options) {
10133
+ requireImageId(input);
10134
+ requireString(input.text, "text");
10135
+ return adapter.updateCaption(input, options);
10136
+ }
10137
+ function executeImagesRemoveCaption(adapter, input, options) {
10138
+ requireImageId(input);
10139
+ return adapter.removeCaption(input, options);
10140
+ }
9741
10141
  function executeCreateImage(adapter, input, options) {
9742
10142
  requireString(input?.src, "src");
9743
10143
  return adapter.image(input, options);
@@ -10157,6 +10557,48 @@ function createDocumentApi(adapters) {
10157
10557
  },
10158
10558
  setZOrder(input, options) {
10159
10559
  return executeImagesSetZOrder(adapters.images, input, options);
10560
+ },
10561
+ scale(input, options) {
10562
+ return executeImagesScale(adapters.images, input, options);
10563
+ },
10564
+ setLockAspectRatio(input, options) {
10565
+ return executeImagesSetLockAspectRatio(adapters.images, input, options);
10566
+ },
10567
+ rotate(input, options) {
10568
+ return executeImagesRotate(adapters.images, input, options);
10569
+ },
10570
+ flip(input, options) {
10571
+ return executeImagesFlip(adapters.images, input, options);
10572
+ },
10573
+ crop(input, options) {
10574
+ return executeImagesCrop(adapters.images, input, options);
10575
+ },
10576
+ resetCrop(input, options) {
10577
+ return executeImagesResetCrop(adapters.images, input, options);
10578
+ },
10579
+ replaceSource(input, options) {
10580
+ return executeImagesReplaceSource(adapters.images, input, options);
10581
+ },
10582
+ setAltText(input, options) {
10583
+ return executeImagesSetAltText(adapters.images, input, options);
10584
+ },
10585
+ setDecorative(input, options) {
10586
+ return executeImagesSetDecorative(adapters.images, input, options);
10587
+ },
10588
+ setName(input, options) {
10589
+ return executeImagesSetName(adapters.images, input, options);
10590
+ },
10591
+ setHyperlink(input, options) {
10592
+ return executeImagesSetHyperlink(adapters.images, input, options);
10593
+ },
10594
+ insertCaption(input, options) {
10595
+ return executeImagesInsertCaption(adapters.images, input, options);
10596
+ },
10597
+ updateCaption(input, options) {
10598
+ return executeImagesUpdateCaption(adapters.images, input, options);
10599
+ },
10600
+ removeCaption(input, options) {
10601
+ return executeImagesRemoveCaption(adapters.images, input, options);
10160
10602
  }
10161
10603
  },
10162
10604
  lists: {
@@ -32778,7 +33220,7 @@ var init_remark_gfm_z_sDF4ss_es = __esm(() => {
32778
33220
  emptyOptions2 = {};
32779
33221
  });
32780
33222
 
32781
- // ../../packages/superdoc/dist/chunks/SuperConverter-C3jSWLmj.es.js
33223
+ // ../../packages/superdoc/dist/chunks/SuperConverter-CHHvo5ta.es.js
32782
33224
  function getExtensionConfigField(extension$1, field, context = { name: "" }) {
32783
33225
  const fieldValue = extension$1.config[field];
32784
33226
  if (typeof fieldValue === "function")
@@ -34533,6 +34975,27 @@ function arraySchema2(items) {
34533
34975
  function ref2(name) {
34534
34976
  return { $ref: `#/$defs/${name}` };
34535
34977
  }
34978
+ function imagesMutationSchemaSet2(inputSchema) {
34979
+ return {
34980
+ input: inputSchema,
34981
+ output: objectSchema2({
34982
+ success: { type: "boolean" },
34983
+ image: { type: "object" },
34984
+ failure: { type: "object" }
34985
+ }),
34986
+ success: objectSchema2({
34987
+ success: { const: true },
34988
+ image: { type: "object" }
34989
+ }, ["success", "image"]),
34990
+ failure: objectSchema2({
34991
+ success: { const: false },
34992
+ failure: objectSchema2({
34993
+ code: { type: "string" },
34994
+ message: { type: "string" }
34995
+ }, ["code", "message"])
34996
+ }, ["success", "failure"])
34997
+ };
34998
+ }
34536
34999
  function discoveryResultSchema2(itemSchema, metaSchema) {
34537
35000
  const properties = {
34538
35001
  evaluatedRevision: { type: "string" },
@@ -35554,6 +36017,20 @@ function buildDispatchTable2(api) {
35554
36017
  "images.setPosition": (input, options) => api.images.setPosition(input, options),
35555
36018
  "images.setAnchorOptions": (input, options) => api.images.setAnchorOptions(input, options),
35556
36019
  "images.setZOrder": (input, options) => api.images.setZOrder(input, options),
36020
+ "images.scale": (input, options) => api.images.scale(input, options),
36021
+ "images.setLockAspectRatio": (input, options) => api.images.setLockAspectRatio(input, options),
36022
+ "images.rotate": (input, options) => api.images.rotate(input, options),
36023
+ "images.flip": (input, options) => api.images.flip(input, options),
36024
+ "images.crop": (input, options) => api.images.crop(input, options),
36025
+ "images.resetCrop": (input, options) => api.images.resetCrop(input, options),
36026
+ "images.replaceSource": (input, options) => api.images.replaceSource(input, options),
36027
+ "images.setAltText": (input, options) => api.images.setAltText(input, options),
36028
+ "images.setDecorative": (input, options) => api.images.setDecorative(input, options),
36029
+ "images.setName": (input, options) => api.images.setName(input, options),
36030
+ "images.setHyperlink": (input, options) => api.images.setHyperlink(input, options),
36031
+ "images.insertCaption": (input, options) => api.images.insertCaption(input, options),
36032
+ "images.updateCaption": (input, options) => api.images.updateCaption(input, options),
36033
+ "images.removeCaption": (input, options) => api.images.removeCaption(input, options),
35557
36034
  "hyperlinks.list": (input) => api.hyperlinks.list(input),
35558
36035
  "hyperlinks.get": (input) => api.hyperlinks.get(input),
35559
36036
  "hyperlinks.wrap": (input, options) => api.hyperlinks.wrap(input, options),
@@ -36016,6 +36493,111 @@ function executeImagesSetZOrder2(adapter, input, options) {
36016
36493
  requireUnsignedInt322(input.zOrder.relativeHeight, "zOrder.relativeHeight");
36017
36494
  return adapter.setZOrder(input, options);
36018
36495
  }
36496
+ function executeImagesScale2(adapter, input, options) {
36497
+ requireImageId2(input);
36498
+ if (typeof input.factor !== "number" || !Number.isFinite(input.factor) || input.factor <= 0)
36499
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.scale requires factor as a finite positive number.", {
36500
+ field: "factor",
36501
+ value: input.factor
36502
+ });
36503
+ return adapter.scale(input, options);
36504
+ }
36505
+ function executeImagesSetLockAspectRatio2(adapter, input, options) {
36506
+ requireImageId2(input);
36507
+ if (typeof input.locked !== "boolean")
36508
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.setLockAspectRatio requires locked as a boolean.", { field: "locked" });
36509
+ return adapter.setLockAspectRatio(input, options);
36510
+ }
36511
+ function executeImagesRotate2(adapter, input, options) {
36512
+ requireImageId2(input);
36513
+ if (typeof input.angle !== "number" || !Number.isFinite(input.angle) || input.angle < 0 || input.angle > 360)
36514
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.rotate requires angle as a number in [0, 360].", {
36515
+ field: "angle",
36516
+ value: input.angle
36517
+ });
36518
+ return adapter.rotate(input, options);
36519
+ }
36520
+ function executeImagesFlip2(adapter, input, options) {
36521
+ requireImageId2(input);
36522
+ if (input.horizontal === undefined && input.vertical === undefined)
36523
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.flip requires at least one of horizontal or vertical.", { field: "horizontal|vertical" });
36524
+ if (input.horizontal !== undefined && typeof input.horizontal !== "boolean")
36525
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.flip horizontal must be a boolean.", { field: "horizontal" });
36526
+ if (input.vertical !== undefined && typeof input.vertical !== "boolean")
36527
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.flip vertical must be a boolean.", { field: "vertical" });
36528
+ return adapter.flip(input, options);
36529
+ }
36530
+ function executeImagesCrop2(adapter, input, options) {
36531
+ requireImageId2(input);
36532
+ if (!input.crop || typeof input.crop !== "object")
36533
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.crop requires a crop object.", { field: "crop" });
36534
+ const { left = 0, top = 0, right = 0, bottom = 0 } = input.crop;
36535
+ for (const [name, value] of Object.entries({
36536
+ left,
36537
+ top,
36538
+ right,
36539
+ bottom
36540
+ }))
36541
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 100)
36542
+ throw new DocumentApiValidationError2("INVALID_INPUT", `crop.${name} must be a number in [0, 100].`, {
36543
+ field: `crop.${name}`,
36544
+ value
36545
+ });
36546
+ if (left + right >= 100)
36547
+ throw new DocumentApiValidationError2("INVALID_INPUT", "crop.left + crop.right must be less than 100.", { field: "crop" });
36548
+ if (top + bottom >= 100)
36549
+ throw new DocumentApiValidationError2("INVALID_INPUT", "crop.top + crop.bottom must be less than 100.", { field: "crop" });
36550
+ return adapter.crop(input, options);
36551
+ }
36552
+ function executeImagesResetCrop2(adapter, input, options) {
36553
+ requireImageId2(input);
36554
+ return adapter.resetCrop(input, options);
36555
+ }
36556
+ function executeImagesReplaceSource2(adapter, input, options) {
36557
+ requireImageId2(input);
36558
+ requireString2(input.src, "src");
36559
+ return adapter.replaceSource(input, options);
36560
+ }
36561
+ function executeImagesSetAltText2(adapter, input, options) {
36562
+ requireImageId2(input);
36563
+ if (typeof input.description !== "string")
36564
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.setAltText requires description as a string.", { field: "description" });
36565
+ return adapter.setAltText(input, options);
36566
+ }
36567
+ function executeImagesSetDecorative2(adapter, input, options) {
36568
+ requireImageId2(input);
36569
+ if (typeof input.decorative !== "boolean")
36570
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.setDecorative requires decorative as a boolean.", { field: "decorative" });
36571
+ return adapter.setDecorative(input, options);
36572
+ }
36573
+ function executeImagesSetName2(adapter, input, options) {
36574
+ requireImageId2(input);
36575
+ if (typeof input.name !== "string")
36576
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.setName requires name as a string.", { field: "name" });
36577
+ return adapter.setName(input, options);
36578
+ }
36579
+ function executeImagesSetHyperlink2(adapter, input, options) {
36580
+ requireImageId2(input);
36581
+ if (input.url !== null && typeof input.url !== "string")
36582
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.setHyperlink requires url as a string or null.", { field: "url" });
36583
+ if (input.tooltip !== undefined && typeof input.tooltip !== "string")
36584
+ throw new DocumentApiValidationError2("INVALID_INPUT", "images.setHyperlink tooltip must be a string.", { field: "tooltip" });
36585
+ return adapter.setHyperlink(input, options);
36586
+ }
36587
+ function executeImagesInsertCaption2(adapter, input, options) {
36588
+ requireImageId2(input);
36589
+ requireString2(input.text, "text");
36590
+ return adapter.insertCaption(input, options);
36591
+ }
36592
+ function executeImagesUpdateCaption2(adapter, input, options) {
36593
+ requireImageId2(input);
36594
+ requireString2(input.text, "text");
36595
+ return adapter.updateCaption(input, options);
36596
+ }
36597
+ function executeImagesRemoveCaption2(adapter, input, options) {
36598
+ requireImageId2(input);
36599
+ return adapter.removeCaption(input, options);
36600
+ }
36019
36601
  function executeCreateImage2(adapter, input, options) {
36020
36602
  requireString2(input?.src, "src");
36021
36603
  return adapter.image(input, options);
@@ -36379,6 +36961,48 @@ function createDocumentApi2(adapters) {
36379
36961
  },
36380
36962
  setZOrder(input, options) {
36381
36963
  return executeImagesSetZOrder2(adapters.images, input, options);
36964
+ },
36965
+ scale(input, options) {
36966
+ return executeImagesScale2(adapters.images, input, options);
36967
+ },
36968
+ setLockAspectRatio(input, options) {
36969
+ return executeImagesSetLockAspectRatio2(adapters.images, input, options);
36970
+ },
36971
+ rotate(input, options) {
36972
+ return executeImagesRotate2(adapters.images, input, options);
36973
+ },
36974
+ flip(input, options) {
36975
+ return executeImagesFlip2(adapters.images, input, options);
36976
+ },
36977
+ crop(input, options) {
36978
+ return executeImagesCrop2(adapters.images, input, options);
36979
+ },
36980
+ resetCrop(input, options) {
36981
+ return executeImagesResetCrop2(adapters.images, input, options);
36982
+ },
36983
+ replaceSource(input, options) {
36984
+ return executeImagesReplaceSource2(adapters.images, input, options);
36985
+ },
36986
+ setAltText(input, options) {
36987
+ return executeImagesSetAltText2(adapters.images, input, options);
36988
+ },
36989
+ setDecorative(input, options) {
36990
+ return executeImagesSetDecorative2(adapters.images, input, options);
36991
+ },
36992
+ setName(input, options) {
36993
+ return executeImagesSetName2(adapters.images, input, options);
36994
+ },
36995
+ setHyperlink(input, options) {
36996
+ return executeImagesSetHyperlink2(adapters.images, input, options);
36997
+ },
36998
+ insertCaption(input, options) {
36999
+ return executeImagesInsertCaption2(adapters.images, input, options);
37000
+ },
37001
+ updateCaption(input, options) {
37002
+ return executeImagesUpdateCaption2(adapters.images, input, options);
37003
+ },
37004
+ removeCaption(input, options) {
37005
+ return executeImagesRemoveCaption2(adapters.images, input, options);
36382
37006
  }
36383
37007
  },
36384
37008
  lists: {
@@ -41292,6 +41916,35 @@ function handleImageNode(node3, params, isAnchor) {
41292
41916
  horizontalFlip: xfrm.attributes["flipH"] === "1"
41293
41917
  };
41294
41918
  }
41919
+ const nvPicPr = picture.elements.find((el) => el.name === "pic:nvPicPr");
41920
+ const picLocks = nvPicPr?.elements?.find((el) => el.name === "pic:cNvPicPr")?.elements?.find((el) => el.name === "a:picLocks");
41921
+ const lockAspectRatio = picLocks ? picLocks.attributes?.["noChangeAspect"] === "1" || picLocks.attributes?.["noChangeAspect"] === 1 : false;
41922
+ const hlinkClick = nvPicPr?.elements?.find((el) => el.name === "pic:cNvPr")?.elements?.find((el) => el.name === "a:hlinkClick") || docPr?.elements?.find((el) => el.name === "a:hlinkClick");
41923
+ let hyperlink = null;
41924
+ if (hlinkClick?.attributes?.["r:id"]) {
41925
+ const hlinkRId = hlinkClick.attributes["r:id"];
41926
+ let hlinkRels = docx[`word/_rels/${filename || "document.xml"}.rels`];
41927
+ if (!hlinkRels)
41928
+ hlinkRels = docx[`word/_rels/document.xml.rels`];
41929
+ const hlinkRel = hlinkRels?.elements?.find((el) => el.name === "Relationships")?.elements?.find((el) => el.attributes?.["Id"] === hlinkRId);
41930
+ if (hlinkRel?.attributes?.["Target"]) {
41931
+ hyperlink = { url: hlinkRel.attributes["Target"] };
41932
+ if (hlinkClick.attributes?.["tooltip"])
41933
+ hyperlink.tooltip = hlinkClick.attributes["tooltip"];
41934
+ }
41935
+ }
41936
+ let decorative = false;
41937
+ const docPrExtLst = docPr?.elements?.find((el) => el.name === "a:extLst");
41938
+ if (docPrExtLst)
41939
+ for (const ext of docPrExtLst.elements || []) {
41940
+ if (ext.name !== "a:ext")
41941
+ continue;
41942
+ const decEl = ext.elements?.find((el) => el.name === "adec:decorative" || el.name === "a16:decorative");
41943
+ if (decEl && (decEl.attributes?.["val"] === "1" || decEl.attributes?.["val"] === 1)) {
41944
+ decorative = true;
41945
+ break;
41946
+ }
41947
+ }
41295
41948
  const { attributes: blipAttributes = {} } = blip;
41296
41949
  const rEmbed = blipAttributes["r:embed"];
41297
41950
  if (!rEmbed)
@@ -41380,6 +42033,9 @@ function handleImageNode(node3, params, isAnchor) {
41380
42033
  },
41381
42034
  originalAttributes: node3.attributes,
41382
42035
  rId: relAttributes["Id"],
42036
+ lockAspectRatio,
42037
+ decorative,
42038
+ hyperlink,
41383
42039
  ...order2.length ? { drawingChildOrder: order2 } : {},
41384
42040
  ...originalChildren.length ? { originalDrawingChildren: originalChildren } : {},
41385
42041
  ...hasGrayscale ? { grayscale: true } : {}
@@ -47827,6 +48483,96 @@ function readImageDimensionsFromDataUri(dataUri) {
47827
48483
  return null;
47828
48484
  }
47829
48485
  }
48486
+ function resolveHyperlinkRId(attrs, params) {
48487
+ if (!attrs.hyperlink?.url || !params)
48488
+ return null;
48489
+ return addHyperlinkRelationship(params, attrs.hyperlink.url);
48490
+ }
48491
+ function buildHlinkClickElement(attrs, hlinkRId) {
48492
+ if (!hlinkRId)
48493
+ return null;
48494
+ const hlinkAttrs = { "r:id": hlinkRId };
48495
+ if (attrs.hyperlink?.tooltip)
48496
+ hlinkAttrs.tooltip = attrs.hyperlink.tooltip;
48497
+ return {
48498
+ name: "a:hlinkClick",
48499
+ attributes: hlinkAttrs
48500
+ };
48501
+ }
48502
+ function buildDocPrElement(attrs, imageName, hlinkRId) {
48503
+ const docPrAttrs = {
48504
+ id: attrs.id || 0,
48505
+ name: attrs.alt || `Picture ${imageName}`
48506
+ };
48507
+ if (!attrs.decorative && attrs.title)
48508
+ docPrAttrs.descr = attrs.title;
48509
+ const children = [];
48510
+ const hlinkEl = buildHlinkClickElement(attrs, hlinkRId);
48511
+ if (hlinkEl)
48512
+ children.push(hlinkEl);
48513
+ if (attrs.decorative)
48514
+ children.push({
48515
+ name: "a:extLst",
48516
+ elements: [{
48517
+ name: "a:ext",
48518
+ attributes: { uri: DECORATIVE_EXT_URI },
48519
+ elements: [{
48520
+ name: "adec:decorative",
48521
+ attributes: {
48522
+ "xmlns:adec": DECORATIVE_NAMESPACE,
48523
+ val: "1"
48524
+ }
48525
+ }]
48526
+ }]
48527
+ });
48528
+ return {
48529
+ name: "wp:docPr",
48530
+ attributes: docPrAttrs,
48531
+ ...children.length ? { elements: children } : {}
48532
+ };
48533
+ }
48534
+ function buildNvPicPrElement(attrs, imageName, hlinkRId) {
48535
+ const cNvPrChildren = [];
48536
+ const hlinkEl = buildHlinkClickElement(attrs, hlinkRId);
48537
+ if (hlinkEl)
48538
+ cNvPrChildren.push(hlinkEl);
48539
+ return {
48540
+ name: "pic:nvPicPr",
48541
+ elements: [{
48542
+ name: "pic:cNvPr",
48543
+ attributes: {
48544
+ id: attrs.id || 0,
48545
+ name: attrs.alt || `Picture ${imageName}`
48546
+ },
48547
+ ...cNvPrChildren.length ? { elements: cNvPrChildren } : {}
48548
+ }, {
48549
+ name: "pic:cNvPicPr",
48550
+ elements: [{
48551
+ name: "a:picLocks",
48552
+ attributes: {
48553
+ ...attrs.lockAspectRatio ? { noChangeAspect: 1 } : {},
48554
+ noChangeArrowheads: 1
48555
+ }
48556
+ }]
48557
+ }]
48558
+ };
48559
+ }
48560
+ function addHyperlinkRelationship(params, url) {
48561
+ const newId = `rId${generateDocxRandomId(8)}`;
48562
+ if (!params.relationships || !Array.isArray(params.relationships))
48563
+ params.relationships = [];
48564
+ params.relationships.push({
48565
+ type: "element",
48566
+ name: "Relationship",
48567
+ attributes: {
48568
+ Id: newId,
48569
+ Type: HYPERLINK_REL_TYPE,
48570
+ Target: url,
48571
+ TargetMode: "External"
48572
+ }
48573
+ });
48574
+ return newId;
48575
+ }
47830
48576
  function isFinitePositive(value) {
47831
48577
  return typeof value === "number" && Number.isFinite(value) && value > 0;
47832
48578
  }
@@ -52884,13 +53630,13 @@ var isRegExp = (value) => {
52884
53630
  tracked: true,
52885
53631
  carrier: markCarrier2(markName),
52886
53632
  schema: schemaBooleanOrNull2()
52887
- }), markTextStyleValue2 = (key, type, ooxmlElement, schema) => ({
53633
+ }), markTextStyleValue2 = (key, type, ooxmlElement, schema, textStyleAttr) => ({
52888
53634
  key,
52889
53635
  type,
52890
53636
  ooxmlElement,
52891
53637
  storage: "mark",
52892
53638
  tracked: true,
52893
- carrier: markCarrier2("textStyle", key),
53639
+ carrier: markCarrier2("textStyle", textStyleAttr ?? key),
52894
53640
  schema
52895
53641
  }), runAttribute2 = (key, type, ooxmlElement, schema, runPropertyKey) => ({
52896
53642
  key,
@@ -60895,7 +61641,7 @@ var isRegExp = (value) => {
60895
61641
  tr,
60896
61642
  changed: true
60897
61643
  };
60898
- }, helpers_exports, translateImageNode = (params) => {
61644
+ }, helpers_exports, DECORATIVE_EXT_URI = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}", DECORATIVE_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2017/decorative", HYPERLINK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", translateImageNode = (params) => {
60899
61645
  const { node: { attrs = {} }, tableCell, imageSize } = params;
60900
61646
  let imageId = attrs.rId;
60901
61647
  const src = attrs.originalSrc || attrs.src || attrs.imageSrc;
@@ -60981,6 +61727,7 @@ var isRegExp = (value) => {
60981
61727
  const rawSrcRect = attrs.rawSrcRect;
60982
61728
  const drawingXmlns = "http://schemas.openxmlformats.org/drawingml/2006/main";
60983
61729
  const pictureXmlns = "http://schemas.openxmlformats.org/drawingml/2006/picture";
61730
+ const hlinkRId = resolveHyperlinkRId(attrs, params);
60984
61731
  return {
60985
61732
  attributes: inlineAttrs,
60986
61733
  elements: [
@@ -60995,20 +61742,14 @@ var isRegExp = (value) => {
60995
61742
  name: "wp:effectExtent",
60996
61743
  attributes: effectExtentAttrs
60997
61744
  },
60998
- {
60999
- name: "wp:docPr",
61000
- attributes: {
61001
- id: attrs.id || 0,
61002
- name: attrs.alt || `Picture ${imageName}`
61003
- }
61004
- },
61745
+ buildDocPrElement(attrs, imageName, hlinkRId),
61005
61746
  {
61006
61747
  name: "wp:cNvGraphicFramePr",
61007
61748
  elements: [{
61008
61749
  name: "a:graphicFrameLocks",
61009
61750
  attributes: {
61010
61751
  "xmlns:a": drawingXmlns,
61011
- noChangeAspect: 1
61752
+ ...attrs.lockAspectRatio ? { noChangeAspect: 1 } : {}
61012
61753
  }
61013
61754
  }]
61014
61755
  },
@@ -61022,25 +61763,7 @@ var isRegExp = (value) => {
61022
61763
  name: "pic:pic",
61023
61764
  attributes: { "xmlns:pic": pictureXmlns },
61024
61765
  elements: [
61025
- {
61026
- name: "pic:nvPicPr",
61027
- elements: [{
61028
- name: "pic:cNvPr",
61029
- attributes: {
61030
- id: attrs.id || 0,
61031
- name: attrs.title || `Picture ${imageName}`
61032
- }
61033
- }, {
61034
- name: "pic:cNvPicPr",
61035
- elements: [{
61036
- name: "a:picLocks",
61037
- attributes: {
61038
- noChangeAspect: 1,
61039
- noChangeArrowheads: 1
61040
- }
61041
- }]
61042
- }]
61043
- },
61766
+ buildNvPicPrElement(attrs, imageName, hlinkRId),
61044
61767
  {
61045
61768
  name: "pic:blipFill",
61046
61769
  elements: [
@@ -64289,7 +65012,7 @@ var isRegExp = (value) => {
64289
65012
  state.kern = kernNode.attributes["w:val"];
64290
65013
  }
64291
65014
  }, SuperConverter;
64292
- var init_SuperConverter_C3jSWLmj_es = __esm(() => {
65015
+ var init_SuperConverter_CHHvo5ta_es = __esm(() => {
64293
65016
  init_rolldown_runtime_B2q5OVn9_es();
64294
65017
  init_jszip_ChlR43oI_es();
64295
65018
  init_xml_js_DLE8mr0n_es();
@@ -66829,7 +67552,7 @@ var init_SuperConverter_C3jSWLmj_es = __esm(() => {
66829
67552
  markTextStyleValue2("position", "number", "w:position", schemaNumberOrNull2()),
66830
67553
  runAttribute2("dstrike", "boolean", "w:dstrike", schemaBooleanOrNull2()),
66831
67554
  runAttribute2("smallCaps", "boolean", "w:smallCaps", schemaBooleanOrNull2()),
66832
- runAttribute2("caps", "boolean", "w:caps", schemaBooleanOrNull2()),
67555
+ markTextStyleValue2("caps", "boolean", "w:caps", schemaBooleanOrNull2(), "textTransform"),
66833
67556
  runAttribute2("shading", "object", "w:shd", schemaObjectOrNull2({
66834
67557
  fill: { oneOf: [{
66835
67558
  type: "string",
@@ -69713,6 +70436,216 @@ var init_SuperConverter_C3jSWLmj_es = __esm(() => {
69713
70436
  referenceDocPath: "images/set-z-order.mdx",
69714
70437
  referenceGroup: "images"
69715
70438
  },
70439
+ "images.scale": {
70440
+ memberPath: "images.scale",
70441
+ description: "Scale an image by a uniform factor applied to both dimensions.",
70442
+ expectedResult: "Returns an ImagesMutationResult with the updated image address.",
70443
+ requiresDocumentContext: true,
70444
+ metadata: mutationOperation2({
70445
+ idempotency: "non-idempotent",
70446
+ supportsDryRun: true,
70447
+ supportsTrackedMode: false,
70448
+ possibleFailureCodes: ["NO_OP"],
70449
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70450
+ }),
70451
+ referenceDocPath: "images/scale.mdx",
70452
+ referenceGroup: "images"
70453
+ },
70454
+ "images.setLockAspectRatio": {
70455
+ memberPath: "images.setLockAspectRatio",
70456
+ description: "Lock or unlock the aspect ratio for an image.",
70457
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if already set.",
70458
+ requiresDocumentContext: true,
70459
+ metadata: mutationOperation2({
70460
+ idempotency: "conditional",
70461
+ supportsDryRun: true,
70462
+ supportsTrackedMode: false,
70463
+ possibleFailureCodes: ["NO_OP"],
70464
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70465
+ }),
70466
+ referenceDocPath: "images/set-lock-aspect-ratio.mdx",
70467
+ referenceGroup: "images"
70468
+ },
70469
+ "images.rotate": {
70470
+ memberPath: "images.rotate",
70471
+ description: "Set the absolute rotation angle for an image.",
70472
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if already set.",
70473
+ requiresDocumentContext: true,
70474
+ metadata: mutationOperation2({
70475
+ idempotency: "conditional",
70476
+ supportsDryRun: true,
70477
+ supportsTrackedMode: false,
70478
+ possibleFailureCodes: ["NO_OP"],
70479
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70480
+ }),
70481
+ referenceDocPath: "images/rotate.mdx",
70482
+ referenceGroup: "images"
70483
+ },
70484
+ "images.flip": {
70485
+ memberPath: "images.flip",
70486
+ description: "Set horizontal and/or vertical flip state for an image.",
70487
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if already set.",
70488
+ requiresDocumentContext: true,
70489
+ metadata: mutationOperation2({
70490
+ idempotency: "conditional",
70491
+ supportsDryRun: true,
70492
+ supportsTrackedMode: false,
70493
+ possibleFailureCodes: ["NO_OP"],
70494
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70495
+ }),
70496
+ referenceDocPath: "images/flip.mdx",
70497
+ referenceGroup: "images"
70498
+ },
70499
+ "images.crop": {
70500
+ memberPath: "images.crop",
70501
+ description: "Apply rectangular edge-percentage crop to an image.",
70502
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
70503
+ requiresDocumentContext: true,
70504
+ metadata: mutationOperation2({
70505
+ idempotency: "conditional",
70506
+ supportsDryRun: true,
70507
+ supportsTrackedMode: false,
70508
+ possibleFailureCodes: ["NO_OP"],
70509
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70510
+ }),
70511
+ referenceDocPath: "images/crop.mdx",
70512
+ referenceGroup: "images"
70513
+ },
70514
+ "images.resetCrop": {
70515
+ memberPath: "images.resetCrop",
70516
+ description: "Remove all cropping from an image.",
70517
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if no crop is set.",
70518
+ requiresDocumentContext: true,
70519
+ metadata: mutationOperation2({
70520
+ idempotency: "conditional",
70521
+ supportsDryRun: true,
70522
+ supportsTrackedMode: false,
70523
+ possibleFailureCodes: ["NO_OP"],
70524
+ throws: T_IMAGE_COMMAND2
70525
+ }),
70526
+ referenceDocPath: "images/reset-crop.mdx",
70527
+ referenceGroup: "images"
70528
+ },
70529
+ "images.replaceSource": {
70530
+ memberPath: "images.replaceSource",
70531
+ description: "Replace the image source while preserving identity and placement.",
70532
+ expectedResult: "Returns an ImagesMutationResult with the updated image address.",
70533
+ requiresDocumentContext: true,
70534
+ metadata: mutationOperation2({
70535
+ idempotency: "non-idempotent",
70536
+ supportsDryRun: true,
70537
+ supportsTrackedMode: false,
70538
+ possibleFailureCodes: ["NO_OP"],
70539
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70540
+ }),
70541
+ referenceDocPath: "images/replace-source.mdx",
70542
+ referenceGroup: "images"
70543
+ },
70544
+ "images.setAltText": {
70545
+ memberPath: "images.setAltText",
70546
+ description: "Set the accessibility description (alt text) for an image.",
70547
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
70548
+ requiresDocumentContext: true,
70549
+ metadata: mutationOperation2({
70550
+ idempotency: "conditional",
70551
+ supportsDryRun: true,
70552
+ supportsTrackedMode: false,
70553
+ possibleFailureCodes: ["NO_OP"],
70554
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70555
+ }),
70556
+ referenceDocPath: "images/set-alt-text.mdx",
70557
+ referenceGroup: "images"
70558
+ },
70559
+ "images.setDecorative": {
70560
+ memberPath: "images.setDecorative",
70561
+ description: "Mark or unmark an image as decorative.",
70562
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
70563
+ requiresDocumentContext: true,
70564
+ metadata: mutationOperation2({
70565
+ idempotency: "conditional",
70566
+ supportsDryRun: true,
70567
+ supportsTrackedMode: false,
70568
+ possibleFailureCodes: ["NO_OP"],
70569
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70570
+ }),
70571
+ referenceDocPath: "images/set-decorative.mdx",
70572
+ referenceGroup: "images"
70573
+ },
70574
+ "images.setName": {
70575
+ memberPath: "images.setName",
70576
+ description: "Set the object name for an image.",
70577
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
70578
+ requiresDocumentContext: true,
70579
+ metadata: mutationOperation2({
70580
+ idempotency: "conditional",
70581
+ supportsDryRun: true,
70582
+ supportsTrackedMode: false,
70583
+ possibleFailureCodes: ["NO_OP"],
70584
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70585
+ }),
70586
+ referenceDocPath: "images/set-name.mdx",
70587
+ referenceGroup: "images"
70588
+ },
70589
+ "images.setHyperlink": {
70590
+ memberPath: "images.setHyperlink",
70591
+ description: "Set or remove the hyperlink attached to an image.",
70592
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if unchanged.",
70593
+ requiresDocumentContext: true,
70594
+ metadata: mutationOperation2({
70595
+ idempotency: "conditional",
70596
+ supportsDryRun: true,
70597
+ supportsTrackedMode: false,
70598
+ possibleFailureCodes: ["NO_OP"],
70599
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70600
+ }),
70601
+ referenceDocPath: "images/set-hyperlink.mdx",
70602
+ referenceGroup: "images"
70603
+ },
70604
+ "images.insertCaption": {
70605
+ memberPath: "images.insertCaption",
70606
+ description: "Insert a caption paragraph below the image.",
70607
+ expectedResult: "Returns an ImagesMutationResult with the image address.",
70608
+ requiresDocumentContext: true,
70609
+ metadata: mutationOperation2({
70610
+ idempotency: "non-idempotent",
70611
+ supportsDryRun: true,
70612
+ supportsTrackedMode: false,
70613
+ possibleFailureCodes: ["NO_OP"],
70614
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70615
+ }),
70616
+ referenceDocPath: "images/insert-caption.mdx",
70617
+ referenceGroup: "images"
70618
+ },
70619
+ "images.updateCaption": {
70620
+ memberPath: "images.updateCaption",
70621
+ description: "Update the text of an existing caption paragraph.",
70622
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if text unchanged.",
70623
+ requiresDocumentContext: true,
70624
+ metadata: mutationOperation2({
70625
+ idempotency: "conditional",
70626
+ supportsDryRun: true,
70627
+ supportsTrackedMode: false,
70628
+ possibleFailureCodes: ["NO_OP"],
70629
+ throws: [...T_IMAGE_COMMAND2, "INVALID_INPUT"]
70630
+ }),
70631
+ referenceDocPath: "images/update-caption.mdx",
70632
+ referenceGroup: "images"
70633
+ },
70634
+ "images.removeCaption": {
70635
+ memberPath: "images.removeCaption",
70636
+ description: "Remove the caption paragraph from below the image.",
70637
+ expectedResult: "Returns an ImagesMutationResult; reports NO_OP if no caption exists.",
70638
+ requiresDocumentContext: true,
70639
+ metadata: mutationOperation2({
70640
+ idempotency: "conditional",
70641
+ supportsDryRun: true,
70642
+ supportsTrackedMode: false,
70643
+ possibleFailureCodes: ["NO_OP"],
70644
+ throws: T_IMAGE_COMMAND2
70645
+ }),
70646
+ referenceDocPath: "images/remove-caption.mdx",
70647
+ referenceGroup: "images"
70648
+ },
69716
70649
  "hyperlinks.list": {
69717
70650
  memberPath: "hyperlinks.list",
69718
70651
  description: "List all hyperlinks in the document, with optional filtering by href, anchor, or display text.",
@@ -73596,27 +74529,81 @@ var init_SuperConverter_C3jSWLmj_es = __esm(() => {
73596
74529
  code: { type: "string" },
73597
74530
  message: { type: "string" }
73598
74531
  }, ["code", "message"])
73599
- }, ["success", "failure"]), objectSchema2({
74532
+ }, ["success", "failure"]), imagesMutationSchemaSet2(objectSchema2({
73600
74533
  imageId: { type: "string" },
73601
74534
  zOrder: objectSchema2({ relativeHeight: {
73602
74535
  type: "integer",
73603
74536
  minimum: 0,
73604
74537
  maximum: Z_ORDER_RELATIVE_HEIGHT_MAX2
73605
74538
  } }, ["relativeHeight"])
73606
- }, ["imageId", "zOrder"]), objectSchema2({
73607
- success: { type: "boolean" },
73608
- image: { type: "object" },
73609
- failure: { type: "object" }
73610
- }), objectSchema2({
73611
- success: { const: true },
73612
- image: { type: "object" }
73613
- }, ["success", "image"]), objectSchema2({
73614
- success: { const: false },
73615
- failure: objectSchema2({
73616
- code: { type: "string" },
73617
- message: { type: "string" }
73618
- }, ["code", "message"])
73619
- }, ["success", "failure"]), objectSchema2({
74539
+ }, ["imageId", "zOrder"])), imagesMutationSchemaSet2(objectSchema2({
74540
+ imageId: { type: "string" },
74541
+ factor: {
74542
+ type: "number",
74543
+ exclusiveMinimum: 0
74544
+ }
74545
+ }, ["imageId", "factor"])), imagesMutationSchemaSet2(objectSchema2({
74546
+ imageId: { type: "string" },
74547
+ locked: { type: "boolean" }
74548
+ }, ["imageId", "locked"])), imagesMutationSchemaSet2(objectSchema2({
74549
+ imageId: { type: "string" },
74550
+ angle: {
74551
+ type: "number",
74552
+ minimum: 0,
74553
+ maximum: 360
74554
+ }
74555
+ }, ["imageId", "angle"])), imagesMutationSchemaSet2(objectSchema2({
74556
+ imageId: { type: "string" },
74557
+ horizontal: { type: "boolean" },
74558
+ vertical: { type: "boolean" }
74559
+ }, ["imageId"])), imagesMutationSchemaSet2(objectSchema2({
74560
+ imageId: { type: "string" },
74561
+ crop: objectSchema2({
74562
+ left: {
74563
+ type: "number",
74564
+ minimum: 0,
74565
+ maximum: 100
74566
+ },
74567
+ top: {
74568
+ type: "number",
74569
+ minimum: 0,
74570
+ maximum: 100
74571
+ },
74572
+ right: {
74573
+ type: "number",
74574
+ minimum: 0,
74575
+ maximum: 100
74576
+ },
74577
+ bottom: {
74578
+ type: "number",
74579
+ minimum: 0,
74580
+ maximum: 100
74581
+ }
74582
+ }, [])
74583
+ }, ["imageId", "crop"])), imagesMutationSchemaSet2(objectSchema2({ imageId: { type: "string" } }, ["imageId"])), imagesMutationSchemaSet2(objectSchema2({
74584
+ imageId: { type: "string" },
74585
+ src: { type: "string" },
74586
+ resetSize: { type: "boolean" }
74587
+ }, ["imageId", "src"])), imagesMutationSchemaSet2(objectSchema2({
74588
+ imageId: { type: "string" },
74589
+ description: { type: "string" }
74590
+ }, ["imageId", "description"])), imagesMutationSchemaSet2(objectSchema2({
74591
+ imageId: { type: "string" },
74592
+ decorative: { type: "boolean" }
74593
+ }, ["imageId", "decorative"])), imagesMutationSchemaSet2(objectSchema2({
74594
+ imageId: { type: "string" },
74595
+ name: { type: "string" }
74596
+ }, ["imageId", "name"])), imagesMutationSchemaSet2(objectSchema2({
74597
+ imageId: { type: "string" },
74598
+ url: { type: ["string", "null"] },
74599
+ tooltip: { type: "string" }
74600
+ }, ["imageId", "url"])), imagesMutationSchemaSet2(objectSchema2({
74601
+ imageId: { type: "string" },
74602
+ text: { type: "string" }
74603
+ }, ["imageId", "text"])), imagesMutationSchemaSet2(objectSchema2({
74604
+ imageId: { type: "string" },
74605
+ text: { type: "string" }
74606
+ }, ["imageId", "text"])), imagesMutationSchemaSet2(objectSchema2({ imageId: { type: "string" } }, ["imageId"])), objectSchema2({
73620
74607
  within: nodeAddressSchema2,
73621
74608
  hrefPattern: { type: "string" },
73622
74609
  anchor: { type: "string" },
@@ -120758,9 +121745,9 @@ var init_remark_gfm_CjV8kaUy_es = __esm(() => {
120758
121745
  init_remark_gfm_z_sDF4ss_es();
120759
121746
  });
120760
121747
 
120761
- // ../../packages/superdoc/dist/chunks/src-nq0HTKfv.es.js
120762
- var exports_src_nq0HTKfv_es = {};
120763
- __export(exports_src_nq0HTKfv_es, {
121748
+ // ../../packages/superdoc/dist/chunks/src-BneEE4-O.es.js
121749
+ var exports_src_BneEE4_O_es = {};
121750
+ __export(exports_src_BneEE4_O_es, {
120764
121751
  zt: () => defineMark,
120765
121752
  z: () => cM,
120766
121753
  yt: () => removeAwarenessStates,
@@ -128697,9 +129684,47 @@ function mapTableOfContentsNode(candidate) {
128697
129684
  }
128698
129685
  };
128699
129686
  }
128700
- function buildImageInfo(attrs, kind) {
129687
+ function parseCropFromClipPath$1(clipPath) {
129688
+ if (!clipPath)
129689
+ return null;
129690
+ const match$1 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
129691
+ if (!match$1)
129692
+ return null;
129693
+ return {
129694
+ top: parseFloat(match$1[1]),
129695
+ right: parseFloat(match$1[2]),
129696
+ bottom: parseFloat(match$1[3]),
129697
+ left: parseFloat(match$1[4])
129698
+ };
129699
+ }
129700
+ function detectCaptionSibling(doc$2, imagePos) {
129701
+ if (!doc$2)
129702
+ return false;
129703
+ try {
129704
+ const $pos = doc$2.resolve(imagePos);
129705
+ const parentDepth = $pos.depth - 1;
129706
+ if (parentDepth < 0)
129707
+ return false;
129708
+ const afterParentPos = $pos.before(parentDepth + 1) + $pos.node(parentDepth + 1).nodeSize;
129709
+ if (afterParentPos >= doc$2.content.size)
129710
+ return false;
129711
+ const nextNode = doc$2.nodeAt(afterParentPos);
129712
+ if (!nextNode || nextNode.type.name !== "paragraph")
129713
+ return false;
129714
+ return nextNode.attrs?.paragraphProperties?.styleId === "Caption";
129715
+ } catch {
129716
+ return false;
129717
+ }
129718
+ }
129719
+ function buildImageInfo(attrs, kind, doc$2, pos) {
128701
129720
  const isFloating = Boolean(attrs?.isAnchor);
128702
129721
  const wrapObj = attrs?.wrap;
129722
+ const td = attrs?.transformData;
129723
+ const transform = td && (td.rotation || td.verticalFlip || td.horizontalFlip) ? {
129724
+ rotation: td.rotation ?? undefined,
129725
+ verticalFlip: td.verticalFlip ?? undefined,
129726
+ horizontalFlip: td.horizontalFlip ?? undefined
129727
+ } : null;
128703
129728
  return {
128704
129729
  nodeType: "image",
128705
129730
  kind,
@@ -128718,7 +129743,15 @@ function buildImageInfo(attrs, kind) {
128718
129743
  },
128719
129744
  anchorData: attrs?.anchorData ?? null,
128720
129745
  marginOffset: attrs?.marginOffset ?? null,
128721
- relativeHeight: attrs?.relativeHeight ?? null
129746
+ relativeHeight: attrs?.relativeHeight ?? null,
129747
+ name: attrs?.alt ?? undefined,
129748
+ description: attrs?.title ?? undefined,
129749
+ transform,
129750
+ crop: parseCropFromClipPath$1(attrs?.clipPath),
129751
+ lockAspectRatio: attrs?.lockAspectRatio ?? true,
129752
+ decorative: attrs?.decorative ?? false,
129753
+ hyperlink: attrs?.hyperlink ?? null,
129754
+ hasCaption: pos != null ? detectCaptionSibling(doc$2, pos) : false
128722
129755
  }
128723
129756
  };
128724
129757
  }
@@ -128916,7 +129949,7 @@ function mapLineBreakNode() {
128916
129949
  function isInlineCandidate(candidate) {
128917
129950
  return "anchor" in candidate;
128918
129951
  }
128919
- function mapNodeInfo(candidate, overrideType) {
129952
+ function mapNodeInfo(candidate, overrideType, doc$2) {
128920
129953
  const nodeType = overrideType ?? candidate.nodeType;
128921
129954
  const kind = isInlineCandidate(candidate) ? "inline" : "block";
128922
129955
  switch (nodeType) {
@@ -128946,7 +129979,7 @@ function mapNodeInfo(candidate, overrideType) {
128946
129979
  return mapTableCellNode(candidate);
128947
129980
  case "image": {
128948
129981
  const attrs = candidate.node?.attrs;
128949
- return buildImageInfo(attrs, kind);
129982
+ return buildImageInfo(attrs, kind, doc$2, candidate.pos);
128950
129983
  }
128951
129984
  case "sdt": {
128952
129985
  const attrs = candidate.node?.attrs;
@@ -128989,7 +130022,7 @@ function resolveNodeInfoForAddress(editor, index2, address2, inlineIndex) {
128989
130022
  const candidate$1 = findBlockById(index2, address2);
128990
130023
  if (!candidate$1)
128991
130024
  return;
128992
- return mapNodeInfo(candidate$1, address2.nodeType);
130025
+ return mapNodeInfo(candidate$1, address2.nodeType, editor.state.doc);
128993
130026
  }
128994
130027
  const candidate = findInlineByAnchor(inlineIndex ?? getInlineIndex(editor), address2);
128995
130028
  if (!candidate)
@@ -129418,12 +130451,12 @@ function getNodeAdapter(editor, address2) {
129418
130451
  throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Node "${address2.nodeType}" not found for id "${address2.nodeId}".`);
129419
130452
  if (matches2.length > 1)
129420
130453
  throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Multiple nodes share ${address2.nodeType} id "${address2.nodeId}".`);
129421
- return mapNodeInfo(matches2[0], address2.nodeType);
130454
+ return mapNodeInfo(matches2[0], address2.nodeType, editor.state.doc);
129422
130455
  }
129423
130456
  const candidate = findInlineByAnchor(getInlineIndex(editor), address2);
129424
130457
  if (!candidate)
129425
130458
  throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Inline node "${address2.nodeType}" not found for the provided anchor.`);
129426
- return mapNodeInfo(candidate, address2.nodeType);
130459
+ return mapNodeInfo(candidate, address2.nodeType, editor.state.doc);
129427
130460
  }
129428
130461
  function resolveBlockById(editor, nodeId, nodeType) {
129429
130462
  const blockIndex = getBlockIndex(editor);
@@ -129457,7 +130490,7 @@ function resolveBlockById(editor, nodeId, nodeType) {
129457
130490
  function getNodeByIdAdapter(editor, input2) {
129458
130491
  const { nodeId, nodeType } = input2;
129459
130492
  const { candidate, resolvedType } = resolveBlockById(editor, nodeId, nodeType);
129460
- return mapNodeInfo(candidate, nodeType ?? resolvedType);
130493
+ return mapNodeInfo(candidate, nodeType ?? resolvedType, editor.state.doc);
129461
130494
  }
129462
130495
  function getTextAdapter(editor, _input) {
129463
130496
  const doc$2 = editor.state.doc;
@@ -131129,6 +132162,11 @@ function toPointString(value) {
131129
132162
  function toHalfPoints(value) {
131130
132163
  return Math.round(value * 2);
131131
132164
  }
132165
+ function capsToTextTransform(caps) {
132166
+ if (caps === null)
132167
+ return null;
132168
+ return caps ? "uppercase" : "none";
132169
+ }
131132
132170
  function collectInlineTextSegments(doc$2, absFrom, absTo) {
131133
132171
  const segments = [];
131134
132172
  doc$2.nodesBetween(absFrom, absTo, (node3, pos) => {
@@ -131178,8 +132216,7 @@ function applyHighlightPatch(tr, markType, absFrom, absTo, value) {
131178
132216
  }
131179
132217
  function mergeTextStyleAttrs(currentAttrs, patch3) {
131180
132218
  const next2 = { ...currentAttrs };
131181
- for (const key$1 of TEXT_STYLE_KEYS) {
131182
- const value = patch3[key$1];
132219
+ for (const [key$1, value] of Object.entries(patch3)) {
131183
132220
  if (value === undefined)
131184
132221
  continue;
131185
132222
  if (value === null) {
@@ -131482,6 +132519,8 @@ function applyInlinePatchToRange(editor, tr, absFrom, absTo, inline) {
131482
132519
  for (const key$1 of TEXT_STYLE_KEYS)
131483
132520
  if (inline[key$1] !== undefined)
131484
132521
  textStylePatch[key$1] = inline[key$1];
132522
+ if (inline.caps !== undefined)
132523
+ textStylePatch.textTransform = capsToTextTransform(inline.caps ?? null);
131485
132524
  if (applyTextStylePatch(tr, schema.marks.textStyle, absFrom, absTo, textStylePatch))
131486
132525
  changed = true;
131487
132526
  const runAttributeUpdates = buildRunAttributeUpdates(inline);
@@ -142824,7 +143863,38 @@ function buildNoOpResult(message) {
142824
143863
  }
142825
143864
  };
142826
143865
  }
142827
- function buildImageSummary(candidate) {
143866
+ function parseCropFromClipPath(clipPath) {
143867
+ if (!clipPath)
143868
+ return null;
143869
+ const match$1 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
143870
+ if (!match$1)
143871
+ return null;
143872
+ return {
143873
+ top: parseFloat(match$1[1]),
143874
+ right: parseFloat(match$1[2]),
143875
+ bottom: parseFloat(match$1[3]),
143876
+ left: parseFloat(match$1[4])
143877
+ };
143878
+ }
143879
+ function buildTransformInfo(td) {
143880
+ if (!td)
143881
+ return null;
143882
+ if (!td.rotation && !td.verticalFlip && !td.horizontalFlip)
143883
+ return null;
143884
+ return {
143885
+ rotation: td.rotation ?? undefined,
143886
+ verticalFlip: td.verticalFlip ?? undefined,
143887
+ horizontalFlip: td.horizontalFlip ?? undefined
143888
+ };
143889
+ }
143890
+ function hasCaptionSibling(editor, imagePos) {
143891
+ try {
143892
+ return findCaptionParagraph(editor, imagePos) !== null;
143893
+ } catch {
143894
+ return false;
143895
+ }
143896
+ }
143897
+ function buildImageSummary(editor, candidate) {
142828
143898
  const attrs = candidate.node.attrs;
142829
143899
  return {
142830
143900
  sdImageId: candidate.sdImageId,
@@ -142840,7 +143910,15 @@ function buildImageSummary(candidate) {
142840
143910
  },
142841
143911
  anchorData: attrs.anchorData ?? null,
142842
143912
  marginOffset: attrs.marginOffset ?? null,
142843
- relativeHeight: attrs.relativeHeight ?? null
143913
+ relativeHeight: attrs.relativeHeight ?? null,
143914
+ name: attrs.alt ?? undefined,
143915
+ description: attrs.title ?? undefined,
143916
+ transform: buildTransformInfo(attrs.transformData),
143917
+ crop: parseCropFromClipPath(attrs.clipPath),
143918
+ lockAspectRatio: attrs.lockAspectRatio ?? true,
143919
+ decorative: attrs.decorative ?? false,
143920
+ hyperlink: attrs.hyperlink ?? null,
143921
+ hasCaption: hasCaptionSibling(editor, candidate.pos)
142844
143922
  }
142845
143923
  };
142846
143924
  }
@@ -142874,14 +143952,14 @@ function imagesListWrapper(editor, input2) {
142874
143952
  const allImages = collectImages(editor.state.doc);
142875
143953
  const offset$1 = input2.offset ?? 0;
142876
143954
  const limit = input2.limit ?? allImages.length;
142877
- const items = allImages.slice(offset$1, offset$1 + limit).map(buildImageSummary);
143955
+ const items = allImages.slice(offset$1, offset$1 + limit).map((c$3) => buildImageSummary(editor, c$3));
142878
143956
  return {
142879
143957
  total: allImages.length,
142880
143958
  items
142881
143959
  };
142882
143960
  }
142883
143961
  function imagesGetWrapper(editor, input2) {
142884
- return buildImageSummary(findImageById(editor, input2.imageId));
143962
+ return buildImageSummary(editor, findImageById(editor, input2.imageId));
142885
143963
  }
142886
143964
  function createImageWrapper(editor, input2, options) {
142887
143965
  rejectTrackedMode("create.image", options);
@@ -143265,6 +144343,395 @@ function imagesSetZOrderWrapper(editor, input2, options) {
143265
144343
  return buildNoOpResult("Set z-order produced no change.");
143266
144344
  return buildSuccessResult(findImageById(editor, input2.imageId));
143267
144345
  }
144346
+ function imagesScaleWrapper(editor, input2, options) {
144347
+ rejectTrackedMode("images.scale", options);
144348
+ const image2 = findImageById(editor, input2.imageId);
144349
+ const currentSize = image2.node.attrs.size;
144350
+ if (!isFinitePositive2(currentSize?.width) || !isFinitePositive2(currentSize?.height))
144351
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Image has no explicit size; use setSize first.");
144352
+ const newSize = {
144353
+ width: Math.max(1, Math.round(currentSize.width * input2.factor)),
144354
+ height: Math.max(1, Math.round(currentSize.height * input2.factor))
144355
+ };
144356
+ if (newSize.width === currentSize.width && newSize.height === currentSize.height)
144357
+ return buildNoOpResult("Scale produced no size change.");
144358
+ if (options?.dryRun)
144359
+ return buildSuccessResult(image2);
144360
+ if (executeDomainCommand(editor, () => {
144361
+ const { pos, node: node3 } = image2;
144362
+ const tr = editor.state.tr;
144363
+ tr.setNodeMarkup(pos, undefined, {
144364
+ ...node3.attrs,
144365
+ size: newSize
144366
+ });
144367
+ if (!tr.docChanged)
144368
+ return false;
144369
+ editor.dispatch(tr);
144370
+ return true;
144371
+ }).steps[0]?.effect !== "changed")
144372
+ return buildNoOpResult("Scale produced no change.");
144373
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144374
+ }
144375
+ function imagesSetLockAspectRatioWrapper(editor, input2, options) {
144376
+ rejectTrackedMode("images.setLockAspectRatio", options);
144377
+ const image2 = findImageById(editor, input2.imageId);
144378
+ if ((image2.node.attrs.lockAspectRatio ?? true) === input2.locked)
144379
+ return buildNoOpResult(`lockAspectRatio is already ${input2.locked}.`);
144380
+ if (options?.dryRun)
144381
+ return buildSuccessResult(image2);
144382
+ if (executeDomainCommand(editor, () => {
144383
+ const { pos, node: node3 } = image2;
144384
+ const tr = editor.state.tr;
144385
+ tr.setNodeMarkup(pos, undefined, {
144386
+ ...node3.attrs,
144387
+ lockAspectRatio: input2.locked
144388
+ });
144389
+ editor.dispatch(tr);
144390
+ return true;
144391
+ }).steps[0]?.effect !== "changed")
144392
+ return buildNoOpResult("Set lock aspect ratio produced no change.");
144393
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144394
+ }
144395
+ function imagesRotateWrapper(editor, input2, options) {
144396
+ rejectTrackedMode("images.rotate", options);
144397
+ const image2 = findImageById(editor, input2.imageId);
144398
+ if ((image2.node.attrs.transformData?.rotation ?? 0) === input2.angle)
144399
+ return buildNoOpResult(`Rotation is already ${input2.angle} degrees.`);
144400
+ if (options?.dryRun)
144401
+ return buildSuccessResult(image2);
144402
+ if (executeDomainCommand(editor, () => {
144403
+ const { pos, node: node3 } = image2;
144404
+ const tr = editor.state.tr;
144405
+ tr.setNodeMarkup(pos, undefined, {
144406
+ ...node3.attrs,
144407
+ transformData: {
144408
+ ...node3.attrs.transformData ?? {},
144409
+ rotation: input2.angle
144410
+ }
144411
+ });
144412
+ editor.dispatch(tr);
144413
+ return true;
144414
+ }).steps[0]?.effect !== "changed")
144415
+ return buildNoOpResult("Rotate produced no change.");
144416
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144417
+ }
144418
+ function imagesFlipWrapper(editor, input2, options) {
144419
+ rejectTrackedMode("images.flip", options);
144420
+ const image2 = findImageById(editor, input2.imageId);
144421
+ const current = image2.node.attrs.transformData ?? {};
144422
+ const targetH = input2.horizontal ?? current.horizontalFlip ?? false;
144423
+ const targetV = input2.vertical ?? current.verticalFlip ?? false;
144424
+ if (targetH === (current.horizontalFlip ?? false) && targetV === (current.verticalFlip ?? false))
144425
+ return buildNoOpResult("Flip state is already as requested.");
144426
+ if (options?.dryRun)
144427
+ return buildSuccessResult(image2);
144428
+ if (executeDomainCommand(editor, () => {
144429
+ const { pos, node: node3 } = image2;
144430
+ const tr = editor.state.tr;
144431
+ tr.setNodeMarkup(pos, undefined, {
144432
+ ...node3.attrs,
144433
+ transformData: {
144434
+ ...node3.attrs.transformData ?? {},
144435
+ horizontalFlip: targetH,
144436
+ verticalFlip: targetV
144437
+ }
144438
+ });
144439
+ editor.dispatch(tr);
144440
+ return true;
144441
+ }).steps[0]?.effect !== "changed")
144442
+ return buildNoOpResult("Flip produced no change.");
144443
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144444
+ }
144445
+ function cropToClipPath(crop) {
144446
+ const { top: top$1 = 0, right: right$1 = 0, bottom: bottom$1 = 0, left: left$1 = 0 } = crop;
144447
+ return `inset(${top$1}% ${right$1}% ${bottom$1}% ${left$1}%)`;
144448
+ }
144449
+ function cropToRawSrcRect(crop) {
144450
+ const { top: top$1 = 0, right: right$1 = 0, bottom: bottom$1 = 0, left: left$1 = 0 } = crop;
144451
+ return {
144452
+ name: "a:srcRect",
144453
+ attributes: {
144454
+ l: String(Math.round(left$1 * 1000)),
144455
+ t: String(Math.round(top$1 * 1000)),
144456
+ r: String(Math.round(right$1 * 1000)),
144457
+ b: String(Math.round(bottom$1 * 1000))
144458
+ }
144459
+ };
144460
+ }
144461
+ function imagesCropWrapper(editor, input2, options) {
144462
+ rejectTrackedMode("images.crop", options);
144463
+ const image2 = findImageById(editor, input2.imageId);
144464
+ const newClipPath = cropToClipPath(input2.crop);
144465
+ if (image2.node.attrs.clipPath === newClipPath)
144466
+ return buildNoOpResult("Crop values are already as requested.");
144467
+ if (options?.dryRun)
144468
+ return buildSuccessResult(image2);
144469
+ if (executeDomainCommand(editor, () => {
144470
+ const { pos, node: node3 } = image2;
144471
+ const tr = editor.state.tr;
144472
+ tr.setNodeMarkup(pos, undefined, {
144473
+ ...node3.attrs,
144474
+ clipPath: newClipPath,
144475
+ rawSrcRect: cropToRawSrcRect(input2.crop)
144476
+ });
144477
+ if (!tr.docChanged)
144478
+ return false;
144479
+ editor.dispatch(tr);
144480
+ return true;
144481
+ }).steps[0]?.effect !== "changed")
144482
+ return buildNoOpResult("Crop produced no change.");
144483
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144484
+ }
144485
+ function imagesResetCropWrapper(editor, input2, options) {
144486
+ rejectTrackedMode("images.resetCrop", options);
144487
+ const image2 = findImageById(editor, input2.imageId);
144488
+ if (!image2.node.attrs.clipPath)
144489
+ return buildNoOpResult("Image has no crop to reset.");
144490
+ if (options?.dryRun)
144491
+ return buildSuccessResult(image2);
144492
+ if (executeDomainCommand(editor, () => {
144493
+ const { pos, node: node3 } = image2;
144494
+ const tr = editor.state.tr;
144495
+ tr.setNodeMarkup(pos, undefined, {
144496
+ ...node3.attrs,
144497
+ clipPath: null,
144498
+ rawSrcRect: null,
144499
+ shouldCover: false
144500
+ });
144501
+ if (!tr.docChanged)
144502
+ return false;
144503
+ editor.dispatch(tr);
144504
+ return true;
144505
+ }).steps[0]?.effect !== "changed")
144506
+ return buildNoOpResult("Reset crop produced no change.");
144507
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144508
+ }
144509
+ function imagesReplaceSourceWrapper(editor, input2, options) {
144510
+ rejectTrackedMode("images.replaceSource", options);
144511
+ const isDataUri = input2.src.startsWith("data:");
144512
+ const isInternalPath = input2.src.startsWith("word/media/");
144513
+ if (!isDataUri && !isInternalPath)
144514
+ throw new DocumentApiAdapterError("INVALID_INPUT", "External URLs are not supported in V1; provide a data URI or internal media path.");
144515
+ const image2 = findImageById(editor, input2.imageId);
144516
+ const newAttrs = {
144517
+ ...image2.node.attrs,
144518
+ src: input2.src,
144519
+ rId: null,
144520
+ originalSrc: null,
144521
+ originalExtension: null,
144522
+ clipPath: null,
144523
+ rawSrcRect: null,
144524
+ shouldCover: false
144525
+ };
144526
+ if (input2.resetSize) {
144527
+ if (!isDataUri)
144528
+ throw new DocumentApiAdapterError("INVALID_INPUT", "Cannot determine intrinsic dimensions from internal path; set size explicitly via setSize after replacement.");
144529
+ const dims = readImageDimensionsFromDataUri(input2.src);
144530
+ if (!dims)
144531
+ throw new DocumentApiAdapterError("INVALID_INPUT", "Could not determine intrinsic dimensions from data URI.");
144532
+ newAttrs.size = {
144533
+ width: dims.width,
144534
+ height: dims.height
144535
+ };
144536
+ }
144537
+ if (options?.dryRun)
144538
+ return buildSuccessResult(image2);
144539
+ if (executeDomainCommand(editor, () => {
144540
+ const { pos } = image2;
144541
+ const tr = editor.state.tr;
144542
+ tr.setNodeMarkup(pos, undefined, newAttrs);
144543
+ if (!tr.docChanged)
144544
+ return false;
144545
+ editor.dispatch(tr);
144546
+ return true;
144547
+ }).steps[0]?.effect !== "changed")
144548
+ return buildNoOpResult("Replace source produced no change.");
144549
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144550
+ }
144551
+ function imagesSetAltTextWrapper(editor, input2, options) {
144552
+ rejectTrackedMode("images.setAltText", options);
144553
+ const image2 = findImageById(editor, input2.imageId);
144554
+ if (image2.node.attrs.title === input2.description && !image2.node.attrs.decorative)
144555
+ return buildNoOpResult("Alt text is already as requested.");
144556
+ if (options?.dryRun)
144557
+ return buildSuccessResult(image2);
144558
+ if (executeDomainCommand(editor, () => {
144559
+ const { pos, node: node3 } = image2;
144560
+ const tr = editor.state.tr;
144561
+ tr.setNodeMarkup(pos, undefined, {
144562
+ ...node3.attrs,
144563
+ title: input2.description,
144564
+ decorative: false
144565
+ });
144566
+ editor.dispatch(tr);
144567
+ return true;
144568
+ }).steps[0]?.effect !== "changed")
144569
+ return buildNoOpResult("Set alt text produced no change.");
144570
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144571
+ }
144572
+ function imagesSetDecorativeWrapper(editor, input2, options) {
144573
+ rejectTrackedMode("images.setDecorative", options);
144574
+ const image2 = findImageById(editor, input2.imageId);
144575
+ if ((image2.node.attrs.decorative ?? false) === input2.decorative)
144576
+ return buildNoOpResult(`Decorative is already ${input2.decorative}.`);
144577
+ if (options?.dryRun)
144578
+ return buildSuccessResult(image2);
144579
+ if (executeDomainCommand(editor, () => {
144580
+ const { pos, node: node3 } = image2;
144581
+ const tr = editor.state.tr;
144582
+ tr.setNodeMarkup(pos, undefined, {
144583
+ ...node3.attrs,
144584
+ decorative: input2.decorative,
144585
+ title: input2.decorative ? "" : node3.attrs.title
144586
+ });
144587
+ editor.dispatch(tr);
144588
+ return true;
144589
+ }).steps[0]?.effect !== "changed")
144590
+ return buildNoOpResult("Set decorative produced no change.");
144591
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144592
+ }
144593
+ function imagesSetNameWrapper(editor, input2, options) {
144594
+ rejectTrackedMode("images.setName", options);
144595
+ const image2 = findImageById(editor, input2.imageId);
144596
+ if (image2.node.attrs.alt === input2.name)
144597
+ return buildNoOpResult("Name is already as requested.");
144598
+ if (options?.dryRun)
144599
+ return buildSuccessResult(image2);
144600
+ if (executeDomainCommand(editor, () => {
144601
+ const { pos, node: node3 } = image2;
144602
+ const tr = editor.state.tr;
144603
+ tr.setNodeMarkup(pos, undefined, {
144604
+ ...node3.attrs,
144605
+ alt: input2.name
144606
+ });
144607
+ editor.dispatch(tr);
144608
+ return true;
144609
+ }).steps[0]?.effect !== "changed")
144610
+ return buildNoOpResult("Set name produced no change.");
144611
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144612
+ }
144613
+ function imagesSetHyperlinkWrapper(editor, input2, options) {
144614
+ rejectTrackedMode("images.setHyperlink", options);
144615
+ const image2 = findImageById(editor, input2.imageId);
144616
+ const newValue = input2.url === null ? null : {
144617
+ url: input2.url,
144618
+ ...input2.tooltip ? { tooltip: input2.tooltip } : {}
144619
+ };
144620
+ const current = image2.node.attrs.hyperlink ?? null;
144621
+ if (current === null && newValue === null || current !== null && newValue !== null && current.url === newValue.url && current.tooltip === newValue.tooltip)
144622
+ return buildNoOpResult("Hyperlink is already as requested.");
144623
+ if (options?.dryRun)
144624
+ return buildSuccessResult(image2);
144625
+ if (executeDomainCommand(editor, () => {
144626
+ const { pos, node: node3 } = image2;
144627
+ const tr = editor.state.tr;
144628
+ tr.setNodeMarkup(pos, undefined, {
144629
+ ...node3.attrs,
144630
+ hyperlink: newValue
144631
+ });
144632
+ editor.dispatch(tr);
144633
+ return true;
144634
+ }).steps[0]?.effect !== "changed")
144635
+ return buildNoOpResult("Set hyperlink produced no change.");
144636
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144637
+ }
144638
+ function findCaptionParagraph(editor, imagePos) {
144639
+ const $pos = editor.state.doc.resolve(imagePos);
144640
+ const parentDepth = $pos.depth - 1;
144641
+ if (parentDepth < 0)
144642
+ return null;
144643
+ const afterParentPos = $pos.before(parentDepth + 1) + $pos.node(parentDepth + 1).nodeSize;
144644
+ if (afterParentPos >= editor.state.doc.content.size)
144645
+ return null;
144646
+ const nextNode = editor.state.doc.nodeAt(afterParentPos);
144647
+ if (!nextNode || nextNode.type.name !== "paragraph")
144648
+ return null;
144649
+ if (nextNode.attrs?.paragraphProperties?.styleId !== "Caption")
144650
+ return null;
144651
+ return {
144652
+ pos: afterParentPos,
144653
+ node: nextNode
144654
+ };
144655
+ }
144656
+ function requireSoleImageInParagraph(editor, imagePos) {
144657
+ const $pos = editor.state.doc.resolve(imagePos);
144658
+ const parentDepth = $pos.depth - 1;
144659
+ if (parentDepth < 0)
144660
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Caption operations require the image to be inside a paragraph.");
144661
+ const parentNode$1 = $pos.node(parentDepth + 1);
144662
+ let inlineContentCount = 0;
144663
+ parentNode$1.forEach((child) => {
144664
+ if (child.isInline)
144665
+ inlineContentCount++;
144666
+ });
144667
+ if (inlineContentCount !== 1)
144668
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Caption operations require the image to be the sole content of its paragraph.");
144669
+ }
144670
+ function imagesInsertCaptionWrapper(editor, input2, options) {
144671
+ rejectTrackedMode("images.insertCaption", options);
144672
+ const image2 = findImageById(editor, input2.imageId);
144673
+ requireSoleImageInParagraph(editor, image2.pos);
144674
+ if (findCaptionParagraph(editor, image2.pos))
144675
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Image already has a caption; use updateCaption.");
144676
+ if (options?.dryRun)
144677
+ return buildSuccessResult(image2);
144678
+ if (executeDomainCommand(editor, () => {
144679
+ const $pos = editor.state.doc.resolve(image2.pos);
144680
+ const parentDepth = $pos.depth - 1;
144681
+ const afterParentPos = $pos.before(parentDepth + 1) + $pos.node(parentDepth + 1).nodeSize;
144682
+ const tr = editor.state.tr;
144683
+ const captionPara = editor.state.schema.nodes.paragraph.create({ paragraphProperties: { styleId: "Caption" } }, editor.state.schema.text(input2.text));
144684
+ tr.insert(afterParentPos, captionPara);
144685
+ if (!tr.docChanged)
144686
+ return false;
144687
+ editor.dispatch(tr);
144688
+ return true;
144689
+ }).steps[0]?.effect !== "changed")
144690
+ return buildNoOpResult("Insert caption produced no change.");
144691
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144692
+ }
144693
+ function imagesUpdateCaptionWrapper(editor, input2, options) {
144694
+ rejectTrackedMode("images.updateCaption", options);
144695
+ const image2 = findImageById(editor, input2.imageId);
144696
+ requireSoleImageInParagraph(editor, image2.pos);
144697
+ const caption = findCaptionParagraph(editor, image2.pos);
144698
+ if (!caption)
144699
+ throw new DocumentApiAdapterError("INVALID_TARGET", "No caption paragraph found; use insertCaption first.");
144700
+ if (options?.dryRun)
144701
+ return buildSuccessResult(image2);
144702
+ if (executeDomainCommand(editor, () => {
144703
+ const tr = editor.state.tr;
144704
+ const textStart = caption.pos + 1;
144705
+ const textEnd = caption.pos + caption.node.nodeSize - 1;
144706
+ tr.replaceWith(textStart, textEnd, editor.state.schema.text(input2.text));
144707
+ if (!tr.docChanged)
144708
+ return false;
144709
+ editor.dispatch(tr);
144710
+ return true;
144711
+ }).steps[0]?.effect !== "changed")
144712
+ return buildNoOpResult("Update caption produced no change.");
144713
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144714
+ }
144715
+ function imagesRemoveCaptionWrapper(editor, input2, options) {
144716
+ rejectTrackedMode("images.removeCaption", options);
144717
+ const image2 = findImageById(editor, input2.imageId);
144718
+ requireSoleImageInParagraph(editor, image2.pos);
144719
+ const caption = findCaptionParagraph(editor, image2.pos);
144720
+ if (!caption)
144721
+ return buildNoOpResult("No caption to remove.");
144722
+ if (options?.dryRun)
144723
+ return buildSuccessResult(image2);
144724
+ if (executeDomainCommand(editor, () => {
144725
+ const tr = editor.state.tr;
144726
+ tr.delete(caption.pos, caption.pos + caption.node.nodeSize);
144727
+ if (!tr.docChanged)
144728
+ return false;
144729
+ editor.dispatch(tr);
144730
+ return true;
144731
+ }).steps[0]?.effect !== "changed")
144732
+ return buildNoOpResult("Remove caption produced no change.");
144733
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144734
+ }
143268
144735
  function getLinkMarkType(editor) {
143269
144736
  const markType = editor.schema.marks.link;
143270
144737
  if (!markType)
@@ -143936,7 +145403,21 @@ function assembleDocumentApiAdapters(editor) {
143936
145403
  setWrapDistances: (input2, options) => imagesSetWrapDistancesWrapper(editor, input2, options),
143937
145404
  setPosition: (input2, options) => imagesSetPositionWrapper(editor, input2, options),
143938
145405
  setAnchorOptions: (input2, options) => imagesSetAnchorOptionsWrapper(editor, input2, options),
143939
- setZOrder: (input2, options) => imagesSetZOrderWrapper(editor, input2, options)
145406
+ setZOrder: (input2, options) => imagesSetZOrderWrapper(editor, input2, options),
145407
+ scale: (input2, options) => imagesScaleWrapper(editor, input2, options),
145408
+ setLockAspectRatio: (input2, options) => imagesSetLockAspectRatioWrapper(editor, input2, options),
145409
+ rotate: (input2, options) => imagesRotateWrapper(editor, input2, options),
145410
+ flip: (input2, options) => imagesFlipWrapper(editor, input2, options),
145411
+ crop: (input2, options) => imagesCropWrapper(editor, input2, options),
145412
+ resetCrop: (input2, options) => imagesResetCropWrapper(editor, input2, options),
145413
+ replaceSource: (input2, options) => imagesReplaceSourceWrapper(editor, input2, options),
145414
+ setAltText: (input2, options) => imagesSetAltTextWrapper(editor, input2, options),
145415
+ setDecorative: (input2, options) => imagesSetDecorativeWrapper(editor, input2, options),
145416
+ setName: (input2, options) => imagesSetNameWrapper(editor, input2, options),
145417
+ setHyperlink: (input2, options) => imagesSetHyperlinkWrapper(editor, input2, options),
145418
+ insertCaption: (input2, options) => imagesInsertCaptionWrapper(editor, input2, options),
145419
+ updateCaption: (input2, options) => imagesUpdateCaptionWrapper(editor, input2, options),
145420
+ removeCaption: (input2, options) => imagesRemoveCaptionWrapper(editor, input2, options)
143940
145421
  },
143941
145422
  hyperlinks: {
143942
145423
  list: (query2) => hyperlinksListWrapper(editor, query2),
@@ -197248,9 +198729,9 @@ var Node$13 = class Node$14 {
197248
198729
  trackedChanges: context.trackedChanges ?? []
197249
198730
  });
197250
198731
  }, _hoisted_1$6, _hoisted_2$2, _hoisted_3, _hoisted_4, ContextMenu_default, _hoisted_1$5, BasicUpload_default, _hoisted_1$4, MIN_WIDTH = 200, PPI = 96, alignment = "flex-end", Ruler_default, GenericPopover_default, _hoisted_1$3, _hoisted_2$1, RESIZE_HANDLE_WIDTH_PX = 9, RESIZE_HANDLE_HEIGHT_PX = 9, RESIZE_HANDLE_OFFSET_PX = 4, DRAG_OVERLAY_EXTENSION_PX = 1000, MIN_DRAG_OVERLAY_WIDTH_PX = 2000, THROTTLE_INTERVAL_MS = 16, MIN_RESIZE_DELTA_PX = 1, TableResizeOverlay_default, _hoisted_1$2, OVERLAY_EXPANSION_PX = 2000, RESIZE_HANDLE_SIZE_PX = 12, MOUSE_MOVE_THROTTLE_MS = 16, DIMENSION_CHANGE_THRESHOLD_PX = 1, Z_INDEX_OVERLAY = 10, Z_INDEX_HANDLE = 15, Z_INDEX_GUIDELINE = 20, ImageResizeOverlay_default, LINK_CLICK_DEBOUNCE_MS = 300, CURSOR_UPDATE_TIMEOUT_MS = 10, POPOVER_VERTICAL_OFFSET_PX = 15, LinkClickHandler_default, _hoisted_1$1, _hoisted_2, DOCX2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.document", TABLE_RESIZE_HOVER_THRESHOLD = 8, TABLE_RESIZE_THROTTLE_MS = 16, SuperEditor_default, _hoisted_1, SuperInput_default, SlashMenu, Extensions;
197251
- var init_src_nq0HTKfv_es = __esm(() => {
198732
+ var init_src_BneEE4_O_es = __esm(() => {
197252
198733
  init_rolldown_runtime_B2q5OVn9_es();
197253
- init_SuperConverter_C3jSWLmj_es();
198734
+ init_SuperConverter_CHHvo5ta_es();
197254
198735
  init_jszip_ChlR43oI_es();
197255
198736
  init_uuid_qzgm05fK_es();
197256
198737
  init_constants_CMPtQbp7_es();
@@ -205525,7 +207006,21 @@ function print() { __p += __j.call(arguments, '') }
205525
207006
  "images.setWrapDistances": ["setImage"],
205526
207007
  "images.setPosition": ["setImage"],
205527
207008
  "images.setAnchorOptions": ["setImage"],
205528
- "images.setZOrder": ["setImage"]
207009
+ "images.setZOrder": ["setImage"],
207010
+ "images.scale": ["setImage"],
207011
+ "images.setLockAspectRatio": ["setImage"],
207012
+ "images.rotate": ["setImage"],
207013
+ "images.flip": ["setImage"],
207014
+ "images.crop": ["setImage"],
207015
+ "images.resetCrop": ["setImage"],
207016
+ "images.replaceSource": ["setImage"],
207017
+ "images.setAltText": ["setImage"],
207018
+ "images.setDecorative": ["setImage"],
207019
+ "images.setName": ["setImage"],
207020
+ "images.setHyperlink": ["setImage"],
207021
+ "images.insertCaption": ["setImage"],
207022
+ "images.updateCaption": ["setImage"],
207023
+ "images.removeCaption": ["setImage"]
205529
207024
  };
205530
207025
  VALID_CAPABILITY_REASON_CODES = new Set(CAPABILITY_REASON_CODES2);
205531
207026
  REQUIRED_HELPERS = {
@@ -222736,6 +224231,18 @@ function print() { __p += __j.call(arguments, '') }
222736
224231
  rawSrcRect: {
222737
224232
  default: null,
222738
224233
  rendered: false
224234
+ },
224235
+ lockAspectRatio: {
224236
+ default: true,
224237
+ rendered: false
224238
+ },
224239
+ decorative: {
224240
+ default: false,
224241
+ rendered: false
224242
+ },
224243
+ hyperlink: {
224244
+ default: null,
224245
+ rendered: false
222739
224246
  }
222740
224247
  };
222741
224248
  },
@@ -228932,8 +230439,8 @@ function print() { __p += __j.call(arguments, '') }
228932
230439
  return isObjectLike_default(value) && hasOwnProperty$8.call(value, "callee") && !propertyIsEnumerable$1.call(value, "callee");
228933
230440
  };
228934
230441
  stubFalse_default = stubFalse;
228935
- freeExports$2 = typeof exports_src_nq0HTKfv_es == "object" && exports_src_nq0HTKfv_es && !exports_src_nq0HTKfv_es.nodeType && exports_src_nq0HTKfv_es;
228936
- freeModule$2 = freeExports$2 && typeof module_src_nq0HTKfv_es == "object" && module_src_nq0HTKfv_es && !module_src_nq0HTKfv_es.nodeType && module_src_nq0HTKfv_es;
230442
+ freeExports$2 = typeof exports_src_BneEE4_O_es == "object" && exports_src_BneEE4_O_es && !exports_src_BneEE4_O_es.nodeType && exports_src_BneEE4_O_es;
230443
+ freeModule$2 = freeExports$2 && typeof module_src_BneEE4_O_es == "object" && module_src_BneEE4_O_es && !module_src_BneEE4_O_es.nodeType && module_src_BneEE4_O_es;
228937
230444
  Buffer$1 = freeModule$2 && freeModule$2.exports === freeExports$2 ? _root_default.Buffer : undefined;
228938
230445
  isBuffer_default = (Buffer$1 ? Buffer$1.isBuffer : undefined) || stubFalse_default;
228939
230446
  typedArrayTags = {};
@@ -228941,8 +230448,8 @@ function print() { __p += __j.call(arguments, '') }
228941
230448
  typedArrayTags[argsTag$1] = typedArrayTags[arrayTag$1] = typedArrayTags[arrayBufferTag$1] = typedArrayTags[boolTag$1] = typedArrayTags[dataViewTag$2] = typedArrayTags[dateTag$1] = typedArrayTags[errorTag$1] = typedArrayTags[funcTag] = typedArrayTags[mapTag$2] = typedArrayTags[numberTag$1] = typedArrayTags[objectTag$3] = typedArrayTags[regexpTag$1] = typedArrayTags[setTag$2] = typedArrayTags[stringTag$1] = typedArrayTags[weakMapTag$1] = false;
228942
230449
  _baseIsTypedArray_default = baseIsTypedArray;
228943
230450
  _baseUnary_default = baseUnary;
228944
- freeExports$1 = typeof exports_src_nq0HTKfv_es == "object" && exports_src_nq0HTKfv_es && !exports_src_nq0HTKfv_es.nodeType && exports_src_nq0HTKfv_es;
228945
- freeModule$1 = freeExports$1 && typeof module_src_nq0HTKfv_es == "object" && module_src_nq0HTKfv_es && !module_src_nq0HTKfv_es.nodeType && module_src_nq0HTKfv_es;
230451
+ freeExports$1 = typeof exports_src_BneEE4_O_es == "object" && exports_src_BneEE4_O_es && !exports_src_BneEE4_O_es.nodeType && exports_src_BneEE4_O_es;
230452
+ freeModule$1 = freeExports$1 && typeof module_src_BneEE4_O_es == "object" && module_src_BneEE4_O_es && !module_src_BneEE4_O_es.nodeType && module_src_BneEE4_O_es;
228946
230453
  freeProcess = freeModule$1 && freeModule$1.exports === freeExports$1 && _freeGlobal_default.process;
228947
230454
  _nodeUtil_default = function() {
228948
230455
  try {
@@ -229047,8 +230554,8 @@ function print() { __p += __j.call(arguments, '') }
229047
230554
  Stack.prototype.has = _stackHas_default;
229048
230555
  Stack.prototype.set = _stackSet_default;
229049
230556
  _Stack_default = Stack;
229050
- freeExports = typeof exports_src_nq0HTKfv_es == "object" && exports_src_nq0HTKfv_es && !exports_src_nq0HTKfv_es.nodeType && exports_src_nq0HTKfv_es;
229051
- freeModule = freeExports && typeof module_src_nq0HTKfv_es == "object" && module_src_nq0HTKfv_es && !module_src_nq0HTKfv_es.nodeType && module_src_nq0HTKfv_es;
230557
+ freeExports = typeof exports_src_BneEE4_O_es == "object" && exports_src_BneEE4_O_es && !exports_src_BneEE4_O_es.nodeType && exports_src_BneEE4_O_es;
230558
+ freeModule = freeExports && typeof module_src_BneEE4_O_es == "object" && module_src_BneEE4_O_es && !module_src_BneEE4_O_es.nodeType && module_src_BneEE4_O_es;
229052
230559
  Buffer4 = freeModule && freeModule.exports === freeExports ? _root_default.Buffer : undefined;
229053
230560
  allocUnsafe = Buffer4 ? Buffer4.allocUnsafe : undefined;
229054
230561
  _cloneBuffer_default = cloneBuffer;
@@ -237128,8 +238635,8 @@ var init_zipper_DqXT7uTa_es = __esm(() => {
237128
238635
 
237129
238636
  // ../../packages/superdoc/dist/super-editor.es.js
237130
238637
  var init_super_editor_es = __esm(() => {
237131
- init_src_nq0HTKfv_es();
237132
- init_SuperConverter_C3jSWLmj_es();
238638
+ init_src_BneEE4_O_es();
238639
+ init_SuperConverter_CHHvo5ta_es();
237133
238640
  init_jszip_ChlR43oI_es();
237134
238641
  init_xml_js_DLE8mr0n_es();
237135
238642
  init_constants_CMPtQbp7_es();
@@ -238496,9 +240003,49 @@ function mapTableOfContentsNode2(candidate) {
238496
240003
  }
238497
240004
  };
238498
240005
  }
238499
- function buildImageInfo2(attrs, kind) {
240006
+ function parseCropFromClipPath2(clipPath) {
240007
+ if (!clipPath)
240008
+ return null;
240009
+ const match2 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
240010
+ if (!match2)
240011
+ return null;
240012
+ return {
240013
+ top: parseFloat(match2[1]),
240014
+ right: parseFloat(match2[2]),
240015
+ bottom: parseFloat(match2[3]),
240016
+ left: parseFloat(match2[4])
240017
+ };
240018
+ }
240019
+ function detectCaptionSibling2(doc4, imagePos) {
240020
+ if (!doc4)
240021
+ return false;
240022
+ try {
240023
+ const $pos = doc4.resolve(imagePos);
240024
+ const parentDepth = $pos.depth - 1;
240025
+ if (parentDepth < 0)
240026
+ return false;
240027
+ const parentPos = $pos.before(parentDepth + 1);
240028
+ const parentNode2 = $pos.node(parentDepth + 1);
240029
+ const afterParentPos = parentPos + parentNode2.nodeSize;
240030
+ if (afterParentPos >= doc4.content.size)
240031
+ return false;
240032
+ const nextNode = doc4.nodeAt(afterParentPos);
240033
+ if (!nextNode || nextNode.type.name !== "paragraph")
240034
+ return false;
240035
+ return nextNode.attrs?.paragraphProperties?.styleId === "Caption";
240036
+ } catch {
240037
+ return false;
240038
+ }
240039
+ }
240040
+ function buildImageInfo2(attrs, kind, doc4, pos) {
238500
240041
  const isFloating = Boolean(attrs?.isAnchor);
238501
240042
  const wrapObj = attrs?.wrap;
240043
+ const td = attrs?.transformData;
240044
+ const transform = td && (td.rotation || td.verticalFlip || td.horizontalFlip) ? {
240045
+ rotation: td.rotation ?? undefined,
240046
+ verticalFlip: td.verticalFlip ?? undefined,
240047
+ horizontalFlip: td.horizontalFlip ?? undefined
240048
+ } : null;
238502
240049
  const properties = {
238503
240050
  src: attrs?.src ?? undefined,
238504
240051
  alt: attrs?.alt ?? undefined,
@@ -238514,7 +240061,15 @@ function buildImageInfo2(attrs, kind) {
238514
240061
  },
238515
240062
  anchorData: attrs?.anchorData ?? null,
238516
240063
  marginOffset: attrs?.marginOffset ?? null,
238517
- relativeHeight: attrs?.relativeHeight ?? null
240064
+ relativeHeight: attrs?.relativeHeight ?? null,
240065
+ name: attrs?.alt ?? undefined,
240066
+ description: attrs?.title ?? undefined,
240067
+ transform,
240068
+ crop: parseCropFromClipPath2(attrs?.clipPath),
240069
+ lockAspectRatio: attrs?.lockAspectRatio ?? true,
240070
+ decorative: attrs?.decorative ?? false,
240071
+ hyperlink: attrs?.hyperlink ?? null,
240072
+ hasCaption: pos != null ? detectCaptionSibling2(doc4, pos) : false
238518
240073
  };
238519
240074
  return {
238520
240075
  nodeType: "image",
@@ -238710,7 +240265,7 @@ function mapLineBreakNode2() {
238710
240265
  function isInlineCandidate2(candidate) {
238711
240266
  return "anchor" in candidate;
238712
240267
  }
238713
- function mapNodeInfo2(candidate, overrideType) {
240268
+ function mapNodeInfo2(candidate, overrideType, doc4) {
238714
240269
  const nodeType = overrideType ?? candidate.nodeType;
238715
240270
  const kind = isInlineCandidate2(candidate) ? "inline" : "block";
238716
240271
  switch (nodeType) {
@@ -238740,7 +240295,7 @@ function mapNodeInfo2(candidate, overrideType) {
238740
240295
  return mapTableCellNode2(candidate);
238741
240296
  case "image": {
238742
240297
  const attrs = candidate.node?.attrs;
238743
- return buildImageInfo2(attrs, kind);
240298
+ return buildImageInfo2(attrs, kind, doc4, candidate.pos);
238744
240299
  }
238745
240300
  case "sdt": {
238746
240301
  const attrs = candidate.node?.attrs;
@@ -238790,7 +240345,7 @@ function resolveNodeInfoForAddress2(editor, index2, address2, inlineIndex) {
238790
240345
  const candidate2 = findBlockById2(index2, address2);
238791
240346
  if (!candidate2)
238792
240347
  return;
238793
- return mapNodeInfo2(candidate2, address2.nodeType);
240348
+ return mapNodeInfo2(candidate2, address2.nodeType, editor.state.doc);
238794
240349
  }
238795
240350
  const resolvedInlineIndex = inlineIndex ?? getInlineIndex2(editor);
238796
240351
  const candidate = findInlineByAnchor2(resolvedInlineIndex, address2);
@@ -239336,14 +240891,14 @@ function getNodeAdapter2(editor, address2) {
239336
240891
  if (matches2.length > 1) {
239337
240892
  throw new DocumentApiAdapterError3("TARGET_NOT_FOUND", `Multiple nodes share ${address2.nodeType} id "${address2.nodeId}".`);
239338
240893
  }
239339
- return mapNodeInfo2(matches2[0], address2.nodeType);
240894
+ return mapNodeInfo2(matches2[0], address2.nodeType, editor.state.doc);
239340
240895
  }
239341
240896
  const inlineIndex = getInlineIndex2(editor);
239342
240897
  const candidate = findInlineByAnchor2(inlineIndex, address2);
239343
240898
  if (!candidate) {
239344
240899
  throw new DocumentApiAdapterError3("TARGET_NOT_FOUND", `Inline node "${address2.nodeType}" not found for the provided anchor.`);
239345
240900
  }
239346
- return mapNodeInfo2(candidate, address2.nodeType);
240901
+ return mapNodeInfo2(candidate, address2.nodeType, editor.state.doc);
239347
240902
  }
239348
240903
  function resolveBlockById2(editor, nodeId, nodeType) {
239349
240904
  const blockIndex = getBlockIndex2(editor);
@@ -239375,7 +240930,7 @@ function getNodeByIdAdapter2(editor, input2) {
239375
240930
  const { nodeId, nodeType } = input2;
239376
240931
  const { candidate, resolvedType } = resolveBlockById2(editor, nodeId, nodeType);
239377
240932
  const displayType = nodeType ?? resolvedType;
239378
- return mapNodeInfo2(candidate, displayType);
240933
+ return mapNodeInfo2(candidate, displayType, editor.state.doc);
239379
240934
  }
239380
240935
  var init_get_node_adapter = __esm(() => {
239381
240936
  init_index_cache();
@@ -282287,6 +283842,41 @@ function handleImageNode3(node4, params3, isAnchor) {
282287
283842
  };
282288
283843
  }
282289
283844
  }
283845
+ const nvPicPr = picture.elements.find((el) => el.name === "pic:nvPicPr");
283846
+ const cNvPicPr = nvPicPr?.elements?.find((el) => el.name === "pic:cNvPicPr");
283847
+ const picLocks = cNvPicPr?.elements?.find((el) => el.name === "a:picLocks");
283848
+ const lockAspectRatio = picLocks ? picLocks.attributes?.["noChangeAspect"] === "1" || picLocks.attributes?.["noChangeAspect"] === 1 : false;
283849
+ const cNvPr = nvPicPr?.elements?.find((el) => el.name === "pic:cNvPr");
283850
+ const hlinkClick = cNvPr?.elements?.find((el) => el.name === "a:hlinkClick") || docPr?.elements?.find((el) => el.name === "a:hlinkClick");
283851
+ let hyperlink = null;
283852
+ if (hlinkClick?.attributes?.["r:id"]) {
283853
+ const hlinkRId = hlinkClick.attributes["r:id"];
283854
+ const currentFile2 = filename || "document.xml";
283855
+ let hlinkRels = docx[`word/_rels/${currentFile2}.rels`];
283856
+ if (!hlinkRels)
283857
+ hlinkRels = docx[`word/_rels/document.xml.rels`];
283858
+ const hlinkRelationships = hlinkRels?.elements?.find((el) => el.name === "Relationships");
283859
+ const hlinkRel = hlinkRelationships?.elements?.find((el) => el.attributes?.["Id"] === hlinkRId);
283860
+ if (hlinkRel?.attributes?.["Target"]) {
283861
+ hyperlink = { url: hlinkRel.attributes["Target"] };
283862
+ if (hlinkClick.attributes?.["tooltip"]) {
283863
+ hyperlink.tooltip = hlinkClick.attributes["tooltip"];
283864
+ }
283865
+ }
283866
+ }
283867
+ let decorative = false;
283868
+ const docPrExtLst = docPr?.elements?.find((el) => el.name === "a:extLst");
283869
+ if (docPrExtLst) {
283870
+ for (const ext of docPrExtLst.elements || []) {
283871
+ if (ext.name !== "a:ext")
283872
+ continue;
283873
+ const decEl = ext.elements?.find((el) => el.name === "adec:decorative" || el.name === "a16:decorative");
283874
+ if (decEl && (decEl.attributes?.["val"] === "1" || decEl.attributes?.["val"] === 1)) {
283875
+ decorative = true;
283876
+ break;
283877
+ }
283878
+ }
283879
+ }
282290
283880
  const { attributes: blipAttributes = {} } = blip;
282291
283881
  const rEmbed = blipAttributes["r:embed"];
282292
283882
  if (!rEmbed) {
@@ -282381,6 +283971,9 @@ function handleImageNode3(node4, params3, isAnchor) {
282381
283971
  },
282382
283972
  originalAttributes: node4.attributes,
282383
283973
  rId: relAttributes["Id"],
283974
+ lockAspectRatio,
283975
+ decorative,
283976
+ hyperlink,
282384
283977
  ...order4.length ? { drawingChildOrder: order4 } : {},
282385
283978
  ...originalChildren.length ? { originalDrawingChildren: originalChildren } : {},
282386
283979
  ...hasGrayscale ? { grayscale: true } : {}
@@ -283098,6 +284691,103 @@ var init_image_dimensions = __esm(() => {
283098
284691
  });
283099
284692
 
283100
284693
  // ../../packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/decode-image-node-helpers.js
284694
+ function resolveHyperlinkRId2(attrs, params3) {
284695
+ if (!attrs.hyperlink?.url || !params3)
284696
+ return null;
284697
+ return addHyperlinkRelationship2(params3, attrs.hyperlink.url);
284698
+ }
284699
+ function buildHlinkClickElement2(attrs, hlinkRId) {
284700
+ if (!hlinkRId)
284701
+ return null;
284702
+ const hlinkAttrs = { "r:id": hlinkRId };
284703
+ if (attrs.hyperlink?.tooltip) {
284704
+ hlinkAttrs.tooltip = attrs.hyperlink.tooltip;
284705
+ }
284706
+ return { name: "a:hlinkClick", attributes: hlinkAttrs };
284707
+ }
284708
+ function buildDocPrElement2(attrs, imageName, hlinkRId) {
284709
+ const docPrAttrs = {
284710
+ id: attrs.id || 0,
284711
+ name: attrs.alt || `Picture ${imageName}`
284712
+ };
284713
+ if (!attrs.decorative && attrs.title) {
284714
+ docPrAttrs.descr = attrs.title;
284715
+ }
284716
+ const children = [];
284717
+ const hlinkEl = buildHlinkClickElement2(attrs, hlinkRId);
284718
+ if (hlinkEl)
284719
+ children.push(hlinkEl);
284720
+ if (attrs.decorative) {
284721
+ children.push({
284722
+ name: "a:extLst",
284723
+ elements: [
284724
+ {
284725
+ name: "a:ext",
284726
+ attributes: { uri: DECORATIVE_EXT_URI2 },
284727
+ elements: [
284728
+ {
284729
+ name: "adec:decorative",
284730
+ attributes: { "xmlns:adec": DECORATIVE_NAMESPACE2, val: "1" }
284731
+ }
284732
+ ]
284733
+ }
284734
+ ]
284735
+ });
284736
+ }
284737
+ return {
284738
+ name: "wp:docPr",
284739
+ attributes: docPrAttrs,
284740
+ ...children.length ? { elements: children } : {}
284741
+ };
284742
+ }
284743
+ function buildNvPicPrElement2(attrs, imageName, hlinkRId) {
284744
+ const cNvPrChildren = [];
284745
+ const hlinkEl = buildHlinkClickElement2(attrs, hlinkRId);
284746
+ if (hlinkEl)
284747
+ cNvPrChildren.push(hlinkEl);
284748
+ return {
284749
+ name: "pic:nvPicPr",
284750
+ elements: [
284751
+ {
284752
+ name: "pic:cNvPr",
284753
+ attributes: {
284754
+ id: attrs.id || 0,
284755
+ name: attrs.alt || `Picture ${imageName}`
284756
+ },
284757
+ ...cNvPrChildren.length ? { elements: cNvPrChildren } : {}
284758
+ },
284759
+ {
284760
+ name: "pic:cNvPicPr",
284761
+ elements: [
284762
+ {
284763
+ name: "a:picLocks",
284764
+ attributes: {
284765
+ ...attrs.lockAspectRatio ? { noChangeAspect: 1 } : {},
284766
+ noChangeArrowheads: 1
284767
+ }
284768
+ }
284769
+ ]
284770
+ }
284771
+ ]
284772
+ };
284773
+ }
284774
+ function addHyperlinkRelationship2(params3, url) {
284775
+ const newId = `rId${generateDocxRandomId2(8)}`;
284776
+ if (!params3.relationships || !Array.isArray(params3.relationships)) {
284777
+ params3.relationships = [];
284778
+ }
284779
+ params3.relationships.push({
284780
+ type: "element",
284781
+ name: "Relationship",
284782
+ attributes: {
284783
+ Id: newId,
284784
+ Type: HYPERLINK_REL_TYPE2,
284785
+ Target: url,
284786
+ TargetMode: "External"
284787
+ }
284788
+ });
284789
+ return newId;
284790
+ }
283101
284791
  function isFinitePositive3(value) {
283102
284792
  return typeof value === "number" && Number.isFinite(value) && value > 0;
283103
284793
  }
@@ -283203,7 +284893,7 @@ function translateShapeGroup2(params3) {
283203
284893
  elements: []
283204
284894
  });
283205
284895
  }
283206
- var translateImageNode2 = (params3) => {
284896
+ var DECORATIVE_EXT_URI2 = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}", DECORATIVE_NAMESPACE2 = "http://schemas.microsoft.com/office/drawing/2017/decorative", HYPERLINK_REL_TYPE2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", translateImageNode2 = (params3) => {
283207
284897
  const {
283208
284898
  node: { attrs = {} },
283209
284899
  tableCell: tableCell2,
@@ -283305,6 +284995,7 @@ var translateImageNode2 = (params3) => {
283305
284995
  const rawSrcRect = attrs.rawSrcRect;
283306
284996
  const drawingXmlns = "http://schemas.openxmlformats.org/drawingml/2006/main";
283307
284997
  const pictureXmlns = "http://schemas.openxmlformats.org/drawingml/2006/picture";
284998
+ const hlinkRId = resolveHyperlinkRId2(attrs, params3);
283308
284999
  return {
283309
285000
  attributes: inlineAttrs,
283310
285001
  elements: [
@@ -283319,13 +285010,7 @@ var translateImageNode2 = (params3) => {
283319
285010
  name: "wp:effectExtent",
283320
285011
  attributes: effectExtentAttrs
283321
285012
  },
283322
- {
283323
- name: "wp:docPr",
283324
- attributes: {
283325
- id: attrs.id || 0,
283326
- name: attrs.alt || `Picture ${imageName}`
283327
- }
283328
- },
285013
+ buildDocPrElement2(attrs, imageName, hlinkRId),
283329
285014
  {
283330
285015
  name: "wp:cNvGraphicFramePr",
283331
285016
  elements: [
@@ -283333,7 +285018,7 @@ var translateImageNode2 = (params3) => {
283333
285018
  name: "a:graphicFrameLocks",
283334
285019
  attributes: {
283335
285020
  "xmlns:a": drawingXmlns,
283336
- noChangeAspect: 1
285021
+ ...attrs.lockAspectRatio ? { noChangeAspect: 1 } : {}
283337
285022
  }
283338
285023
  }
283339
285024
  ]
@@ -283350,30 +285035,7 @@ var translateImageNode2 = (params3) => {
283350
285035
  name: "pic:pic",
283351
285036
  attributes: { "xmlns:pic": pictureXmlns },
283352
285037
  elements: [
283353
- {
283354
- name: "pic:nvPicPr",
283355
- elements: [
283356
- {
283357
- name: "pic:cNvPr",
283358
- attributes: {
283359
- id: attrs.id || 0,
283360
- name: attrs.title || `Picture ${imageName}`
283361
- }
283362
- },
283363
- {
283364
- name: "pic:cNvPicPr",
283365
- elements: [
283366
- {
283367
- name: "a:picLocks",
283368
- attributes: {
283369
- noChangeAspect: 1,
283370
- noChangeArrowheads: 1
283371
- }
283372
- }
283373
- ]
283374
- }
283375
- ]
283376
- },
285038
+ buildNvPicPrElement2(attrs, imageName, hlinkRId),
283377
285039
  {
283378
285040
  name: "pic:blipFill",
283379
285041
  elements: [
@@ -299120,7 +300782,21 @@ var init_capabilities_adapter = __esm(() => {
299120
300782
  "images.setWrapDistances": ["setImage"],
299121
300783
  "images.setPosition": ["setImage"],
299122
300784
  "images.setAnchorOptions": ["setImage"],
299123
- "images.setZOrder": ["setImage"]
300785
+ "images.setZOrder": ["setImage"],
300786
+ "images.scale": ["setImage"],
300787
+ "images.setLockAspectRatio": ["setImage"],
300788
+ "images.rotate": ["setImage"],
300789
+ "images.flip": ["setImage"],
300790
+ "images.crop": ["setImage"],
300791
+ "images.resetCrop": ["setImage"],
300792
+ "images.replaceSource": ["setImage"],
300793
+ "images.setAltText": ["setImage"],
300794
+ "images.setDecorative": ["setImage"],
300795
+ "images.setName": ["setImage"],
300796
+ "images.setHyperlink": ["setImage"],
300797
+ "images.insertCaption": ["setImage"],
300798
+ "images.updateCaption": ["setImage"],
300799
+ "images.removeCaption": ["setImage"]
299124
300800
  };
299125
300801
  VALID_CAPABILITY_REASON_CODES2 = new Set(CAPABILITY_REASON_CODES);
299126
300802
  REQUIRED_HELPERS2 = {
@@ -301032,6 +302708,11 @@ function toPointString2(value) {
301032
302708
  function toHalfPoints2(value) {
301033
302709
  return Math.round(value * 2);
301034
302710
  }
302711
+ function capsToTextTransform2(caps) {
302712
+ if (caps === null)
302713
+ return null;
302714
+ return caps ? "uppercase" : "none";
302715
+ }
301035
302716
  function collectInlineTextSegments2(doc4, absFrom, absTo) {
301036
302717
  const segments = [];
301037
302718
  doc4.nodesBetween(absFrom, absTo, (node4, pos) => {
@@ -301081,8 +302762,7 @@ function applyHighlightPatch2(tr, markType, absFrom, absTo, value) {
301081
302762
  }
301082
302763
  function mergeTextStyleAttrs2(currentAttrs, patch3) {
301083
302764
  const next2 = { ...currentAttrs };
301084
- for (const key2 of TEXT_STYLE_KEYS2) {
301085
- const value = patch3[key2];
302765
+ for (const [key2, value] of Object.entries(patch3)) {
301086
302766
  if (value === undefined)
301087
302767
  continue;
301088
302768
  if (value === null) {
@@ -301380,6 +303060,9 @@ function applyInlinePatchToRange2(editor, tr, absFrom, absTo, inline) {
301380
303060
  textStylePatch[key2] = inline[key2];
301381
303061
  }
301382
303062
  }
303063
+ if (inline.caps !== undefined) {
303064
+ textStylePatch.textTransform = capsToTextTransform2(inline.caps ?? null);
303065
+ }
301383
303066
  if (applyTextStylePatch2(tr, schema.marks.textStyle, absFrom, absTo, textStylePatch)) {
301384
303067
  changed = true;
301385
303068
  }
@@ -314026,7 +315709,38 @@ function buildSuccessResult2(candidate) {
314026
315709
  function buildNoOpResult2(message) {
314027
315710
  return { success: false, failure: { code: "NO_OP", message } };
314028
315711
  }
314029
- function buildImageSummary2(candidate) {
315712
+ function parseCropFromClipPath3(clipPath) {
315713
+ if (!clipPath)
315714
+ return null;
315715
+ const match2 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
315716
+ if (!match2)
315717
+ return null;
315718
+ return {
315719
+ top: parseFloat(match2[1]),
315720
+ right: parseFloat(match2[2]),
315721
+ bottom: parseFloat(match2[3]),
315722
+ left: parseFloat(match2[4])
315723
+ };
315724
+ }
315725
+ function buildTransformInfo2(td) {
315726
+ if (!td)
315727
+ return null;
315728
+ if (!td.rotation && !td.verticalFlip && !td.horizontalFlip)
315729
+ return null;
315730
+ return {
315731
+ rotation: td.rotation ?? undefined,
315732
+ verticalFlip: td.verticalFlip ?? undefined,
315733
+ horizontalFlip: td.horizontalFlip ?? undefined
315734
+ };
315735
+ }
315736
+ function hasCaptionSibling2(editor, imagePos) {
315737
+ try {
315738
+ return findCaptionParagraph2(editor, imagePos) !== null;
315739
+ } catch {
315740
+ return false;
315741
+ }
315742
+ }
315743
+ function buildImageSummary2(editor, candidate) {
314030
315744
  const attrs = candidate.node.attrs;
314031
315745
  return {
314032
315746
  sdImageId: candidate.sdImageId,
@@ -314042,7 +315756,15 @@ function buildImageSummary2(candidate) {
314042
315756
  },
314043
315757
  anchorData: attrs.anchorData ?? null,
314044
315758
  marginOffset: attrs.marginOffset ?? null,
314045
- relativeHeight: attrs.relativeHeight ?? null
315759
+ relativeHeight: attrs.relativeHeight ?? null,
315760
+ name: attrs.alt ?? undefined,
315761
+ description: attrs.title ?? undefined,
315762
+ transform: buildTransformInfo2(attrs.transformData),
315763
+ crop: parseCropFromClipPath3(attrs.clipPath),
315764
+ lockAspectRatio: attrs.lockAspectRatio ?? true,
315765
+ decorative: attrs.decorative ?? false,
315766
+ hyperlink: attrs.hyperlink ?? null,
315767
+ hasCaption: hasCaptionSibling2(editor, candidate.pos)
314046
315768
  }
314047
315769
  };
314048
315770
  }
@@ -314081,12 +315803,12 @@ function imagesListWrapper2(editor, input2) {
314081
315803
  const allImages = collectImages2(editor.state.doc);
314082
315804
  const offset2 = input2.offset ?? 0;
314083
315805
  const limit = input2.limit ?? allImages.length;
314084
- const items = allImages.slice(offset2, offset2 + limit).map(buildImageSummary2);
315806
+ const items = allImages.slice(offset2, offset2 + limit).map((c2) => buildImageSummary2(editor, c2));
314085
315807
  return { total: allImages.length, items };
314086
315808
  }
314087
315809
  function imagesGetWrapper2(editor, input2) {
314088
315810
  const image3 = findImageById2(editor, input2.imageId);
314089
- return buildImageSummary2(image3);
315811
+ return buildImageSummary2(editor, image3);
314090
315812
  }
314091
315813
  function createImageWrapper2(editor, input2, options) {
314092
315814
  rejectTrackedMode2("create.image", options);
@@ -314486,6 +316208,397 @@ function imagesSetZOrderWrapper2(editor, input2, options) {
314486
316208
  const updated = findImageById2(editor, input2.imageId);
314487
316209
  return buildSuccessResult2(updated);
314488
316210
  }
316211
+ function imagesScaleWrapper2(editor, input2, options) {
316212
+ rejectTrackedMode2("images.scale", options);
316213
+ const image3 = findImageById2(editor, input2.imageId);
316214
+ const currentSize = image3.node.attrs.size;
316215
+ if (!isFinitePositive4(currentSize?.width) || !isFinitePositive4(currentSize?.height)) {
316216
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Image has no explicit size; use setSize first.");
316217
+ }
316218
+ const newSize = {
316219
+ width: Math.max(1, Math.round(currentSize.width * input2.factor)),
316220
+ height: Math.max(1, Math.round(currentSize.height * input2.factor))
316221
+ };
316222
+ if (newSize.width === currentSize.width && newSize.height === currentSize.height) {
316223
+ return buildNoOpResult2("Scale produced no size change.");
316224
+ }
316225
+ if (options?.dryRun)
316226
+ return buildSuccessResult2(image3);
316227
+ const receipt2 = executeDomainCommand2(editor, () => {
316228
+ const { pos, node: node4 } = image3;
316229
+ const tr = editor.state.tr;
316230
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, size: newSize });
316231
+ if (!tr.docChanged)
316232
+ return false;
316233
+ editor.dispatch(tr);
316234
+ return true;
316235
+ });
316236
+ if (receipt2.steps[0]?.effect !== "changed")
316237
+ return buildNoOpResult2("Scale produced no change.");
316238
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316239
+ }
316240
+ function imagesSetLockAspectRatioWrapper2(editor, input2, options) {
316241
+ rejectTrackedMode2("images.setLockAspectRatio", options);
316242
+ const image3 = findImageById2(editor, input2.imageId);
316243
+ if ((image3.node.attrs.lockAspectRatio ?? true) === input2.locked) {
316244
+ return buildNoOpResult2(`lockAspectRatio is already ${input2.locked}.`);
316245
+ }
316246
+ if (options?.dryRun)
316247
+ return buildSuccessResult2(image3);
316248
+ const receipt2 = executeDomainCommand2(editor, () => {
316249
+ const { pos, node: node4 } = image3;
316250
+ const tr = editor.state.tr;
316251
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, lockAspectRatio: input2.locked });
316252
+ editor.dispatch(tr);
316253
+ return true;
316254
+ });
316255
+ if (receipt2.steps[0]?.effect !== "changed")
316256
+ return buildNoOpResult2("Set lock aspect ratio produced no change.");
316257
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316258
+ }
316259
+ function imagesRotateWrapper2(editor, input2, options) {
316260
+ rejectTrackedMode2("images.rotate", options);
316261
+ const image3 = findImageById2(editor, input2.imageId);
316262
+ const currentRotation = image3.node.attrs.transformData?.rotation ?? 0;
316263
+ if (currentRotation === input2.angle) {
316264
+ return buildNoOpResult2(`Rotation is already ${input2.angle} degrees.`);
316265
+ }
316266
+ if (options?.dryRun)
316267
+ return buildSuccessResult2(image3);
316268
+ const receipt2 = executeDomainCommand2(editor, () => {
316269
+ const { pos, node: node4 } = image3;
316270
+ const tr = editor.state.tr;
316271
+ tr.setNodeMarkup(pos, undefined, {
316272
+ ...node4.attrs,
316273
+ transformData: { ...node4.attrs.transformData ?? {}, rotation: input2.angle }
316274
+ });
316275
+ editor.dispatch(tr);
316276
+ return true;
316277
+ });
316278
+ if (receipt2.steps[0]?.effect !== "changed")
316279
+ return buildNoOpResult2("Rotate produced no change.");
316280
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316281
+ }
316282
+ function imagesFlipWrapper2(editor, input2, options) {
316283
+ rejectTrackedMode2("images.flip", options);
316284
+ const image3 = findImageById2(editor, input2.imageId);
316285
+ const current = image3.node.attrs.transformData ?? {};
316286
+ const targetH = input2.horizontal ?? current.horizontalFlip ?? false;
316287
+ const targetV = input2.vertical ?? current.verticalFlip ?? false;
316288
+ if (targetH === (current.horizontalFlip ?? false) && targetV === (current.verticalFlip ?? false)) {
316289
+ return buildNoOpResult2("Flip state is already as requested.");
316290
+ }
316291
+ if (options?.dryRun)
316292
+ return buildSuccessResult2(image3);
316293
+ const receipt2 = executeDomainCommand2(editor, () => {
316294
+ const { pos, node: node4 } = image3;
316295
+ const tr = editor.state.tr;
316296
+ tr.setNodeMarkup(pos, undefined, {
316297
+ ...node4.attrs,
316298
+ transformData: { ...node4.attrs.transformData ?? {}, horizontalFlip: targetH, verticalFlip: targetV }
316299
+ });
316300
+ editor.dispatch(tr);
316301
+ return true;
316302
+ });
316303
+ if (receipt2.steps[0]?.effect !== "changed")
316304
+ return buildNoOpResult2("Flip produced no change.");
316305
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316306
+ }
316307
+ function cropToClipPath2(crop) {
316308
+ const { top = 0, right: right2 = 0, bottom: bottom2 = 0, left: left2 = 0 } = crop;
316309
+ return `inset(${top}% ${right2}% ${bottom2}% ${left2}%)`;
316310
+ }
316311
+ function cropToRawSrcRect2(crop) {
316312
+ const { top = 0, right: right2 = 0, bottom: bottom2 = 0, left: left2 = 0 } = crop;
316313
+ return {
316314
+ name: "a:srcRect",
316315
+ attributes: {
316316
+ l: String(Math.round(left2 * 1000)),
316317
+ t: String(Math.round(top * 1000)),
316318
+ r: String(Math.round(right2 * 1000)),
316319
+ b: String(Math.round(bottom2 * 1000))
316320
+ }
316321
+ };
316322
+ }
316323
+ function imagesCropWrapper2(editor, input2, options) {
316324
+ rejectTrackedMode2("images.crop", options);
316325
+ const image3 = findImageById2(editor, input2.imageId);
316326
+ const newClipPath = cropToClipPath2(input2.crop);
316327
+ if (image3.node.attrs.clipPath === newClipPath) {
316328
+ return buildNoOpResult2("Crop values are already as requested.");
316329
+ }
316330
+ if (options?.dryRun)
316331
+ return buildSuccessResult2(image3);
316332
+ const receipt2 = executeDomainCommand2(editor, () => {
316333
+ const { pos, node: node4 } = image3;
316334
+ const tr = editor.state.tr;
316335
+ tr.setNodeMarkup(pos, undefined, {
316336
+ ...node4.attrs,
316337
+ clipPath: newClipPath,
316338
+ rawSrcRect: cropToRawSrcRect2(input2.crop)
316339
+ });
316340
+ if (!tr.docChanged)
316341
+ return false;
316342
+ editor.dispatch(tr);
316343
+ return true;
316344
+ });
316345
+ if (receipt2.steps[0]?.effect !== "changed")
316346
+ return buildNoOpResult2("Crop produced no change.");
316347
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316348
+ }
316349
+ function imagesResetCropWrapper2(editor, input2, options) {
316350
+ rejectTrackedMode2("images.resetCrop", options);
316351
+ const image3 = findImageById2(editor, input2.imageId);
316352
+ if (!image3.node.attrs.clipPath) {
316353
+ return buildNoOpResult2("Image has no crop to reset.");
316354
+ }
316355
+ if (options?.dryRun)
316356
+ return buildSuccessResult2(image3);
316357
+ const receipt2 = executeDomainCommand2(editor, () => {
316358
+ const { pos, node: node4 } = image3;
316359
+ const tr = editor.state.tr;
316360
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, clipPath: null, rawSrcRect: null, shouldCover: false });
316361
+ if (!tr.docChanged)
316362
+ return false;
316363
+ editor.dispatch(tr);
316364
+ return true;
316365
+ });
316366
+ if (receipt2.steps[0]?.effect !== "changed")
316367
+ return buildNoOpResult2("Reset crop produced no change.");
316368
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316369
+ }
316370
+ function imagesReplaceSourceWrapper2(editor, input2, options) {
316371
+ rejectTrackedMode2("images.replaceSource", options);
316372
+ const isDataUri = input2.src.startsWith("data:");
316373
+ const isInternalPath = input2.src.startsWith("word/media/");
316374
+ if (!isDataUri && !isInternalPath) {
316375
+ throw new DocumentApiAdapterError3("INVALID_INPUT", "External URLs are not supported in V1; provide a data URI or internal media path.");
316376
+ }
316377
+ const image3 = findImageById2(editor, input2.imageId);
316378
+ const newAttrs = {
316379
+ ...image3.node.attrs,
316380
+ src: input2.src,
316381
+ rId: null,
316382
+ originalSrc: null,
316383
+ originalExtension: null,
316384
+ clipPath: null,
316385
+ rawSrcRect: null,
316386
+ shouldCover: false
316387
+ };
316388
+ if (input2.resetSize) {
316389
+ if (!isDataUri) {
316390
+ throw new DocumentApiAdapterError3("INVALID_INPUT", "Cannot determine intrinsic dimensions from internal path; set size explicitly via setSize after replacement.");
316391
+ }
316392
+ const dims = readImageDimensionsFromDataUri2(input2.src);
316393
+ if (!dims) {
316394
+ throw new DocumentApiAdapterError3("INVALID_INPUT", "Could not determine intrinsic dimensions from data URI.");
316395
+ }
316396
+ newAttrs.size = { width: dims.width, height: dims.height };
316397
+ }
316398
+ if (options?.dryRun)
316399
+ return buildSuccessResult2(image3);
316400
+ const receipt2 = executeDomainCommand2(editor, () => {
316401
+ const { pos } = image3;
316402
+ const tr = editor.state.tr;
316403
+ tr.setNodeMarkup(pos, undefined, newAttrs);
316404
+ if (!tr.docChanged)
316405
+ return false;
316406
+ editor.dispatch(tr);
316407
+ return true;
316408
+ });
316409
+ if (receipt2.steps[0]?.effect !== "changed")
316410
+ return buildNoOpResult2("Replace source produced no change.");
316411
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316412
+ }
316413
+ function imagesSetAltTextWrapper2(editor, input2, options) {
316414
+ rejectTrackedMode2("images.setAltText", options);
316415
+ const image3 = findImageById2(editor, input2.imageId);
316416
+ if (image3.node.attrs.title === input2.description && !image3.node.attrs.decorative) {
316417
+ return buildNoOpResult2("Alt text is already as requested.");
316418
+ }
316419
+ if (options?.dryRun)
316420
+ return buildSuccessResult2(image3);
316421
+ const receipt2 = executeDomainCommand2(editor, () => {
316422
+ const { pos, node: node4 } = image3;
316423
+ const tr = editor.state.tr;
316424
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, title: input2.description, decorative: false });
316425
+ editor.dispatch(tr);
316426
+ return true;
316427
+ });
316428
+ if (receipt2.steps[0]?.effect !== "changed")
316429
+ return buildNoOpResult2("Set alt text produced no change.");
316430
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316431
+ }
316432
+ function imagesSetDecorativeWrapper2(editor, input2, options) {
316433
+ rejectTrackedMode2("images.setDecorative", options);
316434
+ const image3 = findImageById2(editor, input2.imageId);
316435
+ if ((image3.node.attrs.decorative ?? false) === input2.decorative) {
316436
+ return buildNoOpResult2(`Decorative is already ${input2.decorative}.`);
316437
+ }
316438
+ if (options?.dryRun)
316439
+ return buildSuccessResult2(image3);
316440
+ const receipt2 = executeDomainCommand2(editor, () => {
316441
+ const { pos, node: node4 } = image3;
316442
+ const tr = editor.state.tr;
316443
+ tr.setNodeMarkup(pos, undefined, {
316444
+ ...node4.attrs,
316445
+ decorative: input2.decorative,
316446
+ title: input2.decorative ? "" : node4.attrs.title
316447
+ });
316448
+ editor.dispatch(tr);
316449
+ return true;
316450
+ });
316451
+ if (receipt2.steps[0]?.effect !== "changed")
316452
+ return buildNoOpResult2("Set decorative produced no change.");
316453
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316454
+ }
316455
+ function imagesSetNameWrapper2(editor, input2, options) {
316456
+ rejectTrackedMode2("images.setName", options);
316457
+ const image3 = findImageById2(editor, input2.imageId);
316458
+ if (image3.node.attrs.alt === input2.name) {
316459
+ return buildNoOpResult2("Name is already as requested.");
316460
+ }
316461
+ if (options?.dryRun)
316462
+ return buildSuccessResult2(image3);
316463
+ const receipt2 = executeDomainCommand2(editor, () => {
316464
+ const { pos, node: node4 } = image3;
316465
+ const tr = editor.state.tr;
316466
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, alt: input2.name });
316467
+ editor.dispatch(tr);
316468
+ return true;
316469
+ });
316470
+ if (receipt2.steps[0]?.effect !== "changed")
316471
+ return buildNoOpResult2("Set name produced no change.");
316472
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316473
+ }
316474
+ function imagesSetHyperlinkWrapper2(editor, input2, options) {
316475
+ rejectTrackedMode2("images.setHyperlink", options);
316476
+ const image3 = findImageById2(editor, input2.imageId);
316477
+ const newValue = input2.url === null ? null : { url: input2.url, ...input2.tooltip ? { tooltip: input2.tooltip } : {} };
316478
+ const current = image3.node.attrs.hyperlink ?? null;
316479
+ if (current === null && newValue === null || current !== null && newValue !== null && current.url === newValue.url && current.tooltip === newValue.tooltip) {
316480
+ return buildNoOpResult2("Hyperlink is already as requested.");
316481
+ }
316482
+ if (options?.dryRun)
316483
+ return buildSuccessResult2(image3);
316484
+ const receipt2 = executeDomainCommand2(editor, () => {
316485
+ const { pos, node: node4 } = image3;
316486
+ const tr = editor.state.tr;
316487
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, hyperlink: newValue });
316488
+ editor.dispatch(tr);
316489
+ return true;
316490
+ });
316491
+ if (receipt2.steps[0]?.effect !== "changed")
316492
+ return buildNoOpResult2("Set hyperlink produced no change.");
316493
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316494
+ }
316495
+ function findCaptionParagraph2(editor, imagePos) {
316496
+ const $pos = editor.state.doc.resolve(imagePos);
316497
+ const parentDepth = $pos.depth - 1;
316498
+ if (parentDepth < 0)
316499
+ return null;
316500
+ const parentPos = $pos.before(parentDepth + 1);
316501
+ const parentNode2 = $pos.node(parentDepth + 1);
316502
+ const afterParentPos = parentPos + parentNode2.nodeSize;
316503
+ if (afterParentPos >= editor.state.doc.content.size)
316504
+ return null;
316505
+ const nextNode = editor.state.doc.nodeAt(afterParentPos);
316506
+ if (!nextNode || nextNode.type.name !== "paragraph")
316507
+ return null;
316508
+ if (nextNode.attrs?.paragraphProperties?.styleId !== "Caption")
316509
+ return null;
316510
+ return { pos: afterParentPos, node: nextNode };
316511
+ }
316512
+ function requireSoleImageInParagraph2(editor, imagePos) {
316513
+ const $pos = editor.state.doc.resolve(imagePos);
316514
+ const parentDepth = $pos.depth - 1;
316515
+ if (parentDepth < 0) {
316516
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Caption operations require the image to be inside a paragraph.");
316517
+ }
316518
+ const parentNode2 = $pos.node(parentDepth + 1);
316519
+ let inlineContentCount = 0;
316520
+ parentNode2.forEach((child) => {
316521
+ if (child.isInline)
316522
+ inlineContentCount++;
316523
+ });
316524
+ if (inlineContentCount !== 1) {
316525
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Caption operations require the image to be the sole content of its paragraph.");
316526
+ }
316527
+ }
316528
+ function imagesInsertCaptionWrapper2(editor, input2, options) {
316529
+ rejectTrackedMode2("images.insertCaption", options);
316530
+ const image3 = findImageById2(editor, input2.imageId);
316531
+ requireSoleImageInParagraph2(editor, image3.pos);
316532
+ const existing = findCaptionParagraph2(editor, image3.pos);
316533
+ if (existing) {
316534
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Image already has a caption; use updateCaption.");
316535
+ }
316536
+ if (options?.dryRun)
316537
+ return buildSuccessResult2(image3);
316538
+ const receipt2 = executeDomainCommand2(editor, () => {
316539
+ const $pos = editor.state.doc.resolve(image3.pos);
316540
+ const parentDepth = $pos.depth - 1;
316541
+ const parentPos = $pos.before(parentDepth + 1);
316542
+ const parentNode2 = $pos.node(parentDepth + 1);
316543
+ const afterParentPos = parentPos + parentNode2.nodeSize;
316544
+ const tr = editor.state.tr;
316545
+ const captionPara = editor.state.schema.nodes.paragraph.create({ paragraphProperties: { styleId: "Caption" } }, editor.state.schema.text(input2.text));
316546
+ tr.insert(afterParentPos, captionPara);
316547
+ if (!tr.docChanged)
316548
+ return false;
316549
+ editor.dispatch(tr);
316550
+ return true;
316551
+ });
316552
+ if (receipt2.steps[0]?.effect !== "changed")
316553
+ return buildNoOpResult2("Insert caption produced no change.");
316554
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316555
+ }
316556
+ function imagesUpdateCaptionWrapper2(editor, input2, options) {
316557
+ rejectTrackedMode2("images.updateCaption", options);
316558
+ const image3 = findImageById2(editor, input2.imageId);
316559
+ requireSoleImageInParagraph2(editor, image3.pos);
316560
+ const caption = findCaptionParagraph2(editor, image3.pos);
316561
+ if (!caption) {
316562
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "No caption paragraph found; use insertCaption first.");
316563
+ }
316564
+ if (options?.dryRun)
316565
+ return buildSuccessResult2(image3);
316566
+ const receipt2 = executeDomainCommand2(editor, () => {
316567
+ const tr = editor.state.tr;
316568
+ const textStart = caption.pos + 1;
316569
+ const textEnd = caption.pos + caption.node.nodeSize - 1;
316570
+ tr.replaceWith(textStart, textEnd, editor.state.schema.text(input2.text));
316571
+ if (!tr.docChanged)
316572
+ return false;
316573
+ editor.dispatch(tr);
316574
+ return true;
316575
+ });
316576
+ if (receipt2.steps[0]?.effect !== "changed")
316577
+ return buildNoOpResult2("Update caption produced no change.");
316578
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316579
+ }
316580
+ function imagesRemoveCaptionWrapper2(editor, input2, options) {
316581
+ rejectTrackedMode2("images.removeCaption", options);
316582
+ const image3 = findImageById2(editor, input2.imageId);
316583
+ requireSoleImageInParagraph2(editor, image3.pos);
316584
+ const caption = findCaptionParagraph2(editor, image3.pos);
316585
+ if (!caption) {
316586
+ return buildNoOpResult2("No caption to remove.");
316587
+ }
316588
+ if (options?.dryRun)
316589
+ return buildSuccessResult2(image3);
316590
+ const receipt2 = executeDomainCommand2(editor, () => {
316591
+ const tr = editor.state.tr;
316592
+ tr.delete(caption.pos, caption.pos + caption.node.nodeSize);
316593
+ if (!tr.docChanged)
316594
+ return false;
316595
+ editor.dispatch(tr);
316596
+ return true;
316597
+ });
316598
+ if (receipt2.steps[0]?.effect !== "changed")
316599
+ return buildNoOpResult2("Remove caption produced no change.");
316600
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316601
+ }
314489
316602
  var ALLOWED_WRAP_ATTRS2, WRAP_TYPES_SUPPORTING_SIDE2, WRAP_TYPES_SUPPORTING_DISTANCES2, RELATIVE_HEIGHT_MIN3 = 0, RELATIVE_HEIGHT_MAX3 = 4294967295;
314490
316603
  var init_images_wrappers = __esm(() => {
314491
316604
  init_wrapper();
@@ -315246,7 +317359,21 @@ function assembleDocumentApiAdapters2(editor) {
315246
317359
  setWrapDistances: (input2, options) => imagesSetWrapDistancesWrapper2(editor, input2, options),
315247
317360
  setPosition: (input2, options) => imagesSetPositionWrapper2(editor, input2, options),
315248
317361
  setAnchorOptions: (input2, options) => imagesSetAnchorOptionsWrapper2(editor, input2, options),
315249
- setZOrder: (input2, options) => imagesSetZOrderWrapper2(editor, input2, options)
317362
+ setZOrder: (input2, options) => imagesSetZOrderWrapper2(editor, input2, options),
317363
+ scale: (input2, options) => imagesScaleWrapper2(editor, input2, options),
317364
+ setLockAspectRatio: (input2, options) => imagesSetLockAspectRatioWrapper2(editor, input2, options),
317365
+ rotate: (input2, options) => imagesRotateWrapper2(editor, input2, options),
317366
+ flip: (input2, options) => imagesFlipWrapper2(editor, input2, options),
317367
+ crop: (input2, options) => imagesCropWrapper2(editor, input2, options),
317368
+ resetCrop: (input2, options) => imagesResetCropWrapper2(editor, input2, options),
317369
+ replaceSource: (input2, options) => imagesReplaceSourceWrapper2(editor, input2, options),
317370
+ setAltText: (input2, options) => imagesSetAltTextWrapper2(editor, input2, options),
317371
+ setDecorative: (input2, options) => imagesSetDecorativeWrapper2(editor, input2, options),
317372
+ setName: (input2, options) => imagesSetNameWrapper2(editor, input2, options),
317373
+ setHyperlink: (input2, options) => imagesSetHyperlinkWrapper2(editor, input2, options),
317374
+ insertCaption: (input2, options) => imagesInsertCaptionWrapper2(editor, input2, options),
317375
+ updateCaption: (input2, options) => imagesUpdateCaptionWrapper2(editor, input2, options),
317376
+ removeCaption: (input2, options) => imagesRemoveCaptionWrapper2(editor, input2, options)
315250
317377
  },
315251
317378
  hyperlinks: {
315252
317379
  list: (query2) => hyperlinksListWrapper2(editor, query2),
@@ -368495,6 +370622,25 @@ var init_collaboration = __esm(() => {
368495
370622
  });
368496
370623
 
368497
370624
  // src/lib/bootstrap.ts
370625
+ function waitForContentSettling(ydoc, maxWaitMs = CONTENT_SETTLING_MAX_MS) {
370626
+ if (detectRoomState(ydoc) === "populated")
370627
+ return Promise.resolve();
370628
+ const fragment = ydoc.getXmlFragment("supereditor");
370629
+ return new Promise((resolve4) => {
370630
+ const timeout2 = setTimeout(() => {
370631
+ fragment.unobserve(observer);
370632
+ resolve4();
370633
+ }, maxWaitMs);
370634
+ const observer = () => {
370635
+ if (fragment.length > 0) {
370636
+ clearTimeout(timeout2);
370637
+ fragment.unobserve(observer);
370638
+ resolve4();
370639
+ }
370640
+ };
370641
+ fragment.observe(observer);
370642
+ });
370643
+ }
368498
370644
  function detectRoomState(ydoc) {
368499
370645
  const fragment = ydoc.getXmlFragment("supereditor");
368500
370646
  if (fragment.length > 0)
@@ -368523,6 +370669,9 @@ function resolveBootstrapDecision(roomState, onMissing, hasDoc) {
368523
370669
  return { action: "error", reason: 'Collaboration room is empty and onMissing is set to "error".' };
368524
370670
  }
368525
370671
  }
370672
+ function clearBootstrapMarker(ydoc) {
370673
+ ydoc.getMap("meta").delete("bootstrap");
370674
+ }
368526
370675
  function writeBootstrapMarker(ydoc, source) {
368527
370676
  const metaMap = ydoc.getMap("meta");
368528
370677
  const marker = {
@@ -368605,7 +370754,7 @@ async function detectBootstrapRace(ydoc, observeMs = POST_SEED_OBSERVE_MS) {
368605
370754
  observer.dispose();
368606
370755
  }
368607
370756
  }
368608
- var DEFAULT_BOOTSTRAP_SETTLING_MS = 1500, DEFAULT_BOOTSTRAP_JITTER_MS = 150, POST_SEED_OBSERVE_MS = 200;
370757
+ var DEFAULT_BOOTSTRAP_SETTLING_MS = 1500, DEFAULT_BOOTSTRAP_JITTER_MS = 150, POST_SEED_OBSERVE_MS = 200, CONTENT_SETTLING_MAX_MS = 200;
368609
370758
 
368610
370759
  // src/lib/document.ts
368611
370760
  import { readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
@@ -368747,6 +370896,7 @@ async function openCollaborativeDocument(doc4, io, profile, options2 = {}) {
368747
370896
  const runtime = createCollaborationRuntime(profile);
368748
370897
  try {
368749
370898
  await runtime.waitForSync();
370899
+ await waitForContentSettling(runtime.ydoc);
368750
370900
  const onMissing = profile.onMissing ?? "seedFromDoc";
368751
370901
  let finalRoomState = detectRoomState(runtime.ydoc);
368752
370902
  let decision = resolveBootstrapDecision(finalRoomState, onMissing, doc4 != null);
@@ -368755,6 +370905,13 @@ async function openCollaborativeDocument(doc4, io, profile, options2 = {}) {
368755
370905
  if (!claim.granted) {
368756
370906
  finalRoomState = detectRoomState(runtime.ydoc);
368757
370907
  decision = { action: "join" };
370908
+ } else {
370909
+ const postClaimState = detectRoomState(runtime.ydoc);
370910
+ if (postClaimState === "populated") {
370911
+ clearBootstrapMarker(runtime.ydoc);
370912
+ finalRoomState = postClaimState;
370913
+ decision = { action: "join" };
370914
+ }
368758
370915
  }
368759
370916
  }
368760
370917
  if (decision.action === "error") {