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

Use locally installed govuk-frontend for component names, files, data #4041

Merged
merged 14 commits into from
Aug 14, 2023

Conversation

colinrotherham
Copy link
Contributor

@colinrotherham colinrotherham commented Aug 3, 2023

This PR introduces an improved renderHTML() renderComponent() helper for Nunjucks and HTML previews

By following the Stats for previous version guidance for legacy GOV.UK Frontend versions this also ensures:

  1. Nunjucks environment uses locally installed GOV.UK Frontend
  2. Component helpers use locally installed GOV.UK Frontend

When a legacy version is installed locally, our helper functions that render components, provide their names, list files or read macro options YAML were doing so from packages/govuk-frontend despite legacy CSS and JS being previewed.

npm install [email protected] --save --workspace govuk-frontend-review

It's part of our work to fully test our components:

Since a locally installed GOV.UK Frontend won't have an npm published src directory, this work requires:

Component rendering

Previously we juggled multiple Nunjucks environments and rendered our components in multiple ways.

The component helper renderComponent() now consolidates these four:

1. HTML validation using helper renderHTML()

// Validate component examples
for (const { name: componentName, examples } of componentsData) {
const exampleTasks = examples.map(async ({ name: exampleName, data }) => {
const html = renderHTML(componentName, data)

2. Component previews using Nunjucks renderString()

res.locals.componentView = env.renderString(outdent`
{% from "govuk/components/${componentName}/macro.njk" import ${macroName} %}
{{ ${macroName}(${macroParameters}) }}
`, {})

3. Component HTML code using Nunjucks render()

const templatePath = packageTypeToPath('govuk-frontend', {
modulePath: `components/${componentName}/template.njk`,
moduleRoot: paths.app
})
// Render to HTML
const html = this.env.render(templatePath, { params }).trim()

4. Design System HTML fixtures using Nunjucks render()

html: await new Promise((resolve, reject) => {
return nunjucks.render(template, context, (error, result) => {
return error ? reject(error) : resolve(result?.trim() ?? '')
})
})

@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 3, 2023 17:25 Inactive
@colinrotherham colinrotherham marked this pull request as draft August 3, 2023 18:30
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 4, 2023 07:50 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 4, 2023 08:12 Inactive
@colinrotherham colinrotherham changed the base branch from main to component-fixtures August 4, 2023 08:20
@colinrotherham colinrotherham marked this pull request as ready for review August 4, 2023 08:20
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 4, 2023 08:46 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 4, 2023 15:31 Inactive
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 8, 2023 14:03 Inactive
Base automatically changed from component-fixtures to main August 14, 2023 11:45
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 14, 2023 11:59 Inactive
This move gives us separate Nunjucks render functions (without Cheerio) to consolidate code across tests and the review app

We typically keep test and development tools in “govuk-frontend-helpers” so we’ll keep Cheerio render functions there
This gives us a single place to manage our Nunjucks environment so we don’t need to manage search paths from multiple places
In preparation for a new “Package options” parameter so we can share the same helper but pass in a local Nunjucks environment where required
This was previously handled by `getComponentNames()` to filter component with JavaScript functionality

In preparation for a new “Package options” parameter, it’s simpler to split it out since the filter parameter is also optional
Our helpers should always share the same Nunjucks environment to prevent views from `packages/govuk-frontend` running JavaScript from a locally installed legacy version
…iles

The previous default `''` incorrectly included a double slash:

```
`src/govuk/components//**/*`
```
This fixes an issue where `packages/govuk-frontend` provides a list of component names, files or even YAML component data even though we have a locally installed legacy version
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 14, 2023 12:08 Inactive
@romaricpascal
Copy link
Member

romaricpascal commented Aug 14, 2023

Ran a diff of the package vs. main1 and it seems that some leading and trailing whitespace snuck in the fixtures html.

Here's a sample (diff is too larged to be pasted in the comment, I'll work out how to attach it attached a gziped version of it.

# ...
diff --color -bur --ex .tmp/package-dist--main/govuk/components/accordion/fixtures.json packages/govuk-frontend/dist/govuk/components/accordion/fixtures.json
--- .tmp/package-dist--main/govuk/components/accordion/fixtures.json	2023-08-14 12:50:57
+++ packages/govuk-frontend/dist/govuk/components/accordion/fixtures.json	2023-08-14 14:37:04
@@ -27,7 +27,7 @@
             "hidden": false,
             "description": "",
             "previewLayoutModifiers": [],
-            "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"default-example\">\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-1\">\n              Section A\n            </span>\n          </h2>\n        </div>\n        <div id=\"default-example-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-1\">\n            <p class=\"govuk-body\">We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.</p>\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-2\">\n              Section B\n            </span>\n          </h2>\n        </div>\n        <div id=\"default-example-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>"
+            "html": "\n\n<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"default-example\">\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-1\">\n              Section A\n            </span>\n          </h2>\n        </div>\n        <div id=\"default-example-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-1\">\n            <p class=\"govuk-body\">We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.</p>\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-2\">\n              Section B\n            </span>\n          </h2>\n        </div>\n        <div id=\"default-example-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>\n"
         },
         {
             "name": "with additional descriptions",
@@ -61,7 +61,7 @@
             "hidden": false,
             "description": "",
             "previewLayoutModifiers": [],
-            "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-descriptions\">\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-1\">\n              Test\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-1\">\n              Additional description\n            </div>\n        </div>\n        <div id=\"with-descriptions-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-1\">\n            <p class=\"govuk-body\">\n  We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.\n</p>\n<ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 1</li>\n</ul>\n\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-2\">\n              Test 2\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-2\">\n              <span class=\"govuk-!-font-weight-regular\">Additional description (wrapped in span)</span>\n            </div>\n        </div>\n        <div id=\"with-descriptions-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>"
+            "html": "\n\n<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-descriptions\">\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-1\">\n              Test\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-1\">\n              Additional description\n            </div>\n        </div>\n        <div id=\"with-descriptions-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-1\">\n            <p class=\"govuk-body\">\n  We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.\n</p>\n<ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 1</li>\n</ul>\n\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-2\">\n              Test 2\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-2\">\n              <span class=\"govuk-!-font-weight-regular\">Additional description (wrapped in span)</span>\n            </div>\n        </div>\n        <div id=\"with-descriptions-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>\n"
         },
         {
             "name": "with long content and description",
@@ -95,7 +95,7 @@
             "hidden": false,
             "description": "",
             "previewLayoutModifiers": [],
-            "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-long-content-and-description\">\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-long-content-and-description-heading-1\">\n              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis tortor porttitor.\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-long-content-and-description-summary-1\">\n              Etiam diam dui, tempus ut pharetra in, aliquet non dui. Nunc pulvinar maximus tortor, ac finibus augue congue vitae. Donec sed cursus lorem.\n            </div>\n        </div>\n        <div id=\"with-long-content-and-description-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-long-content-and-description-heading-1\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 1</li>\n</ul>\n\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-long-content-and-description-heading-2\">\n              Praesent faucibus leo feugiat libero pharetra lacinia. Aliquam aliquet ante vitae mollis vestibulum.\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-long-content-and-description-summary-2\">\n              <span class=\"govuk-!-font-weight-regular\">Maecenas nec <abbr>est</abbr> sapien. Etiam varius luctus mauris non porttitor. </span>\n            </div>\n        </div>\n        <div id=\"with-long-content-and-description-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-long-content-and-description-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>"
+            "html": "\n\n<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-long-content-and-description\">\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-long-content-and-description-heading-1\">\n              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis tortor porttitor.\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-long-content-and-description-summary-1\">\n              Etiam diam dui, tempus ut pharetra in, aliquet non dui. Nunc pulvinar maximus tortor, ac finibus augue congue vitae. Donec sed cursus lorem.\n            </div>\n        </div>\n        <div id=\"with-long-content-and-description-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-long-content-and-description-heading-1\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 1</li>\n</ul>\n\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"with-long-content-and-description-heading-2\">\n              Praesent faucibus leo feugiat libero pharetra lacinia. Aliquam aliquet ante vitae mollis vestibulum.\n            </span>\n          </h2>\n            <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-long-content-and-description-summary-2\">\n              <span class=\"govuk-!-font-weight-regular\">Maecenas nec <abbr>est</abbr> sapien. Etiam varius luctus mauris non porttitor. </span>\n            </div>\n        </div>\n        <div id=\"with-long-content-and-description-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-long-content-and-description-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>\n"
         },
         {
             "name": "with one section open",
@@ -124,7 +124,7 @@
             "hidden": false,
             "description": "",
             "previewLayoutModifiers": [],
-            "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"one-section-open-example\">\n      <div class=\"govuk-accordion__section govuk-accordion__section--expanded\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"one-section-open-example-heading-1\">\n              Section A\n            </span>\n          </h2>\n        </div>\n        <div id=\"one-section-open-example-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"one-section-open-example-heading-1\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 1</li>\n</ul>\n\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"one-section-open-example-heading-2\">\n              Section B\n            </span>\n          </h2>\n        </div>\n        <div id=\"one-section-open-example-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"one-section-open-example-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>"
+            "html": "\n\n<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"one-section-open-example\">\n      <div class=\"govuk-accordion__section govuk-accordion__section--expanded\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"one-section-open-example-heading-1\">\n              Section A\n            </span>\n          </h2>\n        </div>\n        <div id=\"one-section-open-example-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"one-section-open-example-heading-1\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 1</li>\n</ul>\n\n        </div>\n      </div>\n      <div class=\"govuk-accordion__section\">\n        <div class=\"govuk-accordion__section-header\">\n          <h2 class=\"govuk-accordion__section-heading\">\n            <span class=\"govuk-accordion__section-button\" id=\"one-section-open-example-heading-2\">\n              Section B\n            </span>\n          </h2>\n        </div>\n        <div id=\"one-section-open-example-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"one-section-open-example-heading-2\">\n            <ul class=\"govuk-list govuk-list--bullet\">\n  <li>Example item 2</li>\n</ul>\n\n        </div>\n      </div>\n</div>\n"
         },
# ...

Footnotes

  1. Built main, saved packages/govuk-frontend/dist in .tmp, built the branch and ran diff -bur excluding sourcemaps.

We used to add `.trim()` before moving to `renderComponent()`
@govuk-design-system-ci govuk-design-system-ci temporarily deployed to govuk-frontend-pr-4041 August 14, 2023 14:02 Inactive
Copy link
Member

@romaricpascal romaricpascal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff is clean with the addition of .trim(). I think it's worth a quick highlight of what moved where at dev catch-up to make everyone aware of the centralisation of the Nunjucks rendering 😊

@colinrotherham colinrotherham merged commit 27df79b into main Aug 14, 2023
@colinrotherham colinrotherham deleted the component-libs-move branch August 14, 2023 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

3 participants