diff --git a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
index 086b5d8e9..ccecd7f43 100644
--- a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
+++ b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt
@@ -409,6 +409,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)
@@ -429,6 +432,9 @@ class EnrichedTextInputView : AppCompatEditText {
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)
@@ -452,6 +458,9 @@ class EnrichedTextInputView : AppCompatEditText {
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()
diff --git a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt
index 286a19b7b..91b004ce7 100644
--- a/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt
+++ b/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt
@@ -235,6 +235,18 @@ class EnrichedTextInputViewManager : SimpleViewManager(),
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 ef1b408ee..6b7f71342 100644
--- a/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
+++ b/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt
@@ -25,6 +25,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"
@@ -49,6 +52,9 @@ object EnrichedSpans {
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),
)
@@ -71,6 +77,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())
}
ITALIC -> StylesMergingConfig(
@@ -87,31 +96,46 @@ object EnrichedSpans {
blockingStyles = arrayOf(CODE_BLOCK)
)
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())
}
+ 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, CODE_BLOCK, ORDERED_LIST, UNORDERED_LIST)
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, 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)
+ 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, ORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE)
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, ORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE)
)
ORDERED_LIST -> StylesMergingConfig(
- conflictingStyles = arrayOf(H1, H2, H3, UNORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
+ conflictingStyles = arrayOf(H1, H2, H3, H4, H5, H6, UNORDERED_LIST, CODE_BLOCK, BLOCK_QUOTE),
)
LINK -> StylesMergingConfig(
blockingStyles = arrayOf(INLINE_CODE, CODE_BLOCK, MENTION)
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 8a4b9088f..de258b3f8 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
@@ -80,6 +89,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 46e08f72b..782cc1d2e 100644
--- a/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
+++ b/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java
@@ -16,6 +16,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;
@@ -153,6 +156,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";
}
}
@@ -452,6 +461,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, mStyle);
} else if (tag.equalsIgnoreCase("code")) {
@@ -490,6 +505,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")) {
@@ -593,6 +614,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);
}
@@ -614,6 +644,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);
}
@@ -807,6 +849,15 @@ private static class H2 {
private static class H3 {
}
+ private static class H4 {
+ }
+
+ private static class H5 {
+ }
+
+ private static class H6 {
+ }
+
private static class Bold {
}
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 ff733dd4f..66f86729a 100644
--- a/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
+++ b/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt
@@ -27,6 +27,12 @@ class EnrichedSpanState(private val view: EnrichedTextInputView) {
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
@@ -82,6 +88,21 @@ class EnrichedSpanState(private val view: EnrichedTextInputView) {
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()
@@ -127,6 +148,9 @@ class EnrichedSpanState(private val view: EnrichedTextInputView) {
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
@@ -150,6 +174,9 @@ class EnrichedSpanState(private val view: EnrichedTextInputView) {
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)
@@ -170,6 +197,9 @@ class EnrichedSpanState(private val view: EnrichedTextInputView) {
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/example/src/App.tsx b/example/src/App.tsx
index 3c29531fe..dedaa2969 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -47,6 +47,9 @@ const DEFAULT_STYLE: StylesState = {
isH1: false,
isH2: false,
isH3: false,
+ isH4: false,
+ isH5: false,
+ isH6: false,
isBlockQuote: false,
isCodeBlock: false,
isOrderedList: false,
@@ -341,14 +344,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/example/src/components/Toolbar.tsx b/example/src/components/Toolbar.tsx
index 28c99b48a..6fad4c527 100644
--- a/example/src/components/Toolbar.tsx
+++ b/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 f145feefa..6022d96c2 100644
--- a/ios/EnrichedTextInputView.mm
+++ b/ios/EnrichedTextInputView.mm
@@ -91,6 +91,9 @@ - (void)setDefaults {
@([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],
@@ -106,13 +109,16 @@ - (void)setDefaults {
@([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]),
+ @([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])]
};
@@ -128,6 +134,9 @@ - (void)setDefaults {
@([H1Style getStyleType]): @[],
@([H2Style getStyleType]): @[],
@([H3Style getStyleType]): @[],
+ @([H4Style getStyleType]): @[],
+ @([H5Style getStyleType]): @[],
+ @([H6Style getStyleType]): @[],
@([UnorderedListStyle getStyleType]): @[],
@([OrderedListStyle getStyleType]): @[],
@([BlockQuoteStyle getStyleType]): @[],
@@ -252,6 +261,36 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
stylePropChanged = YES;
}
+ 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)];
@@ -732,6 +771,9 @@ - (void)tryUpdatingActiveStyles {
.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])],
@@ -798,6 +840,12 @@ - (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"]) {
+ [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"]) {
@@ -1106,10 +1154,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 hasImproperHeadingStyles =
+ h1Style != nullptr && h2Style != nullptr && h3Style != nullptr &&
+ h4Style != nullptr && h5Style != nullptr && h6Style != nullptr;
+
+ if(hasImproperHeadingStyles) {
[h1Style handleImproperHeadings];
[h2Style handleImproperHeadings];
[h3Style handleImproperHeadings];
+ [h4Style handleImproperHeadings];
+ [h5Style handleImproperHeadings];
+ [h6Style handleImproperHeadings];
}
// mentions removal management
@@ -1233,6 +1292,9 @@ - (bool)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range r
H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
+ 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
@@ -1249,6 +1311,9 @@ - (bool)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range r
[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.
diff --git a/ios/config/InputConfig.h b/ios/config/InputConfig.h
index e73935413..cff127c18 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 0e5287c74..631b3f9f5 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;
@@ -218,6 +230,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 10f250aba..03c666122 100644
--- a/ios/inputParser/InputParser.mm
+++ b/ios/inputParser/InputParser.mm
@@ -166,6 +166,9 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
[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])]
) {
@@ -284,9 +287,12 @@ - (NSString *)parseToHtmlFromRange:(NSRange)range {
} else if(
[previousActiveStyles containsObject:@([H1Style getStyleType])] ||
[previousActiveStyles containsObject:@([H2Style getStyleType])] ||
- [previousActiveStyles containsObject:@([H3Style getStyleType])]
+ [previousActiveStyles containsObject:@([H3Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H4Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H5Style getStyleType])] ||
+ [previousActiveStyles containsObject:@([H6Style getStyleType])]
) {
- // do nothing, heading closing tag has already ben appended
+ // do nothing, heading closing tag has already been appended
} else {
[result appendString:@"
"];
}
@@ -389,6 +395,12 @@ - (NSString *)tagContentForStyle:(NSNumber *)style openingTag:(BOOL)openingTag l
return @"h2";
} else if([style isEqualToNumber:@([H3Style getStyleType])]) {
return @"h3";
+ } 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])]) {
@@ -519,6 +531,9 @@ - (NSString * _Nullable)initiallyProcessHtml:(NSString * _Nonnull)html {
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];
@@ -526,6 +541,9 @@ - (NSString * _Nullable)initiallyProcessHtml:(NSString * _Nonnull)html {
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;
@@ -745,6 +763,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 78b80b4a2..28ac55bfd 100644
--- a/ios/styles/BoldStyle.mm
+++ b/ios/styles/BoldStyle.mm
@@ -79,6 +79,12 @@ - (BOOL)boldHeadingConflictsInRange:(NSRange)range type:(StyleType)type {
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)];
@@ -89,7 +95,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 4d3beacab..b1e0699ce 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; }
- (CGFloat)getHeadingFontSize { return 0; }
- (BOOL)isHeadingBold { return false; }
diff --git a/ios/utils/StyleHeaders.h b/ios/utils/StyleHeaders.h
index f980529cc..a6f353a79 100644
--- a/ios/utils/StyleHeaders.h
+++ b/ios/utils/StyleHeaders.h
@@ -61,6 +61,15 @@
@interface H3Style : HeadingStyleBase
@end
+@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 07f2d2fe2..0392aac88 100644
--- a/src/EnrichedTextInput.tsx
+++ b/src/EnrichedTextInput.tsx
@@ -47,6 +47,9 @@ export interface EnrichedTextInputInstance extends NativeMethods {
toggleH1: () => void;
toggleH2: () => void;
toggleH3: () => void;
+ toggleH4: () => void;
+ toggleH5: () => void;
+ toggleH6: () => void;
toggleCodeBlock: () => void;
toggleBlockQuote: () => void;
toggleOrderedList: () => void;
@@ -66,19 +69,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;
@@ -257,6 +259,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 e0b943201..ff0caa6fc 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;
@@ -70,19 +73,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;
@@ -180,6 +182,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;
@@ -220,6 +225,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 96a7053ea..299cc062f 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,