Skip to content

Commit

Permalink
feat: mega dropdown nave
Browse files Browse the repository at this point in the history
and switch to htl for internals
  • Loading branch information
pfitzseb committed Oct 11, 2022
1 parent 21a3098 commit fac91ae
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 143 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.2.0"
[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Gumbo = "708ec375-b3d6-5a57-a7ce-8257bf98657a"
HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
NodeJS = "2bd173c7-0d6d-553b-b6af-13a54713934c"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Expand Down
37 changes: 33 additions & 4 deletions assets/default/multidoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ html {
text-transform: uppercase;
}

#multi-page-nav .nav-dropdown .dropdown-label::after {
#multi-page-nav .dropdown-label::after {
content: "";
margin-left: 5px;

Expand Down Expand Up @@ -99,10 +99,32 @@ html {
background-color: #282f2f;
}

#multi-page-nav .nav-dropdown.nav-expanded .nav-dropdown-container {
#multi-page-nav .nav-expanded .nav-dropdown-container {
display: block;
}

#multi-page-nav .nav-mega-dropdown-container {
width: 100vw;
left: 0;
padding: 1em 2em;
border-radius: 0;
border: none;
flex-wrap: wrap;
}

#multi-page-nav .nav-mega-dropdown-container .nav-mega-column {
margin: 0 2em;
}

#multi-page-nav .nav-mega-dropdown-container .column-header {
color: #fff;
text-transform: uppercase;
}

#multi-page-nav .nav-expanded .nav-mega-dropdown-container {
display: flex;
}

#multi-page-nav .nav-dropdown-container a.nav-link {
color: #ccc;
line-height: 30px;
Expand All @@ -129,8 +151,6 @@ html {
font-weight: bold;
}

/* Search */

/* Documenter css tweaks */

#documenter .docs-main header.docs-navbar {
Expand Down Expand Up @@ -201,6 +221,15 @@ html {
margin-bottom: 1em;
}

#multi-page-nav .nav-mega-dropdown-container {
width: unset;
padding: 1em;
}

#multi-page-nav .nav-mega-dropdown-container .nav-mega-column {
margin: 0 1em;
}

#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom {
top: -100vh;
}
Expand Down
16 changes: 12 additions & 4 deletions assets/multidoc_injector.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@ require(["jquery"], function ($) {
.getElementById("nav-items")
.classList.toggle("hidden-on-mobile");
});
Array.prototype.map.call(document.getElementsByClassName("dropdown-label"), function (el) {
el.addEventListener("click", function () {
el.parentElement.classList.toggle("nav-expanded")
document.body.addEventListener("click", function (ev) {
console.log(ev)
if (!ev.target.matches(".nav-dropdown-container")) {
console.log("closing")
Array.prototype.forEach.call(document.getElementsByClassName("dropdown-label"), function (el) {
el.parentElement.classList.remove("nav-expanded")
});
}
if (ev.target.matches(".dropdown-label")) {
console.log("opening")
ev.target.parentElement.classList.add("nav-expanded")
}
})
})
});
});
119 changes: 31 additions & 88 deletions src/MultiDocumenter.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module MultiDocumenter

import Gumbo, AbstractTrees
using HypertextLiteral

"""
SearchConfig(index_versions = ["stable"], engine = MultiDocumenter.FlexSearch)
Expand Down Expand Up @@ -35,6 +36,16 @@ struct DropdownNav
children::Vector{MultiDocRef}
end

struct Column
name
children::Vector{MultiDocRef}
end

struct MegaDropdownNav
name
columns::Vector{Column}
end

struct BrandImage
path::String
imagepath::String
Expand All @@ -58,6 +69,7 @@ function walk_outputs(f, root, docs::Vector{MultiDocRef}, dirs::Vector{String})
end
end

include("renderers.jl")
include("search/flexsearch.jl")
include("search/stork.jl")

Expand Down Expand Up @@ -137,6 +149,12 @@ function flatten_multidocrefs(docs::Vector)
for doc in docs
if doc isa MultiDocRef
push!(out, doc)
elseif doc isa MegaDropdownNav
for col in doc.columns
for doc in col.children
push!(out, doc)
end
end
else
for doc in doc.children
push!(out, doc)
Expand All @@ -160,7 +178,7 @@ function make_output_structure(docs::Vector{MultiDocRef}, prettyurls)

for doc in docs
outpath = joinpath(dir, doc.path)
cp(doc.upstream, outpath)
cp(doc.upstream, outpath; force = true)

gitpath = joinpath(outpath, ".git")
if isdir(gitpath)
Expand All @@ -181,32 +199,6 @@ function make_output_structure(docs::Vector{MultiDocRef}, prettyurls)
return dir
end

function insert_multidocref_html!(navitems, doc, dir, thispagepath, prettyurls)
path = joinpath(dir, doc.path)
if !isfile(joinpath(path, "index.html"))
stable = joinpath(path, "stable")
dev = joinpath(path, "dev")
if isfile(joinpath(stable, "index.html"))
path = stable
elseif isfile(joinpath(dev, "index.html"))
path = dev
end
end
rp = relpath(path, thispagepath)
a = Gumbo.HTMLElement{:a}(
[],
navitems,
Dict(
"href" => string(rp, prettyurls ? "/" : "/index.html"),
"class" =>
startswith(thispagepath, joinpath(dir, doc.path, "")) ? # need to force a trailing pathsep here
"nav-link active nav-item" : "nav-link nav-item",
),
)
push!(a.children, Gumbo.HTMLText(a, doc.name))
push!(navitems.children, a)
end

function make_global_nav(
dir,
docs::Vector,
Expand All @@ -215,67 +207,18 @@ function make_global_nav(
search_engine,
prettyurls,
)
nav = Gumbo.HTMLElement{:nav}([], Gumbo.NullNode(), Dict("id" => "multi-page-nav"))

if brand_image !== nothing
a = Gumbo.HTMLElement{:a}(
[],
nav,
Dict(
"class" => "brand",
"href" => relpath(joinpath(dir, brand_image.path), thispagepath),
),
)
img = Gumbo.HTMLElement{:img}(
[],
a,
Dict(
"src" => relpath(joinpath(dir, brand_image.imagepath), thispagepath),
"alt" => "Home",
),
)
push!(a.children, img)
push!(nav.children, a)
end

navitems = Gumbo.HTMLElement{:div}(
[],
nav,
Dict("id" => "nav-items", "class" => "hidden-on-mobile"),
)
push!(nav.children, navitems)

for doc in docs
if doc isa MultiDocRef
insert_multidocref_html!(navitems, doc, dir, thispagepath, prettyurls)
else # doc isa DropdownNav
div = Gumbo.HTMLElement{:div}(
[],
navitems,
Dict("class" => "nav-dropdown"),
)
span = Gumbo.HTMLElement{:span}([], div, Dict("class" => "nav-item dropdown-label"))
push!(div.children, span)
push!(span.children, Gumbo.HTMLText(div, doc.name))
ul = Gumbo.HTMLElement{:ul}([], div, Dict("class" => "nav-dropdown-container"))
push!(div.children, ul)
push!(navitems.children, div)

for doc in doc.children
li = Gumbo.HTMLElement{:li}([], ul, Dict())
insert_multidocref_html!(li, doc, dir, thispagepath, prettyurls)
push!(ul.children, li)
end
end
end
if search_engine != false
search_engine.engine.inject_html!(navitems)
end

toggler = Gumbo.HTMLElement{:a}([], nav, Dict("id" => "multidoc-toggler"))
push!(nav.children, toggler)

return nav
nav = @htl """
<nav id="multi-page-nav">
$(render(brand_image, dir, thispagepath))
<div id="nav-items" class="hidden-on-mobile">
$([render(doc, dir, thispagepath, prettyurls) for doc in docs])
$(search_engine.engine.render())
</div>
<a id="multidoc-toggler"></a>
</nav>
"""

return htl_to_gumbo(nav)
end

function make_global_stylesheet(custom_stylesheets, path)
Expand Down
65 changes: 65 additions & 0 deletions src/renderers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
render(::Nothing, args...) = nothing

function render(brand_image::BrandImage, dir, thispagepath)
return @htl """
<a class="brand" href="$(relpath(joinpath(dir, brand_image.path), thispagepath))">
<img src="$(relpath(joinpath(dir, brand_image.imagepath), thispagepath))" alt="home">
</a>"""
end

function render(doc::MultiDocRef, dir, thispagepath, prettyurls)
path = joinpath(dir, doc.path)
if !isfile(joinpath(path, "index.html"))
stable = joinpath(path, "stable")
dev = joinpath(path, "dev")
if isfile(joinpath(stable, "index.html"))
path = stable
elseif isfile(joinpath(dev, "index.html"))
path = dev
end
end
rp = relpath(path, thispagepath)
href = string(rp, prettyurls ? "/" : "/index.html")
# need to force a trailing pathsep here
class = startswith(thispagepath, joinpath(dir, doc.path, "")) ?
"nav-link active nav-item" : "nav-link nav-item"

return @htl """
<a href="$href" class="$class">$(doc.name)</a>
"""
end

function render(doc::DropdownNav, dir, thispagepath, prettyurls)
return @htl """
<div class="nav-dropown">
<span class="nav-item dropdown-label">$(doc.name)</span>
<ul class="nav-dropdown-container">
$([render(doc, dir, thispagepath, prettyurls) for doc in doc.children])
</ul>
</div>
"""
end

function render(doc::MegaDropdownNav, dir, thispagepath, prettyurls)
return @htl """
<div class="nav-dropown">
<span class="nav-item dropdown-label">$(doc.name)</span>
<div class="nav-dropdown-container nav-mega-dropdown-container">
$([render(doc, dir, thispagepath, prettyurls) for doc in doc.columns])
</div>
</div>
"""
end

function render(doc::Column, dir, thispagepath, prettyurls)
return @htl """
<div class="nav-mega-column">
<h5 class="column-header">$(doc.name)</h5>
<ul class="column-content">
$([render(doc, dir, thispagepath, prettyurls) for doc in doc.children])
</ul>
</div>
"""
end

htl_to_gumbo(htl) = Gumbo.parsehtml(sprint(show, htl)).root.children[2].children[1]
32 changes: 10 additions & 22 deletions src/search/flexsearch.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module FlexSearch
import Gumbo, JSON, AbstractTrees, NodeJS
using HypertextLiteral
import ..walk_outputs

const ID = Ref(0)
Expand Down Expand Up @@ -101,28 +102,15 @@ function inject_styles!(custom_styles)
pushfirst!(custom_styles, joinpath("assets", "default", "flexsearch.css"))
end

function inject_html!(parent)
div = Gumbo.HTMLElement{:div}([], parent, Dict("class" => "search nav-item"))
push!(parent.children, div)
input = Gumbo.HTMLElement{:input}(
[],
div,
Dict("id" => "search-input", "placeholder" => "Search..."),
)
push!(div.children, input)
suggestions = Gumbo.HTMLElement{:ul}(
[],
div,
Dict("id" => "search-result-container", "class" => "suggestions hidden"),
)
push!(div.children, suggestions)
keybinding = Gumbo.HTMLElement{:div}(
[],
div,
Dict("class" => "search-keybinding"),
)
push!(keybinding.children, Gumbo.HTMLText(keybinding, "/"))
push!(div.children, keybinding)
function render()
return @htl """
<div class="search nav-item">
<input id="search-input" placeholder="Search...">
<ul id="search-result-container" class="suggestions hidden">
</ul>
<div class="search-keybinding"></div>
</div>
"""
end

function to_json_index(index::SearchIndex, file)
Expand Down
Loading

0 comments on commit fac91ae

Please sign in to comment.