From 6d4d01a2b9578ba7ae53168c27e03fe68a414729 Mon Sep 17 00:00:00 2001 From: Charlie Hewitt Date: Wed, 11 Nov 2020 08:18:23 +0000 Subject: [PATCH] Add support for Azure DevOps repos (#1471) --- CHANGELOG.md | 5 +++++ src/Documenter.jl | 6 ++++-- src/Utilities/Utilities.jl | 36 ++++++++++++++++++++++++++++-------- src/Writers/HTMLWriter.jl | 7 +++++-- test/utilities.jl | 18 ++++++++++++++++++ 5 files changed, 60 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32f64d5940..9c0cc4413c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * ![Enhancement][badge-enhancement] The search page in the HTML output now shows the page titles in the search results. ([#1468][github-1468]) +* ![Enhancement][badge-enhancement] Documenter now support Azure DevOps Repos URL scheme when generating edit and source links pointing to the repository. ([#1462][github-1462], [#1463][github-1463], [#1471][github-1471]) + ## Version `v0.25.3` * ![Feature][badge-feature] Documenter can now deploy from GitLab CI to GitHub Pages with `Documenter.GitLab`. ([#1448][github-1448]) @@ -677,7 +679,10 @@ [github-1448]: https://github.com/JuliaDocs/Documenter.jl/pull/1448 [github-1440]: https://github.com/JuliaDocs/Documenter.jl/pull/1440 [github-1452]: https://github.com/JuliaDocs/Documenter.jl/pull/1452 +[github-1462]: https://github.com/JuliaDocs/Documenter.jl/issues/1462 +[github-1463]: https://github.com/JuliaDocs/Documenter.jl/pull/1463 [github-1468]: https://github.com/JuliaDocs/Documenter.jl/pull/1468 +[github-1471]: https://github.com/JuliaDocs/Documenter.jl/pull/1471 [julia-38079]: https://github.com/JuliaLang/julia/issues/38079 diff --git a/src/Documenter.jl b/src/Documenter.jl index fe5594142a..7c1d45317d 100644 --- a/src/Documenter.jl +++ b/src/Documenter.jl @@ -154,10 +154,12 @@ value of the generated link: - `{path}` Path to the file in the repository - `{line}` Line (or range of lines) in the source file -For example if you are using GitLab.com, you could use +BitBucket, GitLab and Azure DevOps are supported along with GitHub, for example: ```julia -makedocs(repo = \"https://gitlab.com/user/project/blob/{commit}{path}#{line}\") +makedocs(repo = \"https://gitlab.com/user/project/blob/{commit}{path}#{line}\") # GitLab +makedocs(repo = \"https://dev.azure.com/org/project/_git/repo?path={path}&version={commit}{line}&lineStartColumn=1&lineEndColumn=1\") # Azure DevOps +makedocs(repo = \"https://bitbucket.org/user/project/src/{commit}/{path}#lines-{line}\") # BitBucket ``` **`highlightsig`** enables or disables automatic syntax highlighting of leading, unlabeled diff --git a/src/Utilities/Utilities.jl b/src/Utilities/Utilities.jl index 2857740239..a08fb0aaa1 100644 --- a/src/Utilities/Utilities.jl +++ b/src/Utilities/Utilities.jl @@ -343,6 +343,10 @@ function repo_root(file; dbdir=".git") return nothing end +# Repository hosts +# RepoUnknown denotes that the repository type could not be determined automatically +@enum RepoHost RepoGithub RepoBitbucket RepoGitlab RepoAzureDevOps RepoUnknown + """ $(SIGNATURES) @@ -362,6 +366,19 @@ function repo_commit(file) end end +function format_commit(commit::AbstractString, host::RepoHost) + if host === RepoAzureDevOps + # if commit hash then preceeded by GC, if branch name then preceeded by GB + if match(r"[0-9a-fA-F]{40}", commit) !== nothing + commit = "GC$commit" + else + commit = "GB$commit" + end + else + return commit + end +end + function url(repo, file; commit=nothing) file = abspath(file) if !isfile(file) @@ -375,7 +392,8 @@ function url(repo, file; commit=nothing) if path === nothing nothing else - repo = replace(repo, "{commit}" => commit === nothing ? repo_commit(file) : commit) + hosttype = repo_host_from_url(repo) + repo = replace(repo, "{commit}" => format_commit(commit === nothing ? repo_commit(file) : commit, hosttype)) # Note: replacing any backslashes in path (e.g. if building the docs on Windows) repo = replace(repo, "{path}" => string("/", replace(path, '\\' => '/'))) repo = replace(repo, "{line}" => "") @@ -395,8 +413,10 @@ function url(remote, repo, mod, file, linerange) file = realpath(abspath(file)) end + hosttype = repo_host_from_url(repo) + # Format the line range. - line = format_line(linerange, LineRangeFormatting(repo_host_from_url(repo))) + line = format_line(linerange, LineRangeFormatting(hosttype)) # Macro-generated methods such as those produced by `@deprecate` list their file as # `deprecated.jl` since that is where the macro is defined. Use that to help # determine the correct URL. @@ -418,7 +438,7 @@ function url(remote, repo, mod, file, linerange) if path === nothing nothing else - repo = replace(repo, "{commit}" => repo_commit(file)) + repo = replace(repo, "{commit}" => format_commit(repo_commit(file), hosttype)) # Note: replacing any backslashes in path (e.g. if building the docs on Windows) repo = replace(repo, "{path}" => string("/", replace(path, '\\' => '/'))) repo = replace(repo, "{line}" => line) @@ -464,10 +484,6 @@ function inbase(m::Module) end end -# Repository hosts -# RepoUnknown denotes that the repository type could not be determined automatically -@enum RepoHost RepoGithub RepoBitbucket RepoGitlab RepoUnknown - # Repository host from repository url # i.e. "https://github.com/something" => RepoGithub # "https://bitbucket.org/xxx" => RepoBitbucket @@ -479,6 +495,8 @@ function repo_host_from_url(repoURL::String) return RepoGithub elseif occursin("gitlab", repoURL) return RepoGitlab + elseif occursin("azure", repoURL) + return RepoAzureDevOps else return RepoUnknown end @@ -505,7 +523,9 @@ struct LineRangeFormatting separator::String function LineRangeFormatting(host::RepoHost) - if host == RepoBitbucket + if host === RepoAzureDevOps + new("&line=", "&lineEnd=") + elseif host == RepoBitbucket new("", ":") elseif host == RepoGitlab new("L", "-") diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index 2ce1295500..c46e776615 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -438,7 +438,7 @@ module RD const requirejs_cdn = "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" const google_fonts = "https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" - const fontawesome_version = "5.11.2" + const fontawesome_version = "5.15.0" const fontawesome_css = [ "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/$(fontawesome_version)/css/fontawesome.min.css", "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/$(fontawesome_version)/css/solid.min.css", @@ -1079,6 +1079,9 @@ function render_navbar(ctx, navnode, edit_page_link::Bool) elseif host_type == Utilities.RepoBitbucket host = "BitBucket" logo = "\uf171" + elseif host_type == Utilities.RepoAzureDevOps + host = "Azure DevOps" + logo = "\uf3ca" # TODO change to ADO logo when added to FontAwesome else host = "" logo = "\uf15c" @@ -1101,7 +1104,7 @@ function render_navbar(ctx, navnode, edit_page_link::Bool) title = "$(edit_verb)$hoststring" push!(navbar_right.nodes, a[".docs-edit-link", :href => url, :title => title]( - span[".docs-icon.fab"](logo), + span[host_type == Utilities.RepoUnknown ? ".docs-icon.fa" : ".docs-icon.fab"](logo), span[".docs-label.is-hidden-touch"](title) ) ) diff --git a/test/utilities.jl b/test/utilities.jl index aa4578a391..973c8e2cec 100644 --- a/test/utilities.jl +++ b/test/utilities.jl @@ -106,6 +106,7 @@ end @test Documenter.Utilities.repo_host_from_url("https://github.com/Whatever") == Documenter.Utilities.RepoGithub @test Documenter.Utilities.repo_host_from_url("https://www.github.com/Whatever") == Documenter.Utilities.RepoGithub @test Documenter.Utilities.repo_host_from_url("https://gitlab.com/Whatever") == Documenter.Utilities.RepoGitlab + @test Documenter.Utilities.repo_host_from_url("https://dev.azure.com/Whatever") == Documenter.Utilities.RepoAzureDevOps # line range let formatting = Documenter.Utilities.LineRangeFormatting(Documenter.Utilities.RepoGithub) @@ -129,8 +130,25 @@ end @test Documenter.Utilities.format_line(100:9999, formatting) == "100:9999" end + let formatting = Documenter.Utilities.LineRangeFormatting(Documenter.Utilities.RepoAzureDevOps) + @test Documenter.Utilities.format_line(1:1, formatting) == "&line=1" + @test Documenter.Utilities.format_line(123:123, formatting) == "&line=123" + @test Documenter.Utilities.format_line(2:5, formatting) == "&line=2&lineEnd=5" + @test Documenter.Utilities.format_line(100:9999, formatting) == "&line=100&lineEnd=9999" + end + @test Documenter.Utilities.linerange(Core.svec(), 0) === 0:0 + # commit format + @test Documenter.Utilities.format_commit("7467441e33e2bd586fb0ec80ed4c4cdef5068f6a", Documenter.Utilities.RepoGithub) == "7467441e33e2bd586fb0ec80ed4c4cdef5068f6a" + @test Documenter.Utilities.format_commit("test", Documenter.Utilities.RepoGithub) == "test" + @test Documenter.Utilities.format_commit("7467441e33e2bd586fb0ec80ed4c4cdef5068f6a", Documenter.Utilities.RepoGitlab) == "7467441e33e2bd586fb0ec80ed4c4cdef5068f6a" + @test Documenter.Utilities.format_commit("test", Documenter.Utilities.RepoGitlab) == "test" + @test Documenter.Utilities.format_commit("7467441e33e2bd586fb0ec80ed4c4cdef5068f6a", Documenter.Utilities.RepoBitbucket) == "7467441e33e2bd586fb0ec80ed4c4cdef5068f6a" + @test Documenter.Utilities.format_commit("test", Documenter.Utilities.RepoBitbucket) == "test" + @test Documenter.Utilities.format_commit("7467441e33e2bd586fb0ec80ed4c4cdef5068f6a", Documenter.Utilities.RepoAzureDevOps) == "GC7467441e33e2bd586fb0ec80ed4c4cdef5068f6a" + @test Documenter.Utilities.format_commit("test", Documenter.Utilities.RepoAzureDevOps) == "GBtest" + # URL building filepath = string(first(methods(Documenter.Utilities.url)).file) Sys.iswindows() && (filepath = replace(filepath, "/" => "\\")) # work around JuliaLang/julia#26424