Skip to content

Commit

Permalink
Fix linkcheck for docstrings (#2330)
Browse files Browse the repository at this point in the history
  • Loading branch information
goerz authored Nov 8, 2023
1 parent 4cd7a86 commit 715a885
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 8 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,16 @@ jobs:
- name: Install dependencies
run: julia --color=yes --project -e'using Pkg; Pkg.instantiate()'
- name: Run online linkcheck tests
run: julia --color=yes --project test/online_linkcheck.jl
run: julia --color=yes --project --code-coverage test/online_linkcheck.jl
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
with:
file: lcov.info
- name: Submit coverage to Coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: lcov.info

linkcheck-manual:
name: "Linkcheck: Documenter manual"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* Enabled text wrapping in docstring header on smaller screens. ([#2293], [#2307])
* Fixed breadcrumb overflow with long page title on narrow screens (mobile). ([#2317])
* Fixed `linkcheck` not checking inside of docstrings. ([#2329], [#2330])

## Version [v1.1.2] - 2023-10-23

Expand Down
31 changes: 24 additions & 7 deletions src/docchecks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,7 @@ function linkcheck(doc::Document)
if doc.user.linkcheck
if hascurl()
for (src, page) in doc.blueprint.pages
for node in AbstractTrees.PreOrderDFS(page.mdast)
linkcheck(node, doc)
end
linkcheck(page.mdast, doc)
end
else
@docerror(doc, :linkcheck, "linkcheck requires `curl`.")
Expand All @@ -180,9 +178,20 @@ function linkcheck(doc::Document)
return nothing
end

function linkcheck(node::MarkdownAST.Node, doc::Document; method::Symbol=:HEAD)
node.element isa MarkdownAST.Link || return
link = node.element
function linkcheck(mdast::MarkdownAST.Node, doc::Document)
for node in AbstractTrees.PreOrderDFS(mdast)
linkcheck(node, node.element, doc)
end
end

function linkcheck(node::MarkdownAST.Node, element::MarkdownAST.AbstractElement, doc::Document)
# The linkcheck is only active for specific `element` types
# (`MarkdownAST.Link`, most importantly), which are defined below as more
# specific methods
return nothing
end

function linkcheck(node::MarkdownAST.Node, link::MarkdownAST.Link, doc::Document; method::Symbol=:HEAD)

# first, make sure we're not supposed to ignore this link
for r in doc.user.linkcheck_ignore
Expand Down Expand Up @@ -244,7 +253,7 @@ function linkcheck(node::MarkdownAST.Node, doc::Document; method::Symbol=:HEAD)
elseif protocol === :HTTP && status == 405 && method === :HEAD
# when a server doesn't support HEAD requests, fallback to GET
@debug "linkcheck '$(link.destination)' status: $(status), retrying without `-I`"
return linkcheck(link, doc; method=:GET)
return linkcheck(node, link, doc; method=:GET)
else
@docerror(doc, :linkcheck, "linkcheck '$(link.destination)' status: $(status).")
end
Expand All @@ -255,6 +264,14 @@ function linkcheck(node::MarkdownAST.Node, doc::Document; method::Symbol=:HEAD)
return false
end


function linkcheck(node::MarkdownAST.Node, docs_node::Documenter.DocsNode, doc::Document)
for mdast in docs_node.mdasts
linkcheck(mdast, doc)
end
end


linkcheck_ismatch(r::String, url) = (url == r)
linkcheck_ismatch(r::Regex, url) = occursin(r, url)

Expand Down
33 changes: 33 additions & 0 deletions test/docstring_links/make.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module DocstringLinkTests
using Test
using Documenter
import IOCapture


module InvalidLinks
export f

"""Link to [invalid](http://domain.invalid/docstring.html)"""
f(x) = x

end


@testset "invalid links in docstring" begin
c = IOCapture.capture(; rethrow=Union{}) do
makedocs(;
root = dirname(@__FILE__),
modules = InvalidLinks,
sitename = "InvalidLinks Checks",
warnonly = false,
linkcheck = true,
debug = false
)
end
@test contains(c.output, r"Error:.*http://domain.invalid/index.html")
@test contains(c.output, r"Error:.*http://domain.invalid/docstring.html")
@test c.value isa ErrorException
@test contains(c.value.msg, "`makedocs` encountered an error [:linkcheck]")
end

end
6 changes: 6 additions & 0 deletions test/docstring_links/src/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
An [invalid link](http://domain.invalid/index.html) in the `.md` file.


```@docs
Main.OnlineLinkcheckTests.DocstringLinkTests.InvalidLinks.f
```
6 changes: 6 additions & 0 deletions test/online_linkcheck.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ using Markdown
using Test

@testset "Online linkcheck" begin

@testset "Successes" begin
src = convert(
MarkdownAST.Node,
Expand Down Expand Up @@ -36,6 +37,11 @@ using Test
@test_logs (:error,) @test linkcheck(doc) === nothing
@test doc.internal.errors == Set{Symbol}([:linkcheck])
end

@testset "Linkcheck in Docstrings" begin
include("docstring_links/make.jl")
end

end

end # module

0 comments on commit 715a885

Please sign in to comment.