mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-20 20:03:05 +02:00
[Kotlin Cleanup] LaTeX (#11980)
* Cleanup of LaTeX.kt * Modified tests to use string literals, new hashes, functions to public * Renamed functions to be more accurate, params/output to String, comment style
This commit is contained in:
parent
3752358577
commit
f83ce04675
@ -19,7 +19,6 @@ package com.ichi2.libanki
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.ichi2.utils.HtmlUtils.escape
|
||||
import com.ichi2.utils.KotlinCleanup
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@ -37,20 +36,19 @@ import java.util.regex.Pattern
|
||||
* Unlike the original python implementation of this class, the AnkiDroid version does not support
|
||||
* the generation of LaTeX images.
|
||||
*/
|
||||
@KotlinCleanup("fix IDE lint issues")
|
||||
object LaTeX {
|
||||
/**
|
||||
* Patterns used to identify LaTeX tags
|
||||
*/
|
||||
val STANDARD_PATTERN = Pattern.compile(
|
||||
private val STANDARD_PATTERN = Pattern.compile(
|
||||
"\\[latex](.+?)\\[/latex]",
|
||||
Pattern.DOTALL or Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
val EXPRESSION_PATTERN = Pattern.compile(
|
||||
private val EXPRESSION_PATTERN = Pattern.compile(
|
||||
"\\[\\$](.+?)\\[/\\$]",
|
||||
Pattern.DOTALL or Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
val MATH_PATTERN = Pattern.compile(
|
||||
private val MATH_PATTERN = Pattern.compile(
|
||||
"\\[\\$\\$](.+?)\\[/\\$\\$]",
|
||||
Pattern.DOTALL or Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
@ -64,49 +62,61 @@ object LaTeX {
|
||||
return mungeQA(html, col.media, model)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun convertHTML(html: String, media: Media, model: Model): String {
|
||||
val stringBuffer = StringBuffer()
|
||||
STANDARD_PATTERN.matcher(html).run {
|
||||
while (find()) {
|
||||
appendReplacement(stringBuffer, imgLink(group(1)!!, model, media))
|
||||
}
|
||||
appendTail(stringBuffer)
|
||||
}
|
||||
return stringBuffer.toString()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun convertExpression(input: String, media: Media, model: Model): String {
|
||||
val stringBuffer = StringBuffer()
|
||||
EXPRESSION_PATTERN.matcher(input).run {
|
||||
while (find()) {
|
||||
appendReplacement(stringBuffer, imgLink("$" + group(1) + "$", model, media))
|
||||
}
|
||||
appendTail(stringBuffer)
|
||||
}
|
||||
return stringBuffer.toString()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun convertMath(input: String, media: Media, model: Model): String {
|
||||
val stringBuffer = StringBuffer()
|
||||
MATH_PATTERN.matcher(input).run {
|
||||
while (find()) {
|
||||
appendReplacement(
|
||||
stringBuffer,
|
||||
imgLink("\\begin{displaymath}" + group(1) + "\\end{displaymath}", model, media)
|
||||
)
|
||||
}
|
||||
appendTail(stringBuffer)
|
||||
}
|
||||
return stringBuffer.toString()
|
||||
}
|
||||
|
||||
// It's only goal is to allow testing with a different media manager.
|
||||
@VisibleForTesting
|
||||
@JvmStatic
|
||||
@KotlinCleanup("refactor each matcher/sb code group into a standalone function")
|
||||
fun mungeQA(html: String, m: Media, model: Model): String {
|
||||
@KotlinCleanup("declare val variables for sb and matcher for each instantiation instead of using a single var variable")
|
||||
var sb = StringBuffer()
|
||||
@KotlinCleanup("use a scope function like run/with to have matcher in scope to simplify its usage")
|
||||
var matcher = STANDARD_PATTERN.matcher(html)
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(sb, _imgLink(matcher.group(1)!!, model, m))
|
||||
fun mungeQA(html: String, m: Media, model: Model): String =
|
||||
arrayOf(::convertHTML, ::convertExpression, ::convertMath).fold(html) { input, transformer ->
|
||||
transformer(input, m, model)
|
||||
}
|
||||
matcher.appendTail(sb)
|
||||
matcher = EXPRESSION_PATTERN.matcher(sb.toString())
|
||||
sb = StringBuffer()
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(sb, _imgLink("$" + matcher.group(1) + "$", model, m))
|
||||
}
|
||||
matcher.appendTail(sb)
|
||||
matcher = MATH_PATTERN.matcher(sb.toString())
|
||||
sb = StringBuffer()
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(
|
||||
sb,
|
||||
_imgLink("\\begin{displaymath}" + matcher.group(1) + "\\end{displaymath}", model, m)
|
||||
)
|
||||
}
|
||||
matcher.appendTail(sb)
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an img link for LATEX.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@JvmStatic
|
||||
internal fun _imgLink(latex: String, model: Model, m: Media): String {
|
||||
val txt = _latexFromHtml(latex)
|
||||
@KotlinCleanup("use an if expression to determine extension type and make ext a val")
|
||||
var ext = "png"
|
||||
if (model.optBoolean("latexsvg", false)) {
|
||||
ext = "svg"
|
||||
}
|
||||
internal fun imgLink(latex: String, model: Model, m: Media): String {
|
||||
val txt = latexFromHtml(latex)
|
||||
val ext = if (model.optBoolean("latexsvg", false)) "svg" else "png"
|
||||
val fname = "latex-" + Utils.checksum(txt) + "." + ext
|
||||
return if (m.have(fname)) {
|
||||
Matcher.quoteReplacement("<img class=latex alt=\"" + escape(latex) + "\" src=\"" + fname + "\">")
|
||||
@ -119,10 +129,5 @@ object LaTeX {
|
||||
* Convert entities and fix newlines.
|
||||
*/
|
||||
@JvmStatic
|
||||
@KotlinCleanup("remove the intermediary var, reduce function body to single line by inlining the method calls")
|
||||
private fun _latexFromHtml(latex: String): String {
|
||||
var l = latex.replace("<br( /)?>|<div>".toRegex(), "\n")
|
||||
l = Utils.stripHTML(l)
|
||||
return l
|
||||
}
|
||||
private fun latexFromHtml(latex: String): String = Utils.stripHTML(latex.replace("<br( /)?>|<div>".toRegex(), "\n"))
|
||||
}
|
||||
|
@ -40,26 +40,64 @@ class LaTeXTest : RobolectricTest() {
|
||||
val m: Media = MockMedia(col)
|
||||
val model = col.models.byName("Basic")!!
|
||||
// The hashing function should never change, as it would broke link. So hard coding the expected hash value is valid
|
||||
// Test with media access
|
||||
// Test with media access
|
||||
assertThat(
|
||||
LaTeX._imgLink("$\\sqrt[3]{2} + \\text{\"var\"}$", model, m),
|
||||
LaTeX.imgLink("$\\sqrt[3]{2} + \\text{\"var\"}$", model, m),
|
||||
equalTo("<img class=latex alt=\"\\$\\\\sqrt[3]{2} + \\\\text{"var"}\\$\" src=\"latex-dd84e5d506179a137f7924d0960609a8c89d491e.png\">")
|
||||
)
|
||||
|
||||
// Test without access to media
|
||||
assertThat(
|
||||
LaTeX._imgLink("$\\sqrt[3]{2} + \\text{\"var\"}$", model, col.media),
|
||||
LaTeX.imgLink("$\\sqrt[3]{2} + \\text{\"var\"}$", model, col.media),
|
||||
equalTo("\\$\\\\sqrt[3]{2} + \\\\text{\"var\"}\\$")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun htmlMatchTest() {
|
||||
val col = col
|
||||
val media: Media = MockMedia(col)
|
||||
val model = col.models.byName("Basic")!!
|
||||
// The hashing function should never change, as it would broke link. So hard coding the expected hash value is valid
|
||||
// Test with media access
|
||||
assertThat(
|
||||
LaTeX.convertHTML("""[latex]\sqrt[3]{2} + \text{"var"}[/latex]""", media, model),
|
||||
equalTo("""<img class=latex alt="\sqrt[3]{2} + \text{"var"}" src="latex-def68dc5a5ada07529f673b6493464e94f88c3df.png">""")
|
||||
)
|
||||
|
||||
// Test without access to media
|
||||
assertThat(
|
||||
LaTeX.convertHTML("""[latex]\sqrt[3]{2} + \text{"var"}[/latex]""", col.media, model),
|
||||
equalTo("""\sqrt[3]{2} + \text{"var"}""")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mathMatchTest() {
|
||||
val col = col
|
||||
val media: Media = MockMedia(col)
|
||||
val model = col.models.byName("Basic")!!
|
||||
// The hashing function should never change, as it would broke link. So hard coding the expected hash value is valid
|
||||
// Test with media access
|
||||
assertThat(
|
||||
LaTeX.convertMath("""[$$]\sqrt[3]{2} + \text{"var"}[/$$]""", media, model),
|
||||
equalTo("""<img class=latex alt="\begin{displaymath}\sqrt[3]{2} + \text{"var"}\end{displaymath}" src="latex-ac92a31b0e2dc842ac2b3542a68f81d89438793a.png">""")
|
||||
)
|
||||
|
||||
// Test without access to media
|
||||
assertThat(
|
||||
LaTeX.convertMath("""[$$]\sqrt[3]{2} + \text{"var"}[/$$]""", col.media, model),
|
||||
equalTo("""\begin{displaymath}\sqrt[3]{2} + \text{"var"}\end{displaymath}""")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mungeQATest() {
|
||||
val col = col
|
||||
val m: Media = MockMedia(col)
|
||||
val model = col.models.byName("Basic")!!
|
||||
|
||||
// Test with media access
|
||||
// Test with media access
|
||||
assertThat(
|
||||
LaTeX.mungeQA("[$]\\sqrt[3]{2} + \\text{\"var\"}[/$]", m, model),
|
||||
equalTo("<img class=latex alt=\"$\\sqrt[3]{2} + \\text{"var"}$\" src=\"latex-dd84e5d506179a137f7924d0960609a8c89d491e.png\">")
|
||||
|
Loading…
Reference in New Issue
Block a user