@x-govuk/govuk-eleventy-plugin 5.0.7 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +3 -4
  2. package/components/aside/_aside.scss +1 -1
  3. package/components/document-header/_document-header.scss +5 -0
  4. package/components/document-list/_document-list.scss +1 -1
  5. package/components/document-list/template.njk +1 -1
  6. package/components/footnotes-list/_footnotes-list.scss +1 -1
  7. package/components/header/_govuk.svg +4 -0
  8. package/components/header/_header.scss +17 -6
  9. package/components/header/_x-govuk.svg +3 -2
  10. package/components/header/template.njk +16 -16
  11. package/components/prose-scope/_prose-scope.scss +24 -1
  12. package/components/site-search/_site-search.scss +35 -52
  13. package/components/site-search/site-search.js +107 -117
  14. package/components/site-search/template.njk +5 -4
  15. package/index.js +36 -8
  16. package/layouts/base.njk +16 -13
  17. package/layouts/post.njk +1 -1
  18. package/layouts/product.njk +2 -3
  19. package/layouts/search-index.njk +1 -1
  20. package/layouts/sitemap.njk +1 -1
  21. package/layouts/sub-navigation.njk +1 -1
  22. package/lib/collections/ordered.js +9 -3
  23. package/lib/collections/tags.js +9 -3
  24. package/lib/data/eleventy-computed.js +5 -8
  25. package/lib/data/options.js +0 -1
  26. package/lib/events/generate-govuk-assets.js +8 -24
  27. package/lib/extensions/scss.js +2 -6
  28. package/lib/filters/canonical-url.js +31 -0
  29. package/lib/filters/current-page.js +16 -0
  30. package/lib/filters/date.js +3 -5
  31. package/lib/filters/includes.js +12 -12
  32. package/lib/filters/items-from-collection.js +2 -3
  33. package/lib/filters/items-from-navigation.js +13 -17
  34. package/lib/filters/items-from-pagination.js +1 -2
  35. package/lib/filters/markdown.js +1 -3
  36. package/lib/filters/no-orphans.js +2 -4
  37. package/lib/filters/pretty.js +2 -4
  38. package/lib/filters/smart.js +3 -5
  39. package/lib/filters/tokenize.js +16 -8
  40. package/lib/govuk.js +3 -4
  41. package/lib/govuk.scss +1 -2
  42. package/lib/markdown-it/deflist.js +1 -3
  43. package/lib/markdown-it/footnote.js +2 -5
  44. package/lib/markdown-it/table-of-contents.js +3 -4
  45. package/lib/markdown-it/table.js +6 -6
  46. package/lib/markdown-it.js +5 -7
  47. package/lib/nunjucks.js +6 -8
  48. package/lib/utils.js +24 -14
  49. package/package.json +28 -44
  50. package/components/all.js +0 -13
  51. package/components/header/_crown.svg +0 -8
  52. package/components/header/_royal-arms.svg +0 -3
package/README.md CHANGED
@@ -11,9 +11,8 @@ You’re welcome to use the plugin even if your service isn’t considered part
11
11
 
12
12
  ## Requirements
13
13
 
14
- - [Node.js](https://nodejs.org) v16.0.0 or above
15
- - [npm CLI](https://docs.npmjs.com/cli) v8.0.0 or above
16
- - [Eleventy](https://www.11ty.dev) v2.0.0 or above
14
+ - [Node.js](https://nodejs.org) v18.17 or later
15
+ - [Eleventy](https://www.11ty.dev) v2 or later
17
16
 
18
17
  ## Installation
19
18
 
@@ -37,5 +36,5 @@ Learn more about how to [get started](https://x-govuk.github.io/govuk-eleventy-p
37
36
 
38
37
  This command will ask you what version you want to use. It will then publish a new version on NPM, create and push a new git tag and then generate release notes ready for posting on GitHub.
39
38
 
40
- > ![NOTE]
39
+ > [!NOTE]
41
40
  > Releasing a new version requires permission to publish packages to the `@x-govuk` organisation.
@@ -6,8 +6,8 @@
6
6
 
7
7
  .app-aside__heading {
8
8
  @include govuk-font(19, $weight: bold);
9
- margin-top: govuk-spacing(3);
10
9
  margin-bottom: govuk-spacing(2);
10
+ margin-top: govuk-spacing(3);
11
11
  }
12
12
 
13
13
  .app-aside__body {
@@ -1,4 +1,9 @@
1
1
  .app-document-header__metadata {
2
2
  @include govuk-font($size: 16, $line-height: 1.5);
3
3
  color: $govuk-secondary-text-colour;
4
+ max-width: 45em;
5
+ }
6
+
7
+ .app-document-header__description {
8
+ max-width: 30em;
4
9
  }
@@ -16,8 +16,8 @@
16
16
  }
17
17
 
18
18
  .app-document-list__item-metadata {
19
- padding: 0;
20
19
  margin: 0;
20
+ padding: 0;
21
21
  }
22
22
 
23
23
  .app-document-list__item-description {
@@ -5,7 +5,7 @@
5
5
  {% for item in params.items %}
6
6
  <li class="app-document-list__item">
7
7
  <h{{ headingLevel }} class="app-document-list__item-title">
8
- <a class="govuk-link" href="{{ item.url | url | pretty }}">{{ item.data.title | smart }}</a>
8
+ <a class="govuk-link" href="{{ item.url | pretty }}">{{ item.data.title | smart }}</a>
9
9
  </h{{ headingLevel }}>
10
10
  {% if item.data.description %}
11
11
  <p class="app-document-list__item-description">
@@ -29,8 +29,8 @@ a[aria-describedby="footnotes-label"]::after {
29
29
  li::before {
30
30
  @include govuk-font(19, $tabular: true);
31
31
  content: counter(footnotes) ".";
32
- position: absolute;
33
32
  left: govuk-spacing(4);
33
+ position: absolute;
34
34
  }
35
35
 
36
36
  a[aria-label="Back to content"] {
@@ -0,0 +1,4 @@
1
+ <svg class="govuk-header__logotype" xmlns="http://www.w3.org/2000/svg" focusable="false" role="img" width="152" height="30" viewBox="0 0 152 30" aria-label="GOV.UK">
2
+ <title>GOV.UK</title>
3
+ <path d="M6.7 12.2c1 .4 2.1-.1 2.5-1s-.1-2.1-1-2.5c-1-.4-2.1.1-2.5 1-.4 1 0 2.1 1 2.5m-4.3 2.5c1 .4 2.1-.1 2.5-1s-.1-2.1-1-2.5c-1-.4-2.1.1-2.5 1-.5 1 0 2.1 1 2.5m-1.3 4.8c1 .4 2.1-.1 2.5-1 .4-1-.1-2.1-1-2.5-1-.4-2.1.1-2.5 1-.4 1 0 2.1 1 2.5m10.4-5.8c1 .4 2.1-.1 2.5-1s-.1-2.1-1-2.5c-1-.4-2.1.1-2.5 1s0 2.1 1 2.5m17.4-1.5c-1 .4-2.1-.1-2.5-1s.1-2.1 1-2.5c1-.4 2.1.1 2.5 1 .5 1 0 2.1-1 2.5m4.3 2.5c-1 .4-2.1-.1-2.5-1s.1-2.1 1-2.5c1-.4 2.1.1 2.5 1 .5 1 0 2.1-1 2.5m1.3 4.8c-1 .4-2.1-.1-2.5-1-.4-1 .1-2.1 1-2.5 1-.4 2.1.1 2.5 1 .4 1 0 2.1-1 2.5m-10.4-5.8c-1 .4-2.1-.1-2.5-1s.1-2.1 1-2.5c1-.4 2.1.1 2.5 1s0 2.1-1 2.5m-5.3-4.9 2.4 1.3V6.5l-2.4.8c-.1-.1-.1-.2-.2-.2s1-3 1-3h-3.4l1 3c-.1.1-.2.1-.2.2-.1.1-2.4-.7-2.4-.7v3.5L17 8.8c-.1.1 0 .2.1.3l-1.4 4.2c-.1.2-.1.4-.1.7 0 1.1.8 2.1 1.9 2.2h.6C19.2 16 20 15.1 20 14c0-.2 0-.4-.1-.7l-1.4-4.2c.2-.1.3-.2.3-.3m-1 20.3c4.6 0 8.9.3 12.8.9 1.1-4.6 2.4-7.2 3.8-9.1l-2.6-.9c.3 1.3.3 1.9 0 2.8-.4-.4-.8-1.2-1.1-2.4l-1.2 4.2c.8-.5 1.4-.9 2-.9-1.2 2.6-2.7 3.2-3.6 3-1.2-.2-1.7-1.3-1.5-2.2.3-1.3 1.6-1.6 2.2-.1 1.2-2.4-.8-3.1-2.1-2.4 1.9-1.9 2.2-3.6.6-5.7-2.2 1.7-2.2 3.3-1.2 5.6-1.3-1.5-3.3-.7-2.5 1.7.9-1.4 2.1-.5 2 .8-.2 1.2-1.7 2.1-3.7 2-2.8-.2-3-2.2-3-3.7.7-.1 1.9.5 3 2l.4-4.4c-1.1 1.2-2.2 1.4-3.3 1.4.4-1.2 2.1-3.1 2.1-3.1h-5.5s1.8 2 2.1 3.1c-1.1 0-2.2-.3-3.3-1.4l.4 4.4c1.1-1.5 2.3-2.1 3-2-.1 1.6-.2 3.5-3 3.7-1.9.2-3.5-.8-3.7-2-.2-1.3 1-2.2 1.9-.8.7-2.4-1.3-3.1-2.6-1.7 1-2.3 1-4-1.2-5.6-1.6 2.1-1.3 3.8.6 5.7-1.3-.7-3.2 0-2.1 2.4.6-1.5 1.9-1.1 2.2.1.2.9-.4 1.9-1.5 2.2-1 .2-2.5-.5-3.7-3 .7 0 1.3.4 2 .9L5 20.4c-.3 1.2-.7 1.9-1.2 2.4-.3-.8-.2-1.5 0-2.8l-2.6.9C2.7 22.8 4 25.4 5.1 30c3.8-.5 8.2-.9 12.7-.9m30.5-11.5c0 .9.1 1.7.3 2.5.2.8.6 1.5 1 2.2.5.6 1 1.1 1.7 1.5.7.4 1.5.6 2.5.6.9 0 1.7-.1 2.3-.4s1.1-.7 1.5-1.1c.4-.4.6-.9.8-1.5.1-.5.2-1 .2-1.5v-.2h-5.3v-3.2h9.4V28H59v-2.5c-.3.4-.6.8-1 1.1-.4.3-.8.6-1.3.9-.5.2-1 .4-1.6.6s-1.2.2-1.8.2c-1.5 0-2.9-.3-4-.8-1.2-.6-2.2-1.3-3-2.3-.8-1-1.4-2.1-1.8-3.4-.3-1.4-.5-2.8-.5-4.3s.2-2.9.7-4.2c.5-1.3 1.1-2.4 2-3.4.9-1 1.9-1.7 3.1-2.3 1.2-.6 2.6-.8 4.1-.8 1 0 1.9.1 2.8.3.9.2 1.7.6 2.4 1s1.4.9 1.9 1.5c.6.6 1 1.3 1.4 2l-3.7 2.1c-.2-.4-.5-.9-.8-1.2-.3-.4-.6-.7-1-1-.4-.3-.8-.5-1.3-.7-.5-.2-1.1-.2-1.7-.2-1 0-1.8.2-2.5.6-.7.4-1.3.9-1.7 1.5-.5.6-.8 1.4-1 2.2-.3.8-.4 1.9-.4 2.7zm36.4-4.3c-.4-1.3-1.1-2.4-2-3.4-.9-1-1.9-1.7-3.1-2.3-1.2-.6-2.6-.8-4.2-.8s-2.9.3-4.2.8c-1.1.6-2.2 1.4-3 2.3-.9 1-1.5 2.1-2 3.4-.4 1.3-.7 2.7-.7 4.2s.2 2.9.7 4.2c.4 1.3 1.1 2.4 2 3.4.9 1 1.9 1.7 3.1 2.3 1.2.6 2.6.8 4.2.8 1.5 0 2.9-.3 4.2-.8 1.2-.6 2.3-1.3 3.1-2.3.9-1 1.5-2.1 2-3.4.4-1.3.7-2.7.7-4.2-.1-1.5-.3-2.9-.8-4.2zM81 17.6c0 1-.1 1.9-.4 2.7-.2.8-.6 1.6-1.1 2.2-.5.6-1.1 1.1-1.7 1.4-.7.3-1.5.5-2.4.5-.9 0-1.7-.2-2.4-.5s-1.3-.8-1.7-1.4c-.5-.6-.8-1.3-1.1-2.2-.2-.8-.4-1.7-.4-2.7v-.1c0-1 .1-1.9.4-2.7.2-.8.6-1.6 1.1-2.2.5-.6 1.1-1.1 1.7-1.4.7-.3 1.5-.5 2.4-.5.9 0 1.7.2 2.4.5s1.3.8 1.7 1.4c.5.6.8 1.3 1.1 2.2.2.8.4 1.7.4 2.7v.1zM92.9 28 87 7h4.7l4 15.7h.1l4-15.7h4.7l-5.9 21h-5.7zm28.8-3.6c.6 0 1.2-.1 1.7-.3.5-.2 1-.4 1.4-.8.4-.4.7-.8.9-1.4.2-.6.3-1.2.3-2v-13h4.1v13.6c0 1.2-.2 2.2-.6 3.1s-1 1.7-1.8 2.4c-.7.7-1.6 1.2-2.7 1.5-1 .4-2.2.5-3.4.5-1.2 0-2.4-.2-3.4-.5-1-.4-1.9-.9-2.7-1.5-.8-.7-1.3-1.5-1.8-2.4-.4-.9-.6-2-.6-3.1V6.9h4.2v13c0 .8.1 1.4.3 2 .2.6.5 1 .9 1.4.4.4.8.6 1.4.8.6.2 1.1.3 1.8.3zm13-17.4h4.2v9.1l7.4-9.1h5.2l-7.2 8.4L152 28h-4.9l-5.5-9.4-2.7 3V28h-4.2V7zm-27.6 16.1c-1.5 0-2.7 1.2-2.7 2.7s1.2 2.7 2.7 2.7 2.7-1.2 2.7-2.7-1.2-2.7-2.7-2.7z"></path>
4
+ </svg>
@@ -2,6 +2,14 @@
2
2
  // See: https://github.com/alphagov/govuk-design-system/blob/master/src/stylesheets/components/_header.scss
3
3
 
4
4
  @include govuk-exports("app-header") {
5
+ .app-header--full-width-border {
6
+ border-bottom: $govuk-border-width-wide solid $govuk-brand-colour;
7
+ }
8
+
9
+ .app-header--no-border {
10
+ border-bottom: 0;
11
+ }
12
+
5
13
  // Override the default 33% width on the logo in GOV.UK Frontend (prevents
6
14
  // unnecessary wrapping of product name on smaller tablet / desktop
7
15
  // viewports)
@@ -14,11 +22,14 @@
14
22
  }
15
23
  }
16
24
 
17
- // Height of crown is 30px.
18
- // Visually adjust placement to accept larger icons with a height of 35px
19
- .app-header__logotype--large {
20
- margin-bottom: -10px;
21
- position: relative;
22
- top: -3px;
25
+ // Visually adjust placement of X-GOVUK logo which has a height of 35px
26
+ .x-govuk-header__logotype {
27
+ margin-bottom: -5px;
28
+ }
29
+
30
+ // Visually adjust placement of logotype text
31
+ .app-header__logotype {
32
+ font-weight: bold;
33
+ top: 0;
23
34
  }
24
35
  }
@@ -1,3 +1,4 @@
1
- <svg class="app-header__logotype--large" aria-hidden="true" focusable="false" height="35" width="35" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
2
- <path fill="currentColor" d="M180 251v1c-17 7-26 12-26 16s19 6 19-5c4 18-11 21-20 13 4 7 6 18-4 23-11-5-9-16-5-23-10 8-24 4-20-12v-1c0 11 18 9 19 5 0-4-9-9-26-16v-1c11 3 21 4 32 4 10 0 20-1 31-4Zm61-52 1 1c-6 18-8 29-5 34 6-6 11-14 11-24l19 9c-11 5-20 10-27 17 5 2 15-1 21-4l-32 32c3-6 6-16 4-21-7 6-12 16-16 27l-10-19c11 0 18-5 24-11-5-3-16-2-34 5v-1c10-6 18-12 25-19 8-8 14-15 19-26Zm-186 0c6 10 12 18 20 25 7 8 15 14 25 20h-1c-17-6-29-7-33-4 6 5 13 11 24 11l-10 19c-4-12-10-21-16-28-2 5 1 16 3 21l-31-31c5 2 16 5 21 3-7-6-16-12-28-16l19-10c0 11 6 18 11 24 3-5 2-16-4-33Zm152-5a15 15 0 0 1 10 25 15 15 0 0 1-25-10 15 15 0 0 1 15-15Zm-115 0a15 15 0 0 1 11 25 15 15 0 0 1-25-10 15 15 0 0 1 14-15Zm88-27a15 15 0 0 1 10 25 15 15 0 0 1-25-10 15 15 0 0 1 15-15Zm-63 0a15 15 0 0 1 10 25 15 15 0 0 1-25-10 15 15 0 0 1 15-15Zm133-48c7 17 12 26 16 26s6-19-5-19c18-4 21 11 13 20 7-4 18-6 23 5-5 10-16 8-23 4 8 9 5 24-13 20 11 0 9-19 5-19s-9 9-16 26h-1c3-11 4-21 4-31 0-11-1-21-4-32h1Zm-202 0c-3 11-4 21-4 32 0 10 1 20 4 31h-1c-7-17-12-26-15-26-5 0-7 19 4 19-18 4-21-11-13-20-7 4-18 6-23-4 5-11 16-9 23-5-8-9-5-24 13-20-11 0-9 19-4 19 3 0 8-9 15-26Zm101 11a20 20 0 1 1-1 41 20 20 0 0 1 1-41Zm-32-26a15 15 0 0 1 10 25 15 15 0 0 1-25-10 15 15 0 0 1 15-15Zm63 0a15 15 0 0 1 10 25 15 15 0 0 1-25-10 15 15 0 0 1 15-15ZM92 80a15 15 0 0 1 11 25 15 15 0 0 1-25-11 15 15 0 0 1 14-14Zm115 0a15 15 0 0 1 10 25 15 15 0 0 1-25-11 15 15 0 0 1 15-14ZM80 32l9 19c-10 0-18 5-24 11 5 3 16 1 34-5l1 1c-11 5-18 11-26 19-7 7-13 15-19 25h-1c7-18 8-29 5-34-6 6-11 13-11 24L29 82c11-4 21-9 27-16-5-2-15 1-21 4l32-32c-3 6-6 16-4 21 7-7 12-16 17-27Zm137-1c4 12 10 21 16 28 2-5-1-16-3-21l31 31c-5-2-16-5-21-3 7 6 16 12 28 16l-19 10c0-11-6-18-11-24-3 4-2 16 4 33v1c-6-10-12-18-20-25-7-8-15-14-25-20h1c17 6 28 7 33 4-6-5-13-11-24-11l10-19ZM149 2c10 5 8 16 4 23 9-8 24-5 20 13 0-11-19-9-19-4 0 3 9 8 26 15v1c-11-3-21-4-31-4-11 0-21 1-32 4v-1c17-7 26-12 26-15 0-5-19-7-19 4-4-17 10-21 20-13-4-7-6-18 5-23Z"/>
1
+ <svg class="govuk-header__logotype x-govuk-header__logotype" xmlns="http://www.w3.org/2000/svg" focusable="false" role="img" width="172" height="35" viewBox="0 0 172 35" aria-label="X-GOVUK">
2
+ <title>X-GOVUK</title>
3
+ <path d="M21 29v.2c-2 .8-3 1.4-3 1.8 0 .5 2.2.7 2.2-.6.4 2.1-1.3 2.5-2.3 1.6.4.8.7 2-.5 2.6-1.3-.5-1-1.8-.6-2.6-1.2.9-2.8.4-2.3-1.4v-.2c0 1.3 2 1.1 2.2.6 0-.4-1-1-3-1.8V29c1.2.3 2.4.4 3.7.4 1.2 0 2.3-.1 3.6-.4Zm7.1-6 .1.1c-.7 2.1-.9 3.4-.6 4a4 4 0 0 0 1.3-2.8l2.3 1a11 11 0 0 0-3.2 2c.6.2 1.8-.1 2.4-.5l-3.7 3.8c.4-.7.7-1.9.5-2.5-.8.7-1.4 1.9-1.9 3.2L24.1 29c1.3 0 2.1-.5 2.8-1.2-.5-.4-1.8-.3-4 .6v-.2a12.3 12.3 0 0 0 5.2-5.2ZM6.4 23a16.3 16.3 0 0 0 5.3 5.2h-.1c-2-.7-3.4-.8-3.9-.4.7.6 1.5 1.3 2.8 1.3l-1.2 2.2A9.6 9.6 0 0 0 7.5 28c-.3.6 0 1.9.3 2.4l-3.6-3.6c.6.3 1.9.6 2.5.4a9.6 9.6 0 0 0-3.3-1.9l2.2-1.2c0 1.3.7 2.1 1.3 2.8.3-.5.2-1.8-.5-3.8V23Zm17.8-.6a1.7 1.7 0 0 1 1.1 3 1.8 1.8 0 0 1-2.9-1.3c0-1 .8-1.7 1.8-1.7Zm-13.5 0a1.8 1.8 0 0 1 1.3 3A1.8 1.8 0 0 1 9.1 24c0-.9.7-1.6 1.6-1.7ZM21 19.3a1.7 1.7 0 0 1 1.2 2.9 1.8 1.8 0 0 1-3-1.2c0-1 .8-1.8 1.8-1.8Zm-7.3 0a1.7 1.7 0 0 1 1.1 2.9A1.8 1.8 0 0 1 12 21c0-1 .8-1.8 1.8-1.8Zm15.5-5.7c.8 2 1.4 3 1.8 3 .5 0 .7-2.1-.6-2.1 2.1-.5 2.5 1.3 1.6 2.3.8-.5 2-.7 2.6.6-.5 1.2-1.8 1-2.6.5.9 1 .5 2.8-1.6 2.3 1.3 0 1.1-2.2.6-2.2-.4 0-1 1-1.8 3H29c.3-1.3.4-2.4.4-3.6a15 15 0 0 0-.4-3.7Zm-23.6 0c-.3 1.3-.5 2.5-.5 3.8 0 1.2.2 2.3.5 3.6h-.1c-.8-2-1.4-3-1.8-3-.6 0-.8 2.2.5 2.2-2.1.4-2.5-1.3-1.5-2.3-.8.4-2.1.7-2.7-.5.6-1.3 1.9-1 2.7-.6-1-1-.6-2.8 1.5-2.3-1.3 0-1 2.2-.5 2.2.4 0 1-1 1.8-3h.1ZM17.4 15a2.4 2.4 0 1 1-.1 4.8 2.4 2.4 0 0 1 0-4.8Zm-3.7-3a1.7 1.7 0 0 1 1.1 3 1.8 1.8 0 0 1-2.9-1.3c0-1 .8-1.7 1.8-1.7Zm7.3 0a1.7 1.7 0 0 1 1.2 3 1.8 1.8 0 0 1-3-1.3c0-1 .8-1.7 1.8-1.7ZM10.7 9.1a1.7 1.7 0 0 1 1.3 3 1.8 1.8 0 0 1-2.9-1.4c0-.8.8-1.5 1.6-1.6Zm13.4 0a1.8 1.8 0 0 1 1.2 3 1.8 1.8 0 0 1-2.9-1.4c0-.9.8-1.6 1.8-1.6ZM9.3 3.5l1 2.2A4 4 0 0 0 7.7 7c.6.3 1.8.1 4-.6v.1a9.7 9.7 0 0 0-3 2.3c-.8.8-1.5 1.7-2.2 2.9h-.1c.8-2.1 1-3.4.6-4-.7.7-1.3 1.5-1.3 2.8L3.4 9.3c1.3-.4 2.4-1 3.1-1.8-.5-.3-1.7 0-2.4.4l3.7-3.7c-.3.7-.7 1.9-.5 2.5.9-.9 1.5-2 2-3.2Zm16-.1a9.6 9.6 0 0 0 1.9 3.3c.2-.6-.1-2-.4-2.5l3.6 3.6c-.5-.2-1.8-.6-2.4-.3.8.7 1.9 1.4 3.3 1.8L29 10.5a4 4 0 0 0-1.2-2.8c-.4.5-.3 1.9.4 3.9-.7-1.1-1.4-2-2.3-2.8-.8-1-1.8-1.7-3-2.4h.2c2 .7 3.3.8 3.8.5a4 4 0 0 0-2.8-1.3l1.2-2.2Zm-8-3.4c1.3.6 1 1.9.6 2.7 1-1 2.8-.6 2.3 1.5 0-1.3-2.2-1-2.2-.5 0 .4 1 1 3 1.8v.1a13.7 13.7 0 0 0-7.3 0v-.1c2-.8 3-1.4 3-1.8 0-.6-2.2-.8-2.2.5-.5-2 1.1-2.5 2.3-1.5-.5-.8-.7-2.1.6-2.7ZM45 8l4.5 7.5L54 8h5l-6.8 10.5L59 29h-5l-4.5-7.5L45 29h-5l6.5-10.5L40 8h5Zm16.5 8a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm16 13.5c5.7 0 9.5-3.5 9.5-9v-2.8h-9V21h4.5c0 3-2.1 4.8-5 4.8-3.5 0-5.5-2.7-5.5-7.3s2-7.3 5.5-7.3c2.5 0 4.2 1.2 4.8 3.3h4.5c-.8-4.5-4.3-7-9.3-7-6 0-10 4.3-10 11s3.8 11 10 11Zm22.5 0c6.1 0 10-4.2 10-11s-3.9-11-10-11-10 4.2-10 11 3.8 11 10 11Zm0-3.8c-3.5 0-5.5-2.8-5.5-7.2s2-7.3 5.5-7.3 5.5 2.8 5.5 7.3-2 7.3-5.5 7.3Zm53.5 3.3h4.5v-6.5l2-2.3 6 8.8h5.5l-8.3-11.8L171 8h-5l-8 9.5V8h-4.5v21Zm-12 .3c5.6 0 8.8-3 8.8-7.8V8h-4.6v13c0 2.8-1.4 4.5-4.2 4.5-2.8 0-4.3-1.8-4.3-4.5V8h-4.4v13.5c0 4.8 3.1 7.8 8.7 7.8Zm-23.8-.3h5.5L130 8h-4.8l-4.7 16.5L115.7 8H111l6.8 21Z"/>
3
4
  </svg>
@@ -1,22 +1,22 @@
1
1
  {%- from "../site-search/macro.njk" import appSiteSearch -%}
2
- <header class="govuk-header app-header" role="banner" data-module="govuk-header">
2
+ {%- if options.navigation -%}
3
+ {%- set headerType = "full-width-border" -%}
4
+ {% elif layout == "product" or layout == "collection" %}
5
+ {%- set headerType = "no-border" -%}
6
+ {%- endif -%}
7
+ <header class="govuk-header app-header{% if headerType %} app-header--{{ headerType }}{% endif %}" role="banner" data-module="govuk-header">
3
8
  <div class="govuk-header__container govuk-width-container app-header__container">
4
9
  <div class="govuk-header__logo app-header__logo">
5
- <a href="{{ params.homepageUrl | default("/") | url }}" class="govuk-header__link govuk-header__link--homepage">
6
- <span class="govuk-header__logotype">
7
- {% if params.organisationLogo == "crown" %}
8
- {% include "./_crown.svg" %}
9
- {% elif params.organisationLogo == "royal-arms" %}
10
- {% include "./_royal-arms.svg" %}
11
- {% elif params.organisationLogo == "x-govuk" %}
12
- {% include "./_x-govuk.svg" %}
13
- {% elif params.organisationLogo %}
14
- {{ params.organisationLogo | safe }}
15
- {% endif %}
16
- <span class="govuk-header__logotype-text">
17
- {{ params.organisationName | default("GOV.UK") }}
18
- </span>
19
- </span>
10
+ <a href="{{ params.homepageUrl | default("/") }}" class="govuk-header__link govuk-header__link--homepage">
11
+ {% if params.logotype == "x-govuk" %}
12
+ {% include "./_x-govuk.svg" %}
13
+ {% elif params.logotype.html %}
14
+ {{ params.logotype.html }}
15
+ {% elif params.logotype.text %}
16
+ <span class="app-header__logotype">{{ params.logotype.text }}</span>
17
+ {% else %}
18
+ {% include "./_govuk.svg" %}
19
+ {% endif %}
20
20
  {% if params.productName %}
21
21
  <span class="govuk-header__product-name">
22
22
  {{ params.productName }}
@@ -9,6 +9,29 @@
9
9
  margin-bottom: 0;
10
10
  }
11
11
 
12
+ h1 {
13
+ max-width: 15em;
14
+ }
15
+
16
+ h2 {
17
+ max-width: 20em;
18
+ }
19
+
20
+ h3 {
21
+ max-width: 30em;
22
+ }
23
+
24
+ h4,
25
+ h5,
26
+ h6,
27
+ p,
28
+ ul:not([class]),
29
+ ol,
30
+ img,
31
+ video {
32
+ max-width: 38em;
33
+ }
34
+
12
35
  // Indicate abbreviations which have a title
13
36
  abbr {
14
37
  border-bottom: 1px dotted $govuk-secondary-text-colour;
@@ -125,9 +148,9 @@
125
148
  .x-govuk-code__language--shell {
126
149
  background-color: govuk-colour("black");
127
150
  border: $govuk-focus-width solid govuk-colour("white");
151
+ -webkit-font-smoothing: auto;
128
152
  margin-left: $govuk-focus-width * -1;
129
153
  margin-right: $govuk-focus-width * -1;
130
- -webkit-font-smoothing: auto;
131
154
 
132
155
  code {
133
156
  filter: invert(100%);
@@ -1,40 +1,43 @@
1
1
  // Site search using Accessible autocomplete
2
- // below styles are based on the default accessible autocomplete style sheet
3
-
4
- @function encode-hex($hex) {
5
- // Turn colour into a string
6
- $output: inspect($hex);
7
- // Slice the '#' from the start of the string so we can add it back on encoded.
8
- $output: str-slice($output, 2);
9
- // Add the '#' back on the start, but as an encoded character for embedding.
10
- @return "%23" + $output;
11
- }
2
+ // Styles below are based on the default accessible autocomplete style sheet
12
3
 
13
4
  $icon-size: 40px;
14
5
 
15
6
  .app-site-search {
16
7
  float: left;
17
- margin-bottom: govuk-spacing(2);
18
- position: relative;
19
- width: 100%;
8
+ padding-bottom: govuk-spacing(1);
9
+ padding-top: govuk-spacing(1);
20
10
 
21
- @include govuk-media-query($from: 900px) {
11
+ @include govuk-media-query($from: desktop) {
22
12
  float: right;
23
- margin: 0;
24
- margin-top: -5px; // Negative margin to vertically align search in header
25
- width: 300px;
26
13
  }
27
14
 
28
- .no-js & {
29
- display: none;
15
+ &:defined {
16
+ position: relative;
17
+ width: 100%;
30
18
 
31
- @include govuk-media-query($from: 900px) {
32
- display: block;
19
+ @include govuk-media-query($from: desktop) {
20
+ margin-top: -10px;
21
+ width: 300px;
33
22
  }
23
+ }
24
+ }
34
25
 
35
- @include govuk-media-query($from: 900px) {
36
- text-align: right;
37
- }
26
+ .app-site-search__link {
27
+ @include govuk-link-style-inverse;
28
+
29
+ display: inline-block;
30
+ padding-bottom: govuk-spacing(1);
31
+ padding-top: govuk-spacing(1);
32
+ text-decoration: none;
33
+
34
+ &:hover {
35
+ text-decoration: underline;
36
+ text-decoration-thickness: 3px;
37
+ }
38
+
39
+ &:focus {
40
+ @include govuk-focused-text;
38
41
  }
39
42
  }
40
43
 
@@ -45,6 +48,8 @@ $icon-size: 40px;
45
48
 
46
49
  .app-site-search__hint,
47
50
  .app-site-search__input {
51
+ -webkit-appearance: none;
52
+ appearance: none;
48
53
  border: $govuk-border-width-form-element solid govuk-colour("white");
49
54
  border-radius: 0; // Safari 10 on iOS adds implicit border rounding.
50
55
  box-sizing: border-box;
@@ -53,16 +58,15 @@ $icon-size: 40px;
53
58
  padding: govuk-spacing(1);
54
59
  padding-left: $icon-size - govuk-spacing(1);
55
60
  width: 100%;
56
- -webkit-appearance: none;
57
61
  }
58
62
 
59
63
  .app-site-search__hint {
60
- position: absolute;
61
64
  color: govuk-colour("mid-grey");
65
+ position: absolute;
62
66
  }
63
67
 
64
68
  .app-site-search__input {
65
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36' width='40' height='40'%3E%3Cpath d='M25.7 24.8L21.9 21c.7-1 1.1-2.2 1.1-3.5 0-3.6-2.9-6.5-6.5-6.5S10 13.9 10 17.5s2.9 6.5 6.5 6.5c1.6 0 3-.6 4.1-1.5l3.7 3.7 1.4-1.4zM12 17.5c0-2.5 2-4.5 4.5-4.5s4.5 2 4.5 4.5-2 4.5-4.5 4.5-4.5-2-4.5-4.5z' fill='#{encode-hex(govuk-colour("dark-grey"))}'%3E%3C/path%3E%3C/svg%3E");
69
+ background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36' width='40' height='40'><path d='M25.7 24.8L21.9 21c.7-1 1.1-2.2 1.1-3.5 0-3.6-2.9-6.5-6.5-6.5S10 13.9 10 17.5s2.9 6.5 6.5 6.5c1.6 0 3-.6 4.1-1.5l3.7 3.7 1.4-1.4zM12 17.5c0-2.5 2-4.5 4.5-4.5s4.5 2 4.5 4.5-2 4.5-4.5 4.5-4.5-2-4.5-4.5z' fill='%23505a5f'></path></svg>");
66
70
  background-position: center left -2px;
67
71
  background-repeat: no-repeat;
68
72
  background-size: $icon-size $icon-size;
@@ -131,8 +135,8 @@ $icon-size: 40px;
131
135
  border-width: 1px 0;
132
136
  cursor: pointer;
133
137
  display: block;
134
- position: relative;
135
138
  padding: govuk-spacing(2);
139
+ position: relative;
136
140
 
137
141
  &:first-of-type {
138
142
  border-top-width: 0;
@@ -153,8 +157,8 @@ $icon-size: 40px;
153
157
 
154
158
  .app-site-search__option--focused,
155
159
  .app-site-search__option:hover {
156
- background-color: govuk-colour("blue");
157
- border-color: govuk-colour("blue");
160
+ background-color: $govuk-link-colour;
161
+ border-color: $govuk-link-colour;
158
162
  color: govuk-colour("white");
159
163
  // Add a transparent outline for when users change their colours.
160
164
  outline: 3px solid transparent;
@@ -177,10 +181,6 @@ $icon-size: 40px;
177
181
  @include govuk-font($size: 19);
178
182
  }
179
183
 
180
- .app-site-search__link {
181
- display: none;
182
- }
183
-
184
184
  .app-site-search--section {
185
185
  @include govuk-font($size: 16);
186
186
  color: $govuk-secondary-text-colour;
@@ -201,23 +201,6 @@ $icon-size: 40px;
201
201
 
202
202
  .app-site-search__separator {
203
203
  display: inline-block;
204
- margin-right: govuk-spacing(1);
205
204
  margin-left: govuk-spacing(1);
206
- }
207
-
208
- // No JavaScript fallback styles
209
- .no-js .app-site-search__link {
210
- display: none;
211
-
212
- @include govuk-media-query($from: 900px) {
213
- color: govuk-colour("white");
214
- display: inline-block;
215
- margin-top: 10px;
216
- }
217
- }
218
-
219
- .no-js .app-site-search__link:focus {
220
- @include govuk-media-query($from: 900px) {
221
- color: govuk-colour("black");
222
- }
205
+ margin-right: govuk-spacing(1);
223
206
  }
@@ -1,147 +1,137 @@
1
- /* global XMLHttpRequest */
2
1
  import accessibleAutocomplete from 'accessible-autocomplete/dist/accessible-autocomplete.min.js'
3
2
 
4
- // CONSTANTS
5
- const TIMEOUT = 10 // Time to wait before giving up fetching the search index
6
- const STATE_DONE = 4 // XHR client readyState DONE
3
+ export class SiteSearchElement extends HTMLElement {
4
+ constructor() {
5
+ super()
6
+
7
+ this.statusMessage = null
8
+ this.searchInputId = 'app-site-search__input'
9
+ this.searchIndex = null
10
+ this.searchIndexUrl = this.getAttribute('index')
11
+ this.searchLabel = this.getAttribute('label')
12
+ this.searchResults = []
13
+ this.searchTimeout = 10
14
+ this.sitemapLink = this.querySelector('.app-site-search__link')
15
+ }
7
16
 
8
- let searchIndex = null
9
- let statusMessage = null
10
- let searchQuery = ''
11
- let searchCallback = function () {}
12
- let searchResults = []
17
+ async fetchSearchIndex(indexUrl) {
18
+ this.statusMessage = 'Loading search index'
13
19
 
14
- export function Search ($module) {
15
- this.$module = $module
16
- }
20
+ try {
21
+ const response = await fetch(indexUrl, {
22
+ signal: AbortSignal.timeout(this.searchTimeout * 1000)
23
+ })
17
24
 
18
- Search.prototype.fetchSearchIndex = function (indexUrl, callback) {
19
- const request = new XMLHttpRequest()
20
- request.open('GET', indexUrl, true)
21
- request.timeout = TIMEOUT * 1000
22
- statusMessage = 'Loading search index'
23
- request.onreadystatechange = function () {
24
- if (request.readyState === STATE_DONE) {
25
- if (request.status === 200) {
26
- const response = request.responseText
27
- const json = JSON.parse(response)
28
- statusMessage = 'No results found'
29
- searchIndex = json
30
- callback(json)
31
- } else {
32
- statusMessage = 'Failed to load the search index'
25
+ if (!response.ok) {
26
+ throw Error('Search index not found')
33
27
  }
28
+
29
+ const json = await response.json()
30
+ this.statusMessage = 'No results found'
31
+ this.searchIndex = json
32
+ } catch (error) {
33
+ this.statusMessage = 'Failed to load search index'
34
+ console.error(this.statusMessage, error.message)
34
35
  }
35
36
  }
36
- request.send()
37
- }
38
37
 
39
- Search.prototype.findResults = function (searchQuery, searchIndex) {
40
- return searchIndex.filter(item => {
41
- const regex = new RegExp(searchQuery, 'gi')
42
- return item.title.match(regex) || item.templateContent.match(regex)
43
- })
44
- }
45
-
46
- Search.prototype.renderResults = function () {
47
- if (!searchIndex) {
48
- return searchCallback(searchResults)
38
+ findResults(searchQuery, searchIndex) {
39
+ return searchIndex.filter((item) => {
40
+ const regex = new RegExp(searchQuery, 'gi')
41
+ return item.title.match(regex) || item.templateContent.match(regex)
42
+ })
49
43
  }
50
44
 
51
- const resultsArray = this.findResults(searchQuery, searchIndex).reverse()
45
+ renderResults(query, populateResults) {
46
+ if (!this.searchIndex) {
47
+ return populateResults(this.searchResults)
48
+ }
52
49
 
53
- searchResults = resultsArray.map(function (result) {
54
- return result
55
- })
50
+ this.searchResults = this.findResults(query, this.searchIndex).reverse()
56
51
 
57
- searchCallback(searchResults)
58
- }
52
+ populateResults(this.searchResults)
53
+ }
59
54
 
60
- Search.prototype.handleSearchQuery = function (query, callback) {
61
- searchQuery = query
62
- searchCallback = callback
55
+ handleOnConfirm(result) {
56
+ const path = result.url
57
+ if (!path) {
58
+ return
59
+ }
63
60
 
64
- this.renderResults()
65
- }
61
+ window.location.href = path
62
+ }
66
63
 
67
- Search.prototype.handleOnConfirm = function (result) {
68
- const path = result.url
69
- if (!path) {
70
- return
64
+ handleNoResults() {
65
+ return this.statusMessage
71
66
  }
72
- window.location.href = path
73
- }
74
67
 
75
- Search.prototype.inputValueTemplate = function (result) {
76
- if (result) {
77
- return result.title
68
+ inputValueTemplate(result) {
69
+ if (result) {
70
+ return result.title
71
+ }
78
72
  }
79
- }
80
73
 
81
- Search.prototype.resultTemplate = function (result) {
82
- if (result) {
83
- const element = document.createElement('span')
84
- const resultTitle = result.title
85
- element.textContent = resultTitle
74
+ searchTemplate() {
75
+ const labelElement = document.createElement('label')
76
+ labelElement.classList.add('govuk-visually-hidden')
77
+ labelElement.htmlFor = this.searchInputId
78
+ labelElement.textContent = this.searchLabel
79
+
80
+ const searchElement = document.createElement('search')
81
+ searchElement.append(labelElement)
82
+
83
+ return searchElement
84
+ }
86
85
 
87
- if (result.hasFrontmatterDate || result.section) {
88
- const section = document.createElement('span')
89
- section.className = 'app-site-search--section'
86
+ resultTemplate(result) {
87
+ if (result) {
88
+ const element = document.createElement('span')
89
+ element.textContent = result.title
90
90
 
91
- if (result.hasFrontmatterDate && result.section) {
92
- section.innerHTML = `${result.section}<br>${result.date}`
93
- } else {
94
- section.innerHTML = result.section || result.date
91
+ if (result.hasFrontmatterDate || result.section) {
92
+ const section = document.createElement('span')
93
+ section.className = 'app-site-search--section'
94
+
95
+ section.innerHTML =
96
+ result.hasFrontmatterDate && result.section
97
+ ? `${result.section}<br>${result.date}`
98
+ : result.section || result.date
99
+
100
+ element.appendChild(section)
95
101
  }
96
102
 
97
- element.appendChild(section)
103
+ return element.innerHTML
98
104
  }
99
-
100
- return element.innerHTML
101
105
  }
102
- }
103
106
 
104
- Search.prototype.init = function () {
105
- const $module = this.$module
106
- if (!$module) {
107
- return
108
- }
107
+ async connectedCallback() {
108
+ await this.fetchSearchIndex(this.searchIndexUrl)
109
109
 
110
- // The Accessible Autocomplete only works in IE9+ so we can use newer
111
- // JavaScript features here but need to check for browsers that do not have
112
- // these features and force the fallback by returning early.
113
- // http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
114
- const featuresNeeded = (
115
- 'querySelector' in document &&
116
- 'addEventListener' in window &&
117
- !!(Array.prototype && Array.prototype.forEach)
118
- )
119
-
120
- if (!featuresNeeded) {
121
- return
122
- }
110
+ // Remove fallback link to sitemap
111
+ if (this.sitemapLink) {
112
+ this.sitemapLink.remove()
113
+ }
123
114
 
124
- accessibleAutocomplete({
125
- element: $module,
126
- id: 'app-site-search__input',
127
- cssNamespace: 'app-site-search',
128
- displayMenu: 'overlay',
129
- placeholder: $module.querySelector('[for=app-site-search__input]').innerText,
130
- confirmOnBlur: false,
131
- autoselect: true,
132
- source: this.handleSearchQuery.bind(this),
133
- onConfirm: this.handleOnConfirm,
134
- templates: {
135
- inputValue: this.inputValueTemplate,
136
- suggestion: this.resultTemplate
137
- },
138
- tNoResults: function () { return statusMessage }
139
- })
140
-
141
- const searchIndexUrl = $module.getAttribute('data-search-index')
142
- this.fetchSearchIndex(searchIndexUrl, function () {
143
- this.renderResults()
144
- }.bind(this))
115
+ // Add `search` element with `label`
116
+ const search = this.searchTemplate()
117
+ this.append(search)
118
+
119
+ accessibleAutocomplete({
120
+ element: search,
121
+ id: this.searchInputId,
122
+ cssNamespace: 'app-site-search',
123
+ displayMenu: 'overlay',
124
+ minLength: 2,
125
+ placeholder: this.searchLabel,
126
+ confirmOnBlur: false,
127
+ autoselect: true,
128
+ source: this.renderResults.bind(this),
129
+ onConfirm: this.handleOnConfirm,
130
+ templates: {
131
+ inputValue: this.inputValueTemplate,
132
+ suggestion: this.resultTemplate
133
+ },
134
+ tNoResults: this.handleNoResults.bind(this)
135
+ })
136
+ }
145
137
  }
146
-
147
- export default Search
@@ -1,4 +1,5 @@
1
- <div class="app-site-search govuk-!-display-none-print" data-module="app-site-search" data-search-index="{{ params.indexPath | url }}">
2
- <label class="govuk-visually-hidden" for="app-site-search__input">{{ params.label | default("Search site") }}</label>
3
- <a class="app-site-search__link govuk-link-no-visited" href="{{ params.sitemapPath | url }}">Sitemap</a>
4
- </div>
1
+ <site-search class="app-site-search govuk-!-display-none-print" index="{{ params.indexPath | htmlBaseUrl }}" label="{{ params.label | default("Search site") }}">
2
+ {%- if params.sitemapPath -%}
3
+ <a class="app-site-search__link" href="{{ params.sitemapPath }}">Sitemap</a>
4
+ {%- endif -%}
5
+ </site-search>