Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: automatically track open-source libraries for web frontend #279

Merged
merged 2 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:

- name: Upload docs to artifact storage
if: github.ref != 'refs/heads/main'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: "Verso manual (PDF and HTML)"
path: |
Expand Down
12 changes: 11 additions & 1 deletion doc/UsersGuide/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Documentation can take many forms:
* Tutorials
* Etc

{include UsersGuide.Markup}
{include 0 UsersGuide.Markup}

# Genres
%%%
Expand Down Expand Up @@ -97,3 +97,13 @@ number := false
%%%

{theIndex}


# Dependencies
%%%
number := false
%%%

This document contains the following open-source libraries, or code derived from them:

{licenseInfo}
4 changes: 3 additions & 1 deletion src/verso-manual/VersoManual.lean
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import VersoManual.Html
import VersoManual.Html.Style
import VersoManual.Draft
import VersoManual.Index
import VersoManual.License
import VersoManual.Glossary
import VersoManual.Docstring
import VersoManual.WebAssets
Expand Down Expand Up @@ -120,6 +121,7 @@ structure Config where
extraFiles : List (System.FilePath × String) := []
extraCss : List String := []
extraJs : List String := []
licenseInfo : List LicenseInfo := []
/-- Extra elements to add to every page's `head` tag -/
extraHead : Array Output.Html := #[]
draft : Bool := false
Expand Down Expand Up @@ -170,7 +172,7 @@ where

def traverse (logError : String → IO Unit) (text : Part Manual) (config : Config) : ReaderT ExtensionImpls IO (Part Manual × TraverseState) := do
let topCtxt : Manual.TraverseContext := {logError, draft := config.draft}
let mut state : Manual.TraverseState := {}
let mut state : Manual.TraverseState := {licenseInfo := .ofList config.licenseInfo}
let mut text := text
if config.verbose then
IO.println "Initializing extensions"
Expand Down
21 changes: 17 additions & 4 deletions src/verso-manual/VersoManual/Basic.lean
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/-
Copyright (c) 2024 Lean FRO LLC. All rights reserved.
Copyright (c) 2024-2025 Lean FRO LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: David Thrane Christiansen
-/
Expand All @@ -9,6 +9,7 @@ import Verso.Doc
import Verso.Doc.Html
import Verso.Doc.TeX
import VersoManual.Slug
import VersoManual.LicenseInfo
import Verso.Output.Html
import Verso.Output.TeX

Expand Down Expand Up @@ -292,6 +293,7 @@ structure TraverseState where
extraJs : HashSet String := {}
extraJsFiles : Array (String × String) := #[]
extraCssFiles : Array (String × String) := #[]
licenseInfo : HashSet LicenseInfo := {}
private contents : NameMap Json := {}

def freshId [Monad m] [MonadStateOf TraverseState m] : m InternalId := do
Expand Down Expand Up @@ -347,7 +349,8 @@ instance : BEq TraverseState where
x.contents.all fun k v =>
match y.contents.find? k with
| none => false
| some v' => v == v'
| some v' => v == v' &&
x.licenseInfo == y.licenseInfo

namespace TraverseState

Expand Down Expand Up @@ -386,6 +389,10 @@ def htmlId (state : TraverseState) (id : InternalId) : Array (String × String)
if let some (_, htmlId) := state.externalTags[id]? then
#[("id", htmlId.toString)]
else #[]

/-- Add an open-source license used in the generated HTML/JavaScript -/
def addLicenseInfo (state : TraverseState) (licenseInfo : LicenseInfo) : TraverseState :=
{state with licenseInfo := state.licenseInfo.insert licenseInfo}
end TraverseState


Expand Down Expand Up @@ -539,12 +546,13 @@ structure InlineDescr where
extraJsFiles : List (String × String) := []
extraCss : List String := []
extraCssFiles : List (String × String) := []
licenseInfo : List LicenseInfo := []

toTeX : Option (InlineToTeX Manual (ReaderT ExtensionImpls IO))

deriving TypeName

instance : Inhabited InlineDescr := ⟨⟨id, default, default, default, default, default, default, default⟩⟩
instance : Inhabited InlineDescr := ⟨⟨id, default, default, default, default, default, default, default, default⟩⟩

structure BlockDescr where
init : TraverseState → TraverseState := id
Expand All @@ -556,11 +564,12 @@ structure BlockDescr where
extraJsFiles : List (String × String) := []
extraCss : List String := []
extraCssFiles : List (String × String) := []
licenseInfo : List LicenseInfo := []

toTeX : Option (BlockToTeX Manual (ReaderT ExtensionImpls IO))
deriving TypeName

instance : Inhabited BlockDescr := ⟨⟨id, default, default, default, default, default, default, default⟩⟩
instance : Inhabited BlockDescr := ⟨⟨id, default, default, default, default, default, default, default, default⟩⟩

open Lean in
initialize inlineExtensionExt
Expand Down Expand Up @@ -887,6 +896,8 @@ instance : Traverse Manual TraverseM where
for (name, js) in impl.extraCssFiles do
unless (← get).extraCssFiles.any (·.1 == name) do
modify fun s => {s with extraCssFiles := s.extraCssFiles.push (name, js)}
for licenseInfo in impl.licenseInfo do
modify (·.addLicenseInfo licenseInfo)

impl.traverse id data content
else
Expand All @@ -910,6 +921,8 @@ instance : Traverse Manual TraverseM where
for (name, js) in impl.extraCssFiles do
unless (← get).extraCssFiles.any (·.1 == name) do
modify fun s => {s with extraCssFiles := s.extraCssFiles.push (name, js)}
for licenseInfo in impl.licenseInfo do
modify (·.addLicenseInfo licenseInfo)

impl.traverse id data content
else
Expand Down
43 changes: 17 additions & 26 deletions src/verso-manual/VersoManual/Docstring.lean
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Author: David Thrane Christiansen
import Std.Data.HashSet

import VersoManual.Basic
import VersoManual.HighlightedCode
import VersoManual.Index
import VersoManual.Markdown
import VersoManual.Docstring.Config
Expand Down Expand Up @@ -684,7 +685,7 @@ def constructorSignature.descr : BlockDescr where

open Verso.Genre.Manual.Markdown in
@[block_extension Block.docstring]
def docstring.descr : BlockDescr where
def docstring.descr : BlockDescr := withHighlighting {
init st := st
|>.setDomainTitle docstringDomain "Lean constant reference"
|>.setDomainDescription docstringDomain "Documentation for Lean constants"
Expand Down Expand Up @@ -751,10 +752,8 @@ def docstring.descr : BlockDescr where
</div>
}}
toTeX := some <| fun _goI goB _id _info contents => contents.mapM goB
extraCss := [highlightingStyle, docstringStyle]
extraJs := [highlightingJs]
extraJsFiles := [("popper.js", popper), ("tippy.js", tippy)]
extraCssFiles := [("tippy-border.css", tippy.border.css)]
extraCss := [docstringStyle]
}
where
saveRef
(id : InternalId) (name : Name)
Expand Down Expand Up @@ -783,16 +782,12 @@ def Block.leanFromMarkdown (hls : Highlighted) : Block where


@[inline_extension leanFromMarkdown]
def leanFromMarkdown.inlinedescr : InlineDescr where
def leanFromMarkdown.inlinedescr : InlineDescr := withHighlighting {
traverse _id _data _ := pure none
toTeX :=
some <| fun go _ _ content => do
pure <| .seq <| ← content.mapM fun b => do
pure <| .seq #[← go b, .raw "\n"]
extraCss := [highlightingStyle]
extraJs := [highlightingJs]
extraJsFiles := [("popper.js", popper), ("tippy.js", tippy)]
extraCssFiles := [("tippy-border.css", tippy.border.css)]
toHtml :=
open Verso.Output Html in
open Verso.Doc.Html in
Expand All @@ -803,18 +798,15 @@ def leanFromMarkdown.inlinedescr : InlineDescr where
pure .empty
| .ok (hl : Highlighted) =>
hl.inlineHtml "docstring-examples"
}

@[block_extension leanFromMarkdown]
def leanFromMarkdown.blockdescr : BlockDescr where
def leanFromMarkdown.blockdescr : BlockDescr := withHighlighting {
traverse _id _data _ := pure none
toTeX :=
some <| fun goI goB _ _ content => do
pure <| .seq <| ← content.mapM fun b => do
pure <| .seq #[← goB b, .raw "\n"]
extraCss := [highlightingStyle]
extraJs := [highlightingJs]
extraJsFiles := [("popper.js", popper), ("tippy.js", tippy)]
extraCssFiles := [("tippy-border.css", tippy.border.css)]
toHtml :=
open Verso.Output Html in
open Verso.Doc.Html in
Expand All @@ -825,6 +817,7 @@ def leanFromMarkdown.blockdescr : BlockDescr where
pure .empty
| .ok (hl : Highlighted) =>
hl.blockHtml "docstring-examples"
}

open Lean Elab Term in
def tryElabCodeTermWith (mk : Highlighted → String → DocElabM α) (str : String) (ignoreElabErrors := false) (identOnly := false) : DocElabM α := do
Expand Down Expand Up @@ -1555,7 +1548,7 @@ def tactic : DirectiveExpander
open Verso.Genre.Manual.Markdown in
open Lean Elab Term Parser Tactic Doc in
@[block_extension tactic]
def tactic.descr : BlockDescr where
def tactic.descr : BlockDescr := withHighlighting {
init st := st
|>.setDomainTitle tacticDomain "Tactic Documentation"
|>.setDomainDescription tacticDomain "Detailed descriptions of tactics"
Expand Down Expand Up @@ -1594,9 +1587,8 @@ def tactic.descr : BlockDescr where
</div>
}}
toTeX := some <| fun _goI goB _id _info contents => contents.mapM goB
extraCss := [highlightingStyle, docstringStyle]
extraJs := [highlightingJs]

extraCss := [docstringStyle]
}

def Inline.tactic : Inline where
name := `Verso.Genre.Manual.tacticInline
Expand Down Expand Up @@ -1632,15 +1624,14 @@ where


@[inline_extension tacticInline]
def tacticInline.descr : InlineDescr where
def tacticInline.descr : InlineDescr := withHighlighting {
traverse _ _ _ := do
pure none
toTeX :=
some <| fun go _ _ content => do
pure <| .seq <| ← content.mapM fun b => do
pure <| .seq #[← go b, .raw "\n"]
extraCss := [highlightingStyle, docstringStyle]
extraJs := [highlightingJs]
extraCss := [docstringStyle]
toHtml :=
open Verso.Output.Html Verso.Doc.Html in
some <| fun _ _ data _ => do
Expand All @@ -1650,6 +1641,7 @@ def tacticInline.descr : InlineDescr where
pure .empty
| .ok (hl : Highlighted) =>
hl.inlineHtml "examples"
}

-- TODO implement a system upstream like the one for normal tactics
def Block.conv (name : Name) («show» : String) (docs? : Option String) : Block where
Expand Down Expand Up @@ -1691,7 +1683,7 @@ def conv : DirectiveExpander
open Verso.Genre.Manual.Markdown in
open Lean Elab Term Parser Tactic Doc in
@[block_extension conv]
def conv.descr : BlockDescr where
def conv.descr : BlockDescr := withHighlighting {
init st := st
|>.setDomainTitle convDomain "Conversion Tactics"
|>.setDomainDescription convDomain "Tactics for performing targeted rewriting of subterms"
Expand Down Expand Up @@ -1728,9 +1720,8 @@ def conv.descr : BlockDescr where
</div>
}}
toTeX := some <| fun _goI goB _id _info contents => contents.mapM goB
extraCss := [highlightingStyle, docstringStyle]
extraJs := [highlightingJs]

extraCss := [docstringStyle]
}
/--
A progress tracker that shows how many symbols are documented.

Expand Down
46 changes: 46 additions & 0 deletions src/verso-manual/VersoManual/HighlightedCode.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/-
Copyright (c) 2025 Lean FRO LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: David Thrane Christiansen
-/

import Verso

import VersoManual.Basic
import VersoManual.License

namespace Verso.Genre.Manual

open Verso.Code
open Verso.Code.Highlighted.WebAssets

open Licenses

class CanHighlightCode (α : Type) where
addDependencies : α → α

/--
Add the necessary frontend dependencies for showing Verso-highlighted Lean code
-/
def withHighlighting [CanHighlightCode α] (blockOrInline : α) : α :=
CanHighlightCode.addDependencies blockOrInline

instance : CanHighlightCode BlockDescr where
addDependencies b :=
{b with
extraCss := highlightingStyle :: b.extraCss
extraJs := highlightingJs :: b.extraJs
extraJsFiles := ("popper.js", popper) :: ("tippy.js", tippy) :: b.extraJsFiles
extraCssFiles := ("tippy-border.css", tippy.border.css) :: b.extraCssFiles
licenseInfo := b.licenseInfo |>.insert tippy.js |>.insert popper.js
}

instance : CanHighlightCode InlineDescr where
addDependencies i :=
{i with
extraCss := highlightingStyle :: i.extraCss
extraJs := highlightingJs :: i.extraJs
extraJsFiles := ("popper.js", popper) :: ("tippy.js", tippy) :: i.extraJsFiles
extraCssFiles := ("tippy-border.css", tippy.border.css) :: i.extraCssFiles
licenseInfo := i.licenseInfo |>.insert tippy.js |>.insert popper.js
}
Loading