diff --git a/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaAuthorNames.kt b/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaAuthorNames.kt new file mode 100644 index 00000000..0041ea83 --- /dev/null +++ b/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaAuthorNames.kt @@ -0,0 +1,33 @@ +package io.github.kdroidfilter.seforimlibrary.sefariasqlite + +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.jsonObject + +/** + * Hebrew names for Sefaria authors whose topic has an empty `he` title upstream, + * keyed by Sefaria topic slug. Without them the book gets a blank author. + */ +private val missingHebrewAuthorNames = mapOf( + "abraham-cohen" to "אברהם כהן", + "joseph-albo" to "יוסף אלבו", + "meir-posner" to "מאיר פוזנר", + "meshullam-feivush-heller" to "משולם פייבוש הלר", + "nissim-chaim-moshe-mizrachi" to "ניסים חיים משה מזרחי", + "nissim-gaon" to "ניסים גאון", + "sherira-gaon" to "שרירא גאון", + "shmuel-bornsztain-of-sochatchov" to "שמואל בורנשטיין מסוכטשוב", + "yissachar-eilenburg" to "יששכר בער איילנבורג", + "yisrael-friedman1" to "ישראל פרידמן מרוז'ין", + "yitzchak-adarbi" to "יצחק אדרבי", +) + +/** + * Resolves the Hebrew name of a Sefaria `authors` entry: its `he` title, else a known + * override for its slug, else its English name. Returns null when none is usable. + */ +internal fun resolveSefariaAuthorName(author: JsonElement): String? { + val obj = author.jsonObject + return obj["he"]?.stringOrNull()?.trim()?.takeIf { it.isNotEmpty() } + ?: obj["slug"]?.stringOrNull()?.let { missingHebrewAuthorNames[it] } + ?: obj["en"]?.stringOrNull()?.trim()?.takeIf { it.isNotEmpty() } +} diff --git a/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaBookPayloadReader.kt b/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaBookPayloadReader.kt index 42dd9a48..00e1abbd 100644 --- a/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaBookPayloadReader.kt +++ b/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaBookPayloadReader.kt @@ -105,9 +105,7 @@ internal class SefariaBookPayloadReader( ?: textJson["categories"]?.jsonArray?.mapNotNull { it.jsonPrimitive.contentOrNull } ?: emptyList() - val authors = schemaJson["authors"]?.jsonArray?.mapNotNull { author -> - author.jsonObject["he"]?.stringOrNull() - } ?: emptyList() + val authors = schemaJson["authors"]?.jsonArray?.mapNotNull(::resolveSefariaAuthorName).orEmpty() val (lines, refs, headings) = buildBookContent( schemaObj = schemaObj, diff --git a/generator/sefariasqlite/src/jvmTest/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaAuthorNamesTest.kt b/generator/sefariasqlite/src/jvmTest/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaAuthorNamesTest.kt new file mode 100644 index 00000000..754b6d40 --- /dev/null +++ b/generator/sefariasqlite/src/jvmTest/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaAuthorNamesTest.kt @@ -0,0 +1,37 @@ +package io.github.kdroidfilter.seforimlibrary.sefariasqlite + +import kotlinx.serialization.json.Json +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +/** + * Regression for https://github.com/kdroidFilter/Zayit/issues/444: Sefaria ships + * Admat Kodesh's author with an empty `he` title, which produced a blank author. + */ +class SefariaAuthorNamesTest { + private fun resolve(json: String) = resolveSefariaAuthorName(Json.parseToJsonElement(json)) + + @Test + fun keepsSefariaHebrewName() { + assertEquals("רש״י", resolve("""{"en": "Rashi", "he": "רש״י", "slug": "rashi"}""")) + } + + @Test + fun usesOverrideWhenHebrewNameIsEmpty() { + assertEquals( + "ניסים חיים משה מזרחי", + resolve("""{"en": "Nissim Chaim Moshe Mizrachi", "he": "", "slug": "nissim-chaim-moshe-mizrachi"}"""), + ) + } + + @Test + fun fallsBackToEnglishForUnknownSlug() { + assertEquals("Someone", resolve("""{"en": "Someone", "he": " ", "slug": "someone"}""")) + } + + @Test + fun dropsAuthorWithoutAnyName() { + assertNull(resolve("""{"en": "", "he": "", "slug": "nobody"}""")) + } +}