" -/
#guard_msgs in
diff --git a/src/tests/Tests/NestedTacticHtml.lean b/src/tests/Tests/NestedTacticHtml.lean
index 9eb774e8e..cec6d8b67 100644
--- a/src/tests/Tests/NestedTacticHtml.lean
+++ b/src/tests/Tests/NestedTacticHtml.lean
@@ -24,7 +24,7 @@ open SubVerso.Compat.Frontend (processCommands)
open SubVerso.Highlighting (Highlighted highlightFrontendResult)
open Verso.Code (HighlightHtmlM)
open Verso.Doc (Genre)
-open Verso.Output (Html)
+open Verso.Output
open Lean Elab Command
namespace Verso.NestedTacticHtmlTest
@@ -115,8 +115,8 @@ def hasClass (attrs : Array (String × String)) (cls : String) : Bool :=
/-- The concatenated text content of an HTML fragment. -/
partial def htmlText : Html → String
- | .text _ s => s
- | .tag _ _ contents => htmlText contents
+ | .text s | .raw s => s
+ | .element _ _ contents => htmlText contents
| .seq xs => xs.foldl (fun acc x => acc ++ htmlText x) ""
/-- The direct children of an HTML fragment. -/
@@ -126,9 +126,9 @@ def directChildren : Html → Array Html
/-- Whether an HTML fragment renders as nothing visible (whitespace or empty). -/
partial def htmlInsignificant : Html → Bool
- | .text _ s => s.trimAscii.isEmpty
+ | .text s | .raw s => s.trimAscii.isEmpty
| .seq xs => xs.all htmlInsignificant
- | .tag .. => false
+ | .element .. => false
/-- The last visible element of an HTML fragment, looking through `.seq` tails. -/
partial def htmlLastVisible? : Html → Option Html
@@ -139,12 +139,12 @@ partial def htmlLastVisible? : Html → Option Html
def childSpanWithClass (contents : Html) (cls : String) : Option Html :=
(directChildren contents).find? fun h =>
match h with
- | .tag "span" a _ => hasClass a cls
+ | .element "span" a _ => hasClass a cls
| _ => false
/-- Whether `html` is a `` whose own state shows "no goals". -/
def isNoGoalsState : Html → Bool
- | .tag "span" attrs contents =>
+ | .element "span" attrs contents =>
if hasClass attrs "tactic" then
match childSpanWithClass contents "tactic-state" with
| some s => htmlText s |>.contains "All goals completed"
@@ -156,7 +156,7 @@ def isNoGoalsState : Html → Bool
def labelContents (contents : Html) : Html :=
let html? :=
directChildren contents |>.findSome? fun
- | .tag "label" _ c => some c
+ | .element "label" _ c => some c
| _ => none
html?.getD .empty
@@ -167,15 +167,15 @@ states nested inside each one. A toggle is a `` whose own s
-/
partial def proofStates : Html → List ProofState
| .seq xs => xs.toList.flatMap proofStates
- | .tag name attrs contents =>
+ | .element name attrs contents =>
if name == "span" && hasClass attrs "tactic" then
let label := labelContents contents
- [{ noGoals := isNoGoalsState (.tag name attrs contents),
+ [{ noGoals := isNoGoalsState (.element name attrs contents),
endsWithNoGoals := htmlLastVisible? label |>.map isNoGoalsState |>.getD false,
children := proofStates label }]
else
proofStates contents
- | .text .. => []
+ | _ => []
/--
Whether any proof state with goals ends with a no-goals proof state — the redundant nesting that
diff --git a/src/tests/Tests/Serialization.lean b/src/tests/Tests/Serialization.lean
index 70729f8af..f980e86b5 100644
--- a/src/tests/Tests/Serialization.lean
+++ b/src/tests/Tests/Serialization.lean
@@ -260,30 +260,31 @@ where
html : Nat → Gen Html
| 0 => text
| n + 1 =>
- oneOf #[text, tag n, seq n] (by simp)
- text := .text <$> arbitrary <*> arbitrary
+ oneOf #[text, raw, tag n, seq n] (by simp)
+ text := .text <$> arbitrary
+ raw := .raw <$> arbitrary
tag n := do
let name ← arbitrary
let attrs ← sizedArrayOf do return (← arbitrary, ← arbitrary)
let content ← (html n).resize (· - 1)
- return .tag name attrs content
+ return .element name attrs content
seq n := .seq <$> sizedArrayOf (html n)
partial instance : Shrinkable Html where
shrink := shrinkHtml
where
shrinkHtml
- | .text true s =>
- .text false s :: (shrink s |>.map (.text true))
- | .text false s =>
- shrink s |>.map (.text true)
+ | .text s =>
+ .raw s :: (shrink s |>.map .text)
+ | .raw s =>
+ shrink s |>.map .text
| .seq xs =>
have : Shrinkable Html := ⟨shrinkHtml⟩
shrink xs |>.map (.seq)
- | .tag name attrs content =>
- (shrink name |>.map (.tag · attrs content)) ++
- (shrink attrs |>.map (.tag name · content)) ++
- (shrinkHtml content |>.map (.tag name attrs ·))
+ | .element name attrs content =>
+ (shrink name |>.map (.element · attrs content)) ++
+ (shrink attrs |>.map (.element name · content)) ++
+ (shrinkHtml content |>.map (.element name attrs ·))
end
section
@@ -403,7 +404,7 @@ def testRefObject := testProp <| ∀ (obj : RefObject), roundTripOk obj
def testRemoteInfo := testProp <| ∀ (info : RemoteInfo), roundTripOk info
def testAllRemotes := testProp <| ∀ (remotes : AllRemotes), roundTripOk remotes
def testTraverseState := testProp <| ∀ (st : Verso.Genre.Manual.TraverseState), roundTripOk st
-def testHtml := testProp <| ∀ (html : Verso.Output.Html), roundTripOk html
+def testHtml := testProp <| ∀ (html : Html), roundTripOk html
def testDataFile := testProp <| ∀ (f : Verso.Genre.Manual.DataFile), roundTripOk f
def testNumbering := testProp <| ∀ (n : Verso.Genre.Manual.Numbering), roundTripOk n
def testXrefSource := testProp <| ∀ (src : XrefSource), isEqOk (XrefSource.fromJson? src.toJson) src
diff --git a/src/verso-blog/VersoBlog.lean b/src/verso-blog/VersoBlog.lean
index 3faebe463..9cfae33cf 100644
--- a/src/verso-blog/VersoBlog.lean
+++ b/src/verso-blog/VersoBlog.lean
@@ -892,7 +892,7 @@ where
else
pure attr
rwTag (tag : String) (attrs : Array (String × String)) (content : Html) : ReaderT TraverseContext Id (Option Html) := do
- pure <| some <| .tag tag (← attrs.mapM rwAttr) content
+ pure <| some <| .element tag (← attrs.mapM rwAttr) content
open Verso.Code.External
diff --git a/src/verso-blog/VersoBlog/Basic.lean b/src/verso-blog/VersoBlog/Basic.lean
index d72c4ddfc..13fd2eb81 100644
--- a/src/verso-blog/VersoBlog/Basic.lean
+++ b/src/verso-blog/VersoBlog/Basic.lean
@@ -24,7 +24,7 @@ public import VersoBlog.LexedText
public section
open Std (HashSet HashMap)
-open Lean (Json ToJson FromJson)
+open Lean (Json ToJson FromJson Html)
open Verso Doc Output Html Code
open Verso.Multi
diff --git a/src/verso-blog/VersoBlog/Component.lean b/src/verso-blog/VersoBlog/Component.lean
index 9d5bbf696..488259a4d 100644
--- a/src/verso-blog/VersoBlog/Component.lean
+++ b/src/verso-blog/VersoBlog/Component.lean
@@ -18,6 +18,7 @@ open Verso.Doc
open Verso Output Html
open Std (HashSet)
+open Lean (Html)
namespace Verso.Genre.Blog
diff --git a/src/verso-blog/VersoBlog/Generate.lean b/src/verso-blog/VersoBlog/Generate.lean
index c9ed0c861..72c3db8f2 100644
--- a/src/verso-blog/VersoBlog/Generate.lean
+++ b/src/verso-blog/VersoBlog/Generate.lean
@@ -15,6 +15,7 @@ public section
open Verso Doc Output Html HtmlT FS
open Verso.Code.Hover (State)
open Verso.Code (LinkTargets)
+open Lean (Html)
namespace Verso.Genre.Blog
diff --git a/src/verso-blog/VersoBlog/Template.lean b/src/verso-blog/VersoBlog/Template.lean
index 56aba8ad7..7bb365c26 100644
--- a/src/verso-blog/VersoBlog/Template.lean
+++ b/src/verso-blog/VersoBlog/Template.lean
@@ -24,6 +24,7 @@ public section
open Std (HashSet TreeMap)
open Verso Doc Output Html HtmlT
+open Lean (Html)
open Verso.Genre Blog
open SubVerso.Highlighting
@@ -47,11 +48,11 @@ def getD [TypeName α] (value : Val) (default : α) : α :=
end Params.Val
instance : Coe String Template.Params.Val where
- coe str := ⟨.mk str, #[.mk <| Html.text true str]⟩
+ coe str := ⟨.mk str, #[.mk <| Html.text str]⟩
instance : Coe Html Template.Params.Val where
coe
- | .text true str => ↑str
+ | .text str => ↑str
| other => ⟨.mk other, #[]⟩
@@ -163,7 +164,7 @@ def blockHtml (g : Genre)
| .htmlDetails classes summary, contents => do
pure {{ {{summary}} {{← contents.mapM goB}}}}
| .htmlWrapper name attrs, contents => do
- Html.tag name attrs <$> contents.mapM goB
+ Html.element name attrs <$> contents.mapM goB
| .htmlDiv classes, contents => do
pure {{
{{← contents.mapM goB}}
}}
| .blob html, _ => pure html
@@ -194,7 +195,7 @@ def blockHtml (g : Genre)
let contents := contents.extract 1
return {{
- {{ .tag s!"h{lvl + 1}" #[] (← first.mapM goI) }}
+ {{ .element s!"h{lvl + 1}" #[] (← first.mapM goI) }}
{{ ← contents.mapM goB }}
}}
@@ -353,9 +354,9 @@ def builtinHeader : TemplateM Html := do
-- These should come first so later stylesheets can easily override them.
out := out ++ {{}}
for style in (← read).builtInStyles do
- out := out ++ {{"\n"}}
+ out := out ++ {{"\n"}}
for script in (← read).builtInScripts do
- out := out ++ {{"\n"}}
+ out := out ++ {{"\n"}}
for js in (← read).jsFiles do
out := out ++ {{}}
for css in (← read).cssFiles do
@@ -368,9 +369,9 @@ def builtinHeader : TemplateM Html := do
-- Components
for style in (← get).headerCss do
- out := out ++ {{"\n"}}
+ out := out ++ {{"\n"}}
for script in (← get).headerJs do
- out := out ++ {{"\n"}}
+ out := out ++ {{"\n"}}
pure out
diff --git a/src/verso-blog/VersoBlog/Theme.lean b/src/verso-blog/VersoBlog/Theme.lean
index c99c7ffc4..6f433fe59 100644
--- a/src/verso-blog/VersoBlog/Theme.lean
+++ b/src/verso-blog/VersoBlog/Theme.lean
@@ -11,6 +11,7 @@ public section
open Verso.Genre.Blog Template
open Verso Doc Output Html
+open Lean (Html)
namespace Verso.Genre.Blog
@@ -307,7 +308,7 @@ def post : Template := do
| some md => {{
}}
usePackages := ["\\usepackage{svg}"]
diff --git a/src/verso-manual/VersoManual/Docstring.lean b/src/verso-manual/VersoManual/Docstring.lean
index 153f6ab6b..f2e06e587 100644
--- a/src/verso-manual/VersoManual/Docstring.lean
+++ b/src/verso-manual/VersoManual/Docstring.lean
@@ -1621,7 +1621,7 @@ def optionDocs.descr : BlockDescr := withHighlighting {
open Verso.Output Html in do
let .ok (name, defaultValue) := FromJson.fromJson? (α := Name × Highlighted) info
| do reportError "Failed to deserialize docstring data while generating HTML for an option"; pure .empty
- let x : Html := Html.text true <| Name.toString name
+ let x : Html := Html.text <| Name.toString name
let xref ← HtmlT.state
let idAttr := xref.htmlId id
diff --git a/src/verso-manual/VersoManual/Glossary.lean b/src/verso-manual/VersoManual/Glossary.lean
index 723035fe6..b8c7778ca 100644
--- a/src/verso-manual/VersoManual/Glossary.lean
+++ b/src/verso-manual/VersoManual/Glossary.lean
@@ -18,7 +18,7 @@ public import Verso.Doc.Elab.Monad
open Verso Genre Manual ArgParse
open Verso.Doc.Elab
open Verso.Multi (AllRemotes)
-open Lean (Json ToJson FromJson)
+open Lean (Json ToJson FromJson Html)
namespace Verso.Genre.Manual
diff --git a/src/verso-manual/VersoManual/Html.lean b/src/verso-manual/VersoManual/Html.lean
index 492ffdc85..ad8320697 100644
--- a/src/verso-manual/VersoManual/Html.lean
+++ b/src/verso-manual/VersoManual/Html.lean
@@ -16,6 +16,7 @@ import VersoManual.Html.Style
namespace Verso.Genre.Manual.Html
open Std (HashSet)
open Verso.Output Html Multi
+open Lean (Html)
public structure Toc.Meta where
title : Html
@@ -263,9 +264,9 @@ where
safeTags := ["code", "span", "a"]
getHtmlTitle : Html → Option String
- | .text _e s => some s
+ | .text s | .raw s => some s
| .seq es => (String.join ∘ (·.toList)) <$> es.mapM getHtmlTitle
- | .tag t _ e =>
+ | .element t _ e =>
if t ∈ safeTags then
getHtmlTitle e
else none
@@ -372,7 +373,7 @@ where
linkify (path : Path) (id : Option String) (html : Html) :=
match html with
- | .tag "a" _ _ => html
+ | .element "a" _ _ => html
| other => {{{{other}}}}
sectionNum num :=
match num with
@@ -456,8 +457,8 @@ public def page
{{extraJsFiles.map fun f => ({{}})}}
{{extraStylesheets.map (fun url => {{ }})}}
- {{extraCss.toArray.map ({{}})}}
- {{extraJs.toArray.map ({{}})}}
+ {{extraCss.toArray.map ({{}})}}
+ {{extraJs.toArray.map ({{}})}}
{{extraHead}}
@@ -518,7 +519,7 @@ public def page
public def relativize (path : Path) (html : Html) : Html :=
- html.visitM (m := ReaderT Path Id) (tag := rwTag) |>.run path
+ html.visitM (m := ReaderT Path Id) (element := rwTag) |>.run path
where
urlAttr (name : String) : Bool := name ∈ ["href", "src", "data", "poster"]
rwAttr (attr : String × String) : ReaderT Path Id (String × String) := do
@@ -534,4 +535,4 @@ where
-- Don't rewrite URLs that come from remote content. This attribute is inserted by the `ref`
-- role when referring to remote content.
if attrs.any (·.1 == "data-verso-remote") then return none
- return some <| .tag tag (← attrs.mapM rwAttr) content
+ return some <| .element tag (← attrs.mapM rwAttr) content
diff --git a/src/verso-manual/VersoManual/Html/Config.lean b/src/verso-manual/VersoManual/Html/Config.lean
index 128d83014..bef139280 100644
--- a/src/verso-manual/VersoManual/Html/Config.lean
+++ b/src/verso-manual/VersoManual/Html/Config.lean
@@ -5,7 +5,7 @@ Author: David Thrane Christiansen
-/
module
-public import Verso.Output.Html
+public import Lean.Data.Html
import Verso.BEq
public import Lean.Data.Json.FromToJson
import VersoUtil.BinFiles.Z85
@@ -20,9 +20,9 @@ public structure HtmlConfig extends HtmlAssets where
htmlDepth := 2
extraFilesHtml : List (System.FilePath × String) := []
/-- Extra elements to add to every page's `head` tag -/
- extraHead : Array Output.Html := #[]
+ extraHead : Array Html := #[]
/-- Extra elements to add to every page's contents -/
- extraContents : Array Output.Html := #[]
+ extraContents : Array Html := #[]
/-- The URL from which to draw the logo to show, if any -/
logo : Option String := none
/-- The URL that the logo should link to, if any (default is site root) -/
diff --git a/src/verso-manual/VersoManual/Html/SoftHyphenate.lean b/src/verso-manual/VersoManual/Html/SoftHyphenate.lean
index 3cd526847..b45ce36f4 100644
--- a/src/verso-manual/VersoManual/Html/SoftHyphenate.lean
+++ b/src/verso-manual/VersoManual/Html/SoftHyphenate.lean
@@ -12,11 +12,12 @@ set_option doc.verso true
namespace Verso.Genre.Manual
open Verso.Output Html
+open Lean (Html)
private def addShy (xs : Array Html) : Array Html :=
if xs.isEmpty then xs
- else if let some (Verso.Output.Html.tag "wbr" ..) := xs.back? then xs
- else xs.push (.text false "")
+ else if let some (.element "wbr" ..) := xs.back? then xs
+ else xs.push (.raw "")
/--
Adds soft hyphenation opportunities ({lit}`` or {lit}``) to a single text node, allowing
@@ -36,7 +37,7 @@ public def softHyphenateText (esc : Bool) (str : String) : Html := Id.run do
let current := iter.get h
let iter' := iter.next h
if prior == some '.' && current != '.' then
- strs := strs.push (.text esc <| str.extract start iter)
+ strs := strs.push (.ofString esc <| str.extract start iter)
-- Break lines after dots without hyphens
strs := strs.push {{}}
start := iter
@@ -45,7 +46,7 @@ public def softHyphenateText (esc : Bool) (str : String) : Html := Id.run do
if !strs.isEmpty then
strs := addShy strs
-- Break lines at case changes with hyphens
- strs := strs.push (.text esc <| str.extract start iter)
+ strs := strs.push (.ofString esc <| str.extract start iter)
start := iter
prior := some current
@@ -53,7 +54,7 @@ public def softHyphenateText (esc : Bool) (str : String) : Html := Id.run do
if start != iter then
strs := addShy strs
- strs := strs.push (.text esc <| str.extract start iter)
+ strs := strs.push (.ofString esc <| str.extract start iter)
if h : strs.size = 1 then strs[0] else .seq strs
@@ -65,7 +66,7 @@ HTML, allowing browsers to break the word at that point. Line break opportunitie
{lit}`Verso.Genre.Manual.softHyphenateIdentifiers`.
-/
public def softHyphenateTextNodes (html : Html) : Html :=
- html.visitM (m := Id) (text := rwText)
+ html.visitM (m := Id) (text := rwText true) (raw := rwText false)
where
rwText esc str := pure (some (softHyphenateText esc str))
@@ -79,8 +80,8 @@ hyphenation opportunities on transitions from lower-case to upper-case letters,
Here, “identifiers” refers to text nodes found within `` tags.
-/
public partial def softHyphenateIdentifiers (html : Html) : Html :=
- html.visitM (m := Id) (tag := rwTag)
+ html.visitM (m := Id) (element := rwTag)
where
rwTag
- | "code", attrs, content => pure (some (.tag "code" attrs (softHyphenateTextNodes content)))
+ | "code", attrs, content => pure (some (.element "code" attrs (softHyphenateTextNodes content)))
| _, _, _ => pure none
diff --git a/src/verso-manual/VersoManual/Index.lean b/src/verso-manual/VersoManual/Index.lean
index e0e2b7dbc..0087b2a5a 100644
--- a/src/verso-manual/VersoManual/Index.lean
+++ b/src/verso-manual/VersoManual/Index.lean
@@ -20,7 +20,7 @@ open Verso Genre Manual
open Verso.Multi
open Verso.Doc.Elab
open Verso.ArgParse
-open Lean (ToJson FromJson quote)
+open Lean (ToJson FromJson quote Html)
open Std (HashMap HashSet)
namespace Verso.Genre.Manual.Index
@@ -324,7 +324,7 @@ instance : Hashable IndexCat where
| .letter c => mixHash 7 (hash c.toNat)
open Output.Html in
-def IndexCat.header : IndexCat → Output.Html
+def IndexCat.header : IndexCat → Html
| .symbolic => "Symbols"
| .digit => "0–9"
| .letter c => c.toUpper.toString
@@ -447,7 +447,7 @@ def theIndex.descr : BlockDescr where
let r := v.render
let out ← r.mapM fun (cat, entries) => do
let h := (← read).1.headerLevel + 1
- let hdr := Output.Html.tag s!"h{h}" #[("id", s!"---index-hdr-{cat.id}")] (cat.header)
+ let hdr := Html.element s!"h{h}" #[("id", s!"---index-hdr-{cat.id}")] (cat.header)
let entries' ← entries.mapM fun e => do
return softHyphenateIdentifiers {{
{{← e.toHtml goI}}
}}
return {{
{{hdr ++ {{{{entries'}}}} }}
}}
diff --git a/src/verso-manual/VersoManual/License.lean b/src/verso-manual/VersoManual/License.lean
index 41460ad56..5d8f6e89d 100644
--- a/src/verso-manual/VersoManual/License.lean
+++ b/src/verso-manual/VersoManual/License.lean
@@ -15,7 +15,7 @@ import VersoManual.Basic
-open Lean (ToJson FromJson)
+open Lean (ToJson FromJson Html)
open Verso ArgParse Doc Elab
@@ -45,7 +45,7 @@ private def paragraphedHtml (text : String) : Html :=
def LicenseInfo.toHtml (license : LicenseInfo) (headerLevel : Nat) : Html :=
let {identifier, dependency, howUsed, link, text} := license
{{
- {{.tag s!"h{headerLevel}" #[] dependency }}
+ {{.element s!"h{headerLevel}" #[] dependency }}
{{link.map (fun url => {{{{url}}}}) |>.getD .empty}}
{{howUsed.map paragraphedHtml |>.getD .empty}}
{{identifier}}
@@ -56,7 +56,7 @@ where
| (hdr?, txt) =>
let hdrHtml :=
if let some hdr := hdr? then
- Html.tag s!"h{headerLevel+1}" #[] hdr
+ Html.element s!"h{headerLevel+1}" #[] hdr
else
.empty
{{{{hdrHtml}}{{paragraphedHtml txt}}}}
diff --git a/src/verso-manual/VersoManual/Literate.lean b/src/verso-manual/VersoManual/Literate.lean
index 9fd8c6e0a..aa3459664 100644
--- a/src/verso-manual/VersoManual/Literate.lean
+++ b/src/verso-manual/VersoManual/Literate.lean
@@ -48,7 +48,7 @@ block_extension Block.literateDocstringPart (level : Nat) where
let contents := contents.extract 1
pure {{
- {{.tag s!"h{level + 1}" #[] title}}
+ {{.element s!"h{level + 1}" #[] title}}
{{← contents.mapM goB}}
}}
diff --git a/src/verso-manual/VersoManual/LocalContents.lean b/src/verso-manual/VersoManual/LocalContents.lean
index 23c84aefa..c03eba684 100644
--- a/src/verso-manual/VersoManual/LocalContents.lean
+++ b/src/verso-manual/VersoManual/LocalContents.lean
@@ -236,7 +236,7 @@ partial def localContentsCore [Monad m] [MonadLiftT IO m] [ToHtml Manual m (Doc.
let shortTitle := p.metadata.bind (·.shortTitle)
let titleHtml ←
if let some title := shortTitle then
- pure (Html.ofString title)
+ pure (Html.text title)
else
let (html, _) ← p.title.mapM (Manual.toHtml (m := m) opts ctxt xref {} {} {} ·) |>.run {}
pure html
diff --git a/src/verso-manual/VersoManual/Row.lean b/src/verso-manual/VersoManual/Row.lean
index b46a38f75..175c7db28 100644
--- a/src/verso-manual/VersoManual/Row.lean
+++ b/src/verso-manual/VersoManual/Row.lean
@@ -15,7 +15,7 @@ public section
open Lean Elab
open Verso ArgParse Doc Elab Genre.Manual Html
open Verso.Doc.Html (HtmlT)
-open Verso.Output (Html)
+open Verso.Output
namespace Verso.Genre.Manual
diff --git a/src/verso-manual/VersoManual/Table.lean b/src/verso-manual/VersoManual/Table.lean
index 18f779df3..c63cb870c 100644
--- a/src/verso-manual/VersoManual/Table.lean
+++ b/src/verso-manual/VersoManual/Table.lean
@@ -117,8 +117,8 @@ block_extension Block.table (columns : Nat) (header : Bool) (tag : Option String
return {{
{{← rows.mapIdxM fun i r => do
- let cols ← Output.Html.seq <$> r.mapM fun c => do
- let cell : Output.Html ← c.mapM goB
+ let cols ← Html.seq <$> r.mapM fun c => do
+ let cell : Html ← c.mapM goB
if header && i == 0 then
pure {{
{{cell}}
}}
else
diff --git a/src/verso-search/VersoSearch/DomainSearch.lean b/src/verso-search/VersoSearch/DomainSearch.lean
index e8222be8b..52a2f9565 100644
--- a/src/verso-search/VersoSearch/DomainSearch.lean
+++ b/src/verso-search/VersoSearch/DomainSearch.lean
@@ -284,7 +284,7 @@ by every genre at once.
emitted search assets. It is spliced into every {lit}`src`/{lit}`href`, with a trailing
slash added automatically if missing.
-/
-public def searchAssetTags (searchDir : String := "-verso-search") : Verso.Output.Html :=
+public def searchAssetTags (searchDir : String := "-verso-search") : Html :=
open Verso.Output.Html in
let d := if searchDir.endsWith "/" then searchDir else searchDir ++ "/"
-- Deferring the four scripts keeps them off the render-blocking path. `search-init.js` below is a
diff --git a/src/verso/Verso/Code/Highlighted.lean b/src/verso/Verso/Code/Highlighted.lean
index d7f300902..b12f426d3 100644
--- a/src/verso/Verso/Code/Highlighted.lean
+++ b/src/verso/Verso/Code/Highlighted.lean
@@ -17,7 +17,7 @@ import VersoUtil.WfRec
open SubVerso.Highlighting
open Verso.Output Html
-open Lean (Json ToJson FromJson Quote)
+open Lean (Json ToJson FromJson Quote Html)
open Std (HashMap)
namespace SubVerso.Highlighting
@@ -503,11 +503,11 @@ defmethod Token.htmlContent (tok : Token) : HighlightHtmlM g Html := do
iter := iter.next h
str := str.push c
if c == '.' then
- html := html ++ .text true str
+ html := html ++ .text str
str := ""
if iter ≠ content.endPos then
- html := html ++ .text false ""
- if !str.isEmpty then html := html ++ .text true str
+ html := html ++ .raw ""
+ if !str.isEmpty then html := html ++ .text str
return html
else
return content
@@ -606,9 +606,9 @@ where
/-- HTML that renders no visible content. -/
partial def isEmptyHtml : Html → Bool
- | .text _ s => s.isEmpty
+ | .text s | .raw s => s.isEmpty
| .seq xs => xs.all isEmptyHtml
- | .tag .. => false
+ | .element .. => false
/--
Removes the attributes named in `attrs` from `html`, returning their values alongside the
@@ -620,11 +620,11 @@ partial def takeAttrs (attrs : Array String) (html : Html) : Array (String × St
go attrs html
where
go (remaining : Array String) : Html → Array (String × String) × Html
- | html@(.tag name as contents) =>
+ | html@(.element name as contents) =>
let here := as.filter (remaining.contains ·.1)
let (found, contents') := go (remaining.filter (fun r => !here.any (·.1 == r))) contents
if here.isEmpty && found.isEmpty then (#[], html)
- else (here ++ found, .tag name (as.filter (!remaining.contains ·.1)) contents')
+ else (here ++ found, .element name (as.filter (!remaining.contains ·.1)) contents')
| html@(.seq xs) =>
let trimmed := xs.popWhile isEmptyHtml
let trimmed := trimmed.extract (trimmed.findIdx (!isEmptyHtml ·)) trimmed.size
@@ -665,7 +665,7 @@ public partial defmethod Highlighted.toHtml : Highlighted → HighlightHtmlM g H
pure {{
- {{← infos.mapM fun (s, info) => do return {{
+ {{← infos.mapM fun (s, info) => do return {{
{{← info.toHtml [] 10 toHtml}} }}
}}
@@ -690,7 +690,7 @@ public partial defmethod Highlighted.toHtml : Highlighted → HighlightHtmlM g H
{{← if info.isEmpty then
pure {{"All goals completed! 🐙"}}
else
- .seq <$> info.mapIdxM (fun i x => x.toHtml toHtml i)}}
+ info.mapIdxM (fun i x => x.toHtml toHtml i)}}
}}
diff --git a/src/verso/Verso/Doc/Html.lean b/src/verso/Verso/Doc/Html.lean
index 0d7c01167..35640379a 100644
--- a/src/verso/Verso/Doc/Html.lean
+++ b/src/verso/Verso/Doc/Html.lean
@@ -13,6 +13,7 @@ public import Verso.BuildLog
namespace Verso.Doc.Html
open Verso Output Doc Html
+open Lean (Html)
open Verso (Severity SourceSpan MonadBuildLog Logger)
open Verso.Code (HighlightHtmlM)
@@ -86,7 +87,7 @@ public instance [Monad m] : MonadLift (HighlightHtmlM genre) (HtmlT genre m) whe
open HtmlT
public def mkPartHeader (level : Nat) (contents : Html) (headerAttrs : Array (String × String) := #[]) : Html :=
- .tag s!"h{level}" headerAttrs contents
+ .element s!"h{level}" headerAttrs contents
public class ToHtml (genre : Genre) (m : Type → Type) (α : Type u) where
toHtml (val : α) : HtmlT genre m Html
@@ -118,19 +119,19 @@ section
open ToHtml
partial def Inline.toHtml [Monad m] [GenreHtml g m] : Inline g → HtmlT g m Html
- | .text str => pure <| .text true str
+ | .text str => return .text str
| .link content dest => do
pure {{ {{← content.mapM toHtml}} }}
| .image alt dest => do
pure {{ }}
| .footnote name content => do
pure {{ "["{{name}}"]"{{← content.mapM toHtml}}}}
- | .linebreak str => pure <| Html.text false str
+ | .linebreak str => return .raw str
| .emph content => do
pure {{ {{← content.mapM toHtml }} }}
| .bold content => do
pure {{ {{← content.mapM toHtml}} }}
- | .code str => pure {{ {{str}} }}
+ | .code str => return {{ {{str}} }}
| .math mode str => do
let classes := "math " ++ match mode with | .inline => "inline" | .display => "display"
pure {{ {{str}} }}
@@ -162,7 +163,7 @@ partial def Block.toHtml [Monad m] [GenreHtml g m] [TraverseBlock g] (b : Block
}}
}}
- | .code content => pure #[{{
{{ content }}
}}]
+ | .code content => return {{
{{ content }}
}}
| .concat items => Html.seq <$> items.mapM Block.toHtml
| .other container content => GenreHtml.block Inline.toHtml Block.toHtml container content
diff --git a/src/verso/Verso/Output/Html.lean b/src/verso/Verso/Output/Html.lean
index 2ddf8d49a..61272bc43 100644
--- a/src/verso/Verso/Output/Html.lean
+++ b/src/verso/Verso/Output/Html.lean
@@ -12,6 +12,7 @@ public import Lean.PrettyPrinter.Parenthesizer
public import Lean.Elab.Term.TermElabM
meta import Lean.Elab.Term.TermElabM
public meta import Lean.Meta.Hint
+public import Lean.Data.Html
import Verso.Output.Html.Entities
public import Verso.Output.Html.AttributeName
@@ -21,101 +22,9 @@ public meta import Verso.Output.Html.Comments
public meta import Verso.Output.Html.Tags
import Verso.Output.Html.Tags
-namespace Verso.Output
+/-! ## Additions to the Lean namespace -/
-open Lean
-
-/--
-A representation of HTML, used to render Verso to the web.
--/
-public inductive Html where
- /--
- Textual content. If `escape` is `true`, then characters such as `'&'` are escaped to entities such
- as `"&"` during rendering.
- -/
- | text (escape : Bool) (string : String)
- /--
- A tag with the given name and attributes.
- -/
- | tag (name : String) (attrs : Array (String × String)) (contents : Html)
- /--
- A sequence of HTML values.
- -/
- | seq (contents : Array Html)
-deriving Repr, Inhabited, TypeName, BEq, Hashable
-
-public instance : ToJson Html where
- toJson := private to
-where
- to
- | .text true string => .str string
- | .text false string => json%{"raw": $string}
- | .tag name attrs contents =>
- let attrs : Json := .arr <| attrs.map fun (x, y) => json%{"name": $x, "value": $y}
- json%{"tag": $name, "attrs": $attrs, "content": $(to contents)}
- | .seq xs => .arr <| xs.map to
-
-public partial instance : FromJson Html where
- fromJson? := private from?
-where
- from?
- | .str s => pure <| .text true s
- | .arr xs => .seq <$> xs.mapM from?
- | json@(.obj o) => do
- if let some name := o["tag"]? then
- let .str name := name
- | throw s!"Expected a string as a tag name, got: {name.compress}"
- let attrs ← json.getObjValAs? (Array Json) "attrs"
- let attrs ← attrs.mapM fun a => do
- return (← a.getObjValAs? String "name", ← a.getObjValAs? String "value")
- let content ← json.getObjVal? "content" >>= from?
- return .tag name attrs content
- else if let some string := o["raw"]? then
- let .str string := string
- | throw s!"Expected a string for raw content, got: {string.compress}"
- return .text false string
- else
- throw <|
- s!"Failed to deserialize {json.compress} as HTML. " ++
- "Expected key \"tag\" or key \"raw\"."
- | other => throw s!"Failed to deserialize {other.compress} as HTML"
-
-
-open Syntax in
-public partial instance : Quote Html where
- quote := q
-where
- quoteArray {α : _} (_inst : Quote α) (xs : Array α) : TSyntax `term :=
- mkCApp ``List.toArray #[quote xs.toList]
- q
- | .text esc str =>
- mkCApp ``Html.text #[quote esc, quote str]
- | .tag name attrs contents =>
- mkCApp ``Html.tag #[quote name, quote attrs, q contents]
- | .seq contents =>
- mkCApp ``Html.seq #[quoteArray ⟨q⟩ contents]
-
-/--
-The empty HTML document.
--/
-@[suggest_for Verso.Output.Html.nil Verso.Output.Html.none]
-public def Html.empty : Html := .seq #[]
-
-/--
-Converts a string to HTML, escaping special characters.
--/
-public def Html.ofString : String → Html := .text true
-
-/--
-Appends two HTML documents.
--/
-public def Html.append : Html → Html → Html
- | .seq xs, .seq ys => .seq (xs ++ ys)
- | .seq xs, other => .seq (xs.push other)
- | other, .seq ys => .seq (#[other] ++ ys)
- | x, y => .seq #[x, y]
-
-public instance : Append Html := ⟨Html.append⟩
+namespace Lean.Html
/--
If the HTML consists of a single tag, then the given attribute is set to the provided value. If the
@@ -123,15 +32,15 @@ attribute already exists, then its value is replaced.
If the HTML is not a single tag, no changes are made.
-/
-public def Html.setAttribute (attr : String) (value : String) (html : Html) : Html :=
+public def setAttribute (attr : String) (value : String) (html : Html) : Html :=
match html with
- | .tag name attrs children =>
+ | .element name attrs children =>
let attrs :=
if let some i := attrs.findFinIdx? (·.1 == attr) then
attrs.set i (attr, value)
else
attrs.push (attr, value)
- .tag name attrs children
+ .element name attrs children
| _ => html
/--
@@ -140,52 +49,11 @@ attribute already exists, then its value is replaced.
Panics if the HTML is not a single tag.
-/
-public def Html.setAttribute! (attr : String) (value : String) (html : Html) : Html :=
+public def setAttribute! (attr : String) (value : String) (html : Html) : Html :=
match html with
- | .tag .. => html.setAttribute attr value
+ | .element .. => html.setAttribute attr value
| other => panic! s!"Not a single HTML node: {repr other}"
-
-/--
-Converts an array of HTML elements into a single element by appending them.
-
-This is equivalent to using `Html.seq`, but may result a more compact representation.
--/
-public def Html.fromArray (htmls : Array Html) : Html :=
- .seq <| htmls.foldl glue .empty
-where
- glue
- | arr, .seq hs => arr.append hs
- | arr, other => arr.push other
-
-/--
-Converts a list of HTML elements into a single element by appending them.
-
-This is equivalent to using `Html.seq` on the corresponding array, but may result in a more compact representation.
--/
-public def Html.fromList (htmls : List Html) : Html := Id.run do
- let mut out := Html.empty
- for elt in htmls do
- out := out ++ elt
- out
-
-public instance : Coe (Array Html) Html where
- coe arr := Html.fromArray arr
-
-public instance : Coe (List Html) Html where
- coe arr := Html.fromList arr
-
-private def revFrom (i : Nat) (input : Array α) (output : Array α := #[]) : Array α :=
- if h : i < input.size then
- revFrom (i+1) input (output.push input[i])
- else output
-termination_by input.size - i
-
-namespace Html
-
-/-- The default `DOCTYPE` for HTML5. -/
-public abbrev doctype := ""
-
/--
Wrap content in a named group whose visible label should not participate in the document heading
outline.
@@ -202,31 +70,58 @@ public def labeledGroup
let labelAttrs :=
(if labelClass.isEmpty then #[] else #[("class", labelClass)]) ++
#[("id", id)]
- .tag "div" groupAttrs <|
+ .element "div" groupAttrs <|
.seq #[
- .tag "p" labelAttrs (.text true label),
+ .element "p" labelAttrs (.text label),
contents
]
+open Verso.Output.Html (mustClose newlineAfter) in
/--
-Visit the entire tree, applying rewrites in some monad. Return `none` to signal that no rewrites are
-to be performed.
+Converts HTML into a string that's suitable for sending to browsers, but is also readable.
-/
-public partial def visitM [Monad m]
- (text : (escape : Bool) → String → m (Option Html) := (fun _ _ => pure none))
- (tag : (name : String) → (attrs : Array (String × String)) → (contents : Html) → m (Option Html) := fun _ _ _ => pure none)
- (seq : Array Html → m (Option Html) := fun _ => pure none)
- (html : Html) : m Html :=
+public partial def asString (html : Html) (indent : Nat := 0) (breakLines := true) : String :=
match html with
- | .text esc str => do pure <| (← text esc str).getD html
- | .tag name attrs contents => do
- let contents' ← contents.visitM (text := text) (tag := tag) (seq := seq)
- pure <| (← tag name attrs contents').getD (.tag name attrs contents')
- | .seq elts => do
- let elts' ← elts.mapM (visitM (text := text) (tag := tag) (seq := seq))
- pure <| (← seq elts').getD (.seq elts')
+ | .raw str => str
+ | .text str => str.replace "&" "&" |>.replace "<" "<" |>.replace ">" ">"
+ | .element "pre" attrs body =>
+ "