react-native-enriched-markdown-scaffold 0.7.4-scaffold.1 → 0.7.4-scaffold.11

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 (120) hide show
  1. package/android/build.gradle +5 -0
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +9 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +3 -0
  4. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +10 -0
  5. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +7 -0
  6. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +10 -0
  7. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +50 -0
  8. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +6 -4
  9. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +38 -0
  10. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +174 -9
  11. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
  12. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockSyntaxSentinel.kt +69 -0
  13. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +71 -12
  14. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +8 -0
  15. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputLayoutManager.kt +30 -2
  16. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +7 -2
  17. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +3 -0
  18. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +1 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +8 -1
  20. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +27 -1
  21. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +5 -1
  22. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathFontWeight.kt +25 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +12 -1
  24. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +7 -7
  25. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +10 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
  27. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/SpannableExtensions.kt +12 -4
  28. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +1 -1
  29. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +2 -0
  30. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  31. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlinePlaceholderSpan.kt +7 -3
  32. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +8 -5
  33. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathTypeface.kt +30 -0
  34. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +3 -1
  35. package/docs/API_REFERENCE.md +43 -0
  36. package/docs/INPUT.md +87 -0
  37. package/docs/LATEX_MATH.md +62 -0
  38. package/docs/STYLES.md +3 -0
  39. package/ios/EnrichedMarkdown.mm +44 -12
  40. package/ios/EnrichedMarkdownText.mm +47 -11
  41. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +5 -1
  42. package/ios/attachments/ENRMMathInlineAttachment.h +3 -0
  43. package/ios/attachments/ENRMMathInlineAttachment.m +2 -1
  44. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +10 -0
  45. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +7 -0
  46. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +10 -0
  47. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +50 -0
  48. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +29 -0
  49. package/ios/input/ENRMBlockSyntaxSentinel.h +25 -0
  50. package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -0
  51. package/ios/input/ENRMInputFormatter.h +4 -0
  52. package/ios/input/ENRMInputFormatter.mm +2 -0
  53. package/ios/input/ENRMInputParser.h +5 -0
  54. package/ios/input/ENRMInputParser.mm +79 -6
  55. package/ios/input/ENRMInputTextView.mm +11 -1
  56. package/ios/input/EnrichedMarkdownTextInput.h +5 -0
  57. package/ios/input/EnrichedMarkdownTextInput.mm +88 -22
  58. package/ios/input/InputStylePropsUtils.h +13 -0
  59. package/ios/internals/MeasurementCache.h +1 -0
  60. package/ios/math/ENRMRaTeXBridge.swift +52 -3
  61. package/ios/parser/ENRMMarkdownParser.h +8 -0
  62. package/ios/parser/ENRMMarkdownParser.mm +11 -0
  63. package/ios/renderer/ENRMMathInlineRenderer.m +3 -0
  64. package/ios/renderer/ListItemRenderer.m +8 -5
  65. package/ios/styles/StyleConfig.h +6 -0
  66. package/ios/styles/StyleConfig.mm +36 -0
  67. package/ios/utils/ENRMMathFontWeight.h +18 -0
  68. package/ios/utils/StylePropsUtils.h +21 -0
  69. package/ios/views/ENRMMathContainerView.m +3 -1
  70. package/lib/module/EnrichedMarkdownNativeComponent.ts +3 -0
  71. package/lib/module/EnrichedMarkdownTextInput.js +17 -0
  72. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  73. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +34 -0
  74. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +3 -0
  75. package/lib/module/index.js.map +1 -1
  76. package/lib/module/normalizeMarkdownStyle.js +5 -2
  77. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  78. package/lib/module/normalizeMarkdownStyle.web.js +5 -2
  79. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  80. package/lib/module/normalizeMarkdownTextInputStyle.js +7 -3
  81. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  82. package/lib/module/web/globalStyles.js +8 -1
  83. package/lib/module/web/globalStyles.js.map +1 -1
  84. package/lib/module/web/styles.js +3 -1
  85. package/lib/module/web/styles.js.map +1 -1
  86. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +3 -0
  87. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  88. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +26 -1
  89. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  90. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +28 -0
  91. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  92. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +3 -0
  93. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  94. package/lib/typescript/src/index.d.ts +1 -1
  95. package/lib/typescript/src/index.d.ts.map +1 -1
  96. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  97. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  98. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +1 -0
  99. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  100. package/lib/typescript/src/types/MarkdownStyle.d.ts +32 -0
  101. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  102. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +3 -0
  103. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  104. package/lib/typescript/src/types/events.d.ts +15 -0
  105. package/lib/typescript/src/types/events.d.ts.map +1 -1
  106. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  107. package/package.json +1 -1
  108. package/src/EnrichedMarkdownNativeComponent.ts +3 -0
  109. package/src/EnrichedMarkdownTextInput.tsx +41 -0
  110. package/src/EnrichedMarkdownTextInputNativeComponent.ts +34 -0
  111. package/src/EnrichedMarkdownTextNativeComponent.ts +3 -0
  112. package/src/index.tsx +1 -0
  113. package/src/normalizeMarkdownStyle.ts +6 -1
  114. package/src/normalizeMarkdownStyle.web.ts +6 -1
  115. package/src/normalizeMarkdownTextInputStyle.ts +5 -0
  116. package/src/types/MarkdownStyle.ts +32 -0
  117. package/src/types/MarkdownStyleInternal.ts +3 -0
  118. package/src/types/events.ts +16 -0
  119. package/src/web/globalStyles.ts +7 -0
  120. package/src/web/styles.ts +5 -1
@@ -141,10 +141,13 @@ interface MathStyleInternal {
141
141
  marginTop: CodegenTypes.Float;
142
142
  marginBottom: CodegenTypes.Float;
143
143
  textAlign: string;
144
+ fontWeight: string;
144
145
  }
145
146
 
146
147
  interface InlineMathStyleInternal {
147
148
  color: ColorValue;
149
+ paddingVertical: CodegenTypes.Float;
150
+ fontWeight: string;
148
151
  }
149
152
 
150
153
  interface SpoilerParticlesStyleInternal {
@@ -37,6 +37,7 @@ import type {
37
37
  TextStyle,
38
38
  ColorValue,
39
39
  } from 'react-native';
40
+ import type { OnPasteEvent } from './types/events';
40
41
  import { normalizeMarkdownTextInputStyle } from './normalizeMarkdownTextInputStyle';
41
42
  import { normalizeMenuItem } from './normalizeMenuItem';
42
43
  import { toNativeRegexConfig } from './utils/regexParser';
@@ -61,6 +62,7 @@ export interface MathStyle {
61
62
  paddingVertical?: number;
62
63
  selectedBackgroundColor?: string;
63
64
  selectedBorderColor?: string;
65
+ fontWeight?: 'bold' | 'normal';
64
66
  }
65
67
 
66
68
  export interface MathBlockStyle extends MathStyle {
@@ -151,6 +153,13 @@ export interface EnrichedMarkdownTextInputInstance {
151
153
  ) => void;
152
154
  removeMath: (start: number) => void;
153
155
  copyToClipboard: () => void;
156
+ /**
157
+ * Completes a paste reported through `onPaste`. Call it exactly once per
158
+ * event: `resolvePaste('', '')` drops the clipboard content (replacing any
159
+ * selection), a non-empty `markdown` re-applies the copied formatting, and
160
+ * plain `text` inserts verbatim.
161
+ */
162
+ resolvePaste: (text: string, markdown?: string) => void;
154
163
  getMarkdown: () => Promise<string>;
155
164
  getCaretRect: () => Promise<CaretRect>;
156
165
  }
@@ -203,7 +212,17 @@ export interface EnrichedMarkdownTextInputProps extends Omit<
203
212
  editable?: boolean;
204
213
  autoFocus?: boolean;
205
214
  scrollEnabled?: boolean;
215
+ blockSyntax?: boolean;
206
216
  autoCapitalize?: string;
217
+ /**
218
+ * Report pastes through `onPaste` instead of inserting them. Only takes
219
+ * effect when `onPaste` is also set — otherwise native would swallow every
220
+ * paste with nobody left to resolve it.
221
+ *
222
+ * macOS ignores this prop and always pastes inline.
223
+ * @default false
224
+ */
225
+ interceptPaste?: boolean;
207
226
  multiline?: boolean;
208
227
  cursorColor?: ColorValue;
209
228
  selectionColor?: ColorValue;
@@ -216,6 +235,12 @@ export interface EnrichedMarkdownTextInputProps extends Omit<
216
235
  onCaretRectChange?: (rect: CaretRect) => void;
217
236
  onLinkDetected?: (event: OnLinkDetected) => void;
218
237
  onMathPress?: (event: OnMathPressEvent) => void;
238
+ /**
239
+ * Fires instead of the insert when `interceptPaste` is on. The handler owns
240
+ * the paste from here: it must call `resolvePaste` exactly once, on every
241
+ * path including failures, or the paste is silently dropped.
242
+ */
243
+ onPaste?: (event: OnPasteEvent) => void;
219
244
  mentionIndicators?: string[];
220
245
  onStartMention?: (event: OnStartMentionEvent) => void;
221
246
  onChangeMention?: (event: OnChangeMentionEvent) => void;
@@ -283,7 +308,9 @@ export const EnrichedMarkdownTextInput = ({
283
308
  editable = true,
284
309
  autoFocus = false,
285
310
  scrollEnabled = true,
311
+ blockSyntax = true,
286
312
  autoCapitalize = 'sentences',
313
+ interceptPaste = false,
287
314
  multiline = true,
288
315
  cursorColor,
289
316
  selectionColor,
@@ -294,6 +321,7 @@ export const EnrichedMarkdownTextInput = ({
294
321
  onCaretRectChange,
295
322
  onLinkDetected,
296
323
  onMathPress,
324
+ onPaste,
297
325
  mentionIndicators,
298
326
  onStartMention,
299
327
  onChangeMention,
@@ -435,6 +463,14 @@ export const EnrichedMarkdownTextInput = ({
435
463
  [onMathPress]
436
464
  );
437
465
 
466
+ const handlePaste = useCallback(
467
+ (e: NativeSyntheticEvent<OnPasteEvent>) => {
468
+ const { text, markdown } = e.nativeEvent;
469
+ onPaste?.({ text, markdown });
470
+ },
471
+ [onPaste]
472
+ );
473
+
438
474
  const handleChangeText = useCallback(
439
475
  (e: NativeSyntheticEvent<OnChangeTextEvent>) => {
440
476
  onChangeText?.(e.nativeEvent.value);
@@ -590,6 +626,8 @@ export const EnrichedMarkdownTextInput = ({
590
626
  ),
591
627
  removeMath: (start) => Commands.removeMath(commandRef, start),
592
628
  copyToClipboard: () => Commands.copyToClipboard(commandRef),
629
+ resolvePaste: (text, markdown = '') =>
630
+ Commands.resolvePaste(commandRef, text, markdown),
593
631
  getMarkdown: () =>
594
632
  new Promise<string>((resolve, reject) => {
595
633
  const requestId = nextRequestId.current++;
@@ -619,7 +657,9 @@ export const EnrichedMarkdownTextInput = ({
619
657
  editable={editable}
620
658
  autoFocus={autoFocus}
621
659
  scrollEnabled={scrollEnabled}
660
+ blockSyntax={blockSyntax}
622
661
  autoCapitalize={autoCapitalize}
662
+ interceptPaste={interceptPaste === true && onPaste != null}
623
663
  multiline={multiline}
624
664
  cursorColor={cursorColor}
625
665
  selectionColor={selectionColor}
@@ -632,6 +672,7 @@ export const EnrichedMarkdownTextInput = ({
632
672
  onChangeState={handleChangeState as NativeProps['onChangeState']}
633
673
  onLinkDetected={handleLinkDetected as NativeProps['onLinkDetected']}
634
674
  onMathPress={handleMathPress as NativeProps['onMathPress']}
675
+ onPaste={handlePaste as NativeProps['onPaste']}
635
676
  onInputFocus={handleFocus as NativeProps['onInputFocus']}
636
677
  onInputBlur={handleBlur as NativeProps['onInputBlur']}
637
678
  onRequestMarkdownResult={
@@ -19,6 +19,7 @@ interface MathStyleInternal {
19
19
  paddingVertical: CodegenTypes.Float;
20
20
  selectedBackgroundColor: ColorValue;
21
21
  selectedBorderColor: ColorValue;
22
+ fontWeight: string;
22
23
  }
23
24
 
24
25
  interface MathBlockStyleInternal extends MathStyleInternal {
@@ -140,6 +141,11 @@ export interface OnEndMentionEvent {
140
141
  indicator: string;
141
142
  }
142
143
 
144
+ export interface OnPasteEvent {
145
+ text: string;
146
+ markdown: string;
147
+ }
148
+
143
149
  export interface ContextMenuItemConfig {
144
150
  text: string;
145
151
  icon?: string;
@@ -210,10 +216,31 @@ export interface NativeProps extends ViewProps {
210
216
  * @default true
211
217
  */
212
218
  scrollEnabled?: boolean;
219
+ /**
220
+ * Whether block-level markdown syntax is interpreted.
221
+ *
222
+ * When `false`, list markers, headings, blockquotes, tables, code blocks and
223
+ * thematic breaks stay in the text verbatim instead of being consumed as
224
+ * structure, so the markdown round-trips byte-for-byte. Inline syntax
225
+ * (`**bold**`, links, `$math$`) still applies. `\r\n` is normalized to `\n`
226
+ * and `U+000B` is stripped from the input.
227
+ * @default true
228
+ */
229
+ blockSyntax?: boolean;
213
230
  /**
214
231
  * Auto-capitalization behavior.
215
232
  */
216
233
  autoCapitalize?: string;
234
+ /**
235
+ * When `true`, a paste is reported through `onPaste` instead of being
236
+ * inserted. Native reads the clipboard and leaves the buffer untouched — the
237
+ * JS handler decides what happens and must call the `resolvePaste` command
238
+ * exactly once, or the paste is dropped.
239
+ *
240
+ * macOS ignores this prop and always pastes inline.
241
+ * @default false
242
+ */
243
+ interceptPaste?: boolean;
217
244
  /**
218
245
  * Whether the input supports multiple lines.
219
246
  * @default true
@@ -300,6 +327,7 @@ export interface NativeProps extends ViewProps {
300
327
  onContextMenuItemPress?: CodegenTypes.DirectEventHandler<OnContextMenuItemPressEvent>;
301
328
  onLinkDetected?: CodegenTypes.DirectEventHandler<OnLinkDetected>;
302
329
  onMathPress?: CodegenTypes.DirectEventHandler<OnMathPressNativeEvent>;
330
+ onPaste?: CodegenTypes.DirectEventHandler<OnPasteEvent>;
303
331
  onStartMention?: CodegenTypes.DirectEventHandler<OnStartMentionEvent>;
304
332
  onChangeMention?: CodegenTypes.DirectEventHandler<OnChangeMentionEvent>;
305
333
  onEndMention?: CodegenTypes.DirectEventHandler<OnEndMentionEvent>;
@@ -356,6 +384,11 @@ interface NativeCommands {
356
384
  start: CodegenTypes.Int32
357
385
  ) => void;
358
386
  copyToClipboard: (viewRef: React.ElementRef<ComponentType>) => void;
387
+ resolvePaste: (
388
+ viewRef: React.ElementRef<ComponentType>,
389
+ text: string,
390
+ markdown: string
391
+ ) => void;
359
392
  requestMarkdown: (
360
393
  viewRef: React.ElementRef<ComponentType>,
361
394
  requestId: CodegenTypes.Int32
@@ -386,6 +419,7 @@ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
386
419
  'updateMath',
387
420
  'removeMath',
388
421
  'copyToClipboard',
422
+ 'resolvePaste',
389
423
  'requestMarkdown',
390
424
  'requestCaretRect',
391
425
  ],
@@ -141,10 +141,13 @@ interface MathStyleInternal {
141
141
  marginTop: CodegenTypes.Float;
142
142
  marginBottom: CodegenTypes.Float;
143
143
  textAlign: string;
144
+ fontWeight: string;
144
145
  }
145
146
 
146
147
  interface InlineMathStyleInternal {
147
148
  color: ColorValue;
149
+ paddingVertical: CodegenTypes.Float;
150
+ fontWeight: string;
148
151
  }
149
152
 
150
153
  interface SpoilerParticlesStyleInternal {
package/src/index.tsx CHANGED
@@ -12,6 +12,7 @@ export type {
12
12
  LinkPressEvent,
13
13
  LinkLongPressEvent,
14
14
  TaskListItemPressEvent,
15
+ OnPasteEvent,
15
16
  } from './types/events';
16
17
  export type {
17
18
  AccessibilityLabels,
@@ -193,8 +193,13 @@ const DEFAULT_NORMALIZED_STYLE = Object.freeze({
193
193
  marginTop: 0,
194
194
  marginBottom: 16,
195
195
  textAlign: 'center' as BlockTextAlign,
196
+ fontWeight: 'normal',
197
+ },
198
+ inlineMath: {
199
+ color: defaultTextColor,
200
+ paddingVertical: 4,
201
+ fontWeight: 'normal',
196
202
  },
197
- inlineMath: { color: defaultTextColor },
198
203
  taskList: {
199
204
  checkedColor: Platform.select({
200
205
  ios: normalizeColor('#007AFF')!,
@@ -177,8 +177,13 @@ const DEFAULT_NORMALIZED_STYLE: MarkdownStyleInternal = Object.freeze({
177
177
  marginTop: 0,
178
178
  marginBottom: 16,
179
179
  textAlign: 'center' as BlockTextAlign,
180
+ fontWeight: 'normal',
181
+ },
182
+ inlineMath: {
183
+ color: defaultTextColor,
184
+ paddingVertical: 4,
185
+ fontWeight: 'normal',
180
186
  },
181
- inlineMath: { color: defaultTextColor },
182
187
  taskList: {
183
188
  checkedColor: '#007AFF',
184
189
  borderColor: '#9E9E9E',
@@ -26,6 +26,7 @@ interface MathStyleInternal {
26
26
  paddingVertical: number;
27
27
  selectedBackgroundColor: ColorValue;
28
28
  selectedBorderColor: ColorValue;
29
+ fontWeight: string;
29
30
  }
30
31
 
31
32
  interface MathBlockStyleInternal extends MathStyleInternal {
@@ -76,6 +77,7 @@ const defaultMathInternal: MathStyleInternal = Object.freeze({
76
77
  paddingVertical: 0,
77
78
  selectedBackgroundColor: TRANSPARENT,
78
79
  selectedBorderColor: TRANSPARENT,
80
+ fontWeight: 'normal',
79
81
  });
80
82
 
81
83
  const defaultMathBlockInternal: MathBlockStyleInternal = Object.freeze({
@@ -89,6 +91,7 @@ const defaultMathBlockInternal: MathBlockStyleInternal = Object.freeze({
89
91
  paddingVertical: 8,
90
92
  selectedBackgroundColor: TRANSPARENT,
91
93
  selectedBorderColor: TRANSPARENT,
94
+ fontWeight: 'normal',
92
95
  marginTop: 8,
93
96
  marginBottom: 8,
94
97
  alignment: 'center',
@@ -152,6 +155,7 @@ function normalizeMathStyle(
152
155
  normalizeColor(style?.selectedBackgroundColor) ?? backgroundColor,
153
156
  selectedBorderColor:
154
157
  normalizeColor(style?.selectedBorderColor) ?? borderColor,
158
+ fontWeight: style?.fontWeight ?? fallback.fontWeight,
155
159
  };
156
160
  }
157
161
 
@@ -171,6 +175,7 @@ function normalizeMathBlockStyle(
171
175
  paddingVertical: fallback.paddingVertical,
172
176
  selectedBackgroundColor: baseInline.selectedBackgroundColor,
173
177
  selectedBorderColor: baseInline.selectedBorderColor,
178
+ fontWeight: baseInline.fontWeight,
174
179
  };
175
180
  const inheritedInline = normalizeMathStyle(style, merged);
176
181
  let alignment: 'left' | 'center' | 'right' = fallback.alignment;
@@ -155,10 +155,42 @@ interface MathStyle {
155
155
  marginTop?: number;
156
156
  marginBottom?: number;
157
157
  textAlign?: 'left' | 'center' | 'right';
158
+ /**
159
+ * Typeset the formula at bold weight.
160
+ *
161
+ * The native engine has no weight parameter and its glyph positions are
162
+ * already laid out when this applies, so `'bold'` is a SYNTHETIC embolden
163
+ * (a stroke on iOS, the platform's fake-bold on Android) rather than a
164
+ * switch to the bundled bold faces. That is deliberate: KaTeX's bold faces
165
+ * are up to 15% wider than the regular advances the layout reserved, so
166
+ * swapping them in would make glyphs collide.
167
+ * @default 'normal'
168
+ */
169
+ fontWeight?: 'bold' | 'normal';
158
170
  }
159
171
 
160
172
  interface InlineMathStyle {
161
173
  color?: string;
174
+ /**
175
+ * Empty space added above and below the formula box, in points.
176
+ * Inline formulas report their own metrics, so a fraction can be taller
177
+ * than the paragraph's `lineHeight` — which is expand-only and therefore
178
+ * cannot loosen those lines. This is the knob that does.
179
+ * @default 4
180
+ */
181
+ paddingVertical?: number;
182
+ /**
183
+ * Typeset the formula at bold weight.
184
+ *
185
+ * The native engine has no weight parameter and its glyph positions are
186
+ * already laid out when this applies, so `'bold'` is a SYNTHETIC embolden
187
+ * (a stroke on iOS, the platform's fake-bold on Android) rather than a
188
+ * switch to the bundled bold faces. That is deliberate: KaTeX's bold faces
189
+ * are up to 15% wider than the regular advances the layout reserved, so
190
+ * swapping them in would make glyphs collide.
191
+ * @default 'normal'
192
+ */
193
+ fontWeight?: 'bold' | 'normal';
162
194
  }
163
195
 
164
196
  interface SpoilerParticlesStyle {
@@ -140,10 +140,13 @@ interface MathStyleInternal {
140
140
  marginTop: number;
141
141
  marginBottom: number;
142
142
  textAlign: BlockTextAlign;
143
+ fontWeight: string;
143
144
  }
144
145
 
145
146
  interface InlineMathStyleInternal {
146
147
  color: string;
148
+ paddingVertical: number;
149
+ fontWeight: string;
147
150
  }
148
151
 
149
152
  interface SpoilerParticlesStyleInternal {
@@ -30,3 +30,19 @@ export interface OnContextMenuItemPressEvent {
30
30
  selectionStart: number;
31
31
  selectionEnd: number;
32
32
  }
33
+
34
+ /**
35
+ * Event payload fired by the native component when the user pastes while
36
+ * `interceptPaste` is on. Native does not touch the buffer — it only reports
37
+ * what the clipboard held. The handler must call `resolvePaste` exactly once,
38
+ * or the paste is dropped.
39
+ */
40
+ export interface OnPasteEvent {
41
+ /** Plain text from the clipboard, verbatim, before the text view sees it. */
42
+ text: string;
43
+ /**
44
+ * Markdown flavor, set only when the copy source was an input of this
45
+ * component. iOS-only; Android always reports `''`.
46
+ */
47
+ markdown: string;
48
+ }
@@ -8,6 +8,13 @@ const RULES: ReadonlyArray<readonly [id: string, css: string]> = [
8
8
  'enrm-selection-style',
9
9
  `.${ENRM_TEXT_CLASS} ::selection { background-color: var(${ENRM_SELECTION_BG_VAR}); }`,
10
10
  ],
11
+ // `fontWeight` for math is set on the span wrapping KaTeX's output, so the
12
+ // formula only picks it up by inheritance. `katex.css` opens `.katex` with
13
+ // the `font` shorthand, which resets `font-weight` — and a rule matching the
14
+ // element itself always beats a value inherited from an ancestor, inline
15
+ // style included. We do not load `katex.css` (MathML output needs no CSS),
16
+ // but a consumer may, so opt `.katex` back into inheriting.
17
+ ['enrm-katex-font-weight', '.katex { font-weight: inherit; }'],
11
18
  ];
12
19
 
13
20
  for (const [id, css] of RULES) {
package/src/web/styles.ts CHANGED
@@ -333,7 +333,10 @@ function highlightStyle(style: MarkdownStyleInternal): CSSProperties {
333
333
  }
334
334
 
335
335
  function mathInlineStyle(style: MarkdownStyleInternal): CSSProperties {
336
- return { color: style.inlineMath.color };
336
+ return {
337
+ color: style.inlineMath.color,
338
+ fontWeight: normalizeFontWeight(style.inlineMath.fontWeight),
339
+ };
337
340
  }
338
341
 
339
342
  function mathDisplayStyle(style: MarkdownStyleInternal): CSSProperties {
@@ -341,6 +344,7 @@ function mathDisplayStyle(style: MarkdownStyleInternal): CSSProperties {
341
344
  return {
342
345
  fontSize: math.fontSize,
343
346
  color: math.color,
347
+ fontWeight: normalizeFontWeight(math.fontWeight),
344
348
  backgroundColor: math.backgroundColor,
345
349
  padding: math.padding,
346
350
  marginTop: math.marginTop,