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

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 +2282 -138
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -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-BcmJ8-gc.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
  }
@@ -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_BcmJ8_gc_es = __esm(() => {
64293
65016
  init_rolldown_runtime_B2q5OVn9_es();
64294
65017
  init_jszip_ChlR43oI_es();
64295
65018
  init_xml_js_DLE8mr0n_es();
@@ -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-LqliKMID.es.js
121749
+ var exports_src_LqliKMID_es = {};
121750
+ __export(exports_src_LqliKMID_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;
@@ -142824,7 +143857,38 @@ function buildNoOpResult(message) {
142824
143857
  }
142825
143858
  };
142826
143859
  }
142827
- function buildImageSummary(candidate) {
143860
+ function parseCropFromClipPath(clipPath) {
143861
+ if (!clipPath)
143862
+ return null;
143863
+ const match$1 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
143864
+ if (!match$1)
143865
+ return null;
143866
+ return {
143867
+ top: parseFloat(match$1[1]),
143868
+ right: parseFloat(match$1[2]),
143869
+ bottom: parseFloat(match$1[3]),
143870
+ left: parseFloat(match$1[4])
143871
+ };
143872
+ }
143873
+ function buildTransformInfo(td) {
143874
+ if (!td)
143875
+ return null;
143876
+ if (!td.rotation && !td.verticalFlip && !td.horizontalFlip)
143877
+ return null;
143878
+ return {
143879
+ rotation: td.rotation ?? undefined,
143880
+ verticalFlip: td.verticalFlip ?? undefined,
143881
+ horizontalFlip: td.horizontalFlip ?? undefined
143882
+ };
143883
+ }
143884
+ function hasCaptionSibling(editor, imagePos) {
143885
+ try {
143886
+ return findCaptionParagraph(editor, imagePos) !== null;
143887
+ } catch {
143888
+ return false;
143889
+ }
143890
+ }
143891
+ function buildImageSummary(editor, candidate) {
142828
143892
  const attrs = candidate.node.attrs;
142829
143893
  return {
142830
143894
  sdImageId: candidate.sdImageId,
@@ -142840,7 +143904,15 @@ function buildImageSummary(candidate) {
142840
143904
  },
142841
143905
  anchorData: attrs.anchorData ?? null,
142842
143906
  marginOffset: attrs.marginOffset ?? null,
142843
- relativeHeight: attrs.relativeHeight ?? null
143907
+ relativeHeight: attrs.relativeHeight ?? null,
143908
+ name: attrs.alt ?? undefined,
143909
+ description: attrs.title ?? undefined,
143910
+ transform: buildTransformInfo(attrs.transformData),
143911
+ crop: parseCropFromClipPath(attrs.clipPath),
143912
+ lockAspectRatio: attrs.lockAspectRatio ?? true,
143913
+ decorative: attrs.decorative ?? false,
143914
+ hyperlink: attrs.hyperlink ?? null,
143915
+ hasCaption: hasCaptionSibling(editor, candidate.pos)
142844
143916
  }
142845
143917
  };
142846
143918
  }
@@ -142874,14 +143946,14 @@ function imagesListWrapper(editor, input2) {
142874
143946
  const allImages = collectImages(editor.state.doc);
142875
143947
  const offset$1 = input2.offset ?? 0;
142876
143948
  const limit = input2.limit ?? allImages.length;
142877
- const items = allImages.slice(offset$1, offset$1 + limit).map(buildImageSummary);
143949
+ const items = allImages.slice(offset$1, offset$1 + limit).map((c$3) => buildImageSummary(editor, c$3));
142878
143950
  return {
142879
143951
  total: allImages.length,
142880
143952
  items
142881
143953
  };
142882
143954
  }
142883
143955
  function imagesGetWrapper(editor, input2) {
142884
- return buildImageSummary(findImageById(editor, input2.imageId));
143956
+ return buildImageSummary(editor, findImageById(editor, input2.imageId));
142885
143957
  }
142886
143958
  function createImageWrapper(editor, input2, options) {
142887
143959
  rejectTrackedMode("create.image", options);
@@ -143265,6 +144337,395 @@ function imagesSetZOrderWrapper(editor, input2, options) {
143265
144337
  return buildNoOpResult("Set z-order produced no change.");
143266
144338
  return buildSuccessResult(findImageById(editor, input2.imageId));
143267
144339
  }
144340
+ function imagesScaleWrapper(editor, input2, options) {
144341
+ rejectTrackedMode("images.scale", options);
144342
+ const image2 = findImageById(editor, input2.imageId);
144343
+ const currentSize = image2.node.attrs.size;
144344
+ if (!isFinitePositive2(currentSize?.width) || !isFinitePositive2(currentSize?.height))
144345
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Image has no explicit size; use setSize first.");
144346
+ const newSize = {
144347
+ width: Math.max(1, Math.round(currentSize.width * input2.factor)),
144348
+ height: Math.max(1, Math.round(currentSize.height * input2.factor))
144349
+ };
144350
+ if (newSize.width === currentSize.width && newSize.height === currentSize.height)
144351
+ return buildNoOpResult("Scale produced no size change.");
144352
+ if (options?.dryRun)
144353
+ return buildSuccessResult(image2);
144354
+ if (executeDomainCommand(editor, () => {
144355
+ const { pos, node: node3 } = image2;
144356
+ const tr = editor.state.tr;
144357
+ tr.setNodeMarkup(pos, undefined, {
144358
+ ...node3.attrs,
144359
+ size: newSize
144360
+ });
144361
+ if (!tr.docChanged)
144362
+ return false;
144363
+ editor.dispatch(tr);
144364
+ return true;
144365
+ }).steps[0]?.effect !== "changed")
144366
+ return buildNoOpResult("Scale produced no change.");
144367
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144368
+ }
144369
+ function imagesSetLockAspectRatioWrapper(editor, input2, options) {
144370
+ rejectTrackedMode("images.setLockAspectRatio", options);
144371
+ const image2 = findImageById(editor, input2.imageId);
144372
+ if ((image2.node.attrs.lockAspectRatio ?? true) === input2.locked)
144373
+ return buildNoOpResult(`lockAspectRatio is already ${input2.locked}.`);
144374
+ if (options?.dryRun)
144375
+ return buildSuccessResult(image2);
144376
+ if (executeDomainCommand(editor, () => {
144377
+ const { pos, node: node3 } = image2;
144378
+ const tr = editor.state.tr;
144379
+ tr.setNodeMarkup(pos, undefined, {
144380
+ ...node3.attrs,
144381
+ lockAspectRatio: input2.locked
144382
+ });
144383
+ editor.dispatch(tr);
144384
+ return true;
144385
+ }).steps[0]?.effect !== "changed")
144386
+ return buildNoOpResult("Set lock aspect ratio produced no change.");
144387
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144388
+ }
144389
+ function imagesRotateWrapper(editor, input2, options) {
144390
+ rejectTrackedMode("images.rotate", options);
144391
+ const image2 = findImageById(editor, input2.imageId);
144392
+ if ((image2.node.attrs.transformData?.rotation ?? 0) === input2.angle)
144393
+ return buildNoOpResult(`Rotation is already ${input2.angle} degrees.`);
144394
+ if (options?.dryRun)
144395
+ return buildSuccessResult(image2);
144396
+ if (executeDomainCommand(editor, () => {
144397
+ const { pos, node: node3 } = image2;
144398
+ const tr = editor.state.tr;
144399
+ tr.setNodeMarkup(pos, undefined, {
144400
+ ...node3.attrs,
144401
+ transformData: {
144402
+ ...node3.attrs.transformData ?? {},
144403
+ rotation: input2.angle
144404
+ }
144405
+ });
144406
+ editor.dispatch(tr);
144407
+ return true;
144408
+ }).steps[0]?.effect !== "changed")
144409
+ return buildNoOpResult("Rotate produced no change.");
144410
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144411
+ }
144412
+ function imagesFlipWrapper(editor, input2, options) {
144413
+ rejectTrackedMode("images.flip", options);
144414
+ const image2 = findImageById(editor, input2.imageId);
144415
+ const current = image2.node.attrs.transformData ?? {};
144416
+ const targetH = input2.horizontal ?? current.horizontalFlip ?? false;
144417
+ const targetV = input2.vertical ?? current.verticalFlip ?? false;
144418
+ if (targetH === (current.horizontalFlip ?? false) && targetV === (current.verticalFlip ?? false))
144419
+ return buildNoOpResult("Flip state is already as requested.");
144420
+ if (options?.dryRun)
144421
+ return buildSuccessResult(image2);
144422
+ if (executeDomainCommand(editor, () => {
144423
+ const { pos, node: node3 } = image2;
144424
+ const tr = editor.state.tr;
144425
+ tr.setNodeMarkup(pos, undefined, {
144426
+ ...node3.attrs,
144427
+ transformData: {
144428
+ ...node3.attrs.transformData ?? {},
144429
+ horizontalFlip: targetH,
144430
+ verticalFlip: targetV
144431
+ }
144432
+ });
144433
+ editor.dispatch(tr);
144434
+ return true;
144435
+ }).steps[0]?.effect !== "changed")
144436
+ return buildNoOpResult("Flip produced no change.");
144437
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144438
+ }
144439
+ function cropToClipPath(crop) {
144440
+ const { top: top$1 = 0, right: right$1 = 0, bottom: bottom$1 = 0, left: left$1 = 0 } = crop;
144441
+ return `inset(${top$1}% ${right$1}% ${bottom$1}% ${left$1}%)`;
144442
+ }
144443
+ function cropToRawSrcRect(crop) {
144444
+ const { top: top$1 = 0, right: right$1 = 0, bottom: bottom$1 = 0, left: left$1 = 0 } = crop;
144445
+ return {
144446
+ name: "a:srcRect",
144447
+ attributes: {
144448
+ l: String(Math.round(left$1 * 1000)),
144449
+ t: String(Math.round(top$1 * 1000)),
144450
+ r: String(Math.round(right$1 * 1000)),
144451
+ b: String(Math.round(bottom$1 * 1000))
144452
+ }
144453
+ };
144454
+ }
144455
+ function imagesCropWrapper(editor, input2, options) {
144456
+ rejectTrackedMode("images.crop", options);
144457
+ const image2 = findImageById(editor, input2.imageId);
144458
+ const newClipPath = cropToClipPath(input2.crop);
144459
+ if (image2.node.attrs.clipPath === newClipPath)
144460
+ return buildNoOpResult("Crop values are already as requested.");
144461
+ if (options?.dryRun)
144462
+ return buildSuccessResult(image2);
144463
+ if (executeDomainCommand(editor, () => {
144464
+ const { pos, node: node3 } = image2;
144465
+ const tr = editor.state.tr;
144466
+ tr.setNodeMarkup(pos, undefined, {
144467
+ ...node3.attrs,
144468
+ clipPath: newClipPath,
144469
+ rawSrcRect: cropToRawSrcRect(input2.crop)
144470
+ });
144471
+ if (!tr.docChanged)
144472
+ return false;
144473
+ editor.dispatch(tr);
144474
+ return true;
144475
+ }).steps[0]?.effect !== "changed")
144476
+ return buildNoOpResult("Crop produced no change.");
144477
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144478
+ }
144479
+ function imagesResetCropWrapper(editor, input2, options) {
144480
+ rejectTrackedMode("images.resetCrop", options);
144481
+ const image2 = findImageById(editor, input2.imageId);
144482
+ if (!image2.node.attrs.clipPath)
144483
+ return buildNoOpResult("Image has no crop to reset.");
144484
+ if (options?.dryRun)
144485
+ return buildSuccessResult(image2);
144486
+ if (executeDomainCommand(editor, () => {
144487
+ const { pos, node: node3 } = image2;
144488
+ const tr = editor.state.tr;
144489
+ tr.setNodeMarkup(pos, undefined, {
144490
+ ...node3.attrs,
144491
+ clipPath: null,
144492
+ rawSrcRect: null,
144493
+ shouldCover: false
144494
+ });
144495
+ if (!tr.docChanged)
144496
+ return false;
144497
+ editor.dispatch(tr);
144498
+ return true;
144499
+ }).steps[0]?.effect !== "changed")
144500
+ return buildNoOpResult("Reset crop produced no change.");
144501
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144502
+ }
144503
+ function imagesReplaceSourceWrapper(editor, input2, options) {
144504
+ rejectTrackedMode("images.replaceSource", options);
144505
+ const isDataUri = input2.src.startsWith("data:");
144506
+ const isInternalPath = input2.src.startsWith("word/media/");
144507
+ if (!isDataUri && !isInternalPath)
144508
+ throw new DocumentApiAdapterError("INVALID_INPUT", "External URLs are not supported in V1; provide a data URI or internal media path.");
144509
+ const image2 = findImageById(editor, input2.imageId);
144510
+ const newAttrs = {
144511
+ ...image2.node.attrs,
144512
+ src: input2.src,
144513
+ rId: null,
144514
+ originalSrc: null,
144515
+ originalExtension: null,
144516
+ clipPath: null,
144517
+ rawSrcRect: null,
144518
+ shouldCover: false
144519
+ };
144520
+ if (input2.resetSize) {
144521
+ if (!isDataUri)
144522
+ throw new DocumentApiAdapterError("INVALID_INPUT", "Cannot determine intrinsic dimensions from internal path; set size explicitly via setSize after replacement.");
144523
+ const dims = readImageDimensionsFromDataUri(input2.src);
144524
+ if (!dims)
144525
+ throw new DocumentApiAdapterError("INVALID_INPUT", "Could not determine intrinsic dimensions from data URI.");
144526
+ newAttrs.size = {
144527
+ width: dims.width,
144528
+ height: dims.height
144529
+ };
144530
+ }
144531
+ if (options?.dryRun)
144532
+ return buildSuccessResult(image2);
144533
+ if (executeDomainCommand(editor, () => {
144534
+ const { pos } = image2;
144535
+ const tr = editor.state.tr;
144536
+ tr.setNodeMarkup(pos, undefined, newAttrs);
144537
+ if (!tr.docChanged)
144538
+ return false;
144539
+ editor.dispatch(tr);
144540
+ return true;
144541
+ }).steps[0]?.effect !== "changed")
144542
+ return buildNoOpResult("Replace source produced no change.");
144543
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144544
+ }
144545
+ function imagesSetAltTextWrapper(editor, input2, options) {
144546
+ rejectTrackedMode("images.setAltText", options);
144547
+ const image2 = findImageById(editor, input2.imageId);
144548
+ if (image2.node.attrs.title === input2.description && !image2.node.attrs.decorative)
144549
+ return buildNoOpResult("Alt text is already as requested.");
144550
+ if (options?.dryRun)
144551
+ return buildSuccessResult(image2);
144552
+ if (executeDomainCommand(editor, () => {
144553
+ const { pos, node: node3 } = image2;
144554
+ const tr = editor.state.tr;
144555
+ tr.setNodeMarkup(pos, undefined, {
144556
+ ...node3.attrs,
144557
+ title: input2.description,
144558
+ decorative: false
144559
+ });
144560
+ editor.dispatch(tr);
144561
+ return true;
144562
+ }).steps[0]?.effect !== "changed")
144563
+ return buildNoOpResult("Set alt text produced no change.");
144564
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144565
+ }
144566
+ function imagesSetDecorativeWrapper(editor, input2, options) {
144567
+ rejectTrackedMode("images.setDecorative", options);
144568
+ const image2 = findImageById(editor, input2.imageId);
144569
+ if ((image2.node.attrs.decorative ?? false) === input2.decorative)
144570
+ return buildNoOpResult(`Decorative is already ${input2.decorative}.`);
144571
+ if (options?.dryRun)
144572
+ return buildSuccessResult(image2);
144573
+ if (executeDomainCommand(editor, () => {
144574
+ const { pos, node: node3 } = image2;
144575
+ const tr = editor.state.tr;
144576
+ tr.setNodeMarkup(pos, undefined, {
144577
+ ...node3.attrs,
144578
+ decorative: input2.decorative,
144579
+ title: input2.decorative ? "" : node3.attrs.title
144580
+ });
144581
+ editor.dispatch(tr);
144582
+ return true;
144583
+ }).steps[0]?.effect !== "changed")
144584
+ return buildNoOpResult("Set decorative produced no change.");
144585
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144586
+ }
144587
+ function imagesSetNameWrapper(editor, input2, options) {
144588
+ rejectTrackedMode("images.setName", options);
144589
+ const image2 = findImageById(editor, input2.imageId);
144590
+ if (image2.node.attrs.alt === input2.name)
144591
+ return buildNoOpResult("Name is already as requested.");
144592
+ if (options?.dryRun)
144593
+ return buildSuccessResult(image2);
144594
+ if (executeDomainCommand(editor, () => {
144595
+ const { pos, node: node3 } = image2;
144596
+ const tr = editor.state.tr;
144597
+ tr.setNodeMarkup(pos, undefined, {
144598
+ ...node3.attrs,
144599
+ alt: input2.name
144600
+ });
144601
+ editor.dispatch(tr);
144602
+ return true;
144603
+ }).steps[0]?.effect !== "changed")
144604
+ return buildNoOpResult("Set name produced no change.");
144605
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144606
+ }
144607
+ function imagesSetHyperlinkWrapper(editor, input2, options) {
144608
+ rejectTrackedMode("images.setHyperlink", options);
144609
+ const image2 = findImageById(editor, input2.imageId);
144610
+ const newValue = input2.url === null ? null : {
144611
+ url: input2.url,
144612
+ ...input2.tooltip ? { tooltip: input2.tooltip } : {}
144613
+ };
144614
+ const current = image2.node.attrs.hyperlink ?? null;
144615
+ if (current === null && newValue === null || current !== null && newValue !== null && current.url === newValue.url && current.tooltip === newValue.tooltip)
144616
+ return buildNoOpResult("Hyperlink is already as requested.");
144617
+ if (options?.dryRun)
144618
+ return buildSuccessResult(image2);
144619
+ if (executeDomainCommand(editor, () => {
144620
+ const { pos, node: node3 } = image2;
144621
+ const tr = editor.state.tr;
144622
+ tr.setNodeMarkup(pos, undefined, {
144623
+ ...node3.attrs,
144624
+ hyperlink: newValue
144625
+ });
144626
+ editor.dispatch(tr);
144627
+ return true;
144628
+ }).steps[0]?.effect !== "changed")
144629
+ return buildNoOpResult("Set hyperlink produced no change.");
144630
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144631
+ }
144632
+ function findCaptionParagraph(editor, imagePos) {
144633
+ const $pos = editor.state.doc.resolve(imagePos);
144634
+ const parentDepth = $pos.depth - 1;
144635
+ if (parentDepth < 0)
144636
+ return null;
144637
+ const afterParentPos = $pos.before(parentDepth + 1) + $pos.node(parentDepth + 1).nodeSize;
144638
+ if (afterParentPos >= editor.state.doc.content.size)
144639
+ return null;
144640
+ const nextNode = editor.state.doc.nodeAt(afterParentPos);
144641
+ if (!nextNode || nextNode.type.name !== "paragraph")
144642
+ return null;
144643
+ if (nextNode.attrs?.paragraphProperties?.styleId !== "Caption")
144644
+ return null;
144645
+ return {
144646
+ pos: afterParentPos,
144647
+ node: nextNode
144648
+ };
144649
+ }
144650
+ function requireSoleImageInParagraph(editor, imagePos) {
144651
+ const $pos = editor.state.doc.resolve(imagePos);
144652
+ const parentDepth = $pos.depth - 1;
144653
+ if (parentDepth < 0)
144654
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Caption operations require the image to be inside a paragraph.");
144655
+ const parentNode$1 = $pos.node(parentDepth + 1);
144656
+ let inlineContentCount = 0;
144657
+ parentNode$1.forEach((child) => {
144658
+ if (child.isInline)
144659
+ inlineContentCount++;
144660
+ });
144661
+ if (inlineContentCount !== 1)
144662
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Caption operations require the image to be the sole content of its paragraph.");
144663
+ }
144664
+ function imagesInsertCaptionWrapper(editor, input2, options) {
144665
+ rejectTrackedMode("images.insertCaption", options);
144666
+ const image2 = findImageById(editor, input2.imageId);
144667
+ requireSoleImageInParagraph(editor, image2.pos);
144668
+ if (findCaptionParagraph(editor, image2.pos))
144669
+ throw new DocumentApiAdapterError("INVALID_TARGET", "Image already has a caption; use updateCaption.");
144670
+ if (options?.dryRun)
144671
+ return buildSuccessResult(image2);
144672
+ if (executeDomainCommand(editor, () => {
144673
+ const $pos = editor.state.doc.resolve(image2.pos);
144674
+ const parentDepth = $pos.depth - 1;
144675
+ const afterParentPos = $pos.before(parentDepth + 1) + $pos.node(parentDepth + 1).nodeSize;
144676
+ const tr = editor.state.tr;
144677
+ const captionPara = editor.state.schema.nodes.paragraph.create({ paragraphProperties: { styleId: "Caption" } }, editor.state.schema.text(input2.text));
144678
+ tr.insert(afterParentPos, captionPara);
144679
+ if (!tr.docChanged)
144680
+ return false;
144681
+ editor.dispatch(tr);
144682
+ return true;
144683
+ }).steps[0]?.effect !== "changed")
144684
+ return buildNoOpResult("Insert caption produced no change.");
144685
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144686
+ }
144687
+ function imagesUpdateCaptionWrapper(editor, input2, options) {
144688
+ rejectTrackedMode("images.updateCaption", options);
144689
+ const image2 = findImageById(editor, input2.imageId);
144690
+ requireSoleImageInParagraph(editor, image2.pos);
144691
+ const caption = findCaptionParagraph(editor, image2.pos);
144692
+ if (!caption)
144693
+ throw new DocumentApiAdapterError("INVALID_TARGET", "No caption paragraph found; use insertCaption first.");
144694
+ if (options?.dryRun)
144695
+ return buildSuccessResult(image2);
144696
+ if (executeDomainCommand(editor, () => {
144697
+ const tr = editor.state.tr;
144698
+ const textStart = caption.pos + 1;
144699
+ const textEnd = caption.pos + caption.node.nodeSize - 1;
144700
+ tr.replaceWith(textStart, textEnd, editor.state.schema.text(input2.text));
144701
+ if (!tr.docChanged)
144702
+ return false;
144703
+ editor.dispatch(tr);
144704
+ return true;
144705
+ }).steps[0]?.effect !== "changed")
144706
+ return buildNoOpResult("Update caption produced no change.");
144707
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144708
+ }
144709
+ function imagesRemoveCaptionWrapper(editor, input2, options) {
144710
+ rejectTrackedMode("images.removeCaption", options);
144711
+ const image2 = findImageById(editor, input2.imageId);
144712
+ requireSoleImageInParagraph(editor, image2.pos);
144713
+ const caption = findCaptionParagraph(editor, image2.pos);
144714
+ if (!caption)
144715
+ return buildNoOpResult("No caption to remove.");
144716
+ if (options?.dryRun)
144717
+ return buildSuccessResult(image2);
144718
+ if (executeDomainCommand(editor, () => {
144719
+ const tr = editor.state.tr;
144720
+ tr.delete(caption.pos, caption.pos + caption.node.nodeSize);
144721
+ if (!tr.docChanged)
144722
+ return false;
144723
+ editor.dispatch(tr);
144724
+ return true;
144725
+ }).steps[0]?.effect !== "changed")
144726
+ return buildNoOpResult("Remove caption produced no change.");
144727
+ return buildSuccessResult(findImageById(editor, input2.imageId));
144728
+ }
143268
144729
  function getLinkMarkType(editor) {
143269
144730
  const markType = editor.schema.marks.link;
143270
144731
  if (!markType)
@@ -143936,7 +145397,21 @@ function assembleDocumentApiAdapters(editor) {
143936
145397
  setWrapDistances: (input2, options) => imagesSetWrapDistancesWrapper(editor, input2, options),
143937
145398
  setPosition: (input2, options) => imagesSetPositionWrapper(editor, input2, options),
143938
145399
  setAnchorOptions: (input2, options) => imagesSetAnchorOptionsWrapper(editor, input2, options),
143939
- setZOrder: (input2, options) => imagesSetZOrderWrapper(editor, input2, options)
145400
+ setZOrder: (input2, options) => imagesSetZOrderWrapper(editor, input2, options),
145401
+ scale: (input2, options) => imagesScaleWrapper(editor, input2, options),
145402
+ setLockAspectRatio: (input2, options) => imagesSetLockAspectRatioWrapper(editor, input2, options),
145403
+ rotate: (input2, options) => imagesRotateWrapper(editor, input2, options),
145404
+ flip: (input2, options) => imagesFlipWrapper(editor, input2, options),
145405
+ crop: (input2, options) => imagesCropWrapper(editor, input2, options),
145406
+ resetCrop: (input2, options) => imagesResetCropWrapper(editor, input2, options),
145407
+ replaceSource: (input2, options) => imagesReplaceSourceWrapper(editor, input2, options),
145408
+ setAltText: (input2, options) => imagesSetAltTextWrapper(editor, input2, options),
145409
+ setDecorative: (input2, options) => imagesSetDecorativeWrapper(editor, input2, options),
145410
+ setName: (input2, options) => imagesSetNameWrapper(editor, input2, options),
145411
+ setHyperlink: (input2, options) => imagesSetHyperlinkWrapper(editor, input2, options),
145412
+ insertCaption: (input2, options) => imagesInsertCaptionWrapper(editor, input2, options),
145413
+ updateCaption: (input2, options) => imagesUpdateCaptionWrapper(editor, input2, options),
145414
+ removeCaption: (input2, options) => imagesRemoveCaptionWrapper(editor, input2, options)
143940
145415
  },
143941
145416
  hyperlinks: {
143942
145417
  list: (query2) => hyperlinksListWrapper(editor, query2),
@@ -197248,9 +198723,9 @@ var Node$13 = class Node$14 {
197248
198723
  trackedChanges: context.trackedChanges ?? []
197249
198724
  });
197250
198725
  }, _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(() => {
198726
+ var init_src_LqliKMID_es = __esm(() => {
197252
198727
  init_rolldown_runtime_B2q5OVn9_es();
197253
- init_SuperConverter_C3jSWLmj_es();
198728
+ init_SuperConverter_BcmJ8_gc_es();
197254
198729
  init_jszip_ChlR43oI_es();
197255
198730
  init_uuid_qzgm05fK_es();
197256
198731
  init_constants_CMPtQbp7_es();
@@ -205525,7 +207000,21 @@ function print() { __p += __j.call(arguments, '') }
205525
207000
  "images.setWrapDistances": ["setImage"],
205526
207001
  "images.setPosition": ["setImage"],
205527
207002
  "images.setAnchorOptions": ["setImage"],
205528
- "images.setZOrder": ["setImage"]
207003
+ "images.setZOrder": ["setImage"],
207004
+ "images.scale": ["setImage"],
207005
+ "images.setLockAspectRatio": ["setImage"],
207006
+ "images.rotate": ["setImage"],
207007
+ "images.flip": ["setImage"],
207008
+ "images.crop": ["setImage"],
207009
+ "images.resetCrop": ["setImage"],
207010
+ "images.replaceSource": ["setImage"],
207011
+ "images.setAltText": ["setImage"],
207012
+ "images.setDecorative": ["setImage"],
207013
+ "images.setName": ["setImage"],
207014
+ "images.setHyperlink": ["setImage"],
207015
+ "images.insertCaption": ["setImage"],
207016
+ "images.updateCaption": ["setImage"],
207017
+ "images.removeCaption": ["setImage"]
205529
207018
  };
205530
207019
  VALID_CAPABILITY_REASON_CODES = new Set(CAPABILITY_REASON_CODES2);
205531
207020
  REQUIRED_HELPERS = {
@@ -222736,6 +224225,18 @@ function print() { __p += __j.call(arguments, '') }
222736
224225
  rawSrcRect: {
222737
224226
  default: null,
222738
224227
  rendered: false
224228
+ },
224229
+ lockAspectRatio: {
224230
+ default: true,
224231
+ rendered: false
224232
+ },
224233
+ decorative: {
224234
+ default: false,
224235
+ rendered: false
224236
+ },
224237
+ hyperlink: {
224238
+ default: null,
224239
+ rendered: false
222739
224240
  }
222740
224241
  };
222741
224242
  },
@@ -228932,8 +230433,8 @@ function print() { __p += __j.call(arguments, '') }
228932
230433
  return isObjectLike_default(value) && hasOwnProperty$8.call(value, "callee") && !propertyIsEnumerable$1.call(value, "callee");
228933
230434
  };
228934
230435
  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;
230436
+ freeExports$2 = typeof exports_src_LqliKMID_es == "object" && exports_src_LqliKMID_es && !exports_src_LqliKMID_es.nodeType && exports_src_LqliKMID_es;
230437
+ freeModule$2 = freeExports$2 && typeof module_src_LqliKMID_es == "object" && module_src_LqliKMID_es && !module_src_LqliKMID_es.nodeType && module_src_LqliKMID_es;
228937
230438
  Buffer$1 = freeModule$2 && freeModule$2.exports === freeExports$2 ? _root_default.Buffer : undefined;
228938
230439
  isBuffer_default = (Buffer$1 ? Buffer$1.isBuffer : undefined) || stubFalse_default;
228939
230440
  typedArrayTags = {};
@@ -228941,8 +230442,8 @@ function print() { __p += __j.call(arguments, '') }
228941
230442
  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
230443
  _baseIsTypedArray_default = baseIsTypedArray;
228943
230444
  _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;
230445
+ freeExports$1 = typeof exports_src_LqliKMID_es == "object" && exports_src_LqliKMID_es && !exports_src_LqliKMID_es.nodeType && exports_src_LqliKMID_es;
230446
+ freeModule$1 = freeExports$1 && typeof module_src_LqliKMID_es == "object" && module_src_LqliKMID_es && !module_src_LqliKMID_es.nodeType && module_src_LqliKMID_es;
228946
230447
  freeProcess = freeModule$1 && freeModule$1.exports === freeExports$1 && _freeGlobal_default.process;
228947
230448
  _nodeUtil_default = function() {
228948
230449
  try {
@@ -229047,8 +230548,8 @@ function print() { __p += __j.call(arguments, '') }
229047
230548
  Stack.prototype.has = _stackHas_default;
229048
230549
  Stack.prototype.set = _stackSet_default;
229049
230550
  _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;
230551
+ freeExports = typeof exports_src_LqliKMID_es == "object" && exports_src_LqliKMID_es && !exports_src_LqliKMID_es.nodeType && exports_src_LqliKMID_es;
230552
+ freeModule = freeExports && typeof module_src_LqliKMID_es == "object" && module_src_LqliKMID_es && !module_src_LqliKMID_es.nodeType && module_src_LqliKMID_es;
229052
230553
  Buffer4 = freeModule && freeModule.exports === freeExports ? _root_default.Buffer : undefined;
229053
230554
  allocUnsafe = Buffer4 ? Buffer4.allocUnsafe : undefined;
229054
230555
  _cloneBuffer_default = cloneBuffer;
@@ -237128,8 +238629,8 @@ var init_zipper_DqXT7uTa_es = __esm(() => {
237128
238629
 
237129
238630
  // ../../packages/superdoc/dist/super-editor.es.js
237130
238631
  var init_super_editor_es = __esm(() => {
237131
- init_src_nq0HTKfv_es();
237132
- init_SuperConverter_C3jSWLmj_es();
238632
+ init_src_LqliKMID_es();
238633
+ init_SuperConverter_BcmJ8_gc_es();
237133
238634
  init_jszip_ChlR43oI_es();
237134
238635
  init_xml_js_DLE8mr0n_es();
237135
238636
  init_constants_CMPtQbp7_es();
@@ -238496,9 +239997,49 @@ function mapTableOfContentsNode2(candidate) {
238496
239997
  }
238497
239998
  };
238498
239999
  }
238499
- function buildImageInfo2(attrs, kind) {
240000
+ function parseCropFromClipPath2(clipPath) {
240001
+ if (!clipPath)
240002
+ return null;
240003
+ const match2 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
240004
+ if (!match2)
240005
+ return null;
240006
+ return {
240007
+ top: parseFloat(match2[1]),
240008
+ right: parseFloat(match2[2]),
240009
+ bottom: parseFloat(match2[3]),
240010
+ left: parseFloat(match2[4])
240011
+ };
240012
+ }
240013
+ function detectCaptionSibling2(doc4, imagePos) {
240014
+ if (!doc4)
240015
+ return false;
240016
+ try {
240017
+ const $pos = doc4.resolve(imagePos);
240018
+ const parentDepth = $pos.depth - 1;
240019
+ if (parentDepth < 0)
240020
+ return false;
240021
+ const parentPos = $pos.before(parentDepth + 1);
240022
+ const parentNode2 = $pos.node(parentDepth + 1);
240023
+ const afterParentPos = parentPos + parentNode2.nodeSize;
240024
+ if (afterParentPos >= doc4.content.size)
240025
+ return false;
240026
+ const nextNode = doc4.nodeAt(afterParentPos);
240027
+ if (!nextNode || nextNode.type.name !== "paragraph")
240028
+ return false;
240029
+ return nextNode.attrs?.paragraphProperties?.styleId === "Caption";
240030
+ } catch {
240031
+ return false;
240032
+ }
240033
+ }
240034
+ function buildImageInfo2(attrs, kind, doc4, pos) {
238500
240035
  const isFloating = Boolean(attrs?.isAnchor);
238501
240036
  const wrapObj = attrs?.wrap;
240037
+ const td = attrs?.transformData;
240038
+ const transform = td && (td.rotation || td.verticalFlip || td.horizontalFlip) ? {
240039
+ rotation: td.rotation ?? undefined,
240040
+ verticalFlip: td.verticalFlip ?? undefined,
240041
+ horizontalFlip: td.horizontalFlip ?? undefined
240042
+ } : null;
238502
240043
  const properties = {
238503
240044
  src: attrs?.src ?? undefined,
238504
240045
  alt: attrs?.alt ?? undefined,
@@ -238514,7 +240055,15 @@ function buildImageInfo2(attrs, kind) {
238514
240055
  },
238515
240056
  anchorData: attrs?.anchorData ?? null,
238516
240057
  marginOffset: attrs?.marginOffset ?? null,
238517
- relativeHeight: attrs?.relativeHeight ?? null
240058
+ relativeHeight: attrs?.relativeHeight ?? null,
240059
+ name: attrs?.alt ?? undefined,
240060
+ description: attrs?.title ?? undefined,
240061
+ transform,
240062
+ crop: parseCropFromClipPath2(attrs?.clipPath),
240063
+ lockAspectRatio: attrs?.lockAspectRatio ?? true,
240064
+ decorative: attrs?.decorative ?? false,
240065
+ hyperlink: attrs?.hyperlink ?? null,
240066
+ hasCaption: pos != null ? detectCaptionSibling2(doc4, pos) : false
238518
240067
  };
238519
240068
  return {
238520
240069
  nodeType: "image",
@@ -238710,7 +240259,7 @@ function mapLineBreakNode2() {
238710
240259
  function isInlineCandidate2(candidate) {
238711
240260
  return "anchor" in candidate;
238712
240261
  }
238713
- function mapNodeInfo2(candidate, overrideType) {
240262
+ function mapNodeInfo2(candidate, overrideType, doc4) {
238714
240263
  const nodeType = overrideType ?? candidate.nodeType;
238715
240264
  const kind = isInlineCandidate2(candidate) ? "inline" : "block";
238716
240265
  switch (nodeType) {
@@ -238740,7 +240289,7 @@ function mapNodeInfo2(candidate, overrideType) {
238740
240289
  return mapTableCellNode2(candidate);
238741
240290
  case "image": {
238742
240291
  const attrs = candidate.node?.attrs;
238743
- return buildImageInfo2(attrs, kind);
240292
+ return buildImageInfo2(attrs, kind, doc4, candidate.pos);
238744
240293
  }
238745
240294
  case "sdt": {
238746
240295
  const attrs = candidate.node?.attrs;
@@ -238790,7 +240339,7 @@ function resolveNodeInfoForAddress2(editor, index2, address2, inlineIndex) {
238790
240339
  const candidate2 = findBlockById2(index2, address2);
238791
240340
  if (!candidate2)
238792
240341
  return;
238793
- return mapNodeInfo2(candidate2, address2.nodeType);
240342
+ return mapNodeInfo2(candidate2, address2.nodeType, editor.state.doc);
238794
240343
  }
238795
240344
  const resolvedInlineIndex = inlineIndex ?? getInlineIndex2(editor);
238796
240345
  const candidate = findInlineByAnchor2(resolvedInlineIndex, address2);
@@ -239336,14 +240885,14 @@ function getNodeAdapter2(editor, address2) {
239336
240885
  if (matches2.length > 1) {
239337
240886
  throw new DocumentApiAdapterError3("TARGET_NOT_FOUND", `Multiple nodes share ${address2.nodeType} id "${address2.nodeId}".`);
239338
240887
  }
239339
- return mapNodeInfo2(matches2[0], address2.nodeType);
240888
+ return mapNodeInfo2(matches2[0], address2.nodeType, editor.state.doc);
239340
240889
  }
239341
240890
  const inlineIndex = getInlineIndex2(editor);
239342
240891
  const candidate = findInlineByAnchor2(inlineIndex, address2);
239343
240892
  if (!candidate) {
239344
240893
  throw new DocumentApiAdapterError3("TARGET_NOT_FOUND", `Inline node "${address2.nodeType}" not found for the provided anchor.`);
239345
240894
  }
239346
- return mapNodeInfo2(candidate, address2.nodeType);
240895
+ return mapNodeInfo2(candidate, address2.nodeType, editor.state.doc);
239347
240896
  }
239348
240897
  function resolveBlockById2(editor, nodeId, nodeType) {
239349
240898
  const blockIndex = getBlockIndex2(editor);
@@ -239375,7 +240924,7 @@ function getNodeByIdAdapter2(editor, input2) {
239375
240924
  const { nodeId, nodeType } = input2;
239376
240925
  const { candidate, resolvedType } = resolveBlockById2(editor, nodeId, nodeType);
239377
240926
  const displayType = nodeType ?? resolvedType;
239378
- return mapNodeInfo2(candidate, displayType);
240927
+ return mapNodeInfo2(candidate, displayType, editor.state.doc);
239379
240928
  }
239380
240929
  var init_get_node_adapter = __esm(() => {
239381
240930
  init_index_cache();
@@ -282287,6 +283836,41 @@ function handleImageNode3(node4, params3, isAnchor) {
282287
283836
  };
282288
283837
  }
282289
283838
  }
283839
+ const nvPicPr = picture.elements.find((el) => el.name === "pic:nvPicPr");
283840
+ const cNvPicPr = nvPicPr?.elements?.find((el) => el.name === "pic:cNvPicPr");
283841
+ const picLocks = cNvPicPr?.elements?.find((el) => el.name === "a:picLocks");
283842
+ const lockAspectRatio = picLocks ? picLocks.attributes?.["noChangeAspect"] === "1" || picLocks.attributes?.["noChangeAspect"] === 1 : false;
283843
+ const cNvPr = nvPicPr?.elements?.find((el) => el.name === "pic:cNvPr");
283844
+ const hlinkClick = cNvPr?.elements?.find((el) => el.name === "a:hlinkClick") || docPr?.elements?.find((el) => el.name === "a:hlinkClick");
283845
+ let hyperlink = null;
283846
+ if (hlinkClick?.attributes?.["r:id"]) {
283847
+ const hlinkRId = hlinkClick.attributes["r:id"];
283848
+ const currentFile2 = filename || "document.xml";
283849
+ let hlinkRels = docx[`word/_rels/${currentFile2}.rels`];
283850
+ if (!hlinkRels)
283851
+ hlinkRels = docx[`word/_rels/document.xml.rels`];
283852
+ const hlinkRelationships = hlinkRels?.elements?.find((el) => el.name === "Relationships");
283853
+ const hlinkRel = hlinkRelationships?.elements?.find((el) => el.attributes?.["Id"] === hlinkRId);
283854
+ if (hlinkRel?.attributes?.["Target"]) {
283855
+ hyperlink = { url: hlinkRel.attributes["Target"] };
283856
+ if (hlinkClick.attributes?.["tooltip"]) {
283857
+ hyperlink.tooltip = hlinkClick.attributes["tooltip"];
283858
+ }
283859
+ }
283860
+ }
283861
+ let decorative = false;
283862
+ const docPrExtLst = docPr?.elements?.find((el) => el.name === "a:extLst");
283863
+ if (docPrExtLst) {
283864
+ for (const ext of docPrExtLst.elements || []) {
283865
+ if (ext.name !== "a:ext")
283866
+ continue;
283867
+ const decEl = ext.elements?.find((el) => el.name === "adec:decorative" || el.name === "a16:decorative");
283868
+ if (decEl && (decEl.attributes?.["val"] === "1" || decEl.attributes?.["val"] === 1)) {
283869
+ decorative = true;
283870
+ break;
283871
+ }
283872
+ }
283873
+ }
282290
283874
  const { attributes: blipAttributes = {} } = blip;
282291
283875
  const rEmbed = blipAttributes["r:embed"];
282292
283876
  if (!rEmbed) {
@@ -282381,6 +283965,9 @@ function handleImageNode3(node4, params3, isAnchor) {
282381
283965
  },
282382
283966
  originalAttributes: node4.attributes,
282383
283967
  rId: relAttributes["Id"],
283968
+ lockAspectRatio,
283969
+ decorative,
283970
+ hyperlink,
282384
283971
  ...order4.length ? { drawingChildOrder: order4 } : {},
282385
283972
  ...originalChildren.length ? { originalDrawingChildren: originalChildren } : {},
282386
283973
  ...hasGrayscale ? { grayscale: true } : {}
@@ -283098,6 +284685,103 @@ var init_image_dimensions = __esm(() => {
283098
284685
  });
283099
284686
 
283100
284687
  // ../../packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/decode-image-node-helpers.js
284688
+ function resolveHyperlinkRId2(attrs, params3) {
284689
+ if (!attrs.hyperlink?.url || !params3)
284690
+ return null;
284691
+ return addHyperlinkRelationship2(params3, attrs.hyperlink.url);
284692
+ }
284693
+ function buildHlinkClickElement2(attrs, hlinkRId) {
284694
+ if (!hlinkRId)
284695
+ return null;
284696
+ const hlinkAttrs = { "r:id": hlinkRId };
284697
+ if (attrs.hyperlink?.tooltip) {
284698
+ hlinkAttrs.tooltip = attrs.hyperlink.tooltip;
284699
+ }
284700
+ return { name: "a:hlinkClick", attributes: hlinkAttrs };
284701
+ }
284702
+ function buildDocPrElement2(attrs, imageName, hlinkRId) {
284703
+ const docPrAttrs = {
284704
+ id: attrs.id || 0,
284705
+ name: attrs.alt || `Picture ${imageName}`
284706
+ };
284707
+ if (!attrs.decorative && attrs.title) {
284708
+ docPrAttrs.descr = attrs.title;
284709
+ }
284710
+ const children = [];
284711
+ const hlinkEl = buildHlinkClickElement2(attrs, hlinkRId);
284712
+ if (hlinkEl)
284713
+ children.push(hlinkEl);
284714
+ if (attrs.decorative) {
284715
+ children.push({
284716
+ name: "a:extLst",
284717
+ elements: [
284718
+ {
284719
+ name: "a:ext",
284720
+ attributes: { uri: DECORATIVE_EXT_URI2 },
284721
+ elements: [
284722
+ {
284723
+ name: "adec:decorative",
284724
+ attributes: { "xmlns:adec": DECORATIVE_NAMESPACE2, val: "1" }
284725
+ }
284726
+ ]
284727
+ }
284728
+ ]
284729
+ });
284730
+ }
284731
+ return {
284732
+ name: "wp:docPr",
284733
+ attributes: docPrAttrs,
284734
+ ...children.length ? { elements: children } : {}
284735
+ };
284736
+ }
284737
+ function buildNvPicPrElement2(attrs, imageName, hlinkRId) {
284738
+ const cNvPrChildren = [];
284739
+ const hlinkEl = buildHlinkClickElement2(attrs, hlinkRId);
284740
+ if (hlinkEl)
284741
+ cNvPrChildren.push(hlinkEl);
284742
+ return {
284743
+ name: "pic:nvPicPr",
284744
+ elements: [
284745
+ {
284746
+ name: "pic:cNvPr",
284747
+ attributes: {
284748
+ id: attrs.id || 0,
284749
+ name: attrs.alt || `Picture ${imageName}`
284750
+ },
284751
+ ...cNvPrChildren.length ? { elements: cNvPrChildren } : {}
284752
+ },
284753
+ {
284754
+ name: "pic:cNvPicPr",
284755
+ elements: [
284756
+ {
284757
+ name: "a:picLocks",
284758
+ attributes: {
284759
+ ...attrs.lockAspectRatio ? { noChangeAspect: 1 } : {},
284760
+ noChangeArrowheads: 1
284761
+ }
284762
+ }
284763
+ ]
284764
+ }
284765
+ ]
284766
+ };
284767
+ }
284768
+ function addHyperlinkRelationship2(params3, url) {
284769
+ const newId = `rId${generateDocxRandomId2(8)}`;
284770
+ if (!params3.relationships || !Array.isArray(params3.relationships)) {
284771
+ params3.relationships = [];
284772
+ }
284773
+ params3.relationships.push({
284774
+ type: "element",
284775
+ name: "Relationship",
284776
+ attributes: {
284777
+ Id: newId,
284778
+ Type: HYPERLINK_REL_TYPE2,
284779
+ Target: url,
284780
+ TargetMode: "External"
284781
+ }
284782
+ });
284783
+ return newId;
284784
+ }
283101
284785
  function isFinitePositive3(value) {
283102
284786
  return typeof value === "number" && Number.isFinite(value) && value > 0;
283103
284787
  }
@@ -283203,7 +284887,7 @@ function translateShapeGroup2(params3) {
283203
284887
  elements: []
283204
284888
  });
283205
284889
  }
283206
- var translateImageNode2 = (params3) => {
284890
+ 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
284891
  const {
283208
284892
  node: { attrs = {} },
283209
284893
  tableCell: tableCell2,
@@ -283305,6 +284989,7 @@ var translateImageNode2 = (params3) => {
283305
284989
  const rawSrcRect = attrs.rawSrcRect;
283306
284990
  const drawingXmlns = "http://schemas.openxmlformats.org/drawingml/2006/main";
283307
284991
  const pictureXmlns = "http://schemas.openxmlformats.org/drawingml/2006/picture";
284992
+ const hlinkRId = resolveHyperlinkRId2(attrs, params3);
283308
284993
  return {
283309
284994
  attributes: inlineAttrs,
283310
284995
  elements: [
@@ -283319,13 +285004,7 @@ var translateImageNode2 = (params3) => {
283319
285004
  name: "wp:effectExtent",
283320
285005
  attributes: effectExtentAttrs
283321
285006
  },
283322
- {
283323
- name: "wp:docPr",
283324
- attributes: {
283325
- id: attrs.id || 0,
283326
- name: attrs.alt || `Picture ${imageName}`
283327
- }
283328
- },
285007
+ buildDocPrElement2(attrs, imageName, hlinkRId),
283329
285008
  {
283330
285009
  name: "wp:cNvGraphicFramePr",
283331
285010
  elements: [
@@ -283333,7 +285012,7 @@ var translateImageNode2 = (params3) => {
283333
285012
  name: "a:graphicFrameLocks",
283334
285013
  attributes: {
283335
285014
  "xmlns:a": drawingXmlns,
283336
- noChangeAspect: 1
285015
+ ...attrs.lockAspectRatio ? { noChangeAspect: 1 } : {}
283337
285016
  }
283338
285017
  }
283339
285018
  ]
@@ -283350,30 +285029,7 @@ var translateImageNode2 = (params3) => {
283350
285029
  name: "pic:pic",
283351
285030
  attributes: { "xmlns:pic": pictureXmlns },
283352
285031
  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
- },
285032
+ buildNvPicPrElement2(attrs, imageName, hlinkRId),
283377
285033
  {
283378
285034
  name: "pic:blipFill",
283379
285035
  elements: [
@@ -299120,7 +300776,21 @@ var init_capabilities_adapter = __esm(() => {
299120
300776
  "images.setWrapDistances": ["setImage"],
299121
300777
  "images.setPosition": ["setImage"],
299122
300778
  "images.setAnchorOptions": ["setImage"],
299123
- "images.setZOrder": ["setImage"]
300779
+ "images.setZOrder": ["setImage"],
300780
+ "images.scale": ["setImage"],
300781
+ "images.setLockAspectRatio": ["setImage"],
300782
+ "images.rotate": ["setImage"],
300783
+ "images.flip": ["setImage"],
300784
+ "images.crop": ["setImage"],
300785
+ "images.resetCrop": ["setImage"],
300786
+ "images.replaceSource": ["setImage"],
300787
+ "images.setAltText": ["setImage"],
300788
+ "images.setDecorative": ["setImage"],
300789
+ "images.setName": ["setImage"],
300790
+ "images.setHyperlink": ["setImage"],
300791
+ "images.insertCaption": ["setImage"],
300792
+ "images.updateCaption": ["setImage"],
300793
+ "images.removeCaption": ["setImage"]
299124
300794
  };
299125
300795
  VALID_CAPABILITY_REASON_CODES2 = new Set(CAPABILITY_REASON_CODES);
299126
300796
  REQUIRED_HELPERS2 = {
@@ -314026,7 +315696,38 @@ function buildSuccessResult2(candidate) {
314026
315696
  function buildNoOpResult2(message) {
314027
315697
  return { success: false, failure: { code: "NO_OP", message } };
314028
315698
  }
314029
- function buildImageSummary2(candidate) {
315699
+ function parseCropFromClipPath3(clipPath) {
315700
+ if (!clipPath)
315701
+ return null;
315702
+ const match2 = clipPath.match(/^inset\(\s*([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s+([\d.]+)%\s*\)$/);
315703
+ if (!match2)
315704
+ return null;
315705
+ return {
315706
+ top: parseFloat(match2[1]),
315707
+ right: parseFloat(match2[2]),
315708
+ bottom: parseFloat(match2[3]),
315709
+ left: parseFloat(match2[4])
315710
+ };
315711
+ }
315712
+ function buildTransformInfo2(td) {
315713
+ if (!td)
315714
+ return null;
315715
+ if (!td.rotation && !td.verticalFlip && !td.horizontalFlip)
315716
+ return null;
315717
+ return {
315718
+ rotation: td.rotation ?? undefined,
315719
+ verticalFlip: td.verticalFlip ?? undefined,
315720
+ horizontalFlip: td.horizontalFlip ?? undefined
315721
+ };
315722
+ }
315723
+ function hasCaptionSibling2(editor, imagePos) {
315724
+ try {
315725
+ return findCaptionParagraph2(editor, imagePos) !== null;
315726
+ } catch {
315727
+ return false;
315728
+ }
315729
+ }
315730
+ function buildImageSummary2(editor, candidate) {
314030
315731
  const attrs = candidate.node.attrs;
314031
315732
  return {
314032
315733
  sdImageId: candidate.sdImageId,
@@ -314042,7 +315743,15 @@ function buildImageSummary2(candidate) {
314042
315743
  },
314043
315744
  anchorData: attrs.anchorData ?? null,
314044
315745
  marginOffset: attrs.marginOffset ?? null,
314045
- relativeHeight: attrs.relativeHeight ?? null
315746
+ relativeHeight: attrs.relativeHeight ?? null,
315747
+ name: attrs.alt ?? undefined,
315748
+ description: attrs.title ?? undefined,
315749
+ transform: buildTransformInfo2(attrs.transformData),
315750
+ crop: parseCropFromClipPath3(attrs.clipPath),
315751
+ lockAspectRatio: attrs.lockAspectRatio ?? true,
315752
+ decorative: attrs.decorative ?? false,
315753
+ hyperlink: attrs.hyperlink ?? null,
315754
+ hasCaption: hasCaptionSibling2(editor, candidate.pos)
314046
315755
  }
314047
315756
  };
314048
315757
  }
@@ -314081,12 +315790,12 @@ function imagesListWrapper2(editor, input2) {
314081
315790
  const allImages = collectImages2(editor.state.doc);
314082
315791
  const offset2 = input2.offset ?? 0;
314083
315792
  const limit = input2.limit ?? allImages.length;
314084
- const items = allImages.slice(offset2, offset2 + limit).map(buildImageSummary2);
315793
+ const items = allImages.slice(offset2, offset2 + limit).map((c2) => buildImageSummary2(editor, c2));
314085
315794
  return { total: allImages.length, items };
314086
315795
  }
314087
315796
  function imagesGetWrapper2(editor, input2) {
314088
315797
  const image3 = findImageById2(editor, input2.imageId);
314089
- return buildImageSummary2(image3);
315798
+ return buildImageSummary2(editor, image3);
314090
315799
  }
314091
315800
  function createImageWrapper2(editor, input2, options) {
314092
315801
  rejectTrackedMode2("create.image", options);
@@ -314486,6 +316195,397 @@ function imagesSetZOrderWrapper2(editor, input2, options) {
314486
316195
  const updated = findImageById2(editor, input2.imageId);
314487
316196
  return buildSuccessResult2(updated);
314488
316197
  }
316198
+ function imagesScaleWrapper2(editor, input2, options) {
316199
+ rejectTrackedMode2("images.scale", options);
316200
+ const image3 = findImageById2(editor, input2.imageId);
316201
+ const currentSize = image3.node.attrs.size;
316202
+ if (!isFinitePositive4(currentSize?.width) || !isFinitePositive4(currentSize?.height)) {
316203
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Image has no explicit size; use setSize first.");
316204
+ }
316205
+ const newSize = {
316206
+ width: Math.max(1, Math.round(currentSize.width * input2.factor)),
316207
+ height: Math.max(1, Math.round(currentSize.height * input2.factor))
316208
+ };
316209
+ if (newSize.width === currentSize.width && newSize.height === currentSize.height) {
316210
+ return buildNoOpResult2("Scale produced no size change.");
316211
+ }
316212
+ if (options?.dryRun)
316213
+ return buildSuccessResult2(image3);
316214
+ const receipt2 = executeDomainCommand2(editor, () => {
316215
+ const { pos, node: node4 } = image3;
316216
+ const tr = editor.state.tr;
316217
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, size: newSize });
316218
+ if (!tr.docChanged)
316219
+ return false;
316220
+ editor.dispatch(tr);
316221
+ return true;
316222
+ });
316223
+ if (receipt2.steps[0]?.effect !== "changed")
316224
+ return buildNoOpResult2("Scale produced no change.");
316225
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316226
+ }
316227
+ function imagesSetLockAspectRatioWrapper2(editor, input2, options) {
316228
+ rejectTrackedMode2("images.setLockAspectRatio", options);
316229
+ const image3 = findImageById2(editor, input2.imageId);
316230
+ if ((image3.node.attrs.lockAspectRatio ?? true) === input2.locked) {
316231
+ return buildNoOpResult2(`lockAspectRatio is already ${input2.locked}.`);
316232
+ }
316233
+ if (options?.dryRun)
316234
+ return buildSuccessResult2(image3);
316235
+ const receipt2 = executeDomainCommand2(editor, () => {
316236
+ const { pos, node: node4 } = image3;
316237
+ const tr = editor.state.tr;
316238
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, lockAspectRatio: input2.locked });
316239
+ editor.dispatch(tr);
316240
+ return true;
316241
+ });
316242
+ if (receipt2.steps[0]?.effect !== "changed")
316243
+ return buildNoOpResult2("Set lock aspect ratio produced no change.");
316244
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316245
+ }
316246
+ function imagesRotateWrapper2(editor, input2, options) {
316247
+ rejectTrackedMode2("images.rotate", options);
316248
+ const image3 = findImageById2(editor, input2.imageId);
316249
+ const currentRotation = image3.node.attrs.transformData?.rotation ?? 0;
316250
+ if (currentRotation === input2.angle) {
316251
+ return buildNoOpResult2(`Rotation is already ${input2.angle} degrees.`);
316252
+ }
316253
+ if (options?.dryRun)
316254
+ return buildSuccessResult2(image3);
316255
+ const receipt2 = executeDomainCommand2(editor, () => {
316256
+ const { pos, node: node4 } = image3;
316257
+ const tr = editor.state.tr;
316258
+ tr.setNodeMarkup(pos, undefined, {
316259
+ ...node4.attrs,
316260
+ transformData: { ...node4.attrs.transformData ?? {}, rotation: input2.angle }
316261
+ });
316262
+ editor.dispatch(tr);
316263
+ return true;
316264
+ });
316265
+ if (receipt2.steps[0]?.effect !== "changed")
316266
+ return buildNoOpResult2("Rotate produced no change.");
316267
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316268
+ }
316269
+ function imagesFlipWrapper2(editor, input2, options) {
316270
+ rejectTrackedMode2("images.flip", options);
316271
+ const image3 = findImageById2(editor, input2.imageId);
316272
+ const current = image3.node.attrs.transformData ?? {};
316273
+ const targetH = input2.horizontal ?? current.horizontalFlip ?? false;
316274
+ const targetV = input2.vertical ?? current.verticalFlip ?? false;
316275
+ if (targetH === (current.horizontalFlip ?? false) && targetV === (current.verticalFlip ?? false)) {
316276
+ return buildNoOpResult2("Flip state is already as requested.");
316277
+ }
316278
+ if (options?.dryRun)
316279
+ return buildSuccessResult2(image3);
316280
+ const receipt2 = executeDomainCommand2(editor, () => {
316281
+ const { pos, node: node4 } = image3;
316282
+ const tr = editor.state.tr;
316283
+ tr.setNodeMarkup(pos, undefined, {
316284
+ ...node4.attrs,
316285
+ transformData: { ...node4.attrs.transformData ?? {}, horizontalFlip: targetH, verticalFlip: targetV }
316286
+ });
316287
+ editor.dispatch(tr);
316288
+ return true;
316289
+ });
316290
+ if (receipt2.steps[0]?.effect !== "changed")
316291
+ return buildNoOpResult2("Flip produced no change.");
316292
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316293
+ }
316294
+ function cropToClipPath2(crop) {
316295
+ const { top = 0, right: right2 = 0, bottom: bottom2 = 0, left: left2 = 0 } = crop;
316296
+ return `inset(${top}% ${right2}% ${bottom2}% ${left2}%)`;
316297
+ }
316298
+ function cropToRawSrcRect2(crop) {
316299
+ const { top = 0, right: right2 = 0, bottom: bottom2 = 0, left: left2 = 0 } = crop;
316300
+ return {
316301
+ name: "a:srcRect",
316302
+ attributes: {
316303
+ l: String(Math.round(left2 * 1000)),
316304
+ t: String(Math.round(top * 1000)),
316305
+ r: String(Math.round(right2 * 1000)),
316306
+ b: String(Math.round(bottom2 * 1000))
316307
+ }
316308
+ };
316309
+ }
316310
+ function imagesCropWrapper2(editor, input2, options) {
316311
+ rejectTrackedMode2("images.crop", options);
316312
+ const image3 = findImageById2(editor, input2.imageId);
316313
+ const newClipPath = cropToClipPath2(input2.crop);
316314
+ if (image3.node.attrs.clipPath === newClipPath) {
316315
+ return buildNoOpResult2("Crop values are already as requested.");
316316
+ }
316317
+ if (options?.dryRun)
316318
+ return buildSuccessResult2(image3);
316319
+ const receipt2 = executeDomainCommand2(editor, () => {
316320
+ const { pos, node: node4 } = image3;
316321
+ const tr = editor.state.tr;
316322
+ tr.setNodeMarkup(pos, undefined, {
316323
+ ...node4.attrs,
316324
+ clipPath: newClipPath,
316325
+ rawSrcRect: cropToRawSrcRect2(input2.crop)
316326
+ });
316327
+ if (!tr.docChanged)
316328
+ return false;
316329
+ editor.dispatch(tr);
316330
+ return true;
316331
+ });
316332
+ if (receipt2.steps[0]?.effect !== "changed")
316333
+ return buildNoOpResult2("Crop produced no change.");
316334
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316335
+ }
316336
+ function imagesResetCropWrapper2(editor, input2, options) {
316337
+ rejectTrackedMode2("images.resetCrop", options);
316338
+ const image3 = findImageById2(editor, input2.imageId);
316339
+ if (!image3.node.attrs.clipPath) {
316340
+ return buildNoOpResult2("Image has no crop to reset.");
316341
+ }
316342
+ if (options?.dryRun)
316343
+ return buildSuccessResult2(image3);
316344
+ const receipt2 = executeDomainCommand2(editor, () => {
316345
+ const { pos, node: node4 } = image3;
316346
+ const tr = editor.state.tr;
316347
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, clipPath: null, rawSrcRect: null, shouldCover: false });
316348
+ if (!tr.docChanged)
316349
+ return false;
316350
+ editor.dispatch(tr);
316351
+ return true;
316352
+ });
316353
+ if (receipt2.steps[0]?.effect !== "changed")
316354
+ return buildNoOpResult2("Reset crop produced no change.");
316355
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316356
+ }
316357
+ function imagesReplaceSourceWrapper2(editor, input2, options) {
316358
+ rejectTrackedMode2("images.replaceSource", options);
316359
+ const isDataUri = input2.src.startsWith("data:");
316360
+ const isInternalPath = input2.src.startsWith("word/media/");
316361
+ if (!isDataUri && !isInternalPath) {
316362
+ throw new DocumentApiAdapterError3("INVALID_INPUT", "External URLs are not supported in V1; provide a data URI or internal media path.");
316363
+ }
316364
+ const image3 = findImageById2(editor, input2.imageId);
316365
+ const newAttrs = {
316366
+ ...image3.node.attrs,
316367
+ src: input2.src,
316368
+ rId: null,
316369
+ originalSrc: null,
316370
+ originalExtension: null,
316371
+ clipPath: null,
316372
+ rawSrcRect: null,
316373
+ shouldCover: false
316374
+ };
316375
+ if (input2.resetSize) {
316376
+ if (!isDataUri) {
316377
+ throw new DocumentApiAdapterError3("INVALID_INPUT", "Cannot determine intrinsic dimensions from internal path; set size explicitly via setSize after replacement.");
316378
+ }
316379
+ const dims = readImageDimensionsFromDataUri2(input2.src);
316380
+ if (!dims) {
316381
+ throw new DocumentApiAdapterError3("INVALID_INPUT", "Could not determine intrinsic dimensions from data URI.");
316382
+ }
316383
+ newAttrs.size = { width: dims.width, height: dims.height };
316384
+ }
316385
+ if (options?.dryRun)
316386
+ return buildSuccessResult2(image3);
316387
+ const receipt2 = executeDomainCommand2(editor, () => {
316388
+ const { pos } = image3;
316389
+ const tr = editor.state.tr;
316390
+ tr.setNodeMarkup(pos, undefined, newAttrs);
316391
+ if (!tr.docChanged)
316392
+ return false;
316393
+ editor.dispatch(tr);
316394
+ return true;
316395
+ });
316396
+ if (receipt2.steps[0]?.effect !== "changed")
316397
+ return buildNoOpResult2("Replace source produced no change.");
316398
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316399
+ }
316400
+ function imagesSetAltTextWrapper2(editor, input2, options) {
316401
+ rejectTrackedMode2("images.setAltText", options);
316402
+ const image3 = findImageById2(editor, input2.imageId);
316403
+ if (image3.node.attrs.title === input2.description && !image3.node.attrs.decorative) {
316404
+ return buildNoOpResult2("Alt text is already as requested.");
316405
+ }
316406
+ if (options?.dryRun)
316407
+ return buildSuccessResult2(image3);
316408
+ const receipt2 = executeDomainCommand2(editor, () => {
316409
+ const { pos, node: node4 } = image3;
316410
+ const tr = editor.state.tr;
316411
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, title: input2.description, decorative: false });
316412
+ editor.dispatch(tr);
316413
+ return true;
316414
+ });
316415
+ if (receipt2.steps[0]?.effect !== "changed")
316416
+ return buildNoOpResult2("Set alt text produced no change.");
316417
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316418
+ }
316419
+ function imagesSetDecorativeWrapper2(editor, input2, options) {
316420
+ rejectTrackedMode2("images.setDecorative", options);
316421
+ const image3 = findImageById2(editor, input2.imageId);
316422
+ if ((image3.node.attrs.decorative ?? false) === input2.decorative) {
316423
+ return buildNoOpResult2(`Decorative is already ${input2.decorative}.`);
316424
+ }
316425
+ if (options?.dryRun)
316426
+ return buildSuccessResult2(image3);
316427
+ const receipt2 = executeDomainCommand2(editor, () => {
316428
+ const { pos, node: node4 } = image3;
316429
+ const tr = editor.state.tr;
316430
+ tr.setNodeMarkup(pos, undefined, {
316431
+ ...node4.attrs,
316432
+ decorative: input2.decorative,
316433
+ title: input2.decorative ? "" : node4.attrs.title
316434
+ });
316435
+ editor.dispatch(tr);
316436
+ return true;
316437
+ });
316438
+ if (receipt2.steps[0]?.effect !== "changed")
316439
+ return buildNoOpResult2("Set decorative produced no change.");
316440
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316441
+ }
316442
+ function imagesSetNameWrapper2(editor, input2, options) {
316443
+ rejectTrackedMode2("images.setName", options);
316444
+ const image3 = findImageById2(editor, input2.imageId);
316445
+ if (image3.node.attrs.alt === input2.name) {
316446
+ return buildNoOpResult2("Name is already as requested.");
316447
+ }
316448
+ if (options?.dryRun)
316449
+ return buildSuccessResult2(image3);
316450
+ const receipt2 = executeDomainCommand2(editor, () => {
316451
+ const { pos, node: node4 } = image3;
316452
+ const tr = editor.state.tr;
316453
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, alt: input2.name });
316454
+ editor.dispatch(tr);
316455
+ return true;
316456
+ });
316457
+ if (receipt2.steps[0]?.effect !== "changed")
316458
+ return buildNoOpResult2("Set name produced no change.");
316459
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316460
+ }
316461
+ function imagesSetHyperlinkWrapper2(editor, input2, options) {
316462
+ rejectTrackedMode2("images.setHyperlink", options);
316463
+ const image3 = findImageById2(editor, input2.imageId);
316464
+ const newValue = input2.url === null ? null : { url: input2.url, ...input2.tooltip ? { tooltip: input2.tooltip } : {} };
316465
+ const current = image3.node.attrs.hyperlink ?? null;
316466
+ if (current === null && newValue === null || current !== null && newValue !== null && current.url === newValue.url && current.tooltip === newValue.tooltip) {
316467
+ return buildNoOpResult2("Hyperlink is already as requested.");
316468
+ }
316469
+ if (options?.dryRun)
316470
+ return buildSuccessResult2(image3);
316471
+ const receipt2 = executeDomainCommand2(editor, () => {
316472
+ const { pos, node: node4 } = image3;
316473
+ const tr = editor.state.tr;
316474
+ tr.setNodeMarkup(pos, undefined, { ...node4.attrs, hyperlink: newValue });
316475
+ editor.dispatch(tr);
316476
+ return true;
316477
+ });
316478
+ if (receipt2.steps[0]?.effect !== "changed")
316479
+ return buildNoOpResult2("Set hyperlink produced no change.");
316480
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316481
+ }
316482
+ function findCaptionParagraph2(editor, imagePos) {
316483
+ const $pos = editor.state.doc.resolve(imagePos);
316484
+ const parentDepth = $pos.depth - 1;
316485
+ if (parentDepth < 0)
316486
+ return null;
316487
+ const parentPos = $pos.before(parentDepth + 1);
316488
+ const parentNode2 = $pos.node(parentDepth + 1);
316489
+ const afterParentPos = parentPos + parentNode2.nodeSize;
316490
+ if (afterParentPos >= editor.state.doc.content.size)
316491
+ return null;
316492
+ const nextNode = editor.state.doc.nodeAt(afterParentPos);
316493
+ if (!nextNode || nextNode.type.name !== "paragraph")
316494
+ return null;
316495
+ if (nextNode.attrs?.paragraphProperties?.styleId !== "Caption")
316496
+ return null;
316497
+ return { pos: afterParentPos, node: nextNode };
316498
+ }
316499
+ function requireSoleImageInParagraph2(editor, imagePos) {
316500
+ const $pos = editor.state.doc.resolve(imagePos);
316501
+ const parentDepth = $pos.depth - 1;
316502
+ if (parentDepth < 0) {
316503
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Caption operations require the image to be inside a paragraph.");
316504
+ }
316505
+ const parentNode2 = $pos.node(parentDepth + 1);
316506
+ let inlineContentCount = 0;
316507
+ parentNode2.forEach((child) => {
316508
+ if (child.isInline)
316509
+ inlineContentCount++;
316510
+ });
316511
+ if (inlineContentCount !== 1) {
316512
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Caption operations require the image to be the sole content of its paragraph.");
316513
+ }
316514
+ }
316515
+ function imagesInsertCaptionWrapper2(editor, input2, options) {
316516
+ rejectTrackedMode2("images.insertCaption", options);
316517
+ const image3 = findImageById2(editor, input2.imageId);
316518
+ requireSoleImageInParagraph2(editor, image3.pos);
316519
+ const existing = findCaptionParagraph2(editor, image3.pos);
316520
+ if (existing) {
316521
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "Image already has a caption; use updateCaption.");
316522
+ }
316523
+ if (options?.dryRun)
316524
+ return buildSuccessResult2(image3);
316525
+ const receipt2 = executeDomainCommand2(editor, () => {
316526
+ const $pos = editor.state.doc.resolve(image3.pos);
316527
+ const parentDepth = $pos.depth - 1;
316528
+ const parentPos = $pos.before(parentDepth + 1);
316529
+ const parentNode2 = $pos.node(parentDepth + 1);
316530
+ const afterParentPos = parentPos + parentNode2.nodeSize;
316531
+ const tr = editor.state.tr;
316532
+ const captionPara = editor.state.schema.nodes.paragraph.create({ paragraphProperties: { styleId: "Caption" } }, editor.state.schema.text(input2.text));
316533
+ tr.insert(afterParentPos, captionPara);
316534
+ if (!tr.docChanged)
316535
+ return false;
316536
+ editor.dispatch(tr);
316537
+ return true;
316538
+ });
316539
+ if (receipt2.steps[0]?.effect !== "changed")
316540
+ return buildNoOpResult2("Insert caption produced no change.");
316541
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316542
+ }
316543
+ function imagesUpdateCaptionWrapper2(editor, input2, options) {
316544
+ rejectTrackedMode2("images.updateCaption", options);
316545
+ const image3 = findImageById2(editor, input2.imageId);
316546
+ requireSoleImageInParagraph2(editor, image3.pos);
316547
+ const caption = findCaptionParagraph2(editor, image3.pos);
316548
+ if (!caption) {
316549
+ throw new DocumentApiAdapterError3("INVALID_TARGET", "No caption paragraph found; use insertCaption first.");
316550
+ }
316551
+ if (options?.dryRun)
316552
+ return buildSuccessResult2(image3);
316553
+ const receipt2 = executeDomainCommand2(editor, () => {
316554
+ const tr = editor.state.tr;
316555
+ const textStart = caption.pos + 1;
316556
+ const textEnd = caption.pos + caption.node.nodeSize - 1;
316557
+ tr.replaceWith(textStart, textEnd, editor.state.schema.text(input2.text));
316558
+ if (!tr.docChanged)
316559
+ return false;
316560
+ editor.dispatch(tr);
316561
+ return true;
316562
+ });
316563
+ if (receipt2.steps[0]?.effect !== "changed")
316564
+ return buildNoOpResult2("Update caption produced no change.");
316565
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316566
+ }
316567
+ function imagesRemoveCaptionWrapper2(editor, input2, options) {
316568
+ rejectTrackedMode2("images.removeCaption", options);
316569
+ const image3 = findImageById2(editor, input2.imageId);
316570
+ requireSoleImageInParagraph2(editor, image3.pos);
316571
+ const caption = findCaptionParagraph2(editor, image3.pos);
316572
+ if (!caption) {
316573
+ return buildNoOpResult2("No caption to remove.");
316574
+ }
316575
+ if (options?.dryRun)
316576
+ return buildSuccessResult2(image3);
316577
+ const receipt2 = executeDomainCommand2(editor, () => {
316578
+ const tr = editor.state.tr;
316579
+ tr.delete(caption.pos, caption.pos + caption.node.nodeSize);
316580
+ if (!tr.docChanged)
316581
+ return false;
316582
+ editor.dispatch(tr);
316583
+ return true;
316584
+ });
316585
+ if (receipt2.steps[0]?.effect !== "changed")
316586
+ return buildNoOpResult2("Remove caption produced no change.");
316587
+ return buildSuccessResult2(findImageById2(editor, input2.imageId));
316588
+ }
314489
316589
  var ALLOWED_WRAP_ATTRS2, WRAP_TYPES_SUPPORTING_SIDE2, WRAP_TYPES_SUPPORTING_DISTANCES2, RELATIVE_HEIGHT_MIN3 = 0, RELATIVE_HEIGHT_MAX3 = 4294967295;
314490
316590
  var init_images_wrappers = __esm(() => {
314491
316591
  init_wrapper();
@@ -315246,7 +317346,21 @@ function assembleDocumentApiAdapters2(editor) {
315246
317346
  setWrapDistances: (input2, options) => imagesSetWrapDistancesWrapper2(editor, input2, options),
315247
317347
  setPosition: (input2, options) => imagesSetPositionWrapper2(editor, input2, options),
315248
317348
  setAnchorOptions: (input2, options) => imagesSetAnchorOptionsWrapper2(editor, input2, options),
315249
- setZOrder: (input2, options) => imagesSetZOrderWrapper2(editor, input2, options)
317349
+ setZOrder: (input2, options) => imagesSetZOrderWrapper2(editor, input2, options),
317350
+ scale: (input2, options) => imagesScaleWrapper2(editor, input2, options),
317351
+ setLockAspectRatio: (input2, options) => imagesSetLockAspectRatioWrapper2(editor, input2, options),
317352
+ rotate: (input2, options) => imagesRotateWrapper2(editor, input2, options),
317353
+ flip: (input2, options) => imagesFlipWrapper2(editor, input2, options),
317354
+ crop: (input2, options) => imagesCropWrapper2(editor, input2, options),
317355
+ resetCrop: (input2, options) => imagesResetCropWrapper2(editor, input2, options),
317356
+ replaceSource: (input2, options) => imagesReplaceSourceWrapper2(editor, input2, options),
317357
+ setAltText: (input2, options) => imagesSetAltTextWrapper2(editor, input2, options),
317358
+ setDecorative: (input2, options) => imagesSetDecorativeWrapper2(editor, input2, options),
317359
+ setName: (input2, options) => imagesSetNameWrapper2(editor, input2, options),
317360
+ setHyperlink: (input2, options) => imagesSetHyperlinkWrapper2(editor, input2, options),
317361
+ insertCaption: (input2, options) => imagesInsertCaptionWrapper2(editor, input2, options),
317362
+ updateCaption: (input2, options) => imagesUpdateCaptionWrapper2(editor, input2, options),
317363
+ removeCaption: (input2, options) => imagesRemoveCaptionWrapper2(editor, input2, options)
315250
317364
  },
315251
317365
  hyperlinks: {
315252
317366
  list: (query2) => hyperlinksListWrapper2(editor, query2),
@@ -368495,6 +370609,25 @@ var init_collaboration = __esm(() => {
368495
370609
  });
368496
370610
 
368497
370611
  // src/lib/bootstrap.ts
370612
+ function waitForContentSettling(ydoc, maxWaitMs = CONTENT_SETTLING_MAX_MS) {
370613
+ if (detectRoomState(ydoc) === "populated")
370614
+ return Promise.resolve();
370615
+ const fragment = ydoc.getXmlFragment("supereditor");
370616
+ return new Promise((resolve4) => {
370617
+ const timeout2 = setTimeout(() => {
370618
+ fragment.unobserve(observer);
370619
+ resolve4();
370620
+ }, maxWaitMs);
370621
+ const observer = () => {
370622
+ if (fragment.length > 0) {
370623
+ clearTimeout(timeout2);
370624
+ fragment.unobserve(observer);
370625
+ resolve4();
370626
+ }
370627
+ };
370628
+ fragment.observe(observer);
370629
+ });
370630
+ }
368498
370631
  function detectRoomState(ydoc) {
368499
370632
  const fragment = ydoc.getXmlFragment("supereditor");
368500
370633
  if (fragment.length > 0)
@@ -368523,6 +370656,9 @@ function resolveBootstrapDecision(roomState, onMissing, hasDoc) {
368523
370656
  return { action: "error", reason: 'Collaboration room is empty and onMissing is set to "error".' };
368524
370657
  }
368525
370658
  }
370659
+ function clearBootstrapMarker(ydoc) {
370660
+ ydoc.getMap("meta").delete("bootstrap");
370661
+ }
368526
370662
  function writeBootstrapMarker(ydoc, source) {
368527
370663
  const metaMap = ydoc.getMap("meta");
368528
370664
  const marker = {
@@ -368605,7 +370741,7 @@ async function detectBootstrapRace(ydoc, observeMs = POST_SEED_OBSERVE_MS) {
368605
370741
  observer.dispose();
368606
370742
  }
368607
370743
  }
368608
- var DEFAULT_BOOTSTRAP_SETTLING_MS = 1500, DEFAULT_BOOTSTRAP_JITTER_MS = 150, POST_SEED_OBSERVE_MS = 200;
370744
+ var DEFAULT_BOOTSTRAP_SETTLING_MS = 1500, DEFAULT_BOOTSTRAP_JITTER_MS = 150, POST_SEED_OBSERVE_MS = 200, CONTENT_SETTLING_MAX_MS = 200;
368609
370745
 
368610
370746
  // src/lib/document.ts
368611
370747
  import { readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
@@ -368747,6 +370883,7 @@ async function openCollaborativeDocument(doc4, io, profile, options2 = {}) {
368747
370883
  const runtime = createCollaborationRuntime(profile);
368748
370884
  try {
368749
370885
  await runtime.waitForSync();
370886
+ await waitForContentSettling(runtime.ydoc);
368750
370887
  const onMissing = profile.onMissing ?? "seedFromDoc";
368751
370888
  let finalRoomState = detectRoomState(runtime.ydoc);
368752
370889
  let decision = resolveBootstrapDecision(finalRoomState, onMissing, doc4 != null);
@@ -368755,6 +370892,13 @@ async function openCollaborativeDocument(doc4, io, profile, options2 = {}) {
368755
370892
  if (!claim.granted) {
368756
370893
  finalRoomState = detectRoomState(runtime.ydoc);
368757
370894
  decision = { action: "join" };
370895
+ } else {
370896
+ const postClaimState = detectRoomState(runtime.ydoc);
370897
+ if (postClaimState === "populated") {
370898
+ clearBootstrapMarker(runtime.ydoc);
370899
+ finalRoomState = postClaimState;
370900
+ decision = { action: "join" };
370901
+ }
368758
370902
  }
368759
370903
  }
368760
370904
  if (decision.action === "error") {