Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-docgen

Documentation publishing for Pudu: articles, API references, navigation, search, and static websites

0.1.0Apache-2.01

InstallClose

FrontMatter.pudu

Pudu42 lines1.8 KB

GitHub ↗
1/** @Docgen.Markdown.FrontMatter — YAML header split from article body lines */2module PuduLangDocgen.Markdown.FrontMatter34import Std.Text as Text5import PuduLangDocgen as Docgen6import PuduLangDocgen.Yaml as Yaml78/** @Docgen.Markdown.Line — one body line with its one-based source number */9export type Line = { text: Str, number: Int }1011/** @Docgen.Markdown.Header — metadata and the body lines after it */12export type Header = { meta: Array[(Str, Docgen.Meta)], lines: Array[Line] }1314/// Metadata from a leading `---` block and the numbered lines after it.15/// A header that is not a YAML mapping fails with its one-based line.16export fn split(text: Str) -> Result[Header, (Int, Str)] {17  let unmarked = if text.startsWith("\u{feff}") { text.drop(1) } else { text }18  let all = unmarked.replace("\r\n", "\n").replace("\r", "\n").split("\n")19  if Text.trimEnd(all[0]) != "---" { return Ok(Header{meta: [], lines: numbered(&all, 0)}) }20  var close = 121  while close < all.length() && Text.trimEnd(all[close]) != "---" && Text.trimEnd(all[close]) != "..." { close = close + 1 }22  if close >= all.length() { return Err((1, "front matter is not closed")) }23  let header = all.slice(1, close).join("\n")24  let body = numbered(&all, close + 1)25  if header.trim().isEmpty() { return Ok(Header{meta: [], lines: body}) }26  let parsed = match Yaml.decode(header) {27    case Ok(found) => found28    case Err(reason) => { return Err((2, "front matter: " + reason)) }29  }30  match parsed {31    case Docgen.Fields(fields) => Ok(Header{meta: fields, lines: body})32    case _ => Err((2, "front matter must be a mapping of keys to values"))33  }34}3536/// Lines from an index numbered by their position in the file.37fn numbered(all: &Array[Str], from: Int) -> Array[Line] {38  var result: Array[Line] = []39  for index in from..all.length() { result = result.push(Line{text: all[index], number: index + 1}) }40  result41}42