Skip to content

Commit

Permalink
chore: extension method to get cloze field name and templates
Browse files Browse the repository at this point in the history
  • Loading branch information
criticalAY authored and david-allison committed May 26, 2024
1 parent 8e0db75 commit a43900a
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 0 deletions.
75 changes: 75 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Ashish Yadav <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.ichi2.anki.utils

import com.ichi2.utils.deepClonedInto
import org.intellij.lang.annotations.Language
import org.json.JSONObject

class CardTemplateJson : JSONObject {
/**
* Creates a new empty model object
*/
constructor() : super()

/**
* Creates a copy from [JSONObject] and use it as a string
*
* This function will perform deepCopy on the passed object
*
* @see CardTemplateJson.from
*/
constructor(json: JSONObject) : super() {
json.deepClonedInto(this)
}

/**
* Creates a model object form json string
*/
constructor(@Language("json") json: String) : super(json)

val name: String
get() = getString("name")

val ord: Int
get() = getInt("ord")

val qfmt: String
get() = getString("qfmt")

val afmt: String
get() = getString("afmt")

val bqfmt: String
get() = getString("bqfmt")

val bafmt: String
get() = getString("bafmt")

val did: Long?
get() = if (isNull("did")) null else getLong("did")

val bfont: String
get() = getString("bfont")

val bsize: Int
get() = getInt("bsize")

val id: Long
get() = getLong("id")
}
19 changes: 19 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/NoteType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
package com.ichi2.anki.utils.ext

import anki.notetypes.StockNotetype.OriginalStockKind.ORIGINAL_STOCK_KIND_IMAGE_OCCLUSION_VALUE
import com.ichi2.anki.utils.CardTemplateJson
import com.ichi2.libanki.NotetypeJson
import com.ichi2.utils.jsonObjectIterable
import org.json.JSONException

/**
Expand All @@ -29,3 +31,20 @@ val NotetypeJson.isImageOcclusion: Boolean
} catch (e: JSONException) {
false
}

/**
* Regular expression pattern for extracting cloze text fields.
*/
private val clozeRegex = "\\{\\{(?:.*?:)?cloze:([^}]*)\\}\\}".toRegex()

val NotetypeJson.templates: List<CardTemplateJson>
get() = getJSONArray("tmpls").jsonObjectIterable().map { CardTemplateJson(it) }

fun NotetypeJson.getAllClozeTextFields(): List<String> {
if (!this.isCloze) {
throw IllegalStateException("getAllClozeTextFields called on non-cloze template")
}

val questionFormat = templates.single().qfmt
return clozeRegex.findAll(questionFormat).map { it.groups[1]!!.value }.toList()
}
86 changes: 86 additions & 0 deletions AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2024 Ashish Yadav <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.ichi2.utils

import com.ichi2.anki.utils.ext.getAllClozeTextFields
import com.ichi2.anki.utils.ext.templates
import com.ichi2.libanki.NotetypeJson
import junit.framework.TestCase.assertEquals
import kotlin.test.Test

// link to a method in `NoteType.kt` for navigation as it contains no classes
/** Test of [NoteType][templates] */
class NoteTypeTest {

private val noteType = """
{
"type":1,
"tmpls":[
{
"name":"Cloze",
"ord":0,
"qfmt":"{{type:cloze:Text}} {{type:cloze:Text2}} {{cloze:Text3}} {{Added field}}",
"afmt":"{{cloze:Text}}<br>\n{{Back Extra}}",
"bqfmt":"",
"bafmt":"",
"did":null,
"bfont":"",
"bsize":0,
"id":1716321740
}
]
}
"""

@Test
fun testQfmtField() {
val notetypeJson = NotetypeJson(noteType)

val expectedQfmt = "{{type:cloze:Text}} {{type:cloze:Text2}} {{cloze:Text3}} {{Added field}}"
assertEquals(expectedQfmt, notetypeJson.templates[0].qfmt)
}

@Test
fun testGetAllClozeTexts() {
val notetypeJson = NotetypeJson(noteType)

val expectedClozeTexts = listOf("Text", "Text2", "Text3")
assertEquals(expectedClozeTexts, notetypeJson.getAllClozeTextFields())
}

@Test
fun testNameField() {
val notetypeJson = NotetypeJson(noteType)
val expectedName = "Cloze"
assertEquals(expectedName, notetypeJson.templates[0].name)
}

@Test
fun testOrdField() {
val notetypeJson = NotetypeJson(noteType)
val expectedOrd = 0
assertEquals(expectedOrd, notetypeJson.templates[0].ord)
}

@Test
fun testAfmtField() {
val notetypeJson = NotetypeJson(noteType)
val expectedAfmt = "{{cloze:Text}}<br>\n{{Back Extra}}"
assertEquals(expectedAfmt, notetypeJson.templates[0].afmt)
}
}

0 comments on commit a43900a

Please sign in to comment.