react-native-enriched-markdown-scaffold 0.6.0-scaffold.4 → 0.6.0-scaffold.6

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 (63) hide show
  1. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +36 -0
  2. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +1 -0
  3. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +3 -0
  4. package/android/src/main/java/com/swmansion/enriched/markdown/spans/MathModels.kt +1 -0
  5. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +3 -1
  6. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +3 -1
  7. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +14 -0
  8. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +1 -0
  9. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +2 -1
  10. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +3 -1
  11. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +2 -1
  12. package/android/src/math/java/com/swmansion/enriched/markdown/utils/math/LatexWeightWrapper.kt +23 -0
  13. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +8 -1
  14. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +5 -1
  15. package/ios/attachments/ENRMMathInlineAttachment.h +3 -0
  16. package/ios/attachments/ENRMMathInlineAttachment.m +2 -1
  17. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +36 -0
  18. package/ios/input/ENRMInputFormatter.h +6 -0
  19. package/ios/input/ENRMInputFormatter.mm +2 -0
  20. package/ios/input/EnrichedMarkdownTextInput.mm +2 -0
  21. package/ios/input/InputStylePropsUtils.h +8 -0
  22. package/ios/math/ENRMRaTeXBridge.swift +16 -2
  23. package/ios/renderer/ENRMMathInlineRenderer.m +1 -0
  24. package/ios/styles/StyleConfig.h +4 -0
  25. package/ios/styles/StyleConfig.mm +24 -0
  26. package/ios/utils/StylePropsUtils.h +10 -0
  27. package/ios/views/ENRMMathContainerView.m +2 -1
  28. package/lib/module/EnrichedMarkdownNativeComponent.ts +2 -0
  29. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  30. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +1 -0
  31. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +2 -0
  32. package/lib/module/normalizeMarkdownStyle.js +4 -2
  33. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  34. package/lib/module/normalizeMarkdownStyle.web.js +4 -2
  35. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  36. package/lib/module/normalizeMarkdownTextInputStyle.js +10 -3
  37. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  38. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +2 -0
  39. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  40. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +12 -0
  41. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  42. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +1 -0
  43. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  44. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +2 -0
  45. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  46. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  47. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  48. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +2 -0
  49. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  50. package/lib/typescript/src/types/MarkdownStyle.d.ts +14 -0
  51. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  52. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +3 -0
  53. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  54. package/package.json +2 -1
  55. package/src/EnrichedMarkdownNativeComponent.ts +2 -0
  56. package/src/EnrichedMarkdownTextInput.tsx +12 -0
  57. package/src/EnrichedMarkdownTextInputNativeComponent.ts +1 -0
  58. package/src/EnrichedMarkdownTextNativeComponent.ts +2 -0
  59. package/src/normalizeMarkdownStyle.ts +6 -1
  60. package/src/normalizeMarkdownStyle.web.ts +6 -1
  61. package/src/normalizeMarkdownTextInputStyle.ts +14 -0
  62. package/src/types/MarkdownStyle.ts +14 -0
  63. package/src/types/MarkdownStyleInternal.ts +4 -0
@@ -1534,6 +1534,7 @@ struct EnrichedMarkdownMarkdownStyleMathStruct {
1534
1534
  Float marginTop{0.0};
1535
1535
  Float marginBottom{0.0};
1536
1536
  std::string textAlign{};
1537
+ std::string fontWeight{};
1537
1538
 
1538
1539
 
1539
1540
  #ifdef RN_SERIALIZABLE_STATE
@@ -1548,6 +1549,7 @@ struct EnrichedMarkdownMarkdownStyleMathStruct {
1548
1549
  result["marginTop"] = marginTop;
1549
1550
  result["marginBottom"] = marginBottom;
1550
1551
  result["textAlign"] = textAlign;
1552
+ result["fontWeight"] = fontWeight;
1551
1553
  return result;
1552
1554
  }
1553
1555
  #endif
@@ -1584,6 +1586,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
1584
1586
  if (tmp_textAlign != map.end()) {
1585
1587
  fromRawValue(context, tmp_textAlign->second, result.textAlign);
1586
1588
  }
1589
+ auto tmp_fontWeight = map.find("fontWeight");
1590
+ if (tmp_fontWeight != map.end()) {
1591
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
1592
+ }
1587
1593
  }
1588
1594
 
1589
1595
  static inline std::string toString(const EnrichedMarkdownMarkdownStyleMathStruct &value) {
@@ -1598,6 +1604,7 @@ static inline folly::dynamic toDynamic(const EnrichedMarkdownMarkdownStyleMathSt
1598
1604
 
1599
1605
  struct EnrichedMarkdownMarkdownStyleInlineMathStruct {
1600
1606
  SharedColor color{};
1607
+ std::string fontWeight{};
1601
1608
 
1602
1609
 
1603
1610
  #ifdef RN_SERIALIZABLE_STATE
@@ -1606,6 +1613,7 @@ struct EnrichedMarkdownMarkdownStyleInlineMathStruct {
1606
1613
  folly::dynamic toDynamic() const {
1607
1614
  folly::dynamic result = folly::dynamic::object();
1608
1615
  result["color"] = ::facebook::react::toDynamic(color);
1616
+ result["fontWeight"] = fontWeight;
1609
1617
  return result;
1610
1618
  }
1611
1619
  #endif
@@ -1618,6 +1626,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
1618
1626
  if (tmp_color != map.end()) {
1619
1627
  fromRawValue(context, tmp_color->second, result.color);
1620
1628
  }
1629
+ auto tmp_fontWeight = map.find("fontWeight");
1630
+ if (tmp_fontWeight != map.end()) {
1631
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
1632
+ }
1621
1633
  }
1622
1634
 
1623
1635
  static inline std::string toString(const EnrichedMarkdownMarkdownStyleInlineMathStruct &value) {
@@ -2509,6 +2521,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathStruct {
2509
2521
  Float paddingVertical{0.0};
2510
2522
  SharedColor selectedBackgroundColor{};
2511
2523
  SharedColor selectedBorderColor{};
2524
+ std::string fontWeight{};
2512
2525
 
2513
2526
 
2514
2527
  #ifdef RN_SERIALIZABLE_STATE
@@ -2526,6 +2539,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathStruct {
2526
2539
  result["paddingVertical"] = paddingVertical;
2527
2540
  result["selectedBackgroundColor"] = ::facebook::react::toDynamic(selectedBackgroundColor);
2528
2541
  result["selectedBorderColor"] = ::facebook::react::toDynamic(selectedBorderColor);
2542
+ result["fontWeight"] = fontWeight;
2529
2543
  return result;
2530
2544
  }
2531
2545
  #endif
@@ -2574,6 +2588,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
2574
2588
  if (tmp_selectedBorderColor != map.end()) {
2575
2589
  fromRawValue(context, tmp_selectedBorderColor->second, result.selectedBorderColor);
2576
2590
  }
2591
+ auto tmp_fontWeight = map.find("fontWeight");
2592
+ if (tmp_fontWeight != map.end()) {
2593
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
2594
+ }
2577
2595
  }
2578
2596
 
2579
2597
  static inline std::string toString(const EnrichedMarkdownTextInputMarkdownStyleMathStruct &value) {
@@ -2597,6 +2615,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathBlockStruct {
2597
2615
  Float paddingVertical{0.0};
2598
2616
  SharedColor selectedBackgroundColor{};
2599
2617
  SharedColor selectedBorderColor{};
2618
+ std::string fontWeight{};
2600
2619
  Float marginTop{0.0};
2601
2620
  Float marginBottom{0.0};
2602
2621
  std::string alignment{};
@@ -2617,6 +2636,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathBlockStruct {
2617
2636
  result["paddingVertical"] = paddingVertical;
2618
2637
  result["selectedBackgroundColor"] = ::facebook::react::toDynamic(selectedBackgroundColor);
2619
2638
  result["selectedBorderColor"] = ::facebook::react::toDynamic(selectedBorderColor);
2639
+ result["fontWeight"] = fontWeight;
2620
2640
  result["marginTop"] = marginTop;
2621
2641
  result["marginBottom"] = marginBottom;
2622
2642
  result["alignment"] = alignment;
@@ -2668,6 +2688,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
2668
2688
  if (tmp_selectedBorderColor != map.end()) {
2669
2689
  fromRawValue(context, tmp_selectedBorderColor->second, result.selectedBorderColor);
2670
2690
  }
2691
+ auto tmp_fontWeight = map.find("fontWeight");
2692
+ if (tmp_fontWeight != map.end()) {
2693
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
2694
+ }
2671
2695
  auto tmp_marginTop = map.find("marginTop");
2672
2696
  if (tmp_marginTop != map.end()) {
2673
2697
  fromRawValue(context, tmp_marginTop->second, result.marginTop);
@@ -4423,6 +4447,7 @@ struct EnrichedMarkdownTextMarkdownStyleMathStruct {
4423
4447
  Float marginTop{0.0};
4424
4448
  Float marginBottom{0.0};
4425
4449
  std::string textAlign{};
4450
+ std::string fontWeight{};
4426
4451
 
4427
4452
 
4428
4453
  #ifdef RN_SERIALIZABLE_STATE
@@ -4437,6 +4462,7 @@ struct EnrichedMarkdownTextMarkdownStyleMathStruct {
4437
4462
  result["marginTop"] = marginTop;
4438
4463
  result["marginBottom"] = marginBottom;
4439
4464
  result["textAlign"] = textAlign;
4465
+ result["fontWeight"] = fontWeight;
4440
4466
  return result;
4441
4467
  }
4442
4468
  #endif
@@ -4473,6 +4499,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
4473
4499
  if (tmp_textAlign != map.end()) {
4474
4500
  fromRawValue(context, tmp_textAlign->second, result.textAlign);
4475
4501
  }
4502
+ auto tmp_fontWeight = map.find("fontWeight");
4503
+ if (tmp_fontWeight != map.end()) {
4504
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
4505
+ }
4476
4506
  }
4477
4507
 
4478
4508
  static inline std::string toString(const EnrichedMarkdownTextMarkdownStyleMathStruct &value) {
@@ -4487,6 +4517,7 @@ static inline folly::dynamic toDynamic(const EnrichedMarkdownTextMarkdownStyleMa
4487
4517
 
4488
4518
  struct EnrichedMarkdownTextMarkdownStyleInlineMathStruct {
4489
4519
  SharedColor color{};
4520
+ std::string fontWeight{};
4490
4521
 
4491
4522
 
4492
4523
  #ifdef RN_SERIALIZABLE_STATE
@@ -4495,6 +4526,7 @@ struct EnrichedMarkdownTextMarkdownStyleInlineMathStruct {
4495
4526
  folly::dynamic toDynamic() const {
4496
4527
  folly::dynamic result = folly::dynamic::object();
4497
4528
  result["color"] = ::facebook::react::toDynamic(color);
4529
+ result["fontWeight"] = fontWeight;
4498
4530
  return result;
4499
4531
  }
4500
4532
  #endif
@@ -4507,6 +4539,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
4507
4539
  if (tmp_color != map.end()) {
4508
4540
  fromRawValue(context, tmp_color->second, result.color);
4509
4541
  }
4542
+ auto tmp_fontWeight = map.find("fontWeight");
4543
+ if (tmp_fontWeight != map.end()) {
4544
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
4545
+ }
4510
4546
  }
4511
4547
 
4512
4548
  static inline std::string toString(const EnrichedMarkdownTextMarkdownStyleInlineMathStruct &value) {
@@ -396,6 +396,7 @@ object MeasurementStore {
396
396
  fontSize = style.mathStyle.fontSize,
397
397
  latex = segment.latex,
398
398
  mode = MathRenderMode.Display,
399
+ fontWeight = style.mathStyle.fontWeight,
399
400
  ),
400
401
  )
401
402
  }
@@ -13,6 +13,7 @@ open class MathChipStyle(
13
13
  val paddingVertical: Float,
14
14
  val selectedBackgroundColor: Int?,
15
15
  val selectedBorderColor: Int?,
16
+ val fontWeight: String,
16
17
  ) {
17
18
  open fun isBlock(): Boolean = false
18
19
  }
@@ -28,6 +29,7 @@ class MathBlockStyle(
28
29
  paddingVertical: Float,
29
30
  selectedBackgroundColor: Int?,
30
31
  selectedBorderColor: Int?,
32
+ fontWeight: String,
31
33
  val marginTop: Float,
32
34
  val marginBottom: Float,
33
35
  val alignment: Layout.Alignment,
@@ -42,6 +44,7 @@ class MathBlockStyle(
42
44
  paddingVertical,
43
45
  selectedBackgroundColor,
44
46
  selectedBorderColor,
47
+ fontWeight,
45
48
  ) {
46
49
  override fun isBlock(): Boolean = true
47
50
  }
@@ -9,6 +9,7 @@ data class MathMeasureRequest(
9
9
  val fontSize: Float,
10
10
  val latex: String,
11
11
  val mode: MathRenderMode = MathRenderMode.Text,
12
+ val fontWeight: String = "normal",
12
13
  )
13
14
 
14
15
  data class MathMetrics(
@@ -4,6 +4,7 @@ import com.facebook.react.bridge.ReadableMap
4
4
 
5
5
  data class InlineMathStyle(
6
6
  val color: Int,
7
+ val fontWeight: String,
7
8
  ) {
8
9
  companion object {
9
10
  fun fromReadableMap(
@@ -11,7 +12,8 @@ data class InlineMathStyle(
11
12
  parser: StyleParser,
12
13
  ): InlineMathStyle {
13
14
  val color = parser.parseColor(map, "color")
14
- return InlineMathStyle(color)
15
+ val fontWeight = parser.parseString(map, "fontWeight", "normal")
16
+ return InlineMathStyle(color, fontWeight)
15
17
  }
16
18
  }
17
19
  }
@@ -10,6 +10,7 @@ data class MathStyle(
10
10
  val marginTop: Float,
11
11
  val marginBottom: Float,
12
12
  val textAlign: String,
13
+ val fontWeight: String,
13
14
  ) {
14
15
  companion object {
15
16
  fun fromReadableMap(
@@ -23,7 +24,8 @@ data class MathStyle(
23
24
  val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
24
25
  val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
25
26
  val textAlign = parser.parseString(map, "textAlign", "center")
26
- return MathStyle(fontSize, color, backgroundColor, padding, marginTop, marginBottom, textAlign)
27
+ val fontWeight = parser.parseString(map, "fontWeight", "normal")
28
+ return MathStyle(fontSize, color, backgroundColor, padding, marginTop, marginBottom, textAlign, fontWeight)
27
29
  }
28
30
  }
29
31
  }
@@ -76,6 +76,7 @@ object MarkdownStyleParser {
76
76
  if (mathMap?.hasKey("selectedBackgroundColor") == true) mathMap.getInt("selectedBackgroundColor") else null
77
77
  val selectedBorderColor =
78
78
  if (mathMap?.hasKey("selectedBorderColor") == true) mathMap.getInt("selectedBorderColor") else null
79
+ val fontWeight = parseFontWeight(mathMap)
79
80
 
80
81
  return MathChipStyle(
81
82
  color = color,
@@ -88,6 +89,7 @@ object MarkdownStyleParser {
88
89
  paddingVertical = paddingVertical,
89
90
  selectedBackgroundColor = nullIfTransparent(selectedBackgroundColor),
90
91
  selectedBorderColor = nullIfTransparent(selectedBorderColor),
92
+ fontWeight = fontWeight,
91
93
  )
92
94
  }
93
95
 
@@ -158,6 +160,12 @@ object MarkdownStyleParser {
158
160
  "right" -> Layout.Alignment.ALIGN_OPPOSITE
159
161
  else -> Layout.Alignment.ALIGN_CENTER
160
162
  }
163
+ val fontWeight =
164
+ if (mathBlockMap?.hasKey("fontWeight") == true) {
165
+ normalizeFontWeight(mathBlockMap.getString("fontWeight"))
166
+ } else {
167
+ inlineFallback.fontWeight
168
+ }
161
169
 
162
170
  return MathBlockStyle(
163
171
  color = color,
@@ -170,12 +178,18 @@ object MarkdownStyleParser {
170
178
  paddingVertical = paddingVertical,
171
179
  selectedBackgroundColor = nullIfTransparent(selectedBackgroundColor),
172
180
  selectedBorderColor = nullIfTransparent(selectedBorderColor),
181
+ fontWeight = fontWeight,
173
182
  marginTop = marginTop,
174
183
  marginBottom = marginBottom,
175
184
  alignment = alignment,
176
185
  )
177
186
  }
178
187
 
188
+ private fun parseFontWeight(map: ReadableMap?): String =
189
+ if (map?.hasKey("fontWeight") == true) normalizeFontWeight(map.getString("fontWeight")) else "normal"
190
+
191
+ private fun normalizeFontWeight(raw: String?): String = if (raw == "bold") "bold" else "normal"
192
+
179
193
  private fun nullIfTransparent(color: Int?): Int? {
180
194
  if (color == null) return null
181
195
  if (Color.alpha(color) == 0) return null
@@ -35,6 +35,7 @@ class MathInlineRenderer(
35
35
  latex = latex,
36
36
  fontSize = blockStyle.fontSize,
37
37
  textColor = config.style.inlineMathStyle.color,
38
+ fontWeight = config.style.inlineMathStyle.fontWeight,
38
39
  )
39
40
 
40
41
  builder.setSpan(span, start, end, SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE)
@@ -8,6 +8,7 @@ import android.text.Layout
8
8
  import android.text.style.ReplacementSpan
9
9
  import com.swmansion.enriched.markdown.input.model.MathBlockStyle
10
10
  import com.swmansion.enriched.markdown.input.model.MathChipStyle
11
+ import com.swmansion.enriched.markdown.utils.math.LatexWeightWrapper
11
12
  import io.ratex.RaTeXEngine
12
13
  import io.ratex.RaTeXFontLoader
13
14
  import io.ratex.RaTeXRenderer
@@ -62,7 +63,7 @@ class MathChipSpan(
62
63
  try {
63
64
  val displayList =
64
65
  RaTeXEngine.parseBlocking(
65
- latex,
66
+ LatexWeightWrapper.wrap(latex, style.fontWeight),
66
67
  displayMode = displayMode,
67
68
  color = style.color,
68
69
  )
@@ -5,6 +5,7 @@ import android.graphics.Bitmap
5
5
  import android.graphics.Canvas
6
6
  import android.graphics.Paint
7
7
  import android.text.style.ReplacementSpan
8
+ import com.swmansion.enriched.markdown.utils.math.LatexWeightWrapper
8
9
  import io.ratex.RaTeXEngine
9
10
  import io.ratex.RaTeXFontLoader
10
11
  import io.ratex.RaTeXRenderer
@@ -15,6 +16,7 @@ class MathInlineSpan(
15
16
  internal val latex: String,
16
17
  internal val fontSize: Float,
17
18
  private val textColor: Int,
19
+ private val fontWeight: String = "normal",
18
20
  ) : ReplacementSpan() {
19
21
  private var cachedBitmap: Bitmap? = null
20
22
  private var cachedWidth = 0
@@ -27,7 +29,7 @@ class MathInlineSpan(
27
29
  if (renderFailed) return
28
30
 
29
31
  try {
30
- val displayList = RaTeXEngine.parseBlocking(latex, displayMode = false, color = textColor)
32
+ val displayList = RaTeXEngine.parseBlocking(LatexWeightWrapper.wrap(latex, fontWeight), displayMode = false, color = textColor)
31
33
  val renderer = RaTeXRenderer(displayList, fontSize) { RaTeXFontLoader.getTypeface(it) }
32
34
 
33
35
  cachedWidth = renderer.widthPx.toInt().coerceAtLeast(1)
@@ -2,6 +2,7 @@ package com.swmansion.enriched.markdown.spans
2
2
 
3
3
  import android.content.Context
4
4
  import android.util.Log
5
+ import com.swmansion.enriched.markdown.utils.math.LatexWeightWrapper
5
6
  import io.ratex.RaTeXEngine
6
7
  import io.ratex.RaTeXFontLoader
7
8
  import io.ratex.RaTeXRenderer
@@ -27,7 +28,7 @@ object MathMeasureHelper {
27
28
  ): MathMetrics {
28
29
  val displayList =
29
30
  RaTeXEngine.parseBlocking(
30
- request.latex,
31
+ LatexWeightWrapper.wrap(request.latex, request.fontWeight),
31
32
  displayMode = request.mode == MathRenderMode.Display,
32
33
  )
33
34
 
@@ -0,0 +1,23 @@
1
+ package com.swmansion.enriched.markdown.utils.math
2
+
3
+ /**
4
+ * Wraps a raw LaTeX expression with the appropriate KaTeX bold command so RaTeX
5
+ * picks up the bold glyph variant (KaTeX_Main-Bold / KaTeX_Math-BoldItalic).
6
+ *
7
+ * Wrap is render-time only — callers must keep the original `latex` string
8
+ * stored on chips/attachments so serialized markdown round-trips cleanly.
9
+ *
10
+ * Caveat: large operators (`\sum`, `\int`, `\prod`), AMS symbols, Script and
11
+ * Typewriter glyphs have no bold variant in the bundled KaTeX fonts and stay
12
+ * at regular weight even when wrapped.
13
+ */
14
+ object LatexWeightWrapper {
15
+ fun wrap(
16
+ latex: String,
17
+ fontWeight: String,
18
+ ): String =
19
+ when (fontWeight) {
20
+ "bold" -> "\\mathbf{$latex}"
21
+ else -> latex
22
+ }
23
+ }
@@ -16,6 +16,7 @@ import com.swmansion.enriched.markdown.spans.MathMeasureRequest
16
16
  import com.swmansion.enriched.markdown.spans.MathRenderMode
17
17
  import com.swmansion.enriched.markdown.styles.MathStyle
18
18
  import com.swmansion.enriched.markdown.styles.StyleConfig
19
+ import com.swmansion.enriched.markdown.utils.math.LatexWeightWrapper
19
20
  import io.ratex.RaTeXEngine
20
21
  import io.ratex.RaTeXFontLoader
21
22
  import io.ratex.RaTeXRenderer
@@ -82,7 +83,12 @@ class MathContainerView(
82
83
  fun applyLatex(latex: String) {
83
84
  cachedLatex = latex
84
85
  try {
85
- val displayList = RaTeXEngine.parseBlocking(latex, displayMode = true, color = mathStyle.color)
86
+ val displayList =
87
+ RaTeXEngine.parseBlocking(
88
+ LatexWeightWrapper.wrap(latex, mathStyle.fontWeight),
89
+ displayMode = true,
90
+ color = mathStyle.color,
91
+ )
86
92
  mathView.renderer = RaTeXRenderer(displayList, mathStyle.fontSize) { RaTeXFontLoader.getTypeface(it) }
87
93
  } catch (e: Exception) {
88
94
  Log.e(TAG, "Failed to render LaTeX", e)
@@ -138,6 +144,7 @@ class MathContainerView(
138
144
  fontSize = mathStyle.fontSize,
139
145
  latex = latex,
140
146
  mode = MathRenderMode.Display,
147
+ fontWeight = mathStyle.fontWeight,
141
148
  )
142
149
  val metrics = MathMeasureHelper.measure(context, listOf(request)).first()
143
150
  return ceil(metrics.ascent + metrics.descent).toInt() + (mathStyle.padding * 2)
@@ -25,7 +25,11 @@
25
25
  - (void)renderForMacOS
26
26
  {
27
27
  RCTUIColor *color = self.mathTextColor ?: [RCTUIColor blackColor];
28
- ENRMRaTeXRenderResult *result = [ENRMRaTeXBridge parse:self.latex displayMode:NO fontSize:self.fontSize color:color];
28
+ ENRMRaTeXRenderResult *result = [ENRMRaTeXBridge parse:self.latex
29
+ displayMode:NO
30
+ fontSize:self.fontSize
31
+ color:color
32
+ fontWeight:self.fontWeight];
29
33
  if (!result)
30
34
  return;
31
35
 
@@ -8,6 +8,9 @@ NS_ASSUME_NONNULL_BEGIN
8
8
  @property (nonatomic, strong) NSString *latex;
9
9
  @property (nonatomic, assign) CGFloat fontSize;
10
10
  @property (nonatomic, strong, nullable) RCTUIColor *mathTextColor;
11
+ /// `@"bold"` to render with KaTeX bold variant. `nil`/`@"normal"` keeps the
12
+ /// default (regular) glyph. Render-time only — never written back to `latex`.
13
+ @property (nonatomic, copy, nullable) NSString *fontWeight;
11
14
 
12
15
  /// YES if block math (`$$...$$`), NO for inline (`$...$`).
13
16
  @property (nonatomic, assign) BOOL displayMode;
@@ -21,7 +21,8 @@
21
21
  ENRMRaTeXRenderResult *result = [ENRMRaTeXBridge parse:self.latex
22
22
  displayMode:self.displayMode
23
23
  fontSize:self.fontSize
24
- color:color];
24
+ color:color
25
+ fontWeight:self.fontWeight];
25
26
  if (!result)
26
27
  return;
27
28
 
@@ -1534,6 +1534,7 @@ struct EnrichedMarkdownMarkdownStyleMathStruct {
1534
1534
  Float marginTop{0.0};
1535
1535
  Float marginBottom{0.0};
1536
1536
  std::string textAlign{};
1537
+ std::string fontWeight{};
1537
1538
 
1538
1539
 
1539
1540
  #ifdef RN_SERIALIZABLE_STATE
@@ -1548,6 +1549,7 @@ struct EnrichedMarkdownMarkdownStyleMathStruct {
1548
1549
  result["marginTop"] = marginTop;
1549
1550
  result["marginBottom"] = marginBottom;
1550
1551
  result["textAlign"] = textAlign;
1552
+ result["fontWeight"] = fontWeight;
1551
1553
  return result;
1552
1554
  }
1553
1555
  #endif
@@ -1584,6 +1586,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
1584
1586
  if (tmp_textAlign != map.end()) {
1585
1587
  fromRawValue(context, tmp_textAlign->second, result.textAlign);
1586
1588
  }
1589
+ auto tmp_fontWeight = map.find("fontWeight");
1590
+ if (tmp_fontWeight != map.end()) {
1591
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
1592
+ }
1587
1593
  }
1588
1594
 
1589
1595
  static inline std::string toString(const EnrichedMarkdownMarkdownStyleMathStruct &value) {
@@ -1598,6 +1604,7 @@ static inline folly::dynamic toDynamic(const EnrichedMarkdownMarkdownStyleMathSt
1598
1604
 
1599
1605
  struct EnrichedMarkdownMarkdownStyleInlineMathStruct {
1600
1606
  SharedColor color{};
1607
+ std::string fontWeight{};
1601
1608
 
1602
1609
 
1603
1610
  #ifdef RN_SERIALIZABLE_STATE
@@ -1606,6 +1613,7 @@ struct EnrichedMarkdownMarkdownStyleInlineMathStruct {
1606
1613
  folly::dynamic toDynamic() const {
1607
1614
  folly::dynamic result = folly::dynamic::object();
1608
1615
  result["color"] = ::facebook::react::toDynamic(color);
1616
+ result["fontWeight"] = fontWeight;
1609
1617
  return result;
1610
1618
  }
1611
1619
  #endif
@@ -1618,6 +1626,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
1618
1626
  if (tmp_color != map.end()) {
1619
1627
  fromRawValue(context, tmp_color->second, result.color);
1620
1628
  }
1629
+ auto tmp_fontWeight = map.find("fontWeight");
1630
+ if (tmp_fontWeight != map.end()) {
1631
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
1632
+ }
1621
1633
  }
1622
1634
 
1623
1635
  static inline std::string toString(const EnrichedMarkdownMarkdownStyleInlineMathStruct &value) {
@@ -2509,6 +2521,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathStruct {
2509
2521
  Float paddingVertical{0.0};
2510
2522
  SharedColor selectedBackgroundColor{};
2511
2523
  SharedColor selectedBorderColor{};
2524
+ std::string fontWeight{};
2512
2525
 
2513
2526
 
2514
2527
  #ifdef RN_SERIALIZABLE_STATE
@@ -2526,6 +2539,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathStruct {
2526
2539
  result["paddingVertical"] = paddingVertical;
2527
2540
  result["selectedBackgroundColor"] = ::facebook::react::toDynamic(selectedBackgroundColor);
2528
2541
  result["selectedBorderColor"] = ::facebook::react::toDynamic(selectedBorderColor);
2542
+ result["fontWeight"] = fontWeight;
2529
2543
  return result;
2530
2544
  }
2531
2545
  #endif
@@ -2574,6 +2588,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
2574
2588
  if (tmp_selectedBorderColor != map.end()) {
2575
2589
  fromRawValue(context, tmp_selectedBorderColor->second, result.selectedBorderColor);
2576
2590
  }
2591
+ auto tmp_fontWeight = map.find("fontWeight");
2592
+ if (tmp_fontWeight != map.end()) {
2593
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
2594
+ }
2577
2595
  }
2578
2596
 
2579
2597
  static inline std::string toString(const EnrichedMarkdownTextInputMarkdownStyleMathStruct &value) {
@@ -2597,6 +2615,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathBlockStruct {
2597
2615
  Float paddingVertical{0.0};
2598
2616
  SharedColor selectedBackgroundColor{};
2599
2617
  SharedColor selectedBorderColor{};
2618
+ std::string fontWeight{};
2600
2619
  Float marginTop{0.0};
2601
2620
  Float marginBottom{0.0};
2602
2621
  std::string alignment{};
@@ -2617,6 +2636,7 @@ struct EnrichedMarkdownTextInputMarkdownStyleMathBlockStruct {
2617
2636
  result["paddingVertical"] = paddingVertical;
2618
2637
  result["selectedBackgroundColor"] = ::facebook::react::toDynamic(selectedBackgroundColor);
2619
2638
  result["selectedBorderColor"] = ::facebook::react::toDynamic(selectedBorderColor);
2639
+ result["fontWeight"] = fontWeight;
2620
2640
  result["marginTop"] = marginTop;
2621
2641
  result["marginBottom"] = marginBottom;
2622
2642
  result["alignment"] = alignment;
@@ -2668,6 +2688,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
2668
2688
  if (tmp_selectedBorderColor != map.end()) {
2669
2689
  fromRawValue(context, tmp_selectedBorderColor->second, result.selectedBorderColor);
2670
2690
  }
2691
+ auto tmp_fontWeight = map.find("fontWeight");
2692
+ if (tmp_fontWeight != map.end()) {
2693
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
2694
+ }
2671
2695
  auto tmp_marginTop = map.find("marginTop");
2672
2696
  if (tmp_marginTop != map.end()) {
2673
2697
  fromRawValue(context, tmp_marginTop->second, result.marginTop);
@@ -4423,6 +4447,7 @@ struct EnrichedMarkdownTextMarkdownStyleMathStruct {
4423
4447
  Float marginTop{0.0};
4424
4448
  Float marginBottom{0.0};
4425
4449
  std::string textAlign{};
4450
+ std::string fontWeight{};
4426
4451
 
4427
4452
 
4428
4453
  #ifdef RN_SERIALIZABLE_STATE
@@ -4437,6 +4462,7 @@ struct EnrichedMarkdownTextMarkdownStyleMathStruct {
4437
4462
  result["marginTop"] = marginTop;
4438
4463
  result["marginBottom"] = marginBottom;
4439
4464
  result["textAlign"] = textAlign;
4465
+ result["fontWeight"] = fontWeight;
4440
4466
  return result;
4441
4467
  }
4442
4468
  #endif
@@ -4473,6 +4499,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
4473
4499
  if (tmp_textAlign != map.end()) {
4474
4500
  fromRawValue(context, tmp_textAlign->second, result.textAlign);
4475
4501
  }
4502
+ auto tmp_fontWeight = map.find("fontWeight");
4503
+ if (tmp_fontWeight != map.end()) {
4504
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
4505
+ }
4476
4506
  }
4477
4507
 
4478
4508
  static inline std::string toString(const EnrichedMarkdownTextMarkdownStyleMathStruct &value) {
@@ -4487,6 +4517,7 @@ static inline folly::dynamic toDynamic(const EnrichedMarkdownTextMarkdownStyleMa
4487
4517
 
4488
4518
  struct EnrichedMarkdownTextMarkdownStyleInlineMathStruct {
4489
4519
  SharedColor color{};
4520
+ std::string fontWeight{};
4490
4521
 
4491
4522
 
4492
4523
  #ifdef RN_SERIALIZABLE_STATE
@@ -4495,6 +4526,7 @@ struct EnrichedMarkdownTextMarkdownStyleInlineMathStruct {
4495
4526
  folly::dynamic toDynamic() const {
4496
4527
  folly::dynamic result = folly::dynamic::object();
4497
4528
  result["color"] = ::facebook::react::toDynamic(color);
4529
+ result["fontWeight"] = fontWeight;
4498
4530
  return result;
4499
4531
  }
4500
4532
  #endif
@@ -4507,6 +4539,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
4507
4539
  if (tmp_color != map.end()) {
4508
4540
  fromRawValue(context, tmp_color->second, result.color);
4509
4541
  }
4542
+ auto tmp_fontWeight = map.find("fontWeight");
4543
+ if (tmp_fontWeight != map.end()) {
4544
+ fromRawValue(context, tmp_fontWeight->second, result.fontWeight);
4545
+ }
4510
4546
  }
4511
4547
 
4512
4548
  static inline std::string toString(const EnrichedMarkdownTextMarkdownStyleInlineMathStruct &value) {
@@ -50,6 +50,9 @@ NS_ASSUME_NONNULL_BEGIN
50
50
  @property (nonatomic, assign) CGFloat mathPaddingVertical;
51
51
  @property (nonatomic, strong, nullable) RCTUIColor *mathSelectedBackgroundColor;
52
52
  @property (nonatomic, strong, nullable) RCTUIColor *mathSelectedBorderColor;
53
+ /// `@"bold"` to render inline math with KaTeX bold variant.
54
+ /// `nil`/`@"normal"` = default regular weight.
55
+ @property (nonatomic, copy, nullable) NSString *mathFontWeight;
53
56
 
54
57
  /// Math block (`$$...$$`)
55
58
  @property (nonatomic, strong, nullable) RCTUIColor *mathBlockColor;
@@ -65,6 +68,9 @@ NS_ASSUME_NONNULL_BEGIN
65
68
  @property (nonatomic, assign) CGFloat mathBlockMarginTop;
66
69
  @property (nonatomic, assign) CGFloat mathBlockMarginBottom;
67
70
  @property (nonatomic, assign) NSTextAlignment mathBlockAlignment;
71
+ /// `@"bold"` to render block math with KaTeX bold variant.
72
+ /// `nil`/`@"normal"` = default regular weight.
73
+ @property (nonatomic, copy, nullable) NSString *mathBlockFontWeight;
68
74
 
69
75
  - (UIFont *)fontForTraits:(UIFontDescriptorSymbolicTraits)traits;
70
76
  - (void)invalidateFontCache;
@@ -56,6 +56,7 @@
56
56
  copy.mathPaddingVertical = _mathPaddingVertical;
57
57
  copy.mathSelectedBackgroundColor = _mathSelectedBackgroundColor;
58
58
  copy.mathSelectedBorderColor = _mathSelectedBorderColor;
59
+ copy.mathFontWeight = _mathFontWeight;
59
60
  copy.mathBlockColor = _mathBlockColor;
60
61
  copy.mathBlockFontSize = _mathBlockFontSize;
61
62
  copy.mathBlockBackgroundColor = _mathBlockBackgroundColor;
@@ -69,6 +70,7 @@
69
70
  copy.mathBlockMarginTop = _mathBlockMarginTop;
70
71
  copy.mathBlockMarginBottom = _mathBlockMarginBottom;
71
72
  copy.mathBlockAlignment = _mathBlockAlignment;
73
+ copy.mathBlockFontWeight = _mathBlockFontWeight;
72
74
  return copy;
73
75
  }
74
76
 
@@ -683,6 +683,7 @@ using namespace facebook::react;
683
683
  att.blockAlignment = _formatterStyle.mathBlockAlignment;
684
684
  att.selectedBackgroundColor = _formatterStyle.mathBlockSelectedBackgroundColor;
685
685
  att.selectedBorderColor = _formatterStyle.mathBlockSelectedBorderColor;
686
+ att.fontWeight = _formatterStyle.mathBlockFontWeight;
686
687
  } else {
687
688
  att.fontSize = _formatterStyle.mathFontSize > 0 ? _formatterStyle.mathFontSize : 16.0;
688
689
  att.mathTextColor = _formatterStyle.mathColor ?: _formatterStyle.baseTextColor;
@@ -697,6 +698,7 @@ using namespace facebook::react;
697
698
  att.blockAlignment = NSTextAlignmentNatural;
698
699
  att.selectedBackgroundColor = _formatterStyle.mathSelectedBackgroundColor;
699
700
  att.selectedBorderColor = _formatterStyle.mathSelectedBorderColor;
701
+ att.fontWeight = _formatterStyle.mathFontWeight;
700
702
  }
701
703
  }
702
704