Skip to content
Merged
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
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -500,6 +503,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 @@ -524,6 +530,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 @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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 val dependsOnHtmlStyle: Boolean = true

override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h4Bold
if (bold) {
tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
}
}

override fun rebuildWithStyle(htmlStyle: HtmlStyle): EnrichedH4Span = EnrichedH4Span(htmlStyle)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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 val dependsOnHtmlStyle: Boolean = true

override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h5Bold
if (bold) {
tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
}
}

override fun rebuildWithStyle(htmlStyle: HtmlStyle): EnrichedH5Span = EnrichedH5Span(htmlStyle)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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 val dependsOnHtmlStyle: Boolean = true

override fun updateDrawState(tp: TextPaint) {
super.updateDrawState(tp)
val bold = htmlStyle.h6Bold
if (bold) {
tp.typeface = Typeface.create(tp.typeface, Typeface.BOLD)
}
}

override fun rebuildWithStyle(htmlStyle: HtmlStyle): EnrichedH6Span = EnrichedH6Span(htmlStyle)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -65,6 +68,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 Down Expand Up @@ -94,6 +100,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())
}

Expand Down Expand Up @@ -123,26 +132,44 @@ 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())
}

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),
)
}

Expand All @@ -153,6 +180,9 @@ object EnrichedSpans {
H1,
H2,
H3,
H4,
H5,
H6,
BOLD,
ITALIC,
UNDERLINE,
Expand All @@ -167,13 +197,13 @@ object EnrichedSpans {

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),
)
}

Expand Down
33 changes: 33 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 @@ -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")
Expand Down Expand Up @@ -247,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 &&
Expand Down Expand Up @@ -283,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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
}
}

Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -819,6 +861,12 @@ private static class H2 {}

private static class H3 {}

private static class H4 {}

private static class H5 {}

private static class H6 {}

private static class Bold {}

private static class Italic {}
Expand Down
Loading
Loading