Skip to content

Commit

Permalink
Merge branch 'develop' into text-view-script
Browse files Browse the repository at this point in the history
  • Loading branch information
manas-yu authored Dec 17, 2024
2 parents 25e31c0 + 1273c31 commit 0e7240c
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package org.oppia.android.util.parser.html

import android.graphics.Typeface
import android.text.Editable
import android.text.Layout
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.AlignmentSpan
import android.text.style.ImageSpan
import android.text.style.StyleSpan
import org.oppia.android.util.logging.ConsoleLogger
import org.xml.sax.Attributes

/** The custom tag corresponding to [ImageTagHandler]. */
const val CUSTOM_IMG_TAG = "oppia-noninteractive-image"
private const val CUSTOM_IMG_FILE_PATH_ATTRIBUTE = "filepath-with-value"
private const val CUSTOM_IMG_ALT_TEXT_ATTRIBUTE = "alt-with-value"
private const val CUSTOM_IMG_CAPTION_ATTRIBUTE = "caption-with-value"

/**
* A custom tag handler for supporting custom Oppia images parsed with [CustomHtmlContentHandler].
Expand All @@ -27,6 +32,8 @@ class ImageTagHandler(
) {
val source = attributes.getJsonStringValue(CUSTOM_IMG_FILE_PATH_ATTRIBUTE)
val contentDescription = attributes.getJsonStringValue(CUSTOM_IMG_ALT_TEXT_ATTRIBUTE)
val caption = attributes.getJsonStringValue(CUSTOM_IMG_CAPTION_ATTRIBUTE)

if (source != null) {
val (startIndex, endIndex) = output.run {
// Use a control character to ensure that there's at least 1 character on which to "attach"
Expand Down Expand Up @@ -57,6 +64,41 @@ class ImageTagHandler(
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
output.replace(openIndex, output.length, spannableBuilder)
} else consoleLogger.w("ImageTagHandler", "Failed to parse $CUSTOM_IMG_ALT_TEXT_ATTRIBUTE")
} else consoleLogger.w(
"ImageTagHandler",
"Failed to parse $CUSTOM_IMG_ALT_TEXT_ATTRIBUTE"
)
if (!caption.isNullOrBlank()) {
output.append("\n")
val captionStart = output.length
output.append(caption)
val captionEnd = output.length
output.setSpan(
StyleSpan(Typeface.ITALIC),
captionStart,
captionEnd,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
)
output.setSpan(
AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
captionStart,
captionEnd,
Spannable.SPAN_PARAGRAPH
)

// Insert a newline after the caption and reset alignment.
output.append("\n")
val resetStart = output.length
output.append(" ")
output.setSpan(
AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
resetStart,
output.length,
Spannable.SPAN_PARAGRAPH
)
} else consoleLogger.w(
"ImageTagHandler",
"Failed to parse $CUSTOM_IMG_CAPTION_ATTRIBUTE"
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package org.oppia.android.util.parser.html

import android.app.Application
import android.content.Context
import android.graphics.Typeface
import android.text.Html
import android.text.Layout
import android.text.Spannable
import android.text.style.AlignmentSpan
import android.text.style.ImageSpan
import android.text.style.StyleSpan
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
Expand Down Expand Up @@ -70,6 +74,11 @@ private const val IMAGE_TAG_WITH_SPACE_ONLY_ALT_VALUE_MARKUP =
"caption-with-value=\"""\" " +
"filepath-with-value=\"&amp;quot;test_image1.png&amp;quot;\"></oppia-noninteractive-image>"

private const val IMAGE_TAG_WITH_CAPTION_MARKUP =
"<oppia-noninteractive-image alt-with-value=\"&amp;quot;alt text 3&amp;quot;\" " +
"caption-with-value=\"&amp;quot;Sample Caption&amp;quot;\" " +
"filepath-with-value=\"&amp;quot;test_image1.png&amp;quot;\"></oppia-noninteractive-image>"

/** Tests for [ImageTagHandler]. */
@RunWith(AndroidJUnit4::class)
@LooperMode(LooperMode.Mode.PAUSED)
Expand Down Expand Up @@ -99,6 +108,53 @@ class ImageTagHandlerTest {

// TODO(#3085): Introduce test for verifying that the error log scenario is logged correctly.

@Test
fun testParseHtml_withImageCardMarkup_withCaption_addsCaptionWithStyleAndAlignment() {
val parsedHtml = CustomHtmlContentHandler.fromHtml(
html = IMAGE_TAG_WITH_CAPTION_MARKUP,
imageRetriever = mockImageRetriever,
customTagHandlers = tagHandlersWithImageTagSupport
)

val parsedHtmlString = parsedHtml.toString()
assertThat(parsedHtmlString).contains("Sample Caption")

val styleSpans = parsedHtml.getSpans(
/* start = */ 0,
/* end = */ parsedHtml.length,
StyleSpan::class.java
)
assertThat(styleSpans).hasLength(1)
assertThat(styleSpans[0].style).isEqualTo(Typeface.ITALIC)

val alignmentSpans = parsedHtml.getSpans(
/* start = */ 0,
/* end = */ parsedHtml.length,
AlignmentSpan.Standard::class.java
)
assertThat(alignmentSpans).hasLength(2)

// Check the first AlignmentSpan for center alignment (caption)
assertThat(alignmentSpans[0].alignment).isEqualTo(Layout.Alignment.ALIGN_CENTER)

// Check the second AlignmentSpan for normal alignment (reset)
assertThat(alignmentSpans[1].alignment).isEqualTo(Layout.Alignment.ALIGN_NORMAL)
}

@Test
fun testParseHtml_withMultipleImages_withCaptions_includesAllCaptions() {
val parsedHtml =
CustomHtmlContentHandler.fromHtml(
html = "$IMAGE_TAG_WITH_CAPTION_MARKUP and $IMAGE_TAG_WITH_CAPTION_MARKUP",
imageRetriever = mockImageRetriever,
customTagHandlers = tagHandlersWithImageTagSupport
)

val parsedHtmlStr = parsedHtml.toString()
assertThat(parsedHtmlStr).contains("Sample Caption")
assertThat(parsedHtmlStr).contains("Sample Caption")
}

@Test
fun testParseHtml_emptyString_doesNotIncludeImageSpan() {
val parsedHtml =
Expand Down

0 comments on commit 0e7240c

Please sign in to comment.