gt-sanity 0.0.5 → 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 (108) hide show
  1. package/LICENSE.md +1 -8
  2. package/README.md +5 -5
  3. package/dist/index.d.mts +122 -95
  4. package/dist/index.d.ts +122 -95
  5. package/dist/index.js +9089 -1119
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +9099 -1100
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +11 -4
  10. package/src/adapter/core.ts +111 -9
  11. package/src/adapter/createTask.ts +1 -1
  12. package/src/adapter/getLocales.ts +2 -2
  13. package/src/adapter/types.ts +9 -0
  14. package/src/components/TranslationsProvider.tsx +942 -0
  15. package/src/components/page/BatchProgress.tsx +27 -0
  16. package/src/components/page/ImportAllDialog.tsx +51 -0
  17. package/src/components/page/ImportMissingDialog.tsx +55 -0
  18. package/src/components/page/TranslateAllDialog.tsx +55 -0
  19. package/src/components/page/TranslationsTable.tsx +81 -0
  20. package/src/components/page/TranslationsTool.tsx +338 -0
  21. package/src/components/shared/BaseTranslationWrapper.tsx +82 -0
  22. package/src/components/{LanguageStatus.tsx → shared/LanguageStatus.tsx} +2 -0
  23. package/src/components/shared/LocaleCheckbox.tsx +47 -0
  24. package/src/components/{ProgressBar.tsx → shared/ProgressBar.tsx} +2 -0
  25. package/src/components/shared/SingleDocumentView.tsx +108 -0
  26. package/src/components/tab/TranslationView.tsx +379 -0
  27. package/src/components/tab/TranslationsTab.tsx +25 -0
  28. package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +21 -11
  29. package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +57 -23
  30. package/src/configuration/baseDocumentLevelConfig/helpers/createTranslationMetadata.ts +2 -0
  31. package/src/configuration/baseDocumentLevelConfig/helpers/getOrCreateTranslationMetadata.ts +2 -0
  32. package/src/configuration/baseDocumentLevelConfig/helpers/getTranslationMetadata.ts +2 -0
  33. package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +31 -8
  34. package/src/configuration/baseDocumentLevelConfig/index.ts +18 -101
  35. package/src/configuration/baseFieldLevelConfig.ts +19 -51
  36. package/src/configuration/utils/checkSerializationVersion.ts +2 -0
  37. package/src/configuration/utils/findDocumentAtRevision.ts +2 -0
  38. package/src/configuration/utils/findLatestDraft.ts +2 -0
  39. package/src/hooks/useClient.ts +3 -1
  40. package/src/hooks/useSecrets.ts +2 -0
  41. package/src/index.ts +91 -67
  42. package/src/sanity-api/findDocuments.ts +44 -0
  43. package/src/sanity-api/publishDocuments.ts +49 -0
  44. package/src/sanity-api/resolveRefs.ts +146 -0
  45. package/src/serialization/BaseDocumentMerger.ts +138 -0
  46. package/src/serialization/BaseSerializationConfig.ts +220 -0
  47. package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/documentLevelDeserialization.test.ts.snap +189 -0
  48. package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/fieldLevelDeserialization.test.ts.snap +107 -0
  49. package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +397 -0
  50. package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts +107 -0
  51. package/src/serialization/__tests__/BaseDocumentDeserializer/fieldLevelDeserialization.test.ts +107 -0
  52. package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/documentLevelMerge.test.ts.snap +193 -0
  53. package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/fieldLevelMerge.test.ts.snap +97 -0
  54. package/src/serialization/__tests__/BaseDocumentMerger/baseMerge.test.ts +36 -0
  55. package/src/serialization/__tests__/BaseDocumentMerger/documentLevelMerge.test.ts +96 -0
  56. package/src/serialization/__tests__/BaseDocumentMerger/fieldLevelMerge.test.ts +142 -0
  57. package/src/serialization/__tests__/BaseDocumentMerger/utils.ts +52 -0
  58. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentInlineMarks.test.ts.snap +39 -0
  59. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentLevelSerialization.test.ts.snap +8 -0
  60. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/fieldLevelSerialization.test.ts.snap +8 -0
  61. package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +345 -0
  62. package/src/serialization/__tests__/BaseDocumentSerializer/documentInlineMarks.test.ts +53 -0
  63. package/src/serialization/__tests__/BaseDocumentSerializer/documentLevelSerialization.test.ts +120 -0
  64. package/src/serialization/__tests__/BaseDocumentSerializer/fieldLevelSerialization.test.ts +153 -0
  65. package/src/serialization/__tests__/BaseDocumentSerializer/utils.ts +27 -0
  66. package/src/serialization/__tests__/README +2 -0
  67. package/src/serialization/__tests__/__fixtures__/annotationAndInlineBlocks.json +140 -0
  68. package/src/serialization/__tests__/__fixtures__/customStyles.json +62 -0
  69. package/src/serialization/__tests__/__fixtures__/documentInlineMarks.json +70 -0
  70. package/src/serialization/__tests__/__fixtures__/documentLevelArticle.json +185 -0
  71. package/src/serialization/__tests__/__fixtures__/fieldLevelArticle.json +107 -0
  72. package/src/serialization/__tests__/__fixtures__/inlineDocumentLevelArticle.json +134 -0
  73. package/src/serialization/__tests__/__fixtures__/inlineSchema.ts +270 -0
  74. package/src/serialization/__tests__/__fixtures__/messy-html.html +26 -0
  75. package/src/serialization/__tests__/__fixtures__/nestedLanguageFields.json +54 -0
  76. package/src/serialization/__tests__/__fixtures__/schema.ts +310 -0
  77. package/src/serialization/__tests__/global.setup.ts +40 -0
  78. package/src/serialization/__tests__/helpers.ts +132 -0
  79. package/src/serialization/data.ts +82 -0
  80. package/src/serialization/deserialize/BaseDocumentDeserializer.ts +171 -0
  81. package/src/serialization/deserialize/helpers.ts +42 -0
  82. package/src/serialization/helpers.ts +18 -0
  83. package/src/serialization/index.ts +11 -0
  84. package/src/serialization/serialize/fieldFilters.ts +124 -0
  85. package/src/serialization/serialize/index.ts +284 -0
  86. package/src/serialization/types.ts +41 -0
  87. package/src/translation/checkTranslationStatus.ts +42 -0
  88. package/src/translation/createJobs.ts +16 -0
  89. package/src/translation/downloadTranslations.ts +68 -0
  90. package/src/translation/importDocument.ts +23 -0
  91. package/src/translation/initProject.ts +61 -0
  92. package/src/translation/uploadFiles.ts +32 -0
  93. package/src/types.ts +7 -20
  94. package/src/utils/applyDocuments.ts +72 -0
  95. package/src/utils/batchProcessor.ts +111 -0
  96. package/src/utils/importUtils.ts +95 -0
  97. package/src/utils/serialize.ts +52 -0
  98. package/src/utils/shared.ts +1 -0
  99. package/src/adapter/index.ts +0 -13
  100. package/src/components/NewTask.tsx +0 -249
  101. package/src/components/TaskView.tsx +0 -255
  102. package/src/components/TranslationContext.tsx +0 -19
  103. package/src/components/TranslationView.tsx +0 -82
  104. package/src/components/TranslationsTab.tsx +0 -177
  105. package/src/configuration/baseDocumentLevelConfig/helpers/index.ts +0 -5
  106. package/src/configuration/baseDocumentLevelConfig/legacyDocumentLevelPatch.ts +0 -69
  107. package/src/configuration/index.ts +0 -18
  108. package/src/configuration/utils/index.ts +0 -3
@@ -0,0 +1,107 @@
1
+ import { PortableTextBlock } from 'sanity';
2
+ import { expect, test } from 'vitest';
3
+ import { documentLevelArticle } from '../BaseDocumentSerializer/utils';
4
+ import { getDeserialized, toPlainText } from '../helpers';
5
+
6
+ test('Global test of working doc-level functionality and snapshot match', () => {
7
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
8
+ expect(deserialized).toMatchSnapshot();
9
+ });
10
+
11
+ /*
12
+ * Top-level plain text
13
+ */
14
+
15
+ test('String and text types get deserialized correctly at top-level -- document level', () => {
16
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
17
+ expect(deserialized.title).toEqual(documentLevelArticle.title);
18
+ expect(deserialized.snippet).toEqual(documentLevelArticle.snippet);
19
+ });
20
+
21
+ /*
22
+ * Presence and accuracy of fields in "vanilla" deserialization -- objects
23
+ */
24
+ test('Nested object contains accurate values -- document level', () => {
25
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
26
+ const origTitle = documentLevelArticle.config.title;
27
+ const deserializedTitle = deserialized.config.title;
28
+ expect(origTitle).toEqual(deserializedTitle);
29
+
30
+ const origBlockText = documentLevelArticle.config.nestedArrayField;
31
+ const deserializedBlockText = deserialized.config.nestedArrayField;
32
+
33
+ const origKeys = origBlockText.map((block: PortableTextBlock) => block._key);
34
+ const deserializedKeys = deserializedBlockText.map(
35
+ (block: PortableTextBlock) => block._key
36
+ );
37
+
38
+ expect(deserializedKeys.sort()).toEqual(origKeys.sort());
39
+ expect(toPlainText(deserializedBlockText)).toEqual(
40
+ toPlainText(origBlockText)
41
+ );
42
+ });
43
+
44
+ test('Nested object in an object contains accurate values -- document level', () => {
45
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
46
+ const origNestedObject = documentLevelArticle.config.objectAsField;
47
+ const deserializedNestedObject = deserialized.config.objectAsField;
48
+
49
+ expect(origNestedObject.title).toEqual(deserializedNestedObject.title);
50
+
51
+ const origKeys = origNestedObject.content.map(
52
+ (block: PortableTextBlock) => block._key
53
+ );
54
+ const deserializedKeys = deserializedNestedObject.content.map(
55
+ (block: PortableTextBlock) => block._key
56
+ );
57
+
58
+ expect(origKeys.sort()).toEqual(deserializedKeys.sort());
59
+ expect(toPlainText(deserializedNestedObject.content)).toEqual(
60
+ toPlainText(origNestedObject.content)
61
+ );
62
+ });
63
+
64
+ /*
65
+ * Presence and accuracy of fields in vanilla deserialization -- arrays
66
+ */
67
+
68
+ test('Array contains all serializable blocks with keys, in order -- document level', () => {
69
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
70
+ const origKeys = documentLevelArticle.content.map(
71
+ (block: PortableTextBlock) => block._key
72
+ );
73
+ const deserializedKeys = deserialized.content.map(
74
+ (block: PortableTextBlock) => block._key
75
+ );
76
+ expect(deserializedKeys.sort()).toEqual(origKeys.sort());
77
+ });
78
+
79
+ test('Array contains top-level block text -- document level', () => {
80
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
81
+ expect(toPlainText(deserialized.content)).toEqual(
82
+ toPlainText(documentLevelArticle.content)
83
+ );
84
+ });
85
+
86
+ test('Object in array contains accurate values in nested object -- document level', () => {
87
+ const deserialized = getDeserialized(documentLevelArticle, 'document');
88
+ const origTitle = documentLevelArticle.content.find(
89
+ (block: Record<string, any>) => block._type === 'objectField'
90
+ ).objectAsField.title;
91
+ const deserializedTitle = deserialized.content.find(
92
+ (block: Record<string, any>) => block._type === 'objectField'
93
+ ).objectAsField.title;
94
+ expect(deserializedTitle).toEqual(origTitle);
95
+
96
+ const origBlockText = toPlainText(
97
+ documentLevelArticle.content.find(
98
+ (block: Record<string, any>) => block._type === 'objectField'
99
+ ).objectAsField.content
100
+ ).trim();
101
+ const deserializedBlockText = toPlainText(
102
+ documentLevelArticle.content.find(
103
+ (block: Record<string, any>) => block._type === 'objectField'
104
+ ).objectAsField.content
105
+ ).trim();
106
+ expect(deserializedBlockText).toEqual(origBlockText);
107
+ });
@@ -0,0 +1,107 @@
1
+ import { PortableTextBlock } from 'sanity';
2
+ import { expect, test } from 'vitest';
3
+ import { fieldLevelArticle } from '../BaseDocumentSerializer/utils';
4
+ import { getDeserialized, toPlainText } from '../helpers';
5
+
6
+ test('Global test of working field-level functionality and snapshot match', () => {
7
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
8
+ expect(deserialized).toMatchSnapshot();
9
+ });
10
+
11
+ /*
12
+ * Top-level plain text
13
+ */
14
+
15
+ test('String and text types get deserialized correctly at top-level -- field level', () => {
16
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
17
+ expect(deserialized.title.en).toEqual(fieldLevelArticle.title.en);
18
+ expect(deserialized.snippet.en).toEqual(fieldLevelArticle.snippet.en);
19
+ });
20
+
21
+ /*
22
+ * Presence and accuracy of fields in "vanilla" deserialization -- objects
23
+ */
24
+ test('Nested object contains accurate values -- field level', () => {
25
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
26
+ const origTitle = fieldLevelArticle.config.en.title;
27
+ const deserializedTitle = deserialized.config.en.title;
28
+ expect(origTitle).toEqual(deserializedTitle);
29
+
30
+ const origBlockText = fieldLevelArticle.config.en.nestedArrayField;
31
+ const deserializedBlockText = deserialized.config.en.nestedArrayField;
32
+
33
+ const origKeys = origBlockText.map((block: PortableTextBlock) => block._key);
34
+ const deserializedKeys = deserializedBlockText.map(
35
+ (block: PortableTextBlock) => block._key
36
+ );
37
+
38
+ expect(deserializedKeys.sort()).toEqual(origKeys.sort());
39
+ expect(toPlainText(deserializedBlockText)).toEqual(
40
+ toPlainText(origBlockText)
41
+ );
42
+ });
43
+
44
+ test('Nested object in an object contains accurate values -- field level', () => {
45
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
46
+ const origNestedObject = fieldLevelArticle.config.en.objectAsField;
47
+ const deserializedNestedObject = deserialized.config.en.objectAsField;
48
+
49
+ expect(origNestedObject.title).toEqual(deserializedNestedObject.title);
50
+
51
+ const origKeys = origNestedObject.content.map(
52
+ (block: PortableTextBlock) => block._key
53
+ );
54
+ const deserializedKeys = deserializedNestedObject.content.map(
55
+ (block: PortableTextBlock) => block._key
56
+ );
57
+
58
+ expect(origKeys.sort()).toEqual(deserializedKeys.sort());
59
+ expect(toPlainText(deserializedNestedObject.content)).toEqual(
60
+ toPlainText(origNestedObject.content)
61
+ );
62
+ });
63
+
64
+ /*
65
+ * Presence and accuracy of fields in vanilla deserialization -- arrays
66
+ */
67
+
68
+ test('Array contains all serializable blocks with keys, in order -- field level', () => {
69
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
70
+ const origKeys = fieldLevelArticle.content.en.map(
71
+ (block: PortableTextBlock) => block._key
72
+ );
73
+ const deserializedKeys = deserialized.content.en.map(
74
+ (block: PortableTextBlock) => block._key
75
+ );
76
+ expect(deserializedKeys.sort()).toEqual(origKeys.sort());
77
+ });
78
+
79
+ test('Array contains top-level block text -- field level', () => {
80
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
81
+ expect(toPlainText(deserialized.content.en)).toEqual(
82
+ toPlainText(fieldLevelArticle.content.en)
83
+ );
84
+ });
85
+
86
+ test('Object in array contains accurate values in nested object -- field level', () => {
87
+ const deserialized = getDeserialized(fieldLevelArticle, 'field');
88
+ const origTitle = fieldLevelArticle.content.en.find(
89
+ (block: Record<string, any>) => block._type === 'objectField'
90
+ ).objectAsField.title;
91
+ const deserializedTitle = deserialized.content.en.find(
92
+ (block: Record<string, any>) => block._type === 'objectField'
93
+ ).objectAsField.title;
94
+ expect(deserializedTitle).toEqual(origTitle);
95
+
96
+ const origBlockText = toPlainText(
97
+ fieldLevelArticle.content.en.find(
98
+ (block: Record<string, any>) => block._type === 'objectField'
99
+ ).objectAsField.content
100
+ ).trim();
101
+ const deserializedBlockText = toPlainText(
102
+ fieldLevelArticle.content.en.find(
103
+ (block: Record<string, any>) => block._type === 'objectField'
104
+ ).objectAsField.content
105
+ ).trim();
106
+ expect(deserializedBlockText).toEqual(origBlockText);
107
+ });
@@ -0,0 +1,193 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Global document level snapshot test 1`] = `
4
+ {
5
+ "_createdAt": "2021-09-01T23:00:13Z",
6
+ "_id": "drafts.d8ffc675-ce86-4f60-9ac8-da164cde3b0a",
7
+ "_rev": "fxcnqj-uew-gr7-v6r-z965tfm69",
8
+ "_type": "documentLevelArticle",
9
+ "_updatedAt": "2021-09-01T23:02:05Z",
10
+ "config": {
11
+ "_type": "objectField",
12
+ "nestedArrayField": [
13
+ {
14
+ "_key": "4a58adc7c507",
15
+ "_type": "block",
16
+ "children": [
17
+ {
18
+ "_key": "4f6bc15ae261",
19
+ "_type": "span",
20
+ "marks": [],
21
+ "text": "New text",
22
+ },
23
+ ],
24
+ "markDefs": [],
25
+ "style": "normal",
26
+ },
27
+ ],
28
+ "objectAsField": {
29
+ "_type": "childObjectField",
30
+ "content": [
31
+ {
32
+ "_key": "1aa228ac848b",
33
+ "_type": "block",
34
+ "children": [
35
+ {
36
+ "_key": "e2cf67af8e62",
37
+ "_type": "span",
38
+ "marks": [],
39
+ "text": "This is a block text 2 levels deep",
40
+ },
41
+ ],
42
+ "markDefs": [],
43
+ "style": "normal",
44
+ },
45
+ ],
46
+ "title": "A new nested title",
47
+ },
48
+ "title": "A new title",
49
+ },
50
+ "content": [
51
+ {
52
+ "_key": "a4d177e92666",
53
+ "_type": "block",
54
+ "children": [
55
+ {
56
+ "_key": "randomKey-18",
57
+ "_type": "span",
58
+ "marks": [],
59
+ "text": "New block text",
60
+ },
61
+ ],
62
+ "markDefs": [],
63
+ "style": "normal",
64
+ },
65
+ {
66
+ "_key": "c0313627775e",
67
+ "_type": "objectField",
68
+ "objectAsField": {
69
+ "_type": "childObjectField",
70
+ "content": [
71
+ {
72
+ "_key": "4f24f6fbfae7",
73
+ "_type": "block",
74
+ "children": [
75
+ {
76
+ "_key": "d68f4288f5b7",
77
+ "_type": "span",
78
+ "marks": [],
79
+ "text": "This is block text in a nested object in an object in top-level block text.",
80
+ },
81
+ ],
82
+ "markDefs": [],
83
+ "style": "normal",
84
+ },
85
+ ],
86
+ "title": "This is a nested object in an object in top-level block text.",
87
+ },
88
+ "title": "This is an object in top-level block text.",
89
+ },
90
+ {
91
+ "_key": "9e2ab13c6d63",
92
+ "_type": "block",
93
+ "children": [
94
+ {
95
+ "_key": "17e856dc4766",
96
+ "_type": "span",
97
+ "marks": [],
98
+ "text": "This is h1 text",
99
+ },
100
+ ],
101
+ "markDefs": [],
102
+ "style": "h1",
103
+ },
104
+ {
105
+ "_key": "297142fbaf21",
106
+ "_type": "block",
107
+ "children": [
108
+ {
109
+ "_key": "0b2f9e94a161",
110
+ "_type": "span",
111
+ "marks": [],
112
+ "text": "This is h2 text",
113
+ },
114
+ ],
115
+ "markDefs": [],
116
+ "style": "h2",
117
+ },
118
+ {
119
+ "_key": "76e648fc3845",
120
+ "_type": "block",
121
+ "children": [
122
+ {
123
+ "_key": "49f466bbc78c",
124
+ "_type": "span",
125
+ "marks": [],
126
+ "text": "Bullet 1",
127
+ },
128
+ ],
129
+ "level": 1,
130
+ "listItem": "bullet",
131
+ "markDefs": [],
132
+ "style": "normal",
133
+ },
134
+ {
135
+ "_key": "d090cd8b27d2",
136
+ "_type": "block",
137
+ "children": [
138
+ {
139
+ "_key": "599c6991018f",
140
+ "_type": "span",
141
+ "marks": [],
142
+ "text": "nested bullet a",
143
+ },
144
+ ],
145
+ "level": 2,
146
+ "listItem": "bullet",
147
+ "markDefs": [],
148
+ "style": "normal",
149
+ },
150
+ {
151
+ "_key": "1cdffa5d50f5",
152
+ "_type": "block",
153
+ "children": [
154
+ {
155
+ "_key": "c16eb16f01cb",
156
+ "_type": "span",
157
+ "marks": [],
158
+ "text": "Styled bullet 2",
159
+ },
160
+ ],
161
+ "level": 1,
162
+ "listItem": "bullet",
163
+ "markDefs": [],
164
+ "style": "h2",
165
+ },
166
+ {
167
+ "_key": "da29f5063059",
168
+ "_type": "block",
169
+ "children": [
170
+ {
171
+ "_key": "e3d7e3eaad54",
172
+ "_type": "span",
173
+ "marks": [],
174
+ "text": "Number 1",
175
+ },
176
+ ],
177
+ "level": 1,
178
+ "listItem": "number",
179
+ "markDefs": [],
180
+ "style": "h3",
181
+ },
182
+ ],
183
+ "hidden": true,
184
+ "meta": "Do not translate this",
185
+ "snippet": "A new document snippet",
186
+ "tags": [
187
+ "tag 1",
188
+ "tag 2",
189
+ "tag 3",
190
+ ],
191
+ "title": "A new document title",
192
+ }
193
+ `;
@@ -0,0 +1,97 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Global field level snapshot test 1`] = `
4
+ {
5
+ "_id": "drafts.2947533e-1ea5-4116-955b-339608d3445d",
6
+ "_rev": "l58oha-n06-1s4-f6i-74g6cuakl",
7
+ "_type": "fieldLevelArticle",
8
+ "config.es_ES": {
9
+ "_type": "objectField",
10
+ "nestedArrayField": [
11
+ {
12
+ "_key": "f49b4d7e3e51",
13
+ "_type": "block",
14
+ "children": [
15
+ {
16
+ "_key": "a6170f21181c",
17
+ "_type": "span",
18
+ "marks": [],
19
+ "text": "New text",
20
+ },
21
+ ],
22
+ "markDefs": [],
23
+ "style": "normal",
24
+ },
25
+ ],
26
+ "objectAsField": {
27
+ "_type": "childObjectField",
28
+ "content": [
29
+ {
30
+ "_key": "869168fe3a2a",
31
+ "_type": "block",
32
+ "children": [
33
+ {
34
+ "_key": "10d423df228a",
35
+ "_type": "span",
36
+ "marks": [],
37
+ "text": "This is block text 2 levels deep",
38
+ },
39
+ ],
40
+ "markDefs": [],
41
+ "style": "normal",
42
+ },
43
+ ],
44
+ "title": "A new nested title",
45
+ },
46
+ "title": "A new title",
47
+ },
48
+ "content.es_ES": [
49
+ {
50
+ "_key": "e2a39d768ff8",
51
+ "_type": "block",
52
+ "children": [
53
+ {
54
+ "_key": "randomKey-18",
55
+ "_type": "span",
56
+ "marks": [],
57
+ "text": "New block text",
58
+ },
59
+ ],
60
+ "markDefs": [],
61
+ "style": "normal",
62
+ },
63
+ {
64
+ "_key": "271b0c6ee984",
65
+ "_type": "objectField",
66
+ "objectAsField": {
67
+ "_type": "childObjectField",
68
+ "content": [
69
+ {
70
+ "_key": "4f24f6fbfae7",
71
+ "_type": "block",
72
+ "children": [
73
+ {
74
+ "_key": "d68f4288f5b7",
75
+ "_type": "span",
76
+ "marks": [],
77
+ "text": "This is block text in a nested object in an object in top-level block text.",
78
+ },
79
+ ],
80
+ "markDefs": [],
81
+ "style": "normal",
82
+ },
83
+ ],
84
+ "title": "This is a nested object in an object in top-level block text.",
85
+ },
86
+ "title": "This is an object in top-level block text.",
87
+ },
88
+ ],
89
+ "snippet.es_ES": "A new document snippet",
90
+ "tags.es_ES": [
91
+ "tag 1",
92
+ "tag 2",
93
+ "tag 3",
94
+ ],
95
+ "title.es_ES": "A new document title",
96
+ }
97
+ `;
@@ -0,0 +1,36 @@
1
+ import { createRequire } from 'module';
2
+ import { PortableTextBlock } from 'sanity';
3
+ import { expect, test } from 'vitest';
4
+ import { BaseDocumentMerger } from '../../index';
5
+ import { getNewDocument } from './utils';
6
+
7
+ const require = createRequire(import.meta.url);
8
+
9
+ const documentLevelArticle = require('../__fixtures__/documentLevelArticle.json');
10
+
11
+ /*
12
+ * STYLE TAGS
13
+ */
14
+ test('Merged document should maintain style tags', () => {
15
+ const newDocument = getNewDocument();
16
+ const mergedDocument = BaseDocumentMerger.documentLevelMerge(
17
+ newDocument,
18
+ documentLevelArticle
19
+ );
20
+ const origH1Block = documentLevelArticle.content.find(
21
+ (block: PortableTextBlock) => block.style === 'h1'
22
+ );
23
+ const origH2Block = documentLevelArticle.content.find(
24
+ (block: PortableTextBlock) => block.style === 'h2'
25
+ );
26
+ const mergedH1Block = mergedDocument.content.find(
27
+ (block: PortableTextBlock) => block.style === 'h1'
28
+ );
29
+ const mergedH2Block = mergedDocument.content.find(
30
+ (block: PortableTextBlock) => block.style === 'h2'
31
+ );
32
+ expect(mergedH1Block).toBeDefined();
33
+ expect(mergedH2Block).toBeDefined();
34
+ expect(mergedH1Block._key).toEqual(origH1Block._key);
35
+ expect(mergedH2Block._key).toEqual(origH2Block._key);
36
+ });
@@ -0,0 +1,96 @@
1
+ import { createRequire } from 'module';
2
+ import { expect, test } from 'vitest';
3
+ import { BaseDocumentMerger } from '../../index';
4
+ import { getNewDocument, getNewObject } from './utils';
5
+
6
+ const require = createRequire(import.meta.url);
7
+
8
+ const documentLevelArticle = require('../__fixtures__/documentLevelArticle.json');
9
+
10
+ const newDocument = getNewDocument();
11
+ const mergedDocument = BaseDocumentMerger.documentLevelMerge(
12
+ newDocument,
13
+ documentLevelArticle
14
+ );
15
+
16
+ test('Global document level snapshot test', () => {
17
+ expect(mergedDocument).toMatchSnapshot();
18
+ });
19
+
20
+ /*
21
+ * Objects
22
+ */
23
+ test('Top-level string / text fields from new document override old document', () => {
24
+ expect(mergedDocument.title).toEqual(newDocument.title);
25
+ expect(mergedDocument.snippet).toEqual(newDocument.snippet);
26
+ expect(mergedDocument.title).not.toEqual(documentLevelArticle.title);
27
+ expect(mergedDocument.snippet).not.toEqual(documentLevelArticle.snippet);
28
+ });
29
+
30
+ test('Nested object fields override old object fields', () => {
31
+ expect(mergedDocument.config.title).toEqual(newDocument.config.title);
32
+ expect(mergedDocument.config.title).not.toEqual(
33
+ documentLevelArticle.config.title
34
+ );
35
+ expect(mergedDocument.config.nestedArrayField[0].children[0].text).toEqual(
36
+ newDocument.config.nestedArrayField[0].children[0].text
37
+ );
38
+ expect(
39
+ mergedDocument.config.nestedArrayField[0].children[0].text
40
+ ).not.toEqual(
41
+ documentLevelArticle.config.nestedArrayField[0].children[0].text
42
+ );
43
+ });
44
+
45
+ test('Nested object merge uses old fields when not present on new object', () => {
46
+ expect(newDocument.config.objectAsField.content).toBeUndefined();
47
+ expect(mergedDocument.config.objectAsField.content).toBeDefined();
48
+ });
49
+
50
+ /*
51
+ * Arrays
52
+ */
53
+ test('Arrays will use new objects when they exist', () => {
54
+ expect(mergedDocument.content[0].children[0].text).toEqual(
55
+ newDocument.content[0].children[0].text
56
+ );
57
+ expect(mergedDocument.content[0].children[0].text).not.toEqual(
58
+ documentLevelArticle.content[0].children[0].text
59
+ );
60
+ });
61
+
62
+ test('Arrays will use old blocks if they do not exist on new object', () => {
63
+ expect(newDocument.content[1]).toBeUndefined();
64
+ expect(mergedDocument.content[1]).toBeDefined();
65
+ expect(mergedDocument.content[1]._key).toEqual(
66
+ documentLevelArticle.content[1]._key
67
+ );
68
+ });
69
+
70
+ test('Arrays will merge objects in the array', () => {
71
+ const documentWithIncompleteObj = getNewDocument();
72
+ const incompleteObj = getNewObject();
73
+
74
+ //add a new block with some new content, but not all new content
75
+ documentWithIncompleteObj.content.push({
76
+ _key: documentLevelArticle.content[1]._key,
77
+ objectAsField: incompleteObj.objectAsField,
78
+ title: incompleteObj.title,
79
+ });
80
+ const documentWithMergedObj = BaseDocumentMerger.documentLevelMerge(
81
+ documentWithIncompleteObj,
82
+ documentLevelArticle
83
+ );
84
+
85
+ expect(documentWithMergedObj.content[1].title).toEqual(
86
+ documentWithIncompleteObj.content[1].title
87
+ );
88
+ expect(documentWithMergedObj.content[1].objectAsField.title).toEqual(
89
+ documentWithIncompleteObj.content[1].objectAsField.title
90
+ );
91
+ //content existed on old doc but not new, so the two coexist happily
92
+ expect(
93
+ documentWithIncompleteObj.content[1].objectAsField.content
94
+ ).toBeUndefined();
95
+ expect(documentWithMergedObj.content[1].objectAsField.content).toBeDefined();
96
+ });