From 41bd007aec85c4c2476064f5bdb0c46d3dff97e5 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Tue, 11 Nov 2025 21:46:18 +0100
Subject: [PATCH 1/6] feat: add heading styles
---
.../enriched/EnrichedTextInputView.kt | 89 ++---
.../enriched/EnrichedTextInputViewManager.kt | 12 +
.../enriched/spans/EnrichedH4Span.kt | 17 +
.../enriched/spans/EnrichedH5Span.kt | 17 +
.../enriched/spans/EnrichedH6Span.kt | 17 +
.../swmansion/enriched/spans/EnrichedSpans.kt | 116 +++----
.../swmansion/enriched/styles/HtmlStyle.kt | 21 ++
.../enriched/utils/EnrichedParser.java | 54 +++-
.../enriched/utils/EnrichedSpanState.kt | 67 ++--
apps/example/src/App.tsx | 19 +-
apps/example/src/components/Toolbar.tsx | 27 ++
ios/EnrichedTextInputView.mm | 304 +++++++++---------
ios/config/InputConfig.h | 12 +
ios/config/InputConfig.mm | 60 ++++
ios/inputParser/InputParser.mm | 127 +++-----
ios/styles/BoldStyle.mm | 29 +-
ios/styles/H4Style.mm | 10 +
ios/styles/H5Style.mm | 10 +
ios/styles/H6Style.mm | 10 +
ios/styles/HeadingStyleBase.mm | 2 +-
ios/utils/StyleHeaders.h | 11 +-
ios/utils/StyleTypeEnum.h | 3 +
src/EnrichedTextInput.tsx | 35 +-
src/EnrichedTextInputNativeComponent.ts | 32 +-
src/normalizeHtmlStyle.ts | 12 +
25 files changed, 711 insertions(+), 402 deletions(-)
create mode 100644 android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
create mode 100644 android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
create mode 100644 android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
create mode 100644 ios/styles/H4Style.mm
create mode 100644 ios/styles/H5Style.mm
create mode 100644 ios/styles/H6Style.mm
diff --git a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
index 3d8ca8179..5cc963f0c 100644
--- a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
+++ b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
@@ -475,6 +475,9 @@ class EnrichedTextInputView : AppCompatEditText {
EnrichedSpans.H1 -> paragraphStyles?.toggleStyle(EnrichedSpans.H1)
EnrichedSpans.H2 -> paragraphStyles?.toggleStyle(EnrichedSpans.H2)
EnrichedSpans.H3 -> paragraphStyles?.toggleStyle(EnrichedSpans.H3)
+ EnrichedSpans.H4 -> paragraphStyles?.toggleStyle(EnrichedSpans.H4)
+ EnrichedSpans.H5 -> paragraphStyles?.toggleStyle(EnrichedSpans.H5)
+ EnrichedSpans.H6 -> paragraphStyles?.toggleStyle(EnrichedSpans.H6)
EnrichedSpans.CODE_BLOCK -> paragraphStyles?.toggleStyle(EnrichedSpans.CODE_BLOCK)
EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.toggleStyle(EnrichedSpans.BLOCK_QUOTE)
EnrichedSpans.ORDERED_LIST -> listStyles?.toggleStyle(EnrichedSpans.ORDERED_LIST)
@@ -485,54 +488,54 @@ class EnrichedTextInputView : AppCompatEditText {
layoutManager.invalidateLayout()
}
- private fun removeStyle(
- name: String,
- start: Int,
- end: Int,
- ): Boolean {
- val removed =
- when (name) {
- EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
- EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
- EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
- EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
- EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
- EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
- EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
- EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
- EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
- EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
- EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
- EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
- EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
- EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
- EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
- else -> false
- }
+ private fun removeStyle(name: String, start: Int, end: Int): Boolean {
+ val removed = when (name) {
+ EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
+ EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
+ EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
+ EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
+ EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
+ EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
+ EnrichedSpans.H4 -> paragraphStyles?.removeStyle(EnrichedSpans.H4, start, end)
+ EnrichedSpans.H5 -> paragraphStyles?.removeStyle(EnrichedSpans.H5, start, end)
+ EnrichedSpans.H6 -> paragraphStyles?.removeStyle(EnrichedSpans.H6, start, end)
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
+ EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
+ EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
+ EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
+ EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
+ else -> false
+ }
return removed == true
}
private fun getTargetRange(name: String): Pair {
- val result =
- when (name) {
- EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
- EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
- EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
- EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
- EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
- EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
- EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
- EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
- EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
- EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
- EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
- EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
- else -> Pair(0, 0)
- }
+ val result = when (name) {
+ EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
+ EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
+ EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
+ EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H4 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H5 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H6 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
+ EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
+ EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
+ EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
+ else -> Pair(0, 0)
+ }
return result ?: Pair(0, 0)
}
diff --git a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt
index cb4ee3e61..84553e665 100644
--- a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt
+++ b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt
@@ -294,6 +294,18 @@ class EnrichedTextInputViewManager :
view?.verifyAndToggleStyle(EnrichedSpans.H3)
}
+ override fun toggleH4(view: EnrichedTextInputView?) {
+ view?.verifyAndToggleStyle(EnrichedSpans.H4)
+ }
+
+ override fun toggleH5(view: EnrichedTextInputView?) {
+ view?.verifyAndToggleStyle(EnrichedSpans.H5)
+ }
+
+ override fun toggleH6(view: EnrichedTextInputView?) {
+ view?.verifyAndToggleStyle(EnrichedSpans.H6)
+ }
+
override fun toggleCodeBlock(view: EnrichedTextInputView?) {
view?.verifyAndToggleStyle(EnrichedSpans.CODE_BLOCK)
}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
new file mode 100644
index 000000000..76f649476
--- /dev/null
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
@@ -0,0 +1,17 @@
+package com.swmansion.enriched.spans
+
+import android.graphics.Typeface
+import android.text.TextPaint
+import android.text.style.AbsoluteSizeSpan
+import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
+import com.swmansion.enriched.styles.HtmlStyle
+
+class EnrichedH4Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h4FontSize), EnrichedHeadingSpan {
+ override fun updateDrawState(tp: TextPaint) {
+ super.updateDrawState(tp)
+ val bold = htmlStyle.h4Bold
+ if (bold) {
+ tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
+ }
+ }
+}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
new file mode 100644
index 000000000..437bddf14
--- /dev/null
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
@@ -0,0 +1,17 @@
+package com.swmansion.enriched.spans
+
+import android.graphics.Typeface
+import android.text.TextPaint
+import android.text.style.AbsoluteSizeSpan
+import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
+import com.swmansion.enriched.styles.HtmlStyle
+
+class EnrichedH5Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h5FontSize), EnrichedHeadingSpan {
+ override fun updateDrawState(tp: TextPaint) {
+ super.updateDrawState(tp)
+ val bold = htmlStyle.h5Bold
+ if (bold) {
+ tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
+ }
+ }
+}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
new file mode 100644
index 000000000..22c89e7d0
--- /dev/null
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
@@ -0,0 +1,17 @@
+package com.swmansion.enriched.spans
+
+import android.graphics.Typeface
+import android.text.TextPaint
+import android.text.style.AbsoluteSizeSpan
+import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
+import com.swmansion.enriched.styles.HtmlStyle
+
+class EnrichedH6Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h6FontSize), EnrichedHeadingSpan {
+ override fun updateDrawState(tp: TextPaint) {
+ super.updateDrawState(tp)
+ val bold = htmlStyle.h6Bold
+ if (bold) {
+ tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
+ }
+ }
+}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
index 800d2ef0b..09616ca39 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
@@ -39,6 +39,9 @@ object EnrichedSpans {
const val H1 = "h1"
const val H2 = "h2"
const val H3 = "h3"
+ const val H4 = "h4"
+ const val H5 = "h5"
+ const val H6 = "h6"
const val BLOCK_QUOTE = "block_quote"
const val CODE_BLOCK = "code_block"
@@ -60,14 +63,16 @@ object EnrichedSpans {
INLINE_CODE to BaseSpanConfig(EnrichedInlineCodeSpan::class.java),
)
- val paragraphSpans: Map =
- mapOf(
- H1 to ParagraphSpanConfig(EnrichedH1Span::class.java, false),
- H2 to ParagraphSpanConfig(EnrichedH2Span::class.java, false),
- H3 to ParagraphSpanConfig(EnrichedH3Span::class.java, false),
- BLOCK_QUOTE to ParagraphSpanConfig(EnrichedBlockQuoteSpan::class.java, true),
- CODE_BLOCK to ParagraphSpanConfig(EnrichedCodeBlockSpan::class.java, true),
- )
+ val paragraphSpans: Map = mapOf(
+ H1 to ParagraphSpanConfig(EnrichedH1Span::class.java, false),
+ H2 to ParagraphSpanConfig(EnrichedH2Span::class.java, false),
+ H3 to ParagraphSpanConfig(EnrichedH3Span::class.java, false),
+ H4 to ParagraphSpanConfig(EnrichedH4Span::class.java, false),
+ H5 to ParagraphSpanConfig(EnrichedH5Span::class.java, false),
+ H6 to ParagraphSpanConfig(EnrichedH6Span::class.java, false),
+ BLOCK_QUOTE to ParagraphSpanConfig(EnrichedBlockQuoteSpan::class.java, true),
+ CODE_BLOCK to ParagraphSpanConfig(EnrichedCodeBlockSpan::class.java, true),
+ )
val listSpans: Map =
mapOf(
@@ -94,6 +99,9 @@ object EnrichedSpans {
if (htmlStyle.h1Bold) blockingStyles.add(H1)
if (htmlStyle.h2Bold) blockingStyles.add(H2)
if (htmlStyle.h3Bold) blockingStyles.add(H3)
+ if (htmlStyle.h4Bold) blockingStyles.add(H4)
+ if (htmlStyle.h5Bold) blockingStyles.add(H5)
+ if (htmlStyle.h6Bold) blockingStyles.add(H6)
StylesMergingConfig(blockingStyles = blockingStyles.toTypedArray())
}
@@ -123,79 +131,57 @@ object EnrichedSpans {
}
H1 -> {
- val conflictingStyles = mutableListOf(H2, H3, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
+ val conflictingStyles = mutableListOf(H2, H3, H4, H5, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
if (htmlStyle.h1Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
H2 -> {
- val conflictingStyles = mutableListOf(H1, H3, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
+ val conflictingStyles = mutableListOf(H1, H3, H4, H5, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
if (htmlStyle.h2Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
H3 -> {
- val conflictingStyles = mutableListOf(H1, H2, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
+ val conflictingStyles = mutableListOf(H1, H2, H4, H5, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
if (htmlStyle.h3Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
-
- BLOCK_QUOTE -> {
- StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, CODE_BLOCK, ORDERED_LIST, UNORDERED_LIST),
- )
- }
-
- CODE_BLOCK -> {
- StylesMergingConfig(
- conflictingStyles =
- arrayOf(
- H1,
- H2,
- H3,
- BOLD,
- ITALIC,
- UNDERLINE,
- STRIKETHROUGH,
- UNORDERED_LIST,
- ORDERED_LIST,
- BLOCK_QUOTE,
- INLINE_CODE,
- ),
- )
- }
-
- UNORDERED_LIST -> {
- StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, ORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
- )
- }
-
- ORDERED_LIST -> {
- StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, UNORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
- )
- }
-
- LINK -> {
- StylesMergingConfig(
- blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, MENTION),
- )
- }
-
- IMAGE -> {
- StylesMergingConfig()
+ H4 -> {
+ val conflictingStyles = mutableListOf(H1, H2, H3, H5, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
+ if (htmlStyle.h4Bold) conflictingStyles.add(BOLD)
+ StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
-
- MENTION -> {
- StylesMergingConfig(
- blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, LINK),
- )
+ H5 -> {
+ val conflictingStyles = mutableListOf(H1, H2, H3, H4, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
+ if (htmlStyle.h5Bold) conflictingStyles.add(BOLD)
+ StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
-
- else -> {
- null
+ H6 -> {
+ val conflictingStyles = mutableListOf(H1, H2, H3, H4, H5, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
+ if (htmlStyle.h6Bold) conflictingStyles.add(BOLD)
+ StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
+ BLOCK_QUOTE -> StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, CODE_BLOCK, ORDERED_LIST, UNORDERED_LIST)
+ )
+ CODE_BLOCK -> StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, UNORDERED_LIST, ORDERED_LIST, BLOCK_QUOTE, INLINE_CODE)
+ )
+ UNORDERED_LIST -> StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, ORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE)
+ )
+ ORDERED_LIST -> StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, UNORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
+ )
+ LINK -> StylesMergingConfig(
+ blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, MENTION)
+ )
+ IMAGE -> StylesMergingConfig()
+ MENTION -> StylesMergingConfig(
+ blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, LINK)
+ )
+ else -> null
}
fun isTypeContinuous(type: Class<*>): Boolean = paragraphSpans.values.find { it.clazz == type }?.isContinuous == true
diff --git a/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt b/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
index ed0909151..66043b932 100644
--- a/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
+++ b/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
@@ -28,6 +28,15 @@ class HtmlStyle {
var h3FontSize: Int = 56
var h3Bold: Boolean = false
+ var h4FontSize: Int = 48
+ var h4Bold: Boolean = false
+
+ var h5FontSize: Int = 40
+ var h5Bold: Boolean = false
+
+ var h6FontSize: Int = 32
+ var h6Bold: Boolean = false
+
var blockquoteColor: Int? = null
var blockquoteBorderColor: Int = Color.BLACK
var blockquoteStripeWidth: Int = 2
@@ -77,6 +86,18 @@ class HtmlStyle {
h3FontSize = parseFloat(h3Style, "fontSize").toInt()
h3Bold = h3Style?.getBoolean("bold") == true
+ val h4Style = style.getMap("h4")
+ h4FontSize = parseFloat(h4Style, "fontSize").toInt()
+ h4Bold = h4Style?.getBoolean("bold") == true
+
+ val h5Style = style.getMap("h5")
+ h5FontSize = parseFloat(h5Style, "fontSize").toInt()
+ h5Bold = h5Style?.getBoolean("bold") == true
+
+ val h6Style = style.getMap("h6")
+ h6FontSize = parseFloat(h6Style, "fontSize").toInt()
+ h6Bold = h6Style?.getBoolean("bold") == true
+
val blockquoteStyle = style.getMap("blockquote")
blockquoteColor = parseOptionalColor(blockquoteStyle, "color")
blockquoteBorderColor = parseColor(blockquoteStyle, "borderColor")
diff --git a/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java b/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
index f158ab7cc..1a2e1cb55 100644
--- a/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
+++ b/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
@@ -15,6 +15,9 @@
import com.swmansion.enriched.spans.EnrichedH1Span;
import com.swmansion.enriched.spans.EnrichedH2Span;
import com.swmansion.enriched.spans.EnrichedH3Span;
+import com.swmansion.enriched.spans.EnrichedH4Span;
+import com.swmansion.enriched.spans.EnrichedH5Span;
+import com.swmansion.enriched.spans.EnrichedH6Span;
import com.swmansion.enriched.spans.EnrichedImageSpan;
import com.swmansion.enriched.spans.EnrichedInlineCodeSpan;
import com.swmansion.enriched.spans.EnrichedItalicSpan;
@@ -159,6 +162,12 @@ private static String getBlockTag(EnrichedParagraphSpan[] spans) {
return "h2";
} else if (span instanceof EnrichedH3Span) {
return "h3";
+ } else if (span instanceof EnrichedH4Span) {
+ return "h4";
+ } else if (span instanceof EnrichedH5Span) {
+ return "h5";
+ } else if (span instanceof EnrichedH6Span) {
+ return "h6";
}
}
@@ -477,6 +486,12 @@ private void handleStartTag(String tag, Attributes attributes) {
startHeading(mSpannableStringBuilder, 2);
} else if (tag.equalsIgnoreCase("h3")) {
startHeading(mSpannableStringBuilder, 3);
+ } else if (tag.equalsIgnoreCase("h4")) {
+ startHeading(mSpannableStringBuilder, 4);
+ } else if (tag.equalsIgnoreCase("h5")) {
+ startHeading(mSpannableStringBuilder, 5);
+ } else if (tag.equalsIgnoreCase("h6")) {
+ startHeading(mSpannableStringBuilder, 6);
} else if (tag.equalsIgnoreCase("img")) {
startImg(mSpannableStringBuilder, attributes, mImageGetter);
} else if (tag.equalsIgnoreCase("code")) {
@@ -515,6 +530,12 @@ private void handleEndTag(String tag) {
endHeading(mSpannableStringBuilder, mStyle, 2);
} else if (tag.equalsIgnoreCase("h3")) {
endHeading(mSpannableStringBuilder, mStyle, 3);
+ } else if (tag.equalsIgnoreCase("h4")) {
+ endHeading(mSpannableStringBuilder, mStyle, 4);
+ } else if (tag.equalsIgnoreCase("h5")) {
+ endHeading(mSpannableStringBuilder, mStyle, 5);
+ } else if (tag.equalsIgnoreCase("h6")) {
+ endHeading(mSpannableStringBuilder, mStyle, 6);
} else if (tag.equalsIgnoreCase("code")) {
end(mSpannableStringBuilder, Code.class, new EnrichedInlineCodeSpan(mStyle));
} else if (tag.equalsIgnoreCase("mention")) {
@@ -618,6 +639,15 @@ private void startHeading(Editable text, int level) {
case 3:
start(text, new H3());
break;
+ case 4:
+ start(text, new H4());
+ break;
+ case 5:
+ start(text, new H5());
+ break;
+ case 6:
+ start(text, new H6());
+ break;
default:
throw new IllegalArgumentException("Unsupported heading level: " + level);
}
@@ -639,6 +669,18 @@ private static void endHeading(Editable text, HtmlStyle style, int level) {
H3 lastH3 = getLast(text, H3.class);
setParagraphSpanFromMark(text, lastH3, new EnrichedH3Span(style));
break;
+ case 4:
+ H4 lastH4 = getLast(text, H4.class);
+ setParagraphSpanFromMark(text, lastH4, new EnrichedH4Span(style));
+ break;
+ case 5:
+ H5 lastH5 = getLast(text, H5.class);
+ setParagraphSpanFromMark(text, lastH5, new EnrichedH5Span(style));
+ break;
+ case 6:
+ H6 lastH6 = getLast(text, H6.class);
+ setParagraphSpanFromMark(text, lastH6, new EnrichedH6Span(style));
+ break;
default:
throw new IllegalArgumentException("Unsupported heading level: " + level);
}
@@ -819,7 +861,17 @@ private static class H2 {}
private static class H3 {}
- private static class Bold {}
+ private static class H4 {
+ }
+
+ private static class H5 {
+ }
+
+ private static class H6 {
+ }
+
+ private static class Bold {
+ }
private static class Italic {}
diff --git a/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt b/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
index e1871455b..da24a797f 100644
--- a/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
+++ b/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
@@ -29,6 +29,12 @@ class EnrichedSpanState(
private set
var h3Start: Int? = null
private set
+ var h4Start: Int? = null
+ private set
+ var h5Start: Int? = null
+ private set
+ var h6Start: Int? = null
+ private set
var codeBlockStart: Int? = null
private set
var blockQuoteStart: Int? = null
@@ -84,6 +90,21 @@ class EnrichedSpanState(
emitStateChangeEvent()
}
+ fun setH4Start(start: Int?) {
+ this.h4Start = start
+ emitStateChangeEvent()
+ }
+
+ fun setH5Start(start: Int?) {
+ this.h5Start = start
+ emitStateChangeEvent()
+ }
+
+ fun setH6Start(start: Int?) {
+ this.h6Start = start
+ emitStateChangeEvent()
+ }
+
fun setCodeBlockStart(start: Int?) {
this.codeBlockStart = start
emitStateChangeEvent()
@@ -120,25 +141,27 @@ class EnrichedSpanState(
}
fun getStart(name: String): Int? {
- val start =
- when (name) {
- EnrichedSpans.BOLD -> boldStart
- EnrichedSpans.ITALIC -> italicStart
- EnrichedSpans.UNDERLINE -> underlineStart
- EnrichedSpans.STRIKETHROUGH -> strikethroughStart
- EnrichedSpans.INLINE_CODE -> inlineCodeStart
- EnrichedSpans.H1 -> h1Start
- EnrichedSpans.H2 -> h2Start
- EnrichedSpans.H3 -> h3Start
- EnrichedSpans.CODE_BLOCK -> codeBlockStart
- EnrichedSpans.BLOCK_QUOTE -> blockQuoteStart
- EnrichedSpans.ORDERED_LIST -> orderedListStart
- EnrichedSpans.UNORDERED_LIST -> unorderedListStart
- EnrichedSpans.LINK -> linkStart
- EnrichedSpans.IMAGE -> imageStart
- EnrichedSpans.MENTION -> mentionStart
- else -> null
- }
+ val start = when (name) {
+ EnrichedSpans.BOLD -> boldStart
+ EnrichedSpans.ITALIC -> italicStart
+ EnrichedSpans.UNDERLINE -> underlineStart
+ EnrichedSpans.STRIKETHROUGH -> strikethroughStart
+ EnrichedSpans.INLINE_CODE -> inlineCodeStart
+ EnrichedSpans.H1 -> h1Start
+ EnrichedSpans.H2 -> h2Start
+ EnrichedSpans.H3 -> h3Start
+ EnrichedSpans.H4 -> h4Start
+ EnrichedSpans.H5 -> h5Start
+ EnrichedSpans.H6 -> h6Start
+ EnrichedSpans.CODE_BLOCK -> codeBlockStart
+ EnrichedSpans.BLOCK_QUOTE -> blockQuoteStart
+ EnrichedSpans.ORDERED_LIST -> orderedListStart
+ EnrichedSpans.UNORDERED_LIST -> unorderedListStart
+ EnrichedSpans.LINK -> linkStart
+ EnrichedSpans.IMAGE -> imageStart
+ EnrichedSpans.MENTION -> mentionStart
+ else -> null
+ }
return start
}
@@ -156,6 +179,9 @@ class EnrichedSpanState(
EnrichedSpans.H1 -> setH1Start(start)
EnrichedSpans.H2 -> setH2Start(start)
EnrichedSpans.H3 -> setH3Start(start)
+ EnrichedSpans.H4 -> setH4Start(start)
+ EnrichedSpans.H5 -> setH5Start(start)
+ EnrichedSpans.H6 -> setH6Start(start)
EnrichedSpans.CODE_BLOCK -> setCodeBlockStart(start)
EnrichedSpans.BLOCK_QUOTE -> setBlockQuoteStart(start)
EnrichedSpans.ORDERED_LIST -> setOrderedListStart(start)
@@ -176,6 +202,9 @@ class EnrichedSpanState(
payload.putBoolean("isH1", h1Start != null)
payload.putBoolean("isH2", h2Start != null)
payload.putBoolean("isH3", h3Start != null)
+ payload.putBoolean("isH4", h4Start != null)
+ payload.putBoolean("isH5", h5Start != null)
+ payload.putBoolean("isH6", h6Start != null)
payload.putBoolean("isCodeBlock", codeBlockStart != null)
payload.putBoolean("isBlockQuote", blockQuoteStart != null)
payload.putBoolean("isOrderedList", orderedListStart != null)
diff --git a/apps/example/src/App.tsx b/apps/example/src/App.tsx
index d36ac903a..81bdfeebf 100644
--- a/apps/example/src/App.tsx
+++ b/apps/example/src/App.tsx
@@ -46,6 +46,9 @@ const DEFAULT_STYLE: StylesState = {
isH1: false,
isH2: false,
isH3: false,
+ isH4: false,
+ isH5: false,
+ isH6: false,
isBlockQuote: false,
isCodeBlock: false,
isOrderedList: false,
@@ -370,14 +373,26 @@ export default function App() {
const htmlStyle: HtmlStyle = {
h1: {
- fontSize: 40,
+ fontSize: 72,
bold: true,
},
h2: {
- fontSize: 32,
+ fontSize: 60,
bold: true,
},
h3: {
+ fontSize: 50,
+ bold: true,
+ },
+ h4: {
+ fontSize: 40,
+ bold: true,
+ },
+ h5: {
+ fontSize: 30,
+ bold: true,
+ },
+ h6: {
fontSize: 24,
bold: true,
},
diff --git a/apps/example/src/components/Toolbar.tsx b/apps/example/src/components/Toolbar.tsx
index 28c99b48a..6fad4c527 100644
--- a/apps/example/src/components/Toolbar.tsx
+++ b/apps/example/src/components/Toolbar.tsx
@@ -39,6 +39,18 @@ const STYLE_ITEMS = [
name: 'heading-3',
text: 'H3',
},
+ {
+ name: 'heading-4',
+ text: 'H4',
+ },
+ {
+ name: 'heading-5',
+ text: 'H5',
+ },
+ {
+ name: 'heading-6',
+ text: 'H6',
+ },
{
name: 'quote',
icon: 'quote-right',
@@ -114,6 +126,15 @@ export const Toolbar: FC = ({
case 'heading-3':
editorRef.current?.toggleH3();
break;
+ case 'heading-4':
+ editorRef.current?.toggleH4();
+ break;
+ case 'heading-5':
+ editorRef.current?.toggleH5();
+ break;
+ case 'heading-6':
+ editorRef.current?.toggleH6();
+ break;
case 'code-block':
editorRef?.current?.toggleCodeBlock();
break;
@@ -156,6 +177,12 @@ export const Toolbar: FC = ({
return stylesState.isH2;
case 'heading-3':
return stylesState.isH3;
+ case 'heading-4':
+ return stylesState.isH4;
+ case 'heading-5':
+ return stylesState.isH5;
+ case 'heading-6':
+ return stylesState.isH6;
case 'code-block':
return stylesState.isCodeBlock;
case 'quote':
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index a46f4f20d..996e56452 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -86,27 +86,23 @@ - (void)setDefaults {
stylesDict = @{
@([BoldStyle getStyleType]) : [[BoldStyle alloc] initWithInput:self],
- @([ItalicStyle getStyleType]) : [[ItalicStyle alloc] initWithInput:self],
- @([UnderlineStyle getStyleType]) :
- [[UnderlineStyle alloc] initWithInput:self],
- @([StrikethroughStyle getStyleType]) :
- [[StrikethroughStyle alloc] initWithInput:self],
- @([InlineCodeStyle getStyleType]) :
- [[InlineCodeStyle alloc] initWithInput:self],
- @([LinkStyle getStyleType]) : [[LinkStyle alloc] initWithInput:self],
- @([MentionStyle getStyleType]) : [[MentionStyle alloc] initWithInput:self],
- @([H1Style getStyleType]) : [[H1Style alloc] initWithInput:self],
- @([H2Style getStyleType]) : [[H2Style alloc] initWithInput:self],
- @([H3Style getStyleType]) : [[H3Style alloc] initWithInput:self],
- @([UnorderedListStyle getStyleType]) :
- [[UnorderedListStyle alloc] initWithInput:self],
- @([OrderedListStyle getStyleType]) :
- [[OrderedListStyle alloc] initWithInput:self],
- @([BlockQuoteStyle getStyleType]) :
- [[BlockQuoteStyle alloc] initWithInput:self],
- @([CodeBlockStyle getStyleType]) :
- [[CodeBlockStyle alloc] initWithInput:self],
- @([ImageStyle getStyleType]) : [[ImageStyle alloc] initWithInput:self]
+ @([ItalicStyle getStyleType]): [[ItalicStyle alloc] initWithInput:self],
+ @([UnderlineStyle getStyleType]): [[UnderlineStyle alloc] initWithInput:self],
+ @([StrikethroughStyle getStyleType]): [[StrikethroughStyle alloc] initWithInput:self],
+ @([InlineCodeStyle getStyleType]): [[InlineCodeStyle alloc] initWithInput:self],
+ @([LinkStyle getStyleType]): [[LinkStyle alloc] initWithInput:self],
+ @([MentionStyle getStyleType]): [[MentionStyle alloc] initWithInput:self],
+ @([H1Style getStyleType]): [[H1Style alloc] initWithInput:self],
+ @([H2Style getStyleType]): [[H2Style alloc] initWithInput:self],
+ @([H3Style getStyleType]): [[H3Style alloc] initWithInput:self],
+ @([H4Style getStyleType]): [[H4Style alloc] initWithInput:self],
+ @([H5Style getStyleType]): [[H5Style alloc] initWithInput:self],
+ @([H6Style getStyleType]): [[H6Style alloc] initWithInput:self],
+ @([UnorderedListStyle getStyleType]): [[UnorderedListStyle alloc] initWithInput:self],
+ @([OrderedListStyle getStyleType]): [[OrderedListStyle alloc] initWithInput:self],
+ @([BlockQuoteStyle getStyleType]): [[BlockQuoteStyle alloc] initWithInput:self],
+ @([CodeBlockStyle getStyleType]): [[CodeBlockStyle alloc] initWithInput:self],
+ @([ImageStyle getStyleType]): [[ImageStyle alloc] initWithInput:self]
};
conflictingStyles = @{
@@ -114,77 +110,42 @@ - (void)setDefaults {
@([ItalicStyle getStyleType]) : @[],
@([UnderlineStyle getStyleType]) : @[],
@([StrikethroughStyle getStyleType]) : @[],
- @([InlineCodeStyle getStyleType]) :
- @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ],
- @([LinkStyle getStyleType]) : @[
- @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]),
- @([MentionStyle getStyleType])
- ],
- @([MentionStyle getStyleType]) :
- @[ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]) ],
- @([H1Style getStyleType]) : @[
- @([H2Style getStyleType]), @([H3Style getStyleType]),
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
- ],
- @([H2Style getStyleType]) : @[
- @([H1Style getStyleType]), @([H3Style getStyleType]),
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
- ],
- @([H3Style getStyleType]) : @[
- @([H1Style getStyleType]), @([H2Style getStyleType]),
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
- ],
- @([UnorderedListStyle getStyleType]) : @[
- @([H1Style getStyleType]), @([H2Style getStyleType]),
- @([H3Style getStyleType]), @([OrderedListStyle getStyleType]),
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
- ],
- @([OrderedListStyle getStyleType]) : @[
- @([H1Style getStyleType]), @([H2Style getStyleType]),
- @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
- ],
- @([BlockQuoteStyle getStyleType]) : @[
- @([H1Style getStyleType]), @([H2Style getStyleType]),
- @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([CodeBlockStyle getStyleType])
- ],
- @([CodeBlockStyle getStyleType]) : @[
- @([H1Style getStyleType]), @([H2Style getStyleType]),
- @([H3Style getStyleType]), @([BoldStyle getStyleType]),
- @([ItalicStyle getStyleType]), @([UnderlineStyle getStyleType]),
- @([StrikethroughStyle getStyleType]),
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
- @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]),
- @([MentionStyle getStyleType]), @([LinkStyle getStyleType])
- ],
- @([ImageStyle getStyleType]) :
- @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ]
+ @([InlineCodeStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
+ @([LinkStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
+ @([MentionStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType])],
+ @([H1Style getStyleType]): @[@([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([H2Style getStyleType]): @[@([H1Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([H3Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([H4Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([H5Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([H6Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([UnorderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([OrderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
+ @([BlockQuoteStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType])],
+ @([CodeBlockStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]),
+ @([BoldStyle getStyleType]), @([ItalicStyle getStyleType]), @([UnderlineStyle getStyleType]), @([StrikethroughStyle getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]), @([MentionStyle getStyleType]), @([LinkStyle getStyleType])],
+ @([ImageStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])]
};
blockingStyles = @{
- @([BoldStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
- @([ItalicStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
- @([UnderlineStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
- @([StrikethroughStyle getStyleType]) :
- @[ @([CodeBlockStyle getStyleType]) ],
- @([InlineCodeStyle getStyleType]) :
- @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
- @([LinkStyle getStyleType]) :
- @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
- @([MentionStyle getStyleType]) :
- @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
- @([H1Style getStyleType]) : @[],
- @([H2Style getStyleType]) : @[],
- @([H3Style getStyleType]) : @[],
- @([UnorderedListStyle getStyleType]) : @[],
- @([OrderedListStyle getStyleType]) : @[],
- @([BlockQuoteStyle getStyleType]) : @[],
- @([CodeBlockStyle getStyleType]) : @[],
- @([ImageStyle getStyleType]) : @[ @([InlineCodeStyle getStyleType]) ]
+ @([BoldStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
+ @([ItalicStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
+ @([UnderlineStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
+ @([StrikethroughStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
+ @([InlineCodeStyle getStyleType]) : @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
+ @([LinkStyle getStyleType]): @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
+ @([MentionStyle getStyleType]): @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
+ @([H1Style getStyleType]): @[],
+ @([H2Style getStyleType]): @[],
+ @([H3Style getStyleType]): @[],
+ @([H4Style getStyleType]): @[],
+ @([H5Style getStyleType]): @[],
+ @([H6Style getStyleType]): @[],
+ @([UnorderedListStyle getStyleType]): @[],
+ @([OrderedListStyle getStyleType]): @[],
+ @([BlockQuoteStyle getStyleType]): @[],
+ @([CodeBlockStyle getStyleType]): @[],
+ @([ImageStyle getStyleType]) : @[@([InlineCodeStyle getStyleType])]
};
parser = [[InputParser alloc] initWithInput:self];
@@ -316,13 +277,40 @@ - (void)updateProps:(Props::Shared const &)props
[newConfig setH3Bold:newViewProps.htmlStyle.h3.bold];
stylePropChanged = YES;
}
-
- if (newViewProps.htmlStyle.blockquote.borderColor !=
- oldViewProps.htmlStyle.blockquote.borderColor) {
- if (isColorMeaningful(newViewProps.htmlStyle.blockquote.borderColor)) {
- [newConfig setBlockquoteBorderColor:RCTUIColorFromSharedColor(
- newViewProps.htmlStyle.blockquote
- .borderColor)];
+
+ if(newViewProps.htmlStyle.h4.fontSize != oldViewProps.htmlStyle.h4.fontSize) {
+ [newConfig setH4FontSize:newViewProps.htmlStyle.h4.fontSize];
+ stylePropChanged = YES;
+ }
+
+ if(newViewProps.htmlStyle.h4.bold != oldViewProps.htmlStyle.h4.bold) {
+ [newConfig setH4Bold:newViewProps.htmlStyle.h4.bold];
+ stylePropChanged = YES;
+ }
+
+ if(newViewProps.htmlStyle.h5.fontSize != oldViewProps.htmlStyle.h5.fontSize) {
+ [newConfig setH5FontSize:newViewProps.htmlStyle.h5.fontSize];
+ stylePropChanged = YES;
+ }
+
+ if(newViewProps.htmlStyle.h5.bold != oldViewProps.htmlStyle.h5.bold) {
+ [newConfig setH5Bold:newViewProps.htmlStyle.h5.bold];
+ stylePropChanged = YES;
+ }
+
+ if(newViewProps.htmlStyle.h6.fontSize != oldViewProps.htmlStyle.h6.fontSize) {
+ [newConfig setH6FontSize:newViewProps.htmlStyle.h6.fontSize];
+ stylePropChanged = YES;
+ }
+
+ if(newViewProps.htmlStyle.h6.bold != oldViewProps.htmlStyle.h6.bold) {
+ [newConfig setH6Bold:newViewProps.htmlStyle.h6.bold];
+ stylePropChanged = YES;
+ }
+
+ if(newViewProps.htmlStyle.blockquote.borderColor != oldViewProps.htmlStyle.blockquote.borderColor) {
+ if(isColorMeaningful(newViewProps.htmlStyle.blockquote.borderColor)) {
+ [newConfig setBlockquoteBorderColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.blockquote.borderColor)];
stylePropChanged = YES;
}
}
@@ -875,30 +863,24 @@ - (void)tryUpdatingActiveStyles {
_activeStyles = newActiveStyles;
emitter->onChangeState({
- .isBold = [_activeStyles containsObject:@([BoldStyle getStyleType])],
- .isItalic =
- [_activeStyles containsObject:@([ItalicStyle getStyleType])],
- .isUnderline =
- [_activeStyles containsObject:@([UnderlineStyle getStyleType])],
- .isStrikeThrough =
- [_activeStyles containsObject:@([StrikethroughStyle getStyleType])],
- .isInlineCode =
- [_activeStyles containsObject:@([InlineCodeStyle getStyleType])],
- .isLink = [_activeStyles containsObject:@([LinkStyle getStyleType])],
- .isMention =
- [_activeStyles containsObject:@([MentionStyle getStyleType])],
- .isH1 = [_activeStyles containsObject:@([H1Style getStyleType])],
- .isH2 = [_activeStyles containsObject:@([H2Style getStyleType])],
- .isH3 = [_activeStyles containsObject:@([H3Style getStyleType])],
- .isUnorderedList =
- [_activeStyles containsObject:@([UnorderedListStyle getStyleType])],
- .isOrderedList =
- [_activeStyles containsObject:@([OrderedListStyle getStyleType])],
- .isBlockQuote =
- [_activeStyles containsObject:@([BlockQuoteStyle getStyleType])],
- .isCodeBlock =
- [_activeStyles containsObject:@([CodeBlockStyle getStyleType])],
- .isImage = [_activeStyles containsObject:@([ImageStyle getStyleType])],
+ .isBold = [_activeStyles containsObject: @([BoldStyle getStyleType])],
+ .isItalic = [_activeStyles containsObject: @([ItalicStyle getStyleType])],
+ .isUnderline = [_activeStyles containsObject: @([UnderlineStyle getStyleType])],
+ .isStrikeThrough = [_activeStyles containsObject: @([StrikethroughStyle getStyleType])],
+ .isInlineCode = [_activeStyles containsObject: @([InlineCodeStyle getStyleType])],
+ .isLink = [_activeStyles containsObject: @([LinkStyle getStyleType])],
+ .isMention = [_activeStyles containsObject: @([MentionStyle getStyleType])],
+ .isH1 = [_activeStyles containsObject: @([H1Style getStyleType])],
+ .isH2 = [_activeStyles containsObject: @([H2Style getStyleType])],
+ .isH3 = [_activeStyles containsObject: @([H3Style getStyleType])],
+ .isH4 = [_activeStyles containsObject: @([H4Style getStyleType])],
+ .isH5 = [_activeStyles containsObject: @([H5Style getStyleType])],
+ .isH6 = [_activeStyles containsObject: @([H6Style getStyleType])],
+ .isUnorderedList = [_activeStyles containsObject: @([UnorderedListStyle getStyleType])],
+ .isOrderedList = [_activeStyles containsObject: @([OrderedListStyle getStyleType])],
+ .isBlockQuote = [_activeStyles containsObject: @([BlockQuoteStyle getStyleType])],
+ .isCodeBlock = [_activeStyles containsObject: @([CodeBlockStyle getStyleType])],
+ .isImage = [_activeStyles containsObject: @([ImageStyle getStyleType])],
});
}
}
@@ -964,7 +946,13 @@ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
[self toggleParagraphStyle:[H2Style getStyleType]];
} else if ([commandName isEqualToString:@"toggleH3"]) {
[self toggleParagraphStyle:[H3Style getStyleType]];
- } else if ([commandName isEqualToString:@"toggleUnorderedList"]) {
+ } else if([commandName isEqualToString:@"toggleH4"]) {
+ [self toggleParagraphStyle:[H4Style getStyleType]];
+ } else if([commandName isEqualToString:@"toggleH5"]) {
+ [self toggleParagraphStyle:[H5Style getStyleType]];
+ } else if([commandName isEqualToString:@"toggleH6"]) {
+ [self toggleParagraphStyle:[H6Style getStyleType]];
+ } else if([commandName isEqualToString:@"toggleUnorderedList"]) {
[self toggleParagraphStyle:[UnorderedListStyle getStyleType]];
} else if ([commandName isEqualToString:@"toggleOrderedList"]) {
[self toggleParagraphStyle:[OrderedListStyle getStyleType]];
@@ -1378,10 +1366,21 @@ - (void)anyTextMayHaveBeenModified {
H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
- if (h1Style != nullptr && h2Style != nullptr && h3Style != nullptr) {
+ H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
+ H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
+ H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
+
+ bool shouldHandleImproperHeadings =
+ h1Style != nullptr && h2Style != nullptr && h3Style != nullptr &&
+ h4Style != nullptr && h5Style != nullptr && h6Style != nullptr;
+
+ if(shouldHandleImproperHeadings) {
[h1Style handleImproperHeadings];
[h2Style handleImproperHeadings];
[h3Style handleImproperHeadings];
+ [h4Style handleImproperHeadings];
+ [h5Style handleImproperHeadings];
+ [h6Style handleImproperHeadings];
}
// mentions management: removal and editing
@@ -1532,37 +1531,36 @@ - (bool)textView:(UITextView *)textView
H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
-
- // some of the changes these checks do could interfere with later checks and
- // cause a crash so here I rely on short circuiting evaluation of the logical
- // expression either way it's not possible to have two of them come off at the
- // same time
- if ([uStyle handleBackspaceInRange:range replacementText:text] ||
- [uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
- [oStyle handleBackspaceInRange:range replacementText:text] ||
- [oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
- [bqStyle handleBackspaceInRange:range replacementText:text] ||
- [cbStyle handleBackspaceInRange:range replacementText:text] ||
- [linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
- [mentionStyle handleLeadingMentionReplacement:range
- replacementText:text] ||
- [h1Style handleNewlinesInRange:range replacementText:text] ||
- [h2Style handleNewlinesInRange:range replacementText:text] ||
- [h3Style handleNewlinesInRange:range replacementText:text] ||
- [ZeroWidthSpaceUtils handleBackspaceInRange:range
- replacementText:text
- input:self] ||
- [ParagraphAttributesUtils handleBackspaceInRange:range
- replacementText:text
- input:self] ||
- // CRITICAL: This callback HAS TO be always evaluated last.
- //
- // This function is the "Generic Fallback": if no specific style claims
- // the backspace action to change its state, only then do we proceed to
- // physically delete the newline and merge paragraphs.
- [ParagraphAttributesUtils handleParagraphStylesMergeOnBackspace:range
- replacementText:text
- input:self]) {
+ H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
+ H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
+ H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
+
+ // some of the changes these checks do could interfere with later checks and cause a crash
+ // so here I rely on short circuiting evaluation of the logical expression
+ // either way it's not possible to have two of them come off at the same time
+ if(
+ [uStyle handleBackspaceInRange:range replacementText:text] ||
+ [uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
+ [oStyle handleBackspaceInRange:range replacementText:text] ||
+ [oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
+ [bqStyle handleBackspaceInRange:range replacementText:text] ||
+ [cbStyle handleBackspaceInRange:range replacementText:text] ||
+ [linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
+ [mentionStyle handleLeadingMentionReplacement:range replacementText:text] ||
+ [h1Style handleNewlinesInRange:range replacementText:text] ||
+ [h2Style handleNewlinesInRange:range replacementText:text] ||
+ [h3Style handleNewlinesInRange:range replacementText:text] ||
+ [h4Style handleNewlinesInRange:range replacementText:text] ||
+ [h5Style handleNewlinesInRange:range replacementText:text] ||
+ [h6Style handleNewlinesInRange:range replacementText:text] ||
+ [ZeroWidthSpaceUtils handleBackspaceInRange:range replacementText:text input:self] ||
+ [ParagraphAttributesUtils handleBackspaceInRange:range replacementText:text input:self] ||
+ // CRITICAL: This callback HAS TO be always evaluated last.
+ //
+ // This function is the "Generic Fallback": if no specific style claims the backspace action
+ // to change its state, only then do we proceed to physically delete the newline and merge paragraphs.
+ [ParagraphAttributesUtils handleNewlineBackspaceInRange:range replacementText:text input:self]
+ ) {
[self anyTextMayHaveBeenModified];
return NO;
}
diff --git a/ios/config/InputConfig.h b/ios/config/InputConfig.h
index e562517f1..dbf404308 100644
--- a/ios/config/InputConfig.h
+++ b/ios/config/InputConfig.h
@@ -29,6 +29,18 @@
- (void)setH3FontSize:(CGFloat)newValue;
- (BOOL)h3Bold;
- (void)setH3Bold:(BOOL)newValue;
+- (CGFloat)h4FontSize;
+- (void)setH4FontSize:(CGFloat)newValue;
+- (BOOL)h4Bold;
+- (void)setH4Bold:(BOOL)newValue;
+- (CGFloat)h5FontSize;
+- (void)setH5FontSize:(CGFloat)newValue;
+- (BOOL)h5Bold;
+- (void)setH5Bold:(BOOL)newValue;
+- (CGFloat)h6FontSize;
+- (void)setH6FontSize:(CGFloat)newValue;
+- (BOOL)h6Bold;
+- (void)setH6Bold:(BOOL)newValue;
- (UIColor *)blockquoteBorderColor;
- (void)setBlockquoteBorderColor:(UIColor *)newValue;
- (CGFloat)blockquoteBorderWidth;
diff --git a/ios/config/InputConfig.mm b/ios/config/InputConfig.mm
index bccf74612..cef866943 100644
--- a/ios/config/InputConfig.mm
+++ b/ios/config/InputConfig.mm
@@ -17,6 +17,12 @@ @implementation InputConfig {
BOOL _h2Bold;
CGFloat _h3FontSize;
BOOL _h3Bold;
+ CGFloat _h4FontSize;
+ BOOL _h4Bold;
+ CGFloat _h5FontSize;
+ BOOL _h5Bold;
+ CGFloat _h6FontSize;
+ BOOL _h6Bold;
UIColor *_blockquoteBorderColor;
CGFloat _blockquoteBorderWidth;
CGFloat _blockquoteGapWidth;
@@ -66,6 +72,12 @@ - (id)copyWithZone:(NSZone *)zone {
copy->_h2Bold = _h2Bold;
copy->_h3FontSize = _h3FontSize;
copy->_h3Bold = _h3Bold;
+ copy->_h4FontSize = _h4FontSize;
+ copy->_h4Bold = _h4Bold;
+ copy->_h5FontSize = _h5FontSize;
+ copy->_h5Bold = _h5Bold;
+ copy->_h6FontSize = _h6FontSize;
+ copy->_h6Bold = _h6Bold;
copy->_blockquoteBorderColor = [_blockquoteBorderColor copy];
copy->_blockquoteBorderWidth = _blockquoteBorderWidth;
copy->_blockquoteGapWidth = _blockquoteGapWidth;
@@ -222,6 +234,54 @@ - (void)setH3Bold:(BOOL)newValue {
_h3Bold = newValue;
}
+- (CGFloat)h4FontSize {
+ return _h4FontSize;
+}
+
+- (void)setH4FontSize:(CGFloat)newValue {
+ _h4FontSize = newValue;
+}
+
+- (BOOL)h4Bold {
+ return _h4Bold;
+}
+
+- (void)setH4Bold:(BOOL)newValue {
+ _h4Bold = newValue;
+}
+
+- (CGFloat)h5FontSize {
+ return _h5FontSize;
+}
+
+- (void)setH5FontSize:(CGFloat)newValue {
+ _h5FontSize = newValue;
+}
+
+- (BOOL)h5Bold {
+ return _h5Bold;
+}
+
+- (void)setH5Bold:(BOOL)newValue {
+ _h5Bold = newValue;
+}
+
+- (CGFloat)h6FontSize {
+ return _h6FontSize;
+}
+
+- (void)setH6FontSize:(CGFloat)newValue {
+ _h6FontSize = newValue;
+}
+
+- (BOOL)h6Bold {
+ return _h6Bold;
+}
+
+- (void)setH6Bold:(BOOL)newValue {
+ _h6Bold = newValue;
+}
+
- (UIColor *)blockquoteBorderColor {
return _blockquoteBorderColor;
}
diff --git a/ios/inputParser/InputParser.mm b/ios/inputParser/InputParser.mm
index c7543dde9..09d0f0939 100644
--- a/ios/inputParser/InputParser.mm
+++ b/ios/inputParser/InputParser.mm
@@ -217,17 +217,17 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
}
// don't add the tag if some paragraph styles are present
- if ([currentActiveStyles
- containsObject:@([UnorderedListStyle getStyleType])] ||
- [currentActiveStyles
- containsObject:@([OrderedListStyle getStyleType])] ||
- [currentActiveStyles containsObject:@([H1Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H2Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H3Style getStyleType])] ||
- [currentActiveStyles
- containsObject:@([BlockQuoteStyle getStyleType])] ||
- [currentActiveStyles
- containsObject:@([CodeBlockStyle getStyleType])]) {
+ if([currentActiveStyles containsObject:@([UnorderedListStyle getStyleType])] ||
+ [currentActiveStyles containsObject:@([OrderedListStyle getStyleType])] ||
+ [currentActiveStyles containsObject:@([H1Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H2Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H3Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H4Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H5Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H6Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([BlockQuoteStyle getStyleType])] ||
+ [currentActiveStyles containsObject:@([CodeBlockStyle getStyleType])]
+ ) {
[result appendString:@"\n"];
} else {
[result appendString:@"\n
"];
@@ -373,13 +373,15 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
} else if ([previousActiveStyles
containsObject:@([CodeBlockStyle getStyleType])]) {
[result appendString:@"\n"];
- } else if ([previousActiveStyles
- containsObject:@([H1Style getStyleType])] ||
- [previousActiveStyles
- containsObject:@([H2Style getStyleType])] ||
- [previousActiveStyles
- containsObject:@([H3Style getStyleType])]) {
- // do nothing, heading closing tag has already ben appended
+ } else if(
+ [previousActiveStyles containsObject:@([H1Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H2Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H3Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H4Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H5Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H6Style getStyleType])]
+ ) {
+ // do nothing, heading closing tag has already been appended
} else {
[result appendString:@"
"];
}
@@ -513,8 +515,13 @@ - (NSString *)tagContentForStyle:(NSNumber *)style
return @"h2";
} else if ([style isEqualToNumber:@([H3Style getStyleType])]) {
return @"h3";
- } else if ([style isEqualToNumber:@([UnorderedListStyle getStyleType])] ||
- [style isEqualToNumber:@([OrderedListStyle getStyleType])]) {
+ } else if([style isEqualToNumber:@([H4Style getStyleType])]) {
+ return @"h4";
+ } else if([style isEqualToNumber:@([H5Style getStyleType])]) {
+ return @"h5";
+ } else if([style isEqualToNumber:@([H6Style getStyleType])]) {
+ return @"h6";
+ } else if([style isEqualToNumber:@([UnorderedListStyle getStyleType])] || [style isEqualToNumber:@([OrderedListStyle getStyleType])]) {
return @"li";
} else if ([style isEqualToNumber:@([BlockQuoteStyle getStyleType])] ||
[style isEqualToNumber:@([CodeBlockStyle getStyleType])]) {
@@ -724,64 +731,24 @@ - (NSString *_Nullable)initiallyProcessHtml:(NSString *_Nonnull)html {
trailing:YES];
// line opening tags
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:YES
- trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"
"
- inString:fixedHtml
- leading:YES
- trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:YES
- trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:YES
- trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:YES
- trailing:NO];
-
+ fixedHtml = [self stringByAddingNewlinesToTag:@"
" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"
" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
+
// line closing tags
- fixedHtml = [self stringByAddingNewlinesToTag:@"
"
- inString:fixedHtml
- leading:NO
- trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:NO
- trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:NO
- trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:NO
- trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@""
- inString:fixedHtml
- leading:NO
- trailing:YES];
-
- // this is more like a hack but for some reason the last
in
- // and are not properly changed into zero width
- // space so we do that manually here
- fixedHtml = [fixedHtml
- stringByReplacingOccurrencesOfString:@"
\n
"
- withString:@"\u200B
\n"];
- fixedHtml = [fixedHtml
- stringByReplacingOccurrencesOfString:@"
\n"
- withString:@"\u200B
\n"];
-
- // replace "
" at the end with "
\n" if input is not empty to properly
- // handle last
in html
- if ([fixedHtml hasSuffix:@"
"] && fixedHtml.length != 4) {
- fixedHtml = [fixedHtml stringByAppendingString:@"\n"];
- }
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
}
return fixedHtml;
@@ -1198,6 +1165,12 @@ - (NSArray *)getTextAndStylesFromHtml:(NSString *)fixedHtml {
[styleArr addObject:@([H2Style getStyleType])];
} else if ([tagName isEqualToString:@"h3"]) {
[styleArr addObject:@([H3Style getStyleType])];
+ } else if([tagName isEqualToString:@"h4"]) {
+ [styleArr addObject:@([H4Style getStyleType])];
+ } else if([tagName isEqualToString:@"h5"]) {
+ [styleArr addObject:@([H5Style getStyleType])];
+ } else if([tagName isEqualToString:@"h6"]) {
+ [styleArr addObject:@([H6Style getStyleType])];
}
} else if ([tagName isEqualToString:@"ul"]) {
[styleArr addObject:@([UnorderedListStyle getStyleType])];
diff --git a/ios/styles/BoldStyle.mm b/ios/styles/BoldStyle.mm
index aae3b400b..c69f96eb6 100644
--- a/ios/styles/BoldStyle.mm
+++ b/ios/styles/BoldStyle.mm
@@ -92,18 +92,18 @@ - (void)removeTypingAttributes {
}
- (BOOL)boldHeadingConflictsInRange:(NSRange)range type:(StyleType)type {
- if (type == H1) {
- if (![_input->config h1Bold]) {
- return NO;
- }
- } else if (type == H2) {
- if (![_input->config h2Bold]) {
- return NO;
- }
- } else if (type == H3) {
- if (![_input->config h3Bold]) {
- return NO;
- }
+ if(type == H1) {
+ if(![_input->config h1Bold]) { return NO; }
+ } else if(type == H2) {
+ if(![_input->config h2Bold]) { return NO; }
+ } else if(type == H3) {
+ if(![_input->config h3Bold]) { return NO; }
+ } else if(type == H4) {
+ if(![_input->config h4Bold]) { return NO; }
+ } else if(type == H5) {
+ if(![_input->config h5Bold]) { return NO; }
+ } else if(type == H6) {
+ if(![_input->config h6Bold]) { return NO; }
}
id headingStyle = _input->stylesDict[@(type)];
@@ -113,10 +113,7 @@ - (BOOL)boldHeadingConflictsInRange:(NSRange)range type:(StyleType)type {
- (BOOL)styleCondition:(id _Nullable)value:(NSRange)range {
UIFont *font = (UIFont *)value;
- return font != nullptr && [font isBold] &&
- ![self boldHeadingConflictsInRange:range type:H1] &&
- ![self boldHeadingConflictsInRange:range type:H2] &&
- ![self boldHeadingConflictsInRange:range type:H3];
+ return font != nullptr && [font isBold] && ![self boldHeadingConflictsInRange:range type:H1] && ![self boldHeadingConflictsInRange:range type:H2] && ![self boldHeadingConflictsInRange:range type:H3] && ![self boldHeadingConflictsInRange:range type:H4] && ![self boldHeadingConflictsInRange:range type:H5] && ![self boldHeadingConflictsInRange:range type:H6];
}
- (BOOL)detectStyle:(NSRange)range {
diff --git a/ios/styles/H4Style.mm b/ios/styles/H4Style.mm
new file mode 100644
index 000000000..2c76eb37a
--- /dev/null
+++ b/ios/styles/H4Style.mm
@@ -0,0 +1,10 @@
+#import "StyleHeaders.h"
+#import "EnrichedTextInputView.h"
+
+@implementation H4Style
++ (StyleType)getStyleType { return H4; }
+- (CGFloat)getHeadingFontSize { return [((EnrichedTextInputView *)input)->config h4FontSize]; }
+- (BOOL)isHeadingBold {
+ return [((EnrichedTextInputView *)input)->config h4Bold];
+}
+@end
diff --git a/ios/styles/H5Style.mm b/ios/styles/H5Style.mm
new file mode 100644
index 000000000..b47a69120
--- /dev/null
+++ b/ios/styles/H5Style.mm
@@ -0,0 +1,10 @@
+#import "StyleHeaders.h"
+#import "EnrichedTextInputView.h"
+
+@implementation H5Style
++ (StyleType)getStyleType { return H5; }
+- (CGFloat)getHeadingFontSize { return [((EnrichedTextInputView *)input)->config h5FontSize]; }
+- (BOOL)isHeadingBold {
+ return [((EnrichedTextInputView *)input)->config h5Bold];
+}
+@end
diff --git a/ios/styles/H6Style.mm b/ios/styles/H6Style.mm
new file mode 100644
index 000000000..f224e9dca
--- /dev/null
+++ b/ios/styles/H6Style.mm
@@ -0,0 +1,10 @@
+#import "StyleHeaders.h"
+#import "EnrichedTextInputView.h"
+
+@implementation H6Style
++ (StyleType)getStyleType { return H6; }
+- (CGFloat)getHeadingFontSize { return [((EnrichedTextInputView *)input)->config h6FontSize]; }
+- (BOOL)isHeadingBold {
+ return [((EnrichedTextInputView *)input)->config h6Bold];
+}
+@end
diff --git a/ios/styles/HeadingStyleBase.mm b/ios/styles/HeadingStyleBase.mm
index 6e86672f3..7727af8c7 100644
--- a/ios/styles/HeadingStyleBase.mm
+++ b/ios/styles/HeadingStyleBase.mm
@@ -6,7 +6,7 @@
@implementation HeadingStyleBase
-// mock values since H1/2/3Style classes anyway are used
+// mock values since H1/2/3/4/5/6Style classes anyway are used
+ (StyleType)getStyleType {
return None;
}
diff --git a/ios/utils/StyleHeaders.h b/ios/utils/StyleHeaders.h
index 6384f3852..dc848eff0 100644
--- a/ios/utils/StyleHeaders.h
+++ b/ios/utils/StyleHeaders.h
@@ -69,7 +69,16 @@
@interface H3Style : HeadingStyleBase
@end
-@interface UnorderedListStyle : NSObject
+@interface H4Style : HeadingStyleBase
+@end
+
+@interface H5Style : HeadingStyleBase
+@end
+
+@interface H6Style : HeadingStyleBase
+@end
+
+@interface UnorderedListStyle : NSObject
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
- (BOOL)tryHandlingListShorcutInRange:(NSRange)range
replacementText:(NSString *)text;
diff --git a/ios/utils/StyleTypeEnum.h b/ios/utils/StyleTypeEnum.h
index d20419ddb..b19fcb087 100644
--- a/ios/utils/StyleTypeEnum.h
+++ b/ios/utils/StyleTypeEnum.h
@@ -10,6 +10,9 @@ typedef NS_ENUM(NSInteger, StyleType) {
H1,
H2,
H3,
+ H4,
+ H5,
+ H6,
Link,
Mention,
Image,
diff --git a/src/EnrichedTextInput.tsx b/src/EnrichedTextInput.tsx
index 826b8e6d9..795830d92 100644
--- a/src/EnrichedTextInput.tsx
+++ b/src/EnrichedTextInput.tsx
@@ -51,6 +51,9 @@ export interface EnrichedTextInputInstance extends NativeMethods {
toggleH1: () => void;
toggleH2: () => void;
toggleH3: () => void;
+ toggleH4: () => void;
+ toggleH5: () => void;
+ toggleH6: () => void;
toggleCodeBlock: () => void;
toggleBlockQuote: () => void;
toggleOrderedList: () => void;
@@ -70,19 +73,18 @@ export interface OnChangeMentionEvent {
text: string;
}
+type HeadingStyle = {
+ fontSize?: number;
+ bold?: boolean;
+};
+
export interface HtmlStyle {
- h1?: {
- fontSize?: number;
- bold?: boolean;
- };
- h2?: {
- fontSize?: number;
- bold?: boolean;
- };
- h3?: {
- fontSize?: number;
- bold?: boolean;
- };
+ h1?: HeadingStyle;
+ h2?: HeadingStyle;
+ h3?: HeadingStyle;
+ h4?: HeadingStyle;
+ h5?: HeadingStyle;
+ h6?: HeadingStyle;
blockquote?: {
borderColor?: ColorValue;
borderWidth?: number;
@@ -282,6 +284,15 @@ export const EnrichedTextInput = ({
toggleH3: () => {
Commands.toggleH3(nullthrows(nativeRef.current));
},
+ toggleH4: () => {
+ Commands.toggleH4(nullthrows(nativeRef.current));
+ },
+ toggleH5: () => {
+ Commands.toggleH5(nullthrows(nativeRef.current));
+ },
+ toggleH6: () => {
+ Commands.toggleH6(nullthrows(nativeRef.current));
+ },
toggleCodeBlock: () => {
Commands.toggleCodeBlock(nullthrows(nativeRef.current));
},
diff --git a/src/EnrichedTextInputNativeComponent.ts b/src/EnrichedTextInputNativeComponent.ts
index 7d1a8e932..d50d90dae 100644
--- a/src/EnrichedTextInputNativeComponent.ts
+++ b/src/EnrichedTextInputNativeComponent.ts
@@ -25,6 +25,9 @@ export interface OnChangeStateEvent {
isH1: boolean;
isH2: boolean;
isH3: boolean;
+ isH4: boolean;
+ isH5: boolean;
+ isH6: boolean;
isCodeBlock: boolean;
isBlockQuote: boolean;
isOrderedList: boolean;
@@ -75,19 +78,18 @@ export interface MentionStyleProperties {
textDecorationLine?: 'underline' | 'none';
}
+type Heading = {
+ fontSize?: Float;
+ bold?: boolean;
+};
+
export interface HtmlStyleInternal {
- h1?: {
- fontSize?: Float;
- bold?: boolean;
- };
- h2?: {
- fontSize?: Float;
- bold?: boolean;
- };
- h3?: {
- fontSize?: Float;
- bold?: boolean;
- };
+ h1?: Heading;
+ h2?: Heading;
+ h3?: Heading;
+ h4?: Heading;
+ h5?: Heading;
+ h6?: Heading;
blockquote?: {
borderColor?: ColorValue;
borderWidth?: Float;
@@ -187,6 +189,9 @@ interface NativeCommands {
toggleH1: (viewRef: React.ElementRef) => void;
toggleH2: (viewRef: React.ElementRef) => void;
toggleH3: (viewRef: React.ElementRef) => void;
+ toggleH4: (viewRef: React.ElementRef) => void;
+ toggleH5: (viewRef: React.ElementRef) => void;
+ toggleH6: (viewRef: React.ElementRef) => void;
toggleCodeBlock: (viewRef: React.ElementRef) => void;
toggleBlockQuote: (viewRef: React.ElementRef) => void;
toggleOrderedList: (viewRef: React.ElementRef) => void;
@@ -237,6 +242,9 @@ export const Commands: NativeCommands = codegenNativeCommands({
'toggleH1',
'toggleH2',
'toggleH3',
+ 'toggleH4',
+ 'toggleH5',
+ 'toggleH6',
'toggleCodeBlock',
'toggleBlockQuote',
'toggleOrderedList',
diff --git a/src/normalizeHtmlStyle.ts b/src/normalizeHtmlStyle.ts
index 245ed2e4f..03a1d6b21 100644
--- a/src/normalizeHtmlStyle.ts
+++ b/src/normalizeHtmlStyle.ts
@@ -18,6 +18,18 @@ const defaultStyle: Required = {
fontSize: 20,
bold: false,
},
+ h4: {
+ fontSize: 16,
+ bold: false,
+ },
+ h5: {
+ fontSize: 14,
+ bold: false,
+ },
+ h6: {
+ fontSize: 12,
+ bold: false,
+ },
blockquote: {
borderColor: 'darkgray',
borderWidth: 4,
From 328ed061d1f240e02e65ce9b756587858dca5097 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Tue, 6 Jan 2026 22:20:24 +0100
Subject: [PATCH 2/6] fix: rebase with latest main
---
.../enriched/spans/EnrichedH4Span.kt | 4 +
.../enriched/spans/EnrichedH5Span.kt | 4 +
.../enriched/spans/EnrichedH6Span.kt | 4 +
ios/EnrichedTextInputView.mm | 330 +++++++++++-------
ios/inputParser/InputParser.mm | 142 +++++---
ios/styles/BoldStyle.mm | 44 ++-
ios/styles/H4Style.mm | 10 +-
ios/styles/H5Style.mm | 10 +-
ios/styles/H6Style.mm | 10 +-
ios/utils/StyleHeaders.h | 2 +-
10 files changed, 375 insertions(+), 185 deletions(-)
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
index 76f649476..d33ae85d7 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
@@ -7,6 +7,8 @@ import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
import com.swmansion.enriched.styles.HtmlStyle
class EnrichedH4Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h4FontSize), EnrichedHeadingSpan {
+ override val dependsOnHtmlStyle: Boolean = true
+
override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h4Bold
@@ -14,4 +16,6 @@ class EnrichedH4Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlSt
tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
}
}
+
+ override fun rebuildWithStyle(htmlStyle: HtmlStyle): EnrichedH4Span = EnrichedH4Span(htmlStyle)
}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
index 437bddf14..f92c28c7c 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
@@ -7,6 +7,8 @@ import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
import com.swmansion.enriched.styles.HtmlStyle
class EnrichedH5Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h5FontSize), EnrichedHeadingSpan {
+ override val dependsOnHtmlStyle: Boolean = true
+
override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h5Bold
@@ -14,4 +16,6 @@ class EnrichedH5Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlSt
tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
}
}
+
+ override fun rebuildWithStyle(htmlStyle: HtmlStyle): EnrichedH5Span = EnrichedH5Span(htmlStyle)
}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
index 22c89e7d0..999afc340 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
@@ -7,6 +7,8 @@ import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
import com.swmansion.enriched.styles.HtmlStyle
class EnrichedH6Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h6FontSize), EnrichedHeadingSpan {
+ override val dependsOnHtmlStyle: Boolean = true
+
override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h6Bold
@@ -14,4 +16,6 @@ class EnrichedH6Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlSt
tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
}
}
+
+ override fun rebuildWithStyle(htmlStyle: HtmlStyle): EnrichedH6Span = EnrichedH6Span(htmlStyle)
}
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index 996e56452..181116514 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -86,23 +86,30 @@ - (void)setDefaults {
stylesDict = @{
@([BoldStyle getStyleType]) : [[BoldStyle alloc] initWithInput:self],
- @([ItalicStyle getStyleType]): [[ItalicStyle alloc] initWithInput:self],
- @([UnderlineStyle getStyleType]): [[UnderlineStyle alloc] initWithInput:self],
- @([StrikethroughStyle getStyleType]): [[StrikethroughStyle alloc] initWithInput:self],
- @([InlineCodeStyle getStyleType]): [[InlineCodeStyle alloc] initWithInput:self],
- @([LinkStyle getStyleType]): [[LinkStyle alloc] initWithInput:self],
- @([MentionStyle getStyleType]): [[MentionStyle alloc] initWithInput:self],
- @([H1Style getStyleType]): [[H1Style alloc] initWithInput:self],
- @([H2Style getStyleType]): [[H2Style alloc] initWithInput:self],
- @([H3Style getStyleType]): [[H3Style alloc] initWithInput:self],
- @([H4Style getStyleType]): [[H4Style alloc] initWithInput:self],
- @([H5Style getStyleType]): [[H5Style alloc] initWithInput:self],
- @([H6Style getStyleType]): [[H6Style alloc] initWithInput:self],
- @([UnorderedListStyle getStyleType]): [[UnorderedListStyle alloc] initWithInput:self],
- @([OrderedListStyle getStyleType]): [[OrderedListStyle alloc] initWithInput:self],
- @([BlockQuoteStyle getStyleType]): [[BlockQuoteStyle alloc] initWithInput:self],
- @([CodeBlockStyle getStyleType]): [[CodeBlockStyle alloc] initWithInput:self],
- @([ImageStyle getStyleType]): [[ImageStyle alloc] initWithInput:self]
+ @([ItalicStyle getStyleType]) : [[ItalicStyle alloc] initWithInput:self],
+ @([UnderlineStyle getStyleType]) :
+ [[UnderlineStyle alloc] initWithInput:self],
+ @([StrikethroughStyle getStyleType]) :
+ [[StrikethroughStyle alloc] initWithInput:self],
+ @([InlineCodeStyle getStyleType]) :
+ [[InlineCodeStyle alloc] initWithInput:self],
+ @([LinkStyle getStyleType]) : [[LinkStyle alloc] initWithInput:self],
+ @([MentionStyle getStyleType]) : [[MentionStyle alloc] initWithInput:self],
+ @([H1Style getStyleType]) : [[H1Style alloc] initWithInput:self],
+ @([H2Style getStyleType]) : [[H2Style alloc] initWithInput:self],
+ @([H3Style getStyleType]) : [[H3Style alloc] initWithInput:self],
+ @([H4Style getStyleType]) : [[H4Style alloc] initWithInput:self],
+ @([H5Style getStyleType]) : [[H5Style alloc] initWithInput:self],
+ @([H6Style getStyleType]) : [[H6Style alloc] initWithInput:self],
+ @([UnorderedListStyle getStyleType]) :
+ [[UnorderedListStyle alloc] initWithInput:self],
+ @([OrderedListStyle getStyleType]) :
+ [[OrderedListStyle alloc] initWithInput:self],
+ @([BlockQuoteStyle getStyleType]) :
+ [[BlockQuoteStyle alloc] initWithInput:self],
+ @([CodeBlockStyle getStyleType]) :
+ [[CodeBlockStyle alloc] initWithInput:self],
+ @([ImageStyle getStyleType]) : [[ImageStyle alloc] initWithInput:self]
};
conflictingStyles = @{
@@ -110,42 +117,105 @@ - (void)setDefaults {
@([ItalicStyle getStyleType]) : @[],
@([UnderlineStyle getStyleType]) : @[],
@([StrikethroughStyle getStyleType]) : @[],
- @([InlineCodeStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
- @([LinkStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
- @([MentionStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType])],
- @([H1Style getStyleType]): @[@([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([H2Style getStyleType]): @[@([H1Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([H3Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([H4Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([H5Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([H6Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([UnorderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([OrderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])],
- @([BlockQuoteStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType])],
- @([CodeBlockStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([H4Style getStyleType]), @([H5Style getStyleType]), @([H6Style getStyleType]),
- @([BoldStyle getStyleType]), @([ItalicStyle getStyleType]), @([UnderlineStyle getStyleType]), @([StrikethroughStyle getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]), @([MentionStyle getStyleType]), @([LinkStyle getStyleType])],
- @([ImageStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])]
+ @([InlineCodeStyle getStyleType]) :
+ @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ],
+ @([LinkStyle getStyleType]) : @[
+ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]),
+ @([MentionStyle getStyleType])
+ ],
+ @([MentionStyle getStyleType]) :
+ @[ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]) ],
+ @([H1Style getStyleType]) : @[
+ @([H2Style getStyleType]), @([H3Style getStyleType]),
+ @([H4Style getStyleType]), @([H5Style getStyleType]),
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([H2Style getStyleType]) : @[
+ @([H1Style getStyleType]), @([H3Style getStyleType]),
+ @([H4Style getStyleType]), @([H5Style getStyleType]),
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([H3Style getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H4Style getStyleType]), @([H5Style getStyleType]),
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([H4Style getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H5Style getStyleType]),
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([H5Style getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
+ @([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([H6Style getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
+ @([H5Style getStyleType]), @([UnorderedListStyle getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([UnorderedListStyle getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([OrderedListStyle getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
+ @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ ],
+ @([BlockQuoteStyle getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType])
+ ],
+ @([CodeBlockStyle getStyleType]) : @[
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
+ @([H3Style getStyleType]), @([H4Style getStyleType]),
+ @([H5Style getStyleType]), @([H6Style getStyleType]),
+ @([BoldStyle getStyleType]), @([ItalicStyle getStyleType]),
+ @([UnderlineStyle getStyleType]), @([StrikethroughStyle getStyleType]),
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
+ @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]),
+ @([MentionStyle getStyleType]), @([LinkStyle getStyleType])
+ ],
+ @([ImageStyle getStyleType]) :
+ @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ]
};
blockingStyles = @{
- @([BoldStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
- @([ItalicStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
- @([UnderlineStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
- @([StrikethroughStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
- @([InlineCodeStyle getStyleType]) : @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
- @([LinkStyle getStyleType]): @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
- @([MentionStyle getStyleType]): @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
- @([H1Style getStyleType]): @[],
- @([H2Style getStyleType]): @[],
- @([H3Style getStyleType]): @[],
- @([H4Style getStyleType]): @[],
- @([H5Style getStyleType]): @[],
- @([H6Style getStyleType]): @[],
- @([UnorderedListStyle getStyleType]): @[],
- @([OrderedListStyle getStyleType]): @[],
- @([BlockQuoteStyle getStyleType]): @[],
- @([CodeBlockStyle getStyleType]): @[],
- @([ImageStyle getStyleType]) : @[@([InlineCodeStyle getStyleType])]
+ @([BoldStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
+ @([ItalicStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
+ @([UnderlineStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
+ @([StrikethroughStyle getStyleType]) :
+ @[ @([CodeBlockStyle getStyleType]) ],
+ @([InlineCodeStyle getStyleType]) :
+ @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
+ @([LinkStyle getStyleType]) :
+ @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
+ @([MentionStyle getStyleType]) :
+ @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
+ @([H1Style getStyleType]) : @[],
+ @([H2Style getStyleType]) : @[],
+ @([H3Style getStyleType]) : @[],
+ @([H4Style getStyleType]) : @[],
+ @([H5Style getStyleType]) : @[],
+ @([H6Style getStyleType]) : @[],
+ @([UnorderedListStyle getStyleType]) : @[],
+ @([OrderedListStyle getStyleType]) : @[],
+ @([BlockQuoteStyle getStyleType]) : @[],
+ @([CodeBlockStyle getStyleType]) : @[],
+ @([ImageStyle getStyleType]) : @[ @([InlineCodeStyle getStyleType]) ]
};
parser = [[InputParser alloc] initWithInput:self];
@@ -277,40 +347,46 @@ - (void)updateProps:(Props::Shared const &)props
[newConfig setH3Bold:newViewProps.htmlStyle.h3.bold];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.h4.fontSize != oldViewProps.htmlStyle.h4.fontSize) {
+
+ if (newViewProps.htmlStyle.h4.fontSize !=
+ oldViewProps.htmlStyle.h4.fontSize) {
[newConfig setH4FontSize:newViewProps.htmlStyle.h4.fontSize];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.h4.bold != oldViewProps.htmlStyle.h4.bold) {
+
+ if (newViewProps.htmlStyle.h4.bold != oldViewProps.htmlStyle.h4.bold) {
[newConfig setH4Bold:newViewProps.htmlStyle.h4.bold];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.h5.fontSize != oldViewProps.htmlStyle.h5.fontSize) {
+
+ if (newViewProps.htmlStyle.h5.fontSize !=
+ oldViewProps.htmlStyle.h5.fontSize) {
[newConfig setH5FontSize:newViewProps.htmlStyle.h5.fontSize];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.h5.bold != oldViewProps.htmlStyle.h5.bold) {
+
+ if (newViewProps.htmlStyle.h5.bold != oldViewProps.htmlStyle.h5.bold) {
[newConfig setH5Bold:newViewProps.htmlStyle.h5.bold];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.h6.fontSize != oldViewProps.htmlStyle.h6.fontSize) {
+
+ if (newViewProps.htmlStyle.h6.fontSize !=
+ oldViewProps.htmlStyle.h6.fontSize) {
[newConfig setH6FontSize:newViewProps.htmlStyle.h6.fontSize];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.h6.bold != oldViewProps.htmlStyle.h6.bold) {
+
+ if (newViewProps.htmlStyle.h6.bold != oldViewProps.htmlStyle.h6.bold) {
[newConfig setH6Bold:newViewProps.htmlStyle.h6.bold];
stylePropChanged = YES;
}
-
- if(newViewProps.htmlStyle.blockquote.borderColor != oldViewProps.htmlStyle.blockquote.borderColor) {
- if(isColorMeaningful(newViewProps.htmlStyle.blockquote.borderColor)) {
- [newConfig setBlockquoteBorderColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.blockquote.borderColor)];
+
+ if (newViewProps.htmlStyle.blockquote.borderColor !=
+ oldViewProps.htmlStyle.blockquote.borderColor) {
+ if (isColorMeaningful(newViewProps.htmlStyle.blockquote.borderColor)) {
+ [newConfig setBlockquoteBorderColor:RCTUIColorFromSharedColor(
+ newViewProps.htmlStyle.blockquote
+ .borderColor)];
stylePropChanged = YES;
}
}
@@ -863,24 +939,33 @@ - (void)tryUpdatingActiveStyles {
_activeStyles = newActiveStyles;
emitter->onChangeState({
- .isBold = [_activeStyles containsObject: @([BoldStyle getStyleType])],
- .isItalic = [_activeStyles containsObject: @([ItalicStyle getStyleType])],
- .isUnderline = [_activeStyles containsObject: @([UnderlineStyle getStyleType])],
- .isStrikeThrough = [_activeStyles containsObject: @([StrikethroughStyle getStyleType])],
- .isInlineCode = [_activeStyles containsObject: @([InlineCodeStyle getStyleType])],
- .isLink = [_activeStyles containsObject: @([LinkStyle getStyleType])],
- .isMention = [_activeStyles containsObject: @([MentionStyle getStyleType])],
- .isH1 = [_activeStyles containsObject: @([H1Style getStyleType])],
- .isH2 = [_activeStyles containsObject: @([H2Style getStyleType])],
- .isH3 = [_activeStyles containsObject: @([H3Style getStyleType])],
- .isH4 = [_activeStyles containsObject: @([H4Style getStyleType])],
- .isH5 = [_activeStyles containsObject: @([H5Style getStyleType])],
- .isH6 = [_activeStyles containsObject: @([H6Style getStyleType])],
- .isUnorderedList = [_activeStyles containsObject: @([UnorderedListStyle getStyleType])],
- .isOrderedList = [_activeStyles containsObject: @([OrderedListStyle getStyleType])],
- .isBlockQuote = [_activeStyles containsObject: @([BlockQuoteStyle getStyleType])],
- .isCodeBlock = [_activeStyles containsObject: @([CodeBlockStyle getStyleType])],
- .isImage = [_activeStyles containsObject: @([ImageStyle getStyleType])],
+ .isBold = [_activeStyles containsObject:@([BoldStyle getStyleType])],
+ .isItalic =
+ [_activeStyles containsObject:@([ItalicStyle getStyleType])],
+ .isUnderline =
+ [_activeStyles containsObject:@([UnderlineStyle getStyleType])],
+ .isStrikeThrough =
+ [_activeStyles containsObject:@([StrikethroughStyle getStyleType])],
+ .isInlineCode =
+ [_activeStyles containsObject:@([InlineCodeStyle getStyleType])],
+ .isLink = [_activeStyles containsObject:@([LinkStyle getStyleType])],
+ .isMention =
+ [_activeStyles containsObject:@([MentionStyle getStyleType])],
+ .isH1 = [_activeStyles containsObject:@([H1Style getStyleType])],
+ .isH2 = [_activeStyles containsObject:@([H2Style getStyleType])],
+ .isH3 = [_activeStyles containsObject:@([H3Style getStyleType])],
+ .isH4 = [_activeStyles containsObject:@([H4Style getStyleType])],
+ .isH5 = [_activeStyles containsObject:@([H5Style getStyleType])],
+ .isH6 = [_activeStyles containsObject:@([H6Style getStyleType])],
+ .isUnorderedList =
+ [_activeStyles containsObject:@([UnorderedListStyle getStyleType])],
+ .isOrderedList =
+ [_activeStyles containsObject:@([OrderedListStyle getStyleType])],
+ .isBlockQuote =
+ [_activeStyles containsObject:@([BlockQuoteStyle getStyleType])],
+ .isCodeBlock =
+ [_activeStyles containsObject:@([CodeBlockStyle getStyleType])],
+ .isImage = [_activeStyles containsObject:@([ImageStyle getStyleType])],
});
}
}
@@ -946,13 +1031,13 @@ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
[self toggleParagraphStyle:[H2Style getStyleType]];
} else if ([commandName isEqualToString:@"toggleH3"]) {
[self toggleParagraphStyle:[H3Style getStyleType]];
- } else if([commandName isEqualToString:@"toggleH4"]) {
+ } else if ([commandName isEqualToString:@"toggleH4"]) {
[self toggleParagraphStyle:[H4Style getStyleType]];
- } else if([commandName isEqualToString:@"toggleH5"]) {
+ } else if ([commandName isEqualToString:@"toggleH5"]) {
[self toggleParagraphStyle:[H5Style getStyleType]];
- } else if([commandName isEqualToString:@"toggleH6"]) {
+ } else if ([commandName isEqualToString:@"toggleH6"]) {
[self toggleParagraphStyle:[H6Style getStyleType]];
- } else if([commandName isEqualToString:@"toggleUnorderedList"]) {
+ } else if ([commandName isEqualToString:@"toggleUnorderedList"]) {
[self toggleParagraphStyle:[UnorderedListStyle getStyleType]];
} else if ([commandName isEqualToString:@"toggleOrderedList"]) {
[self toggleParagraphStyle:[OrderedListStyle getStyleType]];
@@ -1369,12 +1454,12 @@ - (void)anyTextMayHaveBeenModified {
H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
-
+
bool shouldHandleImproperHeadings =
- h1Style != nullptr && h2Style != nullptr && h3Style != nullptr &&
- h4Style != nullptr && h5Style != nullptr && h6Style != nullptr;
+ h1Style != nullptr && h2Style != nullptr && h3Style != nullptr &&
+ h4Style != nullptr && h5Style != nullptr && h6Style != nullptr;
- if(shouldHandleImproperHeadings) {
+ if (shouldHandleImproperHeadings) {
[h1Style handleImproperHeadings];
[h2Style handleImproperHeadings];
[h3Style handleImproperHeadings];
@@ -1534,33 +1619,40 @@ - (bool)textView:(UITextView *)textView
H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
-
- // some of the changes these checks do could interfere with later checks and cause a crash
- // so here I rely on short circuiting evaluation of the logical expression
- // either way it's not possible to have two of them come off at the same time
- if(
- [uStyle handleBackspaceInRange:range replacementText:text] ||
- [uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
- [oStyle handleBackspaceInRange:range replacementText:text] ||
- [oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
- [bqStyle handleBackspaceInRange:range replacementText:text] ||
- [cbStyle handleBackspaceInRange:range replacementText:text] ||
- [linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
- [mentionStyle handleLeadingMentionReplacement:range replacementText:text] ||
- [h1Style handleNewlinesInRange:range replacementText:text] ||
- [h2Style handleNewlinesInRange:range replacementText:text] ||
- [h3Style handleNewlinesInRange:range replacementText:text] ||
- [h4Style handleNewlinesInRange:range replacementText:text] ||
- [h5Style handleNewlinesInRange:range replacementText:text] ||
- [h6Style handleNewlinesInRange:range replacementText:text] ||
- [ZeroWidthSpaceUtils handleBackspaceInRange:range replacementText:text input:self] ||
- [ParagraphAttributesUtils handleBackspaceInRange:range replacementText:text input:self] ||
- // CRITICAL: This callback HAS TO be always evaluated last.
- //
- // This function is the "Generic Fallback": if no specific style claims the backspace action
- // to change its state, only then do we proceed to physically delete the newline and merge paragraphs.
- [ParagraphAttributesUtils handleNewlineBackspaceInRange:range replacementText:text input:self]
- ) {
+
+ // some of the changes these checks do could interfere with later checks and
+ // cause a crash so here I rely on short circuiting evaluation of the logical
+ // expression either way it's not possible to have two of them come off at the
+ // same time
+ if ([uStyle handleBackspaceInRange:range replacementText:text] ||
+ [uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
+ [oStyle handleBackspaceInRange:range replacementText:text] ||
+ [oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
+ [bqStyle handleBackspaceInRange:range replacementText:text] ||
+ [cbStyle handleBackspaceInRange:range replacementText:text] ||
+ [linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
+ [mentionStyle handleLeadingMentionReplacement:range
+ replacementText:text] ||
+ [h1Style handleNewlinesInRange:range replacementText:text] ||
+ [h2Style handleNewlinesInRange:range replacementText:text] ||
+ [h3Style handleNewlinesInRange:range replacementText:text] ||
+ [h4Style handleNewlinesInRange:range replacementText:text] ||
+ [h5Style handleNewlinesInRange:range replacementText:text] ||
+ [h6Style handleNewlinesInRange:range replacementText:text] ||
+ [ZeroWidthSpaceUtils handleBackspaceInRange:range
+ replacementText:text
+ input:self] ||
+ [ParagraphAttributesUtils handleBackspaceInRange:range
+ replacementText:text
+ input:self] ||
+ // CRITICAL: This callback HAS TO be always evaluated last.
+ //
+ // This function is the "Generic Fallback": if no specific style claims
+ // the backspace action to change its state, only then do we proceed to
+ // physically delete the newline and merge paragraphs.
+ [ParagraphAttributesUtils handleParagraphStylesMergeOnBackspace:range
+ replacementText:text
+ input:self]) {
[self anyTextMayHaveBeenModified];
return NO;
}
diff --git a/ios/inputParser/InputParser.mm b/ios/inputParser/InputParser.mm
index 09d0f0939..0ab87e7c8 100644
--- a/ios/inputParser/InputParser.mm
+++ b/ios/inputParser/InputParser.mm
@@ -217,17 +217,20 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
}
// don't add the tag if some paragraph styles are present
- if([currentActiveStyles containsObject:@([UnorderedListStyle getStyleType])] ||
- [currentActiveStyles containsObject:@([OrderedListStyle getStyleType])] ||
- [currentActiveStyles containsObject:@([H1Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H2Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H3Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H4Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H5Style getStyleType])] ||
- [currentActiveStyles containsObject:@([H6Style getStyleType])] ||
- [currentActiveStyles containsObject:@([BlockQuoteStyle getStyleType])] ||
- [currentActiveStyles containsObject:@([CodeBlockStyle getStyleType])]
- ) {
+ if ([currentActiveStyles
+ containsObject:@([UnorderedListStyle getStyleType])] ||
+ [currentActiveStyles
+ containsObject:@([OrderedListStyle getStyleType])] ||
+ [currentActiveStyles containsObject:@([H1Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H2Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H3Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H4Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H5Style getStyleType])] ||
+ [currentActiveStyles containsObject:@([H6Style getStyleType])] ||
+ [currentActiveStyles
+ containsObject:@([BlockQuoteStyle getStyleType])] ||
+ [currentActiveStyles
+ containsObject:@([CodeBlockStyle getStyleType])]) {
[result appendString:@"\n"];
} else {
[result appendString:@"\n
"];
@@ -373,14 +376,18 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
} else if ([previousActiveStyles
containsObject:@([CodeBlockStyle getStyleType])]) {
[result appendString:@"\n"];
- } else if(
- [previousActiveStyles containsObject:@([H1Style getStyleType])] ||
- [previousActiveStyles containsObject:@([H2Style getStyleType])] ||
- [previousActiveStyles containsObject:@([H3Style getStyleType])] ||
- [previousActiveStyles containsObject:@([H4Style getStyleType])] ||
- [previousActiveStyles containsObject:@([H5Style getStyleType])] ||
- [previousActiveStyles containsObject:@([H6Style getStyleType])]
- ) {
+ } else if ([previousActiveStyles
+ containsObject:@([H1Style getStyleType])] ||
+ [previousActiveStyles
+ containsObject:@([H2Style getStyleType])] ||
+ [previousActiveStyles
+ containsObject:@([H3Style getStyleType])] ||
+ [previousActiveStyles
+ containsObject:@([H4Style getStyleType])] ||
+ [previousActiveStyles
+ containsObject:@([H5Style getStyleType])] ||
+ [previousActiveStyles
+ containsObject:@([H6Style getStyleType])]) {
// do nothing, heading closing tag has already been appended
} else {
[result appendString:@"
"];
@@ -515,13 +522,14 @@ - (NSString *)tagContentForStyle:(NSNumber *)style
return @"h2";
} else if ([style isEqualToNumber:@([H3Style getStyleType])]) {
return @"h3";
- } else if([style isEqualToNumber:@([H4Style getStyleType])]) {
+ } else if ([style isEqualToNumber:@([H4Style getStyleType])]) {
return @"h4";
- } else if([style isEqualToNumber:@([H5Style getStyleType])]) {
+ } else if ([style isEqualToNumber:@([H5Style getStyleType])]) {
return @"h5";
- } else if([style isEqualToNumber:@([H6Style getStyleType])]) {
+ } else if ([style isEqualToNumber:@([H6Style getStyleType])]) {
return @"h6";
- } else if([style isEqualToNumber:@([UnorderedListStyle getStyleType])] || [style isEqualToNumber:@([OrderedListStyle getStyleType])]) {
+ } else if ([style isEqualToNumber:@([UnorderedListStyle getStyleType])] ||
+ [style isEqualToNumber:@([OrderedListStyle getStyleType])]) {
return @"li";
} else if ([style isEqualToNumber:@([BlockQuoteStyle getStyleType])] ||
[style isEqualToNumber:@([CodeBlockStyle getStyleType])]) {
@@ -731,24 +739,72 @@ - (NSString *_Nullable)initiallyProcessHtml:(NSString *_Nonnull)html {
trailing:YES];
// line opening tags
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"
" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:YES trailing:NO];
-
+ fixedHtml = [self stringByAddingNewlinesToTag:@"
"
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@"
"
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:YES
+ trailing:NO];
+
// line closing tags
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"
" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
- fixedHtml = [self stringByAddingNewlinesToTag:@"" inString:fixedHtml leading:NO trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
+ fixedHtml = [self stringByAddingNewlinesToTag:@""
+ inString:fixedHtml
+ leading:NO
+ trailing:YES];
}
return fixedHtml;
@@ -1165,11 +1221,11 @@ - (NSArray *)getTextAndStylesFromHtml:(NSString *)fixedHtml {
[styleArr addObject:@([H2Style getStyleType])];
} else if ([tagName isEqualToString:@"h3"]) {
[styleArr addObject:@([H3Style getStyleType])];
- } else if([tagName isEqualToString:@"h4"]) {
+ } else if ([tagName isEqualToString:@"h4"]) {
[styleArr addObject:@([H4Style getStyleType])];
- } else if([tagName isEqualToString:@"h5"]) {
+ } else if ([tagName isEqualToString:@"h5"]) {
[styleArr addObject:@([H5Style getStyleType])];
- } else if([tagName isEqualToString:@"h6"]) {
+ } else if ([tagName isEqualToString:@"h6"]) {
[styleArr addObject:@([H6Style getStyleType])];
}
} else if ([tagName isEqualToString:@"ul"]) {
diff --git a/ios/styles/BoldStyle.mm b/ios/styles/BoldStyle.mm
index c69f96eb6..1afe0d609 100644
--- a/ios/styles/BoldStyle.mm
+++ b/ios/styles/BoldStyle.mm
@@ -92,18 +92,30 @@ - (void)removeTypingAttributes {
}
- (BOOL)boldHeadingConflictsInRange:(NSRange)range type:(StyleType)type {
- if(type == H1) {
- if(![_input->config h1Bold]) { return NO; }
- } else if(type == H2) {
- if(![_input->config h2Bold]) { return NO; }
- } else if(type == H3) {
- if(![_input->config h3Bold]) { return NO; }
- } else if(type == H4) {
- if(![_input->config h4Bold]) { return NO; }
- } else if(type == H5) {
- if(![_input->config h5Bold]) { return NO; }
- } else if(type == H6) {
- if(![_input->config h6Bold]) { return NO; }
+ if (type == H1) {
+ if (![_input->config h1Bold]) {
+ return NO;
+ }
+ } else if (type == H2) {
+ if (![_input->config h2Bold]) {
+ return NO;
+ }
+ } else if (type == H3) {
+ if (![_input->config h3Bold]) {
+ return NO;
+ }
+ } else if (type == H4) {
+ if (![_input->config h4Bold]) {
+ return NO;
+ }
+ } else if (type == H5) {
+ if (![_input->config h5Bold]) {
+ return NO;
+ }
+ } else if (type == H6) {
+ if (![_input->config h6Bold]) {
+ return NO;
+ }
}
id headingStyle = _input->stylesDict[@(type)];
@@ -113,7 +125,13 @@ - (BOOL)boldHeadingConflictsInRange:(NSRange)range type:(StyleType)type {
- (BOOL)styleCondition:(id _Nullable)value:(NSRange)range {
UIFont *font = (UIFont *)value;
- return font != nullptr && [font isBold] && ![self boldHeadingConflictsInRange:range type:H1] && ![self boldHeadingConflictsInRange:range type:H2] && ![self boldHeadingConflictsInRange:range type:H3] && ![self boldHeadingConflictsInRange:range type:H4] && ![self boldHeadingConflictsInRange:range type:H5] && ![self boldHeadingConflictsInRange:range type:H6];
+ return font != nullptr && [font isBold] &&
+ ![self boldHeadingConflictsInRange:range type:H1] &&
+ ![self boldHeadingConflictsInRange:range type:H2] &&
+ ![self boldHeadingConflictsInRange:range type:H3] &&
+ ![self boldHeadingConflictsInRange:range type:H4] &&
+ ![self boldHeadingConflictsInRange:range type:H5] &&
+ ![self boldHeadingConflictsInRange:range type:H6];
}
- (BOOL)detectStyle:(NSRange)range {
diff --git a/ios/styles/H4Style.mm b/ios/styles/H4Style.mm
index 2c76eb37a..a12047f40 100644
--- a/ios/styles/H4Style.mm
+++ b/ios/styles/H4Style.mm
@@ -1,9 +1,13 @@
-#import "StyleHeaders.h"
#import "EnrichedTextInputView.h"
+#import "StyleHeaders.h"
@implementation H4Style
-+ (StyleType)getStyleType { return H4; }
-- (CGFloat)getHeadingFontSize { return [((EnrichedTextInputView *)input)->config h4FontSize]; }
++ (StyleType)getStyleType {
+ return H4;
+}
+- (CGFloat)getHeadingFontSize {
+ return [((EnrichedTextInputView *)input)->config h4FontSize];
+}
- (BOOL)isHeadingBold {
return [((EnrichedTextInputView *)input)->config h4Bold];
}
diff --git a/ios/styles/H5Style.mm b/ios/styles/H5Style.mm
index b47a69120..8c56b003a 100644
--- a/ios/styles/H5Style.mm
+++ b/ios/styles/H5Style.mm
@@ -1,9 +1,13 @@
-#import "StyleHeaders.h"
#import "EnrichedTextInputView.h"
+#import "StyleHeaders.h"
@implementation H5Style
-+ (StyleType)getStyleType { return H5; }
-- (CGFloat)getHeadingFontSize { return [((EnrichedTextInputView *)input)->config h5FontSize]; }
++ (StyleType)getStyleType {
+ return H5;
+}
+- (CGFloat)getHeadingFontSize {
+ return [((EnrichedTextInputView *)input)->config h5FontSize];
+}
- (BOOL)isHeadingBold {
return [((EnrichedTextInputView *)input)->config h5Bold];
}
diff --git a/ios/styles/H6Style.mm b/ios/styles/H6Style.mm
index f224e9dca..e94fdfe3c 100644
--- a/ios/styles/H6Style.mm
+++ b/ios/styles/H6Style.mm
@@ -1,9 +1,13 @@
-#import "StyleHeaders.h"
#import "EnrichedTextInputView.h"
+#import "StyleHeaders.h"
@implementation H6Style
-+ (StyleType)getStyleType { return H6; }
-- (CGFloat)getHeadingFontSize { return [((EnrichedTextInputView *)input)->config h6FontSize]; }
++ (StyleType)getStyleType {
+ return H6;
+}
+- (CGFloat)getHeadingFontSize {
+ return [((EnrichedTextInputView *)input)->config h6FontSize];
+}
- (BOOL)isHeadingBold {
return [((EnrichedTextInputView *)input)->config h6Bold];
}
diff --git a/ios/utils/StyleHeaders.h b/ios/utils/StyleHeaders.h
index dc848eff0..7a9f1ac8d 100644
--- a/ios/utils/StyleHeaders.h
+++ b/ios/utils/StyleHeaders.h
@@ -78,7 +78,7 @@
@interface H6Style : HeadingStyleBase
@end
-@interface UnorderedListStyle : NSObject
+@interface UnorderedListStyle : NSObject
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
- (BOOL)tryHandlingListShorcutInRange:(NSRange)range
replacementText:(NSString *)text;
From 002b92ca8bdca0d67585bdb1cf5e86f61bb11308 Mon Sep 17 00:00:00 2001
From: IvanIhnatsiuk
Date: Tue, 6 Jan 2026 22:21:06 +0100
Subject: [PATCH 3/6] fix: android lint
---
.../enriched/EnrichedTextInputView.kt | 92 ++++++++--------
.../enriched/spans/EnrichedH4Span.kt | 7 +-
.../enriched/spans/EnrichedH5Span.kt | 5 +-
.../enriched/spans/EnrichedH6Span.kt | 5 +-
.../swmansion/enriched/spans/EnrichedSpans.kt | 104 +++++++++++++-----
.../enriched/utils/EnrichedParser.java | 12 +-
.../enriched/utils/EnrichedSpanState.kt | 43 ++++----
7 files changed, 162 insertions(+), 106 deletions(-)
diff --git a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
index 5cc963f0c..a9a5e0735 100644
--- a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
+++ b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
@@ -488,54 +488,60 @@ class EnrichedTextInputView : AppCompatEditText {
layoutManager.invalidateLayout()
}
- private fun removeStyle(name: String, start: Int, end: Int): Boolean {
- val removed = when (name) {
- EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
- EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
- EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
- EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
- EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
- EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
- EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
- EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
- EnrichedSpans.H4 -> paragraphStyles?.removeStyle(EnrichedSpans.H4, start, end)
- EnrichedSpans.H5 -> paragraphStyles?.removeStyle(EnrichedSpans.H5, start, end)
- EnrichedSpans.H6 -> paragraphStyles?.removeStyle(EnrichedSpans.H6, start, end)
- EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
- EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
- EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
- EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
- EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
- EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
- EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
- else -> false
- }
+ private fun removeStyle(
+ name: String,
+ start: Int,
+ end: Int,
+ ): Boolean {
+ val removed =
+ when (name) {
+ EnrichedSpans.BOLD -> inlineStyles?.removeStyle(EnrichedSpans.BOLD, start, end)
+ EnrichedSpans.ITALIC -> inlineStyles?.removeStyle(EnrichedSpans.ITALIC, start, end)
+ EnrichedSpans.UNDERLINE -> inlineStyles?.removeStyle(EnrichedSpans.UNDERLINE, start, end)
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.removeStyle(EnrichedSpans.STRIKETHROUGH, start, end)
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.removeStyle(EnrichedSpans.INLINE_CODE, start, end)
+ EnrichedSpans.H1 -> paragraphStyles?.removeStyle(EnrichedSpans.H1, start, end)
+ EnrichedSpans.H2 -> paragraphStyles?.removeStyle(EnrichedSpans.H2, start, end)
+ EnrichedSpans.H3 -> paragraphStyles?.removeStyle(EnrichedSpans.H3, start, end)
+ EnrichedSpans.H4 -> paragraphStyles?.removeStyle(EnrichedSpans.H4, start, end)
+ EnrichedSpans.H5 -> paragraphStyles?.removeStyle(EnrichedSpans.H5, start, end)
+ EnrichedSpans.H6 -> paragraphStyles?.removeStyle(EnrichedSpans.H6, start, end)
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.removeStyle(EnrichedSpans.CODE_BLOCK, start, end)
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.removeStyle(EnrichedSpans.BLOCK_QUOTE, start, end)
+ EnrichedSpans.ORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.ORDERED_LIST, start, end)
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.removeStyle(EnrichedSpans.UNORDERED_LIST, start, end)
+ EnrichedSpans.LINK -> parametrizedStyles?.removeStyle(EnrichedSpans.LINK, start, end)
+ EnrichedSpans.IMAGE -> parametrizedStyles?.removeStyle(EnrichedSpans.IMAGE, start, end)
+ EnrichedSpans.MENTION -> parametrizedStyles?.removeStyle(EnrichedSpans.MENTION, start, end)
+ else -> false
+ }
return removed == true
}
private fun getTargetRange(name: String): Pair {
- val result = when (name) {
- EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
- EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
- EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
- EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
- EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
- EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H4 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H5 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.H6 -> paragraphStyles?.getStyleRange()
- EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
- EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
- EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
- EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
- EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
- EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
- EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
- else -> Pair(0, 0)
- }
+ val result =
+ when (name) {
+ EnrichedSpans.BOLD -> inlineStyles?.getStyleRange()
+ EnrichedSpans.ITALIC -> inlineStyles?.getStyleRange()
+ EnrichedSpans.UNDERLINE -> inlineStyles?.getStyleRange()
+ EnrichedSpans.STRIKETHROUGH -> inlineStyles?.getStyleRange()
+ EnrichedSpans.INLINE_CODE -> inlineStyles?.getStyleRange()
+ EnrichedSpans.H1 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H2 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H3 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H4 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H5 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.H6 -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.CODE_BLOCK -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.BLOCK_QUOTE -> paragraphStyles?.getStyleRange()
+ EnrichedSpans.ORDERED_LIST -> listStyles?.getStyleRange()
+ EnrichedSpans.UNORDERED_LIST -> listStyles?.getStyleRange()
+ EnrichedSpans.LINK -> parametrizedStyles?.getStyleRange()
+ EnrichedSpans.IMAGE -> parametrizedStyles?.getStyleRange()
+ EnrichedSpans.MENTION -> parametrizedStyles?.getStyleRange()
+ else -> Pair(0, 0)
+ }
return result ?: Pair(0, 0)
}
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
index d33ae85d7..7d01fd7d4 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt
@@ -6,9 +6,12 @@ import android.text.style.AbsoluteSizeSpan
import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
import com.swmansion.enriched.styles.HtmlStyle
-class EnrichedH4Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h4FontSize), EnrichedHeadingSpan {
+class EnrichedH4Span(
+ private val htmlStyle: HtmlStyle,
+) : AbsoluteSizeSpan(htmlStyle.h4FontSize),
+ EnrichedHeadingSpan {
override val dependsOnHtmlStyle: Boolean = true
-
+
override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h4Bold
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
index f92c28c7c..80abf6137 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt
@@ -6,7 +6,10 @@ import android.text.style.AbsoluteSizeSpan
import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
import com.swmansion.enriched.styles.HtmlStyle
-class EnrichedH5Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h5FontSize), EnrichedHeadingSpan {
+class EnrichedH5Span(
+ private val htmlStyle: HtmlStyle,
+) : AbsoluteSizeSpan(htmlStyle.h5FontSize),
+ EnrichedHeadingSpan {
override val dependsOnHtmlStyle: Boolean = true
override fun updateDrawState(tp: TextPaint) {
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
index 999afc340..85a4f7cfb 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt
@@ -6,7 +6,10 @@ import android.text.style.AbsoluteSizeSpan
import com.swmansion.enriched.spans.interfaces.EnrichedHeadingSpan
import com.swmansion.enriched.styles.HtmlStyle
-class EnrichedH6Span(private val htmlStyle: HtmlStyle) : AbsoluteSizeSpan(htmlStyle.h6FontSize), EnrichedHeadingSpan {
+class EnrichedH6Span(
+ private val htmlStyle: HtmlStyle,
+) : AbsoluteSizeSpan(htmlStyle.h6FontSize),
+ EnrichedHeadingSpan {
override val dependsOnHtmlStyle: Boolean = true
override fun updateDrawState(tp: TextPaint) {
diff --git a/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt b/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
index 09616ca39..3589a73f7 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
@@ -63,16 +63,17 @@ object EnrichedSpans {
INLINE_CODE to BaseSpanConfig(EnrichedInlineCodeSpan::class.java),
)
- val paragraphSpans: Map = mapOf(
- H1 to ParagraphSpanConfig(EnrichedH1Span::class.java, false),
- H2 to ParagraphSpanConfig(EnrichedH2Span::class.java, false),
- H3 to ParagraphSpanConfig(EnrichedH3Span::class.java, false),
- H4 to ParagraphSpanConfig(EnrichedH4Span::class.java, false),
- H5 to ParagraphSpanConfig(EnrichedH5Span::class.java, false),
- H6 to ParagraphSpanConfig(EnrichedH6Span::class.java, false),
- BLOCK_QUOTE to ParagraphSpanConfig(EnrichedBlockQuoteSpan::class.java, true),
- CODE_BLOCK to ParagraphSpanConfig(EnrichedCodeBlockSpan::class.java, true),
- )
+ val paragraphSpans: Map =
+ mapOf(
+ H1 to ParagraphSpanConfig(EnrichedH1Span::class.java, false),
+ H2 to ParagraphSpanConfig(EnrichedH2Span::class.java, false),
+ H3 to ParagraphSpanConfig(EnrichedH3Span::class.java, false),
+ H4 to ParagraphSpanConfig(EnrichedH4Span::class.java, false),
+ H5 to ParagraphSpanConfig(EnrichedH5Span::class.java, false),
+ H6 to ParagraphSpanConfig(EnrichedH6Span::class.java, false),
+ BLOCK_QUOTE to ParagraphSpanConfig(EnrichedBlockQuoteSpan::class.java, true),
+ CODE_BLOCK to ParagraphSpanConfig(EnrichedCodeBlockSpan::class.java, true),
+ )
val listSpans: Map =
mapOf(
@@ -147,41 +148,84 @@ object EnrichedSpans {
if (htmlStyle.h3Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
+
H4 -> {
val conflictingStyles = mutableListOf(H1, H2, H3, H5, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
if (htmlStyle.h4Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
+
H5 -> {
val conflictingStyles = mutableListOf(H1, H2, H3, H4, H6, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
if (htmlStyle.h5Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
+
H6 -> {
val conflictingStyles = mutableListOf(H1, H2, H3, H4, H5, ORDERED_LIST, UNORDERED_LIST, BLOCK_QUOTE, CODE_BLOCK)
if (htmlStyle.h6Bold) conflictingStyles.add(BOLD)
StylesMergingConfig(conflictingStyles = conflictingStyles.toTypedArray())
}
- BLOCK_QUOTE -> StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, CODE_BLOCK, ORDERED_LIST, UNORDERED_LIST)
- )
- CODE_BLOCK -> StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, UNORDERED_LIST, ORDERED_LIST, BLOCK_QUOTE, INLINE_CODE)
- )
- UNORDERED_LIST -> StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, ORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE)
- )
- ORDERED_LIST -> StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, UNORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
- )
- LINK -> StylesMergingConfig(
- blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, MENTION)
- )
- IMAGE -> StylesMergingConfig()
- MENTION -> StylesMergingConfig(
- blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, LINK)
- )
- else -> null
+
+ BLOCK_QUOTE -> {
+ StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, CODE_BLOCK, ORDERED_LIST, UNORDERED_LIST),
+ )
+ }
+
+ CODE_BLOCK -> {
+ StylesMergingConfig(
+ conflictingStyles =
+ arrayOf(
+ H1,
+ H2,
+ H3,
+ H4,
+ H5,
+ H6,
+ BOLD,
+ ITALIC,
+ UNDERLINE,
+ STRIKETHROUGH,
+ UNORDERED_LIST,
+ ORDERED_LIST,
+ BLOCK_QUOTE,
+ INLINE_CODE,
+ ),
+ )
+ }
+
+ UNORDERED_LIST -> {
+ StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, ORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
+ )
+ }
+
+ ORDERED_LIST -> {
+ StylesMergingConfig(
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, UNORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
+ )
+ }
+
+ LINK -> {
+ StylesMergingConfig(
+ blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, MENTION),
+ )
+ }
+
+ IMAGE -> {
+ StylesMergingConfig()
+ }
+
+ MENTION -> {
+ StylesMergingConfig(
+ blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, LINK),
+ )
+ }
+
+ else -> {
+ null
+ }
}
fun isTypeContinuous(type: Class<*>): Boolean = paragraphSpans.values.find { it.clazz == type }?.isContinuous == true
diff --git a/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java b/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
index 1a2e1cb55..82c89efd6 100644
--- a/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
+++ b/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
@@ -861,17 +861,13 @@ private static class H2 {}
private static class H3 {}
- private static class H4 {
- }
+ private static class H4 {}
- private static class H5 {
- }
+ private static class H5 {}
- private static class H6 {
- }
+ private static class H6 {}
- private static class Bold {
- }
+ private static class Bold {}
private static class Italic {}
diff --git a/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt b/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
index da24a797f..f22acca8f 100644
--- a/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
+++ b/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
@@ -141,27 +141,28 @@ class EnrichedSpanState(
}
fun getStart(name: String): Int? {
- val start = when (name) {
- EnrichedSpans.BOLD -> boldStart
- EnrichedSpans.ITALIC -> italicStart
- EnrichedSpans.UNDERLINE -> underlineStart
- EnrichedSpans.STRIKETHROUGH -> strikethroughStart
- EnrichedSpans.INLINE_CODE -> inlineCodeStart
- EnrichedSpans.H1 -> h1Start
- EnrichedSpans.H2 -> h2Start
- EnrichedSpans.H3 -> h3Start
- EnrichedSpans.H4 -> h4Start
- EnrichedSpans.H5 -> h5Start
- EnrichedSpans.H6 -> h6Start
- EnrichedSpans.CODE_BLOCK -> codeBlockStart
- EnrichedSpans.BLOCK_QUOTE -> blockQuoteStart
- EnrichedSpans.ORDERED_LIST -> orderedListStart
- EnrichedSpans.UNORDERED_LIST -> unorderedListStart
- EnrichedSpans.LINK -> linkStart
- EnrichedSpans.IMAGE -> imageStart
- EnrichedSpans.MENTION -> mentionStart
- else -> null
- }
+ val start =
+ when (name) {
+ EnrichedSpans.BOLD -> boldStart
+ EnrichedSpans.ITALIC -> italicStart
+ EnrichedSpans.UNDERLINE -> underlineStart
+ EnrichedSpans.STRIKETHROUGH -> strikethroughStart
+ EnrichedSpans.INLINE_CODE -> inlineCodeStart
+ EnrichedSpans.H1 -> h1Start
+ EnrichedSpans.H2 -> h2Start
+ EnrichedSpans.H3 -> h3Start
+ EnrichedSpans.H4 -> h4Start
+ EnrichedSpans.H5 -> h5Start
+ EnrichedSpans.H6 -> h6Start
+ EnrichedSpans.CODE_BLOCK -> codeBlockStart
+ EnrichedSpans.BLOCK_QUOTE -> blockQuoteStart
+ EnrichedSpans.ORDERED_LIST -> orderedListStart
+ EnrichedSpans.UNORDERED_LIST -> unorderedListStart
+ EnrichedSpans.LINK -> linkStart
+ EnrichedSpans.IMAGE -> imageStart
+ EnrichedSpans.MENTION -> mentionStart
+ else -> null
+ }
return start
}
From f5b4597eba1623ca60c4cadfb34e21a2bcd9266b Mon Sep 17 00:00:00 2001
From: Igor Furgala
Date: Wed, 7 Jan 2026 11:59:35 +0100
Subject: [PATCH 4/6] fix: handle html style update - android
---
.../java/com/swmansion/enriched/styles/HtmlStyle.kt | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt b/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
index 66043b932..cb36ad877 100644
--- a/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
+++ b/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
@@ -268,6 +268,12 @@ class HtmlStyle {
h2Bold == other.h2Bold &&
h3FontSize == other.h3FontSize &&
h3Bold == other.h3Bold &&
+ h4FontSize == other.h4FontSize &&
+ h4Bold == other.h4Bold &&
+ h5FontSize == other.h5FontSize &&
+ h5Bold == other.h5Bold &&
+ h6FontSize == other.h6FontSize &&
+ h6Bold == other.h6Bold &&
blockquoteColor == other.blockquoteColor &&
blockquoteBorderColor == other.blockquoteBorderColor &&
@@ -304,6 +310,12 @@ class HtmlStyle {
result = 31 * result + h2Bold.hashCode()
result = 31 * result + h3FontSize.hashCode()
result = 31 * result + h3Bold.hashCode()
+ result = 31 * result + h4FontSize.hashCode()
+ result = 31 * result + h4Bold.hashCode()
+ result = 31 * result + h5FontSize.hashCode()
+ result = 31 * result + h5Bold.hashCode()
+ result = 31 * result + h6FontSize.hashCode()
+ result = 31 * result + h6Bold.hashCode()
result = 31 * result + (blockquoteColor ?: 0)
result = 31 * result + blockquoteBorderColor.hashCode()
From ee00cca8ed8959f657320efecb28d3573f0a325d Mon Sep 17 00:00:00 2001
From: Igor Furgala
Date: Wed, 7 Jan 2026 12:10:59 +0100
Subject: [PATCH 5/6] chore: update heading docs
---
README.md | 4 +---
docs/API_REFERENCE.md | 49 ++++++++++++++++++++++++++++++++++++++-----
2 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index f2e49eaf0..a7df24c1f 100644
--- a/README.md
+++ b/README.md
@@ -144,9 +144,7 @@ Supported styles:
- underline
- strikethrough
- inline code
-- H1 heading
-- H2 heading
-- H3 heading
+- H1, H2, H3, H4, H5 and H6 headings
- codeblock
- blockquote
- ordered list
diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md
index f8f73f4ee..0c75f9e0c 100644
--- a/docs/API_REFERENCE.md
+++ b/docs/API_REFERENCE.md
@@ -156,6 +156,9 @@ interface OnChangeStateEvent {
isH1: boolean;
isH2: boolean;
isH3: boolean;
+ isH4: boolean;
+ isH5: boolean;
+ isH6: boolean;
isCodeBlock: boolean;
isBlockQuote: boolean;
isOrderedList: boolean;
@@ -461,7 +464,7 @@ Toggles codeblock formatting at the current selection.
toggleH1: () => void;
```
-Toggles heading 1 (h1) style at the current selection.
+Toggles heading 1 (H1) style at the current selection.
### `.toggleH2()`
@@ -469,7 +472,7 @@ Toggles heading 1 (h1) style at the current selection.
toggleH2: () => void;
```
-Toggles heading 2 (h2) style at the current selection.
+Toggles heading 2 (H2) style at the current selection.
### `.toggleH3()`
@@ -477,7 +480,31 @@ Toggles heading 2 (h2) style at the current selection.
toggleH3: () => void;
```
-Toggles heading 3 (h3) style at the current selection.
+Toggles heading 3 (H3) style at the current selection.
+
+### `.toggleH4()`
+
+```ts
+toggleH4: () => void;
+```
+
+Toggles heading 4 (H4) style at the current selection.
+
+### `.toggleH5()`
+
+```ts
+toggleH5: () => void;
+```
+
+Toggles heading 5 (H5) style at the current selection.
+
+### `.toggleH6()`
+
+```ts
+toggleH6: () => void;
+```
+
+Toggles heading 6 (H6) style at the current selection.
### `.toggleInlineCode()`
@@ -545,6 +572,18 @@ interface HtmlStyle {
fontSize?: number;
bold?: boolean;
};
+ h4?: {
+ fontSize?: number;
+ bold?: boolean;
+ };
+ h5?: {
+ fontSize?: number;
+ bold?: boolean;
+ };
+ h6?: {
+ fontSize?: number;
+ bold?: boolean;
+ };
blockquote?: {
borderColor?: ColorValue;
borderWidth?: number;
@@ -586,9 +625,9 @@ interface MentionStyleProperties {
}
```
-### h1/h2/h3 (headings)
+### h1/h2/h3/h4/h5/h6 (headings)
-- `fontSize` is the size of the heading's font, defaults to `32`/`24`/`20` for h1/h2/h3.
+- `fontSize` is the size of the heading's font. Defaults to `32` for `H1`, `24` for `H2`, `20` for `H3`, `16` for `H4`, `14` for `H5`, `12` for `H6`.
- `bold` defines whether the heading should be bolded, defaults to `false`.
> [!NOTE]
From b9b1d8b3000f7cd2534db020eddf71f7abdddeb9 Mon Sep 17 00:00:00 2001
From: szydlovsky <9szydlowski9@gmail.com>
Date: Wed, 7 Jan 2026 14:16:12 +0100
Subject: [PATCH 6/6] fix: iOS missing/wrongly deleted code
---
ios/EnrichedTextInputView.mm | 35 +++++++++++++++++++++-------------
ios/inputParser/InputParser.mm | 25 +++++++++++++++++++++---
ios/styles/H4Style.mm | 3 +++
ios/styles/H5Style.mm | 3 +++
ios/styles/H6Style.mm | 3 +++
5 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/ios/EnrichedTextInputView.mm b/ios/EnrichedTextInputView.mm
index 2b8da4eda..13bf2b0e8 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -129,55 +129,64 @@ - (void)setDefaults {
@([H2Style getStyleType]), @([H3Style getStyleType]),
@([H4Style getStyleType]), @([H5Style getStyleType]),
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([H2Style getStyleType]) : @[
@([H1Style getStyleType]), @([H3Style getStyleType]),
@([H4Style getStyleType]), @([H5Style getStyleType]),
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([H3Style getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H4Style getStyleType]), @([H5Style getStyleType]),
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([H4Style getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H3Style getStyleType]), @([H5Style getStyleType]),
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([H5Style getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H3Style getStyleType]), @([H4Style getStyleType]),
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([H6Style getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H3Style getStyleType]), @([H4Style getStyleType]),
@([H5Style getStyleType]), @([UnorderedListStyle getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([UnorderedListStyle getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H3Style getStyleType]), @([H4Style getStyleType]),
@([H5Style getStyleType]), @([H6Style getStyleType]),
- @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([OrderedListStyle getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H3Style getStyleType]), @([H4Style getStyleType]),
@([H5Style getStyleType]), @([H6Style getStyleType]),
- @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType])
+ @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([BlockQuoteStyle getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@([H3Style getStyleType]), @([H4Style getStyleType]),
@([H5Style getStyleType]), @([H6Style getStyleType]),
- @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType])
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
+ @([CodeBlockStyle getStyleType])
],
@([CodeBlockStyle getStyleType]) : @[
@([H1Style getStyleType]), @([H2Style getStyleType]),
@@ -1454,11 +1463,11 @@ - (void)anyTextMayHaveBeenModified {
H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
- bool shouldHandleImproperHeadings =
- h1Style != nullptr && h2Style != nullptr && h3Style != nullptr &&
- h4Style != nullptr && h5Style != nullptr && h6Style != nullptr;
+ bool headingStylesDefined = h1Style != nullptr && h2Style != nullptr &&
+ h3Style != nullptr && h4Style != nullptr &&
+ h5Style != nullptr && h6Style != nullptr;
- if (shouldHandleImproperHeadings) {
+ if (headingStylesDefined) {
[h1Style handleImproperHeadings];
[h2Style handleImproperHeadings];
[h3Style handleImproperHeadings];
diff --git a/ios/inputParser/InputParser.mm b/ios/inputParser/InputParser.mm
index 0ab87e7c8..4ca1d7d43 100644
--- a/ios/inputParser/InputParser.mm
+++ b/ios/inputParser/InputParser.mm
@@ -137,6 +137,9 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
[previousActiveStyles containsObject:@([H1Style getStyleType])] ||
[previousActiveStyles containsObject:@([H2Style getStyleType])] ||
[previousActiveStyles containsObject:@([H3Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H4Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H5Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H6Style getStyleType])] ||
[previousActiveStyles
containsObject:@([BlockQuoteStyle getStyleType])] ||
[previousActiveStyles
@@ -805,6 +808,22 @@ - (NSString *_Nullable)initiallyProcessHtml:(NSString *_Nonnull)html {
inString:fixedHtml
leading:NO
trailing:YES];
+
+ // this is more like a hack but for some reason the last
in
+ // and are not properly changed into zero width
+ // space so we do that manually here
+ fixedHtml = [fixedHtml
+ stringByReplacingOccurrencesOfString:@"
\n
"
+ withString:@"\u200B
\n"];
+ fixedHtml = [fixedHtml
+ stringByReplacingOccurrencesOfString:@"
\n"
+ withString:@"\u200B
\n"];
+
+ // replace "
" at the end with "
\n" if input is not empty to properly
+ // handle last
in html
+ if ([fixedHtml hasSuffix:@"
"] && fixedHtml.length != 4) {
+ fixedHtml = [fixedHtml stringByAppendingString:@"\n"];
+ }
}
return fixedHtml;
@@ -833,9 +852,9 @@ - (NSString *_Nullable)initiallyProcessHtml:(NSString *_Nonnull)html {
* you MUST add it to the `textTags` set below.
*/
- (NSString *)stripExtraWhiteSpacesAndNewlines:(NSString *)html {
- NSSet *textTags =
- [NSSet setWithObjects:@"p", @"h1", @"h2", @"h3", @"li", @"b", @"a", @"s",
- @"mention", @"code", @"u", @"i", nil];
+ NSSet *textTags = [NSSet setWithObjects:@"p", @"h1", @"h2", @"h3", @"h4",
+ @"h5", @"h6", @"li", @"b", @"a", @"s",
+ @"mention", @"code", @"u", @"i", nil];
NSMutableString *output = [NSMutableString stringWithCapacity:html.length];
NSMutableString *currentTagBuffer = [NSMutableString string];
diff --git a/ios/styles/H4Style.mm b/ios/styles/H4Style.mm
index a12047f40..0fef5cc7d 100644
--- a/ios/styles/H4Style.mm
+++ b/ios/styles/H4Style.mm
@@ -5,6 +5,9 @@ @implementation H4Style
+ (StyleType)getStyleType {
return H4;
}
++ (BOOL)isParagraphStyle {
+ return YES;
+}
- (CGFloat)getHeadingFontSize {
return [((EnrichedTextInputView *)input)->config h4FontSize];
}
diff --git a/ios/styles/H5Style.mm b/ios/styles/H5Style.mm
index 8c56b003a..60a06abaf 100644
--- a/ios/styles/H5Style.mm
+++ b/ios/styles/H5Style.mm
@@ -5,6 +5,9 @@ @implementation H5Style
+ (StyleType)getStyleType {
return H5;
}
++ (BOOL)isParagraphStyle {
+ return YES;
+}
- (CGFloat)getHeadingFontSize {
return [((EnrichedTextInputView *)input)->config h5FontSize];
}
diff --git a/ios/styles/H6Style.mm b/ios/styles/H6Style.mm
index e94fdfe3c..80b46f810 100644
--- a/ios/styles/H6Style.mm
+++ b/ios/styles/H6Style.mm
@@ -5,6 +5,9 @@ @implementation H6Style
+ (StyleType)getStyleType {
return H6;
}
++ (BOOL)isParagraphStyle {
+ return YES;
+}
- (CGFloat)getHeadingFontSize {
return [((EnrichedTextInputView *)input)->config h6FontSize];
}