Coverage Summary for Class: FootnoteBlockParser (io.heapy.kotmark.ext.footnotes.internal)

Class Method, % Branch, % Line, % Instruction, %
FootnoteBlockParser 100% (6/6) 100% (4/4) 100% (13/13) 100% (56/56)
FootnoteBlockParser$Factory 100% (2/2) 73.1% (19/26) 96.2% (25/26) 98.2% (109/111)
Total 100% (8/8) 76.7% (23/30) 97.4% (38/39) 98.8% (165/167)


 package io.heapy.kotmark.ext.footnotes.internal
 
 import io.heapy.kotmark.ext.footnotes.FootnoteDefinition
 import io.heapy.kotmark.node.Block
 import io.heapy.kotmark.node.DefinitionMap
 import io.heapy.kotmark.parser.block.AbstractBlockParser
 import io.heapy.kotmark.parser.block.BlockContinue
 import io.heapy.kotmark.parser.block.BlockParserFactory
 import io.heapy.kotmark.parser.block.BlockStart
 import io.heapy.kotmark.parser.block.MatchedBlockParser
 import io.heapy.kotmark.parser.block.ParserState
 import io.heapy.kotmark.text.Characters
 
 class FootnoteBlockParser(
     label: String,
 ) : AbstractBlockParser() {
     private val definition = FootnoteDefinition(label)
 
     override val block: Block
         get() = definition
 
     override fun isContainer(): Boolean = true
 
     override fun canContain(childBlock: Block): Boolean = true
 
     override fun tryContinue(parserState: ParserState): BlockContinue? =
         when {
             parserState.indent >= 4 -> BlockContinue.AtColumn(4)
             parserState.isBlank -> BlockContinue.AtIndex(parserState.index)
             else -> null
         }
 
     override val definitions: List<DefinitionMap<*>>
         get() =
             listOf(
                 DefinitionMap(FootnoteDefinition::class).apply {
                     putIfAbsent(definition.label, definition)
                 },
             )
 
     class Factory : BlockParserFactory {
         override fun tryStart(
             state: ParserState,
             matchedBlockParser: MatchedBlockParser,
         ): BlockStart? {
             if (state.indent >= 4) {
                 return BlockStart.none()
             }
             var index = state.nextNonSpaceIndex
             val content = state.line.content
             if (index >= content.length || content[index] != '[' || index + 1 >= content.length) {
                 return BlockStart.none()
             }
             index++
             if (content[index] != '^' || index + 1 >= content.length) {
                 return BlockStart.none()
             }
             index++
             val labelStart = index
             while (index < content.length) {
                 when (content[index]) {
                     ']' ->
                         if (
                             index > labelStart &&
                             index + 1 < content.length &&
                             content[index + 1] == ':'
                         ) {
                             val label = content.subSequence(labelStart, index).toString()
                             val afterSpaces =
                                 Characters.skipSpaceTab(content, index + 2, content.length)
                             return BlockStart.of(FootnoteBlockParser(label)).atIndex(afterSpaces)
                         } else {
                             return BlockStart.none()
                         }
                     ' ', '\r', '\n', '\u0000', '\t' -> return BlockStart.none()
                 }
                 index++
             }
             return BlockStart.none()
         }
     }
 }