@uniformdev/tms-sdk 19.154.1-alpha.27 → 19.154.1-alpha.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  bindVariables,
4
4
  walkNodeTree as walkNodeTree2
5
5
  } from "@uniformdev/canvas";
6
- import { isRichTextValue, isRichTextValueConsideredEmpty as isRichTextValueConsideredEmpty2 } from "@uniformdev/richtext";
6
+ import { isRichTextValue as isRichTextValue2, isRichTextValueConsideredEmpty as isRichTextValueConsideredEmpty2 } from "@uniformdev/richtext";
7
7
 
8
8
  // src/constants.ts
9
9
  var TRANSLATION_PAYLOAD_SOURCE_KEY = "source";
@@ -14,12 +14,213 @@ var SUPPORTED_PARAM_TYPES = {
14
14
  richText: "richText"
15
15
  };
16
16
 
17
+ // src/richText/renderAsTranslatableXml.ts
18
+ import { getRichTextTagsFromTextFormat, isRichTextNodeType } from "@uniformdev/richtext";
19
+ var REF_ATTRIBUTE_NAME = "ref";
20
+ function renderAsTranslatableXml(root) {
21
+ if (!root) {
22
+ return null;
23
+ }
24
+ const result = {
25
+ attributes: [],
26
+ xmlParts: []
27
+ };
28
+ renderXmlNode(result, root);
29
+ const metadata = result.attributes.reduce((result2, current, index) => {
30
+ result2[String(index)] = {
31
+ attrs: current
32
+ };
33
+ return result2;
34
+ }, {});
35
+ return {
36
+ metadata,
37
+ xml: result.xmlParts.join("")
38
+ };
39
+ }
40
+ var IGNORE_ATTRS = ["type", "children", "text"];
41
+ function renderXmlNode(context, node) {
42
+ if (!node) {
43
+ return;
44
+ }
45
+ const base64Props = getPropsAsBase64(node, IGNORE_ATTRS);
46
+ let refKey = context.attributes.findIndex((x) => x === base64Props);
47
+ if (refKey == -1) {
48
+ context.attributes.push(base64Props);
49
+ refKey = context.attributes.length - 1;
50
+ }
51
+ context.xmlParts.push(`<${node.type} ${REF_ATTRIBUTE_NAME}="${refKey}"`);
52
+ const metaAttrsString = getNodeMetaAttributesString(node);
53
+ if (metaAttrsString) {
54
+ context.xmlParts.push(" " + metaAttrsString);
55
+ }
56
+ context.xmlParts.push(">");
57
+ if (isRichTextNodeType(node, "text")) {
58
+ context.xmlParts.push(node.text);
59
+ } else if (Array.isArray(node.children) && node.children.length) {
60
+ node.children.forEach((child) => {
61
+ renderXmlNode(context, child);
62
+ });
63
+ }
64
+ context.xmlParts.push(`</${node.type}>`);
65
+ }
66
+ var getPropsAsBase64 = (node, ignoreProps) => {
67
+ const props = {};
68
+ Object.keys(node).forEach((key) => {
69
+ if (!ignoreProps.includes(key)) {
70
+ props[key] = node[key];
71
+ }
72
+ });
73
+ return btoa(JSON.stringify(props));
74
+ };
75
+ var getNodeMetaAttributesString = (node) => {
76
+ const metadata = {};
77
+ if (isRichTextNodeType(node, "text")) {
78
+ const formatTags = getRichTextTagsFromTextFormat(node.format);
79
+ if (formatTags.length) {
80
+ metadata["format"] = formatTags.join(" ");
81
+ }
82
+ } else if (isRichTextNodeType(node, "heading")) {
83
+ if (node.tag) {
84
+ metadata["tag"] = node.tag;
85
+ }
86
+ } else if (isRichTextNodeType(node, "paragraph")) {
87
+ if (node.format) {
88
+ metadata["format"] = node.format;
89
+ }
90
+ } else if (isRichTextNodeType(node, "list")) {
91
+ if (node.tag) {
92
+ metadata["tag"] = node.tag;
93
+ }
94
+ } else if (isRichTextNodeType(node, "listitem")) {
95
+ metadata["value"] = String(node.value);
96
+ }
97
+ if (!Object.keys(metadata).length) {
98
+ return "";
99
+ }
100
+ const result = [];
101
+ Object.entries(metadata).forEach(([key, value]) => {
102
+ result.push(`${key}="${value}"`);
103
+ });
104
+ return result.join(" ");
105
+ };
106
+
17
107
  // src/translationHelpers.ts
18
108
  import {
19
109
  walkNodeTree
20
110
  } from "@uniformdev/canvas";
21
111
  import { isRichTextValueConsideredEmpty } from "@uniformdev/richtext";
22
112
  import { dequal } from "dequal/lite";
113
+
114
+ // src/richText/parseTranslatableXml.ts
115
+ import { isRichTextValue } from "@uniformdev/richtext";
116
+ import { XMLParser } from "fast-xml-parser";
117
+ var ATTR_NAME_PREFIX = "@_";
118
+ var ATTRIBUTES_SUBNODE_NAME = ":@";
119
+ var IGNORE_PROPS_PREFIX = [ATTR_NAME_PREFIX, ATTRIBUTES_SUBNODE_NAME, "#"];
120
+ var parseTranslatableXml = ({ xml, metadata }) => {
121
+ const parser = new XMLParser({
122
+ ignoreDeclaration: true,
123
+ ignorePiTags: true,
124
+ ignoreAttributes: false,
125
+ preserveOrder: true,
126
+ trimValues: false,
127
+ attributeNamePrefix: ATTR_NAME_PREFIX
128
+ });
129
+ const rawObj = parser.parse(xml);
130
+ const result = processParseObject(rawObj, {
131
+ metadata,
132
+ nodeTypes: []
133
+ });
134
+ return result;
135
+ };
136
+ var processParseObject = (rawObj, context) => {
137
+ const result = visitAndTransformNode(rawObj, context);
138
+ const root = Array.isArray(result) ? result.at(0) : result;
139
+ if (root && root.type === "root") {
140
+ const value = { root };
141
+ if (isRichTextValue(value)) {
142
+ return value;
143
+ }
144
+ }
145
+ return null;
146
+ };
147
+ var visitAndTransformNode = (node, context) => {
148
+ if (Array.isArray(node)) {
149
+ return node.map((x) => visitAndTransformNode(x, context)).filter((node2) => !!node2);
150
+ } else if (typeof node === "object" && node !== null) {
151
+ const type = Object.keys(node).find(
152
+ (key) => !IGNORE_PROPS_PREFIX.some((prefix) => key.startsWith(prefix))
153
+ );
154
+ if (!type) {
155
+ return null;
156
+ }
157
+ const transformed = {};
158
+ transformed["type"] = type;
159
+ const propsFromRef = restorePropsFromRef(node, context);
160
+ Object.entries(propsFromRef).forEach(([key, value]) => {
161
+ transformed[key] = value;
162
+ });
163
+ if (type === "text") {
164
+ const nestedNode = node[type];
165
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
166
+ const firstChild = nestedNodeAsArray.at(0);
167
+ const text = firstChild == null ? void 0 : firstChild["#text"];
168
+ transformed["text"] = typeof text === "string" && text ? text : "";
169
+ } else {
170
+ const children = [];
171
+ const nestedNode = node[type];
172
+ if (typeof nestedNode === "object" && nestedNode) {
173
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
174
+ nestedNodeAsArray.forEach((currNode) => {
175
+ const transformed2 = visitAndTransformNode(currNode, context);
176
+ if (transformed2) {
177
+ children.push(transformed2);
178
+ }
179
+ });
180
+ }
181
+ if (children.length) {
182
+ transformed["children"] = children;
183
+ }
184
+ }
185
+ return transformed;
186
+ } else {
187
+ return node;
188
+ }
189
+ };
190
+ var restorePropsFromRef = (node, context) => {
191
+ const result = {};
192
+ let uniformRef = node[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
193
+ if (!uniformRef) {
194
+ const attrsSubNode = node[ATTRIBUTES_SUBNODE_NAME];
195
+ uniformRef = attrsSubNode == null ? void 0 : attrsSubNode[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
196
+ }
197
+ if (typeof uniformRef === "string" && uniformRef && context.metadata[uniformRef]) {
198
+ const metadata = context.metadata[uniformRef];
199
+ if (metadata.attrs) {
200
+ const decodedProps = JSON.parse(atob(metadata.attrs));
201
+ Object.keys(decodedProps).forEach((key) => {
202
+ result[key] = decodedProps[key];
203
+ });
204
+ }
205
+ }
206
+ return result;
207
+ };
208
+
209
+ // src/richText/types.ts
210
+ var isTranslatableRichTextValue = (value) => {
211
+ if (typeof value !== "object" || !value) {
212
+ return false;
213
+ }
214
+ if (!("xml" in value) || typeof value.xml !== "string") {
215
+ return false;
216
+ }
217
+ if (!("metadata" in value) || typeof value.metadata !== "object" || !value.metadata) {
218
+ return false;
219
+ }
220
+ return true;
221
+ };
222
+
223
+ // src/translationHelpers.ts
23
224
  var MERGE_TRANSLATION_ERRORS = {
24
225
  unknown: "Unknown error",
25
226
  "invalid-args": "Invalid arguments",
@@ -103,9 +304,19 @@ var processParameterTranslation = ({
103
304
  left: originalParameter.locales[uniformTargetLocale],
104
305
  right: originalTargetValue
105
306
  });
106
- if (targetValue && isSourceValueUntouched && isTargetValueUntouched) {
107
- originalParameter.locales[uniformTargetLocale] = targetValue;
108
- return { updated: true };
307
+ if (targetValue !== void 0 && isSourceValueUntouched && isTargetValueUntouched) {
308
+ if (parameter.type == SUPPORTED_PARAM_TYPES.richText && isTranslatableRichTextValue(targetValue)) {
309
+ try {
310
+ const richTextValue = parseTranslatableXml(targetValue);
311
+ originalParameter.locales[uniformTargetLocale] = richTextValue;
312
+ return { updated: true };
313
+ } catch (e) {
314
+ return { updated: false };
315
+ }
316
+ } else if (parameter.type == SUPPORTED_PARAM_TYPES.text) {
317
+ originalParameter.locales[uniformTargetLocale] = targetValue;
318
+ return { updated: true };
319
+ }
109
320
  }
110
321
  return { updated: false };
111
322
  };
@@ -118,29 +329,18 @@ var processOverrideTranslation = ({
118
329
  var _a, _b;
119
330
  let updated = false;
120
331
  Object.entries((_a = override.parameters) != null ? _a : {}).forEach(([paramKey, parameter]) => {
121
- var _a2, _b2, _c, _d;
332
+ var _a2;
122
333
  const originalParameter = (_a2 = originalOverride.parameters) == null ? void 0 : _a2[paramKey];
123
- if (!originalParameter || !originalParameter.locales) {
124
- return;
125
- }
126
- if (originalParameter.type !== parameter.type) {
334
+ if (!originalParameter) {
127
335
  return;
128
336
  }
129
- const sourceValue = (_b2 = parameter.locales) == null ? void 0 : _b2[TRANSLATION_PAYLOAD_SOURCE_KEY];
130
- const targetValue = (_c = parameter.locales) == null ? void 0 : _c[TRANSLATION_PAYLOAD_TARGET_KEY];
131
- const originalTargetValue = (_d = parameter.locales) == null ? void 0 : _d[TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY];
132
- const isSourceValueUntouched = isSameParameterValue({
133
- parameterType: originalParameter.type,
134
- left: originalParameter.locales[uniformSourceLocale],
135
- right: sourceValue
136
- });
137
- const isTargetValueUntouched = isSameParameterValue({
138
- parameterType: originalParameter.type,
139
- left: originalParameter.locales[uniformTargetLocale],
140
- right: originalTargetValue
337
+ const result = processParameterTranslation({
338
+ uniformSourceLocale,
339
+ uniformTargetLocale,
340
+ originalParameter,
341
+ parameter
141
342
  });
142
- if (targetValue && isSourceValueUntouched && isTargetValueUntouched) {
143
- originalParameter.locales[uniformTargetLocale] = targetValue;
343
+ if (result.updated) {
144
344
  updated = true;
145
345
  }
146
346
  });
@@ -194,8 +394,12 @@ var isSameParameterValue = ({
194
394
  return left === right || !left && !right;
195
395
  break;
196
396
  case SUPPORTED_PARAM_TYPES.richText:
197
- if (isRichTextValueConsideredEmpty(left) && isRichTextValueConsideredEmpty(right)) {
198
- return true;
397
+ try {
398
+ if (isRichTextValueConsideredEmpty(left) && isRichTextValueConsideredEmpty(right)) {
399
+ return true;
400
+ }
401
+ } catch (e) {
402
+ return false;
199
403
  }
200
404
  return dequal(left, right);
201
405
  break;
@@ -302,7 +506,7 @@ var collectFromNode = ({
302
506
  type: param.type,
303
507
  locales: {
304
508
  [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
305
- [TRANSLATION_PAYLOAD_TARGET_KEY]: sourceLocaleValue,
509
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
306
510
  [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
307
511
  }
308
512
  };
@@ -346,7 +550,7 @@ var collectFromNode = ({
346
550
  type: param.type,
347
551
  locales: {
348
552
  [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
349
- [TRANSLATION_PAYLOAD_TARGET_KEY]: sourceLocaleValue,
553
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
350
554
  [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
351
555
  }
352
556
  };
@@ -405,7 +609,7 @@ var canTranslateParameterValue = (parameter, value) => {
405
609
  }
406
610
  return true;
407
611
  } else if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
408
- return isRichTextValue(value) && !isRichTextValueConsideredEmpty2(value);
612
+ return isRichTextValue2(value) && !isRichTextValueConsideredEmpty2(value);
409
613
  }
410
614
  return false;
411
615
  };
@@ -425,6 +629,16 @@ var isTargetLocaleUntouched = (parameterType, sourceLocaleValue, targetLocaleVal
425
629
  right: targetLocaleValue
426
630
  });
427
631
  };
632
+ var preprocessTargetValue = (parameter, value) => {
633
+ if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
634
+ try {
635
+ return isRichTextValue2(value) ? renderAsTranslatableXml(value.root) : value;
636
+ } catch (e) {
637
+ return value;
638
+ }
639
+ }
640
+ return value;
641
+ };
428
642
 
429
643
  // src/getCompositionForTranslation.ts
430
644
  import { CANVAS_DRAFT_STATE } from "@uniformdev/canvas";
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ module.exports = __toCommonJS(src_exports);
33
33
 
34
34
  // src/collectTranslationPayload.ts
35
35
  var import_canvas2 = require("@uniformdev/canvas");
36
- var import_richtext2 = require("@uniformdev/richtext");
36
+ var import_richtext4 = require("@uniformdev/richtext");
37
37
 
38
38
  // src/constants.ts
39
39
  var TRANSLATION_PAYLOAD_SOURCE_KEY = "source";
@@ -44,10 +44,211 @@ var SUPPORTED_PARAM_TYPES = {
44
44
  richText: "richText"
45
45
  };
46
46
 
47
+ // src/richText/renderAsTranslatableXml.ts
48
+ var import_richtext = require("@uniformdev/richtext");
49
+ var REF_ATTRIBUTE_NAME = "ref";
50
+ function renderAsTranslatableXml(root) {
51
+ if (!root) {
52
+ return null;
53
+ }
54
+ const result = {
55
+ attributes: [],
56
+ xmlParts: []
57
+ };
58
+ renderXmlNode(result, root);
59
+ const metadata = result.attributes.reduce((result2, current, index) => {
60
+ result2[String(index)] = {
61
+ attrs: current
62
+ };
63
+ return result2;
64
+ }, {});
65
+ return {
66
+ metadata,
67
+ xml: result.xmlParts.join("")
68
+ };
69
+ }
70
+ var IGNORE_ATTRS = ["type", "children", "text"];
71
+ function renderXmlNode(context, node) {
72
+ if (!node) {
73
+ return;
74
+ }
75
+ const base64Props = getPropsAsBase64(node, IGNORE_ATTRS);
76
+ let refKey = context.attributes.findIndex((x) => x === base64Props);
77
+ if (refKey == -1) {
78
+ context.attributes.push(base64Props);
79
+ refKey = context.attributes.length - 1;
80
+ }
81
+ context.xmlParts.push(`<${node.type} ${REF_ATTRIBUTE_NAME}="${refKey}"`);
82
+ const metaAttrsString = getNodeMetaAttributesString(node);
83
+ if (metaAttrsString) {
84
+ context.xmlParts.push(" " + metaAttrsString);
85
+ }
86
+ context.xmlParts.push(">");
87
+ if ((0, import_richtext.isRichTextNodeType)(node, "text")) {
88
+ context.xmlParts.push(node.text);
89
+ } else if (Array.isArray(node.children) && node.children.length) {
90
+ node.children.forEach((child) => {
91
+ renderXmlNode(context, child);
92
+ });
93
+ }
94
+ context.xmlParts.push(`</${node.type}>`);
95
+ }
96
+ var getPropsAsBase64 = (node, ignoreProps) => {
97
+ const props = {};
98
+ Object.keys(node).forEach((key) => {
99
+ if (!ignoreProps.includes(key)) {
100
+ props[key] = node[key];
101
+ }
102
+ });
103
+ return btoa(JSON.stringify(props));
104
+ };
105
+ var getNodeMetaAttributesString = (node) => {
106
+ const metadata = {};
107
+ if ((0, import_richtext.isRichTextNodeType)(node, "text")) {
108
+ const formatTags = (0, import_richtext.getRichTextTagsFromTextFormat)(node.format);
109
+ if (formatTags.length) {
110
+ metadata["format"] = formatTags.join(" ");
111
+ }
112
+ } else if ((0, import_richtext.isRichTextNodeType)(node, "heading")) {
113
+ if (node.tag) {
114
+ metadata["tag"] = node.tag;
115
+ }
116
+ } else if ((0, import_richtext.isRichTextNodeType)(node, "paragraph")) {
117
+ if (node.format) {
118
+ metadata["format"] = node.format;
119
+ }
120
+ } else if ((0, import_richtext.isRichTextNodeType)(node, "list")) {
121
+ if (node.tag) {
122
+ metadata["tag"] = node.tag;
123
+ }
124
+ } else if ((0, import_richtext.isRichTextNodeType)(node, "listitem")) {
125
+ metadata["value"] = String(node.value);
126
+ }
127
+ if (!Object.keys(metadata).length) {
128
+ return "";
129
+ }
130
+ const result = [];
131
+ Object.entries(metadata).forEach(([key, value]) => {
132
+ result.push(`${key}="${value}"`);
133
+ });
134
+ return result.join(" ");
135
+ };
136
+
47
137
  // src/translationHelpers.ts
48
138
  var import_canvas = require("@uniformdev/canvas");
49
- var import_richtext = require("@uniformdev/richtext");
139
+ var import_richtext3 = require("@uniformdev/richtext");
50
140
  var import_lite = require("dequal/lite");
141
+
142
+ // src/richText/parseTranslatableXml.ts
143
+ var import_richtext2 = require("@uniformdev/richtext");
144
+ var import_fast_xml_parser = require("fast-xml-parser");
145
+ var ATTR_NAME_PREFIX = "@_";
146
+ var ATTRIBUTES_SUBNODE_NAME = ":@";
147
+ var IGNORE_PROPS_PREFIX = [ATTR_NAME_PREFIX, ATTRIBUTES_SUBNODE_NAME, "#"];
148
+ var parseTranslatableXml = ({ xml, metadata }) => {
149
+ const parser = new import_fast_xml_parser.XMLParser({
150
+ ignoreDeclaration: true,
151
+ ignorePiTags: true,
152
+ ignoreAttributes: false,
153
+ preserveOrder: true,
154
+ trimValues: false,
155
+ attributeNamePrefix: ATTR_NAME_PREFIX
156
+ });
157
+ const rawObj = parser.parse(xml);
158
+ const result = processParseObject(rawObj, {
159
+ metadata,
160
+ nodeTypes: []
161
+ });
162
+ return result;
163
+ };
164
+ var processParseObject = (rawObj, context) => {
165
+ const result = visitAndTransformNode(rawObj, context);
166
+ const root = Array.isArray(result) ? result.at(0) : result;
167
+ if (root && root.type === "root") {
168
+ const value = { root };
169
+ if ((0, import_richtext2.isRichTextValue)(value)) {
170
+ return value;
171
+ }
172
+ }
173
+ return null;
174
+ };
175
+ var visitAndTransformNode = (node, context) => {
176
+ if (Array.isArray(node)) {
177
+ return node.map((x) => visitAndTransformNode(x, context)).filter((node2) => !!node2);
178
+ } else if (typeof node === "object" && node !== null) {
179
+ const type = Object.keys(node).find(
180
+ (key) => !IGNORE_PROPS_PREFIX.some((prefix) => key.startsWith(prefix))
181
+ );
182
+ if (!type) {
183
+ return null;
184
+ }
185
+ const transformed = {};
186
+ transformed["type"] = type;
187
+ const propsFromRef = restorePropsFromRef(node, context);
188
+ Object.entries(propsFromRef).forEach(([key, value]) => {
189
+ transformed[key] = value;
190
+ });
191
+ if (type === "text") {
192
+ const nestedNode = node[type];
193
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
194
+ const firstChild = nestedNodeAsArray.at(0);
195
+ const text = firstChild == null ? void 0 : firstChild["#text"];
196
+ transformed["text"] = typeof text === "string" && text ? text : "";
197
+ } else {
198
+ const children = [];
199
+ const nestedNode = node[type];
200
+ if (typeof nestedNode === "object" && nestedNode) {
201
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
202
+ nestedNodeAsArray.forEach((currNode) => {
203
+ const transformed2 = visitAndTransformNode(currNode, context);
204
+ if (transformed2) {
205
+ children.push(transformed2);
206
+ }
207
+ });
208
+ }
209
+ if (children.length) {
210
+ transformed["children"] = children;
211
+ }
212
+ }
213
+ return transformed;
214
+ } else {
215
+ return node;
216
+ }
217
+ };
218
+ var restorePropsFromRef = (node, context) => {
219
+ const result = {};
220
+ let uniformRef = node[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
221
+ if (!uniformRef) {
222
+ const attrsSubNode = node[ATTRIBUTES_SUBNODE_NAME];
223
+ uniformRef = attrsSubNode == null ? void 0 : attrsSubNode[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
224
+ }
225
+ if (typeof uniformRef === "string" && uniformRef && context.metadata[uniformRef]) {
226
+ const metadata = context.metadata[uniformRef];
227
+ if (metadata.attrs) {
228
+ const decodedProps = JSON.parse(atob(metadata.attrs));
229
+ Object.keys(decodedProps).forEach((key) => {
230
+ result[key] = decodedProps[key];
231
+ });
232
+ }
233
+ }
234
+ return result;
235
+ };
236
+
237
+ // src/richText/types.ts
238
+ var isTranslatableRichTextValue = (value) => {
239
+ if (typeof value !== "object" || !value) {
240
+ return false;
241
+ }
242
+ if (!("xml" in value) || typeof value.xml !== "string") {
243
+ return false;
244
+ }
245
+ if (!("metadata" in value) || typeof value.metadata !== "object" || !value.metadata) {
246
+ return false;
247
+ }
248
+ return true;
249
+ };
250
+
251
+ // src/translationHelpers.ts
51
252
  var MERGE_TRANSLATION_ERRORS = {
52
253
  unknown: "Unknown error",
53
254
  "invalid-args": "Invalid arguments",
@@ -131,9 +332,19 @@ var processParameterTranslation = ({
131
332
  left: originalParameter.locales[uniformTargetLocale],
132
333
  right: originalTargetValue
133
334
  });
134
- if (targetValue && isSourceValueUntouched && isTargetValueUntouched) {
135
- originalParameter.locales[uniformTargetLocale] = targetValue;
136
- return { updated: true };
335
+ if (targetValue !== void 0 && isSourceValueUntouched && isTargetValueUntouched) {
336
+ if (parameter.type == SUPPORTED_PARAM_TYPES.richText && isTranslatableRichTextValue(targetValue)) {
337
+ try {
338
+ const richTextValue = parseTranslatableXml(targetValue);
339
+ originalParameter.locales[uniformTargetLocale] = richTextValue;
340
+ return { updated: true };
341
+ } catch (e) {
342
+ return { updated: false };
343
+ }
344
+ } else if (parameter.type == SUPPORTED_PARAM_TYPES.text) {
345
+ originalParameter.locales[uniformTargetLocale] = targetValue;
346
+ return { updated: true };
347
+ }
137
348
  }
138
349
  return { updated: false };
139
350
  };
@@ -146,29 +357,18 @@ var processOverrideTranslation = ({
146
357
  var _a, _b;
147
358
  let updated = false;
148
359
  Object.entries((_a = override.parameters) != null ? _a : {}).forEach(([paramKey, parameter]) => {
149
- var _a2, _b2, _c, _d;
360
+ var _a2;
150
361
  const originalParameter = (_a2 = originalOverride.parameters) == null ? void 0 : _a2[paramKey];
151
- if (!originalParameter || !originalParameter.locales) {
152
- return;
153
- }
154
- if (originalParameter.type !== parameter.type) {
362
+ if (!originalParameter) {
155
363
  return;
156
364
  }
157
- const sourceValue = (_b2 = parameter.locales) == null ? void 0 : _b2[TRANSLATION_PAYLOAD_SOURCE_KEY];
158
- const targetValue = (_c = parameter.locales) == null ? void 0 : _c[TRANSLATION_PAYLOAD_TARGET_KEY];
159
- const originalTargetValue = (_d = parameter.locales) == null ? void 0 : _d[TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY];
160
- const isSourceValueUntouched = isSameParameterValue({
161
- parameterType: originalParameter.type,
162
- left: originalParameter.locales[uniformSourceLocale],
163
- right: sourceValue
164
- });
165
- const isTargetValueUntouched = isSameParameterValue({
166
- parameterType: originalParameter.type,
167
- left: originalParameter.locales[uniformTargetLocale],
168
- right: originalTargetValue
365
+ const result = processParameterTranslation({
366
+ uniformSourceLocale,
367
+ uniformTargetLocale,
368
+ originalParameter,
369
+ parameter
169
370
  });
170
- if (targetValue && isSourceValueUntouched && isTargetValueUntouched) {
171
- originalParameter.locales[uniformTargetLocale] = targetValue;
371
+ if (result.updated) {
172
372
  updated = true;
173
373
  }
174
374
  });
@@ -222,8 +422,12 @@ var isSameParameterValue = ({
222
422
  return left === right || !left && !right;
223
423
  break;
224
424
  case SUPPORTED_PARAM_TYPES.richText:
225
- if ((0, import_richtext.isRichTextValueConsideredEmpty)(left) && (0, import_richtext.isRichTextValueConsideredEmpty)(right)) {
226
- return true;
425
+ try {
426
+ if ((0, import_richtext3.isRichTextValueConsideredEmpty)(left) && (0, import_richtext3.isRichTextValueConsideredEmpty)(right)) {
427
+ return true;
428
+ }
429
+ } catch (e) {
430
+ return false;
227
431
  }
228
432
  return (0, import_lite.dequal)(left, right);
229
433
  break;
@@ -330,7 +534,7 @@ var collectFromNode = ({
330
534
  type: param.type,
331
535
  locales: {
332
536
  [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
333
- [TRANSLATION_PAYLOAD_TARGET_KEY]: sourceLocaleValue,
537
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
334
538
  [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
335
539
  }
336
540
  };
@@ -374,7 +578,7 @@ var collectFromNode = ({
374
578
  type: param.type,
375
579
  locales: {
376
580
  [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
377
- [TRANSLATION_PAYLOAD_TARGET_KEY]: sourceLocaleValue,
581
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
378
582
  [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
379
583
  }
380
584
  };
@@ -433,7 +637,7 @@ var canTranslateParameterValue = (parameter, value) => {
433
637
  }
434
638
  return true;
435
639
  } else if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
436
- return (0, import_richtext2.isRichTextValue)(value) && !(0, import_richtext2.isRichTextValueConsideredEmpty)(value);
640
+ return (0, import_richtext4.isRichTextValue)(value) && !(0, import_richtext4.isRichTextValueConsideredEmpty)(value);
437
641
  }
438
642
  return false;
439
643
  };
@@ -444,7 +648,7 @@ var isTargetLocaleUntouched = (parameterType, sourceLocaleValue, targetLocaleVal
444
648
  if (parameterType === SUPPORTED_PARAM_TYPES.text && !targetLocaleValue) {
445
649
  return true;
446
650
  }
447
- if (parameterType === SUPPORTED_PARAM_TYPES.richText && (0, import_richtext2.isRichTextValueConsideredEmpty)(targetLocaleValue)) {
651
+ if (parameterType === SUPPORTED_PARAM_TYPES.richText && (0, import_richtext4.isRichTextValueConsideredEmpty)(targetLocaleValue)) {
448
652
  return true;
449
653
  }
450
654
  return isSameParameterValue({
@@ -453,6 +657,16 @@ var isTargetLocaleUntouched = (parameterType, sourceLocaleValue, targetLocaleVal
453
657
  right: targetLocaleValue
454
658
  });
455
659
  };
660
+ var preprocessTargetValue = (parameter, value) => {
661
+ if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
662
+ try {
663
+ return (0, import_richtext4.isRichTextValue)(value) ? renderAsTranslatableXml(value.root) : value;
664
+ } catch (e) {
665
+ return value;
666
+ }
667
+ }
668
+ return value;
669
+ };
456
670
 
457
671
  // src/getCompositionForTranslation.ts
458
672
  var import_canvas3 = require("@uniformdev/canvas");
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  bindVariables,
4
4
  walkNodeTree as walkNodeTree2
5
5
  } from "@uniformdev/canvas";
6
- import { isRichTextValue, isRichTextValueConsideredEmpty as isRichTextValueConsideredEmpty2 } from "@uniformdev/richtext";
6
+ import { isRichTextValue as isRichTextValue2, isRichTextValueConsideredEmpty as isRichTextValueConsideredEmpty2 } from "@uniformdev/richtext";
7
7
 
8
8
  // src/constants.ts
9
9
  var TRANSLATION_PAYLOAD_SOURCE_KEY = "source";
@@ -14,12 +14,213 @@ var SUPPORTED_PARAM_TYPES = {
14
14
  richText: "richText"
15
15
  };
16
16
 
17
+ // src/richText/renderAsTranslatableXml.ts
18
+ import { getRichTextTagsFromTextFormat, isRichTextNodeType } from "@uniformdev/richtext";
19
+ var REF_ATTRIBUTE_NAME = "ref";
20
+ function renderAsTranslatableXml(root) {
21
+ if (!root) {
22
+ return null;
23
+ }
24
+ const result = {
25
+ attributes: [],
26
+ xmlParts: []
27
+ };
28
+ renderXmlNode(result, root);
29
+ const metadata = result.attributes.reduce((result2, current, index) => {
30
+ result2[String(index)] = {
31
+ attrs: current
32
+ };
33
+ return result2;
34
+ }, {});
35
+ return {
36
+ metadata,
37
+ xml: result.xmlParts.join("")
38
+ };
39
+ }
40
+ var IGNORE_ATTRS = ["type", "children", "text"];
41
+ function renderXmlNode(context, node) {
42
+ if (!node) {
43
+ return;
44
+ }
45
+ const base64Props = getPropsAsBase64(node, IGNORE_ATTRS);
46
+ let refKey = context.attributes.findIndex((x) => x === base64Props);
47
+ if (refKey == -1) {
48
+ context.attributes.push(base64Props);
49
+ refKey = context.attributes.length - 1;
50
+ }
51
+ context.xmlParts.push(`<${node.type} ${REF_ATTRIBUTE_NAME}="${refKey}"`);
52
+ const metaAttrsString = getNodeMetaAttributesString(node);
53
+ if (metaAttrsString) {
54
+ context.xmlParts.push(" " + metaAttrsString);
55
+ }
56
+ context.xmlParts.push(">");
57
+ if (isRichTextNodeType(node, "text")) {
58
+ context.xmlParts.push(node.text);
59
+ } else if (Array.isArray(node.children) && node.children.length) {
60
+ node.children.forEach((child) => {
61
+ renderXmlNode(context, child);
62
+ });
63
+ }
64
+ context.xmlParts.push(`</${node.type}>`);
65
+ }
66
+ var getPropsAsBase64 = (node, ignoreProps) => {
67
+ const props = {};
68
+ Object.keys(node).forEach((key) => {
69
+ if (!ignoreProps.includes(key)) {
70
+ props[key] = node[key];
71
+ }
72
+ });
73
+ return btoa(JSON.stringify(props));
74
+ };
75
+ var getNodeMetaAttributesString = (node) => {
76
+ const metadata = {};
77
+ if (isRichTextNodeType(node, "text")) {
78
+ const formatTags = getRichTextTagsFromTextFormat(node.format);
79
+ if (formatTags.length) {
80
+ metadata["format"] = formatTags.join(" ");
81
+ }
82
+ } else if (isRichTextNodeType(node, "heading")) {
83
+ if (node.tag) {
84
+ metadata["tag"] = node.tag;
85
+ }
86
+ } else if (isRichTextNodeType(node, "paragraph")) {
87
+ if (node.format) {
88
+ metadata["format"] = node.format;
89
+ }
90
+ } else if (isRichTextNodeType(node, "list")) {
91
+ if (node.tag) {
92
+ metadata["tag"] = node.tag;
93
+ }
94
+ } else if (isRichTextNodeType(node, "listitem")) {
95
+ metadata["value"] = String(node.value);
96
+ }
97
+ if (!Object.keys(metadata).length) {
98
+ return "";
99
+ }
100
+ const result = [];
101
+ Object.entries(metadata).forEach(([key, value]) => {
102
+ result.push(`${key}="${value}"`);
103
+ });
104
+ return result.join(" ");
105
+ };
106
+
17
107
  // src/translationHelpers.ts
18
108
  import {
19
109
  walkNodeTree
20
110
  } from "@uniformdev/canvas";
21
111
  import { isRichTextValueConsideredEmpty } from "@uniformdev/richtext";
22
112
  import { dequal } from "dequal/lite";
113
+
114
+ // src/richText/parseTranslatableXml.ts
115
+ import { isRichTextValue } from "@uniformdev/richtext";
116
+ import { XMLParser } from "fast-xml-parser";
117
+ var ATTR_NAME_PREFIX = "@_";
118
+ var ATTRIBUTES_SUBNODE_NAME = ":@";
119
+ var IGNORE_PROPS_PREFIX = [ATTR_NAME_PREFIX, ATTRIBUTES_SUBNODE_NAME, "#"];
120
+ var parseTranslatableXml = ({ xml, metadata }) => {
121
+ const parser = new XMLParser({
122
+ ignoreDeclaration: true,
123
+ ignorePiTags: true,
124
+ ignoreAttributes: false,
125
+ preserveOrder: true,
126
+ trimValues: false,
127
+ attributeNamePrefix: ATTR_NAME_PREFIX
128
+ });
129
+ const rawObj = parser.parse(xml);
130
+ const result = processParseObject(rawObj, {
131
+ metadata,
132
+ nodeTypes: []
133
+ });
134
+ return result;
135
+ };
136
+ var processParseObject = (rawObj, context) => {
137
+ const result = visitAndTransformNode(rawObj, context);
138
+ const root = Array.isArray(result) ? result.at(0) : result;
139
+ if (root && root.type === "root") {
140
+ const value = { root };
141
+ if (isRichTextValue(value)) {
142
+ return value;
143
+ }
144
+ }
145
+ return null;
146
+ };
147
+ var visitAndTransformNode = (node, context) => {
148
+ if (Array.isArray(node)) {
149
+ return node.map((x) => visitAndTransformNode(x, context)).filter((node2) => !!node2);
150
+ } else if (typeof node === "object" && node !== null) {
151
+ const type = Object.keys(node).find(
152
+ (key) => !IGNORE_PROPS_PREFIX.some((prefix) => key.startsWith(prefix))
153
+ );
154
+ if (!type) {
155
+ return null;
156
+ }
157
+ const transformed = {};
158
+ transformed["type"] = type;
159
+ const propsFromRef = restorePropsFromRef(node, context);
160
+ Object.entries(propsFromRef).forEach(([key, value]) => {
161
+ transformed[key] = value;
162
+ });
163
+ if (type === "text") {
164
+ const nestedNode = node[type];
165
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
166
+ const firstChild = nestedNodeAsArray.at(0);
167
+ const text = firstChild == null ? void 0 : firstChild["#text"];
168
+ transformed["text"] = typeof text === "string" && text ? text : "";
169
+ } else {
170
+ const children = [];
171
+ const nestedNode = node[type];
172
+ if (typeof nestedNode === "object" && nestedNode) {
173
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
174
+ nestedNodeAsArray.forEach((currNode) => {
175
+ const transformed2 = visitAndTransformNode(currNode, context);
176
+ if (transformed2) {
177
+ children.push(transformed2);
178
+ }
179
+ });
180
+ }
181
+ if (children.length) {
182
+ transformed["children"] = children;
183
+ }
184
+ }
185
+ return transformed;
186
+ } else {
187
+ return node;
188
+ }
189
+ };
190
+ var restorePropsFromRef = (node, context) => {
191
+ const result = {};
192
+ let uniformRef = node[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
193
+ if (!uniformRef) {
194
+ const attrsSubNode = node[ATTRIBUTES_SUBNODE_NAME];
195
+ uniformRef = attrsSubNode == null ? void 0 : attrsSubNode[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
196
+ }
197
+ if (typeof uniformRef === "string" && uniformRef && context.metadata[uniformRef]) {
198
+ const metadata = context.metadata[uniformRef];
199
+ if (metadata.attrs) {
200
+ const decodedProps = JSON.parse(atob(metadata.attrs));
201
+ Object.keys(decodedProps).forEach((key) => {
202
+ result[key] = decodedProps[key];
203
+ });
204
+ }
205
+ }
206
+ return result;
207
+ };
208
+
209
+ // src/richText/types.ts
210
+ var isTranslatableRichTextValue = (value) => {
211
+ if (typeof value !== "object" || !value) {
212
+ return false;
213
+ }
214
+ if (!("xml" in value) || typeof value.xml !== "string") {
215
+ return false;
216
+ }
217
+ if (!("metadata" in value) || typeof value.metadata !== "object" || !value.metadata) {
218
+ return false;
219
+ }
220
+ return true;
221
+ };
222
+
223
+ // src/translationHelpers.ts
23
224
  var MERGE_TRANSLATION_ERRORS = {
24
225
  unknown: "Unknown error",
25
226
  "invalid-args": "Invalid arguments",
@@ -103,9 +304,19 @@ var processParameterTranslation = ({
103
304
  left: originalParameter.locales[uniformTargetLocale],
104
305
  right: originalTargetValue
105
306
  });
106
- if (targetValue && isSourceValueUntouched && isTargetValueUntouched) {
107
- originalParameter.locales[uniformTargetLocale] = targetValue;
108
- return { updated: true };
307
+ if (targetValue !== void 0 && isSourceValueUntouched && isTargetValueUntouched) {
308
+ if (parameter.type == SUPPORTED_PARAM_TYPES.richText && isTranslatableRichTextValue(targetValue)) {
309
+ try {
310
+ const richTextValue = parseTranslatableXml(targetValue);
311
+ originalParameter.locales[uniformTargetLocale] = richTextValue;
312
+ return { updated: true };
313
+ } catch (e) {
314
+ return { updated: false };
315
+ }
316
+ } else if (parameter.type == SUPPORTED_PARAM_TYPES.text) {
317
+ originalParameter.locales[uniformTargetLocale] = targetValue;
318
+ return { updated: true };
319
+ }
109
320
  }
110
321
  return { updated: false };
111
322
  };
@@ -118,29 +329,18 @@ var processOverrideTranslation = ({
118
329
  var _a, _b;
119
330
  let updated = false;
120
331
  Object.entries((_a = override.parameters) != null ? _a : {}).forEach(([paramKey, parameter]) => {
121
- var _a2, _b2, _c, _d;
332
+ var _a2;
122
333
  const originalParameter = (_a2 = originalOverride.parameters) == null ? void 0 : _a2[paramKey];
123
- if (!originalParameter || !originalParameter.locales) {
124
- return;
125
- }
126
- if (originalParameter.type !== parameter.type) {
334
+ if (!originalParameter) {
127
335
  return;
128
336
  }
129
- const sourceValue = (_b2 = parameter.locales) == null ? void 0 : _b2[TRANSLATION_PAYLOAD_SOURCE_KEY];
130
- const targetValue = (_c = parameter.locales) == null ? void 0 : _c[TRANSLATION_PAYLOAD_TARGET_KEY];
131
- const originalTargetValue = (_d = parameter.locales) == null ? void 0 : _d[TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY];
132
- const isSourceValueUntouched = isSameParameterValue({
133
- parameterType: originalParameter.type,
134
- left: originalParameter.locales[uniformSourceLocale],
135
- right: sourceValue
136
- });
137
- const isTargetValueUntouched = isSameParameterValue({
138
- parameterType: originalParameter.type,
139
- left: originalParameter.locales[uniformTargetLocale],
140
- right: originalTargetValue
337
+ const result = processParameterTranslation({
338
+ uniformSourceLocale,
339
+ uniformTargetLocale,
340
+ originalParameter,
341
+ parameter
141
342
  });
142
- if (targetValue && isSourceValueUntouched && isTargetValueUntouched) {
143
- originalParameter.locales[uniformTargetLocale] = targetValue;
343
+ if (result.updated) {
144
344
  updated = true;
145
345
  }
146
346
  });
@@ -194,8 +394,12 @@ var isSameParameterValue = ({
194
394
  return left === right || !left && !right;
195
395
  break;
196
396
  case SUPPORTED_PARAM_TYPES.richText:
197
- if (isRichTextValueConsideredEmpty(left) && isRichTextValueConsideredEmpty(right)) {
198
- return true;
397
+ try {
398
+ if (isRichTextValueConsideredEmpty(left) && isRichTextValueConsideredEmpty(right)) {
399
+ return true;
400
+ }
401
+ } catch (e) {
402
+ return false;
199
403
  }
200
404
  return dequal(left, right);
201
405
  break;
@@ -302,7 +506,7 @@ var collectFromNode = ({
302
506
  type: param.type,
303
507
  locales: {
304
508
  [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
305
- [TRANSLATION_PAYLOAD_TARGET_KEY]: sourceLocaleValue,
509
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
306
510
  [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
307
511
  }
308
512
  };
@@ -346,7 +550,7 @@ var collectFromNode = ({
346
550
  type: param.type,
347
551
  locales: {
348
552
  [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
349
- [TRANSLATION_PAYLOAD_TARGET_KEY]: sourceLocaleValue,
553
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
350
554
  [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
351
555
  }
352
556
  };
@@ -405,7 +609,7 @@ var canTranslateParameterValue = (parameter, value) => {
405
609
  }
406
610
  return true;
407
611
  } else if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
408
- return isRichTextValue(value) && !isRichTextValueConsideredEmpty2(value);
612
+ return isRichTextValue2(value) && !isRichTextValueConsideredEmpty2(value);
409
613
  }
410
614
  return false;
411
615
  };
@@ -425,6 +629,16 @@ var isTargetLocaleUntouched = (parameterType, sourceLocaleValue, targetLocaleVal
425
629
  right: targetLocaleValue
426
630
  });
427
631
  };
632
+ var preprocessTargetValue = (parameter, value) => {
633
+ if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
634
+ try {
635
+ return isRichTextValue2(value) ? renderAsTranslatableXml(value.root) : value;
636
+ } catch (e) {
637
+ return value;
638
+ }
639
+ }
640
+ return value;
641
+ };
428
642
 
429
643
  // src/getCompositionForTranslation.ts
430
644
  import { CANVAS_DRAFT_STATE } from "@uniformdev/canvas";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/tms-sdk",
3
- "version": "19.154.1-alpha.27+38c3908d9d",
3
+ "version": "19.154.1-alpha.28+76ef9fb12e",
4
4
  "description": "Uniform Translation Management System SDK",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./dist/index.js",
@@ -33,11 +33,12 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@uniformdev/canvas": "19.154.1-alpha.27+38c3908d9d",
37
- "@uniformdev/mesh-sdk": "19.154.1-alpha.27+38c3908d9d",
38
- "@uniformdev/richtext": "19.154.1-alpha.27+38c3908d9d",
36
+ "@uniformdev/canvas": "19.154.1-alpha.28+76ef9fb12e",
37
+ "@uniformdev/mesh-sdk": "19.154.1-alpha.28+76ef9fb12e",
38
+ "@uniformdev/richtext": "19.154.1-alpha.28+76ef9fb12e",
39
39
  "dequal": "2.0.3",
40
+ "fast-xml-parser": "4.4.0",
40
41
  "immer": "10.0.4"
41
42
  },
42
- "gitHead": "38c3908d9d966e4b12cf7ecdc5831ff03c529917"
43
+ "gitHead": "76ef9fb12eebbfa41f1c587cb560b821a2fdb746"
43
44
  }