Avoid an unstyled rendering moment with the tables of contents

Tables of contents are now statically rendered in their appropriately
open/closed states, rather than updated via JavaScript, so they render
correctly on the first page load. In order to make the "page sections"
table still usable without JS, this adds a stylesheet in a <noscript>
tag that forces the sections into an open state.
This commit is contained in:
Natalie Weizenbaum 2019-04-12 00:01:56 -07:00
parent ce9244b504
commit e7ffef4fc9
7 changed files with 62 additions and 37 deletions

View File

@ -58,12 +58,11 @@ before_render do |body, page, _, template_class|
if current_page.data.table_of_contents &&
template_class == Middleman::Renderers::RedcarpetTemplate
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC.new)
toc = markdown.render(body).sub(/<ul( |>)/, '<ul class="table-of-contents"\1')
fragment = Nokogiri::HTML::DocumentFragment.parse(markdown.render(body))
# The JS API's header names are uniquely large and difficult to break up
# effectively. We do some post-processing to clean them up.
if page.start_with?("js-api.")
fragment = Nokogiri::HTML::DocumentFragment.parse(toc)
fragment.css("a code").each do |code|
code.content = code.content.
gsub(/^types\.[A-Za-z]+\./, '').
@ -71,10 +70,18 @@ before_render do |body, page, _, template_class|
gsub(/^new types\./, 'new ').
gsub(/\(.+\)$/, '()')
end
toc = fragment.to_html
end
current_page.add_metadata(table_of_contents: toc)
# Modify the default Markdown table of contents to have overview links and
# section classes.
fragment.css("li > ul").each do |ul|
a = ul.parent.elements.first
a.add_class("section")
ul.elements.before('<li class="overview"><a>Overview</a></li>')
ul.elements.first.elements.first['href'] = a['href']
end
current_page.add_metadata(table_of_contents: fragment.to_html)
body
end
end

View File

@ -52,21 +52,34 @@ module SassHelpers
end
def documentation_toc
_toc_level(data.documentation.toc)
_toc_level(nil, data.documentation.toc)
end
def _toc_level(links)
content_tag(:ul, links.map do |link|
children = link[:children]
text = link.keys.reject {|k| k == :children}.first
href = link[text]
def _toc_level(parent_href, links)
if parent_href
overview = content_tag(:li,
content_tag(:a, "Overview", href: parent_href,
class: ("selected" if current_page.url == parent_href + ".html")),
class: "overview")
end
content_tag(:li, [
content_tag(:a, text, href: href,
class: ("open selected" if current_page.url.start_with?(href))),
(_toc_level(children) if children)
].compact)
end)
content_tag(:ul, [
overview,
*links.map do |link|
children = link[:children]
text = link.keys.reject {|k| k == :children}.first
href = link[text]
content_tag(:li, [
content_tag(:a, text, href: href,
class: [
("section" if children),
("open selected" if current_page.url.start_with?(href))
].compact.join(" ")),
(_toc_level(href, children) if children)
].compact)
end
].compact)
end
# Renders a code example.

View File

@ -51,14 +51,15 @@
width: 100%;
&:hover { background-color: $sl-color--dawn-pink; }
&.overview {
font-size: $sl-font-size--small;
&:not(.selected) { color: transparentize($sl-color--midnight-blue, 0.5); }
}
}
li.overview a {
font-size: $sl-font-size--small;
&:not(.selected) { color: transparentize($sl-color--midnight-blue, 0.5); }
}
li a {
&:not([href]) {
&.section {
&::after {
content: "";
float: right;
@ -77,7 +78,7 @@
&.selected {
font-weight: bold;
&[href] { background-color: $sl-color--dawn-pink; }
&:not(.section) { background-color: $sl-color--dawn-pink; }
}
}
}

View File

@ -0,0 +1,10 @@
// Styles that are included only when JavaScript is disabled. These override the
// default styles to make them work better without JS.
// Make the in-page table of contents fully open by default, since we can't
// dynamically expand it.
.page-sections li a.section {
&::after { transform: rotate(90deg); }
+ ul {display: block; }
}

View File

@ -115,18 +115,11 @@ $(function() {
$(function() {
$(".sl-c-list-navigation-wrapper--collapsible li > ul")
.parent().children("a").each(function() {
var overview = $('<li><a class="overview">Overview</a></li>\n');
var link = overview.children().first().attr("href", $(this).attr("href"));
if ($(this).hasClass("selected") &&
link[0].pathname == window.location.pathname) {
link.addClass("selected");
}
$(this).parent().children("ul").prepend(overview);
$(this).removeAttr("href");
}).click(function() {
$(this).toggleClass("open");
});
.parent()
.children("a")
.removeAttr("href")
.click(function() {
$(this).toggleClass("open");
return false;
});
});

View File

@ -11,6 +11,7 @@
= stylesheet_link_tag 'https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css'
= stylesheet_link_tag 'sass'
= yield_content :css
%noscript= stylesheet_link_tag 'noscript'
-# Old version of analytics (https://developers.google.com/analytics/devguides/collection/gajs/).
:javascript

View File

@ -8,5 +8,5 @@
- content_for :complementary do
%h3 Page Sections
%nav.sl-c-list-navigation-wrapper.sl-c-list-navigation-wrapper--collapsible
%nav.page-sections.sl-c-list-navigation-wrapper.sl-c-list-navigation-wrapper--collapsible
= current_page.metadata[:table_of_contents]