govuk_tech_docs 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of govuk_tech_docs might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b05aaaeb08b75633793f5ede8102ef35d54cedbe6bc419b9fe262a3596d6cfef
4
- data.tar.gz: 30ab85794e056634591d692999364da7644908653e06d2707aa15eeff9b5bfea
3
+ metadata.gz: 06ad063ddc3de387b2bae379df43d4ecd6996a42bdc1f0472e2eb46b404b5701
4
+ data.tar.gz: 23b17f1d49d77303d7acb06be0ee2f30cd8ec9b40407b18689696008bf594b89
5
5
  SHA512:
6
- metadata.gz: 406187054e9b14fd631fb56a2602f8c607ab2abfe8be466673ffee99fba6451ebe684dca40e53270b66b5b1a6b12142336ad26124335b33b02205e13005290e8
7
- data.tar.gz: fc0afcd3567241e487bb75fbfebb26561ee8b6c9dd0a50d5f2d8252ea2d8a95c71976ae2540ff1f58e2d89886234c25b6d6b726fb74e618a1fba05ae97b0303d
6
+ metadata.gz: dfff9af883e1eb613f704789bd55f65947309e5df3a7a1d1280f4a28483a55d38200108d9808279d3985e2fd75bdc86adccea94520bb7469a78cdfa654def53c
7
+ data.tar.gz: '09ae4a42091646b3850af6e4db030a0912e48a10df7b0db296621cdaa58c5df236c17399374201fe2f4af4bd38ce9525837a0811145cfea5fa380b70c5836541'
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 3.2.0
6
+
7
+ ### New features
8
+
9
+ You can now [configure your Tech Docs Template (TDT) to build your documentation site to use relative links to pages and assets](https://tdt-documentation.london.cloudapps.digital/configure_project/global_configuration/#build-your-site-using-relative-links).
10
+
11
+ Thanks [@eddgrant](https://github.com/eddgrant) for contributing this feature and the associated fixes.
12
+
13
+ This change was introduced in [pull request #291: Support sites deployed on paths other than "/" (by generating relative links)](https://github.com/alphagov/tech-docs-gem/pull/291).
14
+
5
15
  ## 3.1.0
6
16
 
7
17
  ### New features
@@ -57,25 +57,31 @@
57
57
  $toggleLabel.text(setOpen ? 'Collapse ' + $heading.text() : 'Expand ' + $heading.text())
58
58
  }
59
59
 
60
+ /**
61
+ * Returns an absolute pathname to $target by combining it with window.location.href
62
+ * @param $target The target whose pathname to return. This may be an anchor with an absolute or relative href.
63
+ * @returns {string} The absolute pathname of $target
64
+ */
65
+ function getAbsolutePath ($target) {
66
+ return new URL($target.attr('href'), window.location.href).pathname
67
+ }
68
+
60
69
  function openActiveHeading () {
61
70
  var $activeElement
62
71
  var currentPath = window.location.pathname
63
- var isActiveTrail = '[href*="' + currentPath + '"]'
64
- // Add an exception for the root page, as every href includes /
65
- if (currentPath === '/') {
66
- isActiveTrail = '[href="' + currentPath + window.location.hash + '"]'
67
- }
68
72
  for (var i = $topLevelItems.length - 1; i >= 0; i--) {
69
73
  var $element = $($topLevelItems[i])
70
74
  var $heading = $element.find('> a')
71
75
  // Check if this item href matches
72
- if ($heading.is(isActiveTrail)) {
76
+ if (getAbsolutePath($heading) === currentPath) {
73
77
  $activeElement = $element
74
78
  break
75
79
  }
76
80
  // Otherwise check the children
77
81
  var $children = $element.find('li > a')
78
- var $matchingChildren = $children.filter(isActiveTrail)
82
+ var $matchingChildren = $children.filter(function (_) {
83
+ return getAbsolutePath($(this)) === currentPath
84
+ })
79
85
  if ($matchingChildren.length) {
80
86
  $activeElement = $element
81
87
  break
@@ -70,13 +70,18 @@
70
70
  function highlightActiveItemInToc (fragment) {
71
71
  // Navigation items for single page navigation don't necessarily include the path name, but
72
72
  // navigation items for multipage navigation items do include it. This checks for either case.
73
- var $activeTocItem = $tocItems.filter(
74
- '[href="' + window.location.pathname + fragment + '"],[href="' + fragment + '"]'
75
- )
73
+ var $activeTocItem = $tocItems.filter(function (_) {
74
+ var url = new URL($(this).attr('href'), window.location.href)
75
+ return url.href === window.location.href
76
+ })
77
+
76
78
  // Navigation items with children don't contain fragments in their url
77
79
  // Check to see if any nav items contain just the path name.
78
80
  if (!$activeTocItem.get(0)) {
79
- $activeTocItem = $tocItems.filter('[href="' + window.location.pathname + '"]')
81
+ $activeTocItem = $tocItems.filter(function (_) {
82
+ var url = new URL($(this).attr('href'), window.location.href)
83
+ return url.hash === '' && url.pathname === window.location.pathname
84
+ })
80
85
  }
81
86
  if ($activeTocItem.get(0)) {
82
87
  $tocItems.removeClass('toc-link--in-view')
@@ -16,6 +16,7 @@
16
16
  var results
17
17
  var query
18
18
  var maxSearchEntries = 20
19
+ var pathToSiteRoot
19
20
 
20
21
  this.start = function start ($element) {
21
22
  $searchForm = $element.find('form')
@@ -25,6 +26,7 @@
25
26
  $searchResults = $searchResultsWrapper.find('.search-results__content')
26
27
  $searchResultsTitle = $searchResultsWrapper.find('.search-results__title')
27
28
  $searchHelp = $('#search-help')
29
+ pathToSiteRoot = $element.data('pathToSiteRoot')
28
30
 
29
31
  changeSearchAction()
30
32
  changeSearchLabel()
@@ -38,7 +40,7 @@
38
40
  query = s.getQuery()
39
41
  if (query) {
40
42
  $searchInput.val(query)
41
- doSearch(query)
43
+ doSearch(query, pathToSiteRoot)
42
44
  doAnalytics()
43
45
  document.title = query + ' - ' + document.title
44
46
  }
@@ -49,7 +51,7 @@
49
51
  this.downloadSearchIndex = function downloadSearchIndex () {
50
52
  updateTitle('Loading search results')
51
53
  $.ajax({
52
- url: '/search.json',
54
+ url: pathToSiteRoot + 'search.json',
53
55
  cache: true,
54
56
  method: 'GET',
55
57
  success: function (data) {
@@ -65,7 +67,7 @@
65
67
  // We need JavaScript to do search, so if JS is not available the search
66
68
  // input sends the query string to Google. This JS function changes the
67
69
  // input to instead send it to the search page.
68
- $searchForm.prop('action', '/search')
70
+ $searchForm.prop('action', pathToSiteRoot + 'search/index.html')
69
71
  $searchForm.find('input[name="as_sitesearch"]').remove()
70
72
  }
71
73
 
@@ -86,10 +88,10 @@
86
88
  return query
87
89
  }
88
90
 
89
- function doSearch (query) {
91
+ function doSearch (query, pathToSiteRoot) {
90
92
  s.search(query, function (r) {
91
93
  results = r
92
- renderResults(query)
94
+ renderResults(query, pathToSiteRoot)
93
95
  updateTitle()
94
96
  })
95
97
  }
@@ -138,7 +140,7 @@
138
140
  callback(getResults(query))
139
141
  }
140
142
 
141
- function renderResults (query) {
143
+ function renderResults (query, pathToSiteRoot) {
142
144
  var output = ''
143
145
  if (results.length === 0) {
144
146
  output += '<p>Nothing found</p>'
@@ -149,7 +151,9 @@
149
151
  var content = s.processContent(result.content, query)
150
152
  output += '<li class="search-result">'
151
153
  output += '<h3 class="search-result__title">'
152
- output += '<a href="' + result.url + '">'
154
+ var pagePathWithoutLeadingSlash = result.url.startsWith('/') ? result.url.slice(1) : result.url
155
+ var url = pathToSiteRoot.startsWith('.') ? pathToSiteRoot + pagePathWithoutLeadingSlash : '/' + pagePathWithoutLeadingSlash
156
+ output += '<a href="' + url + '">'
153
157
  output += result.title
154
158
  output += '</a>'
155
159
  output += '</h3>'
@@ -1,4 +1,4 @@
1
- $govuk-assets-path: "/assets/govuk/assets/";
1
+ $govuk-assets-path: "/assets/govuk/assets/" !default;
2
2
 
3
3
  // Include only the bits of GOV.UK Frontend we need
4
4
  $govuk-new-link-styles: true;
@@ -18,12 +18,12 @@
18
18
  text-decoration: none;
19
19
  text-indent: -9999em;
20
20
 
21
- background-image: url('/images/anchored-heading-icon.png');
21
+ background-image: image-url('/images/anchored-heading-icon.png');
22
22
  background-repeat: no-repeat;
23
23
  background-position: center center;
24
24
 
25
25
  @include govuk-device-pixel-ratio {
26
- background-image: url('/images/anchored-heading-icon-2x.png');
26
+ background-image: image-url('/images/anchored-heading-icon-2x.png');
27
27
  background-size: $icon-width $icon-height;
28
28
  }
29
29
 
@@ -36,7 +36,7 @@ $input-size: 40px;
36
36
  padding: 0;
37
37
  width: $input-size;
38
38
  height: 100%;
39
- background-image: url('/images/search-button.png');
39
+ background-image: image-url('/images/search-button.png');
40
40
  background-repeat: no-repeat;
41
41
  background-position: 2px 50%;
42
42
  text-indent: -5000px;
@@ -104,7 +104,7 @@ $input-size: 40px;
104
104
  left: -9px;
105
105
  width: 10px;
106
106
  height: 20px;
107
- background: no-repeat url('/images/search-result-caret.svg') center right;
107
+ background: no-repeat image-url('/images/search-result-caret.svg') center right;
108
108
  background-size: contain;
109
109
  }
110
110
  }
@@ -152,12 +152,12 @@
152
152
  height: 20px;
153
153
  float: right;
154
154
 
155
- background-image: url('/images/govuk-icn-numbered-list.png');
155
+ background-image: image-url('/images/govuk-icn-numbered-list.png');
156
156
  background-repeat: no-repeat;
157
157
  background-position: left center;
158
158
 
159
159
  @include govuk-device-pixel-ratio {
160
- background-image: url('/images/govuk-icn-numbered-list@2x.png');
160
+ background-image: image-url('/images/govuk-icn-numbered-list@2x.png');
161
161
  background-size: 20px 20px;
162
162
  }
163
163
  }
@@ -178,12 +178,12 @@
178
178
  height: 20px;
179
179
  cursor: pointer;
180
180
 
181
- background-image: url('/images/govuk-icn-close.png');
181
+ background-image: image-url('/images/govuk-icn-close.png');
182
182
  background-repeat: no-repeat;
183
183
  background-position: left center;
184
184
 
185
185
  @include govuk-device-pixel-ratio {
186
- background-image: url('/images/govuk-icn-close@2x.png');
186
+ background-image: image-url('/images/govuk-icn-close@2x.png');
187
187
  background-size: 20px 20px;
188
188
  }
189
189
 
@@ -1,10 +1,12 @@
1
1
  module GovukTechDocs
2
2
  class Pages
3
+ include GovukTechDocs::PathHelpers
3
4
  attr_reader :sitemap
4
5
 
5
- def initialize(sitemap, config)
6
+ def initialize(sitemap, config, current_page)
6
7
  @sitemap = sitemap
7
8
  @config = config
9
+ @current_page = current_page
8
10
  end
9
11
 
10
12
  def to_json(*_args)
@@ -18,7 +20,7 @@ module GovukTechDocs
18
20
  review = PageReview.new(page, @config)
19
21
  {
20
22
  title: page.data.title,
21
- url: "#{@config[:tech_docs][:host]}#{page.url}",
23
+ url: get_path_to_resource(@config, page, @current_page).to_s,
22
24
  review_by: review.review_by,
23
25
  owner_slack: review.owner_slack,
24
26
  }
@@ -0,0 +1,30 @@
1
+ module GovukTechDocs
2
+ module PathHelpers
3
+ def get_path_to_resource(config, resource, current_page)
4
+ if config[:relative_links]
5
+ resource_path_segments = resource.path.split("/").reject(&:empty?)[0..-2]
6
+ resource_file_name = resource.path.split("/")[-1]
7
+
8
+ path_to_site_root = path_to_site_root config, current_page.path
9
+ resource_path = path_to_site_root + resource_path_segments
10
+ .push(resource_file_name)
11
+ .join("/")
12
+ else
13
+ resource_path = resource.url
14
+ end
15
+ resource_path
16
+ end
17
+
18
+ def path_to_site_root(config, page_path)
19
+ if config[:relative_links]
20
+ number_of_ascents_to_site_root = page_path.to_s.split("/").reject(&:empty?)[0..-2].length
21
+ ascents = number_of_ascents_to_site_root.zero? ? ["."] : number_of_ascents_to_site_root.times.collect { ".." }
22
+ path_to_site_root = ascents.join("/").concat("/")
23
+ else
24
+ middleman_http_prefix = config[:http_prefix]
25
+ path_to_site_root = middleman_http_prefix.end_with?("/") ? middleman_http_prefix : "#{middleman_http_prefix}/"
26
+ end
27
+ path_to_site_root
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,4 @@
1
+ require "govuk_tech_docs/path_helpers"
1
2
  require "govuk_tech_docs/table_of_contents/heading_tree_builder"
2
3
  require "govuk_tech_docs/table_of_contents/heading_tree_renderer"
3
4
  require "govuk_tech_docs/table_of_contents/heading_tree"
@@ -7,6 +8,8 @@ require "govuk_tech_docs/table_of_contents/headings_builder"
7
8
  module GovukTechDocs
8
9
  module TableOfContents
9
10
  module Helpers
11
+ include GovukTechDocs::PathHelpers
12
+
10
13
  def single_page_table_of_contents(html, url: "", max_level: nil)
11
14
  output = "<ul>\n"
12
15
  output += list_items_from_headings(html, url: url, max_level: max_level)
@@ -48,11 +51,7 @@ module GovukTechDocs
48
51
 
49
52
  # Reuse the generated content for the active page
50
53
  # If we generate it twice it increments the heading ids
51
- content = if current_page.url == resource.url && current_page_html
52
- current_page_html
53
- else
54
- resource.render(layout: false)
55
- end
54
+ content = current_page.url == resource.url && current_page_html ? current_page_html : resource.render(layout: false)
56
55
  # Avoid redirect pages
57
56
  next if content.include? "http-equiv=refresh"
58
57
 
@@ -71,15 +70,16 @@ module GovukTechDocs
71
70
  config[:http_prefix] + "/"
72
71
  end
73
72
 
73
+ link_value = get_path_to_resource(config, resource, current_page)
74
74
  if resource.children.any? && resource.url != home_url
75
- output += %{<li><a href="#{resource.url}"><span>#{resource.data.title}</span></a>\n}
75
+ output += %{<li><a href="#{link_value}"><span>#{resource.data.title}</span></a>\n}
76
76
  output += render_page_tree(resource.children, current_page, config, current_page_html)
77
77
  output += "</li>\n"
78
78
  else
79
79
  output +=
80
80
  list_items_from_headings(
81
81
  content,
82
- url: resource.url,
82
+ url: link_value,
83
83
  max_level: config[:tech_docs][:max_toc_heading_level],
84
84
  )
85
85
  end
@@ -1,3 +1,3 @@
1
1
  module GovukTechDocs
2
- VERSION = "3.1.0".freeze
2
+ VERSION = "3.2.0".freeze
3
3
  end
@@ -67,6 +67,7 @@ module GovukTechDocs
67
67
  context.activate :api_reference
68
68
 
69
69
  context.helpers do
70
+ include GovukTechDocs::PathHelpers
70
71
  include GovukTechDocs::TableOfContents::Helpers
71
72
  include GovukTechDocs::ContributionBanner
72
73
 
@@ -1 +1 @@
1
- <%= GovukTechDocs::Pages.new(sitemap, config).to_json %>
1
+ <%= GovukTechDocs::Pages.new(sitemap, config, current_page).to_json %>
@@ -1,5 +1,5 @@
1
1
  <% if config[:tech_docs][:enable_search] %>
2
- <div class="search" data-module="search">
2
+ <div class="search" data-module="search" data-path-to-site-root="<%= path_to_site_root config, current_page.path %>">
3
3
  <form action="https://www.google.co.uk/search" method="get" role="search" class="search__form govuk-!-margin-bottom-4">
4
4
  <input type="hidden" name="as_sitesearch" value="<%= config[:tech_docs][:host] %>"/>
5
5
  <label class="govuk-label search__label" for="search" aria-hidden="true">
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_tech_docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Government Digital Service
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-20 00:00:00.000000000 Z
11
+ date: 2022-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: autoprefixer-rails
@@ -360,6 +360,7 @@ files:
360
360
  - lib/govuk_tech_docs/meta_tags.rb
361
361
  - lib/govuk_tech_docs/page_review.rb
362
362
  - lib/govuk_tech_docs/pages.rb
363
+ - lib/govuk_tech_docs/path_helpers.rb
363
364
  - lib/govuk_tech_docs/redirects.rb
364
365
  - lib/govuk_tech_docs/table_of_contents/heading.rb
365
366
  - lib/govuk_tech_docs/table_of_contents/heading_tree.rb