
Overwrite.pudu
Pudu116 lines5.0 KB
1/** @Docgen.Build.Overwrite — sections that amend documented identities from separate files */2module PuduLangDocgen.Build.Overwrite34import PuduLangDocgen.Api.Model as Model5import PuduLangDocgen.Constants.Codes as Codes6import PuduLangDocgen as Docgen7import PuduLangDocgen.Meta as Meta8import PuduLangDocgen.Yaml as Yaml910/** @Docgen.Build.Section — one amendment: target identity, metadata, and Markdown content */11export type Section = { uid: Str, meta: Array[(Str, Docgen.Meta)], content: Str, target: Str, source: Str, line: Int }121314const CONTENT: Str = "\u{1}content"1516171819export fn parse(path: Str, text: Str) -> (Array[Section], Array[Docgen.Diagnostic]) {20 let lines = text.replace("\r\n", "\n").split("\n")21 var sections: Array[Section] = []22 var problems: Array[Docgen.Diagnostic] = []23 var index = 024 var current: Option[Section] = None25 var body: Array[Str] = []26 while index < lines.length() {27 if lines[index].trim() == "---" {28 var close = index + 129 while close < lines.length() && lines[close].trim() != "---" { close = close + 1 }30 if close < lines.length() {31 let header = lines.slice(index + 1, close).map(|line: Str| line.replace(": *content", ": \"" + CONTENT + "\"")).join("\n")32 match Yaml.decode(header) {33 case Ok(Docgen.Fields(fields)) => {34 sections = finish(sections, ¤t, &body)35 let uid = Meta.textOr(&fields, "uid", "")36 if uid.isEmpty() {37 problems = problems.push(Docgen.error(Codes.OVERWRITE_INVALID, path, index + 1, "overwrite header needs a uid"))38 current = None39 } else {40 var target = ""41 var meta: Array[(Str, Docgen.Meta)] = []42 for (key, held) in fields {43 if held == Docgen.Text(CONTENT) { target = key } else if key != "uid" { meta = meta.push((key, held)) }44 }45 current = Some(Section{uid: uid, meta: meta, content: "", target: target, source: path, line: index + 1})46 }47 body = []48 index = close + 149 continue50 }51 case Err(reason) => {52 if index == 0 { problems = problems.push(Docgen.error(Codes.OVERWRITE_INVALID, path, 1, "overwrite header: " + reason)) }53 }54 case _ => {}55 }56 }57 }58 body = body.push(lines[index])59 index = index + 160 }61 (finish(sections, ¤t, &body), problems)62}636465fn finish(sections: Array[Section], current: &Option[Section], body: &Array[Str]) -> Array[Section] {66 match current {67 case Some(open) => sections.push(Section{..open, content: body.join("\n").trim()})68 case None => sections69 }70}717273export fn metaFor(sections: &Array[Section], uid: Str) -> Array[(Str, Docgen.Meta)] {74 var result: Array[(Str, Docgen.Meta)] = []75 for section in *sections {76 if section.uid == uid { result = Meta.merge(&result, §ion.meta) }77 }78 result79}8081828384export fn units(all: &Array[Model.Unit], sections: &Array[Section]) -> Array[Model.Unit] {85 if sections.isEmpty() { return *all }86 all.map(fn(unit: Model.Unit) -> Model.Unit {87 let members = unit.members.map(fn(member: Model.Member) -> Model.Member {88 let inner = member.members.map(|held: Model.Member| Model.Member{..held, doc: amended(held.uid, held.doc, sections)})89 Model.Member{..member, doc: amended(member.uid, member.doc, sections), members: inner}90 })91 Model.Unit{..unit, doc: amended(unit.uid, unit.doc, sections), members: members}92 })93}949596fn amended(uid: Str, doc: Str, sections: &Array[Section]) -> Str {97 var result = doc98 for section in *sections {99 if section.uid != uid || section.content.isEmpty() { continue }100 let summary = Model.summary(result)101 let remarks = Model.remarks(result)102 result = if section.target == "summary" { joined(section.content, remarks) }103 else if section.target == "remarks" { joined(summary, section.content) }104 else if section.target == "example" { joined(result, "## Examples\n\n" + section.content) }105 else { joined(result, section.content) }106 }107 result108}109110111fn joined(first: Str, second: Str) -> Str {112 if first.trim().isEmpty() { return second }113 if second.trim().isEmpty() { return first }114 first + "\n\n" + second115}116