gt-sanity 4.0.25 → 4.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +14 -3
- package/dist/index.js +249 -78
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/serialization/BaseDocumentMerger.ts +33 -1
- package/src/serialization/BaseSerializationConfig.ts +236 -46
- package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/documentLevelDeserialization.test.ts.snap +10 -10
- package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/fieldLevelDeserialization.test.ts.snap +4 -4
- package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +42 -1
- package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/documentLevelMerge.test.ts.snap +1 -1
- package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/fieldLevelMerge.test.ts.snap +1 -1
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentInlineMarks.test.ts.snap +51 -3
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentLevelSerialization.test.ts.snap +1 -1
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/fieldLevelSerialization.test.ts.snap +1 -1
- package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +17 -9
- package/src/serialization/__tests__/roundTrip.test.ts +1083 -0
- package/src/serialization/data.ts +16 -3
- package/src/serialization/deserialize/BaseDocumentDeserializer.ts +48 -10
- package/src/serialization/helpers.ts +98 -1
- package/src/serialization/serialize/index.ts +64 -57
- package/src/utils/serialize.ts +2 -0
package/dist/index.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export declare interface Adapter {
|
|
|
53
53
|
export declare function attachGTData(
|
|
54
54
|
html: string,
|
|
55
55
|
data: Record<string, unknown>,
|
|
56
|
-
type:
|
|
56
|
+
type: GTDataType,
|
|
57
57
|
): string;
|
|
58
58
|
|
|
59
59
|
export declare const BaseDocumentDeserializer: Deserializer;
|
|
@@ -82,7 +82,7 @@ export declare const BaseDocumentSerializer: (schemas: Schema) => {
|
|
|
82
82
|
baseLang: string,
|
|
83
83
|
) => Record<string, unknown>;
|
|
84
84
|
serializeArray: (
|
|
85
|
-
fieldContent:
|
|
85
|
+
fieldContent: unknown[],
|
|
86
86
|
fieldName: string,
|
|
87
87
|
stopTypes: string[],
|
|
88
88
|
serializers: Partial<PortableTextHtmlComponents>,
|
|
@@ -93,6 +93,7 @@ export declare const BaseDocumentSerializer: (schemas: Schema) => {
|
|
|
93
93
|
stopTypes: string[],
|
|
94
94
|
serializers: Partial<PortableTextHtmlComponents>,
|
|
95
95
|
declaredFields?: ObjectField[],
|
|
96
|
+
isDocument?: boolean,
|
|
96
97
|
) => string;
|
|
97
98
|
};
|
|
98
99
|
|
|
@@ -127,7 +128,7 @@ declare interface Deserializer {
|
|
|
127
128
|
|
|
128
129
|
export declare function detachGTData(html: string): {
|
|
129
130
|
html: string;
|
|
130
|
-
data?:
|
|
131
|
+
data?: GTData;
|
|
131
132
|
};
|
|
132
133
|
|
|
133
134
|
export { documentInternationalization };
|
|
@@ -186,6 +187,16 @@ export declare const findLatestDraft: (
|
|
|
186
187
|
|
|
187
188
|
declare const gt: GT;
|
|
188
189
|
|
|
190
|
+
declare type GTData = Record<"markDef", Record<string, unknown>> &
|
|
191
|
+
Partial<Record<"inlineObject", Record<string, unknown>>>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Kinds of Sanity data that can be carried on an element:
|
|
195
|
+
* - `markDef`: an annotation (e.g. a link) applied to the element's children
|
|
196
|
+
* - `inlineObject`: an inline object in a block's `children`, restored as-is
|
|
197
|
+
*/
|
|
198
|
+
declare type GTDataType = "markDef" | "inlineObject";
|
|
199
|
+
|
|
189
200
|
/**
|
|
190
201
|
* Field-level localization options. `gtPlugin` forwards these to
|
|
191
202
|
* `sanity-plugin-internationalized-array` — the reference Sanity plugin, which
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GT, getLocaleProperties } from "generaltranslation";
|
|
2
2
|
import { createDiagnosticMessage } from "generaltranslation/diagnostics";
|
|
3
|
-
import { createGtApiAdapter, defaultBaseUrl, libraryDefaultLocale,
|
|
3
|
+
import { createGtApiAdapter, defaultBaseUrl, libraryDefaultLocale, encode, decode } from "generaltranslation/internal";
|
|
4
4
|
import { useClient as useClient$1, useSchema, Preview, definePlugin } from "sanity";
|
|
5
5
|
import { useIntentLink, Link, route } from "sanity/router";
|
|
6
6
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
@@ -13,8 +13,8 @@ import { extractWithPath, arrayToJSONMatchPath } from "@sanity/mutator";
|
|
|
13
13
|
import { JSONPath } from "jsonpath-plus";
|
|
14
14
|
import JSONPointer from "jsonpointer";
|
|
15
15
|
import { htmlToBlocks } from "@portabletext/block-tools";
|
|
16
|
+
import { defaultComponents, toHTML } from "@portabletext/to-html";
|
|
16
17
|
import { Schema } from "@sanity/schema";
|
|
17
|
-
import { toHTML } from "@portabletext/to-html";
|
|
18
18
|
import merge from "lodash.merge";
|
|
19
19
|
import { Tooltip } from "@sanity/ui/tooltip";
|
|
20
20
|
import { Code } from "@sanity/ui/code";
|
|
@@ -213,7 +213,22 @@ const gtRadius = [0, 4, 6, 8, 12, 16, 24], baseTheme = buildTheme(), theme = {
|
|
|
213
213
|
!loadingSecrets && secrets && children
|
|
214
214
|
] });
|
|
215
215
|
return /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx(ToastProvider, { paddingY: 7, children: showContainer ? /* @__PURE__ */ jsx(Box, { padding, children: content }) : content }) });
|
|
216
|
-
}, isRecord$5 = (value) => typeof value == "object" && value !== null && !Array.isArray(value),
|
|
216
|
+
}, isRecord$5 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), withMarkDefOrder = (translatedBlock, origBlock) => {
|
|
217
|
+
if (!Array.isArray(translatedBlock.markDefs) || !Array.isArray(origBlock.markDefs))
|
|
218
|
+
return translatedBlock;
|
|
219
|
+
const origOrder = origBlock.markDefs.map(
|
|
220
|
+
(markDef) => isRecord$5(markDef) ? markDef._key : void 0
|
|
221
|
+
), position = (markDef) => {
|
|
222
|
+
const index = isRecord$5(markDef) ? origOrder.indexOf(markDef._key) : -1;
|
|
223
|
+
return index < 0 ? origOrder.length : index;
|
|
224
|
+
};
|
|
225
|
+
return {
|
|
226
|
+
...translatedBlock,
|
|
227
|
+
markDefs: [...translatedBlock.markDefs].sort(
|
|
228
|
+
(a, b) => position(a) - position(b)
|
|
229
|
+
)
|
|
230
|
+
};
|
|
231
|
+
}, reconcileArray = (origArray, translatedArray) => {
|
|
217
232
|
if (translatedArray && translatedArray.some((el) => typeof el == "string"))
|
|
218
233
|
return translatedArray;
|
|
219
234
|
const combined = JSON.parse(JSON.stringify(origArray));
|
|
@@ -227,7 +242,10 @@ const gtRadius = [0, 4, 6, 8, 12, 16, 24], baseTheme = buildTheme(), theme = {
|
|
|
227
242
|
`This block no longer exists on the original document. Was it removed? ${JSON.stringify(
|
|
228
243
|
translatedItem
|
|
229
244
|
)}`
|
|
230
|
-
) : isRecord$5(origArray[foundBlockIdx]) && (origArray[foundBlockIdx]._type === "block" || origArray[foundBlockIdx]._type === "span") ? combined[foundBlockIdx] =
|
|
245
|
+
) : isRecord$5(origArray[foundBlockIdx]) && (origArray[foundBlockIdx]._type === "block" || origArray[foundBlockIdx]._type === "span") ? combined[foundBlockIdx] = withMarkDefOrder(
|
|
246
|
+
translatedItem,
|
|
247
|
+
origArray[foundBlockIdx]
|
|
248
|
+
) : isRecord$5(origArray[foundBlockIdx]) && (combined[foundBlockIdx] = reconcileObject(
|
|
231
249
|
origArray[foundBlockIdx],
|
|
232
250
|
translatedItem
|
|
233
251
|
));
|
|
@@ -765,7 +783,34 @@ function detachGTData(html) {
|
|
|
765
783
|
data: extractedData
|
|
766
784
|
};
|
|
767
785
|
}
|
|
768
|
-
|
|
786
|
+
function mergeBlocks(blocks) {
|
|
787
|
+
const mergedBlock = { ...blocks[0] };
|
|
788
|
+
mergedBlock.markDefs = mergedBlock.markDefs ?? [];
|
|
789
|
+
for (const [idx, block] of blocks.entries())
|
|
790
|
+
idx !== 0 && (mergedBlock.children.push(...block.children), mergedBlock.markDefs.push(...block.markDefs ?? []));
|
|
791
|
+
mergedBlock._type = "block";
|
|
792
|
+
const seenMarkKeys = /* @__PURE__ */ new Set();
|
|
793
|
+
return mergedBlock.markDefs = mergedBlock.markDefs.filter((markDef) => seenMarkKeys.has(markDef._key) ? !1 : (seenMarkKeys.add(markDef._key), !0)), mergedBlock;
|
|
794
|
+
}
|
|
795
|
+
const htmlEscapes = {
|
|
796
|
+
"&": "&",
|
|
797
|
+
"<": "<",
|
|
798
|
+
">": ">",
|
|
799
|
+
'"': """
|
|
800
|
+
}, escapeHTML = (value) => value.replace(/[&<>"]/g, (char) => htmlEscapes[char]), SIGNIFICANT_WHITESPACE = /[\t\n\f\r]|^\s|\s$|\s\s/, STRING_ATTRIBUTE = "data-gt-string", LEADING_NEWLINES_ATTRIBUTE = "data-gt-leading-newlines", serializeString = (value, className, multiline = !1) => {
|
|
801
|
+
const classAttribute = className ? ` class="${className}"` : "";
|
|
802
|
+
if (!multiline && !SIGNIFICANT_WHITESPACE.test(value))
|
|
803
|
+
return `<span${classAttribute}>${escapeHTML(value)}</span>`;
|
|
804
|
+
const text = value.replace(/^\n+/, ""), leadingNewlines = value.length - text.length, leadingNewlinesAttribute = leadingNewlines ? ` ${LEADING_NEWLINES_ATTRIBUTE}="${leadingNewlines}"` : "";
|
|
805
|
+
return `<pre${classAttribute} ${STRING_ATTRIBUTE}=""${leadingNewlinesAttribute}>${escapeHTML(text)}</pre>`;
|
|
806
|
+
}, INLINE_OBJECT_KEY_FIELD = "__gtInlineObjectKey", restoreInlineObjectKeys = (block) => (block.children?.forEach(
|
|
807
|
+
(child) => {
|
|
808
|
+
INLINE_OBJECT_KEY_FIELD in child && (typeof child[INLINE_OBJECT_KEY_FIELD] == "string" && (child._key = child[INLINE_OBJECT_KEY_FIELD]), delete child[INLINE_OBJECT_KEY_FIELD]);
|
|
809
|
+
}
|
|
810
|
+
), block), MARKED_LINE_BREAK = "\uFDD0", restoreMarkedLineBreaks = (block) => (block.children?.forEach((child) => {
|
|
811
|
+
typeof child.text == "string" && (child.text = child.text.replaceAll(MARKED_LINE_BREAK, `
|
|
812
|
+
`));
|
|
813
|
+
}), block), isRecord$3 = (value) => typeof value == "object" && value !== null && !Array.isArray(value), defaultStopTypes = [
|
|
769
814
|
"reference",
|
|
770
815
|
"date",
|
|
771
816
|
"datetime",
|
|
@@ -779,7 +824,30 @@ const isRecord$3 = (value) => typeof value == "object" && value !== null && !Arr
|
|
|
779
824
|
"url",
|
|
780
825
|
"color",
|
|
781
826
|
"code"
|
|
782
|
-
],
|
|
827
|
+
], BUILTIN_ATTRIBUTE = "data-gt-builtin", annotationMark = (fallback) => (props) => {
|
|
828
|
+
const { value, children, markType } = props;
|
|
829
|
+
if (!(isRecord$3(value) && typeof value._key == "string"))
|
|
830
|
+
return fallback(props);
|
|
831
|
+
const href = markType === "link" && typeof value.href == "string" ? ` href="${escapeHTML(value.href)}"` : "", tag = markType === "link" ? "a" : "span";
|
|
832
|
+
return attachGTData(
|
|
833
|
+
`<${tag}${href} ${BUILTIN_ATTRIBUTE}="">${children}</${tag}>`,
|
|
834
|
+
value,
|
|
835
|
+
"markDef"
|
|
836
|
+
);
|
|
837
|
+
}, DECORATOR_ATTRIBUTE = "data-gt-decorator", decoratorMark = ({ children, markType }) => `<span ${DECORATOR_ATTRIBUTE}="${escapeHTML(markType)}">${children}</span>`, DECORATOR_ELEMENTS = {
|
|
838
|
+
sup: "sup",
|
|
839
|
+
sub: "sub",
|
|
840
|
+
u: "underline"
|
|
841
|
+
}, defaultMarks = {
|
|
842
|
+
link: annotationMark(
|
|
843
|
+
defaultComponents.marks.link
|
|
844
|
+
),
|
|
845
|
+
// annotations share the mark registry, so an annotation named like one of
|
|
846
|
+
// these decorators keeps its markDef
|
|
847
|
+
sup: annotationMark(({ children }) => `<sup>${children}</sup>`),
|
|
848
|
+
sub: annotationMark(({ children }) => `<sub>${children}</sub>`),
|
|
849
|
+
underline: annotationMark(({ children }) => `<u>${children}</u>`)
|
|
850
|
+
}, defaultPortableTextBlockStyles = {
|
|
783
851
|
normal: ({ value, children }) => `<p id="${value._key}">${children}</p>`,
|
|
784
852
|
blockquote: ({ value, children }) => `<blockquote id="${value._key}">${children}</blockquote>`,
|
|
785
853
|
h1: ({ value, children }) => `<h1 id="${value._key}">${children}</h1>`,
|
|
@@ -797,37 +865,102 @@ const isRecord$3 = (value) => typeof value == "object" && value !== null && !Arr
|
|
|
797
865
|
}) => {
|
|
798
866
|
const { _key, level } = value;
|
|
799
867
|
return `<li id="${(_key || "").replace("-parent", "")}" data-level="${level}">${children}</li>`;
|
|
800
|
-
}, unknownBlockFunc = ({ value, children }) => `<p id="${value._key}" data-type="unknown-block-style" data-style="${value.style}">${children}</p>`, customSerializers = {
|
|
801
|
-
|
|
868
|
+
}, unknownBlockFunc = ({ value, children }) => `<p id="${value._key}" data-type="unknown-block-style" data-style="${value.style}">${children}</p>`, INLINE_OBJECT_CONTENT = "\u200B", customSerializers = {
|
|
869
|
+
// Inline objects must stay inline: a <div> inside a <p> closes the
|
|
870
|
+
// paragraph and the rest of its text is dropped on import. The object is
|
|
871
|
+
// carried as data and restored by the inline-object rule below. The
|
|
872
|
+
// zero-width space keeps the span non-empty: HTML formatters (GT's
|
|
873
|
+
// included) collapse the spaces on both sides of an empty element into one.
|
|
874
|
+
unknownType: ({ value, isInline }) => isInline ? attachGTData(
|
|
875
|
+
`<span class="${escapeHTML(value._type)}">${INLINE_OBJECT_CONTENT}</span>`,
|
|
876
|
+
value,
|
|
877
|
+
"inlineObject"
|
|
878
|
+
) : `<div class="${escapeHTML(value._type)}"></div>`,
|
|
879
|
+
unknownMark: annotationMark(decoratorMark),
|
|
802
880
|
types: {},
|
|
803
881
|
marks: defaultMarks,
|
|
804
882
|
block: defaultPortableTextBlockStyles,
|
|
805
883
|
list: defaultLists,
|
|
806
884
|
listItem: defaultListItem,
|
|
807
885
|
unknownBlockStyle: unknownBlockFunc
|
|
808
|
-
}, customDeserializers = { types: {} },
|
|
809
|
-
|
|
886
|
+
}, customDeserializers = { types: {} }, MARK_ELEMENTS = /* @__PURE__ */ new Set([
|
|
887
|
+
"a",
|
|
888
|
+
"b",
|
|
889
|
+
"code",
|
|
890
|
+
"del",
|
|
891
|
+
"em",
|
|
892
|
+
"i",
|
|
893
|
+
"s",
|
|
894
|
+
"span",
|
|
895
|
+
"strike",
|
|
896
|
+
"strong",
|
|
897
|
+
"sub",
|
|
898
|
+
"sup",
|
|
899
|
+
"u"
|
|
900
|
+
]), markDefRule = (claims) => ({
|
|
901
|
+
deserialize(node, next) {
|
|
902
|
+
if (node.nodeType !== 1)
|
|
903
|
+
return;
|
|
904
|
+
const el = node;
|
|
905
|
+
if (!el.hasChildNodes() || !el.getAttribute("data-gt-internal") || !claims(el))
|
|
906
|
+
return;
|
|
907
|
+
const markDef = detachGTData(el.outerHTML).data?.markDef;
|
|
908
|
+
if (!(!isRecord$3(markDef) || typeof markDef._key != "string"))
|
|
909
|
+
return {
|
|
910
|
+
_type: "__annotation",
|
|
911
|
+
markDef,
|
|
912
|
+
children: next(el.childNodes)
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
}), decoratorRule = (decoratorName) => ({
|
|
916
|
+
deserialize(node, next) {
|
|
917
|
+
if (node.nodeType !== 1)
|
|
918
|
+
return;
|
|
919
|
+
const name = decoratorName(node);
|
|
920
|
+
if (name)
|
|
921
|
+
return {
|
|
922
|
+
_type: "__decorator",
|
|
923
|
+
name,
|
|
924
|
+
children: next(node.childNodes)
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
}), customBlockDeserializers = [
|
|
928
|
+
// keep whitespace-only text inside a mark (`Note:<strong> </strong>The`,
|
|
929
|
+
// or next to a nested mark: `<strong><em>Note:</em> </strong>The`):
|
|
930
|
+
// block-tools drops it and glues the words on either side together
|
|
810
931
|
{
|
|
811
|
-
deserialize(node
|
|
932
|
+
deserialize(node) {
|
|
933
|
+
const parent = node.parentElement;
|
|
934
|
+
if (!(node.nodeType !== 3 || !node.textContent || node.textContent.trim() || !parent || !MARK_ELEMENTS.has(parent.tagName.toLowerCase())))
|
|
935
|
+
return {
|
|
936
|
+
_type: "span",
|
|
937
|
+
marks: [],
|
|
938
|
+
text: node.textContent.replace(/[\t\n\f\r ]+/g, " ")
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
// handle inline objects with data-gt-internal
|
|
943
|
+
{
|
|
944
|
+
deserialize(node) {
|
|
812
945
|
if (node.nodeType !== 1)
|
|
813
946
|
return;
|
|
814
947
|
const el = node;
|
|
815
|
-
if (!el.
|
|
948
|
+
if (!el.getAttribute("data-gt-internal"))
|
|
816
949
|
return;
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
}), {
|
|
825
|
-
...block,
|
|
826
|
-
markDefs,
|
|
827
|
-
children
|
|
828
|
-
};
|
|
950
|
+
const inlineObject = detachGTData(el.outerHTML).data?.inlineObject;
|
|
951
|
+
if (!(!isRecord$3(inlineObject) || typeof inlineObject._type != "string"))
|
|
952
|
+
return {
|
|
953
|
+
...inlineObject,
|
|
954
|
+
_type: inlineObject._type,
|
|
955
|
+
[INLINE_OBJECT_KEY_FIELD]: inlineObject._key
|
|
956
|
+
};
|
|
829
957
|
}
|
|
830
958
|
},
|
|
959
|
+
// handle marks with data-gt-internal from a user's serializer
|
|
960
|
+
// (attachGTData); the built-in ones are in fallbackBlockDeserializers
|
|
961
|
+
markDefRule((el) => !el.hasAttribute(BUILTIN_ATTRIBUTE)),
|
|
962
|
+
// handle decorators, whether or not the generic import schema declares them
|
|
963
|
+
decoratorRule((el) => el.getAttribute(DECORATOR_ATTRIBUTE)),
|
|
831
964
|
//handle undeclared styles
|
|
832
965
|
{
|
|
833
966
|
deserialize(node, next) {
|
|
@@ -872,7 +1005,13 @@ const isRecord$3 = (value) => typeof value == "object" && value !== null && !Arr
|
|
|
872
1005
|
// @ts-ignore
|
|
873
1006
|
style: customStyle ?? newBlock.style
|
|
874
1007
|
}, customStyle))
|
|
875
|
-
return
|
|
1008
|
+
return {
|
|
1009
|
+
...block,
|
|
1010
|
+
level,
|
|
1011
|
+
_key,
|
|
1012
|
+
listItem,
|
|
1013
|
+
children: next(el.children[0].childNodes)
|
|
1014
|
+
};
|
|
876
1015
|
}
|
|
877
1016
|
return {
|
|
878
1017
|
...block,
|
|
@@ -883,21 +1022,45 @@ const isRecord$3 = (value) => typeof value == "object" && value !== null && !Arr
|
|
|
883
1022
|
};
|
|
884
1023
|
}
|
|
885
1024
|
}
|
|
886
|
-
]
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1025
|
+
], fallbackBlockDeserializers = [
|
|
1026
|
+
markDefRule((el) => el.hasAttribute(BUILTIN_ATTRIBUTE)),
|
|
1027
|
+
decoratorRule((el) => DECORATOR_ELEMENTS[el.tagName.toLowerCase()]),
|
|
1028
|
+
// a line break inside a mark (`<em>one<br>two</em>`) keeps that mark; one
|
|
1029
|
+
// between marks (`<em>one</em><br><em>two</em>`) stays unmarked
|
|
1030
|
+
{
|
|
1031
|
+
deserialize(node) {
|
|
1032
|
+
const parent = node.parentElement;
|
|
1033
|
+
if (!(node.nodeName !== "BR" || !parent || !MARK_ELEMENTS.has(parent.tagName.toLowerCase())))
|
|
1034
|
+
return {
|
|
1035
|
+
_type: "span",
|
|
1036
|
+
marks: [],
|
|
1037
|
+
text: MARKED_LINE_BREAK
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
], defaultBlockDeserializers = [
|
|
1042
|
+
...customBlockDeserializers,
|
|
1043
|
+
...fallbackBlockDeserializers
|
|
1044
|
+
], deserializeString = (element) => {
|
|
1045
|
+
const tagName = element.tagName?.toLowerCase();
|
|
1046
|
+
if (tagName === "pre" && element.hasAttribute(STRING_ATTRIBUTE)) {
|
|
1047
|
+
const text = (element.textContent ?? "").replace(/^\n+/, ""), leadingNewlines = Number.parseInt(
|
|
1048
|
+
element.getAttribute(LEADING_NEWLINES_ATTRIBUTE) ?? "",
|
|
1049
|
+
10
|
|
1050
|
+
) || 0;
|
|
1051
|
+
return `
|
|
1052
|
+
`.repeat(Math.max(leadingNewlines, 0)) + text;
|
|
1053
|
+
}
|
|
1054
|
+
if (tagName === "span")
|
|
1055
|
+
return preprocess(element.innerHTML);
|
|
1056
|
+
}, deserializeArray = (arrayHTML, deserializers = customDeserializers, blockDeserializers = defaultBlockDeserializers) => {
|
|
895
1057
|
const output = [];
|
|
896
1058
|
return Array.from(arrayHTML.children).forEach((child) => {
|
|
897
1059
|
let deserializedObject;
|
|
898
1060
|
try {
|
|
899
|
-
|
|
900
|
-
|
|
1061
|
+
const stringValue = deserializeString(child);
|
|
1062
|
+
if (stringValue !== void 0)
|
|
1063
|
+
deserializedObject = stringValue;
|
|
901
1064
|
else if (child.className || child.getAttribute("data-type") === "object")
|
|
902
1065
|
deserializedObject = deserializeObject(
|
|
903
1066
|
child,
|
|
@@ -908,8 +1071,10 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
908
1071
|
const blocks = htmlToBlocks(child.outerHTML, blockContentType, {
|
|
909
1072
|
rules: blockDeserializers
|
|
910
1073
|
});
|
|
911
|
-
deserializedObject =
|
|
912
|
-
|
|
1074
|
+
deserializedObject = restoreMarkedLineBreaks(
|
|
1075
|
+
restoreInlineObjectKeys(
|
|
1076
|
+
mergeBlocks(blocks)
|
|
1077
|
+
)
|
|
913
1078
|
), deserializedObject._key = child.id;
|
|
914
1079
|
}
|
|
915
1080
|
} catch (e) {
|
|
@@ -919,14 +1084,15 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
919
1084
|
}
|
|
920
1085
|
output.push(deserializedObject);
|
|
921
1086
|
}), output;
|
|
922
|
-
}, deserializeObject = (objectHTML, deserializers = customDeserializers, blockDeserializers =
|
|
1087
|
+
}, deserializeObject = (objectHTML, deserializers = customDeserializers, blockDeserializers = defaultBlockDeserializers) => {
|
|
923
1088
|
const deserialize = deserializers.types?.[objectHTML.className];
|
|
924
1089
|
if (deserialize)
|
|
925
1090
|
return deserialize(objectHTML);
|
|
926
1091
|
const output = {};
|
|
927
1092
|
return objectHTML.className && (output._type = objectHTML.className), Array.from(objectHTML.children).forEach((child) => {
|
|
928
|
-
|
|
929
|
-
|
|
1093
|
+
const stringValue = deserializeString(child);
|
|
1094
|
+
if (stringValue !== void 0)
|
|
1095
|
+
output[child.className] = stringValue;
|
|
930
1096
|
else if (child.getAttribute("data-level") === "field") {
|
|
931
1097
|
const deserialized = deserializeHTML(
|
|
932
1098
|
child.outerHTML,
|
|
@@ -951,7 +1117,7 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
951
1117
|
return deserialize ? output = deserialize(HTMLnode) : HTMLnode.getAttribute("data-type") === "object" ? output = deserializeObject(HTMLnode, deserializers, blockDeserializers) : HTMLnode.getAttribute("data-type") === "array" ? output = deserializeArray(HTMLnode, deserializers, blockDeserializers) : (output = {}, console.debug(
|
|
952
1118
|
`Tried to deserialize block ${HTMLnode.outerHTML} but failed to identify it!`
|
|
953
1119
|
)), output;
|
|
954
|
-
}, deserializeDocument$1 = (serializedDoc, deserializers = customDeserializers, blockDeserializers =
|
|
1120
|
+
}, deserializeDocument$1 = (serializedDoc, deserializers = customDeserializers, blockDeserializers = defaultBlockDeserializers) => {
|
|
955
1121
|
const metadata = {}, head = new DOMParser().parseFromString(serializedDoc, "text/html").head;
|
|
956
1122
|
return Array.from(head.children).forEach((metaTag) => {
|
|
957
1123
|
const validTags = ["_id", "_rev", "_type"], metaName = metaTag.getAttribute("name");
|
|
@@ -1059,7 +1225,27 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
1059
1225
|
if (typeDef.fields) return typeDef.fields;
|
|
1060
1226
|
current = typeof typeDef.type == "string" ? typeDef.type : void 0;
|
|
1061
1227
|
}
|
|
1062
|
-
},
|
|
1228
|
+
}, isTextType = (typeName) => {
|
|
1229
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1230
|
+
let current = typeName;
|
|
1231
|
+
for (; current && !seen.has(current); ) {
|
|
1232
|
+
if (current === "text") return !0;
|
|
1233
|
+
seen.add(current);
|
|
1234
|
+
const typeDef = getSchema(current);
|
|
1235
|
+
current = typeof typeDef?.type == "string" ? typeDef.type : void 0;
|
|
1236
|
+
}
|
|
1237
|
+
return !1;
|
|
1238
|
+
}, resolveArrayMembers = (fieldDef) => {
|
|
1239
|
+
if (fieldDef?.of) return fieldDef.of;
|
|
1240
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1241
|
+
let current = fieldDef?.type;
|
|
1242
|
+
for (; current && !seen.has(current); ) {
|
|
1243
|
+
seen.add(current);
|
|
1244
|
+
const typeDef = getSchema(current);
|
|
1245
|
+
if (typeDef?.of) return typeDef.of;
|
|
1246
|
+
current = typeof typeDef?.type == "string" ? typeDef.type : void 0;
|
|
1247
|
+
}
|
|
1248
|
+
}, serializeObject = (obj, stopTypes, serializers, declaredFields, isDocument = !1) => {
|
|
1063
1249
|
if (stopTypes.includes(obj._type) || isTypeExcludedByOptions(obj._type, getSchema))
|
|
1064
1250
|
return "";
|
|
1065
1251
|
const typeSerializers = isRecord$1(serializers.types) ? serializers.types : {};
|
|
@@ -1091,7 +1277,11 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
1091
1277
|
(field) => field.name === fieldName
|
|
1092
1278
|
);
|
|
1093
1279
|
if (typeof value == "string")
|
|
1094
|
-
|
|
1280
|
+
htmlField = serializeString(
|
|
1281
|
+
value,
|
|
1282
|
+
fieldName,
|
|
1283
|
+
isTextType(fieldDef?.type)
|
|
1284
|
+
);
|
|
1095
1285
|
else if (Array.isArray(value))
|
|
1096
1286
|
htmlField = serializeArray(
|
|
1097
1287
|
value,
|
|
@@ -1101,12 +1291,12 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
1101
1291
|
...serializers,
|
|
1102
1292
|
types: { ...typeSerializers }
|
|
1103
1293
|
},
|
|
1104
|
-
fieldDef
|
|
1294
|
+
resolveArrayMembers(fieldDef)
|
|
1105
1295
|
);
|
|
1106
1296
|
else if (isRecord$1(value)) {
|
|
1107
1297
|
const embeddedObject = value, embeddedFields = resolveSchemaFields(embeddedObject._type);
|
|
1108
1298
|
let toTranslate = embeddedObject;
|
|
1109
|
-
embeddedFields && (toTranslate = fieldFilter(
|
|
1299
|
+
embeddedFields && !isDocument && (toTranslate = fieldFilter(
|
|
1110
1300
|
toTranslate,
|
|
1111
1301
|
embeddedFields,
|
|
1112
1302
|
stopTypes,
|
|
@@ -1150,7 +1340,7 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
1150
1340
|
return serializedBlock;
|
|
1151
1341
|
}, serializeArray = (fieldContent, fieldName, stopTypes, serializers, memberDefs) => {
|
|
1152
1342
|
const validBlocks = fieldContent.filter(
|
|
1153
|
-
(block) => typeof block == "string" || typeof block._type != "string" || !stopTypes.includes(block._type)
|
|
1343
|
+
(block) => typeof block == "string" || isRecord$1(block) && (typeof block._type != "string" || !stopTypes.includes(block._type))
|
|
1154
1344
|
), declaredMemberFields = (blockType) => {
|
|
1155
1345
|
if (!memberDefs?.length) return;
|
|
1156
1346
|
const byName = memberDefs.find(
|
|
@@ -1160,7 +1350,11 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
1160
1350
|
if (!blockType && memberDefs.length === 1) return memberDefs[0].fields;
|
|
1161
1351
|
}, output = validBlocks.map((block) => {
|
|
1162
1352
|
if (typeof block == "string")
|
|
1163
|
-
return
|
|
1353
|
+
return serializeString(
|
|
1354
|
+
block,
|
|
1355
|
+
void 0,
|
|
1356
|
+
memberDefs?.some((def) => isTextType(def.type))
|
|
1357
|
+
);
|
|
1164
1358
|
const blockType = typeof block._type == "string" ? block._type : void 0, memberFields = resolveSchemaFields(blockType), filtered = memberFields ? fieldFilter(block, memberFields, stopTypes, getSchema) : block;
|
|
1165
1359
|
return serializeObject(
|
|
1166
1360
|
filtered,
|
|
@@ -1181,37 +1375,13 @@ const deserializeArray = (arrayHTML, deserializers = customDeserializers, blockD
|
|
|
1181
1375
|
stopTypes,
|
|
1182
1376
|
getSchema
|
|
1183
1377
|
);
|
|
1184
|
-
const serializedFields = {};
|
|
1185
|
-
for (const key in filteredObj) {
|
|
1186
|
-
if (filteredObj.hasOwnProperty(key) === !1) continue;
|
|
1187
|
-
const value = filteredObj[key], fieldDef = schema?.fields?.find((field) => field.name === key);
|
|
1188
|
-
if (typeof value == "string")
|
|
1189
|
-
serializedFields[key] = value;
|
|
1190
|
-
else if (Array.isArray(value))
|
|
1191
|
-
serializedFields[key] = serializeArray(
|
|
1192
|
-
value.filter(
|
|
1193
|
-
(item) => typeof item == "string" || isRecord$1(item)
|
|
1194
|
-
),
|
|
1195
|
-
key,
|
|
1196
|
-
stopTypes,
|
|
1197
|
-
serializers,
|
|
1198
|
-
fieldDef?.of
|
|
1199
|
-
);
|
|
1200
|
-
else if (value && isRecord$1(value) && !stopTypes.find((stopType) => stopType == value?._type)) {
|
|
1201
|
-
const serialized = serializeObject(
|
|
1202
|
-
value,
|
|
1203
|
-
stopTypes,
|
|
1204
|
-
serializers,
|
|
1205
|
-
fieldDef?.fields
|
|
1206
|
-
);
|
|
1207
|
-
serializedFields[key] = `<div class="${key}" data-level='field'>${serialized}</div>`;
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
1378
|
const rawHTMLBody = document.createElement("body");
|
|
1211
1379
|
rawHTMLBody.innerHTML = serializeObject(
|
|
1212
|
-
|
|
1380
|
+
filteredObj,
|
|
1213
1381
|
stopTypes,
|
|
1214
|
-
serializers
|
|
1382
|
+
serializers,
|
|
1383
|
+
void 0,
|
|
1384
|
+
!0
|
|
1215
1385
|
);
|
|
1216
1386
|
const rawHTMLHead = document.createElement("head");
|
|
1217
1387
|
["_id", "_type", "_rev"].forEach((field) => {
|
|
@@ -1255,7 +1425,8 @@ function deserializeDocument(document2) {
|
|
|
1255
1425
|
pluginConfig.getAdditionalDeserializers()
|
|
1256
1426
|
), blockDeserializers = [
|
|
1257
1427
|
...customBlockDeserializers,
|
|
1258
|
-
...pluginConfig.getAdditionalBlockDeserializers()
|
|
1428
|
+
...pluginConfig.getAdditionalBlockDeserializers(),
|
|
1429
|
+
...fallbackBlockDeserializers
|
|
1259
1430
|
];
|
|
1260
1431
|
return BaseDocumentDeserializer.deserializeDocument(
|
|
1261
1432
|
document2,
|
|
@@ -2746,7 +2917,7 @@ const useTranslations = () => {
|
|
|
2746
2917
|
] }) })
|
|
2747
2918
|
}
|
|
2748
2919
|
) : null;
|
|
2749
|
-
var version = "4.0.
|
|
2920
|
+
var version = "4.0.27";
|
|
2750
2921
|
function buildDebugInfo({
|
|
2751
2922
|
secrets,
|
|
2752
2923
|
preferences,
|