Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ RegistryInstances = "2792f1a3-b283-48e8-9a74-f99dce5104f3"
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[compat]
Expand Down
3 changes: 3 additions & 0 deletions src/Documenter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ import Unicode
import Pkg
import RegistryInstances
import Git
import TimerOutputs
# Additional imported names
using Test: @testset, @test
using DocStringExtensions: SIGNATURES, EXPORTS
using Base64: base64decode

const TIMER = Ref(TimerOutputs.TimerOutput())

# Version number of Documenter itself
const DOCUMENTER_VERSION = let
project = joinpath(dirname(dirname(pathof(Documenter))), "Project.toml")
Expand Down
164 changes: 85 additions & 79 deletions src/builder_pipeline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,85 +72,87 @@ Selectors.matcher(::Type{T}, doc::Documenter.Document) where {T <: Builder.Docum
Selectors.strict(::Type{T}) where {T <: Builder.DocumentPipeline} = false

function Selectors.runner(::Type{Builder.SetupBuildDirectory}, doc::Documenter.Document)
@info "SetupBuildDirectory: setting up build directory."

# Frequently used fields.
build = doc.user.build
source = doc.user.source
workdir = doc.user.workdir

# The .user.source directory must exist.
isdir(source) || error("source directory '$(abspath(source))' is missing.")

# We create the .user.build directory.
# If .user.clean is set, we first clean the existing directory.
doc.user.clean && isdir(build) && rm(build; recursive = true)
isdir(build) || mkpath(build)

# We'll walk over all the files in the .user.source directory.
# The directory structure is copied over to .user.build. All files, with
# the exception of markdown files (identified by the extension) are copied
# over as well, since they're assumed to be images, data files etc.
# Markdown files, however, get added to the document and also stored into
# `mdpages`, to be used later.
mdpages = String[]
for (root, dirs, files) in walkdir(source)
for dir in dirs
d = normpath(joinpath(build, relpath(root, source), dir))
isdir(d) || mkdir(d)
end
for file in files
src = normpath(joinpath(root, file))
dst = normpath(joinpath(build, relpath(root, source), file))

if workdir == :build
# set working directory to be the same as `build`
wd = normpath(joinpath(build, relpath(root, source)))
elseif workdir isa Symbol
# Maybe allow `:src` and `:root` as well?
throw(ArgumentError("Unrecognized working directory option '$workdir'"))
else
wd = normpath(joinpath(doc.user.root, workdir))
TimerOutputs.@timeit Documenter.TIMER[] "SetupBuildDirectory" begin
@info "SetupBuildDirectory: setting up build directory."

# Frequently used fields.
build = doc.user.build
source = doc.user.source
workdir = doc.user.workdir

# The .user.source directory must exist.
isdir(source) || error("source directory '$(abspath(source))' is missing.")

# We create the .user.build directory.
# If .user.clean is set, we first clean the existing directory.
doc.user.clean && isdir(build) && rm(build; recursive = true)
isdir(build) || mkpath(build)

# We'll walk over all the files in the .user.source directory.
# The directory structure is copied over to .user.build. All files, with
# the exception of markdown files (identified by the extension) are copied
# over as well, since they're assumed to be images, data files etc.
# Markdown files, however, get added to the document and also stored into
# `mdpages`, to be used later.
mdpages = String[]
for (root, dirs, files) in walkdir(source)
for dir in dirs
d = normpath(joinpath(build, relpath(root, source), dir))
isdir(d) || mkdir(d)
end

if endswith(file, ".md")
push!(mdpages, Documenter.srcpath(source, root, file))
Documenter.addpage!(doc, src, dst, wd)
else
cp(src, dst; force = true)
for file in files
src = normpath(joinpath(root, file))
dst = normpath(joinpath(build, relpath(root, source), file))

if workdir == :build
# set working directory to be the same as `build`
wd = normpath(joinpath(build, relpath(root, source)))
elseif workdir isa Symbol
# Maybe allow `:src` and `:root` as well?
throw(ArgumentError("Unrecognized working directory option '$workdir'"))
else
wd = normpath(joinpath(doc.user.root, workdir))
end

if endswith(file, ".md")
push!(mdpages, Documenter.srcpath(source, root, file))
Documenter.addpage!(doc, src, dst, wd)
else
cp(src, dst; force = true)
end
end
end
end

# If the user hasn't specified the page list, then we'll just default to a
# flat list of all the markdown files we found, sorted by the filesystem
# path (it will group them by subdirectory, among others).
userpages = isempty(doc.user.pages) ? sort(mdpages, lt=lt_page) : doc.user.pages
# If the user hasn't specified the page list, then we'll just default to a
# flat list of all the markdown files we found, sorted by the filesystem
# path (it will group them by subdirectory, among others).
userpages = isempty(doc.user.pages) ? sort(mdpages, lt=lt_page) : doc.user.pages

# Populating the .navtree and .navlist.
# We need the for loop because we can't assign to the fields of the immutable
# doc.internal.
for navnode in walk_navpages(userpages, nothing, doc)
push!(doc.internal.navtree, navnode)
end
# Populating the .navtree and .navlist.
# We need the for loop because we can't assign to the fields of the immutable
# doc.internal.
for navnode in walk_navpages(userpages, nothing, doc)
push!(doc.internal.navtree, navnode)
end

# Finally we populate the .next and .prev fields of the navnodes that point
# to actual pages.
local prev::Union{Documenter.NavNode, Nothing} = nothing
for navnode in doc.internal.navlist
navnode.prev = prev
if prev !== nothing
prev.next = navnode
# Finally we populate the .next and .prev fields of the navnodes that point
# to actual pages.
local prev::Union{Documenter.NavNode, Nothing} = nothing
for navnode in doc.internal.navlist
navnode.prev = prev
if prev !== nothing
prev.next = navnode
end
prev = navnode
end
prev = navnode
end

# If the user specified pagesonly, we will remove all the pages not in the navigation
# menu (.pages).
if doc.user.pagesonly
navlist_pages = getfield.(doc.internal.navlist, :page)
for page in keys(doc.blueprint.pages)
page ∈ navlist_pages || delete!(doc.blueprint.pages, page)
# If the user specified pagesonly, we will remove all the pages not in the navigation
# menu (.pages).
if doc.user.pagesonly
navlist_pages = getfield.(doc.internal.navlist, :page)
for page in keys(doc.blueprint.pages)
page ∈ navlist_pages || delete!(doc.blueprint.pages, page)
end
end
end
end
Expand Down Expand Up @@ -206,7 +208,9 @@ walk_navpages(src::String, parent, doc) = walk_navpages(true, nothing, src, [],
function Selectors.runner(::Type{Builder.Doctest}, doc::Documenter.Document)
if doc.user.doctest in [:fix, :only, true]
@info "Doctest: running doctests."
_doctest(doc.blueprint, doc)
TimerOutputs.@timeit Documenter.TIMER[] "Doctest: running doctests." begin
_doctest(doc.blueprint, doc)
end
num_errors = length(doc.internal.errors)
if (doc.user.doctest === :only || is_strict(doc, :doctest)) && num_errors > 0
error("`makedocs` encountered $(num_errors > 1 ? "$(num_errors) doctest errors" : "a doctest error"). Terminating build")
Expand All @@ -219,22 +223,24 @@ end
function Selectors.runner(::Type{Builder.ExpandTemplates}, doc::Documenter.Document)
is_doctest_only(doc, "ExpandTemplates") && return
@info "ExpandTemplates: expanding markdown templates."
expand(doc)
TimerOutputs.@timeit Documenter.TIMER[] "ExpandTemplates: expanding markdown templates." expand(doc)
end

function Selectors.runner(::Type{Builder.CrossReferences}, doc::Documenter.Document)
is_doctest_only(doc, "CrossReferences") && return
@info "CrossReferences: building cross-references."
crossref(doc)
TimerOutputs.@timeit Documenter.TIMER[] "CrossReferences: building cross-references." crossref(doc)
end

function Selectors.runner(::Type{Builder.CheckDocument}, doc::Documenter.Document)
is_doctest_only(doc, "CheckDocument") && return
@info "CheckDocument: running document checks."
missingdocs(doc)
footnotes(doc)
linkcheck(doc)
githubcheck(doc)
TimerOutputs.@timeit Documenter.TIMER[] "CheckDocument: running document checks." begin
missingdocs(doc)
footnotes(doc)
linkcheck(doc)
githubcheck(doc)
end
end

function Selectors.runner(::Type{Builder.Populate}, doc::Documenter.Document)
Expand All @@ -255,7 +261,7 @@ function Selectors.runner(::Type{Builder.RenderDocument}, doc::Documenter.Docume
* "] -- terminating build before rendering.")
else
@info "RenderDocument: rendering document."
Documenter.render(doc)
TimerOutputs.@timeit Documenter.TIMER[] "RenderDocument: rendering document." Documenter.render(doc)
end
end

Expand Down
Loading