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

Draft mode that skips (potentially) expensive parts of the build process #1836

Merged
merged 2 commits into from
Jun 3, 2022
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

## Version `v0.27.19`

* ![Enhancement][badge-enhancement] Documenter can now build draft version of HTML documentation by passing `draft=true` to `makedocs`. Draft mode skips potentially expensive parts of the building process and can be useful to get faster feedback when writing documentation. Draft mode currently skips doctests, `@example`-, `@repl`-, `@eval`-, and `@setup`-blocks. Draft mode can be disabled (or enabled) on a per-page basis by setting `Draft = true` in an `@meta` block. ([#1836][github-1836])
* ![Enhancement][badge-enhancement] On the HTML search page, pressing enter no longer causes the page to refresh (and therefore does not trigger the slow search index rebuild). ([#1728][github-1728], [#1833][github-1833], [#1834][github-1834])
* ![Enhancement][badge-enhancement] For the `edit_link` keyword to `HTML()`, Documenter automatically tries to figure out if the remote default branch is `main`, `master`, or something else. It will print a warning if it is unable to reliably determine either `edit_link` or `devbranch` (for `deploydocs`). ([#1827][github-1827], [#1829][github-1829])

Expand Down Expand Up @@ -1052,6 +1053,7 @@
[github-1829]: https://github.com/JuliaDocs/Documenter.jl/pull/1829
[github-1833]: https://github.com/JuliaDocs/Documenter.jl/pull/1833
[github-1834]: https://github.com/JuliaDocs/Documenter.jl/pull/1834
[github-1836]: https://github.com/JuliaDocs/Documenter.jl/pull/1836
<!-- end of issue link definitions -->

[julia-38079]: https://github.com/JuliaLang/julia/issues/38079
Expand Down
1 change: 1 addition & 0 deletions docs/src/man/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ page. Currently recognised keys:
- `EditURL`: link to where the page can be edited. This defaults to the `.md` page itself,
but if the source is something else (for example if the `.md` page is generated as part of
the doc build) this can be set, either as a local link, or an absolute url.
- `Draft`: boolean for overriding the global draft mode for the page.

Example:

Expand Down
9 changes: 9 additions & 0 deletions src/DocTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,18 @@ function doctest(blueprint::Documents.DocumentBlueprint, doc::Documents.Document
@debug "Running doctests."
# find all the doctest blocks in the pages
for (src, page) in blueprint.pages
if Utilities.is_draft(doc, page)
@debug "Skipping page-doctests in draft mode" page.source
continue
end
doctest(page, doc)
end

if Utilities.is_draft(doc)
@debug "Skipping docstring-doctests in draft mode"
return
end

# find all the doctest block in all the docstrings (within specified modules)
for mod in blueprint.modules
for (binding, multidoc) in DocSystem.getmeta(mod)
Expand Down
6 changes: 6 additions & 0 deletions src/Documenter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export Deps, makedocs, deploydocs, hide, doctest, DocMeta, asset,
highlightsig = true,
sitename = "",
expandfirst = [],
draft = false,
)

Combines markdown files and inline docstrings into an interlinked document.
Expand Down Expand Up @@ -188,6 +189,11 @@ is enabled by default.
before the others. Documenter normally evaluates the files in the alphabetic order of their
file paths relative to `src`, but `expandfirst` allows some pages to be prioritized.

**`draft`** can be set to `true` to build a draft version of the document. In draft mode
some potentially time-consuming steps are skipped (e.g. running `@example` blocks), which is
useful when iterating on the documentation. This setting can also be configured per-page
by setting `Draft = true` in an `@meta` block.

For example, if you have `foo.md` and `bar.md`, `bar.md` would normally be evaluated before
`foo.md`. But with `expandfirst = ["foo.md"]`, you can force `foo.md` to be evaluated first.

Expand Down
5 changes: 4 additions & 1 deletion src/Documents.jl
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ struct User
authors :: String
version :: String # version string used in the version selector by default
highlightsig::Bool # assume leading unlabeled code blocks in docstrings to be Julia.
draft :: Bool
end

"""
Expand Down Expand Up @@ -304,6 +305,7 @@ function Document(plugins = nothing;
authors :: AbstractString = "",
version :: AbstractString = "",
highlightsig::Bool = true,
draft::Bool = false,
others...
)

Expand Down Expand Up @@ -338,7 +340,8 @@ function Document(plugins = nothing;
sitename,
authors,
version,
highlightsig
highlightsig,
draft,
)
internal = Internal(
Utilities.assetsdir(),
Expand Down
38 changes: 38 additions & 0 deletions src/Expanders.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ function pagecheck(page)
end
end

# Draft output code block
function create_draft_result(x; blocktype="code")
content = []
push!(content, Markdown.Code("julia", x.code))
push!(content, Dict{MIME,Any}(MIME"text/plain"() => "<< $(blocktype)-block not executed in draft mode >>"))
return Documents.MultiOutput(content)
end


# Expander Pipeline.
# ------------------
Expand Down Expand Up @@ -514,6 +522,12 @@ end
# -----

function Selectors.runner(::Type{EvalBlocks}, x, page, doc)
# Bail early if in draft mode
if Utilities.is_draft(doc, page)
@debug "Skipping evaluation of @eval block in draft mode:\n$(x.code)"
page.mapping[x] = create_draft_result(x; blocktype="@eval")
return
end
sandbox = Module(:EvalBlockSandbox)
lines = Utilities.find_block_in_file(x.code, page.source)
linenumbernode = LineNumberNode(lines === nothing ? 0 : lines.first,
Expand Down Expand Up @@ -571,6 +585,14 @@ function Selectors.runner(::Type{ExampleBlocks}, x, page, doc)
matched = match(r"^@example(?:\s+([^\s;]+))?\s*(;.*)?$", x.language)
matched === nothing && error("invalid '@example' syntax: $(x.language)")
name, kwargs = matched.captures

# Bail early if in draft mode
if Utilities.is_draft(doc, page)
@debug "Skipping evaluation of @example block in draft mode:\n$(x.code)"
page.mapping[x] = create_draft_result(x; blocktype="@example")
return
end

# The sandboxed module -- either a new one or a cached one from this page.
mod = Utilities.get_sandbox_module!(page.globals.meta, "atexample", name)
sym = nameof(mod)
Expand Down Expand Up @@ -663,6 +685,14 @@ function Selectors.runner(::Type{REPLBlocks}, x, page, doc)
matched = match(r"^@repl(?:\s+([^\s;]+))?\s*(;.*)?$", x.language)
matched === nothing && error("invalid '@repl' syntax: $(x.language)")
name, kwargs = matched.captures

# Bail early if in draft mode
if Utilities.is_draft(doc, page)
@debug "Skipping evaluation of @repl block in draft mode:\n$(x.code)"
page.mapping[x] = create_draft_result(x; blocktype="@repl")
return
end

# The sandboxed module -- either a new one or a cached one from this page.
mod = Utilities.get_sandbox_module!(page.globals.meta, "atexample", name)

Expand Down Expand Up @@ -726,6 +756,14 @@ function Selectors.runner(::Type{SetupBlocks}, x, page, doc)
matched = match(r"^@setup(?:\s+([^\s;]+))?\s*$", x.language)
matched === nothing && error("invalid '@setup <name>' syntax: $(x.language)")
name = matched[1]

# Bail early if in draft mode
if Utilities.is_draft(doc, page)
@debug "Skipping evaluation of @setup block in draft mode:\n$(x.code)"
page.mapping[x] = create_draft_result(x; blocktype="@setup")
return
end

# The sandboxed module -- either a new one or a cached one from this page.
mod = Utilities.get_sandbox_module!(page.globals.meta, "atexample", name)

Expand Down
8 changes: 8 additions & 0 deletions src/Utilities/Utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,14 @@ function git_remote_head_branch(varname, root; remotename = "origin", fallback =
end
end

# Check global draft setting
is_draft(doc) = doc.user.draft
# Check if the page is built with draft mode
function is_draft(doc, page)::Bool
# Check both Draft and draft from @meta block
return get(page.globals.meta, :Draft, get(page.globals.meta, :draft, is_draft(doc)))
end

include("DOM.jl")
include("MDFlatten.jl")
include("TextDiff.jl")
Expand Down
19 changes: 18 additions & 1 deletion test/examples/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ EXAMPLE_BUILDS = if haskey(ENV, "DOCUMENTER_TEST_EXAMPLES")
split(ENV["DOCUMENTER_TEST_EXAMPLES"])
else
["markdown", "html", "html-mathjax2-custom", "html-mathjax3", "html-mathjax3-custom",
"html-local"]
"html-local", "html-draft"]
fredrikekre marked this conversation as resolved.
Show resolved Hide resolved
end

# Modules `Mod` and `AutoDocs`
Expand Down Expand Up @@ -342,6 +342,23 @@ else
nothing
end

# HTML: draft mode
examples_html_local_doc = if "html-draft" in EXAMPLE_BUILDS
@info("Building mock package docs: HTMLWriter / draft build")
@quietly makedocs(
debug = true,
draft = true,
root = examples_root,
build = "builds/html-draft",
sitename = "Documenter example (draft)",
pages = htmlbuild_pages,
)
else
@info "Skipping build: HTML/draft"
@debug "Controlling variables:" EXAMPLE_BUILDS get(ENV, "DOCUMENTER_TEST_EXAMPLES", nothing)
nothing
end

# Markdown
examples_markdown_doc = if "markdown" in EXAMPLE_BUILDS
@info("Building mock package docs: MarkdownWriter")
Expand Down