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: first working version for DocumenterCitations #139

Merged
merged 9 commits into from
May 19, 2024
Merged
11 changes: 9 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,16 @@ NodeJS_20_jll = "c7aee132-11e1-519c-8219-0a43005e73c2"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[compat]
julia = "1.6"
ANSIColoredPrinters = "0.0.1"
Documenter = "1"
DocStringExtensions = "0.9"
Documenter = "1"
DocumenterCitations = "1"
IOCapture = "0.2"
NodeJS_20_jll = "20"
julia = "1.6"

[weakdeps]
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"

[extensions]
DocumenterVitepressDocumenterCitationsExt = "DocumenterCitations"
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365"
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
32 changes: 29 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
using Documenter
using DocumenterVitepress
using DocumenterCitations

# Handle DocumenterCitations integration - if you're running this, then you don't need anything here!!
documenter_citations_dir = dirname(dirname(pathof(DocumenterCitations)))
documenter_citations_docs_dir = joinpath(documenter_citations_dir, "docs")
# Copy over the DocumenterCitations docs
cp(joinpath(documenter_citations_docs_dir, "src", "refs.bib"), joinpath(@__DIR__, "src", "refs.bib"))
if !occursin("Gallery", read(joinpath(@__DIR__, "src", "citations.md"), String))
open(joinpath(@__DIR__, "src", "citations.md"); append = true, write = true) do io
write(io, read(joinpath(documenter_citations_docs_dir, "src", "gallery.md"), String))
end
end
include(joinpath(documenter_citations_docs_dir, "custom_styles", "enumauthoryear.jl"))
include(joinpath(documenter_citations_docs_dir, "custom_styles", "keylabels.jl"))
# End DocumenterCitation integration code. Below is what you need to actually run DC.


bib = CitationBibliography(
joinpath(@__DIR__, "src", "refs.bib");
style=:numeric # default
)


makedocs(;
sitename = "DocumenterVitepress",
Expand All @@ -22,12 +44,16 @@ makedocs(;
"Code" => "code_example.md",
"Markdown" => "markdown-examples.md",
"MIME output" => "mime_examples.md",
"Updating to DocumenterVitepress" => "documenter_to_vitepress_docs_example.md"
"Updating to DocumenterVitepress" => "documenter_to_vitepress_docs_example.md",
"DocumenterCitations integration" => "citations.md",

],
"For Developers" => "render_pipeline.md",
"Developers' documentation" => [
"render_pipeline.md"
],
"api.md",
]
],
plugins = [bib,],
)


Expand Down
197 changes: 197 additions & 0 deletions docs/src/citations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# DocumenterCitations.jl integration

This page shows the DocumenterCitations.jl integration and what it looks like. You can use DocumenterCitations in DocumenterVitepress in the same way that you use them in Documenter!

This page's source was taken from the DocumenterCitations docs and rendered via DocumenterVitepress.

# [Citation Style Gallery](@id gallery)

The citation style is determined when instantiating the `CitationBibliography`, via the `style` argument.

The built-in styles are:

* `style=:numeric` (default): [numeric style](@ref numeric_style)
* `style=:authoryear`: [author-year style](@ref author_year_style)
* `style=:alpha`: [alphabetic style](@ref alphabetic_style)

## [Numeric style](@id numeric_style)

This is the default style (`style=:numeric`) used throughout the other pages of this documentation, cf. the Syntax examples.

* `[GoerzQ2022](@cite)` renders as "[GoerzQ2022](@cite)"
* `[FuerstNJP2014,SolaAAMOP2018](@cite)` renders as "[FuerstNJP2014,SolaAAMOP2018](@cite)"
* `[GoerzQ2022](@citet)` renders as "[GoerzQ2022](@citet)"
* `[GoerzQ2022](@citep)` renders as "[GoerzQ2022](@citep)" — `@citep` is the same as `@cite` for this style
* `[GoerzQ2022; Eq. (1)](@cite)` renders as "[GoerzQ2022; Eq. (1)](@cite)"
* `[GoerzQ2022; Eq. (1)](@citet)` renders as "[GoerzQ2022; Eq. (1)](@citet)"
* `[GoerzQ2022](@citet*)` renders as "[GoerzQ2022](@citet*)"
* `[GoerzQ2022; Eq. (1)](@citet*)` renders as "[GoerzQ2022; Eq. (1)](@citet*)"
* `[WinckelIP2008](@citet)` renders as "[WinckelIP2008](@citet)"
* `[WinckelIP2008](@Citet)` renders as "[WinckelIP2008](@Citet)"
* `[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@cite)` renders as "[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@cite)"
* `[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@Citet)` renders as "[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@Citet)"
* `[arbitrary text](@cite GoerzQ2022)` renders as "[arbitrary text](@cite GoerzQ2022)"

**References:**

```@bibliography
Pages = [@__FILE__]
Style = :numeric
Canonical = false
```

## [Author-year style](@id author_year_style)

The author-year style (`style=:authoryear`) formats citations with the author name and publication year. This is the citation style used, e.g., in [Rev. Mod. Phys.](https://journals.aps.org/rmp/) (`rmp` option in [REVTeX](https://www.ctan.org/tex-archive/macros/latex/contrib/revtex/auguide)). The bibliography is sorted alphabetically by author name. The default `@cite` command is parenthetical (`@cite` and `@citep` are equivalent) which is different from the `authoryear` style in [natbib](https://mirrors.rit.edu/CTAN/macros/latex/contrib/natbib/natnotes.pdf).

* `[GoerzQ2022](@cite)` renders as "[GoerzQ2022](@cite%authoryear%)"
* `[FuerstNJP2014,SolaAAMOP2018](@cite)` renders as "[FuerstNJP2014,SolaAAMOP2018](@cite%authoryear%)"
* `[GoerzQ2022](@citet)` renders as "[GoerzQ2022](@citet%authoryear%)"
* `[GoerzQ2022](@citep)` renders as "[GoerzQ2022](@citep%authoryear%)" — `@citep` is the same as `@cite` for this style
* `[GoerzQ2022; Eq. (1)](@cite)` renders as "[GoerzQ2022; Eq. (1)](@cite%authoryear%)"
* `[GoerzQ2022; Eq. (1)](@citet)` renders as "[GoerzQ2022; Eq. (1)](@citet%authoryear%)"
* `[GoerzQ2022](@cite*)` renders as "[GoerzQ2022](@cite*%authoryear%)"
* `[GoerzQ2022](@citet*)` renders as "[GoerzQ2022](@citet*%authoryear%)"
* `[GoerzQ2022; Eq. (1)](@cite*)` renders as "[GoerzQ2022; Eq. (1)](@cite*%authoryear%)"
* `[GoerzQ2022; Eq. (1)](@citet*)` renders as "[GoerzQ2022; Eq. (1)](@citet*%authoryear%)"
* `[WinckelIP2008](@citet)` renders as "[WinckelIP2008](@citet%authoryear%)"
* `[WinckelIP2008](@Citet)` renders as "[WinckelIP2008](@Citet%authoryear%)"
* `[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@cite)` renders as "[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@cite%authoryear%)"
* `[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@Citet)` renders as "[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@Citet%authoryear%)"
* `[arbitrary text](@cite GoerzQ2022)` renders as "[arbitrary text](@cite GoerzQ2022)"

**References:**

```@bibliography
Pages = [@__FILE__]
Style = :authoryear
Canonical = false
```

## [Alphabetic style](@id alphabetic_style)

The `style=:alpha` formats citations and references like `:numeric`, except that it uses labels derived from the author names and publication year and sorts the references alphabetically.

* `[GoerzQ2022](@cite)` renders as "[GoerzQ2022](@cite%alpha%)"
* `[FuerstNJP2014,SolaAAMOP2018](@cite)` renders as "[FuerstNJP2014,SolaAAMOP2018](@cite%alpha%)"
* `[GoerzQ2022](@citet)` renders as "[GoerzQ2022](@citet%alpha%)"
* `[GoerzQ2022](@citep)` renders as "[GoerzQ2022](@citep%alpha%)" — `@citep` is the same as `@cite` for this style
* `[GoerzQ2022; Eq. (1)](@cite)` renders as "[GoerzQ2022; Eq. (1)](@cite%alpha%)"
* `[GoerzQ2022; Eq. (1)](@citet)` renders as "[GoerzQ2022; Eq. (1)](@citet%alpha%)"
* `[GoerzQ2022](@citet*)` renders as "[GoerzQ2022](@citet*%alpha%)"
* `[GoerzQ2022; Eq. (1)](@citet*)` renders as "[GoerzQ2022; Eq. (1)](@citet*%alpha%)"
* `[WinckelIP2008](@citet)` renders as "[WinckelIP2008](@citet%alpha%)"
* `[WinckelIP2008](@Citet)` renders as "[WinckelIP2008](@Citet%alpha%)"
* `[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@cite)` renders as "[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@cite%alpha%)". Note that unlike for `style=:numeric`, the citations are not compressed.
* `[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@Citet)` renders as "[BrumerShapiro2003, BrifNJP2010, Shapiro2012, KochJPCM2016; and references therein](@Citet%alpha%)"
* `[arbitrary text](@cite GoerzQ2022)` renders as "[arbitrary text](@cite GoerzQ2022)"

**References:**

```@bibliography
Pages = [@__FILE__]
Style = :alpha
Canonical = false

SolaAAMOP2018
```

```@raw latex
Compared to the HTML version of the documentation, the hanging indent in the above list of references is too small for the longer labels of the \texttt{:alpha} style. This can be remedied by adjusting the \texttt{dl\_hangindent} and \texttt{dl\_labelwidth} parameters with \hyperlinkref{sec:customizing_latex_output}{\texttt{DocumenterCitations.set\_latex\_options}}.
```

Note that the `:alpha` style is able to automatically disambiguate labels:

```@bibliography
Pages = []
Style = :alpha
Canonical = false

GraceJMO2007
GraceJPB2007
```

This works because the `DocumenterCitations` plugin automatically upgrades `style=:alpha` to the internal

```
DocumenterCitations.AlphaStyle
```


## [Custom styles](@id custom_styles)

In the following, we show two examples for user-defined styles. See the notes on customization on how to generally define a custom style.

### Custom style: enumerated author-year

In this example, the `:authoryear` style is used, but the references are shown in an enumerated list.

~~~@eval
# custom styles are included in docs/make.jl, which is how we get around
# world-age issues.
using Markdown
custom_style = joinpath(@__DIR__, "..", "custom_styles", "enumauthoryear.jl")
if isfile(custom_style)
Markdown.parse("""
```julia
$(read(custom_style, String))
```
""")
end
~~~

The important part of the definition is in the last line, indicating that the References should be shown as an enumeration (ordered list, `<ol>`, in HTML), see below. Meanwhile, citations render exactly as with `style=:authoryear`:

* `[GoerzQ2022](@cite)` renders as "[GoerzQ2022](@cite%enumauthoryear%)"
* `[FuerstNJP2014,SolaAAMOP2018](@cite)` renders as "[FuerstNJP2014,SolaAAMOP2018](@cite%enumauthoryear%)"
* `[WinckelIP2008](@Citet)` renders as "[WinckelIP2008](@Citet%enumauthoryear%)"

**References:**

```@bibliography
Pages = [@__FILE__]
Style = :enumauthoryear
Canonical = false
```

### Custom style: Citation-key labels

In this less trivial example, a style similar to `:alpha` is used, using the citation keys in the `.bib` file as labels. This would be somewhat more appropriate with citation keys that are shorter that the ones used here (keys similar to those automatically generated with the `:alpha` style).

~~~@eval
# custom styles are included in docs/make.jl, which is how we get around
# world-age issues.
using Markdown
custom_style = joinpath(@__DIR__, "..", "custom_styles", "keylabels.jl")
if isfile(custom_style)
Markdown.parse("""
```julia
$(read(custom_style, String))
```
""")
end
~~~

* `[GoerzQ2022](@cite)` renders as "[GoerzQ2022](@cite%keylabels%)"
* `[FuerstNJP2014,SolaAAMOP2018](@cite)` renders as "[FuerstNJP2014,SolaAAMOP2018](@cite%keylabels%)"
* `[GoerzQ2022](@citet)` renders as "[GoerzQ2022](@citet%keylabels%)"
* `[GoerzQ2022](@citep)` renders as "[GoerzQ2022](@citep%keylabels%)" — `@citep` is the same as `@cite` for this style
* `[GoerzQ2022; Eq. (1)](@cite)` renders as "[GoerzQ2022; Eq. (1)](@cite%keylabels%)"
* `[GoerzQ2022; Eq. (1)](@citet)` renders as "[GoerzQ2022; Eq. (1)](@citet%keylabels%)"
* `[GoerzQ2022](@citet*)` renders as "[GoerzQ2022](@citet*%keylabels%)"
* `[GoerzQ2022; Eq. (1)](@citet*)` renders as "[GoerzQ2022; Eq. (1)](@citet*%keylabels%)"
* `[WinckelIP2008](@citet)` renders as "[WinckelIP2008](@citet%keylabels%)"
* `[WinckelIP2008](@Citet)` renders as "[WinckelIP2008](@Citet%keylabels%)"
* `[arbitrary text](@cite GoerzQ2022)` renders as "[arbitrary text](@cite GoerzQ2022)"

**References:**

```@bibliography
Pages = [@__FILE__]
Style = :keylabels
Canonical = false
```

```@raw latex
As with the \texttt{:alpha} style, for \LaTeX{} output, the \texttt{dl\_hangindent} and \texttt{dl\_labelwidth} parameters should be adjusted with \hyperlinkref{sec:customizing_latex_output}{\texttt{DocumenterCitations.set\_latex\_options}} to obtain a more suitable hanging indent that matches the HTML version of this documentation.
```
100 changes: 100 additions & 0 deletions ext/DocumenterVitepressDocumenterCitationsExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
module DocumenterVitepressDocumenterCitationsExt

using DocumenterCitations, DocumenterVitepress

import DocumenterVitepress as DV
using Documenter: MarkdownAST

# TODO:
# - List style (rendered vs unrendered)
# - Loose vs tight lists
# - handle :dl properly, we cannot use Markdown for this, since it cannot be represented
# using pure Markdown. We need to insert HTML directly.
# At the moment, we treat :dl as :ol
Comment on lines +11 to +13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to do that, I think Vitepress accepts pure HTML. I'm just not sure if the Markdown will still be picked up. We'll have to test but that can be done later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

function DV.render(io::IO, mime::MIME"text/plain", node::DV.MarkdownAST.Node, bibliography::DocumenterCitations.BibliographyNode, page, doc; kwargs...)

println(io)
println(io, "***")
println(io, "# Bibliography")
println(io)

# Turn the list into a proper MarkdownAST.node
bibnode = _bibliography_to_list(bibliography)

return DV.render(io, mime, bibnode, bibnode.element, page, doc; kwargs...)
end

function _bibliography_to_list(bib::DocumenterCitations.BibliographyNode)
# Construct a MarkdownAST.Node containing this list
list = MarkdownAST.List(bib.list_style in [:ol, :dl] ? :ordered : :bullet, false)
node = MarkdownAST.Node(list)
for item in bib.items
newitem = MarkdownAST.Node(MarkdownAST.Item())
push!(newitem.children, item.reference)
push!(node.children, newitem)
end
node
end

# Below is the code intended for LaTeXWriter.
#=
function Documenter.LaTeXWriter.latex(
lctx::Documenter.LaTeXWriter.Context,
node::MarkdownAST.Node,
bibliography::BibliographyNode
)

if bibliography.list_style == :ol
texenv = "enumerate"
elseif bibliography.list_style == :ul
if _LATEX_OPTIONS[:ul_as_hanging]
texenv = nothing
else
texenv = "itemize"
end
else
@assert bibliography.list_style == :dl
# We emulate a definition list manually with hangindent and labelwidth
texenv = nothing
end

io = lctx.io

function tex_item(n, item)
if bibliography.list_style == :ul
if _LATEX_OPTIONS[:ul_as_hanging]
print(io, "\\hangindent=$(_LATEX_OPTIONS[:ul_hangindent]) ")
else
print(io, "\\item ")
end
elseif bibliography.list_style == :ol # enumerate
print(io, "\\item ")
else
@assert bibliography.list_style == :dl
print(io, "\\hangindent=$(_LATEX_OPTIONS[:dl_hangindent]) {")
_labelbox(io; width=_LATEX_OPTIONS[:dl_labelwidth]) do
Documenter.LaTeXWriter.latex(lctx, item.label.children)
end
print(io, "}")
end
end

println(io, "{$(_LATEX_OPTIONS[:bib_blockformat])% @bibliography\n")
_wrapblock(io, texenv) do
for (n, item) in enumerate(bibliography.items)
tex_item(n, item)
if !isnothing(item.anchor_key)
id = _hash(item.anchor_key)
print(io, "\\hypertarget{", id, "}{}")
end
Documenter.LaTeXWriter.latex(lctx, item.reference.children)
print(io, "\n\n")
end
end
println(io, "}% end @bibliography")

end

=#

end
3 changes: 3 additions & 0 deletions src/vitepress_config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ function modify_config_file(doc, settings, deploy_decision)

end

function _get_raw_text(element)
end

function pagelist2str(doc, page::String)
# If no name is given, find the first header in the page,
# and use that as the name.
Expand Down
Loading
Loading