Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@ class EnrichedTextInputViewManager : SimpleViewManager<EnrichedTextInputView>(),
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)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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),
)
Expand All @@ -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(
Expand All @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
}
}

Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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 {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand Down
Loading
Loading