Skip to content

Commit e6997ed

Browse files
authored
Allow letting the docs build to fail with servedocs() (#176)
Previously `servedocs()` would exit whenever the docs failed to build, and it can be annoying to always restart it on errors. Now when building the docs fails a special status will be set on the `SimpleWatcher` which will get `serve_file()` to return a custom error page (which will be reloaded automatically when the docs build again).
1 parent 262aa6a commit e6997ed

File tree

4 files changed

+78
-21
lines changed

4 files changed

+78
-21
lines changed

src/server.jl

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,11 @@ function serve_file(
349349
ret_code = 200
350350
fs_path, case = get_fs_path(req.target)
351351

352-
if case == :not_found_without_404
353-
html_404 = pagehtml(title = "404 Not Found") do io
354-
write(io, """
352+
# Fast paths to execute if building documentation isn't currently failing
353+
if fw.status != :documenter_jl_error
354+
if case == :not_found_without_404
355+
html_404 = pagehtml(title = "404 Not Found") do io
356+
write(io, """
355357
<div style="width: 100%; max-width: 500px; margin: auto">
356358
<h1 style="margin-top: 2em">404 Not Found</h1>
357359
<p>
@@ -366,26 +368,48 @@ function serve_file(
366368
</p>
367369
</div>
368370
"""
369-
)
371+
)
372+
end
373+
return HTTP.Response(404, html_404)
374+
elseif case == :not_found_with_404
375+
ret_code = 404
376+
elseif case == :dir_without_index
377+
index_page = get_dir_list(fs_path)
378+
return HTTP.Response(200, index_page)
370379
end
371-
return HTTP.Response(404, html_404)
372-
elseif case == :not_found_with_404
373-
ret_code = 404
374-
elseif case == :dir_without_index
375-
index_page = get_dir_list(fs_path)
376-
return HTTP.Response(200, index_page)
377380
end
378381

379-
#
380-
# In what follows, fs_path points to a file
381-
# :dir_with_index
382-
# :file
383-
# :not_found_with_404
384-
# --> html-like: try to inject reload-script
385-
# --> other: just get the browser to show it
386-
#
387-
ext = lstrip(last(splitext(fs_path)), '.') |> string
388-
content = read(fs_path, String)
382+
ext = nothing
383+
content = nothing
384+
385+
# If building the documentation is failing we return a special error page,
386+
# otherwise we just read the file from disk.
387+
if fw.status == :documenter_jl_error
388+
ret_code = 500
389+
ext = "html"
390+
content = pagehtml(title = "Documenter.jl error") do io
391+
write(io, """
392+
<div style="width: 100%; max-width: 500px; margin: auto">
393+
<h1 style="margin-top: 2em">Error building docs</h1>
394+
<p>
395+
An error occurred when rebuilding the documentation, please check the <code>servedocs()</code> output.
396+
</p>
397+
</div>
398+
"""
399+
)
400+
end
401+
else
402+
#
403+
# In what follows, fs_path points to a file
404+
# :dir_with_index
405+
# :file
406+
# :not_found_with_404
407+
# --> html-like: try to inject reload-script
408+
# --> other: just get the browser to show it
409+
#
410+
ext = lstrip(last(splitext(fs_path)), '.') |> string
411+
content = read(fs_path, String)
412+
end
389413

390414
# build the response with appropriate mime type (this is inspired from Mux
391415
# https://github.com/JuliaWeb/Mux.jl/blob/master/src/examples/files.jl)

src/utils.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,14 @@ function servedocs_callback!(
4949
end
5050

5151
# Run a Documenter pass
52-
Main.include(abspath(path2makejl))
52+
try
53+
Main.include(abspath(path2makejl))
54+
dw.status = :runnable
55+
catch ex
56+
# If there was an error, record it so that an error is displayed to the user
57+
dw.status = :documenter_jl_error
58+
end
59+
5360
file_changed_callback(fp)
5461
return
5562
end

test/server.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,22 @@ tasks that you will try to start.
127127
@test !sentinel1.io.io.writable
128128
@test !sentinel2.io.io.writable
129129

130+
# Mimic an error when building documentation with Documenter.jl. When this
131+
# happens servedocs_callback!() will set the watcher status to
132+
# :documenter_jl_error.
133+
fw.status = :documenter_jl_error
134+
135+
# Now any requests should give us the custom error page
136+
response = HTTP.get("http://localhost:$port/"; status_exception=false)
137+
body_str = String(response.body)
138+
@test response.status == 500
139+
@test occursin("error occurred when rebuilding", body_str)
140+
# And they should include the browser reload script so they automatically
141+
# reload when the docs build again.
142+
@test occursin(LS.BROWSER_RELOAD_SCRIPT, body_str)
143+
# Reset the watcher status for the rest of the tests
144+
fw.status = :runnable
145+
130146
# if we remove the files, it shall stop following it
131147
rm("tmp.html")
132148
rm("css", recursive=true)

test/utils.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@
4949
@test length(dw.watchedfiles) == 2
5050
@test readmake() == 4
5151

52+
# Modify make.jl to force an error
53+
write(makejl, "error()")
54+
LS.servedocs_callback!(dw, joinpath("docs", "src", "index.md"), makejl, def...)
55+
@test dw.status == :documenter_jl_error
56+
57+
# Fixing the error should reset the status
58+
write(makejl, "42")
59+
LS.servedocs_callback!(dw, joinpath("docs", "src", "index.md"), makejl, def...)
60+
@test dw.status == :runnable
61+
5262
cd(bk)
5363
end
5464

0 commit comments

Comments
 (0)