Skip to content

Commit

Permalink
Use EditURL instead of regex for edit links
Browse files Browse the repository at this point in the history
Previously Documenter's HTML was postprocessed in order to point edit on
GitHub links to the original source file as input to DemoCards.jl. This
commit changes this so that the original source file is provided to
Documenter.jl in the generated markdown files using the @meta: EditURL
setting. This is less fragile to changes in Documenter.jl or e.g.
different templates since it doesn't rely on using regex to modify the
particular form of the HTML output by Documenter.jl.
  • Loading branch information
frankier committed Sep 19, 2023
1 parent ae1a1e1 commit 040f178
Show file tree
Hide file tree
Showing 21 changed files with 97 additions and 142 deletions.
98 changes: 0 additions & 98 deletions src/generate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,6 @@ function makedemos(source::String, templates::Union{Dict, Nothing} = nothing;

# pipeline: generate postprocess callback function
postprocess_cb = ()->begin
@info "Redirect page URL: redirect docs-edit-link for demos in \"$(source)\" directory."
isnothing(templates) || push!(source_files, joinpath(page_root, "index.md"))
foreach(source_files) do source_file
redirect_link(source_file, source, root, src, build, edit_branch)
end

@info "Clean up DemoCards build dir: \"$source\""
# Ref: https://discourse.julialang.org/t/find-what-has-locked-held-a-file/23278/2
Base.Sys.iswindows() && GC.gc()
Expand Down Expand Up @@ -426,98 +420,6 @@ function _copy_assets(dest_root::String, src_root::String)
end
end

### postprocess

"""
redirect_link(src_file, source, root, src, build, edit_branch)
Redirect the "Edit On GitHub" link of generated demo files to its original url, without
this a 404 error is expected.
"""
function redirect_link(source_file, source, root, src, build, edit_branch)
build_file = get_build_file(source_file, source, root, build)
if !isfile(build_file)
@warn "$build_file doesn't exists, skip"
return nothing
end
contents = read(build_file, String)

if !isfile(source_file)
# reach here when user doesn't create a page template index.md
# just remove the whole button so that user don't click and get 404
new_contents = replace(contents, regex_edit_on_github=>"")
else
# otherwise, redirect the url links
m = match(regex_edit_on_github, contents)
isnothing(m) && return nothing
build_url = m.captures[1]

src_url = get_source_url(build_url, source, basename(source_file), src)
new_contents = replace(contents, build_url=>src_url)
end
write(build_file, new_contents)
end

function get_source_url(build_url, source, cardname, src)
# given input:
# - projct_root: "$REPO/blob/$edit_branch"
# - build_root: "$projct_root/$docs_root/$src"
# - build_dir: "$build_root/$prefix/$page/$section/$subsection"
# - build_url: "$build_dir/$cardfile"
# example of build_url:
# "https://github.com/johnnychen94/DemoCards.jl/blob/master/docs/src/quickstart/usage_example/julia_demos/2.cover_on_the_fly.md"
# we need to generate:
# - src_root: "$projct_root/$docs_root/$src"
# - src_dir: "$src_root/$prefix/$page/$section/$subsection"
# - src_url: "$src_dir/$cardfile"
# example of src_url:
# "https://github.com/johnnychen94/DemoCards.jl/blob/master/docs/quickstart/usage_example/julia_demos/2.cover_on_the_fly.jl"
source = replace(source, Base.Filesystem.path_separator => "/")

repo, path = strip.(split(build_url, "/blob/"; limit=2), '/')
root_to_subsection = replace(splitdir(path)[1], "$(src)/" => ""; count=1)
root_to_subsection = replace(root_to_subsection, "/$(basename(source))/" => "/$(source)/"; count=1)
src_url = join([repo, "blob", root_to_subsection, cardname], "/")

return src_url
end

function get_build_file(source_file, source, root, build)
# given inputs:
# - source_file: "$source_root/$prefix/$page/$section/$subsection/$card.md"
# - source: "$prefix/$page
# - build: "build"
# we need to generate:
# - build_root: "$source_root/$build"
# - build_dir: "$build_root/$page/$section/$subsection
# - build_file: "$build_dir/$card.html" or "$build_dir/$card/index.html"

sep = Base.Filesystem.path_separator
# add trailing / to avoid incorrect substring match
source_root = abspath(root, source)
build_root = joinpath(root, build)
prefix, page = splitdir(source_root)

source_dir, name = splitdir(source_file)
card, ext = splitext(name)
_, prefix_to_subsection = split(source_dir, source_root; limit=2)
if !isempty(prefix) && prefix_to_subsection != ""
# add trailing / to remove leading / for prefix_to_subsection
# otherwise, joinpath of two absolute path would simply drop the first one
_, prefix_to_subsection = split(prefix_to_subsection, sep; limit=2)
end
build_dir = joinpath(build_root, page, prefix_to_subsection)

prettyurls = isdir(joinpath(build_dir, card))
# Documenter.HTML behaves differently on prettyurls
if prettyurls
build_file = joinpath(build_dir, card, "index.html")
else
build_file = joinpath(build_dir, card * ".html")
end
return build_file
end

# modified from https://github.com/fredrikekre/Literate.jl to replace the use of @__NBVIEWER_ROOT_URL__
function get_nbviewer_root_url(branch)
if haskey(ENV, "HAS_JOSH_K_SEAL_OF_APPROVAL") # Travis CI
Expand Down
3 changes: 2 additions & 1 deletion src/types/julia.jl
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ function save_democards(card_dir::String,
kwargs...)
isdir(card_dir) || mkpath(card_dir)
@debug card.path
original_card_path = card.path
cardname = splitext(basename(card.path))[1]
md_path = joinpath(card_dir, "$(cardname).md")
nb_path = joinpath(card_dir, "$(cardname).ipynb")
Expand Down Expand Up @@ -256,7 +257,7 @@ function save_democards(card_dir::String,
# @ref syntax: https://juliadocs.github.io/Documenter.jl/stable/man/syntax/#@ref-link-1
header = need_header ? "# [$(card.title)](@id $(card.id))\n" : "\n"
footer = credit ? julia_footer : "\n"
write(md_path, header, body, footer)
write(md_path, meta_edit_url(original_card_path), header, body, footer)

# 5. filter out source file
mktempdir(card_dir) do tmpdir
Expand Down
2 changes: 1 addition & 1 deletion src/types/markdown.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,5 @@ function save_democards(card_dir::String,
header = need_header ? "# [$(card.title)](@id $(card.id))\n" : "\n"

footer = credit ? markdown_footer : "\n"
write(markdown_path, header, make_badges(card)*"\n\n", body, footer)
write(markdown_path, meta_edit_url(card.path), header, make_badges(card)*"\n\n", body, footer)
end
2 changes: 1 addition & 1 deletion src/types/page.jl
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ function DemoPage(root::String, filter_func=x -> true)::DemoPage

# default template requires a title
template = load_config(page, "template"; config=config)
page.template = template
page.template = meta_edit_url(template_file) * template

if haskey(config, "properties")
properties = config["properties"]::Dict
Expand Down
14 changes: 14 additions & 0 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,17 @@ function input_bool(prompt)
end

is_pluto_notebook(path::String) = any(occursin.(r"#\s?╔═╡\s?[0-9a-f\-]{36}", readlines(path)))

"""
meta_edit_url(path)
helper to add in corrected edit link for markdown files which will be processed by Documenter.jl later
"""
function meta_edit_url(path)
return """
```@meta
EditURL = "$path"
```
"""
end
4 changes: 2 additions & 2 deletions test/generate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@test_reference joinpath("references", "generate_section_$theme.txt") generate(sec, templates) by=ignore_CR

page = DemoPage(joinpath(root, "page", "default"))
@test_reference joinpath("references", "generate_page_$theme.txt") generate(page, templates) by=ignore_CR
@test_reference joinpath("references", "generate_page_$theme.txt") generate(page, templates) by=ignore_all
end

abs_root = joinpath(pwd(), root, "page", "default")
Expand All @@ -26,7 +26,7 @@
page_dir = @suppress_err preview_demos(joinpath(root, "page", "hidden"); theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
# test only one card is shown in index.md
@test_reference joinpath("references", "hidden_index.txt") read(md_index, String)
@test_reference joinpath("references", "hidden_index.txt") read(md_index, String) by=ignore_all

# check that assets are still normally generated even if they are hidden from index.md
@test readdir(page_dir) == ["covers", "index.md", "sec"]
Expand Down
12 changes: 6 additions & 6 deletions test/preview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@testset "page structure" begin
page_dir = @suppress_err preview_demos(joinpath(abs_root, "page", "template"), theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
@test_reference joinpath("references", "preview", "index_page.md") read(md_index, String) by=ignore_CR
@test_reference joinpath("references", "preview", "index_page.md") read(md_index, String) by=ignore_all

@test readdir(page_dir) == ["covers", "index.md", "subsection_1", "subsection_2"]
@test readdir(joinpath(page_dir, "subsection_2")) == ["card_3.md", "card_4.md"]
Expand All @@ -20,7 +20,7 @@
@testset "section with non page structure" begin
page_dir = @suppress_err preview_demos(joinpath(abs_root, "preview", "scripts"), theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
@test_reference joinpath("references", "preview", "index_sec_nopage.md") read(md_index, String) by=ignore_CR
@test_reference joinpath("references", "preview", "index_sec_nopage.md") read(md_index, String) by=ignore_all

@test readdir(page_dir) == ["assets", "covers", "index.md", "scripts"]
@test readdir(joinpath(page_dir, "covers")) == ["demo2.svg", "democards_logo.svg"]
Expand All @@ -30,7 +30,7 @@
@testset "section with page structure" begin
page_dir = @suppress_err preview_demos(joinpath(abs_root, "page", "template", "subsection_2"), theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
@test_reference joinpath("references", "preview", "index_sec_page.md") read(md_index, String) by=ignore_CR
@test_reference joinpath("references", "preview", "index_sec_page.md") read(md_index, String) by=ignore_all

@test readdir(page_dir) == ["covers", "index.md", "subsection_2"]
@test readdir(joinpath(page_dir, "subsection_2")) == ["card_3.md", "card_4.md"]
Expand All @@ -43,7 +43,7 @@
@testset "file with non page structure" begin
page_dir = @suppress_err preview_demos(joinpath(abs_root, "preview", "scripts", "demo2.md"), theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
@test_reference joinpath("references", "preview", "index_file.md") read(md_index, String) by=ignore_CR
@test_reference joinpath("references", "preview", "index_file.md") read(md_index, String) by=ignore_all

@test readdir(page_dir) == ["assets", "covers", "index.md", "scripts"]
@test readdir(joinpath(page_dir, "covers")) == ["demo2.svg"]
Expand All @@ -52,7 +52,7 @@

page_dir = @suppress_err preview_demos(joinpath(abs_root, "preview_demo1.jl"), theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
@test_reference joinpath("references", "preview", "index_file2.md") read(md_index, String) by=ignore_CR
@test_reference joinpath("references", "preview", "index_file2.md") read(md_index, String) by=ignore_all

@test readdir(page_dir) == ["covers", "index.md", "preview_section"]
@test readdir(joinpath(page_dir, "covers")) == ["democards_logo.svg"]
Expand All @@ -62,7 +62,7 @@
@testset "file with page structure" begin
page_dir = @suppress_err preview_demos(joinpath(abs_root, "page", "template", "subsection_2", "card_3.md"), theme="grid", require_html=false)
md_index = joinpath(page_dir, "index.md")
@test_reference joinpath("references", "preview", "index_file_page.md") read(md_index, String) by=ignore_CR
@test_reference joinpath("references", "preview", "index_file_page.md") read(md_index, String) by=ignore_all

@test readdir(page_dir) == ["covers", "index.md", "subsection_2"]
@test readdir(joinpath(page_dir, "subsection_2")) == ["card_3.md"]
Expand Down
4 changes: 4 additions & 0 deletions test/references/cards/julia_md.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/card/julia/title_7.jl"
```

# [Custom Title](@id custom_id)

[![Source code](https://img.shields.io/badge/download-julia-brightgreen.svg)](title_7.jl) ![compat](https://img.shields.io/badge/julia-1.2.3-blue.svg) ![Author](https://img.shields.io/badge/Author-Jane%20Doe-blue) ![Author](https://img.shields.io/badge/Author-John%20Roe-blue) ![Update time](https://img.shields.io/date/1580428800)
Expand Down
4 changes: 4 additions & 0 deletions test/references/cards/markdown.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/card/markdown/title_6.md"
```

# [Custom Title](@id custom_id)
![Author](https://img.shields.io/badge/Author-Jane%20Doe-blue) ![Author](https://img.shields.io/badge/Author-John%20Roe-blue) ![Update time](https://img.shields.io/date/1580428800)

Expand Down
4 changes: 4 additions & 0 deletions test/references/generate_page_grid.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "assets/page/default/index.md"
```

# Default

# Subsection 1
Expand Down
4 changes: 4 additions & 0 deletions test/references/hidden_index.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/hidden/index.md"
```

# Hidden

# Sec
Expand Down
4 changes: 4 additions & 0 deletions test/references/preview/index_file.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/preview/index.md"
```

# Preview

# Scripts
Expand Down
4 changes: 4 additions & 0 deletions test/references/preview/index_file2.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/preview_page/index.md"
```

# Preview page

# Preview section
Expand Down
4 changes: 4 additions & 0 deletions test/references/preview/index_file_page.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/template/template.md"
```

# Template

# Subsection 2
Expand Down
4 changes: 4 additions & 0 deletions test/references/preview/index_page.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/template/template.md"
```

# [Custom Title](@id custom_id)

This is the content of the template
Expand Down
4 changes: 4 additions & 0 deletions test/references/preview/index_sec_nopage.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/preview/index.md"
```

# Preview

# Scripts
Expand Down
4 changes: 4 additions & 0 deletions test/references/preview/index_sec_page.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
```@meta
EditURL = "/tmp/jl_MynnRG/template/template.md"
```

# Template

# Subsection 2
Expand Down
28 changes: 28 additions & 0 deletions test/testutils.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
"""
This function combines `ignore_CR` with ignoring difference between `ref` and
`actual` resulting from blank lines.
"""
ignore_all(ref::AbstractString, actual::AbstractString) = isequal(_ignore_all(ref), _ignore_all(actual))

_ignore_all(x::AbstractString) = _ignore_tempdir(_ignore_blank_line_and_CR(_ignore_CR(x)))

const edit_url_re = r"EditURL = \"(.*)\""

function _ignore_tempdir(doc::AbstractString)
path_match = match(edit_url_re, doc)
if path_match === nothing
return doc
end
path = path_match[1]
if !startswith(path, "/") && match(r"^[A-Z]:", path) === nothing
return doc
end
bits = split(replace(path, "\\" => "/"), "/")
tmp_dir = findlast(x -> startswith(x, "jl_"), bits)
if tmp_dir === nothing
error("Cannot find tempdir in $path")
end
norm_dir = "/TEMPDIR/" * join(bits[end+1:end], "/")
return replace(doc, edit_url_re => "EditURL = \"$norm_dir\"")
end

"""
This function combines `ignore_CR` with ignoring difference between `ref` and
`actual` resulting from blank lines.
Expand Down
4 changes: 2 additions & 2 deletions test/types/julia.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@
replace(contents, r"\[!\[notebook\]\(.*\)\]\(.*\.ipynb\) " => "")
end
isempty(DemoCards.get_nbviewer_root_url("master")) || println(read(joinpath(card_dir, "title_7.md"), String)) # for debug usage
@test_reference joinpath(test_root, "references", "cards", "julia_md.md") strip_notebook(read(joinpath(card_dir, "title_7.md"), String)) by=ignore_CR
@test_reference joinpath(test_root, "references", "cards", "julia_src.jl") read(joinpath(card_dir, "title_7.jl"), String) by=ignore_blank_line_and_CR
@test_reference joinpath(test_root, "references", "cards", "julia_md.md") strip_notebook(read(joinpath(card_dir, "title_7.md"), String)) by=ignore_all
@test_reference joinpath(test_root, "references", "cards", "julia_src.jl") read(joinpath(card_dir, "title_7.jl"), String) by=ignore_all
@test isfile(joinpath(card_dir, "title_7.ipynb"))

# check if notebook keyword actually affects the generation
Expand Down
2 changes: 1 addition & 1 deletion test/types/markdown.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
@testset "generate" begin
page_dir = @suppress_err preview_demos("title_6.md", theme="grid", require_html=false)
card_path = joinpath(page_dir, "markdown", "title_6.md")
@test_reference joinpath(test_root, "references", "cards", "markdown.md") read(card_path, String) by=ignore_CR
@test_reference joinpath(test_root, "references", "cards", "markdown.md") read(card_path, String) by=ignore_all
end
end
end
Loading

0 comments on commit 040f178

Please sign in to comment.