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
@@ -0,0 +1,27 @@
appId: swmansion.enriched.markdown.example
tags:
- advanced
- inline
- highlight
- bold
- text
---
# checks highlight combined with bold (nested both ways)
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- tapOn:
id: underline-button

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
==**Bold inside highlight**== and **==highlight inside bold==**.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'highlight_bold_combo_display'
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
appId: swmansion.enriched.markdown.example
tags:
- advanced
- inline
- highlight
- italic
- text
---
# checks highlight combined with italic (nested both ways)
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
==*Italic inside highlight*== and *==highlight inside italic==*.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'highlight_italic_combo_display'
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
appId: swmansion.enriched.markdown.example
tags:
- advanced
- inline
- highlight
- spoiler
- text
---
# checks highlight combined with spoiler (nested both ways)
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
==||Spoiler inside highlight||== and ||==highlight inside spoiler==||.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'highlight_spoiler_combo_display'
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
appId: swmansion.enriched.markdown.example
tags:
- advanced
- inline
- highlight
- strikethrough
- text
---
# checks highlight combined with strikethrough (nested both ways)
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
==~~Strikethrough inside highlight~~== and ~~==highlight inside strikethrough==~~.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'highlight_strikethrough_combo_display'
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
appId: swmansion.enriched.markdown.example
tags:
- advanced
- inline
- highlight
- underline
- text
---
# checks highlight combined with underline (nested both ways)
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
==__Underlined inside highlight__== and __==highlight inside underline==__.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'highlight_underline_combo_display'
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
appId: swmansion.enriched.markdown.example
tags:
- smoke
- inline
- highlight
- text
---
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
==Highlighted text== and normal text and ==more highlight==.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'highlight_display'
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion .maestro/scripts/setup-android-emulator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ until adb -s "$SERIAL" shell getprop sys.boot_completed 2>/dev/null | grep -q "^
sleep 2
done

adb -s "$SERIAL" shell pm disable-user --user 0 com.google.android.inputmethod.latin
adb -s "$SERIAL" shell settings put secure show_ime_with_hard_keyboard 0

echo "Emulator ready: $AVD_NAME ($SERIAL)"
echo "DEVICE_ID=$SERIAL"
6 changes: 6 additions & 0 deletions android/src/main/cpp/jni-adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ static jint nodeTypeToJavaOrdinal(NodeType type) {
return 27;
case NodeType::Subscript:
return 28;
case NodeType::Highlight:
return 29;
default:
return 0;
}
Expand Down Expand Up @@ -218,6 +220,10 @@ JNIEXPORT jobject JNICALL Java_com_swmansion_enriched_markdown_parser_Parser_nat
if (subscriptField) {
md4cFlags.subscript = env->GetBooleanField(flags, subscriptField) == JNI_TRUE;
}
jfieldID highlightField = env->GetFieldID(flagsClass, "highlight", "Z");
if (highlightField) {
md4cFlags.highlight = env->GetBooleanField(flags, highlightField) == JNI_TRUE;
}
jfieldID permissiveAutolinksField = env->GetFieldID(flagsClass, "permissiveAutolinks", "Z");
if (permissiveAutolinksField) {
md4cFlags.permissiveAutolinks = env->GetBooleanField(flags, permissiveAutolinksField) == JNI_TRUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ object MeasurementStore {
latexMath = FeatureFlags.IS_MATH_ENABLED && props.getMapOrNull("md4cFlags").getBooleanOrDefault("latexMath", true),
superscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("superscript", false),
subscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("subscript", false),
highlight = props.getMapOrNull("md4cFlags").getBooleanOrDefault("highlight", false),
)

val fontSize = getInitialFontSize(styleMap, context, allowFontScaling, fontScale, maxFontSizeMultiplier)
Expand Down Expand Up @@ -355,6 +356,7 @@ object MeasurementStore {
latexMath = FeatureFlags.IS_MATH_ENABLED && props.getMapOrNull("md4cFlags").getBooleanOrDefault("latexMath", true),
superscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("superscript", false),
subscript = props.getMapOrNull("md4cFlags").getBooleanOrDefault("subscript", false),
highlight = props.getMapOrNull("md4cFlags").getBooleanOrDefault("highlight", false),
)
val allowTrailingMargin = props.getBooleanOrDefault("allowTrailingMargin", false)
val fontSize = getInitialFontSize(styleMap, context, allowFontScaling, fontScale, maxFontSizeMultiplier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ data class MarkdownASTNode(
Spoiler,
Superscript,
Subscript,
Highlight,
}

fun getAttribute(key: String): String? = attributes[key]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class Md4cFlags(
val latexMath: Boolean = FeatureFlags.IS_MATH_ENABLED,
val superscript: Boolean = false,
val subscript: Boolean = false,
val highlight: Boolean = false,
val permissiveAutolinks: Boolean = true,
) {
companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.swmansion.enriched.markdown.renderer

import android.text.SpannableStringBuilder
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
import com.swmansion.enriched.markdown.spans.HighlightSpan
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE

class HighlightRenderer : NodeRenderer {
override fun render(
node: MarkdownASTNode,
builder: SpannableStringBuilder,
onLinkPress: ((String) -> Unit)?,
onLinkLongPress: ((String) -> Unit)?,
factory: RendererFactory,
) {
factory.renderWithSpan(builder, { factory.renderChildren(node, builder, onLinkPress, onLinkLongPress) }) { start, end, blockStyle ->
builder.setSpan(
HighlightSpan(factory.styleCache, blockStyle),
start,
end,
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class RendererFactory(
put(MarkdownASTNode.NodeType.Underline, UnderlineRenderer(config))
put(MarkdownASTNode.NodeType.Superscript, SuperscriptRenderer())
put(MarkdownASTNode.NodeType.Subscript, SubscriptRenderer())
put(MarkdownASTNode.NodeType.Highlight, HighlightRenderer())
put(MarkdownASTNode.NodeType.Code, CodeRenderer(config))
put(MarkdownASTNode.NodeType.Image, ImageRenderer())
put(MarkdownASTNode.NodeType.LineBreak, lineBreakRenderer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class SpanStyleCache(
val superscriptBaselineOffsetScale: Float = style.superscriptStyle.baselineOffsetScale
val subscriptFontScale: Float = style.subscriptStyle.fontScale
val subscriptBaselineOffsetScale: Float = style.subscriptStyle.baselineOffsetScale
val highlightColor: Int = style.highlightStyle.color
val highlightBackgroundColor: Int = style.highlightStyle.backgroundColor
private val paragraphColor: Int = style.paragraphStyle.color

private fun buildColorsToPreserve(style: StyleConfig): IntArray {
val paragraphColor = style.paragraphStyle.color
Expand Down Expand Up @@ -75,6 +78,8 @@ class SpanStyleCache(

fun getStrongColorFor(blockColor: Int): Int = strongColor ?: blockColor

fun getHighlightColorFor(blockColor: Int): Int = if (highlightColor == paragraphColor) blockColor else highlightColor

fun getEmphasisColorFor(
blockColor: Int,
currentColor: Int,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.swmansion.enriched.markdown.spans

import android.graphics.Color
import android.text.TextPaint
import android.text.style.CharacterStyle
import com.swmansion.enriched.markdown.renderer.BlockStyle
import com.swmansion.enriched.markdown.renderer.SpanStyleCache

/**
* Applies highlight foreground/background only. Must not reset typeface or text size so nested
* strong/emphasis spans inside ==highlight== keep working (MetricAffectingSpan would overwrite them).
*/
class HighlightSpan(
private val styleCache: SpanStyleCache,
private val blockStyle: BlockStyle,
) : CharacterStyle() {
private val foregroundColor = styleCache.getHighlightColorFor(blockStyle.color)

override fun updateDrawState(textPaint: TextPaint) {
textPaint.color = foregroundColor
val backgroundColor = styleCache.highlightBackgroundColor
if (Color.alpha(backgroundColor) > 0) {
textPaint.bgColor = backgroundColor
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.swmansion.enriched.markdown.styles

import com.facebook.react.bridge.ReadableMap

data class HighlightStyle(
val color: Int,
val backgroundColor: Int,
) {
companion object {
fun fromReadableMap(
map: ReadableMap,
parser: StyleParser,
): HighlightStyle {
val color = parser.parseColor(map, "color")
val backgroundColor = parser.parseColor(map, "backgroundColor")
return HighlightStyle(color, backgroundColor)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,14 @@ class StyleConfig(
SubscriptStyle.fromReadableMap(map)
}

val highlightStyle: HighlightStyle by lazy {
val map =
requireNotNull(style.getMap("highlight")) {
"Highlight style not found. JS should always provide defaults."
}
HighlightStyle.fromReadableMap(map, styleParser)
}

val tableTypeface: Typeface? by lazy {
val fontFamily = tableStyle.fontFamily.takeIf { it.isNotEmpty() }
val fontWeight = parseFontWeight(tableStyle.fontWeight)
Expand Down Expand Up @@ -323,7 +331,8 @@ class StyleConfig(
inlineMathStyle == other.inlineMathStyle &&
spoilerStyle == other.spoilerStyle &&
superscriptStyle == other.superscriptStyle &&
subscriptStyle == other.subscriptStyle
subscriptStyle == other.subscriptStyle &&
highlightStyle == other.highlightStyle
}

override fun hashCode(): Int {
Expand All @@ -349,6 +358,7 @@ class StyleConfig(
result = 31 * result + spoilerStyle.hashCode()
result = 31 * result + superscriptStyle.hashCode()
result = 31 * result + subscriptStyle.hashCode()
result = 31 * result + highlightStyle.hashCode()
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ fun parseMd4cFlags(flags: ReadableMap?): Md4cFlags =
latexMath = FeatureFlags.IS_MATH_ENABLED && (flags?.getBoolean("latexMath") ?: true),
superscript = flags?.getBoolean("superscript") ?: false,
subscript = flags?.getBoolean("subscript") ?: false,
highlight = flags?.getBoolean("highlight") ?: false,
)

fun parseContextMenuItems(value: ReadableArray?): List<String> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ object MarkdownASTSerializer {
buffer.append("~")
}

NodeType.Highlight -> {
buffer.append("==")
appendChildren(node, buffer)
buffer.append("==")
}

NodeType.Code -> {
buffer.append("`")
appendChildren(node, buffer)
Expand Down
Loading
Loading