@prismicio/types-internal 2.2.0-traverse.alpha-6 → 2.2.0-traverse.alpha-8
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/lib/_internal/utils.d.ts +3 -6
- package/lib/content/Document.d.ts +1248 -32
- package/lib/content/Document.js +1 -1
- package/lib/content/fields/GroupContent.d.ts +273 -7
- package/lib/content/fields/WidgetContent.d.ts +1248 -32
- package/lib/content/fields/nestable/NestableContent.d.ts +156 -6
- package/lib/content/fields/nestable/NestableContent.js +1 -29
- package/lib/content/fields/nestable/RichTextContent/Blocks.d.ts +582 -28
- package/lib/content/fields/nestable/RichTextContent/Blocks.js +29 -46
- package/lib/content/fields/nestable/RichTextContent/index.d.ts +195 -5
- package/lib/content/fields/slices/Slice/CompositeSliceContent.d.ts +314 -10
- package/lib/content/fields/slices/Slice/CompositeSliceContent.js +18 -12
- package/lib/content/fields/slices/Slice/RepeatableContent.d.ts +117 -3
- package/lib/content/fields/slices/Slice/SharedSliceContent.d.ts +312 -8
- package/lib/content/fields/slices/Slice/SharedSliceContent.js +5 -1
- package/lib/content/fields/slices/Slice/SimpleSliceContent.d.ts +312 -8
- package/lib/content/fields/slices/Slice/SimpleSliceContent.js +1 -1
- package/lib/content/fields/slices/Slice/index.d.ts +702 -18
- package/lib/content/fields/slices/SliceItem.d.ts +702 -18
- package/lib/content/fields/slices/SlicesContent.d.ts +936 -24
- package/lib/content/fields/slices/SlicesContent.js +2 -4
- package/lib/customtypes/CustomType.d.ts +1 -1
- package/lib/customtypes/CustomType.js +3 -3
- package/lib/customtypes/widgets/slices/CompositeSlice.d.ts +0 -5
- package/lib/customtypes/widgets/slices/SharedSlice.d.ts +1 -2
- package/lib/import/converters/fields/nestable/GeoPoint.d.ts +3 -0
- package/lib/import/converters/fields/nestable/GeoPoint.js +15 -0
- package/lib/import/converters/fields/nestable/Image.d.ts +25 -3
- package/lib/import/converters/fields/nestable/Image.js +21 -25
- package/lib/import/converters/fields/nestable/RichText/embedBlock.d.ts +4 -0
- package/lib/import/converters/fields/nestable/RichText/embedBlock.js +14 -0
- package/lib/import/converters/fields/nestable/RichText/imageBlock.d.ts +4 -0
- package/lib/import/converters/fields/nestable/RichText/imageBlock.js +12 -0
- package/lib/import/converters/fields/nestable/RichText/index.d.ts +4 -0
- package/lib/import/converters/fields/nestable/RichText/index.js +22 -0
- package/lib/import/converters/fields/nestable/RichText/textBlock.d.ts +4 -0
- package/lib/import/converters/fields/nestable/RichText/textBlock.js +41 -0
- package/lib/import/converters/fields/nestable/index.d.ts +1 -1
- package/lib/import/converters/fields/nestable/index.js +1 -1
- package/lib/import/validators/fields/ImportContent.js +3 -3
- package/lib/import/validators/fields/ImportField.d.ts +1 -1
- package/lib/import/validators/fields/ImportSlices/ImportSlices.js +4 -3
- package/lib/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.js +1 -1
- package/lib/import/validators/fields/nestable/ImportRichText/ImportRichText.d.ts +1 -1
- package/lib/import/validators/fields/nestable/ImportRichText/ImportRichText.js +20 -14
- package/lib/import/validators/fields/nestable/ImportRichText/blocks/ImportImageBlock.d.ts +16 -2
- package/lib/import/validators/fields/nestable/ImportRichText/blocks/ImportImageBlock.js +7 -5
- package/lib/import/validators/fields/nestable/Nestable.d.ts +1 -1
- package/lib/validators/DefaultOrElse.js +3 -3
- package/package.json +1 -1
- package/src/_internal/utils.ts +3 -7
- package/src/content/Document.ts +2 -2
- package/src/content/fields/nestable/NestableContent.ts +0 -32
- package/src/content/fields/nestable/RichTextContent/Blocks.ts +48 -58
- package/src/content/fields/slices/Slice/CompositeSliceContent.ts +26 -16
- package/src/content/fields/slices/Slice/SharedSliceContent.ts +7 -1
- package/src/content/fields/slices/Slice/SimpleSliceContent.ts +1 -1
- package/src/content/fields/slices/SlicesContent.ts +4 -6
- package/src/customtypes/CustomType.ts +1 -1
- package/src/customtypes/widgets/slices/CompositeSlice.ts +0 -6
- package/src/customtypes/widgets/slices/SharedSlice.ts +2 -2
- package/src/import/converters/fields/nestable/Image.ts +10 -22
- package/src/import/converters/fields/nestable/RichText/embedBlock.ts +17 -0
- package/src/import/converters/fields/nestable/RichText/imageBlock.ts +17 -0
- package/src/import/converters/fields/nestable/RichText/index.ts +23 -0
- package/src/import/converters/fields/nestable/RichText/textBlock.ts +48 -0
- package/src/import/converters/fields/nestable/index.ts +1 -1
- package/src/import/validators/fields/ImportContent.ts +3 -3
- package/src/import/validators/fields/ImportSlices/ImportSlices.ts +7 -5
- package/src/import/validators/fields/ImportSlices/SharedSlice/fields/SharedSliceContent/SharedSliceContentEntry.ts +1 -1
- package/src/import/validators/fields/nestable/ImportRichText/ImportRichText.ts +38 -25
- package/src/import/validators/fields/nestable/ImportRichText/blocks/ImportImageBlock.ts +9 -5
- package/src/validators/DefaultOrElse.ts +4 -4
- package/src/import/converters/fields/nestable/RichText.ts +0 -62
- /package/src/import/converters/fields/nestable/{GeooPoint.ts → GeoPoint.ts} +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { isRight } from "fp-ts/lib/Either"
|
|
2
2
|
import * as t from "io-ts"
|
|
3
3
|
|
|
4
|
-
import type { NestableWidget } from "../../../customtypes"
|
|
5
4
|
import type { LegacyContentCtx } from "../../LegacyContentCtx"
|
|
6
5
|
import { EmptyContent, EmptyLegacy, isEmptyContent } from "../EmptyContent"
|
|
7
6
|
import {
|
|
@@ -201,34 +200,3 @@ export const NestableLegacy = (ctx: LegacyContentCtx) => {
|
|
|
201
200
|
},
|
|
202
201
|
}
|
|
203
202
|
}
|
|
204
|
-
|
|
205
|
-
export function isValidStaticNestableContent(
|
|
206
|
-
content: NestableContent,
|
|
207
|
-
model?: NestableWidget,
|
|
208
|
-
) {
|
|
209
|
-
if (!model) return false
|
|
210
|
-
|
|
211
|
-
switch (content.__TYPE__) {
|
|
212
|
-
// special case for no content so we can consider it valid no matter its model
|
|
213
|
-
case "EmptyContent":
|
|
214
|
-
return true
|
|
215
|
-
case "BooleanContent":
|
|
216
|
-
return model.type === "Boolean"
|
|
217
|
-
case "EmbedContent":
|
|
218
|
-
return model.type === "Embed"
|
|
219
|
-
case "FieldContent":
|
|
220
|
-
return content.type === model.type
|
|
221
|
-
case "GeoPointContent":
|
|
222
|
-
return model.type === "GeoPoint"
|
|
223
|
-
case "ImageContent":
|
|
224
|
-
return model.type === "Image"
|
|
225
|
-
case "IntegrationFieldsContent":
|
|
226
|
-
return model.type === "IntegrationFields"
|
|
227
|
-
case "LinkContent":
|
|
228
|
-
return model.type === "Link"
|
|
229
|
-
case "StructuredTextContent":
|
|
230
|
-
return model.type === "StructuredText"
|
|
231
|
-
case "SeparatorContent":
|
|
232
|
-
return model.type === "Separator"
|
|
233
|
-
}
|
|
234
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { either } from "fp-ts"
|
|
2
|
-
import {
|
|
2
|
+
import { isRight } from "fp-ts/lib/Either"
|
|
3
3
|
import { pipe } from "fp-ts/lib/function"
|
|
4
4
|
import * as t from "io-ts"
|
|
5
5
|
|
|
@@ -18,66 +18,54 @@ import {
|
|
|
18
18
|
import { ImageContentView } from "../ImageContent"
|
|
19
19
|
import { Link, LinkLegacy } from "../LinkContent"
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
t.
|
|
23
|
-
t.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return [...acc, { ...meta, data: decoded.right }]
|
|
56
|
-
} else if (meta.type !== "hyperlink") {
|
|
57
|
-
return [...acc, meta]
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return acc
|
|
21
|
+
const SpanFn = (linkCodec: typeof Link | typeof LinkLegacy) =>
|
|
22
|
+
t.exact(
|
|
23
|
+
t.intersection([
|
|
24
|
+
t.partial({
|
|
25
|
+
data: linkCodec,
|
|
26
|
+
}),
|
|
27
|
+
t.type({
|
|
28
|
+
start: t.number,
|
|
29
|
+
end: t.number,
|
|
30
|
+
type: t.union([RichTextNodeTypeCodec, t.literal("label")]),
|
|
31
|
+
}),
|
|
32
|
+
]),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
export const Span = SpanFn(Link)
|
|
36
|
+
export type Span = t.TypeOf<typeof Span>
|
|
37
|
+
|
|
38
|
+
export const SpanLegacy = SpanFn(LinkLegacy)
|
|
39
|
+
export type SpanLegacy = t.TypeOf<typeof SpanLegacy>
|
|
40
|
+
|
|
41
|
+
export const ValidatedSpans = <C extends typeof Span | typeof SpanLegacy>(
|
|
42
|
+
spanCodec: C,
|
|
43
|
+
) => {
|
|
44
|
+
type S = t.TypeOf<C>
|
|
45
|
+
|
|
46
|
+
return new t.Type<S[], S[], unknown>(
|
|
47
|
+
"ValidatedSpans",
|
|
48
|
+
(spans): spans is S[] => Array.isArray(spans) && spans.every(spanCodec.is),
|
|
49
|
+
(spans: unknown, c) => {
|
|
50
|
+
if (Array.isArray(spans)) {
|
|
51
|
+
const res = spans
|
|
52
|
+
.reduce<Array<S>>((acc, maybeSpan) => {
|
|
53
|
+
const decodedSpan = spanCodec.decode(maybeSpan)
|
|
54
|
+
return isRight(decodedSpan) ? [...acc, decodedSpan.right] : acc
|
|
61
55
|
}, [])
|
|
62
|
-
.sort((m1:
|
|
56
|
+
.sort((m1: S, m2: S) => m1.start - m2.start)
|
|
63
57
|
return t.success(res)
|
|
64
|
-
} else return t.failure(
|
|
58
|
+
} else return t.failure(spans, c)
|
|
65
59
|
},
|
|
66
60
|
(m) => {
|
|
67
|
-
return m.reduce<Array<
|
|
68
|
-
|
|
69
|
-
// since the Span data are typed as unknown we have to redecode for type safety and then encode to either new format or legacy.
|
|
70
|
-
const decoded = linkCodec.decode(meta.data)
|
|
71
|
-
if (isLeft(decoded)) return acc
|
|
72
|
-
|
|
73
|
-
return [...acc, { ...meta, data: linkCodec.encode(decoded.right) }]
|
|
74
|
-
}
|
|
75
|
-
return [...acc, Meta.encode(meta)]
|
|
61
|
+
return m.reduce<Array<S>>((acc, meta) => {
|
|
62
|
+
return [...acc, spanCodec.encode(meta)]
|
|
76
63
|
}, [])
|
|
77
64
|
},
|
|
78
65
|
)
|
|
66
|
+
}
|
|
79
67
|
|
|
80
|
-
const ImageBlockCodec = (linkCodec:
|
|
68
|
+
const ImageBlockCodec = (linkCodec: typeof Link | typeof LinkLegacy) =>
|
|
81
69
|
t.exact(
|
|
82
70
|
t.intersection([
|
|
83
71
|
t.type({
|
|
@@ -169,8 +157,9 @@ export function checkEmbedBlock(block: Block): block is EmbedBlock {
|
|
|
169
157
|
return block.type === RichTextNodeType.embed
|
|
170
158
|
}
|
|
171
159
|
|
|
172
|
-
|
|
173
|
-
|
|
160
|
+
const TextBlockCodec = <C extends typeof Span | typeof SpanLegacy>(
|
|
161
|
+
spanCodec: C,
|
|
162
|
+
) =>
|
|
174
163
|
t.exact(
|
|
175
164
|
t.intersection([
|
|
176
165
|
t.type({
|
|
@@ -184,7 +173,7 @@ const TextBlockCodec = (linkCodec: LinkCodec) =>
|
|
|
184
173
|
text: t.string,
|
|
185
174
|
}),
|
|
186
175
|
t.partial({
|
|
187
|
-
spans:
|
|
176
|
+
spans: ValidatedSpans(spanCodec),
|
|
188
177
|
}),
|
|
189
178
|
]),
|
|
190
179
|
}),
|
|
@@ -195,10 +184,11 @@ const TextBlockCodec = (linkCodec: LinkCodec) =>
|
|
|
195
184
|
]),
|
|
196
185
|
)
|
|
197
186
|
|
|
198
|
-
|
|
187
|
+
/* These Text block will decode codec A and encode from codec B to A */
|
|
188
|
+
export const TextBlock = TextBlockCodec(Span)
|
|
199
189
|
export type TextBlock = t.TypeOf<typeof TextBlock>
|
|
200
190
|
|
|
201
|
-
const TextBlockLegacy = TextBlockCodec(
|
|
191
|
+
const TextBlockLegacy = TextBlockCodec(SpanLegacy)
|
|
202
192
|
type TextBlockLegacy = t.TypeOf<typeof TextBlockLegacy>
|
|
203
193
|
|
|
204
194
|
const legacyBlockCodec = t.union([
|
|
@@ -8,10 +8,7 @@ import type {
|
|
|
8
8
|
TraverseSliceContentFn,
|
|
9
9
|
TraverseWidgetContentFn,
|
|
10
10
|
} from "../../../../_internal/utils"
|
|
11
|
-
import type {
|
|
12
|
-
CompositeSliceFields,
|
|
13
|
-
VariationFields,
|
|
14
|
-
} from "../../../../customtypes"
|
|
11
|
+
import type { CompositeSlice, VariationFields } from "../../../../customtypes"
|
|
15
12
|
import {
|
|
16
13
|
getFieldCtx,
|
|
17
14
|
LegacyContentCtx,
|
|
@@ -147,7 +144,7 @@ export function traverseCompositeSliceContent({
|
|
|
147
144
|
sliceKey: string
|
|
148
145
|
sliceName: string
|
|
149
146
|
content: CompositeSliceItemContent
|
|
150
|
-
model?: VariationFields |
|
|
147
|
+
model?: VariationFields | CompositeSlice | undefined
|
|
151
148
|
}) {
|
|
152
149
|
return (
|
|
153
150
|
transformWidget: TraverseWidgetContentFn,
|
|
@@ -159,7 +156,7 @@ export function traverseCompositeSliceContent({
|
|
|
159
156
|
const fieldDef = (() => {
|
|
160
157
|
return model?.type === "SharedSlice"
|
|
161
158
|
? model?.fields?.primary?.[fieldKey]
|
|
162
|
-
: model?.
|
|
159
|
+
: model?.["non-repeat"]?.[fieldKey]
|
|
163
160
|
})()
|
|
164
161
|
|
|
165
162
|
const transformedField = transformWidget({
|
|
@@ -173,7 +170,13 @@ export function traverseCompositeSliceContent({
|
|
|
173
170
|
content: fieldContent,
|
|
174
171
|
})
|
|
175
172
|
// Can happen if the transform function returns undefined to filter out a field
|
|
176
|
-
if (!transformedField
|
|
173
|
+
if (!transformedField) return acc
|
|
174
|
+
if (!isNestableContent(transformedField)) {
|
|
175
|
+
console.warn(
|
|
176
|
+
`Warn: Non nestable content with key [${fieldKey}] detected in a composite slice [${sliceName}] with key [${sliceKey}]`,
|
|
177
|
+
)
|
|
178
|
+
return acc
|
|
179
|
+
}
|
|
177
180
|
return {
|
|
178
181
|
...acc,
|
|
179
182
|
[fieldKey]: transformedField,
|
|
@@ -183,9 +186,7 @@ export function traverseCompositeSliceContent({
|
|
|
183
186
|
const items = traverseGroupItemsContent({
|
|
184
187
|
path: path.concat([{ key: "repeat", type: "items" }]),
|
|
185
188
|
model:
|
|
186
|
-
model?.type === "SharedSlice"
|
|
187
|
-
? model?.fields.items
|
|
188
|
-
: model?.fields.repeat,
|
|
189
|
+
model?.type === "SharedSlice" ? model?.fields.items : model?.repeat,
|
|
189
190
|
content: content.widget.repeat,
|
|
190
191
|
})(transformWidget)
|
|
191
192
|
|
|
@@ -219,9 +220,14 @@ export function migrateCompositeSlice(
|
|
|
219
220
|
variation: model.variationId,
|
|
220
221
|
primary: Object.entries(content.widget.nonRepeat).reduce(
|
|
221
222
|
(acc, [fieldKey, fieldContent]) => {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
if (!model.fields.primary?.[fieldKey]) {
|
|
224
|
+
console.warn(
|
|
225
|
+
`The widget ${fieldKey} in the non-repeat zone of the composite slice [${model.sliceName}] with key [${content.key}] doesn't exist in the model.`,
|
|
226
|
+
)
|
|
227
|
+
return acc
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { ...acc, [fieldKey]: fieldContent }
|
|
225
231
|
},
|
|
226
232
|
{},
|
|
227
233
|
),
|
|
@@ -230,9 +236,13 @@ export function migrateCompositeSlice(
|
|
|
230
236
|
__TYPE__: "GroupItemContent",
|
|
231
237
|
value: groupItem.value.reduce<GroupItemContent["value"]>(
|
|
232
238
|
(acc, [fieldKey, fieldContent]) => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
239
|
+
if (!model.fields.items?.[fieldKey]) {
|
|
240
|
+
console.warn(
|
|
241
|
+
`The widget ${fieldKey} in the repeat zone of the composite slice [${model.sliceName}] with key [${content.key}] doesn't exist in the model.`,
|
|
242
|
+
)
|
|
243
|
+
return acc
|
|
244
|
+
}
|
|
245
|
+
return acc.concat([[fieldKey, fieldContent]])
|
|
236
246
|
},
|
|
237
247
|
[],
|
|
238
248
|
),
|
|
@@ -174,7 +174,13 @@ export function traverseSharedSliceContent({
|
|
|
174
174
|
content: fieldContent,
|
|
175
175
|
})
|
|
176
176
|
// Can happen if the transform function returns undefined to filter out a field
|
|
177
|
-
if (!transformedField
|
|
177
|
+
if (!transformedField) return acc
|
|
178
|
+
if (!isNestableContent(transformedField)) {
|
|
179
|
+
console.warn(
|
|
180
|
+
`Warn: Non nestable content with key [${fieldKey}] detected in a shared slice [${sliceName}] with key [${sliceKey}]`,
|
|
181
|
+
)
|
|
182
|
+
return acc
|
|
183
|
+
}
|
|
178
184
|
return {
|
|
179
185
|
...acc,
|
|
180
186
|
[fieldKey]: transformedField,
|
|
@@ -168,7 +168,7 @@ export function migrateSimpleSlice(
|
|
|
168
168
|
__TYPE__: "SharedSliceContent",
|
|
169
169
|
variation: model.variationId,
|
|
170
170
|
primary: model.fields.primary?.[content.name]
|
|
171
|
-
? { [content.
|
|
171
|
+
? { [content.name]: content.widget }
|
|
172
172
|
: {},
|
|
173
173
|
items: [],
|
|
174
174
|
},
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "../../../_internal/utils"
|
|
11
11
|
import {
|
|
12
12
|
type StaticSlices,
|
|
13
|
-
|
|
13
|
+
CompositeSlice,
|
|
14
14
|
Group,
|
|
15
15
|
isCompositeSlice,
|
|
16
16
|
isLegacySlice,
|
|
@@ -146,7 +146,7 @@ function findSliceModel(
|
|
|
146
146
|
|
|
147
147
|
const legacySliceModel = ():
|
|
148
148
|
| NestableWidget
|
|
149
|
-
|
|
|
149
|
+
| CompositeSlice
|
|
150
150
|
| Group
|
|
151
151
|
| undefined => {
|
|
152
152
|
if (!defaultModel) return
|
|
@@ -154,10 +154,8 @@ function findSliceModel(
|
|
|
154
154
|
if (isCompositeSlice(defaultModel)) {
|
|
155
155
|
return {
|
|
156
156
|
type: "Slice",
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
repeat: defaultModel.repeat || {},
|
|
160
|
-
},
|
|
157
|
+
"non-repeat": defaultModel["non-repeat"] || {},
|
|
158
|
+
repeat: defaultModel.repeat || {},
|
|
161
159
|
}
|
|
162
160
|
}
|
|
163
161
|
if (isLegacySlice(defaultModel)) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as t from "io-ts"
|
|
2
2
|
|
|
3
|
-
import type { PickOnly } from "../../../_internal/utils"
|
|
4
3
|
import { WidgetKey } from "../../../common"
|
|
5
4
|
import { StringOrNull } from "../../../validators"
|
|
6
5
|
import { NestableWidget } from "../nestable/NestableWidget"
|
|
@@ -33,11 +32,6 @@ export const CompositeSlice = t.exact(
|
|
|
33
32
|
)
|
|
34
33
|
export type CompositeSlice = t.TypeOf<typeof CompositeSlice>
|
|
35
34
|
|
|
36
|
-
export type CompositeSliceFields = {
|
|
37
|
-
type: "Slice"
|
|
38
|
-
fields: PickOnly<CompositeSlice, "non-repeat" | "repeat">
|
|
39
|
-
}
|
|
40
|
-
|
|
41
35
|
export function isCompositeSlice(
|
|
42
36
|
slice: DynamicSlice | StaticSlice,
|
|
43
37
|
): slice is CompositeSlice {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as t from "io-ts"
|
|
2
2
|
import { withFallback } from "io-ts-types/lib/withFallback"
|
|
3
3
|
|
|
4
|
-
import type { PickOnly } from "../../../_internal/utils"
|
|
5
4
|
import { WidgetKey } from "../../../common"
|
|
6
5
|
import { NestableWidget } from "../nestable/NestableWidget"
|
|
7
6
|
import type { SharedSliceRef } from "./SharedSliceRef"
|
|
@@ -30,11 +29,12 @@ export const Variation = t.exact(
|
|
|
30
29
|
|
|
31
30
|
export type Variation = t.TypeOf<typeof Variation>
|
|
32
31
|
|
|
32
|
+
// VariationFields is used exclusively for the slices migration, LegacySlice -> SharedSlice
|
|
33
33
|
export type VariationFields = {
|
|
34
34
|
type: "SharedSlice"
|
|
35
35
|
sliceName: string
|
|
36
36
|
variationId: string
|
|
37
|
-
fields:
|
|
37
|
+
fields: Pick<Variation, "primary" | "items">
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export const SharedSliceType = "SharedSlice"
|
|
@@ -5,22 +5,20 @@ import { withOptionals } from "../../../../utils/Objects"
|
|
|
5
5
|
import type { ImageField, ImportImage } from "../../../validators"
|
|
6
6
|
import type { ImportImageBlock } from "../../../validators/fields/nestable/ImportRichText/blocks"
|
|
7
7
|
|
|
8
|
-
function
|
|
8
|
+
export function convertImageView<Input extends ImageField | ImportImageBlock>(
|
|
9
9
|
inputImage: Input,
|
|
10
10
|
image: Asset,
|
|
11
11
|
) {
|
|
12
12
|
// We can do that because anyway all properties being read
|
|
13
13
|
const imageField: ImageField = {
|
|
14
14
|
...inputImage,
|
|
15
|
-
edit:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
dimensions: "dimensions" in inputImage ? inputImage.dimensions : {},
|
|
15
|
+
edit: {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0,
|
|
18
|
+
zoom: 1,
|
|
19
|
+
...inputImage.edit,
|
|
20
|
+
},
|
|
21
|
+
dimensions: inputImage.dimensions ?? {},
|
|
24
22
|
}
|
|
25
23
|
return withOptionals<ImageContentView>(
|
|
26
24
|
{
|
|
@@ -64,7 +62,7 @@ function convertThumbnails(
|
|
|
64
62
|
(acc, [thumbnailName, thumbnail]) => {
|
|
65
63
|
return {
|
|
66
64
|
...acc,
|
|
67
|
-
[thumbnailName]:
|
|
65
|
+
[thumbnailName]: convertImageView(
|
|
68
66
|
thumbnail,
|
|
69
67
|
getAssetOrThrow(assets)(thumbnail.id),
|
|
70
68
|
),
|
|
@@ -74,16 +72,6 @@ function convertThumbnails(
|
|
|
74
72
|
)
|
|
75
73
|
}
|
|
76
74
|
|
|
77
|
-
export const imageBlockConverter = (
|
|
78
|
-
imageBlock: ImportImageBlock,
|
|
79
|
-
assets: Record<Asset["id"], Asset | undefined>,
|
|
80
|
-
): ImageContentView => {
|
|
81
|
-
return convertImage<ImportImageBlock>(
|
|
82
|
-
imageBlock,
|
|
83
|
-
getAssetOrThrow(assets)(imageBlock.id),
|
|
84
|
-
)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
75
|
// All assets from `imageField` must be present in `assets`
|
|
88
76
|
// If not then function will throw an error
|
|
89
77
|
export const imageConverter = (
|
|
@@ -93,7 +81,7 @@ export const imageConverter = (
|
|
|
93
81
|
if (!imageField) return
|
|
94
82
|
|
|
95
83
|
return {
|
|
96
|
-
...
|
|
84
|
+
...convertImageView<ImageField>(
|
|
97
85
|
imageField,
|
|
98
86
|
getAssetOrThrow(assets)(imageField.id),
|
|
99
87
|
),
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Embed } from "../../../../../common"
|
|
2
|
+
import type { EmbedBlock } from "../../../../../content"
|
|
3
|
+
import type { ImportEmbedBlock } from "../../../../validators/fields/nestable/ImportRichText/blocks"
|
|
4
|
+
import { embedConverter } from "../Embed"
|
|
5
|
+
|
|
6
|
+
export function embedBlockConverter(
|
|
7
|
+
block: ImportEmbedBlock,
|
|
8
|
+
embeds: Record<string, Embed | undefined>,
|
|
9
|
+
): EmbedBlock {
|
|
10
|
+
const embedData = embedConverter(block.oembed, embeds)
|
|
11
|
+
|
|
12
|
+
if (!embedData) throw new Error("Failed to convert embed data")
|
|
13
|
+
return {
|
|
14
|
+
type: block.type,
|
|
15
|
+
data: embedData,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Asset, getAssetOrThrow } from "../../../../../common"
|
|
2
|
+
import type { ImageBlock } from "../../../../../content"
|
|
3
|
+
import type { ImportImageBlock } from "../../../../validators/fields/nestable/ImportRichText/blocks"
|
|
4
|
+
import { convertImageView } from "../Image"
|
|
5
|
+
|
|
6
|
+
export function imageBlockConverter(
|
|
7
|
+
block: ImportImageBlock,
|
|
8
|
+
assets: Record<Asset["id"], Asset | undefined>,
|
|
9
|
+
): ImageBlock {
|
|
10
|
+
return {
|
|
11
|
+
type: block.type,
|
|
12
|
+
data: convertImageView<ImportImageBlock>(
|
|
13
|
+
block,
|
|
14
|
+
getAssetOrThrow(assets)(block.id),
|
|
15
|
+
),
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Asset, Embed } from "../../../../../common"
|
|
2
|
+
import type { RichTextContent } from "../../../../../content"
|
|
3
|
+
import { RichTextContentType } from "../../../../../content"
|
|
4
|
+
import type { ImportRichText } from "../../../../validators"
|
|
5
|
+
import { embedBlockConverter } from "./embedBlock"
|
|
6
|
+
import { imageBlockConverter } from "./imageBlock"
|
|
7
|
+
import { textBlockConverter } from "./textBlock"
|
|
8
|
+
|
|
9
|
+
export const richTextConverter = (
|
|
10
|
+
richTextField: ImportRichText["value"],
|
|
11
|
+
assets: Record<Asset["id"], Asset | undefined>,
|
|
12
|
+
embeds: Record<string, Embed | undefined>,
|
|
13
|
+
): RichTextContent | undefined => {
|
|
14
|
+
if (richTextField === null) return
|
|
15
|
+
return {
|
|
16
|
+
__TYPE__: RichTextContentType,
|
|
17
|
+
value: richTextField.map((block) => {
|
|
18
|
+
if (block.type === "image") return imageBlockConverter(block, assets)
|
|
19
|
+
else if (block.type === "embed") return embedBlockConverter(block, embeds)
|
|
20
|
+
return textBlockConverter(block, assets)
|
|
21
|
+
}),
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Asset } from "../../../../../common"
|
|
2
|
+
import type { TextBlock } from "../../../../../content"
|
|
3
|
+
import type { ImportTextBlock } from "../../../../validators/fields/nestable/ImportRichText/blocks"
|
|
4
|
+
import { linkConverter } from "../Link"
|
|
5
|
+
|
|
6
|
+
export function textBlockConverter(
|
|
7
|
+
block: ImportTextBlock,
|
|
8
|
+
assets: Record<Asset["id"], Asset | undefined>,
|
|
9
|
+
): TextBlock {
|
|
10
|
+
return {
|
|
11
|
+
type: block.type,
|
|
12
|
+
content: {
|
|
13
|
+
text: block.text,
|
|
14
|
+
...(() => {
|
|
15
|
+
if (block.spans) {
|
|
16
|
+
const convertedSpans = spansConverter(block.spans, assets)
|
|
17
|
+
if (!convertedSpans) return {}
|
|
18
|
+
|
|
19
|
+
return { spans: convertedSpans }
|
|
20
|
+
}
|
|
21
|
+
return {}
|
|
22
|
+
})(),
|
|
23
|
+
},
|
|
24
|
+
...(block.direction ? { direction: block.direction } : {}),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function spansConverter(
|
|
29
|
+
spans: NonNullable<ImportTextBlock["spans"]>,
|
|
30
|
+
assets: Record<Asset["id"], Asset | undefined>,
|
|
31
|
+
): TextBlock["content"]["spans"] {
|
|
32
|
+
return spans.map((span) => {
|
|
33
|
+
return {
|
|
34
|
+
type: span.type,
|
|
35
|
+
start: span.start,
|
|
36
|
+
end: span.end,
|
|
37
|
+
...(() => {
|
|
38
|
+
if (span.type === "hyperlink") {
|
|
39
|
+
const convertedLinkContent = linkConverter(span.data, assets)
|
|
40
|
+
if (!convertedLinkContent) return {}
|
|
41
|
+
|
|
42
|
+
return { data: convertedLinkContent?.value }
|
|
43
|
+
}
|
|
44
|
+
return {}
|
|
45
|
+
})(),
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
}
|
|
@@ -10,14 +10,14 @@ export const ImportContent = <T extends FieldType, A, O = A>(
|
|
|
10
10
|
valueCodec: t.Type<A, O>,
|
|
11
11
|
) =>
|
|
12
12
|
new t.Type<{ type: T; value: A }, O>(
|
|
13
|
-
|
|
13
|
+
`ImportField: ${valueCodec.name}`,
|
|
14
14
|
(u: unknown): u is { type: T; value: A } => {
|
|
15
15
|
if (!isObject(u)) return false
|
|
16
16
|
return type === u["type"] && valueCodec.is(u["value"])
|
|
17
17
|
},
|
|
18
|
-
(u: unknown) => {
|
|
18
|
+
(u: unknown, c) => {
|
|
19
19
|
return pipe(
|
|
20
|
-
valueCodec.
|
|
20
|
+
valueCodec.validate(u, c),
|
|
21
21
|
either.map((decodedValue) => {
|
|
22
22
|
return {
|
|
23
23
|
type,
|
|
@@ -3,7 +3,7 @@ import { pipe } from "fp-ts/function"
|
|
|
3
3
|
import * as t from "io-ts"
|
|
4
4
|
|
|
5
5
|
import type { StaticSlices } from "../../../../customtypes"
|
|
6
|
-
import {
|
|
6
|
+
import { EmptyArrayOrElse } from "../../../../validators"
|
|
7
7
|
import { ImportContent } from "../ImportContent"
|
|
8
8
|
import { SharedSlice } from "./SharedSlice"
|
|
9
9
|
import {
|
|
@@ -16,13 +16,14 @@ export const ImportSlices = (staticSlices: StaticSlices) => {
|
|
|
16
16
|
|
|
17
17
|
// For now we only support the SharedSlice, however if we want to support more in the future
|
|
18
18
|
// we would have to change the codec here to something like this: t.array(t.union([ImportSharedSlice(sharedSlices), NewSliceCodec(newSliceCustomTypes)])).
|
|
19
|
-
const
|
|
19
|
+
const SharedSliceCodec = SharedSlice(supportedSlices)
|
|
20
|
+
const SlicesArrayCodec = t.array(SharedSliceCodec)
|
|
20
21
|
|
|
21
22
|
return ImportContent(
|
|
22
23
|
"Slices",
|
|
23
|
-
|
|
24
|
-
new t.
|
|
25
|
-
|
|
24
|
+
EmptyArrayOrElse(
|
|
25
|
+
new t.ArrayType<typeof SharedSliceCodec, SharedSlice[]>(
|
|
26
|
+
SlicesArrayCodec.name,
|
|
26
27
|
(u): u is SharedSlice[] => SlicesArrayCodec.is(u),
|
|
27
28
|
(u, c) => {
|
|
28
29
|
return pipe(
|
|
@@ -46,6 +47,7 @@ export const ImportSlices = (staticSlices: StaticSlices) => {
|
|
|
46
47
|
)
|
|
47
48
|
},
|
|
48
49
|
t.identity,
|
|
50
|
+
SharedSliceCodec,
|
|
49
51
|
),
|
|
50
52
|
),
|
|
51
53
|
)
|
|
@@ -83,8 +83,8 @@ export const SharedSliceContentEntry = (
|
|
|
83
83
|
errors.map((error) => {
|
|
84
84
|
const context = [
|
|
85
85
|
...c,
|
|
86
|
-
...error.context.filter(({ key }) => !!key), // We replace the "" key coming from ImportNestable decoder
|
|
87
86
|
{ key, actual: content, type: codec },
|
|
87
|
+
...error.context.slice(1), // We ignore the first context element with "" key coming from ImportNestable decoder
|
|
88
88
|
]
|
|
89
89
|
|
|
90
90
|
const updatedError: t.ValidationError = { ...error, context }
|