gt-sanity 0.0.6 → 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.
- package/LICENSE.md +1 -1
- package/dist/index.d.mts +95 -73
- package/dist/index.d.ts +95 -73
- package/dist/index.js +9066 -1207
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9083 -1197
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -3
- package/src/adapter/core.ts +41 -4
- package/src/adapter/getLocales.ts +2 -2
- package/src/components/TranslationsProvider.tsx +942 -0
- package/src/components/page/BatchProgress.tsx +27 -0
- package/src/components/page/ImportAllDialog.tsx +51 -0
- package/src/components/page/ImportMissingDialog.tsx +55 -0
- package/src/components/page/TranslateAllDialog.tsx +55 -0
- package/src/components/page/TranslationsTable.tsx +81 -0
- package/src/components/page/TranslationsTool.tsx +299 -837
- package/src/components/shared/BaseTranslationWrapper.tsx +82 -0
- package/src/components/shared/LocaleCheckbox.tsx +47 -0
- package/src/components/shared/SingleDocumentView.tsx +108 -0
- package/src/components/tab/TranslationView.tsx +379 -0
- package/src/components/tab/TranslationsTab.tsx +25 -0
- package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +6 -9
- package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +5 -24
- package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +3 -23
- package/src/configuration/baseDocumentLevelConfig/index.ts +16 -68
- package/src/configuration/baseFieldLevelConfig.ts +15 -50
- package/src/index.ts +29 -43
- package/src/sanity-api/findDocuments.ts +44 -0
- package/src/sanity-api/publishDocuments.ts +49 -0
- package/src/sanity-api/resolveRefs.ts +146 -0
- package/src/serialization/BaseDocumentMerger.ts +138 -0
- package/src/serialization/BaseSerializationConfig.ts +220 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/documentLevelDeserialization.test.ts.snap +189 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/fieldLevelDeserialization.test.ts.snap +107 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +397 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts +107 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/fieldLevelDeserialization.test.ts +107 -0
- package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/documentLevelMerge.test.ts.snap +193 -0
- package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/fieldLevelMerge.test.ts.snap +97 -0
- package/src/serialization/__tests__/BaseDocumentMerger/baseMerge.test.ts +36 -0
- package/src/serialization/__tests__/BaseDocumentMerger/documentLevelMerge.test.ts +96 -0
- package/src/serialization/__tests__/BaseDocumentMerger/fieldLevelMerge.test.ts +142 -0
- package/src/serialization/__tests__/BaseDocumentMerger/utils.ts +52 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentInlineMarks.test.ts.snap +39 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentLevelSerialization.test.ts.snap +8 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/fieldLevelSerialization.test.ts.snap +8 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +345 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/documentInlineMarks.test.ts +53 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/documentLevelSerialization.test.ts +120 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/fieldLevelSerialization.test.ts +153 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/utils.ts +27 -0
- package/src/serialization/__tests__/README +2 -0
- package/src/serialization/__tests__/__fixtures__/annotationAndInlineBlocks.json +140 -0
- package/src/serialization/__tests__/__fixtures__/customStyles.json +62 -0
- package/src/serialization/__tests__/__fixtures__/documentInlineMarks.json +70 -0
- package/src/serialization/__tests__/__fixtures__/documentLevelArticle.json +185 -0
- package/src/serialization/__tests__/__fixtures__/fieldLevelArticle.json +107 -0
- package/src/serialization/__tests__/__fixtures__/inlineDocumentLevelArticle.json +134 -0
- package/src/serialization/__tests__/__fixtures__/inlineSchema.ts +270 -0
- package/src/serialization/__tests__/__fixtures__/messy-html.html +26 -0
- package/src/serialization/__tests__/__fixtures__/nestedLanguageFields.json +54 -0
- package/src/serialization/__tests__/__fixtures__/schema.ts +310 -0
- package/src/serialization/__tests__/global.setup.ts +40 -0
- package/src/serialization/__tests__/helpers.ts +132 -0
- package/src/serialization/data.ts +82 -0
- package/src/serialization/deserialize/BaseDocumentDeserializer.ts +171 -0
- package/src/serialization/deserialize/helpers.ts +42 -0
- package/src/serialization/helpers.ts +18 -0
- package/src/serialization/index.ts +11 -0
- package/src/serialization/serialize/fieldFilters.ts +124 -0
- package/src/serialization/serialize/index.ts +284 -0
- package/src/serialization/types.ts +41 -0
- package/src/translation/importDocument.ts +4 -5
- package/src/translation/uploadFiles.ts +1 -1
- package/src/types.ts +3 -19
- package/src/utils/batchProcessor.ts +111 -0
- package/src/utils/importUtils.ts +95 -0
- package/src/utils/serialize.ts +25 -5
- package/src/utils/shared.ts +1 -1
- package/src/adapter/index.ts +0 -13
- package/src/components/NewTask.tsx +0 -251
- package/src/components/TaskView.tsx +0 -257
- package/src/components/TranslationContext.tsx +0 -24
- package/src/components/TranslationView.tsx +0 -114
- package/src/components/TranslationsTab.tsx +0 -181
- /package/src/components/{LanguageStatus.tsx → shared/LanguageStatus.tsx} +0 -0
- /package/src/components/{ProgressBar.tsx → shared/ProgressBar.tsx} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Global test of working field-level functionality and snapshot match 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"_id": "drafts.2947533e-1ea5-4116-955b-339608d3445d",
|
|
6
|
+
"_rev": "l58oha-n06-1s4-f6i-74g6cuakl",
|
|
7
|
+
"_type": "fieldLevelArticle",
|
|
8
|
+
"config": {
|
|
9
|
+
"en": {
|
|
10
|
+
"_type": "objectField",
|
|
11
|
+
"nestedArrayField": [
|
|
12
|
+
{
|
|
13
|
+
"_key": "f49b4d7e3e51",
|
|
14
|
+
"_type": "block",
|
|
15
|
+
"children": [
|
|
16
|
+
{
|
|
17
|
+
"_key": "randomKey-16",
|
|
18
|
+
"_type": "span",
|
|
19
|
+
"marks": [],
|
|
20
|
+
"text": "This is block text 1 level deep",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
"markDefs": [],
|
|
24
|
+
"style": "normal",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
"objectAsField": {
|
|
28
|
+
"_type": "childObjectField",
|
|
29
|
+
"content": [
|
|
30
|
+
{
|
|
31
|
+
"_key": "869168fe3a2a",
|
|
32
|
+
"_type": "block",
|
|
33
|
+
"children": [
|
|
34
|
+
{
|
|
35
|
+
"_key": "randomKey-14",
|
|
36
|
+
"_type": "span",
|
|
37
|
+
"marks": [],
|
|
38
|
+
"text": "This is block text 2 levels deep",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
"markDefs": [],
|
|
42
|
+
"style": "normal",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
"title": "This is one level deeper",
|
|
46
|
+
},
|
|
47
|
+
"title": "This is an object nested in a document",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"content": {
|
|
51
|
+
"en": [
|
|
52
|
+
{
|
|
53
|
+
"_key": "e2a39d768ff8",
|
|
54
|
+
"_type": "block",
|
|
55
|
+
"children": [
|
|
56
|
+
{
|
|
57
|
+
"_key": "randomKey-18",
|
|
58
|
+
"_type": "span",
|
|
59
|
+
"marks": [],
|
|
60
|
+
"text": "This is block text at the top level.",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
"markDefs": [],
|
|
64
|
+
"style": "normal",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"_key": "271b0c6ee984",
|
|
68
|
+
"_type": "objectField",
|
|
69
|
+
"objectAsField": {
|
|
70
|
+
"_type": "childObjectField",
|
|
71
|
+
"content": [
|
|
72
|
+
{
|
|
73
|
+
"_key": "4f24f6fbfae7",
|
|
74
|
+
"_type": "block",
|
|
75
|
+
"children": [
|
|
76
|
+
{
|
|
77
|
+
"_key": "randomKey-24",
|
|
78
|
+
"_type": "span",
|
|
79
|
+
"marks": [],
|
|
80
|
+
"text": "This is block text in a nested object in an object in top-level block text.",
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
"markDefs": [],
|
|
84
|
+
"style": "normal",
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
"title": "This is a nested object in an object in top-level block text.",
|
|
88
|
+
},
|
|
89
|
+
"title": "This is an object in top-level block text.",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
"snippet": {
|
|
94
|
+
"en": "This is text in my text field",
|
|
95
|
+
},
|
|
96
|
+
"tags": {
|
|
97
|
+
"en": [
|
|
98
|
+
"tag 1",
|
|
99
|
+
"tag 2",
|
|
100
|
+
"tag 3",
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
"title": {
|
|
104
|
+
"en": "My Field-Level Article",
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import {
|
|
3
|
+
PortableTextBlock,
|
|
4
|
+
PortableTextObject,
|
|
5
|
+
PortableTextSpan,
|
|
6
|
+
PortableTextTextBlock,
|
|
7
|
+
} from 'sanity';
|
|
8
|
+
import { beforeEach, expect, test, vi } from 'vitest';
|
|
9
|
+
import {
|
|
10
|
+
BaseDocumentDeserializer,
|
|
11
|
+
BaseDocumentSerializer,
|
|
12
|
+
customBlockDeserializers,
|
|
13
|
+
defaultStopTypes,
|
|
14
|
+
} from '../../index';
|
|
15
|
+
import {
|
|
16
|
+
annotationAndInlineBlocks,
|
|
17
|
+
documentLevelArticle,
|
|
18
|
+
inlineDocumentLevelArticle,
|
|
19
|
+
inlineSchema,
|
|
20
|
+
schema,
|
|
21
|
+
} from '../BaseDocumentSerializer/utils';
|
|
22
|
+
import {
|
|
23
|
+
addedBlockDeserializers,
|
|
24
|
+
addedCustomDeserializers,
|
|
25
|
+
addedCustomSerializers,
|
|
26
|
+
getDeserialized,
|
|
27
|
+
} from '../helpers';
|
|
28
|
+
|
|
29
|
+
const customStyles = require('../__fixtures__/customStyles');
|
|
30
|
+
|
|
31
|
+
let mockTestKey = 0;
|
|
32
|
+
|
|
33
|
+
vi.mock('@sanity/block-tools', async () => {
|
|
34
|
+
const originalModule = await vi.importActual<
|
|
35
|
+
typeof import('@sanity/block-tools')
|
|
36
|
+
>('@sanity/block-tools');
|
|
37
|
+
return {
|
|
38
|
+
...originalModule,
|
|
39
|
+
//not ideal but vi.mock('@sanity/block-tools/src/util/randomKey.ts' is not working
|
|
40
|
+
htmlToBlocks: (html: string, blockContentType: any, options: any) => {
|
|
41
|
+
const blocks = originalModule.htmlToBlocks(
|
|
42
|
+
html,
|
|
43
|
+
blockContentType,
|
|
44
|
+
options
|
|
45
|
+
);
|
|
46
|
+
const newBlocks = blocks.map((block) => {
|
|
47
|
+
const newChildren = (
|
|
48
|
+
block as unknown as PortableTextTextBlock<
|
|
49
|
+
PortableTextSpan | PortableTextObject
|
|
50
|
+
>
|
|
51
|
+
).children.map((child) => {
|
|
52
|
+
return { ...child, _key: `randomKey-${mockTestKey++}` };
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
...block,
|
|
56
|
+
children: newChildren,
|
|
57
|
+
_key: `randomKey-${mockTestKey++}`,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
return newBlocks;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
mockTestKey = 0;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('Contains id of original document', () => {
|
|
70
|
+
const deserialized = getDeserialized(documentLevelArticle, 'document');
|
|
71
|
+
const id = deserialized._id;
|
|
72
|
+
expect(id).toEqual(documentLevelArticle._id);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('Contains rev of original document', () => {
|
|
76
|
+
const deserialized = getDeserialized(documentLevelArticle, 'document');
|
|
77
|
+
const rev = deserialized._rev;
|
|
78
|
+
expect(rev).toEqual(documentLevelArticle._rev);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('Contains type of original document', () => {
|
|
82
|
+
const deserialized = getDeserialized(documentLevelArticle, 'document');
|
|
83
|
+
const type = deserialized._type;
|
|
84
|
+
expect(type).toEqual(documentLevelArticle._type);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/*
|
|
88
|
+
* CUSTOM SETTINGS
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
test('Custom deserialization should manifest at all levels', () => {
|
|
92
|
+
const serialized = BaseDocumentSerializer(schema).serializeDocument(
|
|
93
|
+
documentLevelArticle,
|
|
94
|
+
'document',
|
|
95
|
+
'en',
|
|
96
|
+
defaultStopTypes,
|
|
97
|
+
addedCustomSerializers
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
101
|
+
serialized.content,
|
|
102
|
+
addedCustomDeserializers,
|
|
103
|
+
customBlockDeserializers
|
|
104
|
+
);
|
|
105
|
+
expect(deserialized.config.title).toEqual(documentLevelArticle.config.title);
|
|
106
|
+
expect(deserialized.config._type).toEqual(documentLevelArticle.config._type);
|
|
107
|
+
|
|
108
|
+
const origArrayObj = documentLevelArticle.content.find(
|
|
109
|
+
(b: Record<string, any>) => b._type === 'objectField'
|
|
110
|
+
);
|
|
111
|
+
const deserializedArrayObj = deserialized.content.find(
|
|
112
|
+
(b: Record<string, any>) => b._type === 'objectField'
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
expect(deserializedArrayObj.title).toEqual(origArrayObj.title);
|
|
116
|
+
expect(deserializedArrayObj._key).toEqual(origArrayObj._key);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('Content with custom styles deserializes correctly and maintains style', () => {
|
|
120
|
+
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
121
|
+
|
|
122
|
+
const customStyledDocument = {
|
|
123
|
+
...documentLevelArticle,
|
|
124
|
+
...customStyles,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const serialized = BaseDocumentSerializer(schema).serializeDocument(
|
|
128
|
+
customStyledDocument,
|
|
129
|
+
'document'
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
133
|
+
serialized.content
|
|
134
|
+
);
|
|
135
|
+
const origCustomStyleBlock = customStyledDocument.content.find(
|
|
136
|
+
(b: Record<string, any>) => b._type === 'block' && b.style === 'custom1'
|
|
137
|
+
);
|
|
138
|
+
const origCustomStyleListItem = customStyledDocument.content.find(
|
|
139
|
+
(b: Record<string, any>) =>
|
|
140
|
+
b._type === 'block' && b.listItem === 'number' && b.style === 'custom1'
|
|
141
|
+
);
|
|
142
|
+
const deserializedCustomStyleBlock = deserialized.content.find(
|
|
143
|
+
(b: Record<string, any>) => b._type === 'block' && b.style === 'custom1'
|
|
144
|
+
);
|
|
145
|
+
const deserializedCustomStyleListItem = deserialized.content.find(
|
|
146
|
+
(b: Record<string, any>) =>
|
|
147
|
+
b._type === 'block' && b.listItem === 'number' && b.style === 'custom1'
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(deserializedCustomStyleBlock.children[0].text).toEqual(
|
|
151
|
+
origCustomStyleBlock.children[0].text
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
expect(deserializedCustomStyleListItem.children[0].text).toEqual(
|
|
155
|
+
origCustomStyleListItem.children[0].text
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
//test -- unhandled annotations and inlines don't break when they get deserialized back
|
|
160
|
+
test('Handled inline objects should be accurately deserialized', () => {
|
|
161
|
+
const inlineDocument = {
|
|
162
|
+
...documentLevelArticle,
|
|
163
|
+
...annotationAndInlineBlocks,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const serialized = BaseDocumentSerializer(schema).serializeDocument(
|
|
167
|
+
inlineDocument,
|
|
168
|
+
'document',
|
|
169
|
+
'en',
|
|
170
|
+
defaultStopTypes,
|
|
171
|
+
addedCustomSerializers
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
175
|
+
serialized.content,
|
|
176
|
+
addedCustomDeserializers,
|
|
177
|
+
addedBlockDeserializers
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
const getInlineObj = (
|
|
181
|
+
content: PortableTextBlock[],
|
|
182
|
+
level: number | undefined = undefined
|
|
183
|
+
) => {
|
|
184
|
+
let child: Record<string, any> = {};
|
|
185
|
+
const blocks = content.filter((block: PortableTextBlock) => {
|
|
186
|
+
if (level) {
|
|
187
|
+
return block.level === level;
|
|
188
|
+
}
|
|
189
|
+
return !block.level;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
blocks.forEach((block: PortableTextBlock) => {
|
|
193
|
+
if (block.children && Array.isArray(block.children)) {
|
|
194
|
+
child = block.children.find((span: Record<string, any>) => {
|
|
195
|
+
if (level) {
|
|
196
|
+
return span._type === 'childObjectField' && block.level === level;
|
|
197
|
+
}
|
|
198
|
+
return span._type === 'childObjectField' && !block.level;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
return child;
|
|
204
|
+
};
|
|
205
|
+
const origInlineObject = getInlineObj(inlineDocument.content);
|
|
206
|
+
const origInlineListObject = getInlineObj(inlineDocument.content, 1);
|
|
207
|
+
|
|
208
|
+
const deserializedInlineObject = getInlineObj(deserialized.content);
|
|
209
|
+
const deserializedInlineListObject = getInlineObj(deserialized.content, 1);
|
|
210
|
+
|
|
211
|
+
expect(deserializedInlineObject.title).toEqual(origInlineObject.title);
|
|
212
|
+
expect(deserializedInlineObject._type).toEqual(origInlineObject._type);
|
|
213
|
+
|
|
214
|
+
expect(deserializedInlineListObject.title).toEqual(
|
|
215
|
+
origInlineListObject.title
|
|
216
|
+
);
|
|
217
|
+
expect(deserializedInlineListObject._type).toEqual(
|
|
218
|
+
origInlineListObject._type
|
|
219
|
+
);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('Handled annotations should be accurately deserialized', () => {
|
|
223
|
+
const inlineDocument = {
|
|
224
|
+
...documentLevelArticle,
|
|
225
|
+
...annotationAndInlineBlocks,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const serialized = BaseDocumentSerializer(schema).serializeDocument(
|
|
229
|
+
inlineDocument,
|
|
230
|
+
'document',
|
|
231
|
+
'en',
|
|
232
|
+
defaultStopTypes,
|
|
233
|
+
addedCustomSerializers
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
237
|
+
serialized.content,
|
|
238
|
+
addedCustomDeserializers,
|
|
239
|
+
addedBlockDeserializers
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
let origAnnotation: Record<string, any> | null = null;
|
|
243
|
+
let deserializedAnnotation: Record<string, any> | null = null;
|
|
244
|
+
|
|
245
|
+
inlineDocument.content.forEach((block: PortableTextBlock) => {
|
|
246
|
+
if (block.children && Array.isArray(block.children)) {
|
|
247
|
+
block.children.forEach((span: Record<string, any>) => {
|
|
248
|
+
if (span.marks && span.marks.length) {
|
|
249
|
+
origAnnotation = span;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
deserialized.content.forEach((block: PortableTextBlock) => {
|
|
256
|
+
if (block.children && Array.isArray(block.children)) {
|
|
257
|
+
block.children.forEach((span: Record<string, any>) => {
|
|
258
|
+
if (span.marks && span.marks.length) {
|
|
259
|
+
deserializedAnnotation = span;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
expect(deserializedAnnotation!.text).toEqual(origAnnotation!.text);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
/*
|
|
269
|
+
* STYLE TAGS
|
|
270
|
+
*/
|
|
271
|
+
test('Deserialized content should preserve style tags', () => {
|
|
272
|
+
const deserialized = getDeserialized(documentLevelArticle, 'document');
|
|
273
|
+
const origH1 = documentLevelArticle.content.find(
|
|
274
|
+
(block: PortableTextBlock) => block.style === 'h1'
|
|
275
|
+
);
|
|
276
|
+
const deserializedH1 = deserialized.content.find(
|
|
277
|
+
(block: PortableTextBlock) => block.style === 'h1'
|
|
278
|
+
);
|
|
279
|
+
const origH2 = documentLevelArticle.content.find(
|
|
280
|
+
(block: PortableTextBlock) => block.style === 'h2'
|
|
281
|
+
);
|
|
282
|
+
const deserializedH2 = deserialized.content.find(
|
|
283
|
+
(block: PortableTextBlock) => block.style === 'h2'
|
|
284
|
+
);
|
|
285
|
+
expect(deserializedH1).toBeDefined();
|
|
286
|
+
expect(deserializedH2).toBeDefined();
|
|
287
|
+
expect(deserializedH1._key).toEqual(origH1._key);
|
|
288
|
+
expect(deserializedH2._key).toEqual(origH2._key);
|
|
289
|
+
expect(deserializedH1.children[0].text).toEqual(origH1.children[0].text);
|
|
290
|
+
expect(deserializedH2.children[0].text).toEqual(origH2.children[0].text);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
/*
|
|
294
|
+
* LIST ITEMS
|
|
295
|
+
*/
|
|
296
|
+
test('Deserialized list items should preserve level, style and tag', () => {
|
|
297
|
+
const deserialized = getDeserialized(documentLevelArticle, 'document');
|
|
298
|
+
const origListItem = documentLevelArticle.content.find(
|
|
299
|
+
(block: PortableTextBlock) =>
|
|
300
|
+
block.listItem === 'bullet' && block.style === 'h2'
|
|
301
|
+
);
|
|
302
|
+
const deserializedListItem = deserialized.content.find(
|
|
303
|
+
(block: PortableTextBlock) =>
|
|
304
|
+
block.listItem === 'bullet' && block.style === 'h2'
|
|
305
|
+
);
|
|
306
|
+
const origNestedListItem = documentLevelArticle.content.find(
|
|
307
|
+
(block: PortableTextBlock) =>
|
|
308
|
+
block.listItem === 'bullet' && block.level === 2
|
|
309
|
+
);
|
|
310
|
+
const deserializedNestedListItem = deserialized.content.find(
|
|
311
|
+
(block: PortableTextBlock) =>
|
|
312
|
+
block.listItem === 'bullet' && block.level === 2
|
|
313
|
+
);
|
|
314
|
+
expect(deserializedListItem).toBeDefined();
|
|
315
|
+
expect(deserializedNestedListItem).toBeDefined();
|
|
316
|
+
expect(deserializedListItem._key).toEqual(origListItem._key);
|
|
317
|
+
expect(deserializedNestedListItem._key).toEqual(origNestedListItem._key);
|
|
318
|
+
expect(deserializedListItem.children[0].text).toEqual(
|
|
319
|
+
origListItem.children[0].text
|
|
320
|
+
);
|
|
321
|
+
expect(deserializedNestedListItem.children[0].text).toEqual(
|
|
322
|
+
origNestedListItem.children[0].text
|
|
323
|
+
);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
/*
|
|
327
|
+
* MESSY INPUT
|
|
328
|
+
*/
|
|
329
|
+
test(' whitespace should not be escaped', () => {
|
|
330
|
+
vi.spyOn(console, 'debug').mockImplementation(() => {});
|
|
331
|
+
|
|
332
|
+
const content = readFileSync(
|
|
333
|
+
'src/serialization/__tests__/__fixtures__/messy-html.html',
|
|
334
|
+
{
|
|
335
|
+
encoding: 'utf-8',
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
const result = BaseDocumentDeserializer.deserializeDocument(content);
|
|
339
|
+
expect(result.title).toEqual('Här är artikel titeln');
|
|
340
|
+
expect(result.content[1].nestedArrayField[0].title).toEqual(
|
|
341
|
+
'Det här är en dragspels titeln'
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
/*
|
|
346
|
+
* V2 functionality -- be able to operate without a strict schema
|
|
347
|
+
*/
|
|
348
|
+
test('Content with anonymous inline objects deserializes all fields, at any depth', () => {
|
|
349
|
+
vi.spyOn(console, 'debug').mockImplementation(() => {});
|
|
350
|
+
|
|
351
|
+
const serialized = BaseDocumentSerializer(inlineSchema).serializeDocument(
|
|
352
|
+
inlineDocumentLevelArticle,
|
|
353
|
+
'document'
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
357
|
+
serialized.content
|
|
358
|
+
);
|
|
359
|
+
//object in field
|
|
360
|
+
expect(deserialized.tabs.config.title).toEqual(
|
|
361
|
+
inlineDocumentLevelArticle.tabs.config.title
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
//array in object in object
|
|
365
|
+
expect(
|
|
366
|
+
deserialized.tabs.config.objectAsField.content[0].children[0].text
|
|
367
|
+
).toEqual(
|
|
368
|
+
inlineDocumentLevelArticle.tabs.config.objectAsField.content[0].children[0]
|
|
369
|
+
.text
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
//arrays
|
|
373
|
+
expect(deserialized.tabs.content).toBeInstanceOf(Array);
|
|
374
|
+
expect(deserialized.tabs.content.map((block: any) => block._key)).toEqual(
|
|
375
|
+
inlineDocumentLevelArticle.tabs.content.map((block: any) => block._key)
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
//object in array
|
|
379
|
+
const origObj = inlineDocumentLevelArticle.tabs.content.find(
|
|
380
|
+
(block: any) => block._type === 'objectField'
|
|
381
|
+
);
|
|
382
|
+
const deserializedObj = deserialized.tabs.content.find(
|
|
383
|
+
(block: any) => block._type === 'objectField'
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
expect(deserializedObj.title).toEqual(origObj.title);
|
|
387
|
+
expect(deserializedObj.objectAsField.content[0].children[0].text).toEqual(
|
|
388
|
+
origObj.objectAsField.content[0].children[0].text
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
//anonymous object in array
|
|
392
|
+
const origArray = inlineDocumentLevelArticle.tabs.arrayWithAnonymousObjects;
|
|
393
|
+
const deserializedArray = deserialized.tabs.arrayWithAnonymousObjects;
|
|
394
|
+
expect(deserializedArray.length).toEqual(origArray.length);
|
|
395
|
+
expect(deserializedArray[0]._key).toEqual(origArray[0]._key);
|
|
396
|
+
expect(Object.keys(deserializedArray[0])).not.toContain('span');
|
|
397
|
+
});
|
package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts
ADDED
|
@@ -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
|
+
});
|