/- Copyright (c) 2022 Henrik Böving. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Henrik Böving, Xubai Wang -/ import DocGen4.Output.Base import DocGen4.Output.ToHtmlFormat import DocGen4.LeanInk.Process import Lean.Data.Json import LeanInk.Annotation.Alectryon namespace LeanInk.Annotation.Alectryon open DocGen4 Output open scoped DocGen4.Jsx structure AlectryonContext where counter : Nat abbrev AlectryonM := StateT AlectryonContext HtmlM def getNextButtonLabel : AlectryonM String := do let val ← get let newCounter := val.counter + 1 set { val with counter := newCounter } pure s!"plain-lean4-lean-chk{val.counter}" def TypeInfo.toHtml (tyi : TypeInfo) : AlectryonM Html := do pure
{tyi.name} : {tyi.type}
def Token.processSemantic (t : Token) : Html := match t.semanticType with | some "Name.Attribute" => {t.raw} | some "Name.Variable" => {t.raw} | some "Keyword" => {t.raw} | _ => Html.text t.raw def Token.toHtml (t : Token) : AlectryonM Html := do -- Right now t.link is always none from LeanInk, ignore it -- TODO: render docstring let mut parts := #[] if let some tyi := t.typeinfo then parts := parts.push $ ←tyi.toHtml parts := parts.push t.processSemantic pure -- TODO: Show rest of token [parts] def Contents.toHtml : Contents → AlectryonM Html | .string value => pure {value} | .experimentalTokens values => do let values ← values.mapM Token.toHtml pure [values] def Hypothesis.toHtml (h : Hypothesis) : AlectryonM Html := do let mut hypParts := #[[h.names.intersperse ", " |>.map Html.text |>.toArray]] if h.body != "" then hypParts := hypParts.push := {h.body} hypParts := hypParts.push : {h.type} pure [hypParts] def Goal.toHtml (g : Goal) : AlectryonM Html := do let mut hypotheses := #[] for hyp in g.hypotheses do let rendered ← hyp.toHtml hypotheses := hypotheses.push rendered hypotheses := hypotheses.push
pure
[hypotheses]

{g.name}
{g.conclusion}
def Message.toHtml (m : Message) : AlectryonM Html := do pure
-- TODO: This might have to be done in a fancier way {m.contents}
def Sentence.toHtml (s : Sentence) : AlectryonM Html := do let messages := if s.messages.size > 0 then #[
[←s.messages.mapM Message.toHtml]
] else #[] let goals := if s.goals.size > 0 then -- TODO: Alectryon has a "alectryon-extra-goals" here, implement it #[
[←s.goals.mapM Goal.toHtml]
] else #[] let buttonLabel ← getNextButtonLabel pure [messages] [goals] def Text.toHtml (t : Text) : AlectryonM Html := t.contents.toHtml def Fragment.toHtml : Fragment → AlectryonM Html | .text value => value.toHtml | .sentence value => value.toHtml def baseHtml (content : Array Html) : AlectryonM Html := do let banner :=
Built with doc-gen4, running Lean4. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use Cmd instead of Ctrl.
pure
{banner}
            [content]
          
def renderFragments (fs : Array Fragment) : AlectryonM Html := fs.mapM Fragment.toHtml >>= baseHtml end LeanInk.Annotation.Alectryon namespace DocGen4.Output.LeanInk open Lean open LeanInk.Annotation.Alectryon open scoped DocGen4.Jsx def moduleToHtml (module : Process.Module) (inkPath : System.FilePath) (sourceFilePath : System.FilePath) : HtmlT IO Html := withReader (setCurrentName module.name) do let json ← runInk inkPath sourceFilePath let fragments := fromJson? json match fragments with | .ok fragments => let render := StateT.run (LeanInk.Annotation.Alectryon.renderFragments fragments) { counter := 0 } let ctx ← read let (html, _) := ReaderT.run render ctx pure html | .error err => throw $ IO.userError s!"Error while parsing LeanInk Output: {err}" end DocGen4.Output.LeanInk