Coverage Summary for Class: YamlSubsetParser (io.heapy.kotmark.ext.front.matter.parser)

Class Method, % Branch, % Line, % Instruction, %
YamlSubsetParser 100% (5/5) 88.9% (16/18) 100% (29/29) 100% (182/182)
YamlSubsetParser$Companion 100% (1/1) 75% (6/8) 100% (8/8) 100% (70/70)
YamlSubsetParser$Factory 100% (2/2) 100% (2/2) 100% (6/6)
Total 100% (8/8) 84.6% (22/26) 100% (39/39) 100% (258/258)


 package io.heapy.kotmark.ext.front.matter.parser
 
 import io.heapy.kotmark.ext.front.matter.YamlFrontMatterBlock
 import io.heapy.kotmark.ext.front.matter.YamlFrontMatterNode
 import io.heapy.kotmark.ext.front.matter.parser.FrontMatterParser.SeparatorRole
 import io.heapy.kotmark.parser.SourceLine
 
 /** Parses the existing limited YAML subset into key/value nodes. */
 class YamlSubsetParser : FrontMatterParser {
     private var inLiteral = false
     private var currentKey: String? = null
     private var currentValues = mutableListOf<StringBuilder>()
 
     override fun onNextLine(block: YamlFrontMatterBlock, line: SourceLine) {
         val metadata = REGEX_METADATA.matchEntire(line.content)
         if (metadata != null) {
             appendCurrentNode(block)
             inLiteral = false
             currentKey = metadata.groupValues[1]
             currentValues = mutableListOf()
             val value = metadata.groupValues[2]
             if (value == "|") {
                 inLiteral = true
             } else if (value.isNotEmpty()) {
                 currentValues.add(StringBuilder(parseString(value)))
             }
         } else if (inLiteral) {
             val literal = REGEX_METADATA_LITERAL.matchEntire(line.content)
             if (literal != null) {
                 val value = literal.groupValues[1].trim()
                 if (currentValues.size == 1) {
                     currentValues[0].append('\n').append(value)
                 } else {
                     currentValues.add(StringBuilder(value))
                 }
             }
         } else {
             val listItem = REGEX_METADATA_LIST.matchEntire(line.content)
             if (listItem != null) {
                 currentValues.add(StringBuilder(parseString(listItem.groupValues[1])))
             }
         }
     }
 
     override fun onEndingSeparator(block: YamlFrontMatterBlock, separator: SourceLine): SeparatorRole {
         appendCurrentNode(block)
         return SeparatorRole.BLOCK_END
     }
 
     private fun appendCurrentNode(block: YamlFrontMatterBlock) {
         currentKey?.let { block.appendChild(YamlFrontMatterNode(it, currentValues.map { value -> value.toString() })) }
     }
 
     class Factory : FrontMatterParser.Factory {
         override fun create(): FrontMatterParser = YamlSubsetParser()
     }
 
     private companion object {
         private val REGEX_METADATA = Regex("""^[ ]{0,3}([A-Za-z0-9._-]+):\s*(.*)""")
         private val REGEX_METADATA_LIST = Regex("""^[ ]+-\s*(.*)""")
         private val REGEX_METADATA_LITERAL = Regex("""^\s*(.*)""")
 
         private fun parseString(value: String): String =
             when {
                 value.startsWith("'") && value.endsWith("'") ->
                     value.substring(1, value.length - 1).replace("''", "'")
                 value.startsWith("\"") && value.endsWith("\"") ->
                     value.substring(1, value.length - 1)
                         .replace("""\"""", "\"")
                         .replace("""\\""", "\\")
                 else -> value
             }
     }
 }