@apollohg/react-native-rich-text-editor 2.0.0 → 2.0.1
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/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/android/build.gradle +3 -0
- package/app.plugin.js +42 -39
- package/dist/AtomHost.js +18 -11
- package/dist/EditorAddon.js +4 -2
- package/dist/EditorAddonNormalization.js +17 -9
- package/dist/EditorMentionThemeNormalization.js +6 -3
- package/dist/EditorMentionThemeValidation.js +28 -11
- package/dist/EditorStyleSheetNormalization.js +84 -37
- package/dist/EditorTheme.d.ts +4 -0
- package/dist/EditorTheme.js +5 -3
- package/dist/EditorToolbarComponent.d.ts +1 -1
- package/dist/EditorToolbarComponent.js +1 -1
- package/dist/EditorToolbarRegistry.js +5 -5
- package/dist/EditorToolbarTypes.d.ts +12 -12
- package/dist/EditorToolbarVisuals.js +1 -1
- package/dist/ExternalTextComposition.js +89 -43
- package/dist/ImageLoadingPolicy.d.ts +1 -1
- package/dist/NativeEditorBoundaryError.d.ts +7 -7
- package/dist/NativeEditorBoundaryError.js +9 -5
- package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
- package/dist/NativeEditorCollaborationTransport.js +28 -15
- package/dist/NativeEditorCreateConfig.js +11 -6
- package/dist/NativeEditorCreateJson.js +51 -25
- package/dist/NativeEditorCreateValidation.js +11 -6
- package/dist/NativeEditorDocumentBridge.d.ts +1 -1
- package/dist/NativeEditorDocumentBridge.js +32 -18
- package/dist/NativeEditorDocumentHandle.d.ts +4 -4
- package/dist/NativeEditorDocumentHandle.js +1 -1
- package/dist/NativeEditorLocalAwareness.js +25 -13
- package/dist/NativeEditorNativeModule.d.ts +8 -1
- package/dist/NativeEditorNativeModule.js +7 -5
- package/dist/NativeEditorRenderNormalization.js +66 -25
- package/dist/NativeEditorResultNormalization.js +53 -29
- package/dist/NativeEditorTypes.d.ts +10 -10
- package/dist/NativeEditorV2Decimal.js +6 -3
- package/dist/NativeProseViewer.js +11 -3
- package/dist/ResourceLimits.d.ts +2 -2
- package/dist/ResourceLimits.js +7 -2
- package/dist/RichTextEditor.js +1 -1
- package/dist/RichTextEditorNativeTypes.d.ts +1 -1
- package/dist/RichTextEditorNativeView.d.ts +1 -3
- package/dist/RichTextEditorSerialization.js +24 -14
- package/dist/RichTextEditorTypes.d.ts +1 -1
- package/dist/YjsCollaboration.d.ts +7 -7
- package/dist/YjsCollaboration.js +42 -26
- package/dist/addons.d.ts +4 -4
- package/dist/addons.js +3 -3
- package/dist/atomInstances.js +6 -3
- package/dist/atomUpdates.js +7 -4
- package/dist/atoms.js +20 -12
- package/dist/attributeValidation.js +55 -24
- package/dist/contentExpression.js +80 -42
- package/dist/listMarkers.d.ts +1 -1
- package/dist/listMarkers.js +1 -1
- package/dist/schemaDefinition.d.ts +1 -1
- package/dist/schemaDefinition.js +23 -14
- package/dist/schemaDocument.js +1 -1
- package/dist/schemaDocumentConstruction.js +25 -14
- package/dist/schemaNormalization.js +51 -29
- package/dist/schemaPresets.d.ts +1 -1
- package/dist/schemaPresets.js +9 -4
- package/dist/schemaResolution.js +46 -25
- package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
- package/dist/useEditorToolbarInteractions.d.ts +2 -2
- package/dist/useEditorToolbarInteractions.js +45 -23
- package/dist/useEditorToolbarItems.d.ts +1 -1
- package/dist/useEditorToolbarItems.js +4 -3
- package/dist/useEditorToolbarPresentation.d.ts +3 -3
- package/dist/useEditorToolbarPresentation.js +4 -4
- package/dist/useEditorToolbarState.d.ts +1 -1
- package/dist/useEditorToolbarState.js +1 -1
- package/dist/useFocusPreservingFrames.js +11 -8
- package/dist/useNativeEditor.d.ts +1 -1
- package/dist/useNativeEditor.js +21 -11
- package/dist/useRichTextEditorCommands.d.ts +2 -2
- package/dist/useRichTextEditorCommands.js +59 -29
- package/dist/useRichTextEditorEvents.d.ts +3 -3
- package/dist/useRichTextEditorEvents.js +75 -32
- package/dist/useRichTextEditorMentions.d.ts +4 -4
- package/dist/useRichTextEditorMentions.js +48 -29
- package/dist/useRichTextEditorPresentation.d.ts +4 -4
- package/dist/useRichTextEditorPresentation.js +25 -23
- package/dist/useRichTextEditorState.d.ts +3 -3
- package/dist/useRichTextEditorState.js +20 -15
- package/dist/useRichTextEditorUpdates.d.ts +1 -1
- package/dist/useRichTextEditorUpdates.js +99 -41
- package/dist/useViewerAtoms.js +63 -36
- package/ios/EditorCore.xcframework/Info.plist +5 -5
- package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
- package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
- package/package.json +11 -3
- package/react-native.config.js +1 -1
- package/rust/android/arm64-v8a/libeditor_core.so +0 -0
- package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
- package/rust/android/x86/libeditor_core.so +0 -0
- package/rust/android/x86_64/libeditor_core.so +0 -0
- package/src/AtomHost.tsx +58 -28
- package/src/EditorAddon.ts +18 -8
- package/src/EditorAddonNormalization.ts +40 -11
- package/src/EditorMentionThemeNormalization.ts +15 -4
- package/src/EditorMentionThemeValidation.ts +51 -14
- package/src/EditorStyleSheet.ts +1 -0
- package/src/EditorStyleSheetNormalization.ts +195 -64
- package/src/EditorTheme.ts +13 -5
- package/src/EditorToolbarComponent.tsx +2 -1
- package/src/EditorToolbarRegistry.tsx +23 -13
- package/src/EditorToolbarTypes.tsx +12 -12
- package/src/EditorToolbarVisuals.tsx +6 -3
- package/src/EditorUpdateRevision.ts +1 -0
- package/src/ExternalTextComposition.ts +259 -49
- package/src/ImageLoadingPolicy.ts +3 -1
- package/src/NativeEditorBoundaryError.ts +38 -11
- package/src/NativeEditorCollaborationTransport.ts +108 -27
- package/src/NativeEditorCreateConfig.ts +92 -19
- package/src/NativeEditorCreateJson.ts +163 -26
- package/src/NativeEditorCreateValidation.ts +33 -12
- package/src/NativeEditorDocumentBridge.ts +111 -19
- package/src/NativeEditorDocumentHandle.ts +9 -4
- package/src/NativeEditorLocalAwareness.ts +70 -15
- package/src/NativeEditorNativeModule.ts +13 -9
- package/src/NativeEditorRenderNormalization.ts +128 -29
- package/src/NativeEditorResultNormalization.ts +143 -32
- package/src/NativeEditorTypes.ts +12 -11
- package/src/NativeEditorV2Decimal.ts +12 -3
- package/src/NativeProseViewer.tsx +46 -16
- package/src/ResourceLimits.ts +15 -8
- package/src/RichTextEditor.tsx +3 -1
- package/src/RichTextEditorNativeTypes.tsx +1 -1
- package/src/RichTextEditorNativeView.tsx +2 -8
- package/src/RichTextEditorSerialization.tsx +70 -24
- package/src/RichTextEditorTypes.tsx +1 -1
- package/src/YjsCollaboration.ts +143 -47
- package/src/addons.ts +12 -8
- package/src/atomInstances.ts +25 -5
- package/src/atomUpdates.ts +23 -6
- package/src/atoms.ts +85 -18
- package/src/attributeValidation.ts +97 -33
- package/src/contentExpression.ts +218 -63
- package/src/listMarkers.ts +1 -1
- package/src/schemaDefinition.ts +82 -20
- package/src/schemaDocument.ts +15 -1
- package/src/schemaDocumentConstruction.ts +80 -16
- package/src/schemaNormalization.ts +155 -41
- package/src/schemaPresets.ts +37 -31
- package/src/schemaResolution.ts +126 -27
- package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
- package/src/useEditorToolbarInteractions.tsx +85 -36
- package/src/useEditorToolbarItems.tsx +50 -22
- package/src/useEditorToolbarPresentation.tsx +81 -58
- package/src/useEditorToolbarState.tsx +8 -6
- package/src/useFocusPreservingFrames.ts +43 -15
- package/src/useNativeEditor.ts +111 -51
- package/src/useRichTextEditorCommands.tsx +127 -54
- package/src/useRichTextEditorEvents.tsx +144 -42
- package/src/useRichTextEditorMentions.tsx +118 -37
- package/src/useRichTextEditorPresentation.tsx +128 -114
- package/src/useRichTextEditorState.tsx +76 -40
- package/src/useRichTextEditorUpdates.tsx +207 -56
- package/src/useViewerAtoms.tsx +162 -66
package/dist/schemaDocument.js
CHANGED
|
@@ -43,7 +43,7 @@ function defaultEmptyDocument(schema = schemaPresets_1.defaultSchema, limits) {
|
|
|
43
43
|
function resolveDocumentDescriptor(schema, limits) {
|
|
44
44
|
const resolvedLimits = (0, schemaResolution_1.resolveDescriptorLimits)(limits);
|
|
45
45
|
const resolvedSchema = (0, schemaResolution_1.resolveDocumentSchema)(schema, resolvedLimits);
|
|
46
|
-
const documentNode = resolvedSchema.nodes.find(
|
|
46
|
+
const documentNode = resolvedSchema.nodes.find(node => node.role === 'doc');
|
|
47
47
|
if (!documentNode) {
|
|
48
48
|
throw new NativeEditorBoundaryError_1.NativeEditorBoundaryError('SCHEMA_INVALID', 'schema has no document-role node');
|
|
49
49
|
}
|
|
@@ -4,9 +4,10 @@ exports.constructDefaultEmptyDocument = constructDefaultEmptyDocument;
|
|
|
4
4
|
const contentExpression_1 = require("./contentExpression");
|
|
5
5
|
const schemaNormalization_1 = require("./schemaNormalization");
|
|
6
6
|
function constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollections) {
|
|
7
|
-
const docNode = schema.nodes.find(
|
|
8
|
-
if (!docNode)
|
|
7
|
+
const docNode = schema.nodes.find(node => node.role === 'doc');
|
|
8
|
+
if (!docNode) {
|
|
9
9
|
throw new Error('schema cannot construct a default document: missing doc role');
|
|
10
|
+
}
|
|
10
11
|
const budget = { nodes: 0, work: 0, exhausted: false };
|
|
11
12
|
const workLimit = Math.min(contentExpression_1.DEFAULT_CONTENT_MAX_NODES, resolvedLimits.maxSchemaNodes * 64 + resolvedLimits.maxSchemaExpressionBytes * 32);
|
|
12
13
|
const consumeWork = () => {
|
|
@@ -27,13 +28,16 @@ function constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollectio
|
|
|
27
28
|
const candidatesBySymbol = new Map();
|
|
28
29
|
let candidateIndexAdmitted = true;
|
|
29
30
|
const addCandidate = (symbol, candidate) => {
|
|
30
|
-
if (!consumeWork())
|
|
31
|
+
if (!consumeWork()) {
|
|
31
32
|
return false;
|
|
33
|
+
}
|
|
32
34
|
const candidates = candidatesBySymbol.get(symbol);
|
|
33
|
-
if (candidates)
|
|
35
|
+
if (candidates) {
|
|
34
36
|
candidates.push(candidate);
|
|
35
|
-
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
36
39
|
candidatesBySymbol.set(symbol, [candidate]);
|
|
40
|
+
}
|
|
37
41
|
return true;
|
|
38
42
|
};
|
|
39
43
|
for (const candidate of schema.nodes) {
|
|
@@ -47,8 +51,9 @@ function constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollectio
|
|
|
47
51
|
break;
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
|
-
if (!candidateIndexAdmitted)
|
|
54
|
+
if (!candidateIndexAdmitted) {
|
|
51
55
|
break;
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
58
|
for (const candidates of candidatesBySymbol.values()) {
|
|
54
59
|
const sortingWork = Math.max(candidates.length, Math.ceil(candidates.length * Math.log2(Math.max(2, candidates.length))));
|
|
@@ -58,8 +63,9 @@ function constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollectio
|
|
|
58
63
|
break;
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
|
-
if (!candidateIndexAdmitted)
|
|
66
|
+
if (!candidateIndexAdmitted) {
|
|
62
67
|
break;
|
|
68
|
+
}
|
|
63
69
|
candidates.sort((left, right) => candidatePriority(left) - candidatePriority(right) ||
|
|
64
70
|
left.name.localeCompare(right.name));
|
|
65
71
|
}
|
|
@@ -71,10 +77,11 @@ function constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollectio
|
|
|
71
77
|
!consumeWork()) {
|
|
72
78
|
return undefined;
|
|
73
79
|
}
|
|
74
|
-
if (node.role === 'text' || visiting.has(node.name))
|
|
80
|
+
if (node.role === 'text' || visiting.has(node.name)) {
|
|
75
81
|
return undefined;
|
|
82
|
+
}
|
|
76
83
|
const attrs = admittedCollections.attrsByNode.get(node) ?? [];
|
|
77
|
-
for (
|
|
84
|
+
for (let index = 0; index < attrs.length; index += 1) {
|
|
78
85
|
if (!consumeWork()) {
|
|
79
86
|
budget.exhausted = true;
|
|
80
87
|
return undefined;
|
|
@@ -84,27 +91,31 @@ function constructDefaultEmptyDocument(schema, resolvedLimits, admittedCollectio
|
|
|
84
91
|
return undefined;
|
|
85
92
|
}
|
|
86
93
|
visiting.add(node.name);
|
|
87
|
-
const children = (0, contentExpression_1.minimalContentMatch)(node.content ?? '',
|
|
94
|
+
const children = (0, contentExpression_1.minimalContentMatch)(node.content ?? '', symbol => {
|
|
88
95
|
for (const candidate of candidatesBySymbol.get(symbol) ?? []) {
|
|
89
|
-
if (!consumeWork())
|
|
96
|
+
if (!consumeWork()) {
|
|
90
97
|
return undefined;
|
|
98
|
+
}
|
|
91
99
|
const constructed = constructNode(candidate, visiting, depth + 1);
|
|
92
|
-
if (constructed)
|
|
100
|
+
if (constructed) {
|
|
93
101
|
return constructed;
|
|
102
|
+
}
|
|
94
103
|
}
|
|
95
104
|
return undefined;
|
|
96
105
|
}, consumeWork);
|
|
97
106
|
visiting.delete(node.name);
|
|
98
|
-
if (!children)
|
|
107
|
+
if (!children) {
|
|
99
108
|
return undefined;
|
|
109
|
+
}
|
|
100
110
|
if (budget.nodes >= resolvedLimits.maxDocumentNodes) {
|
|
101
111
|
budget.exhausted = true;
|
|
102
112
|
return undefined;
|
|
103
113
|
}
|
|
104
114
|
budget.nodes += 1;
|
|
105
115
|
const result = { type: node.json?.type ?? node.name };
|
|
106
|
-
if (children.length > 0)
|
|
116
|
+
if (children.length > 0) {
|
|
107
117
|
result.content = children;
|
|
118
|
+
}
|
|
108
119
|
const projectedAttrs = Object.entries(node.json?.attrs ?? {});
|
|
109
120
|
if (attrs.length > 0 || projectedAttrs.length > 0) {
|
|
110
121
|
result.attrs = Object.fromEntries([
|
|
@@ -30,22 +30,26 @@ function utf8ByteLengthUpTo(value, maximum) {
|
|
|
30
30
|
for (const char of value) {
|
|
31
31
|
const codePoint = char.codePointAt(0) ?? 0;
|
|
32
32
|
bytes += codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;
|
|
33
|
-
if (bytes > maximum)
|
|
33
|
+
if (bytes > maximum) {
|
|
34
34
|
return bytes;
|
|
35
|
+
}
|
|
35
36
|
}
|
|
36
37
|
return bytes;
|
|
37
38
|
}
|
|
38
39
|
function forEachGroupToken(group, visit, consumeCharacter, consumeToken) {
|
|
39
40
|
let tokenStart = -1;
|
|
40
41
|
for (let index = 0; index <= group.length; index += 1) {
|
|
41
|
-
if (index < group.length && consumeCharacter && !consumeCharacter())
|
|
42
|
+
if (index < group.length && consumeCharacter && !consumeCharacter()) {
|
|
42
43
|
return false;
|
|
44
|
+
}
|
|
43
45
|
const isBoundary = index === group.length || /\s/.test(group[index]);
|
|
44
|
-
if (!isBoundary && tokenStart < 0)
|
|
46
|
+
if (!isBoundary && tokenStart < 0) {
|
|
45
47
|
tokenStart = index;
|
|
48
|
+
}
|
|
46
49
|
if (isBoundary && tokenStart >= 0) {
|
|
47
|
-
if (consumeToken && !consumeToken())
|
|
50
|
+
if (consumeToken && !consumeToken()) {
|
|
48
51
|
return false;
|
|
52
|
+
}
|
|
49
53
|
visit(group.slice(tokenStart, index));
|
|
50
54
|
tokenStart = -1;
|
|
51
55
|
}
|
|
@@ -67,21 +71,25 @@ function consumeSchemaStringWork(budget, value) {
|
|
|
67
71
|
return consumeSchemaWorkAmount(budget, utf8ByteLengthUpTo(value, budget.limit) + 1);
|
|
68
72
|
}
|
|
69
73
|
function collectOwnAttrs(value, budget) {
|
|
70
|
-
if (value == null || typeof value !== 'object' || Array.isArray(value))
|
|
74
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
71
75
|
return [];
|
|
76
|
+
}
|
|
72
77
|
const attrs = [];
|
|
73
78
|
for (const name in value) {
|
|
74
|
-
if (!Object.prototype.hasOwnProperty.call(value, name))
|
|
79
|
+
if (!Object.prototype.hasOwnProperty.call(value, name)) {
|
|
75
80
|
continue;
|
|
76
|
-
|
|
81
|
+
}
|
|
82
|
+
if (!consumeSchemaWork(budget)) {
|
|
77
83
|
return attrs;
|
|
84
|
+
}
|
|
78
85
|
attrs.push([name, value[name]]);
|
|
79
86
|
}
|
|
80
87
|
return attrs;
|
|
81
88
|
}
|
|
82
89
|
function isSafeHtmlTag(tag) {
|
|
83
|
-
if (tag.length === 0 || tag[0] < 'a' || tag[0] > 'z')
|
|
90
|
+
if (tag.length === 0 || tag[0] < 'a' || tag[0] > 'z') {
|
|
84
91
|
return false;
|
|
92
|
+
}
|
|
85
93
|
for (let index = 1; index < tag.length; index += 1) {
|
|
86
94
|
const char = tag[index];
|
|
87
95
|
if (!((char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char === '-')) {
|
|
@@ -91,11 +99,13 @@ function isSafeHtmlTag(tag) {
|
|
|
91
99
|
return true;
|
|
92
100
|
}
|
|
93
101
|
function isSafeHtmlAttr(name) {
|
|
94
|
-
if (name.length === 0)
|
|
102
|
+
if (name.length === 0) {
|
|
95
103
|
return false;
|
|
104
|
+
}
|
|
96
105
|
const isAlpha = (char) => (char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z');
|
|
97
|
-
if (!(isAlpha(name[0]) || name[0] === '_' || name[0] === ':'))
|
|
106
|
+
if (!(isAlpha(name[0]) || name[0] === '_' || name[0] === ':')) {
|
|
98
107
|
return false;
|
|
108
|
+
}
|
|
99
109
|
for (let index = 1; index < name.length; index += 1) {
|
|
100
110
|
const char = name[index];
|
|
101
111
|
if (!(isAlpha(char) ||
|
|
@@ -110,8 +120,9 @@ function isSafeHtmlAttr(name) {
|
|
|
110
120
|
return true;
|
|
111
121
|
}
|
|
112
122
|
function normalizeAttrs(value) {
|
|
113
|
-
if (value == null || typeof value !== 'object' || Array.isArray(value))
|
|
123
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
114
124
|
return {};
|
|
125
|
+
}
|
|
115
126
|
return Object.fromEntries(Object.entries(value).map(([name, rawSpec]) => {
|
|
116
127
|
if (rawSpec == null || typeof rawSpec !== 'object' || Array.isArray(rawSpec)) {
|
|
117
128
|
return [name, {}];
|
|
@@ -124,21 +135,27 @@ function normalizeAttrs(value) {
|
|
|
124
135
|
}));
|
|
125
136
|
}
|
|
126
137
|
function normalizeNodeJSONProjection(value) {
|
|
127
|
-
if (value === undefined)
|
|
138
|
+
if (value === undefined) {
|
|
128
139
|
return undefined;
|
|
129
|
-
|
|
140
|
+
}
|
|
141
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
130
142
|
return null;
|
|
143
|
+
}
|
|
131
144
|
const raw = value;
|
|
132
|
-
if (typeof raw.type !== 'string' || raw.type.length === 0)
|
|
145
|
+
if (typeof raw.type !== 'string' || raw.type.length === 0) {
|
|
133
146
|
return null;
|
|
134
|
-
|
|
147
|
+
}
|
|
148
|
+
if (raw.attrs === undefined) {
|
|
135
149
|
return { type: raw.type };
|
|
136
|
-
|
|
150
|
+
}
|
|
151
|
+
if (raw.attrs == null || typeof raw.attrs !== 'object' || Array.isArray(raw.attrs)) {
|
|
137
152
|
return null;
|
|
153
|
+
}
|
|
138
154
|
const attrs = {};
|
|
139
155
|
for (const [name, attrValue] of Object.entries(raw.attrs)) {
|
|
140
|
-
if (!isSafeHtmlAttr(name))
|
|
156
|
+
if (!isSafeHtmlAttr(name)) {
|
|
141
157
|
return null;
|
|
158
|
+
}
|
|
142
159
|
if (attrValue !== null &&
|
|
143
160
|
typeof attrValue !== 'string' &&
|
|
144
161
|
typeof attrValue !== 'boolean' &&
|
|
@@ -158,26 +175,30 @@ function isSafeAtomHtmlAttr(name) {
|
|
|
158
175
|
!atomPolicy_1.ATOM_HTML_DENIED_ATTRS.has(name));
|
|
159
176
|
}
|
|
160
177
|
function normalizeNodeHtmlRules(value) {
|
|
161
|
-
if (value === undefined)
|
|
178
|
+
if (value === undefined) {
|
|
162
179
|
return undefined;
|
|
163
|
-
|
|
180
|
+
}
|
|
181
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
164
182
|
return null;
|
|
183
|
+
}
|
|
165
184
|
const raw = value;
|
|
166
|
-
if (Object.keys(raw).some(
|
|
185
|
+
if (Object.keys(raw).some(key => key !== 'tag' && key !== 'staticAttrs' && key !== 'attrMap') ||
|
|
167
186
|
typeof raw.tag !== 'string' ||
|
|
168
187
|
!isSafeAtomHtmlTag(raw.tag)) {
|
|
169
188
|
return null;
|
|
170
189
|
}
|
|
171
190
|
const normalizeMap = (candidate, validateName) => {
|
|
172
|
-
if (candidate === undefined)
|
|
191
|
+
if (candidate === undefined) {
|
|
173
192
|
return undefined;
|
|
193
|
+
}
|
|
174
194
|
if (candidate == null || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
175
195
|
return null;
|
|
176
196
|
}
|
|
177
197
|
const normalized = {};
|
|
178
198
|
for (const [name, mapped] of Object.entries(candidate)) {
|
|
179
|
-
if (!validateName(name) || typeof mapped !== 'string')
|
|
199
|
+
if (!validateName(name) || typeof mapped !== 'string') {
|
|
180
200
|
return null;
|
|
201
|
+
}
|
|
181
202
|
normalized[name] = mapped;
|
|
182
203
|
}
|
|
183
204
|
return normalized;
|
|
@@ -186,7 +207,7 @@ function normalizeNodeHtmlRules(value) {
|
|
|
186
207
|
const attrMap = normalizeMap(raw.attrMap, isSafeHtmlAttr);
|
|
187
208
|
if (staticAttrs === null ||
|
|
188
209
|
attrMap === null ||
|
|
189
|
-
(attrMap != null && Object.values(attrMap).some(
|
|
210
|
+
(attrMap != null && Object.values(attrMap).some(name => !isSafeAtomHtmlAttr(name)))) {
|
|
190
211
|
return null;
|
|
191
212
|
}
|
|
192
213
|
return {
|
|
@@ -199,8 +220,9 @@ function projectionAttrsOverlap(left, right) {
|
|
|
199
220
|
return Object.entries(left).every(([name, value]) => !Object.prototype.hasOwnProperty.call(right, name) || right[name] === value);
|
|
200
221
|
}
|
|
201
222
|
function legacyHeadingProjectionName(projection) {
|
|
202
|
-
if (projection.type !== 'heading')
|
|
223
|
+
if (projection.type !== 'heading') {
|
|
203
224
|
return undefined;
|
|
225
|
+
}
|
|
204
226
|
const value = projection.attrs?.level;
|
|
205
227
|
let level;
|
|
206
228
|
if (typeof value === 'number' && Number.isInteger(value)) {
|
|
@@ -240,7 +262,7 @@ function normalizeSchemaDefinition(schema, budget) {
|
|
|
240
262
|
if ((htmlTag != null && !isSafeHtmlTag(htmlTag)) ||
|
|
241
263
|
html === null ||
|
|
242
264
|
json === null ||
|
|
243
|
-
Object.keys(attrs).some(
|
|
265
|
+
Object.keys(attrs).some(name => !isSafeHtmlAttr(name))) {
|
|
244
266
|
return null;
|
|
245
267
|
}
|
|
246
268
|
nodes.push({
|
|
@@ -261,8 +283,8 @@ function normalizeSchemaDefinition(schema, budget) {
|
|
|
261
283
|
: {}),
|
|
262
284
|
});
|
|
263
285
|
}
|
|
264
|
-
const nativeNodeNames = new Set(nodes.map(
|
|
265
|
-
const projectedNodes = nodes.filter(
|
|
286
|
+
const nativeNodeNames = new Set(nodes.map(node => node.name));
|
|
287
|
+
const projectedNodes = nodes.filter(node => node.json != null);
|
|
266
288
|
for (let index = 0; index < projectedNodes.length; index += 1) {
|
|
267
289
|
const node = projectedNodes[index];
|
|
268
290
|
const projection = node.json;
|
|
@@ -272,7 +294,7 @@ function normalizeSchemaDefinition(schema, budget) {
|
|
|
272
294
|
(legacyHeadingName != null &&
|
|
273
295
|
legacyHeadingName !== node.name &&
|
|
274
296
|
nativeNodeNames.has(legacyHeadingName)) ||
|
|
275
|
-
Object.keys(projection.attrs ?? {}).some(
|
|
297
|
+
Object.keys(projection.attrs ?? {}).some(name => Object.prototype.hasOwnProperty.call(node.attrs ?? {}, name))) {
|
|
276
298
|
return null;
|
|
277
299
|
}
|
|
278
300
|
for (let previousIndex = 0; previousIndex < index; previousIndex += 1) {
|
|
@@ -296,7 +318,7 @@ function normalizeSchemaDefinition(schema, budget) {
|
|
|
296
318
|
const htmlTag = typeof raw.htmlTag === 'string' ? raw.htmlTag.toLowerCase() : undefined;
|
|
297
319
|
const attrs = normalizeAttrs(raw.attrs);
|
|
298
320
|
if ((htmlTag != null && !schemaDefinition_1.ALLOWED_MARK_HTML_TAGS.has(htmlTag)) ||
|
|
299
|
-
Object.keys(attrs).some(
|
|
321
|
+
Object.keys(attrs).some(name => !isSafeHtmlAttr(name))) {
|
|
300
322
|
return null;
|
|
301
323
|
}
|
|
302
324
|
marks.push({
|
package/dist/schemaPresets.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface ImageNodeAttributes {
|
|
|
16
16
|
export interface ResolvedDocumentSchema {
|
|
17
17
|
/** The schema itself, defaulted to {@link defaultSchema} when none was supplied. */
|
|
18
18
|
schema: SchemaDefinition;
|
|
19
|
-
/** Name of the node with `role: 'doc'`
|
|
19
|
+
/** Name of the node with `role: 'doc'` : the `type` of a document's root. */
|
|
20
20
|
documentNodeName: string;
|
|
21
21
|
/** The smallest document this schema admits. Used by `clearContent()`. */
|
|
22
22
|
emptyDocument: DocumentJSON;
|
package/dist/schemaPresets.js
CHANGED
|
@@ -9,7 +9,12 @@ exports.buildImageFragmentJson = buildImageFragmentJson;
|
|
|
9
9
|
const schemaDefinition_1 = require("./schemaDefinition");
|
|
10
10
|
/** Node name the built-in image node is stored under. */
|
|
11
11
|
exports.IMAGE_NODE_NAME = 'image';
|
|
12
|
-
exports.HEADING_LEVELS = [1,
|
|
12
|
+
exports.HEADING_LEVELS = [1,
|
|
13
|
+
2,
|
|
14
|
+
3,
|
|
15
|
+
4,
|
|
16
|
+
5,
|
|
17
|
+
6];
|
|
13
18
|
/**
|
|
14
19
|
* The built-in image node spec: a void block node carrying
|
|
15
20
|
* {@link ImageNodeAttributes}. Add it through {@link withImagesSchema}.
|
|
@@ -41,7 +46,7 @@ function imageNodeSpec(name = exports.IMAGE_NODE_NAME) {
|
|
|
41
46
|
* already declares one. {@link tiptapCompatibleSchema} already includes it.
|
|
42
47
|
*/
|
|
43
48
|
function withImagesSchema(schema) {
|
|
44
|
-
const hasImageNode = schema.nodes.some(
|
|
49
|
+
const hasImageNode = schema.nodes.some(node => node.name === exports.IMAGE_NODE_NAME);
|
|
45
50
|
if (hasImageNode) {
|
|
46
51
|
return schema;
|
|
47
52
|
}
|
|
@@ -93,13 +98,13 @@ exports.tiptapCompatibleSchemaSpec = {
|
|
|
93
98
|
group: 'block',
|
|
94
99
|
role: 'heading',
|
|
95
100
|
attrs: { level: { default: 1 } },
|
|
96
|
-
parseDOM: exports.HEADING_LEVELS.map(
|
|
101
|
+
parseDOM: exports.HEADING_LEVELS.map(level => ({
|
|
97
102
|
tag: `h${level}`,
|
|
98
103
|
attrs: { level },
|
|
99
104
|
})),
|
|
100
105
|
toDOM: {
|
|
101
106
|
switchOn: 'level',
|
|
102
|
-
cases: Object.fromEntries(exports.HEADING_LEVELS.map(
|
|
107
|
+
cases: Object.fromEntries(exports.HEADING_LEVELS.map(level => [level, [`h${level}`, 0]])),
|
|
103
108
|
},
|
|
104
109
|
},
|
|
105
110
|
blockquote: {
|
package/dist/schemaResolution.js
CHANGED
|
@@ -25,20 +25,23 @@ function admitSchemaCollections(schema, budget) {
|
|
|
25
25
|
const attrsByNode = new Map();
|
|
26
26
|
for (let nodeIndex = 0; nodeIndex < schema.nodes.length; nodeIndex += 1) {
|
|
27
27
|
const node = schema.nodes[nodeIndex];
|
|
28
|
-
if (node == null || typeof node !== 'object')
|
|
28
|
+
if (node == null || typeof node !== 'object') {
|
|
29
29
|
return null;
|
|
30
|
+
}
|
|
30
31
|
const groups = [];
|
|
31
32
|
if (typeof node.group === 'string') {
|
|
32
|
-
if (!(0, schemaNormalization_1.forEachGroupToken)(node.group,
|
|
33
|
+
if (!(0, schemaNormalization_1.forEachGroupToken)(node.group, group => groups.push(group), () => (0, schemaNormalization_1.consumeSchemaWork)(budget), () => (0, schemaNormalization_1.consumeSchemaWork)(budget))) {
|
|
33
34
|
throw (0, schemaNormalization_1.schemaBoundaryError)(budget.limit, budget.limit + 1);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
const attrs = (0, schemaNormalization_1.collectOwnAttrs)(node.attrs, budget);
|
|
37
|
-
if (attrs == null)
|
|
38
|
+
if (attrs == null) {
|
|
38
39
|
return null;
|
|
40
|
+
}
|
|
39
41
|
const projectionAttrs = (0, schemaNormalization_1.collectOwnAttrs)(node.json?.attrs, budget);
|
|
40
|
-
if (projectionAttrs == null)
|
|
42
|
+
if (projectionAttrs == null) {
|
|
41
43
|
return null;
|
|
44
|
+
}
|
|
42
45
|
if (node.json != null &&
|
|
43
46
|
((typeof node.json.type === 'string' &&
|
|
44
47
|
!(0, schemaNormalization_1.consumeSchemaStringWork)(budget, node.json.type)) ||
|
|
@@ -62,11 +65,13 @@ function admitSchemaCollections(schema, budget) {
|
|
|
62
65
|
if (!(0, schemaNormalization_1.consumeSchemaWork)(budget)) {
|
|
63
66
|
throw (0, schemaNormalization_1.schemaBoundaryError)(budget.limit, budget.limit + 1);
|
|
64
67
|
}
|
|
65
|
-
if (mark == null || typeof mark !== 'object')
|
|
68
|
+
if (mark == null || typeof mark !== 'object') {
|
|
66
69
|
return null;
|
|
70
|
+
}
|
|
67
71
|
const attrs = (0, schemaNormalization_1.collectOwnAttrs)(mark.attrs, budget);
|
|
68
|
-
if (attrs == null)
|
|
72
|
+
if (attrs == null) {
|
|
69
73
|
return null;
|
|
74
|
+
}
|
|
70
75
|
if (budget.exhausted) {
|
|
71
76
|
throw (0, schemaNormalization_1.schemaBoundaryError)(budget.limit, budget.limit + 1);
|
|
72
77
|
}
|
|
@@ -75,10 +80,12 @@ function admitSchemaCollections(schema, budget) {
|
|
|
75
80
|
}
|
|
76
81
|
/** Mirror native's invalid-schema fallback after bounded admission succeeds. */
|
|
77
82
|
function resolveDocumentSchema(schema, limits) {
|
|
78
|
-
if (schema == null)
|
|
83
|
+
if (schema == null) {
|
|
79
84
|
return schemaPresets_1.defaultSchema;
|
|
80
|
-
|
|
85
|
+
}
|
|
86
|
+
if (!Array.isArray(schema.nodes)) {
|
|
81
87
|
return schemaPresets_1.defaultSchema;
|
|
88
|
+
}
|
|
82
89
|
if (!Array.isArray(schema.marks)) {
|
|
83
90
|
schema = { ...schema, marks: [] };
|
|
84
91
|
}
|
|
@@ -97,19 +104,22 @@ function resolveDocumentSchema(schema, limits) {
|
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
const schemaBudget = createSchemaWorkBudget(resolvedLimits);
|
|
100
|
-
if (admitSchemaCollections(schema, schemaBudget) == null)
|
|
107
|
+
if (admitSchemaCollections(schema, schemaBudget) == null) {
|
|
101
108
|
return schemaPresets_1.defaultSchema;
|
|
109
|
+
}
|
|
102
110
|
const normalizedSchema = (0, schemaNormalization_1.normalizeSchemaDefinition)(schema, schemaBudget);
|
|
103
|
-
if (normalizedSchema == null)
|
|
111
|
+
if (normalizedSchema == null) {
|
|
104
112
|
return schemaPresets_1.defaultSchema;
|
|
113
|
+
}
|
|
105
114
|
schema = normalizedSchema;
|
|
106
115
|
const admittedCollections = admitSchemaCollections(schema, {
|
|
107
116
|
limit: Number.MAX_SAFE_INTEGER,
|
|
108
117
|
work: 0,
|
|
109
118
|
exhausted: false,
|
|
110
119
|
});
|
|
111
|
-
if (admittedCollections == null)
|
|
120
|
+
if (admittedCollections == null) {
|
|
112
121
|
return schemaPresets_1.defaultSchema;
|
|
122
|
+
}
|
|
113
123
|
const nodeNames = new Set();
|
|
114
124
|
const markNames = new Set();
|
|
115
125
|
let docRoles = 0;
|
|
@@ -124,10 +134,12 @@ function resolveDocumentSchema(schema, limits) {
|
|
|
124
134
|
return schemaPresets_1.defaultSchema;
|
|
125
135
|
}
|
|
126
136
|
nodeNames.add(node.name);
|
|
127
|
-
if (node.role === 'doc')
|
|
137
|
+
if (node.role === 'doc') {
|
|
128
138
|
docRoles += 1;
|
|
129
|
-
|
|
139
|
+
}
|
|
140
|
+
if (node.role === 'text') {
|
|
130
141
|
textRoles += 1;
|
|
142
|
+
}
|
|
131
143
|
}
|
|
132
144
|
for (const mark of schema.marks) {
|
|
133
145
|
if (mark == null ||
|
|
@@ -138,16 +150,19 @@ function resolveDocumentSchema(schema, limits) {
|
|
|
138
150
|
}
|
|
139
151
|
markNames.add(mark.name);
|
|
140
152
|
}
|
|
141
|
-
if (docRoles !== 1 || textRoles !== 1)
|
|
153
|
+
if (docRoles !== 1 || textRoles !== 1) {
|
|
142
154
|
return schemaPresets_1.defaultSchema;
|
|
155
|
+
}
|
|
143
156
|
const groups = new Set();
|
|
144
157
|
const nodesBySymbol = new Map();
|
|
145
158
|
const addCandidate = (symbol, node) => {
|
|
146
159
|
const candidates = nodesBySymbol.get(symbol);
|
|
147
|
-
if (candidates)
|
|
160
|
+
if (candidates) {
|
|
148
161
|
candidates.push(node);
|
|
149
|
-
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
150
164
|
nodesBySymbol.set(symbol, [node]);
|
|
165
|
+
}
|
|
151
166
|
};
|
|
152
167
|
for (const node of schema.nodes) {
|
|
153
168
|
addCandidate(node.name, node);
|
|
@@ -159,22 +174,25 @@ function resolveDocumentSchema(schema, limits) {
|
|
|
159
174
|
for (const node of schema.nodes) {
|
|
160
175
|
const symbols = (0, contentExpression_1.contentExpressionSymbols)(node.content);
|
|
161
176
|
if (symbols == null ||
|
|
162
|
-
symbols.some(
|
|
177
|
+
symbols.some(symbol => !nodeNames.has(symbol) && !groups.has(symbol))) {
|
|
163
178
|
return schemaPresets_1.defaultSchema;
|
|
164
179
|
}
|
|
165
180
|
}
|
|
166
181
|
const generatable = new Set();
|
|
167
182
|
const consumeWork = () => (0, schemaNormalization_1.consumeSchemaWork)(schemaBudget);
|
|
168
183
|
const contentIsConstructible = (node) => {
|
|
169
|
-
if (!consumeWork())
|
|
184
|
+
if (!consumeWork()) {
|
|
170
185
|
return false;
|
|
171
|
-
|
|
186
|
+
}
|
|
187
|
+
return ((0, contentExpression_1.minimalContentMatch)(node.content, symbol => {
|
|
172
188
|
const candidates = nodesBySymbol.get(symbol) ?? [];
|
|
173
189
|
for (const candidate of candidates) {
|
|
174
|
-
if (!consumeWork())
|
|
190
|
+
if (!consumeWork()) {
|
|
175
191
|
return undefined;
|
|
176
|
-
|
|
192
|
+
}
|
|
193
|
+
if (generatable.has(candidate.name)) {
|
|
177
194
|
return { type: candidate.name };
|
|
195
|
+
}
|
|
178
196
|
}
|
|
179
197
|
return undefined;
|
|
180
198
|
}, consumeWork) != null);
|
|
@@ -187,25 +205,28 @@ function resolveDocumentSchema(schema, limits) {
|
|
|
187
205
|
generatable.add(node.name);
|
|
188
206
|
}
|
|
189
207
|
}
|
|
190
|
-
if (generatable.size === before)
|
|
208
|
+
if (generatable.size === before) {
|
|
191
209
|
break;
|
|
210
|
+
}
|
|
192
211
|
}
|
|
193
212
|
if (schemaBudget.exhausted) {
|
|
194
213
|
throw (0, schemaNormalization_1.schemaBoundaryError)(schemaBudget.limit, schemaBudget.limit + 1);
|
|
195
214
|
}
|
|
196
|
-
const hasUnconstructibleNode = schema.nodes.some(
|
|
215
|
+
const hasUnconstructibleNode = schema.nodes.some(node => !contentIsConstructible(node));
|
|
197
216
|
if (schemaBudget.exhausted) {
|
|
198
217
|
throw (0, schemaNormalization_1.schemaBoundaryError)(schemaBudget.limit, schemaBudget.limit + 1);
|
|
199
218
|
}
|
|
200
|
-
if (hasUnconstructibleNode)
|
|
219
|
+
if (hasUnconstructibleNode) {
|
|
201
220
|
return schemaPresets_1.defaultSchema;
|
|
221
|
+
}
|
|
202
222
|
try {
|
|
203
223
|
(0, schemaDocumentConstruction_1.constructDefaultEmptyDocument)(schema, resolvedLimits, admittedCollections);
|
|
204
224
|
return schema;
|
|
205
225
|
}
|
|
206
226
|
catch (error) {
|
|
207
|
-
if (error instanceof NativeEditorBoundaryError_1.NativeEditorBoundaryError)
|
|
227
|
+
if (error instanceof NativeEditorBoundaryError_1.NativeEditorBoundaryError) {
|
|
208
228
|
throw error;
|
|
229
|
+
}
|
|
209
230
|
return schemaPresets_1.defaultSchema;
|
|
210
231
|
}
|
|
211
232
|
}
|
|
@@ -15,6 +15,10 @@ export interface NativeProps extends ViewProps {
|
|
|
15
15
|
href: string;
|
|
16
16
|
text: string;
|
|
17
17
|
}>;
|
|
18
|
+
/**
|
|
19
|
+
* React Native numbers are IEEE-754 doubles, which exactly represent every
|
|
20
|
+
* UInt32 document position. Int32 would corrupt positions above 2^31 - 1.
|
|
21
|
+
*/
|
|
18
22
|
onPressMention?: DirectEventHandler<{
|
|
19
23
|
docPos: Double;
|
|
20
24
|
label: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEditorToolbarState } from './useEditorToolbarState';
|
|
2
|
-
import { useEditorToolbarItems } from './useEditorToolbarItems';
|
|
1
|
+
import { type useEditorToolbarState } from './useEditorToolbarState';
|
|
2
|
+
import { type useEditorToolbarItems } from './useEditorToolbarItems';
|
|
3
3
|
import { type ToolbarButton, type ToolbarGroupButton } from './EditorToolbarTypes';
|
|
4
4
|
export declare function useEditorToolbarInteractions(context: Pick<ReturnType<typeof useEditorToolbarState>, 'showTopBorder' | 'theme' | 'registrationIdRef' | 'rootRef' | 'publishesFocusFrames' | 'frameOwnerId' | 'framePublisherMountedRef' | 'publishesFocusFramesRef' | 'frameOwnerIdRef' | 'menuRegistrationIdRef' | 'menuCardRef' | 'menuState' | 'menuStateRef' | 'framePublishAnimationFramesRef' | 'framePublishTimeoutsRef' | 'expandedGroupKey' | 'windowHeight' | 'windowWidth' | 'toolbarInteractionActiveRef' | 'setExpandedGroupKey' | 'setMenuState' | 'shouldRenderMentionSuggestions' | 'preserveEditorFocus' | 'groupButtonRefs'> & Pick<ReturnType<typeof useEditorToolbarItems>, 'startItems' | 'scrollItems' | 'endItems' | 'groupsByKey'>): {
|
|
5
5
|
handleToolbarPressIn: () => void;
|