@kontent-ai/migration-toolkit 1.0.0

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 (240) hide show
  1. package/.npmignore +13 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +272 -0
  4. package/dist/es2022/core/helpers/workflow-helper.d.ts +37 -0
  5. package/dist/es2022/core/helpers/workflow-helper.js +67 -0
  6. package/dist/es2022/core/helpers/workflow-helper.js.map +1 -0
  7. package/dist/es2022/core/index.d.ts +15 -0
  8. package/dist/es2022/core/index.js +16 -0
  9. package/dist/es2022/core/index.js.map +1 -0
  10. package/dist/es2022/core/logs/loggers.d.ts +2 -0
  11. package/dist/es2022/core/logs/loggers.js +69 -0
  12. package/dist/es2022/core/logs/loggers.js.map +1 -0
  13. package/dist/es2022/core/models/core.models.d.ts +91 -0
  14. package/dist/es2022/core/models/core.models.js +2 -0
  15. package/dist/es2022/core/models/core.models.js.map +1 -0
  16. package/dist/es2022/core/models/log.models.d.ts +15 -0
  17. package/dist/es2022/core/models/log.models.js +2 -0
  18. package/dist/es2022/core/models/log.models.js.map +1 -0
  19. package/dist/es2022/core/models/migration.models.d.ts +136 -0
  20. package/dist/es2022/core/models/migration.models.js +2 -0
  21. package/dist/es2022/core/models/migration.models.js.map +1 -0
  22. package/dist/es2022/core/utils/array.utils.d.ts +5 -0
  23. package/dist/es2022/core/utils/array.utils.js +27 -0
  24. package/dist/es2022/core/utils/array.utils.js.map +1 -0
  25. package/dist/es2022/core/utils/binary-data.utils.d.ts +5 -0
  26. package/dist/es2022/core/utils/binary-data.utils.js +21 -0
  27. package/dist/es2022/core/utils/binary-data.utils.js.map +1 -0
  28. package/dist/es2022/core/utils/confirm.utils.d.ts +31 -0
  29. package/dist/es2022/core/utils/confirm.utils.js +73 -0
  30. package/dist/es2022/core/utils/confirm.utils.js.map +1 -0
  31. package/dist/es2022/core/utils/error.utils.d.ts +4 -0
  32. package/dist/es2022/core/utils/error.utils.js +50 -0
  33. package/dist/es2022/core/utils/error.utils.js.map +1 -0
  34. package/dist/es2022/core/utils/external-id.utils.d.ts +5 -0
  35. package/dist/es2022/core/utils/external-id.utils.js +5 -0
  36. package/dist/es2022/core/utils/external-id.utils.js.map +1 -0
  37. package/dist/es2022/core/utils/global.utils.d.ts +14 -0
  38. package/dist/es2022/core/utils/global.utils.js +45 -0
  39. package/dist/es2022/core/utils/global.utils.js.map +1 -0
  40. package/dist/es2022/core/utils/http.utils.d.ts +3 -0
  41. package/dist/es2022/core/utils/http.utils.js +29 -0
  42. package/dist/es2022/core/utils/http.utils.js.map +1 -0
  43. package/dist/es2022/core/utils/management-client-utils.d.ts +19 -0
  44. package/dist/es2022/core/utils/management-client-utils.js +129 -0
  45. package/dist/es2022/core/utils/management-client-utils.js.map +1 -0
  46. package/dist/es2022/core/utils/processing-utils.d.ts +12 -0
  47. package/dist/es2022/core/utils/processing-utils.js +39 -0
  48. package/dist/es2022/core/utils/processing-utils.js.map +1 -0
  49. package/dist/es2022/core/utils/run.utils.d.ts +10 -0
  50. package/dist/es2022/core/utils/run.utils.js +37 -0
  51. package/dist/es2022/core/utils/run.utils.js.map +1 -0
  52. package/dist/es2022/export/context/export-context-fetcher.d.ts +4 -0
  53. package/dist/es2022/export/context/export-context-fetcher.js +289 -0
  54. package/dist/es2022/export/context/export-context-fetcher.js.map +1 -0
  55. package/dist/es2022/export/export-manager.d.ts +5 -0
  56. package/dist/es2022/export/export-manager.js +167 -0
  57. package/dist/es2022/export/export-manager.js.map +1 -0
  58. package/dist/es2022/export/export.models.d.ts +55 -0
  59. package/dist/es2022/export/export.models.js +2 -0
  60. package/dist/es2022/export/export.models.js.map +1 -0
  61. package/dist/es2022/export/index.d.ts +2 -0
  62. package/dist/es2022/export/index.js +3 -0
  63. package/dist/es2022/export/index.js.map +1 -0
  64. package/dist/es2022/export/utils/export.utils.d.ts +2 -0
  65. package/dist/es2022/export/utils/export.utils.js +5 -0
  66. package/dist/es2022/export/utils/export.utils.js.map +1 -0
  67. package/dist/es2022/file/file-manager.d.ts +5 -0
  68. package/dist/es2022/file/file-manager.js +29 -0
  69. package/dist/es2022/file/file-manager.js.map +1 -0
  70. package/dist/es2022/file/index.d.ts +1 -0
  71. package/dist/es2022/file/index.js +2 -0
  72. package/dist/es2022/file/index.js.map +1 -0
  73. package/dist/es2022/import/comparers/asset-comparer.d.ts +12 -0
  74. package/dist/es2022/import/comparers/asset-comparer.js +65 -0
  75. package/dist/es2022/import/comparers/asset-comparer.js.map +1 -0
  76. package/dist/es2022/import/context/import-context-fetcher.d.ts +4 -0
  77. package/dist/es2022/import/context/import-context-fetcher.js +235 -0
  78. package/dist/es2022/import/context/import-context-fetcher.js.map +1 -0
  79. package/dist/es2022/import/import-manager.d.ts +4 -0
  80. package/dist/es2022/import/import-manager.js +80 -0
  81. package/dist/es2022/import/import-manager.js.map +1 -0
  82. package/dist/es2022/import/import.models.d.ts +45 -0
  83. package/dist/es2022/import/import.models.js +2 -0
  84. package/dist/es2022/import/import.models.js.map +1 -0
  85. package/dist/es2022/import/importers/assets-importer.d.ts +10 -0
  86. package/dist/es2022/import/importers/assets-importer.js +175 -0
  87. package/dist/es2022/import/importers/assets-importer.js.map +1 -0
  88. package/dist/es2022/import/importers/content-items-importer.d.ts +10 -0
  89. package/dist/es2022/import/importers/content-items-importer.js +97 -0
  90. package/dist/es2022/import/importers/content-items-importer.js.map +1 -0
  91. package/dist/es2022/import/importers/language-variant-importer.d.ts +11 -0
  92. package/dist/es2022/import/importers/language-variant-importer.js +215 -0
  93. package/dist/es2022/import/importers/language-variant-importer.js.map +1 -0
  94. package/dist/es2022/import/importers/workflow-importer.d.ts +18 -0
  95. package/dist/es2022/import/importers/workflow-importer.js +122 -0
  96. package/dist/es2022/import/importers/workflow-importer.js.map +1 -0
  97. package/dist/es2022/import/index.d.ts +2 -0
  98. package/dist/es2022/import/index.js +3 -0
  99. package/dist/es2022/import/index.js.map +1 -0
  100. package/dist/es2022/import/utils/import.utils.d.ts +2 -0
  101. package/dist/es2022/import/utils/import.utils.js +5 -0
  102. package/dist/es2022/import/utils/import.utils.js.map +1 -0
  103. package/dist/es2022/index.d.ts +8 -0
  104. package/dist/es2022/index.js +10 -0
  105. package/dist/es2022/index.js.map +1 -0
  106. package/dist/es2022/metadata.d.ts +5 -0
  107. package/dist/es2022/metadata.js +6 -0
  108. package/dist/es2022/metadata.js.map +1 -0
  109. package/dist/es2022/node/cli/actions/export-action.d.ts +2 -0
  110. package/dist/es2022/node/cli/actions/export-action.js +40 -0
  111. package/dist/es2022/node/cli/actions/export-action.js.map +1 -0
  112. package/dist/es2022/node/cli/actions/import-action.d.ts +2 -0
  113. package/dist/es2022/node/cli/actions/import-action.js +29 -0
  114. package/dist/es2022/node/cli/actions/import-action.js.map +1 -0
  115. package/dist/es2022/node/cli/actions/migrate-action.d.ts +2 -0
  116. package/dist/es2022/node/cli/actions/migrate-action.js +47 -0
  117. package/dist/es2022/node/cli/actions/migrate-action.js.map +1 -0
  118. package/dist/es2022/node/cli/app.d.ts +2 -0
  119. package/dist/es2022/node/cli/app.js +27 -0
  120. package/dist/es2022/node/cli/app.js.map +1 -0
  121. package/dist/es2022/node/cli/args/args-fetcher.d.ts +2 -0
  122. package/dist/es2022/node/cli/args/args-fetcher.js +46 -0
  123. package/dist/es2022/node/cli/args/args-fetcher.js.map +1 -0
  124. package/dist/es2022/node/cli/args/args-setter.d.ts +2 -0
  125. package/dist/es2022/node/cli/args/args-setter.js +31 -0
  126. package/dist/es2022/node/cli/args/args-setter.js.map +1 -0
  127. package/dist/es2022/node/cli/cli.models.d.ts +24 -0
  128. package/dist/es2022/node/cli/cli.models.js +2 -0
  129. package/dist/es2022/node/cli/cli.models.js.map +1 -0
  130. package/dist/es2022/node/cli/commands.d.ts +1 -0
  131. package/dist/es2022/node/cli/commands.js +157 -0
  132. package/dist/es2022/node/cli/commands.js.map +1 -0
  133. package/dist/es2022/toolkit/elements-builder.d.ts +14 -0
  134. package/dist/es2022/toolkit/elements-builder.js +69 -0
  135. package/dist/es2022/toolkit/elements-builder.js.map +1 -0
  136. package/dist/es2022/toolkit/export.d.ts +3 -0
  137. package/dist/es2022/toolkit/export.js +21 -0
  138. package/dist/es2022/toolkit/export.js.map +1 -0
  139. package/dist/es2022/toolkit/file.d.ts +12 -0
  140. package/dist/es2022/toolkit/file.js +50 -0
  141. package/dist/es2022/toolkit/file.js.map +1 -0
  142. package/dist/es2022/toolkit/import.d.ts +2 -0
  143. package/dist/es2022/toolkit/import.js +21 -0
  144. package/dist/es2022/toolkit/import.js.map +1 -0
  145. package/dist/es2022/toolkit/index.d.ts +5 -0
  146. package/dist/es2022/toolkit/index.js +6 -0
  147. package/dist/es2022/toolkit/index.js.map +1 -0
  148. package/dist/es2022/toolkit/migrate.d.ts +21 -0
  149. package/dist/es2022/toolkit/migrate.js +39 -0
  150. package/dist/es2022/toolkit/migrate.js.map +1 -0
  151. package/dist/es2022/translation/extraction/items-extraction.processor.d.ts +24 -0
  152. package/dist/es2022/translation/extraction/items-extraction.processor.js +108 -0
  153. package/dist/es2022/translation/extraction/items-extraction.processor.js.map +1 -0
  154. package/dist/es2022/translation/helpers/rich-text.processor.d.ts +22 -0
  155. package/dist/es2022/translation/helpers/rich-text.processor.js +209 -0
  156. package/dist/es2022/translation/helpers/rich-text.processor.js.map +1 -0
  157. package/dist/es2022/translation/index.d.ts +4 -0
  158. package/dist/es2022/translation/index.js +5 -0
  159. package/dist/es2022/translation/index.js.map +1 -0
  160. package/dist/es2022/translation/transforms/export-transforms.d.ts +3 -0
  161. package/dist/es2022/translation/transforms/export-transforms.js +196 -0
  162. package/dist/es2022/translation/transforms/export-transforms.js.map +1 -0
  163. package/dist/es2022/translation/transforms/import-transforms.d.ts +7 -0
  164. package/dist/es2022/translation/transforms/import-transforms.js +183 -0
  165. package/dist/es2022/translation/transforms/import-transforms.js.map +1 -0
  166. package/dist/es2022/zip/index.d.ts +4 -0
  167. package/dist/es2022/zip/index.js +5 -0
  168. package/dist/es2022/zip/index.js.map +1 -0
  169. package/dist/es2022/zip/zip-manager.d.ts +6 -0
  170. package/dist/es2022/zip/zip-manager.js +27 -0
  171. package/dist/es2022/zip/zip-manager.js.map +1 -0
  172. package/dist/es2022/zip/zip-packager.d.ts +3 -0
  173. package/dist/es2022/zip/zip-packager.js +69 -0
  174. package/dist/es2022/zip/zip-packager.js.map +1 -0
  175. package/dist/es2022/zip/zip-transformer.d.ts +6 -0
  176. package/dist/es2022/zip/zip-transformer.js +82 -0
  177. package/dist/es2022/zip/zip-transformer.js.map +1 -0
  178. package/dist/es2022/zip/zip.models.d.ts +13 -0
  179. package/dist/es2022/zip/zip.models.js +2 -0
  180. package/dist/es2022/zip/zip.models.js.map +1 -0
  181. package/lib/core/helpers/workflow-helper.ts +104 -0
  182. package/lib/core/index.ts +17 -0
  183. package/lib/core/logs/loggers.ts +80 -0
  184. package/lib/core/models/core.models.ts +134 -0
  185. package/lib/core/models/log.models.ts +31 -0
  186. package/lib/core/models/migration.models.ts +165 -0
  187. package/lib/core/utils/array.utils.ts +49 -0
  188. package/lib/core/utils/binary-data.utils.ts +29 -0
  189. package/lib/core/utils/confirm.utils.ts +139 -0
  190. package/lib/core/utils/error.utils.ts +65 -0
  191. package/lib/core/utils/external-id.utils.ts +9 -0
  192. package/lib/core/utils/global.utils.ts +59 -0
  193. package/lib/core/utils/http.utils.ts +35 -0
  194. package/lib/core/utils/management-client-utils.ts +182 -0
  195. package/lib/core/utils/processing-utils.ts +71 -0
  196. package/lib/core/utils/run.utils.ts +51 -0
  197. package/lib/export/context/export-context-fetcher.ts +475 -0
  198. package/lib/export/export-manager.ts +249 -0
  199. package/lib/export/export.models.ts +87 -0
  200. package/lib/export/index.ts +2 -0
  201. package/lib/export/utils/export.utils.ts +10 -0
  202. package/lib/file/file-manager.ts +37 -0
  203. package/lib/file/index.ts +1 -0
  204. package/lib/import/comparers/asset-comparer.ts +113 -0
  205. package/lib/import/context/import-context-fetcher.ts +367 -0
  206. package/lib/import/import-manager.ts +103 -0
  207. package/lib/import/import.models.ts +84 -0
  208. package/lib/import/importers/assets-importer.ts +239 -0
  209. package/lib/import/importers/content-items-importer.ts +142 -0
  210. package/lib/import/importers/language-variant-importer.ts +342 -0
  211. package/lib/import/importers/workflow-importer.ts +159 -0
  212. package/lib/import/index.ts +2 -0
  213. package/lib/import/utils/import.utils.ts +10 -0
  214. package/lib/index.ts +9 -0
  215. package/lib/metadata.ts +6 -0
  216. package/lib/node/cli/actions/export-action.ts +45 -0
  217. package/lib/node/cli/actions/import-action.ts +34 -0
  218. package/lib/node/cli/actions/migrate-action.ts +52 -0
  219. package/lib/node/cli/app.ts +29 -0
  220. package/lib/node/cli/args/args-fetcher.ts +61 -0
  221. package/lib/node/cli/args/args-setter.ts +35 -0
  222. package/lib/node/cli/cli.models.ts +28 -0
  223. package/lib/node/cli/commands.ts +161 -0
  224. package/lib/toolkit/elements-builder.ts +84 -0
  225. package/lib/toolkit/export.ts +21 -0
  226. package/lib/toolkit/file.ts +70 -0
  227. package/lib/toolkit/import.ts +21 -0
  228. package/lib/toolkit/index.ts +5 -0
  229. package/lib/toolkit/migrate.ts +71 -0
  230. package/lib/translation/extraction/items-extraction.processor.ts +181 -0
  231. package/lib/translation/helpers/rich-text.processor.ts +300 -0
  232. package/lib/translation/index.ts +4 -0
  233. package/lib/translation/transforms/export-transforms.ts +253 -0
  234. package/lib/translation/transforms/import-transforms.ts +215 -0
  235. package/lib/zip/index.ts +4 -0
  236. package/lib/zip/zip-manager.ts +33 -0
  237. package/lib/zip/zip-packager.ts +86 -0
  238. package/lib/zip/zip-transformer.ts +105 -0
  239. package/lib/zip/zip.models.ts +12 -0
  240. package/package.json +88 -0
@@ -0,0 +1,181 @@
1
+ import { richTextProcessor } from '../index.js';
2
+ import {
3
+ MigrationElementModels,
4
+ MigrationElements,
5
+ ReferencedDataInLanguageVariants,
6
+ ReferencedDataInMigrationItems,
7
+ parseAsMigrationReferencesArray
8
+ } from '../../core/index.js';
9
+ import { GetFlattenedElementByCodenames } from '../../import/index.js';
10
+ import { ElementModels } from '@kontent-ai/management-sdk';
11
+ import { GetFlattenedElementByIds } from 'lib/export/export.models.js';
12
+
13
+ export interface ExtractItemById {
14
+ readonly elements: Readonly<ElementModels.ContentItemElement>[];
15
+ readonly contentTypeId: string;
16
+ }
17
+
18
+ export interface ExtractItemByCodename {
19
+ readonly elements: MigrationElements;
20
+ readonly contentTypeCodename: string;
21
+ }
22
+
23
+ export interface ReferencedDataInMigrationItemsLocal {
24
+ readonly itemCodenames: Set<string>;
25
+ readonly assetCodenames: Set<string>;
26
+ }
27
+
28
+ export interface ReferencedDataInLanguageVariantsLocal {
29
+ readonly itemIds: Set<string>;
30
+ readonly assetIds: Set<string>;
31
+ }
32
+
33
+ export function itemsExtractionProcessor() {
34
+ const extractReferencedDataFromExtractItems = (
35
+ items: readonly ExtractItemById[],
36
+ getElement: GetFlattenedElementByIds
37
+ ): ReferencedDataInLanguageVariants => {
38
+ const extractedIds = items.reduce<ReferencedDataInLanguageVariantsLocal>(
39
+ (extractedIds, item) => {
40
+ return item.elements.reduce<ReferencedDataInLanguageVariantsLocal>((childExtractedIds, itemElement) => {
41
+ const typeElement = getElement(item.contentTypeId, itemElement.element.id ?? '');
42
+
43
+ if (typeElement.type === 'rich_text') {
44
+ const rteValue = itemElement.value?.toString();
45
+
46
+ // extract referenced items
47
+ richTextProcessor()
48
+ .processDataIds(rteValue ?? '')
49
+ .ids.forEach((id) => extractedIds.itemIds.add(id));
50
+
51
+ richTextProcessor()
52
+ .processLinkItemIds(rteValue ?? '')
53
+ .ids.forEach((id) => extractedIds.itemIds.add(id));
54
+
55
+ // extract referenced assets
56
+ richTextProcessor()
57
+ .processAssetIds(rteValue ?? '')
58
+ .ids.forEach((id) => extractedIds.assetIds.add(id));
59
+
60
+ // recursively extract data from components as well because they may reference additional assets & content items
61
+ const extractedComponents = extractReferencedDataFromExtractItems(
62
+ itemElement.components.map((component) => {
63
+ return {
64
+ contentTypeId: component.type.id ?? '',
65
+ elements: component.elements
66
+ };
67
+ }),
68
+ getElement
69
+ );
70
+
71
+ extractedComponents.itemIds.forEach((id) => extractedIds.itemIds.add(id));
72
+ extractedComponents.assetIds.forEach((id) => extractedIds.assetIds.add(id));
73
+ } else if (typeElement.type === 'modular_content' || typeElement.type === 'subpages') {
74
+ if (itemElement.value && Array.isArray(itemElement.value)) {
75
+ itemElement.value.forEach((value) => (value.id ? extractedIds.itemIds.add(value.id) : {}));
76
+ }
77
+ } else if (typeElement.type === 'asset') {
78
+ if (itemElement.value && Array.isArray(itemElement.value)) {
79
+ itemElement.value.forEach((value) => (value.id ? extractedIds.assetIds.add(value.id) : {}));
80
+ }
81
+ }
82
+
83
+ return childExtractedIds;
84
+ }, extractedIds);
85
+ },
86
+ { itemIds: new Set(), assetIds: new Set() }
87
+ );
88
+
89
+ return <ReferencedDataInLanguageVariants>{
90
+ itemIds: extractedIds.itemIds,
91
+ assetIds: extractedIds.assetIds
92
+ };
93
+ };
94
+
95
+ const extractReferencedItemsFromMigrationItems = (
96
+ items: readonly ExtractItemByCodename[],
97
+ getElement: GetFlattenedElementByCodenames
98
+ ): ReferencedDataInMigrationItems => {
99
+ const extractedCodenames = items.reduce<ReferencedDataInMigrationItemsLocal>(
100
+ (extractedCodenames, item) => {
101
+ return Object.entries(item.elements).reduce<ReferencedDataInMigrationItemsLocal>(
102
+ (childExtractedCodenames, [elementCodename, element]) => {
103
+ const flattenedElement = getElement(item.contentTypeCodename, elementCodename, element.type);
104
+
105
+ if (flattenedElement.type === 'rich_text') {
106
+ const richTextElementValue = element as MigrationElementModels.RichTextElement;
107
+
108
+ if (!richTextElementValue.value) {
109
+ return childExtractedCodenames;
110
+ }
111
+
112
+ const richTextHtml = richTextElementValue.value?.value ?? '';
113
+
114
+ // items
115
+ richTextProcessor()
116
+ .processItemCodenames(richTextHtml)
117
+ .codenames.forEach((codename) => childExtractedCodenames.itemCodenames.add(codename));
118
+
119
+ richTextProcessor()
120
+ .processLinkItemCodenames(richTextHtml)
121
+ .codenames.forEach((codename) => childExtractedCodenames.itemCodenames.add(codename));
122
+
123
+ // assets
124
+ richTextProcessor()
125
+ .processAssetCodenames(richTextHtml)
126
+ .codenames.forEach((codename) => childExtractedCodenames.assetCodenames.add(codename));
127
+
128
+ // recursively extract data from components as well because they may reference additional assets & content items
129
+ const extractedComponents = extractReferencedItemsFromMigrationItems(
130
+ richTextElementValue.value.components.map((component) => {
131
+ const extractionItem: ExtractItemByCodename = {
132
+ contentTypeCodename: component.system.type.codename,
133
+ elements: component.elements
134
+ };
135
+
136
+ return extractionItem;
137
+ }),
138
+ getElement
139
+ );
140
+
141
+ extractedComponents.itemCodenames.forEach((codename) =>
142
+ childExtractedCodenames.itemCodenames.add(codename)
143
+ );
144
+ extractedComponents.assetCodenames.forEach((codename) =>
145
+ childExtractedCodenames.assetCodenames.add(codename)
146
+ );
147
+ } else if (
148
+ flattenedElement.type === 'modular_content' ||
149
+ flattenedElement.type === 'subpages'
150
+ ) {
151
+ parseAsMigrationReferencesArray(element.value)
152
+ .map((m) => m.codename)
153
+ .forEach((codename) => childExtractedCodenames.itemCodenames.add(codename));
154
+ } else if (flattenedElement.type === 'asset') {
155
+ parseAsMigrationReferencesArray(element.value)
156
+ .map((m) => m.codename)
157
+ .forEach((codename) => childExtractedCodenames.assetCodenames.add(codename));
158
+ }
159
+
160
+ return childExtractedCodenames;
161
+ },
162
+ extractedCodenames
163
+ );
164
+ },
165
+ {
166
+ itemCodenames: new Set(),
167
+ assetCodenames: new Set()
168
+ }
169
+ );
170
+
171
+ return <ReferencedDataInMigrationItems>{
172
+ itemCodenames: extractedCodenames.itemCodenames,
173
+ assetCodenames: extractedCodenames.assetCodenames
174
+ };
175
+ };
176
+
177
+ return {
178
+ extractReferencedDataFromExtractItems,
179
+ extractReferencedItemsFromMigrationItems
180
+ };
181
+ }
@@ -0,0 +1,300 @@
1
+ import { AssetStateInTargetEnvironmentByCodename, ItemStateInTargetEnvironmentByCodename } from 'lib/core/index.js';
2
+
3
+ type CodenameReplaceFunc<T> = (codename: string) => T;
4
+ type IdReplaceFunc = (id: string) => { codename: string };
5
+
6
+ interface ProcessCodenamesResult {
7
+ readonly codenames: ReadonlySet<string>;
8
+ readonly html: string;
9
+ }
10
+
11
+ interface ProcessIdsResult {
12
+ readonly ids: ReadonlySet<string>;
13
+ readonly html: string;
14
+ }
15
+
16
+ const attributes = {
17
+ codenames: {
18
+ itemCodenameAttribute: 'data-codename',
19
+ linkItemCodenameAttribute: 'data-item-codename',
20
+ assetCodenameAttribute: 'data-asset-codename'
21
+ },
22
+ ids: {
23
+ assetIdAttributeName: 'data-asset-id',
24
+ itemIdAttributeName: 'data-item-id',
25
+ itemExternalIdAttributeName: 'data-item-external-id',
26
+ idAttributeName: 'data-id',
27
+ externalIdAttributeName: 'data-external-id',
28
+ externalAssetIdAttributeName: 'data-asset-external-id'
29
+ },
30
+ componentIdentifierAttribute: 'data-type="component"'
31
+ } as const;
32
+
33
+ const rteRegexes = {
34
+ elements: {
35
+ objectTagRegex: new RegExp(`<object(.+?)</object>`, 'g'),
36
+ imgTagRegex: new RegExp(`<img(.+?)</img>`, 'g'),
37
+ figureTagRegex: new RegExp(`<figure(.+?)</figure>`, 'g'),
38
+ linkTagRegex: new RegExp(`<a(.+?)</a>`, 'g')
39
+ },
40
+ ids: {
41
+ dataItemIdAttrRegex: new RegExp(`${attributes.ids.itemIdAttributeName}=\\"(.+?)\\"`),
42
+ dataAssetIdAttrRegex: new RegExp(`${attributes.ids.assetIdAttributeName}=\\"(.+?)\\"`),
43
+ dataIdAttrRegex: new RegExp(`${attributes.ids.idAttributeName}=\\"(.+?)\\"`)
44
+ },
45
+ codenames: {
46
+ rteItemCodenameRegex: new RegExp(`${attributes.codenames.itemCodenameAttribute}=\\"(.+?)\\"`),
47
+ rteLinkItemCodenameRegex: new RegExp(`${attributes.codenames.linkItemCodenameAttribute}=\\"(.+?)\\"`),
48
+ rteAssetCodenameRegex: new RegExp(`${attributes.codenames.assetCodenameAttribute}=\\"(.+?)\\"`)
49
+ }
50
+ } as const;
51
+
52
+ export function richTextProcessor() {
53
+ const processDataIds = (richTextHtml: string, replaceFunc?: IdReplaceFunc): ProcessIdsResult => {
54
+ const itemIds = new Set<string>();
55
+
56
+ if (!richTextHtml) {
57
+ return {
58
+ html: richTextHtml,
59
+ ids: itemIds
60
+ };
61
+ }
62
+
63
+ richTextHtml = richTextHtml.replaceAll(rteRegexes.elements.objectTagRegex, (objectTag) => {
64
+ // skip processing for components
65
+ if (objectTag.includes(attributes.componentIdentifierAttribute)) {
66
+ return objectTag;
67
+ }
68
+ const itemIdMatch = objectTag.match(rteRegexes.ids.dataIdAttrRegex);
69
+ if (itemIdMatch && (itemIdMatch?.length ?? 0) >= 2) {
70
+ const itemId = itemIdMatch[1];
71
+
72
+ itemIds.add(itemId);
73
+
74
+ if (replaceFunc) {
75
+ const { codename } = replaceFunc(itemId);
76
+
77
+ return objectTag.replaceAll(
78
+ `${attributes.ids.idAttributeName}="${itemId}"`,
79
+ `${attributes.codenames.itemCodenameAttribute}="${codename}"`
80
+ );
81
+ }
82
+ }
83
+
84
+ return objectTag;
85
+ });
86
+
87
+ return {
88
+ html: richTextHtml,
89
+ ids: itemIds
90
+ };
91
+ };
92
+
93
+ const processAssetIds = (richTextHtml: string, replaceFunc?: IdReplaceFunc): ProcessIdsResult => {
94
+ const assetIds = new Set<string>();
95
+
96
+ if (!richTextHtml) {
97
+ return {
98
+ html: richTextHtml,
99
+ ids: assetIds
100
+ };
101
+ }
102
+
103
+ richTextHtml = richTextHtml.replaceAll(rteRegexes.elements.figureTagRegex, (figureTag) => {
104
+ const assetIdMatch = figureTag.match(rteRegexes.ids.dataAssetIdAttrRegex);
105
+ if (assetIdMatch && (assetIdMatch?.length ?? 0) >= 2) {
106
+ const assetId = assetIdMatch[1];
107
+
108
+ assetIds.add(assetId);
109
+
110
+ if (replaceFunc) {
111
+ const { codename } = replaceFunc(assetId);
112
+
113
+ return figureTag.replaceAll(
114
+ `${attributes.ids.assetIdAttributeName}="${assetId}"`,
115
+ `${attributes.codenames.assetCodenameAttribute}="${codename}"`
116
+ );
117
+ }
118
+ }
119
+
120
+ return figureTag;
121
+ });
122
+
123
+ return {
124
+ html: richTextHtml,
125
+ ids: assetIds
126
+ };
127
+ };
128
+
129
+ const processLinkItemIds = (richTextHtml: string, replaceFunc?: IdReplaceFunc): ProcessIdsResult => {
130
+ const linkItemIds = new Set<string>();
131
+
132
+ if (!richTextHtml) {
133
+ return {
134
+ html: richTextHtml,
135
+ ids: linkItemIds
136
+ };
137
+ }
138
+
139
+ richTextHtml = richTextHtml.replaceAll(rteRegexes.elements.linkTagRegex, (linkTag) => {
140
+ const itemIdMatch = linkTag.match(rteRegexes.ids.dataItemIdAttrRegex);
141
+ if (itemIdMatch && (itemIdMatch?.length ?? 0) >= 2) {
142
+ const itemId = itemIdMatch[1];
143
+ linkItemIds.add(itemId);
144
+
145
+ if (replaceFunc) {
146
+ const { codename } = replaceFunc(itemId);
147
+
148
+ return linkTag.replaceAll(
149
+ `${attributes.ids.itemIdAttributeName}="${itemId}"`,
150
+ `${attributes.codenames.linkItemCodenameAttribute}="${codename}"`
151
+ );
152
+ }
153
+ }
154
+
155
+ return linkTag;
156
+ });
157
+
158
+ return {
159
+ html: richTextHtml,
160
+ ids: linkItemIds
161
+ };
162
+ };
163
+
164
+ const processItemCodenames = (
165
+ richTextHtml: string,
166
+ replaceFunc?: CodenameReplaceFunc<ItemStateInTargetEnvironmentByCodename>
167
+ ): ProcessCodenamesResult => {
168
+ const itemCodenames = new Set<string>();
169
+
170
+ if (!richTextHtml) {
171
+ return {
172
+ codenames: itemCodenames,
173
+ html: richTextHtml
174
+ };
175
+ }
176
+
177
+ richTextHtml = richTextHtml.replaceAll(rteRegexes.elements.objectTagRegex, (objectTag) => {
178
+ const codenameMatch = objectTag.match(rteRegexes.codenames.rteItemCodenameRegex);
179
+ if (codenameMatch && (codenameMatch?.length ?? 0) >= 2) {
180
+ const codename = codenameMatch[1];
181
+
182
+ itemCodenames.add(codename);
183
+
184
+ if (replaceFunc) {
185
+ const itemState = replaceFunc(codename);
186
+
187
+ if (itemState.item && itemState.state === 'exists') {
188
+ // no need to replace codename attribute
189
+ return objectTag;
190
+ }
191
+
192
+ return objectTag.replaceAll(
193
+ `${attributes.codenames.itemCodenameAttribute}="${codename}"`,
194
+ `${attributes.ids.externalIdAttributeName}="${itemState.externalIdToUse}"`
195
+ );
196
+ }
197
+ }
198
+
199
+ return objectTag;
200
+ });
201
+
202
+ return {
203
+ codenames: itemCodenames,
204
+ html: richTextHtml
205
+ };
206
+ };
207
+
208
+ const processLinkItemCodenames = (
209
+ richTextHtml: string,
210
+ replaceFunc?: CodenameReplaceFunc<ItemStateInTargetEnvironmentByCodename>
211
+ ): ProcessCodenamesResult => {
212
+ const itemCodenames = new Set<string>();
213
+
214
+ if (!richTextHtml) {
215
+ return {
216
+ codenames: itemCodenames,
217
+ html: richTextHtml
218
+ };
219
+ }
220
+
221
+ richTextHtml = richTextHtml.replaceAll(rteRegexes.elements.linkTagRegex, (linkTag) => {
222
+ const codenameMatch = linkTag.match(rteRegexes.codenames.rteLinkItemCodenameRegex);
223
+ if (codenameMatch && (codenameMatch?.length ?? 0) >= 2) {
224
+ const codename = codenameMatch[1];
225
+
226
+ itemCodenames.add(codename);
227
+
228
+ if (replaceFunc) {
229
+ const itemState = replaceFunc(codename);
230
+
231
+ if (itemState.item && itemState.state === 'exists') {
232
+ return linkTag;
233
+ }
234
+ return linkTag.replaceAll(
235
+ `${attributes.codenames.linkItemCodenameAttribute}="${codename}"`,
236
+ `${attributes.ids.itemExternalIdAttributeName}="${itemState.externalIdToUse}"`
237
+ );
238
+ }
239
+ }
240
+
241
+ return linkTag;
242
+ });
243
+
244
+ return {
245
+ codenames: itemCodenames,
246
+ html: richTextHtml
247
+ };
248
+ };
249
+
250
+ const processAssetCodenames = (
251
+ richTextHtml: string,
252
+ replaceFunc?: CodenameReplaceFunc<AssetStateInTargetEnvironmentByCodename>
253
+ ): ProcessCodenamesResult => {
254
+ const assetCodenames = new Set<string>();
255
+
256
+ if (!richTextHtml) {
257
+ return {
258
+ codenames: assetCodenames,
259
+ html: richTextHtml
260
+ };
261
+ }
262
+
263
+ richTextHtml = richTextHtml.replaceAll(rteRegexes.elements.figureTagRegex, (figureTag) => {
264
+ const codenameMatch = figureTag.match(rteRegexes.codenames.rteAssetCodenameRegex);
265
+ if (codenameMatch && (codenameMatch?.length ?? 0) >= 2) {
266
+ const codename = codenameMatch[1];
267
+
268
+ assetCodenames.add(codename);
269
+
270
+ if (replaceFunc) {
271
+ const assetState = replaceFunc(codename);
272
+
273
+ if (assetState.asset && assetState.state === 'exists') {
274
+ return figureTag;
275
+ }
276
+ return figureTag.replaceAll(
277
+ `${attributes.codenames.assetCodenameAttribute}="${codename}"`,
278
+ `${attributes.ids.externalAssetIdAttributeName}="${assetState.externalIdToUse}"`
279
+ );
280
+ }
281
+ }
282
+
283
+ return figureTag;
284
+ });
285
+
286
+ return {
287
+ codenames: assetCodenames,
288
+ html: richTextHtml
289
+ };
290
+ };
291
+
292
+ return {
293
+ processAssetIds,
294
+ processDataIds,
295
+ processLinkItemIds,
296
+ processAssetCodenames,
297
+ processItemCodenames,
298
+ processLinkItemCodenames
299
+ };
300
+ }
@@ -0,0 +1,4 @@
1
+ export * from './helpers/rich-text.processor.js';
2
+ export * from './extraction/items-extraction.processor.js';
3
+ export * from './transforms/export-transforms.js';
4
+ export * from './transforms/import-transforms.js';