|
| 1 | +/- |
| 2 | +Copyright (c) 2024-2025 Lean FRO LLC. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Author: Emilio J. Gallego Arias |
| 5 | +-/ |
| 6 | +import VersoManual |
| 7 | + |
| 8 | +namespace DocstringSectionRegression |
| 9 | + |
| 10 | +open Verso |
| 11 | +open Verso.Output |
| 12 | +open Verso.Genre.Manual |
| 13 | + |
| 14 | +/-- A fixture for Manual docstring subsection HTML rendering. -/ |
| 15 | +structure SectionFixture where |
| 16 | + /-- Field documentation. -/ |
| 17 | + field : Nat |
| 18 | + |
| 19 | +/-- A fixture for Manual docstring constructor subsection HTML rendering. -/ |
| 20 | +inductive ConstructorFixture where |
| 21 | + /-- Constructor documentation. -/ |
| 22 | + | intro : ConstructorFixture |
| 23 | + |
| 24 | +#docs (Manual) doc "Docstring section labels" := |
| 25 | +::::::: |
| 26 | + |
| 27 | +{docstring SectionFixture} |
| 28 | + |
| 29 | +{docstring ConstructorFixture} |
| 30 | + |
| 31 | +::::::: |
| 32 | + |
| 33 | +private def hasSubstring (s sub : String) : Bool := |
| 34 | + s.find? sub |>.isSome |
| 35 | + |
| 36 | +private def compactHtml (s : String) : String := |
| 37 | + s.foldl (init := "") fun out c => |
| 38 | + if c.isWhitespace then out else out.push c |
| 39 | + |
| 40 | +private def renderDoc : IO String := do |
| 41 | + let rendered ← IO.mkRef "" |
| 42 | + let exitCode ← withLogger fun logger => do |
| 43 | + let cfg : RenderConfig := {} |
| 44 | + let (part, state) ← (traverseHtmlSingle cfg doc.toPart).run extension_impls% |>.run logger |
| 45 | + let ctxt : Manual.TraverseContext := {} |
| 46 | + let definitionIds := state.definitionIds ctxt |
| 47 | + let remotes : Multi.AllRemotes := {} |
| 48 | + let linkTargets := cfg.linkTargets state remotes |
| 49 | + let (html, _) ← |
| 50 | + (Manual.toHtml (m := ReaderT Multi.AllRemotes (ReaderT ExtensionImpls (BuildLogT IO))) |
| 51 | + {} ctxt state definitionIds linkTargets {} part).run {} |
| 52 | + |>.run remotes |
| 53 | + |>.run extension_impls% |
| 54 | + |>.run logger |
| 55 | + rendered.set html.asString |
| 56 | + unless exitCode == 0 do |
| 57 | + throw <| IO.userError "Manual docstring HTML rendering logged errors" |
| 58 | + rendered.get |
| 59 | + |
| 60 | +private def assertLabeledSection (compact label : String) : IO Unit := do |
| 61 | + let id := s!"docstring-section-{label}" |
| 62 | + let group := s!"<divclass=\"docstring-section\"role=\"group\"aria-labelledby=\"{id}\">" |
| 63 | + unless hasSubstring compact group do |
| 64 | + throw <| IO.userError s!"{label} section should render as a named group" |
| 65 | + let labelHtml := s!"<pclass=\"docstring-section-label\"id=\"{id}\">{label}</p>" |
| 66 | + unless hasSubstring compact labelHtml do |
| 67 | + throw <| IO.userError s!"{label} section should use a paragraph label with the group's ID" |
| 68 | + if hasSubstring compact s!"<h1>{label}</h1>" then |
| 69 | + throw <| IO.userError s!"{label} section label should not render as h1" |
| 70 | + |
| 71 | +/-- |
| 72 | +info: docstring section labels render as labeled groups |
| 73 | +-/ |
| 74 | +#guard_msgs in |
| 75 | +#eval show IO Unit from do |
| 76 | + let compact := compactHtml (← renderDoc) |
| 77 | + assertLabeledSection compact "Fields" |
| 78 | + assertLabeledSection compact "Constructors" |
| 79 | + IO.println "docstring section labels render as labeled groups" |
0 commit comments