Skip to content

Commit 2ab25aa

Browse files
authored
Update Documenter -> v1 (#372)
* Update `Documenter -> v1` * Fix docs block dropdown * Fix slug for `@customdocs` * Add preview for documentation PR * Refactor + Add comments + Trigger Preview
1 parent 52b0afb commit 2ab25aa

File tree

5 files changed

+177
-32
lines changed

5 files changed

+177
-32
lines changed

.github/workflows/docs.yml

+4
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ on:
66
- main
77
tags:
88
- '*'
9+
pull_request:
10+
types: [opened, synchronize, reopened]
11+
workflow_dispatch:
912

1013
jobs:
1114
docs:
15+
if: ${{ !(github.event_name == 'pull_request') || contains(github.event.pull_request.labels.*.name, 'documentation') }}
1216
name: Documentation
1317
runs-on: ubuntu-latest
1418
steps:

.github/workflows/docscleanuo.yml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Documentation Preview Cleanup
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
jobs:
8+
doc-preview-cleanup:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout gh-pages branch
12+
uses: actions/checkout@v2
13+
with:
14+
ref: gh-pages
15+
16+
- name: Delete preview and history
17+
run: |
18+
git config user.name "Documenter.jl"
19+
git config user.email "[email protected]"
20+
git rm -rf "previews/PR$PRNUM"
21+
git commit -m "delete preview"
22+
git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree})
23+
env:
24+
PRNUM: ${{ github.event.number }}
25+
26+
- name: Push changes
27+
run: |
28+
git push --force origin gh-pages-new:gh-pages
29+
30+
# Workflow copied from https://github.com/CliMA/TimeMachine.jl

docs/Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
33
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
44

55
[compat]
6-
Documenter = "0.27"
6+
Documenter = "1"

docs/customdocs.jl

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
module CustomDocs
2+
3+
import Base: Docs
4+
import Documenter
5+
import Documenter: DocSystem, Markdown, MarkdownAST, doccat
6+
import Documenter.Selectors: order, matcher, runner
7+
8+
# This is a bit of a hack to let us insert documentation blocks with custom content.
9+
# It means we can document Python things directly in the documentation source, and they
10+
# are searchable.
11+
#
12+
# It's a hack because of the `doccat` overload, requiring a special kind of "signature"
13+
# to embed the information we want.
14+
#
15+
# The first line is of the form "name - category", the rest is Markdown documentation.
16+
# For example:
17+
# ```@customdoc
18+
# foo - Function
19+
# Documentation for `foo`.
20+
# ```
21+
struct CustomCat{cat} end
22+
23+
# help?> Documenter.doccat
24+
# Returns the category name of the provided Object.
25+
doccat(::Docs.Binding, ::Type{CustomCat{cat}}) where {cat} = string(cat)
26+
27+
abstract type CustomDocExpander <: Documenter.Expanders.ExpanderPipeline end
28+
29+
order(::Type{CustomDocExpander}) = 20.0
30+
31+
function matcher(::Type{CustomDocExpander}, node, page, doc)
32+
return Documenter.iscode(node, "@customdoc")
33+
end
34+
35+
# source:
36+
# https://github.com/JuliaDocs/Documenter.jl/blob/7d3dc2ceef39a62edf2de7081e2d3aaf9be8d7c3/src/expander_pipeline.jl#L353
37+
function runner(::Type{CustomDocExpander}, node, page, doc)
38+
@assert node.element isa MarkdownAST.CodeBlock
39+
40+
block = node.element
41+
42+
name, cat, body = _parse_docs(block.code)
43+
44+
binding = DocSystem.binding(Main, name)
45+
46+
docsnodes = MarkdownAST.Node[]
47+
48+
object = Documenter.Object(binding, CustomCat{cat})
49+
50+
docstr = Markdown.parse(body)::Markdown.MD
51+
result = Docs.docstr(
52+
body,
53+
Dict{Symbol,Any}( # NOTE: Not sure about what to put here.
54+
:module => Main, # This is supposed to be tracking python code.
55+
:path => "",
56+
:linenumber => 0
57+
)
58+
)::Docs.DocStr
59+
60+
# NOTE: This was modified because the original Documenter.create_docsnode was generating unreachable links
61+
# Also, the original implementation required docstr, result to be vectors.
62+
63+
docsnode = _create_docsnode(docstr, result, object, page, doc)
64+
65+
# Track the order of insertion of objects per-binding.
66+
push!(get!(doc.internal.bindings, binding, Documenter.Object[]), object)
67+
68+
doc.internal.objects[object] = docsnode.element
69+
70+
push!(docsnodes, docsnode)
71+
72+
node.element = Documenter.DocsNodesBlock(block)
73+
74+
push!(node.children, docsnode)
75+
76+
return nothing
77+
end
78+
79+
function _parse_docs(code::AbstractString)
80+
m = match(r"^(.+?)\s*-\s*(.+?)\s*(\n[\s\S]*)$", strip(code))
81+
82+
if isnothing(m)
83+
error(
84+
"""
85+
Invalid docstring:
86+
$(code)
87+
"""
88+
)
89+
end
90+
91+
name = Symbol(m[1])
92+
cat = Symbol(m[2])
93+
body = strip(something(m[3], ""))
94+
95+
return (name, cat, body)
96+
end
97+
98+
# source:
99+
# https://github.com/JuliaDocs/Documenter.jl/blob/7d3dc2ceef39a62edf2de7081e2d3aaf9be8d7c3/src/expander_pipeline.jl#L959-L960
100+
function _create_docsnode(docstring, result, object, page, doc)
101+
# Generate a unique name to be used in anchors and links for the docstring.
102+
# NOTE: The way this is being slugified is causing problems:
103+
# slug = Documenter.slugify(object)
104+
slug = Documenter.slugify(string(object.binding))
105+
106+
anchor = Documenter.anchor_add!(doc.internal.docs, object, slug, page.build)
107+
docsnode = Documenter.DocsNode(anchor, object, page)
108+
109+
# Convert docstring to MarkdownAST, convert Heading elements, and push to DocsNode
110+
111+
ast = convert(MarkdownAST.Node, docstring)
112+
113+
doc.user.highlightsig && Documenter.highlightsig!(ast)
114+
115+
# The following 'for' corresponds to the old dropheaders() function
116+
for headingnode in ast.children
117+
headingnode.element isa MarkdownAST.Heading || continue
118+
119+
boldnode = MarkdownAST.Node(MarkdownAST.Strong())
120+
121+
for textnode in collect(headingnode.children)
122+
push!(boldnode.children, textnode)
123+
end
124+
125+
headingnode.element = MarkdownAST.Paragraph()
126+
127+
push!(headingnode.children, boldnode)
128+
end
129+
130+
push!(docsnode.mdasts, ast)
131+
push!(docsnode.results, result)
132+
push!(docsnode.metas, docstring.meta)
133+
134+
return MarkdownAST.Node(docsnode)
135+
end
136+
137+
end # module CustomDocs

docs/make.jl

+5-31
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,11 @@
1-
using Documenter, PythonCall, Markdown
1+
using Documenter, PythonCall
22

3-
# This is a bit of a hack to let us insert documentation blocks with custom content.
4-
# It means we can document Python things directly in the documentation source, and they
5-
# are searchable.
6-
#
7-
# It's a hack because of the `doccat` overload, requiring a special kind of "signature"
8-
# to embed the information we want.
9-
#
10-
# The first line is of the form "name - category", the rest is Markdown documentation.
11-
# For example:
12-
# ```@customdoc
13-
# foo - Function
14-
# Documentation for `foo`.
15-
# ```
16-
struct CustomCat{cat} end
17-
Documenter.Utilities.doccat(::Base.Docs.Binding, ::Type{CustomCat{cat}}) where {cat} = string(cat)
18-
struct CustomDocBlocks <: Documenter.Expanders.ExpanderPipeline end
19-
Documenter.Expanders.Selectors.order(::Type{CustomDocBlocks}) = 20.0
20-
Documenter.Expanders.Selectors.matcher(::Type{CustomDocBlocks}, node, page, doc) = Documenter.Expanders.iscode(node, "@customdoc")
21-
Documenter.Expanders.Selectors.runner(::Type{CustomDocBlocks}, x, page, doc) = begin
22-
header, rest = split(x.code, "\n", limit=2)
23-
docstr = Markdown.parse(rest)
24-
name, cat = split(header, "-", limit=2)
25-
binding = Docs.Binding(Main, Symbol(strip(name)))
26-
object = Documenter.Utilities.Object(binding, CustomCat{Symbol(strip(cat))})
27-
slug = Documenter.Utilities.slugify(strip(name))
28-
anchor = Documenter.Anchors.add!(doc.internal.docs, object, slug, page.build)
29-
node = Documenter.Documents.DocsNode(docstr, anchor, object, page)
30-
page.mapping[x] = node
31-
end
3+
include("customdocs.jl")
324

335
makedocs(
346
sitename = "PythonCall & JuliaCall",
357
modules = [PythonCall],
8+
warnonly = [:missing_docs], # avoid raising error when docs are missing
369
pages = [
3710
"Home" => "index.md",
3811
"The Julia module PythonCall" => [
@@ -55,5 +28,6 @@ makedocs(
5528
)
5629

5730
deploydocs(
58-
repo = "github.com/JuliaPy/PythonCall.jl.git",
31+
repo = raw"github.com/JuliaPy/PythonCall.jl.git",
32+
push_preview = true
5933
)

0 commit comments

Comments
 (0)