
Signature.pudu
Pudu81 lines3.4 KB
1/** @Docgen.Api.Signature — declarations shown with keywords marked and types linked */2module PuduLangDocgen.Api.Signature34import Std.Map as Map5import Std.Text as Text6import PuduLangDocgen.Api.Lexer as Lexer7import PuduLangDocgen.Api.Model as Model8import PuduLangDocgen as Docgen9import PuduLangDocgen.Paths as Paths101112const KEYWORDS: Array[Str] = ["fn", "async", "type", "trait", "impl", "const", "for", "export", "module", "self", "Self"]1314151617export fn resolve(unit: &Model.Unit, written: Str, references: &Map[Str, Docgen.Reference]) -> Str {18 let parts = written.split(".")19 if parts.length() >= 2 {20 let alias = parts[0]21 for (name, imported) in unit.imports {22 if name == alias {23 let uid = imported + "." + parts.slice(1, parts.length()).join(".")24 if Map.containsKey(references, uid) { return uid }25 }26 }27 }28 let local = unit.uid + "." + written29 if Map.containsKey(references, local) { return local }30 if Map.containsKey(references, written) { return written }31 ""32}33343536export fn html(unit: &Model.Unit, signature: Str, references: &Map[Str, Docgen.Reference], page: Str) -> Str {37 signature.split("\n").map(fn(line: Str) -> Str {38 let depth = line.length() - Text.trimStart(line).length()39 line.take(depth) + lineHtml(unit, line, references, page)40 }).join("\n")41}424344fn lineHtml(unit: &Model.Unit, signature: Str, references: &Map[Str, Docgen.Reference], page: Str) -> Str {45 let tokens = Lexer.tokens(signature)46 var pieces: Array[Str] = []47 var index = 048 var previous = ""49 while index < tokens.length() {50 let token = tokens[index]51 var end = index + 152 var written = token.text53 if token.kind == Lexer.Word {54 while end + 1 < tokens.length() && tokens[end].text == "." && tokens[end + 1].kind == Lexer.Word {55 written = written + "." + tokens[end + 1].text56 end = end + 257 }58 }59 let spaced = !pieces.isEmpty() && ![")", "]", ",", ":", ".", "?"].contains(token.text) && !["(", "[", ".", "&", "*", "!"].contains(previous) && !((token.text == "(" || token.text == "[") && !["->", "=", "|", ",", ":"].contains(previous))60 if spaced { pieces = pieces.push(" ") }61 let uid = if token.kind == Lexer.Word && !KEYWORDS.contains(written) { resolve(unit, written, references) } else { "" }62 if !uid.isEmpty() {63 let reference = Map.get(references, uid)64 let href = match reference {65 case Some(found) => if Paths.remote(found.href) { found.href } else { Paths.between(page, found.href) }66 case None => ""67 }68 pieces = pieces.push("<a class=\"xref\" href=\"" + Paths.escape(href) + "\">" + Paths.escape(written) + "</a>")69 } else if token.kind == Lexer.Word && KEYWORDS.contains(written) {70 pieces = pieces.push("<span class=\"hl-k\">" + written + "</span>")71 } else if token.kind == Lexer.Literal {72 pieces = pieces.push("<span class=\"hl-s\">" + Paths.escape(written) + "</span>")73 } else {74 pieces = pieces.push(Paths.escape(written))75 }76 previous = tokens[end - 1].text77 index = end78 }79 pieces.join("")80}81