@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.
Files changed (161) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/android/build.gradle +3 -0
  4. package/app.plugin.js +42 -39
  5. package/dist/AtomHost.js +18 -11
  6. package/dist/EditorAddon.js +4 -2
  7. package/dist/EditorAddonNormalization.js +17 -9
  8. package/dist/EditorMentionThemeNormalization.js +6 -3
  9. package/dist/EditorMentionThemeValidation.js +28 -11
  10. package/dist/EditorStyleSheetNormalization.js +84 -37
  11. package/dist/EditorTheme.d.ts +4 -0
  12. package/dist/EditorTheme.js +5 -3
  13. package/dist/EditorToolbarComponent.d.ts +1 -1
  14. package/dist/EditorToolbarComponent.js +1 -1
  15. package/dist/EditorToolbarRegistry.js +5 -5
  16. package/dist/EditorToolbarTypes.d.ts +12 -12
  17. package/dist/EditorToolbarVisuals.js +1 -1
  18. package/dist/ExternalTextComposition.js +89 -43
  19. package/dist/ImageLoadingPolicy.d.ts +1 -1
  20. package/dist/NativeEditorBoundaryError.d.ts +7 -7
  21. package/dist/NativeEditorBoundaryError.js +9 -5
  22. package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
  23. package/dist/NativeEditorCollaborationTransport.js +28 -15
  24. package/dist/NativeEditorCreateConfig.js +11 -6
  25. package/dist/NativeEditorCreateJson.js +51 -25
  26. package/dist/NativeEditorCreateValidation.js +11 -6
  27. package/dist/NativeEditorDocumentBridge.d.ts +1 -1
  28. package/dist/NativeEditorDocumentBridge.js +32 -18
  29. package/dist/NativeEditorDocumentHandle.d.ts +4 -4
  30. package/dist/NativeEditorDocumentHandle.js +1 -1
  31. package/dist/NativeEditorLocalAwareness.js +25 -13
  32. package/dist/NativeEditorNativeModule.d.ts +8 -1
  33. package/dist/NativeEditorNativeModule.js +7 -5
  34. package/dist/NativeEditorRenderNormalization.js +66 -25
  35. package/dist/NativeEditorResultNormalization.js +53 -29
  36. package/dist/NativeEditorTypes.d.ts +10 -10
  37. package/dist/NativeEditorV2Decimal.js +6 -3
  38. package/dist/NativeProseViewer.js +11 -3
  39. package/dist/ResourceLimits.d.ts +2 -2
  40. package/dist/ResourceLimits.js +7 -2
  41. package/dist/RichTextEditor.js +1 -1
  42. package/dist/RichTextEditorNativeTypes.d.ts +1 -1
  43. package/dist/RichTextEditorNativeView.d.ts +1 -3
  44. package/dist/RichTextEditorSerialization.js +24 -14
  45. package/dist/RichTextEditorTypes.d.ts +1 -1
  46. package/dist/YjsCollaboration.d.ts +7 -7
  47. package/dist/YjsCollaboration.js +42 -26
  48. package/dist/addons.d.ts +4 -4
  49. package/dist/addons.js +3 -3
  50. package/dist/atomInstances.js +6 -3
  51. package/dist/atomUpdates.js +7 -4
  52. package/dist/atoms.js +20 -12
  53. package/dist/attributeValidation.js +55 -24
  54. package/dist/contentExpression.js +80 -42
  55. package/dist/listMarkers.d.ts +1 -1
  56. package/dist/listMarkers.js +1 -1
  57. package/dist/schemaDefinition.d.ts +1 -1
  58. package/dist/schemaDefinition.js +23 -14
  59. package/dist/schemaDocument.js +1 -1
  60. package/dist/schemaDocumentConstruction.js +25 -14
  61. package/dist/schemaNormalization.js +51 -29
  62. package/dist/schemaPresets.d.ts +1 -1
  63. package/dist/schemaPresets.js +9 -4
  64. package/dist/schemaResolution.js +46 -25
  65. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
  66. package/dist/useEditorToolbarInteractions.d.ts +2 -2
  67. package/dist/useEditorToolbarInteractions.js +45 -23
  68. package/dist/useEditorToolbarItems.d.ts +1 -1
  69. package/dist/useEditorToolbarItems.js +4 -3
  70. package/dist/useEditorToolbarPresentation.d.ts +3 -3
  71. package/dist/useEditorToolbarPresentation.js +4 -4
  72. package/dist/useEditorToolbarState.d.ts +1 -1
  73. package/dist/useEditorToolbarState.js +1 -1
  74. package/dist/useFocusPreservingFrames.js +11 -8
  75. package/dist/useNativeEditor.d.ts +1 -1
  76. package/dist/useNativeEditor.js +21 -11
  77. package/dist/useRichTextEditorCommands.d.ts +2 -2
  78. package/dist/useRichTextEditorCommands.js +59 -29
  79. package/dist/useRichTextEditorEvents.d.ts +3 -3
  80. package/dist/useRichTextEditorEvents.js +75 -32
  81. package/dist/useRichTextEditorMentions.d.ts +4 -4
  82. package/dist/useRichTextEditorMentions.js +48 -29
  83. package/dist/useRichTextEditorPresentation.d.ts +4 -4
  84. package/dist/useRichTextEditorPresentation.js +25 -23
  85. package/dist/useRichTextEditorState.d.ts +3 -3
  86. package/dist/useRichTextEditorState.js +20 -15
  87. package/dist/useRichTextEditorUpdates.d.ts +1 -1
  88. package/dist/useRichTextEditorUpdates.js +99 -41
  89. package/dist/useViewerAtoms.js +63 -36
  90. package/ios/EditorCore.xcframework/Info.plist +5 -5
  91. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  92. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  93. package/package.json +11 -3
  94. package/react-native.config.js +1 -1
  95. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  96. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  97. package/rust/android/x86/libeditor_core.so +0 -0
  98. package/rust/android/x86_64/libeditor_core.so +0 -0
  99. package/src/AtomHost.tsx +58 -28
  100. package/src/EditorAddon.ts +18 -8
  101. package/src/EditorAddonNormalization.ts +40 -11
  102. package/src/EditorMentionThemeNormalization.ts +15 -4
  103. package/src/EditorMentionThemeValidation.ts +51 -14
  104. package/src/EditorStyleSheet.ts +1 -0
  105. package/src/EditorStyleSheetNormalization.ts +195 -64
  106. package/src/EditorTheme.ts +13 -5
  107. package/src/EditorToolbarComponent.tsx +2 -1
  108. package/src/EditorToolbarRegistry.tsx +23 -13
  109. package/src/EditorToolbarTypes.tsx +12 -12
  110. package/src/EditorToolbarVisuals.tsx +6 -3
  111. package/src/EditorUpdateRevision.ts +1 -0
  112. package/src/ExternalTextComposition.ts +259 -49
  113. package/src/ImageLoadingPolicy.ts +3 -1
  114. package/src/NativeEditorBoundaryError.ts +38 -11
  115. package/src/NativeEditorCollaborationTransport.ts +108 -27
  116. package/src/NativeEditorCreateConfig.ts +92 -19
  117. package/src/NativeEditorCreateJson.ts +163 -26
  118. package/src/NativeEditorCreateValidation.ts +33 -12
  119. package/src/NativeEditorDocumentBridge.ts +111 -19
  120. package/src/NativeEditorDocumentHandle.ts +9 -4
  121. package/src/NativeEditorLocalAwareness.ts +70 -15
  122. package/src/NativeEditorNativeModule.ts +13 -9
  123. package/src/NativeEditorRenderNormalization.ts +128 -29
  124. package/src/NativeEditorResultNormalization.ts +143 -32
  125. package/src/NativeEditorTypes.ts +12 -11
  126. package/src/NativeEditorV2Decimal.ts +12 -3
  127. package/src/NativeProseViewer.tsx +46 -16
  128. package/src/ResourceLimits.ts +15 -8
  129. package/src/RichTextEditor.tsx +3 -1
  130. package/src/RichTextEditorNativeTypes.tsx +1 -1
  131. package/src/RichTextEditorNativeView.tsx +2 -8
  132. package/src/RichTextEditorSerialization.tsx +70 -24
  133. package/src/RichTextEditorTypes.tsx +1 -1
  134. package/src/YjsCollaboration.ts +143 -47
  135. package/src/addons.ts +12 -8
  136. package/src/atomInstances.ts +25 -5
  137. package/src/atomUpdates.ts +23 -6
  138. package/src/atoms.ts +85 -18
  139. package/src/attributeValidation.ts +97 -33
  140. package/src/contentExpression.ts +218 -63
  141. package/src/listMarkers.ts +1 -1
  142. package/src/schemaDefinition.ts +82 -20
  143. package/src/schemaDocument.ts +15 -1
  144. package/src/schemaDocumentConstruction.ts +80 -16
  145. package/src/schemaNormalization.ts +155 -41
  146. package/src/schemaPresets.ts +37 -31
  147. package/src/schemaResolution.ts +126 -27
  148. package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
  149. package/src/useEditorToolbarInteractions.tsx +85 -36
  150. package/src/useEditorToolbarItems.tsx +50 -22
  151. package/src/useEditorToolbarPresentation.tsx +81 -58
  152. package/src/useEditorToolbarState.tsx +8 -6
  153. package/src/useFocusPreservingFrames.ts +43 -15
  154. package/src/useNativeEditor.ts +111 -51
  155. package/src/useRichTextEditorCommands.tsx +127 -54
  156. package/src/useRichTextEditorEvents.tsx +144 -42
  157. package/src/useRichTextEditorMentions.tsx +118 -37
  158. package/src/useRichTextEditorPresentation.tsx +128 -114
  159. package/src/useRichTextEditorState.tsx +76 -40
  160. package/src/useRichTextEditorUpdates.tsx +207 -56
  161. package/src/useViewerAtoms.tsx +162 -66
package/README.md CHANGED
@@ -147,7 +147,7 @@ Addons are a readonly array. Conditional `false`, `null`, and `undefined` entrie
147
147
 
148
148
  ```tsx
149
149
  import { createMentionsAddon } from '@apollohg/react-native-rich-text-editor';
150
- import { createCodeHighlightingAddon } from '@react-native-rich-text-editor/code-highlighting';
150
+ import { createCodeHighlightingAddon } from '@apollohg/react-native-rich-text-editor-code-highlighting';
151
151
 
152
152
  <RichTextEditor
153
153
  documentHandle={documentHandle}
@@ -6,7 +6,7 @@ Include the applicable notices and source links with distributed applications or
6
6
 
7
7
  ## Package scope
8
8
 
9
- `@apollohg/react-native-rich-text-editor` — core Rust engine, generated UniFFI bindings, native dependencies, and copied Material Icons assets. The optional `@react-native-rich-text-editor/code-highlighting` package has its own notices file.
9
+ `@apollohg/react-native-rich-text-editor` — core Rust engine, generated UniFFI bindings, native dependencies, and copied Material Icons assets. The optional `@apollohg/react-native-rich-text-editor-code-highlighting` package has its own notices file.
10
10
 
11
11
  ## Rust dependencies
12
12
 
@@ -86,6 +86,9 @@ tasks.register('buildHostEditorCore', Exec) {
86
86
  // by a transformed Android artifact.
87
87
  def hostTestJnaClasspath = files(configurations.hostTestJna)
88
88
  tasks.withType(Test).configureEach {
89
+ // Security fixtures can be selected through the process environment.
90
+ outputs.upToDateWhen { false }
91
+ outputs.cacheIf { false }
89
92
  dependsOn tasks.named('buildHostEditorCore')
90
93
  inputs.files(hostTestJnaClasspath).withPropertyName('hostTestJnaClasspath')
91
94
  systemProperty 'uniffi.component.editor_core.libraryOverride', hostEditorCoreLibrary.absolutePath
package/app.plugin.js CHANGED
@@ -4,59 +4,62 @@ const { createRequire } = require('module');
4
4
  const pkg = require('./package.json');
5
5
 
6
6
  const PACKAGING_EXCLUDES_PROPERTY = 'android.packagingOptions.excludes';
7
+
7
8
  const LEGACY_JNA_ABI_EXCLUDES = [
8
- '**/armeabi/libjnidispatch.so',
9
- '**/mips/libjnidispatch.so',
10
- '**/mips64/libjnidispatch.so',
9
+ '**/armeabi/libjnidispatch.so',
10
+ '**/mips/libjnidispatch.so',
11
+ '**/mips64/libjnidispatch.so',
11
12
  ];
12
13
 
13
14
  function requireExpoConfigPlugins() {
14
- try {
15
- return require('expo/config-plugins');
16
- } catch (error) {
17
- if (error.code !== 'MODULE_NOT_FOUND') {
18
- throw error;
19
- }
15
+ try {
16
+ return require('expo/config-plugins');
17
+ } catch (error) {
18
+ if (error.code !== 'MODULE_NOT_FOUND') {
19
+ throw error;
20
+ }
20
21
 
21
- const appRequire = createRequire(path.join(process.cwd(), 'package.json'));
22
- return appRequire('expo/config-plugins');
23
- }
22
+ const appRequire = createRequire(path.join(process.cwd(), 'package.json'));
23
+
24
+ return appRequire('expo/config-plugins');
25
+ }
24
26
  }
25
27
 
26
28
  function mergeCommaList(value, additions) {
27
- const values = (value || '')
28
- .split(',')
29
- .map((item) => item.trim())
30
- .filter(Boolean);
29
+ const values = (value || '')
30
+ .split(',')
31
+ .map(item => item.trim())
32
+ .filter(Boolean);
31
33
 
32
- return Array.from(new Set([...values, ...additions])).join(',');
34
+ return Array.from(new Set([ ...values, ...additions ])).join(',');
33
35
  }
34
36
 
35
37
  function withReactNativeProseEditor(config) {
36
- const { withGradleProperties } = requireExpoConfigPlugins();
37
-
38
- return withGradleProperties(config, (config) => {
39
- const existing = config.modResults.find(
40
- (property) => property.type === 'property' && property.key === PACKAGING_EXCLUDES_PROPERTY
41
- );
42
- const value = mergeCommaList(existing && existing.value, LEGACY_JNA_ABI_EXCLUDES);
43
-
44
- if (existing) {
45
- existing.value = value;
46
- } else {
47
- config.modResults.push({
48
- type: 'property',
49
- key: PACKAGING_EXCLUDES_PROPERTY,
50
- value,
51
- });
52
- }
38
+ const { withGradleProperties } = requireExpoConfigPlugins();
39
+
40
+ return withGradleProperties(config, config => {
41
+ const existing = config.modResults.find(
42
+ property => property.type === 'property' && property.key === PACKAGING_EXCLUDES_PROPERTY
43
+ );
44
+
45
+ const value = mergeCommaList(existing && existing.value, LEGACY_JNA_ABI_EXCLUDES);
46
+
47
+ if (existing) {
48
+ existing.value = value;
49
+ } else {
50
+ config.modResults.push({
51
+ type: 'property',
52
+ key: PACKAGING_EXCLUDES_PROPERTY,
53
+ value,
54
+ });
55
+ }
53
56
 
54
- return config;
55
- });
57
+ return config;
58
+ });
56
59
  }
57
60
 
58
61
  module.exports = requireExpoConfigPlugins().createRunOncePlugin(
59
- withReactNativeProseEditor,
60
- pkg.name,
61
- pkg.version
62
+ withReactNativeProseEditor,
63
+ pkg.name,
64
+ pkg.version
62
65
  );
package/dist/AtomHost.js CHANGED
@@ -40,8 +40,9 @@ const react_1 = __importStar(require("react"));
40
40
  const react_native_1 = require("react-native");
41
41
  const atomInstances_1 = require("./atomInstances");
42
42
  function atomIsVisible(y, height, viewport) {
43
- if (!viewport)
43
+ if (!viewport) {
44
44
  return true;
45
+ }
45
46
  if (![viewport.y, viewport.height, viewport.overscan ?? 200].every(Number.isFinite) ||
46
47
  viewport.height < 0 ||
47
48
  (viewport.overscan ?? 200) < 0) {
@@ -64,8 +65,9 @@ class AtomErrorBoundary extends react_1.default.Component {
64
65
  : { component: props.component, error: false };
65
66
  }
66
67
  render() {
67
- if (!this.state.error)
68
+ if (!this.state.error) {
68
69
  return this.props.children;
70
+ }
69
71
  return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { accessibilityRole: 'alert', style: { minHeight: 32, padding: 8 }, children: [(0, jsx_runtime_1.jsxs)(react_native_1.Text, { children: ["Unable to display ", this.props.nodeType] }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { accessibilityRole: 'button', onPress: () => this.setState({ error: false }), children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { children: "Retry" }) })] }));
70
72
  }
71
73
  }
@@ -85,30 +87,35 @@ function AtomHost({ component: Component, atomProps, width, estimatedHeight, vis
85
87
  };
86
88
  }, []);
87
89
  const updateAttrs = (0, react_1.useCallback)(async (update) => {
88
- if (!mounted.current)
90
+ if (!mounted.current) {
89
91
  throw new atomInstances_1.AtomUpdateAttrsError('not-ready', 'The atom is unmounted.');
92
+ }
90
93
  const request = ++latestRequest.current;
91
- setPending((count) => count + 1);
94
+ setPending(count => count + 1);
92
95
  setUpdateError(null);
93
96
  try {
94
97
  await applyUpdate(update);
95
98
  }
96
99
  catch (error) {
97
- if (mounted.current && latestRequest.current === request)
100
+ if (mounted.current && latestRequest.current === request) {
98
101
  setUpdateError(error instanceof Error ? error : new Error(String(error)));
102
+ }
99
103
  throw error;
100
104
  }
101
105
  finally {
102
- if (mounted.current)
103
- setPending((count) => count - 1);
106
+ if (mounted.current) {
107
+ setPending(count => count - 1);
108
+ }
104
109
  }
105
110
  }, [applyUpdate]);
106
111
  const editor = (0, react_1.useMemo)(() => {
107
- if (!atomProps.editor)
112
+ if (!atomProps.editor) {
108
113
  return undefined;
114
+ }
109
115
  const guard = (action) => async () => {
110
- if (!mounted.current)
116
+ if (!mounted.current) {
111
117
  throw new atomInstances_1.AtomUpdateAttrsError('not-ready', 'The atom is unmounted.');
118
+ }
112
119
  return action();
113
120
  };
114
121
  return {
@@ -120,14 +127,14 @@ function AtomHost({ component: Component, atomProps, width, estimatedHeight, vis
120
127
  }, [atomProps.editor]);
121
128
  const retainedHeight = measurement.width === width ? measurement.height : estimatedHeight;
122
129
  const show = visible || focused || active || pending > 0 || atomProps.selected;
123
- return ((0, jsx_runtime_1.jsx)(react_native_1.View, { testID: 'atom-host', nativeID: nativeID, collapsable: false, pointerEvents: atomProps.interactive === false ? 'none' : 'box-none', accessibilityElementsHidden: !show, importantForAccessibility: !show ? 'no-hide-descendants' : 'auto', onFocus: () => setFocused(true), onBlur: () => setFocused(false), onLayout: (event) => {
130
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { testID: 'atom-host', nativeID: nativeID, collapsable: false, pointerEvents: atomProps.interactive === false ? 'none' : 'box-none', accessibilityElementsHidden: !show, importantForAccessibility: !show ? 'no-hide-descendants' : 'auto', onFocus: () => setFocused(true), onBlur: () => setFocused(false), onLayout: event => {
124
131
  onMeasure?.(event);
125
132
  const size = event.nativeEvent.layout;
126
133
  if (show &&
127
134
  Number.isFinite(size.height) &&
128
135
  size.height >= 0 &&
129
136
  Math.abs(size.width - width) <= 1) {
130
- setMeasurement((previous) => previous.width === width && previous.height === size.height
137
+ setMeasurement(previous => previous.width === width && previous.height === size.height
131
138
  ? previous
132
139
  : { width, height: size.height });
133
140
  }
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMentionsAddon = createMentionsAddon;
4
4
  function copyConfiguration(value, ancestors = new Set()) {
5
- if (value === null || typeof value !== 'object')
5
+ if (value === null || typeof value !== 'object') {
6
6
  return value;
7
- if (ancestors.has(value))
7
+ }
8
+ if (ancestors.has(value)) {
8
9
  throw new Error('Addon configuration must not contain cycles.');
10
+ }
9
11
  if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) {
10
12
  throw new Error('Addon configuration must contain only plain objects and arrays.');
11
13
  }
@@ -5,30 +5,38 @@ function isRecord(value) {
5
5
  return value !== null && typeof value === 'object' && !Array.isArray(value);
6
6
  }
7
7
  function normalizeEditorAddons(addons) {
8
- if (addons === undefined)
8
+ if (addons === undefined) {
9
9
  return {};
10
- if (!Array.isArray(addons))
10
+ }
11
+ if (!Array.isArray(addons)) {
11
12
  throw new Error('addons must be a flat readonly array.');
13
+ }
12
14
  const normalized = {};
13
15
  const ids = new Set();
14
16
  for (const [index, addon] of addons.entries()) {
15
- if (addon === false || addon === null || addon === undefined)
17
+ if (addon === false || addon === null || addon === undefined) {
16
18
  continue;
19
+ }
17
20
  const path = `addons[${index}]`;
18
- if (!isRecord(addon))
21
+ if (!isRecord(addon)) {
19
22
  throw new Error(`${path} must be an addon descriptor.`);
20
- if (addon.version !== 1)
23
+ }
24
+ if (addon.version !== 1) {
21
25
  throw new Error(`${path}.version must be 1.`);
26
+ }
22
27
  if (addon.capability !== 'mentions' && addon.capability !== 'code-highlighting') {
23
28
  throw new Error(`${path}.capability is unsupported.`);
24
29
  }
25
- if (addon.id !== addon.capability)
30
+ if (addon.id !== addon.capability) {
26
31
  throw new Error(`${path}.id must match its capability.`);
27
- if (ids.has(addon.capability))
28
- throw new Error(`${path}: duplicate addon id '${addon.id}'.`);
32
+ }
33
+ if (ids.has(addon.capability)) {
34
+ throw new Error(`${path}: duplicate addon id '${String(addon.id)}'.`);
35
+ }
29
36
  ids.add(addon.capability);
30
- if (!isRecord(addon.options))
37
+ if (!isRecord(addon.options)) {
31
38
  throw new Error(`${path}.options must be an object.`);
39
+ }
32
40
  if (addon.capability === 'mentions') {
33
41
  normalized.mentions = addon.options;
34
42
  }
@@ -4,12 +4,15 @@ exports.normalizeEditorMentionTheme = normalizeEditorMentionTheme;
4
4
  const EditorStyleSheetNormalization_1 = require("./EditorStyleSheetNormalization");
5
5
  const EditorMentionThemeValidation_1 = require("./EditorMentionThemeValidation");
6
6
  function normalizeEditorMentionTheme(theme) {
7
- if (theme === undefined)
7
+ if (theme === undefined) {
8
8
  return undefined;
9
- if (!(0, EditorMentionThemeValidation_1.validEditorMentionTheme)(theme))
9
+ }
10
+ if (!(0, EditorMentionThemeValidation_1.validEditorMentionTheme)(theme)) {
10
11
  throw new TypeError('Invalid mention theme');
11
- if (!theme.node)
12
+ }
13
+ if (!theme.node) {
12
14
  return theme;
15
+ }
13
16
  const node = theme.node;
14
17
  const { textColor, style: existingStyle, ...appearance } = node;
15
18
  const style = (0, EditorStyleSheetNormalization_1.normalizeEditorTheme)({
@@ -9,7 +9,7 @@ function isPlainRecord(value) {
9
9
  return value !== null && typeof value === 'object' && !Array.isArray(value);
10
10
  }
11
11
  function hasOnlyOwnKeys(value, fields) {
12
- return Reflect.ownKeys(value).every((key) => typeof key === 'string' && fields.includes(key));
12
+ return Reflect.ownKeys(value).every(key => typeof key === 'string' && fields.includes(key));
13
13
  }
14
14
  exports.MENTION_NODE_STRING_FIELDS = [
15
15
  'textColor',
@@ -41,7 +41,17 @@ exports.MENTION_SUGGESTIONS_NUMBER_FIELDS = [
41
41
  'borderWidth',
42
42
  'borderRadius',
43
43
  ];
44
- exports.EDITOR_MENTION_THEME_FONT_WEIGHTS = new Set(['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900']);
44
+ exports.EDITOR_MENTION_THEME_FONT_WEIGHTS = new Set(['normal',
45
+ 'bold',
46
+ '100',
47
+ '200',
48
+ '300',
49
+ '400',
50
+ '500',
51
+ '600',
52
+ '700',
53
+ '800',
54
+ '900']);
45
55
  exports.EDITOR_MENTION_THEME_FIELDS = [
46
56
  'node',
47
57
  'suggestions',
@@ -52,12 +62,14 @@ function validMentionFontWeight(value) {
52
62
  exports.EDITOR_MENTION_THEME_FONT_WEIGHTS.has(value)));
53
63
  }
54
64
  function validMentionThemeSection(value, stringFields, numberFields, extraFields) {
55
- if (!isPlainRecord(value))
65
+ if (!isPlainRecord(value)) {
56
66
  return false;
57
- if (!hasOnlyOwnKeys(value, [...stringFields, ...numberFields, ...extraFields]))
67
+ }
68
+ if (!hasOnlyOwnKeys(value, [...stringFields, ...numberFields, ...extraFields])) {
58
69
  return false;
59
- return (stringFields.every((field) => value[field] === undefined || typeof value[field] === 'string') &&
60
- numberFields.every((field) => value[field] === undefined ||
70
+ }
71
+ return (stringFields.every(field => value[field] === undefined || typeof value[field] === 'string') &&
72
+ numberFields.every(field => value[field] === undefined ||
61
73
  (typeof value[field] === 'number' && Number.isFinite(value[field]))));
62
74
  }
63
75
  function validEditorMentionTheme(value) {
@@ -66,16 +78,19 @@ function validEditorMentionTheme(value) {
66
78
  }
67
79
  const { node, suggestions } = value;
68
80
  if (node !== undefined) {
69
- if (!isPlainRecord(node))
81
+ if (!isPlainRecord(node)) {
70
82
  return false;
83
+ }
71
84
  const { textColor, style, ...appearance } = node;
72
- if (textColor !== undefined && typeof textColor !== 'string')
85
+ if (textColor !== undefined && typeof textColor !== 'string') {
73
86
  return false;
87
+ }
74
88
  try {
75
89
  (0, EditorStyleSheetNormalization_1.normalizeEditorTheme)({ mention: [{ color: textColor }, appearance] });
76
90
  if (style !== undefined) {
77
- if (!isPlainRecord(style))
91
+ if (!isPlainRecord(style)) {
78
92
  return false;
93
+ }
79
94
  (0, EditorStyleSheetNormalization_1.normalizeEditorTheme)({ mention: style });
80
95
  }
81
96
  }
@@ -83,13 +98,15 @@ function validEditorMentionTheme(value) {
83
98
  return false;
84
99
  }
85
100
  }
86
- if (suggestions === undefined)
101
+ if (suggestions === undefined) {
87
102
  return true;
103
+ }
88
104
  if (!validMentionThemeSection(suggestions, exports.MENTION_SUGGESTIONS_STRING_FIELDS, exports.MENTION_SUGGESTIONS_NUMBER_FIELDS, ['option'])) {
89
105
  return false;
90
106
  }
91
107
  const option = suggestions.option;
92
- if (option === undefined)
108
+ if (option === undefined) {
93
109
  return true;
110
+ }
94
111
  return (validMentionThemeSection(option, exports.MENTION_OPTION_STRING_FIELDS, exports.MENTION_OPTION_NUMBER_FIELDS, ['fontWeight']) && validMentionFontWeight(option.fontWeight));
95
112
  }
@@ -22,14 +22,14 @@ const border = [
22
22
  'borderColor',
23
23
  'borderStyle',
24
24
  'borderRadius',
25
- ...sides.flatMap((side) => [`border${side}Width`, `border${side}Color`]),
26
- ...corners.map((corner) => `border${corner}Radius`),
25
+ ...sides.flatMap(side => [`border${side}Width`, `border${side}Color`]),
26
+ ...corners.map(corner => `border${corner}Radius`),
27
27
  ];
28
28
  const spacing = (prefix) => [
29
29
  prefix,
30
30
  `${prefix}Horizontal`,
31
31
  `${prefix}Vertical`,
32
- ...sides.map((side) => `${prefix}${side}`),
32
+ ...sides.map(side => `${prefix}${side}`),
33
33
  ];
34
34
  const surface = ['backgroundColor', ...border, ...spacing('padding')];
35
35
  const box = [...surface, ...spacing('margin')];
@@ -68,8 +68,22 @@ const fields = {
68
68
  };
69
69
  const enums = {
70
70
  fontStyle: ['normal', 'italic'],
71
- fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
72
- textAlign: ['auto', 'left', 'right', 'center', 'justify'],
71
+ fontWeight: ['normal',
72
+ 'bold',
73
+ '100',
74
+ '200',
75
+ '300',
76
+ '400',
77
+ '500',
78
+ '600',
79
+ '700',
80
+ '800',
81
+ '900'],
82
+ textAlign: ['auto',
83
+ 'left',
84
+ 'right',
85
+ 'center',
86
+ 'justify'],
73
87
  textDecorationLine: ['none', 'underline', 'line-through', 'underline line-through'],
74
88
  textDecorationStyle: ['solid', 'double', 'dotted', 'dashed'],
75
89
  borderStyle: ['solid', 'dashed', 'dotted'],
@@ -79,39 +93,50 @@ function invalid(path, reason) {
79
93
  throw new TypeError(`Invalid editor style ${path}: ${reason}`);
80
94
  }
81
95
  function record(value) {
82
- if (value == null || typeof value !== 'object' || Array.isArray(value))
96
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) {
83
97
  return false;
98
+ }
84
99
  const prototype = Object.getPrototypeOf(value);
85
100
  return prototype === Object.prototype || prototype === null;
86
101
  }
87
102
  function normalizeEditorColor(value, path) {
88
- if (typeof value !== 'string')
103
+ if (typeof value !== 'string') {
89
104
  return invalid(path, 'expected a color string');
105
+ }
90
106
  const argb = (0, react_native_1.processColor)(value);
91
- if (typeof argb !== 'number')
107
+ if (typeof argb !== 'number') {
92
108
  return invalid(path, 'unrecognized color');
109
+ }
93
110
  const rgba = ((argb << 8) | (argb >>> 24)) >>> 0;
94
111
  return `#${rgba.toString(16).padStart(8, '0')}`;
95
112
  }
96
113
  function orderedMarker(value, path) {
97
- if (!record(value))
114
+ if (!record(value)) {
98
115
  return invalid(path, 'expected an ordered marker object');
116
+ }
99
117
  const result = {};
100
118
  for (const [key, entry] of Object.entries(value)) {
101
- if (key !== 'schemes' && key !== 'suffix')
119
+ if (key !== 'schemes' && key !== 'suffix') {
102
120
  invalid(`${path}.${key}`, 'unsupported property');
103
- if (entry === undefined)
121
+ }
122
+ if (entry === undefined) {
104
123
  continue;
124
+ }
105
125
  if (key === 'suffix') {
106
- if (entry !== '.' && entry !== ')')
126
+ if (entry !== '.' && entry !== ')') {
107
127
  invalid(`${path}.${key}`, 'expected . or )');
128
+ }
108
129
  result[key] = entry;
109
130
  }
110
131
  else {
111
- const schemes = ['decimal', 'lowerAlpha', 'upperAlpha', 'lowerRoman', 'upperRoman'];
132
+ const schemes = ['decimal',
133
+ 'lowerAlpha',
134
+ 'upperAlpha',
135
+ 'lowerRoman',
136
+ 'upperRoman'];
112
137
  if (!Array.isArray(entry) ||
113
138
  entry.length === 0 ||
114
- !entry.every((item) => typeof item === 'string' && schemes.includes(item))) {
139
+ !entry.every(item => typeof item === 'string' && schemes.includes(item))) {
115
140
  invalid(`${path}.${key}`, 'expected a nonempty array of numbering schemes');
116
141
  }
117
142
  result[key] = [...entry];
@@ -120,54 +145,68 @@ function orderedMarker(value, path) {
120
145
  return result;
121
146
  }
122
147
  function property(key, value, path) {
123
- if (value === undefined)
148
+ if (value === undefined) {
124
149
  return undefined;
125
- if (key === 'ordered')
150
+ }
151
+ if (key === 'ordered') {
126
152
  return orderedMarker(value, path);
127
- if (key === 'checked')
153
+ }
154
+ if (key === 'checked') {
128
155
  return normalizeStyle(value, checkbox, path);
129
- if (key === 'color' || key.endsWith('Color'))
156
+ }
157
+ if (key === 'color' || key.endsWith('Color')) {
130
158
  return normalizeEditorColor(value, path);
159
+ }
131
160
  if (key === 'fontFamily') {
132
- if (typeof value !== 'string' || value.length === 0)
161
+ if (typeof value !== 'string' || value.length === 0) {
133
162
  invalid(path, 'expected a nonempty font family');
163
+ }
134
164
  return value;
135
165
  }
136
166
  if (enums[key]) {
137
167
  const candidate = key === 'fontWeight' && typeof value === 'number' ? String(value) : value;
138
- if (typeof candidate !== 'string' || !enums[key].includes(candidate))
168
+ if (typeof candidate !== 'string' || !enums[key].includes(candidate)) {
139
169
  invalid(path, 'unsupported value');
170
+ }
140
171
  return candidate;
141
172
  }
142
- if (typeof value !== 'number' || !Number.isFinite(value))
173
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
143
174
  invalid(path, 'expected a finite number');
144
- if (['fontSize', 'lineHeight', 'size', 'scale'].includes(key) && value <= 0)
175
+ }
176
+ if (['fontSize', 'lineHeight', 'size', 'scale'].includes(key) && value <= 0) {
145
177
  invalid(path, 'expected a positive number');
146
- if (!key.startsWith('margin') && key !== 'letterSpacing' && value < 0)
178
+ }
179
+ if (!key.startsWith('margin') && key !== 'letterSpacing' && value < 0) {
147
180
  invalid(path, 'expected a nonnegative number');
181
+ }
148
182
  return value;
149
183
  }
150
184
  function normalizeStyle(value, allowed, path) {
151
185
  const raw = {};
152
186
  const ancestors = new Set();
153
187
  function append(entry, depth) {
154
- if (entry === false || entry == null)
188
+ if (entry === false || entry == null) {
155
189
  return;
156
- if (depth > 64)
190
+ }
191
+ if (depth > 64) {
157
192
  invalid(path, 'style arrays are nested too deeply');
193
+ }
158
194
  if (Array.isArray(entry)) {
159
- if (ancestors.has(entry))
195
+ if (ancestors.has(entry)) {
160
196
  invalid(path, 'cyclic style array');
197
+ }
161
198
  ancestors.add(entry);
162
- entry.forEach((item) => append(item, depth + 1));
199
+ entry.forEach(item => append(item, depth + 1));
163
200
  ancestors.delete(entry);
164
201
  return;
165
202
  }
166
- if (!record(entry))
203
+ if (!record(entry)) {
167
204
  invalid(path, 'expected a style object or array');
205
+ }
168
206
  for (const [key, field] of Object.entries(entry)) {
169
- if (!allowed.includes(key))
207
+ if (!allowed.includes(key)) {
170
208
  invalid(`${path}.${key}`, 'unsupported property');
209
+ }
171
210
  raw[key] = property(key, field, `${path}.${key}`);
172
211
  }
173
212
  }
@@ -177,8 +216,9 @@ function normalizeStyle(value, allowed, path) {
177
216
  for (const side of sides) {
178
217
  const axis = side === 'Top' || side === 'Bottom' ? 'Vertical' : 'Horizontal';
179
218
  const resolved = raw[`${prefix}${side}`] ?? raw[`${prefix}${axis}`] ?? raw[prefix];
180
- if (resolved !== undefined)
219
+ if (resolved !== undefined) {
181
220
  result[`${prefix}${side}`] = resolved;
221
+ }
182
222
  }
183
223
  delete result[prefix];
184
224
  delete result[`${prefix}Horizontal`];
@@ -187,40 +227,47 @@ function normalizeStyle(value, allowed, path) {
187
227
  for (const suffix of ['Width', 'Color']) {
188
228
  for (const side of sides) {
189
229
  const resolved = raw[`border${side}${suffix}`] ?? raw[`border${suffix}`];
190
- if (resolved !== undefined)
230
+ if (resolved !== undefined) {
191
231
  result[`border${side}${suffix}`] = resolved;
232
+ }
192
233
  }
193
234
  delete result[`border${suffix}`];
194
235
  }
195
236
  for (const corner of corners) {
196
237
  const resolved = raw[`border${corner}Radius`] ?? raw.borderRadius;
197
- if (resolved !== undefined)
238
+ if (resolved !== undefined) {
198
239
  result[`border${corner}Radius`] = resolved;
240
+ }
199
241
  }
200
242
  delete result.borderRadius;
201
243
  return result;
202
244
  }
203
245
  function normalizeEditorTheme(theme) {
204
- if (!record(theme))
246
+ if (!record(theme)) {
205
247
  invalid('theme', 'expected a named style map');
248
+ }
206
249
  const styles = {};
207
250
  const result = { version: 1 };
208
251
  for (const [key, value] of Object.entries(theme)) {
209
252
  if (key === 'toolbar') {
210
253
  if (value !== undefined) {
211
- if (!record(value))
254
+ if (!record(value)) {
212
255
  invalid('toolbar', 'expected toolbar configuration');
256
+ }
213
257
  result.toolbar = { ...value };
214
258
  }
215
259
  continue;
216
260
  }
217
- if (!Object.prototype.hasOwnProperty.call(fields, key))
261
+ if (!Object.prototype.hasOwnProperty.call(fields, key)) {
218
262
  invalid(key, 'unsupported element');
263
+ }
219
264
  const style = normalizeStyle(value, fields[key], key);
220
- if (Object.keys(style).length)
265
+ if (Object.keys(style).length) {
221
266
  styles[key] = style;
267
+ }
222
268
  }
223
- if (Object.keys(styles).length)
269
+ if (Object.keys(styles).length) {
224
270
  result.styles = styles;
271
+ }
225
272
  return result;
226
273
  }
@@ -114,4 +114,8 @@ export interface EditorContentInsets {
114
114
  bottom?: number;
115
115
  left?: number;
116
116
  }
117
+ /**
118
+ * Mentions are configured on the mentions addon, not on EditorTheme; native
119
+ * still reads them from the theme payload.
120
+ */
117
121
  export declare function serializeEditorTheme(theme?: EditorTheme, mentionTheme?: EditorMentionTheme): string | undefined;