Skip to content
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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.2.1

- [Add option to not render child resources when creating a table of contents](https://github.com/alphagov/tech-docs-gem/pull/439/changes)

## 5.2.0

### New features
Expand Down
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,61 @@ This gem uses [GOV.UK Frontend](https://github.com/alphagov/govuk-frontend), par

We use `npm` to download the govuk-frontend package. To update to a new version, change the version in the [package.json file](package.json) and run `npm update`.

## Table of contents helper functions

With `Middleman` you can apply layouts to group pages and customise sites. This gem has the following additional helper functions to manage the table of contents (ToC):

- `single_page_table_of_contents` to create a ToC from the headings on the current page
- `multi_page_table_of_contents` to create a ToC for a group of pages, opened at the current page

### Single page table of contents

The `single_page_table_of_contents` helper has the following parameters:

| Parameter | Description |
|-------------|----------------------------------------------------------------------------------------|
| `html` | The html of the current page. |
| `url` | Optional parameter used to override the url of the page heading. Defaults to `""`. |
| `max_level` | Optional parameter used to set the depth of the table of contents. Defaults to `nil`. |

Below is an example of using `single_page_table_of_contents` in a layout file:

```
<%
wrap_layout :core do
content_for :sidebar do
<%= single_page_table_of_contents(html, max_level: 2) %>
end
end
%>
```

This example will create a ToC containing the current page title, and nested headings to a depth of 2.

### Multi page table of contents

The `multi_page_table_of_contents` has the following parameters:

| Parameter | Description |
|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `resources` | An array of middleman site resources for the pages to be included in the ToC. |
| `current_page` | The resource object found in the [middleman current_page](https://www.rubydoc.info/gems/middleman-core/Middleman/TemplateContext#current_resource-instance_method). |
| `config` | Site settings defined in `/config/tech-docs.yaml`. |
| `current_page_html` | Optional html of the current page. Defaults to `nil`. |
| `include_child_resources` | Optional setting used to include child resources when creating a ToC. Defaults to `true`. |
Below is an example of using `multi_page_table_of_contents` in a layout file:

```
<%
wrap_layout :core do
content_for :sidebar do
<%= multi_page_table_of_contents(sitemap.resources, current_page, config, yield, include_child_resources: true) %>
end
end
%>
```
This example will create a ToC containing the page title of each resource, as a heading. Each heading can be expanded to show nested headings to the depth defined in the site config. If `include_child_resources` is set to `true`, child resources will also be included.

## Developing locally

There are 2 ways to develop with this gem. You can see your changes on either:
Expand Down
8 changes: 4 additions & 4 deletions lib/govuk_tech_docs/table_of_contents/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ def select_top_level_html_files(resources)
.select { |r| r.path.end_with?(".html") && (r.parent.nil? || r.parent.url == "/") }
end

def multi_page_table_of_contents(resources, current_page, config, current_page_html = nil)
def multi_page_table_of_contents(resources, current_page, config, current_page_html = nil, include_child_resources: true)
resources = sort_resources_stably(
select_top_level_html_files(resources),
)

render_page_tree(resources, current_page, config, current_page_html)
render_page_tree(resources, current_page, config, current_page_html, include_child_resources:)
end

def list_items_from_headings(html, url: "", max_level: nil)
Expand All @@ -54,7 +54,7 @@ def list_items_from_headings(html, url: "", max_level: nil)
HeadingTreeRenderer.new(tree, max_level:).html
end

def render_page_tree(resources, current_page, config, current_page_html)
def render_page_tree(resources, current_page, config, current_page_html, include_child_resources: true)
resources = sort_resources_stably(resources)

output = "<ul>\n"
Expand Down Expand Up @@ -84,7 +84,7 @@ def render_page_tree(resources, current_page, config, current_page_html)
end

link_value = get_path_to_resource(config, resource, current_page)
if resource.children.any? && resource.url != home_url
if resource.children.any? && resource.url != home_url && include_child_resources
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"
Expand Down
2 changes: 1 addition & 1 deletion lib/govuk_tech_docs/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module GovukTechDocs
VERSION = "5.2.0".freeze
VERSION = "5.2.1".freeze
end
40 changes: 40 additions & 0 deletions spec/table_of_contents/helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -393,5 +393,45 @@ def is_a?(klass)

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 a single page resource when include_child_resources is set to false" do
resources = []
resources[0] = FakeResource.new("/index.html", '<h1 id="heading-one">Parent heading one</h1><h2 id="heading-two">Parent heading two</h2>', 10, "Index")
resources[1] = FakeResource.new("/1/2/a.html", '<h1 id="heading-one">Child heading one</h1><h2 id="heading-two">Child heading two</h2>', 20, "Sub page A", resources[0])
resources[2] = FakeResource.new("/1/2/3/b.html", '<h1 id="heading-one">Second child heading one</h1><h2 id="heading-two">Second child heading two</h2>', 30, "Sub page A", resources[0])

resources[0].add_children [resources[1], resources[2]]

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">Parent heading one</h1><h2 id="heading-two">Parent heading two</h2>'

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

expected_multi_page_table_of_contents = %(
<ul>
<li>
<a href="/index.html"><span>Parent heading one</span></a>
<ul>
<li>
<a href="/index.html#heading-two"><span>Parent heading two</span></a>
</li>
</ul>
</li>
</ul>
)

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