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 c6139ffa..e5c78b45 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 @@ -542,9 +542,13 @@ internal class SefariaBookPayloadReader( val sectionIndex = sectionNames.size - depth val isReferenceable = referenceableSections.getOrNull(sectionIndex) ?: true + val isNumberedParagraph = depth == 1 && hasNumberedParagraphs(bookEnTitle) val nextLinePrefix = if ( - depth == 1 && isReferenceable && currentAddressType != "Integer" && nonEmptyCount > 1 && - !hasSelfLabeledSegments(bookEnTitle) + isNumberedParagraph || + ( + depth == 1 && isReferenceable && currentAddressType != "Integer" && nonEmptyCount > 1 && + !hasSelfLabeledSegments(bookEnTitle) + ) ) { "($letter) " } else { @@ -586,6 +590,7 @@ internal class SefariaBookPayloadReader( append(", ") } val nextRefIndexOffset = childRefOffsets?.getOrNull(idx) ?: 0 + val lineCountBefore = output.size recursiveSections( sectionNames = sectionNames, @@ -604,6 +609,12 @@ internal class SefariaBookPayloadReader( referenceableSections = referenceableSections, refIndexOffset = nextRefIndexOffset ) + + // The paragraph's TOC entry points at the paragraph line itself, so the + // text gets no extra heading line. + if (isNumberedParagraph && output.size > lineCountBefore) { + headings += Heading(title = "אות $letter", level = level, lineIndex = lineCountBefore) + } } } diff --git a/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaImportText.kt b/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaImportText.kt index 87a544f6..fff464f5 100644 --- a/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaImportText.kt +++ b/generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaImportText.kt @@ -35,6 +35,24 @@ private val SELF_LABELED_SEGMENT_BOOKS = setOf("Mishnah Berurah") internal fun hasSelfLabeledSegments(bookEnTitle: String): Boolean = bookEnTitle in SELF_LABELED_SEGMENT_BOOKS +// Books whose unnamed ("Integer") segments are the printed numbered paragraphs (אותיות) +// readers navigate by: each segment gets its "(letter) " label and its own TOC entry +// (kdroidFilter/Zayit#509). +private val NUMBERED_PARAGRAPH_BOOKS = setOf( + "Bereshit Rabbah", + "Shemot Rabbah", + "Vayikra Rabbah", + "Bamidbar Rabbah", + "Devarim Rabbah", + "Ruth Rabbah", + "Esther Rabbah", + "Eikhah Rabbah", + "Kohelet Rabbah", + "Shir HaShirim Rabbah", +) + +internal fun hasNumberedParagraphs(bookEnTitle: String): Boolean = bookEnTitle in NUMBERED_PARAGRAPH_BOOKS + // Some simanim of the Mishnah Berurah (494-529) mark the seif katan as "{א}" // instead of the printed "(א)". private val BRACED_SEGMENT_MARKER_REGEX = Regex("""^\{([א-ת]{1,4})\}""") diff --git a/generator/sefariasqlite/src/jvmTest/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaNumberedParagraphsTest.kt b/generator/sefariasqlite/src/jvmTest/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaNumberedParagraphsTest.kt new file mode 100644 index 00000000..10bb1b29 --- /dev/null +++ b/generator/sefariasqlite/src/jvmTest/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaNumberedParagraphsTest.kt @@ -0,0 +1,96 @@ +package io.github.kdroidfilter.seforimlibrary.sefariasqlite + +import co.touchlab.kermit.Logger +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.json.Json +import java.nio.file.Files +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * Regression for kdroidFilter/Zayit#509: the Midrash Rabbah's paragraphs (אותיות) + * are unnamed "Integer" segments, so they had neither a number nor a TOC entry. + */ +class SefariaNumberedParagraphsTest { + @Test + fun midrashRabbahParagraphsGetLabelAndTocEntry() { + val payload = readBook("Bereshit Rabbah", "בראשית רבה") + + assertEquals( + listOf( + "