diff --git a/Project.toml b/Project.toml
index 29fe5b31..c8c7d2a9 100644
--- a/Project.toml
+++ b/Project.toml
@@ -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"
IOCapture = "0.2"
NodeJS_20_jll = "20"
+Test = "1"
+julia = "1.6"
+
+[extras]
+Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+
+[targets]
+test = ["Test"]
diff --git a/docs/make.jl b/docs/make.jl
index 95c07bb9..253652de 100644
--- a/docs/make.jl
+++ b/docs/make.jl
@@ -10,7 +10,8 @@ makedocs(;
format=DocumenterVitepress.MarkdownVitepress(
repo = "github.com/LuxDL/DocumenterVitepress.jl", # this must be the full URL!
devbranch = "master",
- devurl = "dev";
+ devurl = "dev",
+ redirect_trailing_slash = true;
),
draft = false,
source = "src",
@@ -35,4 +36,4 @@ deploydocs(;
branch = "gh-pages",
devbranch = "master",
push_preview = true
-)
\ No newline at end of file
+)
diff --git a/src/writer.jl b/src/writer.jl
index 2ae3615d..74ec8543 100644
--- a/src/writer.jl
+++ b/src/writer.jl
@@ -9,8 +9,8 @@ import Markdown
"""
MarkdownVitepress(; repo, devbranch, devurl, kwargs...)
-This is the main entry point for the Vitepress Markdown writer.
-
+This is the main entry point for the Vitepress Markdown writer.
+
It is a config which can be passed to the `format` keyword argument in `Documenter.makedocs`, and causes it to emit a Vitepress site.
!!! tip "Quick start"
@@ -46,7 +46,7 @@ Base.@kwdef struct MarkdownVitepress <: Documenter.Writer
"""The path to which the Markdown files will be output. Defaults to `\$build/.documenter`."""
md_output_path::String = ".documenter"
"""
- Determines whether to clean up the Markdown assets after build, i.e., whether to remove the contents of `md_output_path` after the Vitepress site is built.
+ Determines whether to clean up the Markdown assets after build, i.e., whether to remove the contents of `md_output_path` after the Vitepress site is built.
Options are:
- `nothing`: **Default**. Only remove the contents of `md_output_path` if the documentation will deploy, to save space.
- `true`: Removes the contents of `md_output_path` after the Vitepress site is built.
@@ -54,7 +54,14 @@ Base.@kwdef struct MarkdownVitepress <: Documenter.Writer
"""
clean_md_output::Union{Nothing, Bool} = nothing
"""
- DeployDecision from Documenter.jl. This is used to determine whether to deploy the documentation or not.
+ Whether to insert 200 redirects from https://example.com/page/ to https://example.com/page.
+
+ Defaults to `false`. This is useful for transitioning from Documenter.jl which uses
+ trailing slashes for its canonical urls by default.
+ """
+ redirect_trailing_slash::Bool = false
+ """
+ `DeployDecision` from Documenter.jl. This is used to determine whether to deploy the documentation or not.
Options are:
- `nothing`: **Default**. Automatically determine whether to deploy the documentation.
- `Documenter.DeployDecision`: Override the automatic decision and deploy based on the passed config.
@@ -63,6 +70,16 @@ Base.@kwdef struct MarkdownVitepress <: Documenter.Writer
`Documenter.deploy_folder(Documenter.auto_detect_deploy_system(); repo, devbranch, devurl, push_preview)`.
"""
deploy_decision::Union{Nothing, Documenter.DeployDecision} = nothing
+ # This inner constructor serves only to
+ function MarkdownVitepress(args...)
+ args[10] && !args[6] && throw(ArgumentError(
+ """
+ MarkdownVitepress: `redirect_trailing_slash` can only be `true` if `build_vitepress` is also `true`,
+ because redirects are insterted after the site is built.
+ """
+ ))
+ new(args...)
+ end
end
# return the same file with the extension changed to .md
@@ -77,13 +94,13 @@ This function takes the filename `file`, and returns a file path in the `mdfolde
function docpath(file, builddir, mdfolder)
path = relpath(file, builddir)
filename = mdext(path)
- return joinpath(builddir, mdfolder, filename)
+ return joinpath(builddir, mdfolder, filename)
end
"""
render(args...)
-This is the main entry point and recursive function to render a Documenter document to
+This is the main entry point and recursive function to render a Documenter document to
Markdown in the Vitepress flavour. It is called by `Documenter.build` and should not be
called directly.
@@ -125,7 +142,7 @@ function render(doc::Documenter.Document, settings::MarkdownVitepress=MarkdownVi
file_relpath = relpath(file, joinpath(builddir, settings.md_output_path, "assets"))
cp(joinpath(builddir, settings.md_output_path, "assets", file_relpath), joinpath(builddir, settings.md_output_path, "public", file_relpath))
end
- end
+ end
if any(favicon_files)
for file in files[favicon_files]
file_relpath = relpath(file, joinpath(builddir, settings.md_output_path, "assets"))
@@ -148,7 +165,7 @@ function render(doc::Documenter.Document, settings::MarkdownVitepress=MarkdownVi
# We manually obtain the Documenter deploy configuration,
# so we can use it to set Vitepress's settings.
- if settings.deploy_decision === nothing
+ if isnothing(settings.deploy_decision)
# TODO: make it so that the user does not have to provide a repo url!
deploy_config = Documenter.auto_detect_deploy_system()
deploy_decision = Documenter.deploy_folder(
@@ -201,7 +218,7 @@ function render(doc::Documenter.Document, settings::MarkdownVitepress=MarkdownVi
rm(joinpath(dirname(builddir), "package-lock.json"))
end
end
- # This is only useful if placed in the root of the `docs` folder, and we don't
+ # This is only useful if placed in the root of the `docs` folder, and we don't
# have any names which conflict with Jekyll (beginning with _ or .) in any case.
# touch(joinpath(builddir, "final_site", ".nojekyll"))
@@ -221,6 +238,44 @@ function render(doc::Documenter.Document, settings::MarkdownVitepress=MarkdownVi
@info "DocumenterVitepress: Markdown output cleaned up. Folder looks like: $(readdir(doc.user.build))"
end
+ if settings.redirect_trailing_slash
+ @info "DocumenterVitepress: inserting javascript 200 redirects from https://example.com/page/ to https://example.com/page because `redirect_trailing_slash` is true."
+ for (root, dirs, files) in walkdir(builddir)
+ for file in files
+ name, ext = splitext(file)
+ if ext === ".html" && name ∉ ("404", "index")
+ dir = joinpath(root, name)
+ if !isdir(dir)
+ mkdir(dir)
+ println(((settings.deploy_url, root, builddir, name)))
+ url = "https://"*normpath(joinpath(settings.deploy_url, relpath(root, builddir), name))
+ println(url)
+ open(joinpath(dir, "index.html"), "w") do io
+ write(io, """
+
+
+ Redirecting to ..$name
+
+ """)
+ # The script is equivalent to
+ # ``
+ # but keeps fragments. If Javascript fails for whatever
+ # reason, the meta http-equiv will proc, dropping fragments
+ # If that, too fails, there's an ordinary, human readable
+ # relative link.
+ #
+ # This uses a relative canonical link which is bad form, but
+ # oh well. We don't have access to the full URL until deploy
+ # time.
+ end
+ end
+ end
+ end
+ end
+ end
else
@info """
DocumenterVitepress: did not build Vitepress site because `build_vitepress` was set to `false`.
@@ -316,7 +371,7 @@ function renderdoc(io::IO, mime::MIME"text/plain", node::Documenter.MarkdownAST.
if url !== nothing
# This is how Documenter does it:
# push!(ret.nodes, a[".docs-sourcelink", :target=>"_blank", :href=>url]("source"))
- # so clearly we should be inserting some form of HTML tag here,
+ # so clearly we should be inserting some form of HTML tag here,
# and defining its rendering in CSS?
# TODO: switch to Documenter style here
println(io, "\n", "[source]($url)", "\n")
@@ -384,9 +439,9 @@ function join_multiblock(node::Documenter.MarkdownAST.Node)
for thing in code_blocks
# reset the buffer and push the old code block
if thing.language != current_language
- # Remove this if statement if you want to
+ # Remove this if statement if you want to
# include empty code blocks in the output.
- if isempty(thing.code)
+ if isempty(thing.code)
current_string *= "\n\n"
continue
end
@@ -482,7 +537,7 @@ function render_mime(io::IO, mime::MIME"image/svg+xml", node, element, page, doc
# Additionally, Vitepress complains about the XML version and encoding string below,
# so we just remove this bad hombre!
bad_hombre_string = "" |> lowercase
- location = findfirst(bad_hombre_string, lowercase(image_text))
+ location = findfirst(bad_hombre_string, lowercase(image_text))
if !isnothing(location) # couldn't figure out how to do this in one line - maybe regex? A question for later though.
image_text = replace(image_text, image_text[location] => "")
end
@@ -727,7 +782,7 @@ function render(io::IO, mime::MIME"text/plain", node::Documenter.MarkdownAST.Nod
# Main.@infiltrate
print(io, "\$", math.math, "\$")
end
-# Display math
+# Display math
function render(io::IO, mime::MIME"text/plain", node::Documenter.MarkdownAST.Node, math::MarkdownAST.DisplayMath, page, doc; kwargs...)
# Main.@infiltrate
println(io)
@@ -771,7 +826,7 @@ function render(io::IO, mime::MIME"text/plain", node::Documenter.MarkdownAST.Nod
end
end
# We create this IOBuffer in order to render to it.
- iob = IOBuffer()
+ iob = IOBuffer()
# This will eventually hold the rendered table cells as Strings.
cell_strings = Vector{Vector{String}}()
current_row_vec = String[]
diff --git a/test/runtests.jl b/test/runtests.jl
new file mode 100644
index 00000000..2a3ee55f
--- /dev/null
+++ b/test/runtests.jl
@@ -0,0 +1,5 @@
+using Test, DocumenterVitepress
+
+@test DocumenterVitepress.MarkdownVitepress(; repo = "...", devbranch = "...", devurl = "...") isa DocumenterVitepress.MarkdownVitepress
+@test_throws ArgumentError DocumenterVitepress.MarkdownVitepress(; repo = "...", devbranch = "...", devurl = "...",
+ build_vitepress = false, redirect_trailing_slash = true)