Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrocatively generate warning for outdated docs #51

Merged
merged 13 commits into from
Jun 6, 2021
4 changes: 4 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ uuid = "35a29f4d-8980-5a13-9543-d66fff28ecb8"
version = "0.1.10"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FileWatching = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
Gumbo = "708ec375-b3d6-5a57-a7ce-8257bf98657a"
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
Sass = "322a6be2-4ae8-5d68-aaf1-3e960788d1d9"

[compat]
AbstractTrees = "0.3"
DocStringExtensions = "0.7, 0.8"
Documenter = "0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26"
Gumbo = "0.7, 0.8"
Sass = "0.1, 0.2"
julia = "1"

Expand Down
1 change: 1 addition & 0 deletions src/DocumenterTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,6 @@ end
include("genkeys.jl")
include("Generator.jl")
include("Themes.jl")
include("OutdatedWarning.jl")

end # module
175 changes: 175 additions & 0 deletions src/OutdatedWarning.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
module OutdatedWarning
pfitzseb marked this conversation as resolved.
Show resolved Hide resolved

using Gumbo, AbstractTrees, Documenter

OLD_VERSION_CSS = replace("""
.outdated-warning-overlay {
position: fixed;
width: 100%;
top: 0;
left: 0;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 999;
background-color: #ffaba7;
color: rgba(0, 0, 0, 0.7);
border-bottom: 3px solid #da0b00;
padding: 10px 35px;
text-align: center;
font-size: 15px; }
.outdated-warning-overlay .outdated-warning-closer {
position: absolute;
top: calc(50% - 10px);
right: 18px;
cursor: pointer;
width: 12px; }
.outdated-warning-overlay a {
color: #2e63b8; }
.outdated-warning-overlay a:hover {
color: #363636; }
""", '\n' => "")

OUTDATED_VERSION_ATTR = isdefined(Documenter.Writers.HTMLWriter, :OUTDATED_VERSION_ATTR) ?
Documenter.Writers.HTMLWriter.OUTDATED_VERSION_ATTR : "data-outdated-warner"

OLD_VERSION_WARNER = """
function maybeAddWarning () {
const head = document.getElementsByTagName('head')[0];

// Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs.
if (document.body.querySelector('meta[name="robots"]') === null) {
const meta = document.createElement('meta');
meta.name = 'robots';
meta.content = 'noindex';

head.appendChild(meta);
};

// Add a stylesheet to avoid inline styling
const style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode('$(OLD_VERSION_CSS)'));
head.appendChild(style);

const div = document.createElement('div');
div.classList.add('outdated-warning-overlay');
const closer = document.createElement('div');
closer.classList.add('outdated-warning-closer');

// Icon by font-awesome (license: https://fontawesome.com/license, link: https://fontawesome.com/icons/times?style=solid)
closer.innerHTML = '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" class="svg-inline--fa fa-times fa-w-11" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path fill="currentColor" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg>';
closer.addEventListener('click', function () {
document.body.removeChild(div);
});
let href = '/stable';
if (window.documenterBaseURL) {
href = window.documenterBaseURL + '/../stable';
}
div.innerHTML = 'This is an old version of the documentation. <br> <a href="' + href + '">Go to the newest version</a>.';
div.appendChild(closer);
document.body.appendChild(div);
};

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', maybeAddWarning);
} else {
maybeAddWarning();
};
"""

function add_old_docs_notice(index, force = false)
html = read(index, String)
parsed = Gumbo.parsehtml(html)

for el in PreOrderDFS(parsed.root)
if el isa HTMLElement && Gumbo.tag(el) == :head
old_notice = get_notice(el)

if old_notice === nothing
push!(el.children, make_notice(el))
elseif force
update_notice(old_notice)
end

break
end
end

open(string(index), "w") do io
print(io, parsed)
end
end

function make_notice(parent)
script = Gumbo.HTMLElement{:script}([], parent, Dict(OUTDATED_VERSION_ATTR => ""))
content = Gumbo.HTMLText(script, OLD_VERSION_WARNER)
push!(script.children, content)
return script
end

function update_notice(script)
content = Gumbo.HTMLText(script, OLD_VERSION_WARNER)
empty!(script.children)
push!(script.children, content)
return script
end

function get_notice(html)
for el in PreOrderDFS(html)
if el isa HTMLElement && Gumbo.tag(el) == :script
attrs = Gumbo.attrs(el)
if haskey(attrs, OUTDATED_VERSION_ATTR)
return el
end
end
end
return nothing
end

"""
generate([io::IO = stdout,] root::String; latest = "stable", force = false)

This function adds a warning (and `noindex` meta tag) to all versions of
the documentation in `root` except for `latest`.

`force` overwrites a previous injected warning message created by this function.

A typical use case is to run this on the `gh-pages` branch of a packge.
"""
generate(root::String; kwargs...) = generate(stdout, root; kwargs...)
function generate(io::IO, root::String; latest = "stable", force = false)
latest = joinpath(root, latest)
while islink(latest)
latest = joinpath(root, readlink(latest))
end

for dir in readdir(root)
path = joinpath(root, dir)
islink(path) && continue
isdir(path) || continue
index = joinpath(path, "index.html")
isfile(index) || continue

if endswith(path, "dev")
println(io, "Skipping $(dir) since it's a dev version.")
continue
end

if path == latest
println(io, "Skipping $(dir) since it's the latest version.")
else
print(io, "Processing $(dir): ")
for (root, _, files) in walkdir(path)
for file in files
_, ext = splitext(file)
if ext == ".html"
print(io, ".")
add_old_docs_notice(joinpath(root, file), force)
end
end
end
println(io)
end
end
end

end