All files / src/utils frontmatter.ts

93.33% Statements 42/45
90.9% Branches 30/33
100% Functions 7/7
100% Lines 35/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69              207x       54x       171x       54x 18x       117x 117x 117x 117x         41x 28x 28x   27x 27x 27x 27x   27x 207x 207x 36x 36x 36x     171x 18x 18x 18x     171x 171x 171x 171x   171x 135x 117x     27x 27x    
import type { FrontmatterValue } from '../components/Inspector'
 
export interface ParsedFrontmatter {
  [key: string]: FrontmatterValue
}
 
function unquote(s: string): string {
  return s.replace(/^["']|["']$/g, '')
}
 
function collapseList(items: string[]): FrontmatterValue {
  return items.length === 1 ? items[0] : items
}
 
function isBlockScalar(value: string): boolean {
  return value === '' || value === '|' || value === '>'
}
 
function parseInlineArray(value: string): FrontmatterValue {
  const items = value.slice(1, -1).split(',').map(s => unquote(s.trim()))
  return collapseList(items)
}
 
function parseScalar(value: string): FrontmatterValue {
  const clean = unquote(value)
  Iif (clean.toLowerCase() === 'true') return true
  Iif (clean.toLowerCase() === 'false') return false
  return clean
}
 
/** Parse YAML frontmatter from content */
export function parseFrontmatter(content: string | null): ParsedFrontmatter {
  if (!content) return {}
  const match = content.match(/^---\n([\s\S]*?)\n---/)
  if (!match) return {}
 
  const result: ParsedFrontmatter = {}
  let currentKey: string | null = null
  let currentList: string[] = []
  let inList = false
 
  for (const line of match[1].split('\n')) {
    const listMatch = line.match(/^ {2}- (.*)$/)
    if (listMatch && currentKey) {
      inList = true
      currentList.push(unquote(listMatch[1]))
      continue
    }
 
    if (inList && currentKey) {
      result[currentKey] = collapseList(currentList)
      currentList = []
      inList = false
    }
 
    const kvMatch = line.match(/^["']?([^"':]+)["']?\s*:\s*(.*)$/)
    Iif (!kvMatch) continue
    currentKey = kvMatch[1].trim()
    const value = kvMatch[2].trim()
 
    if (isBlockScalar(value)) continue
    if (value.startsWith('[') && value.endsWith(']')) { result[currentKey] = parseInlineArray(value); continue }
    result[currentKey] = parseScalar(value)
  }
 
  if (inList && currentKey) result[currentKey] = collapseList(currentList)
  return result
}