Skip to content

Commit

Permalink
TRG-128 - Generate Table of Content links as relative links.
Browse files Browse the repository at this point in the history
This aims to address #271 by ensuring that all TOC links are generated as relative links, rather than absolute. The desired outcome being that the site no longer makes assumptions about being deployed at "/" which in turn makes it "portable" (i.e. possible to deploy it at an arbitrary path).
  • Loading branch information
eddgrant committed Jan 4, 2022
1 parent 84a1839 commit 824116a
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 12 deletions.
28 changes: 26 additions & 2 deletions lib/govuk_tech_docs/table_of_contents/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,29 @@ def list_items_from_headings(html, url: "", max_level: nil)
HeadingTreeRenderer.new(tree, max_level: max_level).html
end

def get_resource_link_value(config, resource, current_page)
if config[:relative_links]
current_page_segments = current_page.path.split("/").reject(&:empty?)[0..-2]
resource_path_segments = resource.path.split("/").reject(&:empty?)[0..-2]
resource_file_name = resource.path.split("/")[-1]
number_of_ascents_to_site_root = current_page_segments.length

if number_of_ascents_to_site_root == 0
ascents = ["."]
else
ascents = number_of_ascents_to_site_root.times.collect { ".." }
end

link_value = ascents.concat(resource_path_segments)
.push(resource_file_name)
.join("/")

else
link_value = resource.url
end
link_value
end

def render_page_tree(resources, current_page, config, current_page_html)
# Sort by weight frontmatter
resources = resources
Expand Down Expand Up @@ -71,15 +94,16 @@ def render_page_tree(resources, current_page, config, current_page_html)
config[:http_prefix] + "/"
end

link_value = get_resource_link_value(config, resource, current_page)
if resource.children.any? && resource.url != home_url
output += %{<li><a href="#{resource.url}"><span>#{resource.data.title}</span></a>\n}
output += %{<li><a href="#{link_value}"><span>#{resource.data.title}</span></a>\n}
output += render_page_tree(resource.children, current_page, config, current_page_html)
output += "</li>\n"
else
output +=
list_items_from_headings(
content,
url: resource.url,
url: link_value,
max_level: config[:tech_docs][:max_toc_heading_level],
)
end
Expand Down
129 changes: 119 additions & 10 deletions spec/table_of_contents/helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,20 @@ def add_children(children)

subject { Subject.new }

it "builds a table of contents from several page resources" do
it "builds a table of contents using absolute links from several page resources" do
resources = []
resources[0] = FakeResource.new("/index.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 10, "Index");
resources[1] = FakeResource.new("/a.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 10, "Sub page A", resources[0]);
resources[2] = FakeResource.new("/b.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 20, "Sub page B", resources[0]);
resources[0].add_children [resources[1], resources[2]]
resources[1] = FakeResource.new("/1/2/a.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 20, "Sub page A", resources[0]);
resources[2] = FakeResource.new("/1/2/3/b.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 30, "Sub page A", resources[0]);
resources[3] = FakeResource.new("/1/2/3/4/c.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 40, "Sub page B", resources[0]);
resources[4] = FakeResource.new("/1/5/d.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 50, "Sub page A", resources[0]);
resources[5] = FakeResource.new("/1/5/6/e.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 60, "Sub page A", resources[0]);
resources[0].add_children [resources[1], resources[2], resources[3], resources[4], resources[5]]

current_page = double("current_page",
data: double("page_frontmatter", description: "The description.", title: "The Title"),
url: "/index.html",
url: "/1/2/3/index.html",
path: "/1/2/3/index.html",
metadata: { locals: {} })

current_page_html = '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>';
Expand All @@ -152,18 +156,120 @@ def add_children(children)
<li><a href="/index.html"><span>Index</span></a>
<ul>
<li>
<a href="/a.html"><span>Heading one</span></a>
<a href="/1/2/a.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/1/2/a.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="/1/2/3/b.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/1/2/3/b.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="/1/2/3/4/c.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/1/2/3/4/c.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="/1/5/d.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/1/5/d.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="/1/5/6/e.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/1/5/6/e.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
}

expect(subject.multi_page_table_of_contents(resources, current_page, config, current_page_html).strip).to eq(expected_multi_page_table_of_contents.strip)
end

it "builds a table of contents using relative links from several page resources" do
resources = []
resources[0] = FakeResource.new("/index.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 10, "Index");
resources[1] = FakeResource.new("/1/2/a.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 20, "Sub page A", resources[0]);
resources[2] = FakeResource.new("/1/2/3/b.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 30, "Sub page A", resources[0]);
resources[3] = FakeResource.new("/1/2/3/4/c.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 40, "Sub page B", resources[0]);
resources[4] = FakeResource.new("/1/5/d.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 50, "Sub page A", resources[0]);
resources[5] = FakeResource.new("/1/5/6/e.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 60, "Sub page A", resources[0]);
resources[0].add_children [resources[1], resources[2], resources[3], resources[4], resources[5]]

current_page = double("current_page",
data: double("page_frontmatter", description: "The description.", title: "The Title"),
url: "/1/2/3/index.html",
path: "/1/2/3/index.html",
metadata: { locals: {} })

current_page_html = '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>';

config = {
http_prefix: "/",
relative_links: true,
tech_docs: {
max_toc_heading_level: 3,
},
}

expected_multi_page_table_of_contents = %{
<ul>
<li><a href="../../../index.html"><span>Index</span></a>
<ul>
<li>
<a href="../../../1/2/a.html"><span>Heading one</span></a>
<ul>
<li>
<a href="../../../1/2/a.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="../../../1/2/3/b.html"><span>Heading one</span></a>
<ul>
<li>
<a href="../../../1/2/3/b.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="../../../1/2/3/4/c.html"><span>Heading one</span></a>
<ul>
<li>
<a href="../../../1/2/3/4/c.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="../../../1/5/d.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/a.html#heading-two"><span>Heading two</span></a>
<a href="../../../1/5/d.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
<li>
<a href="/b.html"><span>Heading one</span></a>
<a href="../../../1/5/6/e.html"><span>Heading one</span></a>
<ul>
<li>
<a href="/b.html#heading-two"><span>Heading two</span></a>
<a href="../../../1/5/6/e.html#heading-two"><span>Heading two</span></a>
</li>
</ul>
</li>
Expand All @@ -175,7 +281,8 @@ def add_children(children)
expect(subject.multi_page_table_of_contents(resources, current_page, config, current_page_html).strip).to eq(expected_multi_page_table_of_contents.strip)
end

it "builds a table of contents from several page resources with a custom http prefix ocnfigured" do
#TODO: Assess whether this test is still relevant given that we are now generating relative links.
it "builds a table of contents from several page resources with a custom http prefix configured" do
resources = []
resources[0] = FakeResource.new("/prefix/index.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 10, "Index");
resources[1] = FakeResource.new("/prefix/a.html", '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>', 10, "Sub page A", resources[0]);
Expand All @@ -185,6 +292,7 @@ def add_children(children)
current_page = double("current_page",
data: double("page_frontmatter", description: "The description.", title: "The Title"),
url: "/prefix/index.html",
path: "/prefix/index.html",
metadata: { locals: {} })

current_page_html = '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>';
Expand Down Expand Up @@ -231,6 +339,7 @@ def add_children(children)
current_page = double("current_page",
data: double("page_frontmatter", description: "The description.", title: "The Title"),
url: "/index.html",
path: "/index.html",
metadata: { locals: {} })

current_page_html = '<h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2><h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2><h1 id="heading-one">Heading one</h1><h2 id="heading-two">Heading two</h2>';
Expand Down

0 comments on commit 824116a

Please sign in to comment.