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

Always use h1 for first heading on a page #3009

Merged
merged 17 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions extra/docs_landing.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@
display: none;
}

#left_col {
display: none;
}

#guide .subnavigation {
top: 00px;
border-bottom: 1px solid var(--color-gray);
Expand Down
128 changes: 0 additions & 128 deletions integtest/spec/single_book_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -314,134 +314,6 @@
end
end

context 'regarding the xpack tag' do
let(:edit_me) do
<<~HTML.strip
<a class="edit_me" rel="nofollow" title="Edit this page on GitHub" href="https://github.com/elastic/docs/edit/master/index.asciidoc">edit</a>
HTML
end
let(:xpack_tag) do
<<~HTML.strip
<a class="xpack_tag" href="/subscriptions"></a>
HTML
end
let(:rx) { %r{<#{h} class="title"><a id="#{id}"></a>(.+?)</#{h}>} }
let(:title_tag) do
return unless body

m = rx.match(body)
raise "Can't find title_tag with #{rx} in #{body}" unless m

m[1]
end
shared_examples 'xpack tag title' do |has_tag|
it 'contains the edit_me link' do
expect(title_tag).to include(edit_me)
end
if has_tag
it 'contains the xpack tag' do
expect(title_tag).to include(xpack_tag)
end
else
it "doesn't contain the xpack tag" do
expect(title_tag).not_to include(xpack_tag)
end
end
end
shared_examples 'part page titles' do |onpart|
page_context 'part.html' do
let(:h) { 'h1' }
let(:id) { 'part' }
include_examples 'xpack tag title', onpart
end
end
shared_examples 'chapter page titles' do |onchapter, onfloater, onsection|
page_context 'chapter.html' do
let(:h) { 'h2' }
context 'the chapter title' do
let(:id) { 'chapter' }
include_examples 'xpack tag title', onchapter
end
context 'the section title' do
let(:id) { 'section' }
include_examples 'xpack tag title', onsection
end
context 'the float title' do
let(:rx) { %r{<h2><a id="floater"></a>(.+?)</h2>} }
include_examples 'xpack tag title', onfloater
end
end
end

def self.xpack_tag_context(onpart, onchapter, onfloater, onsection,
hide_xpack)
convert_single_before_context do |src|
index = xpack_tag_test_asciidoc onpart, onchapter, onfloater, onsection,
hide_xpack
src.write 'index.asciidoc', index
end

include_examples 'part page titles',
onpart && !hide_xpack
include_examples 'chapter page titles', onchapter && !hide_xpack,
onfloater && !hide_xpack, onsection && !hide_xpack
end

def self.xpack_tag_test_asciidoc(onpart, onchapter, onfloater, onsection,
hide_xpack)
<<~ASCIIDOC
= Title

#{hide_xpack ? ':hide-xpack-tags: true' : ''}

#{onpart ? '[role="xpack"]' : ''}
[[part]]
= Part

#{onchapter ? '[role="xpack"]' : ''}
[[chapter]]
== Chapter

Chapter words.

[[floater]]
[float]
== #{onfloater ? '[xpack]#Floater#' : 'Floater'}

Floater words.

#{onsection ? '[role="xpack"]' : ''}
[[section]]
=== Section

Section words.
ASCIIDOC
end

context 'when not hiding xpack tags' do
context 'when the xpack role is on a part' do
xpack_tag_context true, false, false, false, false
end
context 'when the xpack role is on a chapter' do
xpack_tag_context false, true, false, false, false
end
context 'when the xpack role is on a floating title' do
xpack_tag_context false, false, true, false, false
end
context 'when the xpack role is on a section' do
xpack_tag_context false, false, false, true, false
end
context 'when the xpack role is on everything' do
xpack_tag_context true, true, true, true, false
end
end
context 'when hiding xpack tags' do
context 'when the xpack role is on everything' do
xpack_tag_context true, true, true, true, true
end
end
end

context 'for README.asciidoc' do
convert_single_before_context do |src|
root = File.expand_path('../../', __dir__)
Expand Down
2 changes: 1 addition & 1 deletion resources/asciidoctor/lib/chunker/breadcrumbs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def generate_breadcrumbs(doc, section)

update_breadcrumbs_cases(result, chev, doc)

Asciidoctor::Block.new doc, :pass, source: result.join("\n")
result.join("\n")
end

def update_breadcrumbs_cases(result, chev, doc)
Expand Down
28 changes: 23 additions & 5 deletions resources/asciidoctor/lib/chunker/extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ def convert_section(section)
return yield unless section.level <= @chunk_level

html = form_section_into_page doc, section, yield
# Replace the breadcrumbs placeholder with
# the generated breadcrumbs
if html =~ %r{<div id="breadcrumbs-go-here"></div>}
html.gsub!(
%r{<div id="breadcrumbs-go-here"></div>},
generate_breadcrumbs(doc, section).to_s
)
# raise("Couldn't add breadcrumbs in #{html}")
end
write doc, "#{section.id}.html", html
''
end
Expand Down Expand Up @@ -93,12 +102,11 @@ def form_section_into_page(doc, section, html)
# We don't use asciidoctor's "parent" documents here because they don't
# seem to buy us much and they are an "internal" detail.
subdoc = Asciidoctor::Document.new [], subdoc_opts(doc, section)
add_subdoc_sections doc, subdoc, section, html
add_subdoc_sections doc, subdoc, html
subdoc.convert
end

def add_subdoc_sections(doc, subdoc, section, html)
subdoc << generate_breadcrumbs(doc, section)
def add_subdoc_sections(doc, subdoc, html)
nav = Nav.new subdoc
subdoc << nav.header
subdoc << Asciidoctor::Block.new(subdoc, :pass, source: html)
Expand All @@ -121,7 +129,10 @@ def subdoc_opts(doc, section)
def subdoc_attrs(doc, section)
attrs = doc.attributes.dup
maintitle = doc.doctitle partition: true
attrs['doctitle'] = subdoc_title section, maintitle
# Rendered h1 heading
attrs['doctitle'] = subdoc_doctitle section
# Value of `title` in the `head`
attrs['title'] = subdoc_title section, maintitle
# Asciidoctor defaults these attribute to empty string if they aren't
# specified and setting them to `nil` clears them. Since we want to
# preserve the configuration from the parent into the child, we clear
Expand All @@ -130,13 +141,20 @@ def subdoc_attrs(doc, section)
attrs['stylesheet'] = nil unless attrs['stylesheet']
attrs['icons'] = nil unless attrs['icons']
attrs['subdoc'] = true # Mark the subdoc so we don't try and chunk it
attrs['noheader'] = true
attrs['title-separator'] = ''
attrs['canonical-url'] = section.attributes['canonical-url']
attrs.merge! find_related(section)
attrs
end

# For the `h1` heading that appears on the rendered page,
# use just the page title
def subdoc_doctitle(section)
strip_tags section.captioned_title.to_s
end

# For the `title` in the `head`, use the page title followed
# by the site title ("Elastic")
def subdoc_title(section, maintitle)
strip_tags "#{section.captioned_title} | #{maintitle.main}"
end
Expand Down
36 changes: 24 additions & 12 deletions resources/asciidoctor/lib/docbook_compat/convert_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def convert_document(doc)
def munge_html(doc, html, wants_toc)
title = doc.doctitle partition: true
munge_html_tag html
munge_head doc.attr('title-extra'), title, html
munge_head doc.attr('title-extra'), html
munge_body doc, html
munge_title doc, title, html
add_toc doc, html if wants_toc
Expand All @@ -36,17 +36,28 @@ def munge_html_tag(html)
raise("Coudn't fix html in #{html}")
end

def munge_head(title_extra, title, html)
html.gsub!(
%r{<title>.+?</title>}m, <<~HTML
<title>#{strip_tags title.main}#{title_extra} | Elastic</title>
<meta class=\"elastic\" name=\"content\" \
content=\"#{strip_tags title.main}#{title_extra}\">
HTML
) || raise("Couldn't munge <title> in #{html}")
def munge_head(title_extra, html)
if html !~ %r{^<title>([\S\s]+)<\/title>$}m
raise("Couldn't munge <title> in #{html}")
end

html.gsub!(%r{^<title>([\S\s]+)<\/title>$}m) do
add_content_meta Regexp.last_match[1], title_extra
end
munge_meta html
end

def add_content_meta(match, title_extra)
# If multiple lines, get just the first line
clean_title = match.gsub!(/\n[\S\s]+/, '') || match
clean_title = strip_tags clean_title
<<~HTML
<title>#{clean_title}#{title_extra} | Elastic</title>
<meta class=\"elastic\" name=\"content\" \
content=\"#{clean_title}#{title_extra}\">
HTML
end

META_VIEWPORT = <<~HTML
<meta name="viewport" content="width=device-width, initial-scale=1.0">
HTML
Expand All @@ -61,12 +72,14 @@ def munge_meta(html)
end

def munge_title(doc, title, html)
return if doc.attr 'noheader'

# Important: we're not replacing the whole header - it still will have a
# closing </div>.
#
# We also add a placeholder for the breadcrumbs that will be replaced
# in resources/asciidoctor/lib/chunker/extension.rb
header_start = <<~HTML
<div class="titlepage">
<div id="breadcrumbs-go-here"></div>
#{docbook_style_title doc, title}
HTML
html.gsub!(%r{<div id="header">\n<h1>.+?</h1>\n}m, header_start) ||
Expand All @@ -84,7 +97,6 @@ def docbook_style_title(doc, title)
HTML
result + <<~HTML.strip
</div>
<hr>
<!--EXTRA-->
HTML
end
Expand Down
27 changes: 14 additions & 13 deletions resources/asciidoctor/lib/docbook_compat/extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,20 @@ def xpack_tag(node)
end

def hlevel(section)
# Walk up the ancestry until the ancestor's parent is the document. The
# ancestor that we end up with is the "biggest" section containing this
# section. Except don't walk *all* the way. Because docbook doesn't.
# See that `unless` below? If we were walking it should be `until` but
# docbook *doesn't* walk. It just does this. Why? Ghosts maybe. I dunno.
# But we're trying to emulate docbook. So here we are.
ancestor = section
ancestor = ancestor.parent unless ancestor.parent.context == :document
# If *that* section is level 0 then we have to bump the hlevel of our
# section by one. The argument for this goes: we have to bump the level 0
# section's hlevel by one anyway because there *isn't* an h0 tag. So we
# have to bump all of its children.
section.level + (ancestor.level.zero? ? 1 : 0)
# If the heading level is less than 2, use 2,
# otherwise use the given heading level.
#
# This ensures:
# - There are no `h0`s, which are not valid HTML elements.
# - There are no `h1`s in the page's main content since
# we only want one `h1` per page, and one is generated
# automatically and added to the page header (outside
# div#content).
if section.level < 2
2
else
section.level
end
end

SECTION_WRAPPER_CLASSES = %w[part chapter].freeze
Expand Down
Loading