From c7fda23207f2efa36799228e72d768785f226d80 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Mon, 14 Aug 2023 13:07:51 +0100 Subject: [PATCH 01/14] Move all component libs into `govuk-frontend-lib/components` --- packages/govuk-frontend-review/src/app.mjs | 8 +- .../govuk-frontend-review/src/app.test.mjs | 2 +- .../govuk-prototype-kit.config.mjs | 7 +- .../accordion/accessibility.test.mjs | 2 +- .../components/accordion/accordion.test.js | 2 +- .../components/accordion/template.test.js | 2 +- .../back-link/accessibility.test.mjs | 2 +- .../components/back-link/template.test.js | 2 +- .../breadcrumbs/accessibility.test.mjs | 2 +- .../components/breadcrumbs/template.test.js | 2 +- .../components/button/accessibility.test.mjs | 2 +- .../govuk/components/button/button.test.js | 6 +- .../govuk/components/button/template.test.js | 2 +- .../character-count/accessibility.test.mjs | 2 +- .../character-count/character-count.test.js | 2 +- .../character-count/template.test.js | 2 +- .../checkboxes/accessibility.test.mjs | 2 +- .../components/checkboxes/checkboxes.test.js | 2 +- .../components/checkboxes/template.test.js | 2 +- .../components/components.template.test.js | 2 +- .../cookie-banner/accessibility.test.mjs | 2 +- .../components/cookie-banner/template.test.js | 2 +- .../date-input/accessibility.test.mjs | 2 +- .../components/date-input/template.test.js | 2 +- .../components/details/accessibility.test.mjs | 2 +- .../govuk/components/details/template.test.js | 2 +- .../error-message/accessibility.test.mjs | 2 +- .../components/error-message/template.test.js | 2 +- .../error-summary/accessibility.test.mjs | 2 +- .../error-summary/error-summary.test.js | 2 +- .../components/error-summary/template.test.js | 2 +- .../exit-this-page/accessibility.test.mjs | 2 +- .../exit-this-page/exit-this-page.test.js | 2 +- .../exit-this-page/template.test.js | 2 +- .../fieldset/accessibility.test.mjs | 2 +- .../components/fieldset/template.test.js | 2 +- .../file-upload/accessibility.test.mjs | 2 +- .../components/file-upload/template.test.js | 2 +- .../components/footer/accessibility.test.mjs | 2 +- .../govuk/components/footer/template.test.js | 2 +- .../components/header/accessibility.test.mjs | 2 +- .../govuk/components/header/header.test.js | 2 +- .../govuk/components/header/template.test.js | 2 +- .../components/hint/accessibility.test.mjs | 2 +- .../govuk/components/hint/template.test.js | 2 +- .../components/input/accessibility.test.mjs | 2 +- .../govuk/components/input/template.test.js | 2 +- .../inset-text/accessibility.test.mjs | 2 +- .../components/inset-text/template.test.js | 2 +- .../components/label/accessibility.test.mjs | 2 +- .../govuk/components/label/template.test.js | 2 +- .../accessibility.test.mjs | 2 +- .../notification-banner.test.js | 2 +- .../notification-banner/template.test.js | 2 +- .../pagination/accessibility.test.mjs | 2 +- .../components/pagination/template.test.js | 2 +- .../components/panel/accessibility.test.mjs | 2 +- .../govuk/components/panel/template.test.js | 2 +- .../phase-banner/accessibility.test.mjs | 2 +- .../components/phase-banner/template.test.js | 2 +- .../components/radios/accessibility.test.mjs | 2 +- .../govuk/components/radios/radios.test.js | 2 +- .../govuk/components/radios/template.test.js | 2 +- .../components/select/accessibility.test.mjs | 2 +- .../govuk/components/select/template.test.js | 2 +- .../skip-link/accessibility.test.mjs | 2 +- .../components/skip-link/skip-link.test.js | 2 +- .../components/skip-link/template.test.js | 2 +- .../summary-list/accessibility.test.mjs | 2 +- .../components/summary-list/template.test.js | 2 +- .../components/table/accessibility.test.mjs | 2 +- .../govuk/components/table/template.test.js | 2 +- .../components/tabs/accessibility.test.mjs | 2 +- .../src/govuk/components/tabs/tabs.test.js | 2 +- .../govuk/components/tabs/template.test.js | 2 +- .../components/tag/accessibility.test.mjs | 2 +- .../src/govuk/components/tag/template.test.js | 2 +- .../task-list/accessibility.test.mjs | 2 +- .../components/task-list/template.test.js | 2 +- .../textarea/accessibility.test.mjs | 2 +- .../components/textarea/template.test.js | 2 +- .../warning-text/accessibility.test.mjs | 2 +- .../components/warning-text/template.test.js | 2 +- .../tasks/build/package.test.mjs | 8 +- packages/govuk-frontend/tasks/fixtures.mjs | 2 +- shared/lib/components.js | 141 +++++++++++++++++ ...s.unit.test.js => components.unit.test.js} | 2 +- shared/lib/files.js | 144 +----------------- shared/lib/index.js | 4 +- shared/stats/src/index.mjs | 7 +- shared/tasks/browser.mjs | 4 +- shared/tasks/components.mjs | 10 +- 92 files changed, 249 insertions(+), 254 deletions(-) create mode 100644 shared/lib/components.js rename shared/lib/{files.unit.test.js => components.unit.test.js} (94%) diff --git a/packages/govuk-frontend-review/src/app.mjs b/packages/govuk-frontend-review/src/app.mjs index 2aca799e66..ddd8ec9c55 100644 --- a/packages/govuk-frontend-review/src/app.mjs +++ b/packages/govuk-frontend-review/src/app.mjs @@ -1,9 +1,9 @@ import express from 'express' import { getComponentsFixtures, - getComponentNames, - filterPath -} from 'govuk-frontend-lib/files' + getComponentNames +} from 'govuk-frontend-lib/components' +import { filterPath } from 'govuk-frontend-lib/files' import { componentNameToMacroName } from 'govuk-frontend-lib/names' import { getStats, modulePaths } from 'govuk-frontend-stats' import { outdent } from 'outdent' @@ -208,5 +208,5 @@ export default async () => { } /** - * @typedef {import('govuk-frontend-lib/files').ComponentFixtures} ComponentFixtures + * @typedef {import('govuk-frontend-lib/components').ComponentFixtures} ComponentFixtures */ diff --git a/packages/govuk-frontend-review/src/app.test.mjs b/packages/govuk-frontend-review/src/app.test.mjs index dd9243f33b..8e842e36b4 100644 --- a/packages/govuk-frontend-review/src/app.test.mjs +++ b/packages/govuk-frontend-review/src/app.test.mjs @@ -1,7 +1,7 @@ import { load } from 'cheerio' import { ports } from 'govuk-frontend-config' import { fetchPath } from 'govuk-frontend-helpers/tests' -import { getComponentNames } from 'govuk-frontend-lib/files' +import { getComponentNames } from 'govuk-frontend-lib/components' const expectedPages = [ '/', diff --git a/packages/govuk-frontend/src/govuk-prototype-kit/govuk-prototype-kit.config.mjs b/packages/govuk-frontend/src/govuk-prototype-kit/govuk-prototype-kit.config.mjs index afb62bfeca..38494a7232 100644 --- a/packages/govuk-frontend/src/govuk-prototype-kit/govuk-prototype-kit.config.mjs +++ b/packages/govuk-frontend/src/govuk-prototype-kit/govuk-prototype-kit.config.mjs @@ -1,10 +1,7 @@ import { join } from 'path' -import { - filterPath, - getComponentNames, - getListing -} from 'govuk-frontend-lib/files' +import { getComponentNames } from 'govuk-frontend-lib/components' +import { filterPath, getListing } from 'govuk-frontend-lib/files' import { componentNameToMacroName, packageNameToPath diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/accordion/accessibility.test.mjs index 06ad73cbcf..c7db3e276d 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/accordion/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/accordion', () => { let axeRules diff --git a/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js b/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js index 03578faa86..b69ccfaafc 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js +++ b/packages/govuk-frontend/src/govuk/components/accordion/accordion.test.js @@ -4,7 +4,7 @@ const { renderAndInitialise, getAccessibleName } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('/components/accordion', () => { describe('/components/accordion/preview', () => { diff --git a/packages/govuk-frontend/src/govuk/components/accordion/template.test.js b/packages/govuk-frontend/src/govuk/components/accordion/template.test.js index e4ca86633b..5f11e8b784 100644 --- a/packages/govuk-frontend/src/govuk/components/accordion/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/accordion/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Accordion', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/back-link/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/back-link/accessibility.test.mjs index 632d810e61..6144447d13 100644 --- a/packages/govuk-frontend/src/govuk/components/back-link/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/back-link/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/back-link', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/back-link/template.test.js b/packages/govuk-frontend/src/govuk/components/back-link/template.test.js index 3c3ed764e2..33885444f4 100644 --- a/packages/govuk-frontend/src/govuk/components/back-link/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/back-link/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('back-link component', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/breadcrumbs/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/breadcrumbs/accessibility.test.mjs index 356c51e427..d9c2e76833 100644 --- a/packages/govuk-frontend/src/govuk/components/breadcrumbs/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/breadcrumbs/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/breadcrumbs', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js b/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js index f7c98fe217..6649345b73 100644 --- a/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/breadcrumbs/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Breadcrumbs', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/button/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/button/accessibility.test.mjs index 24b79ed934..eb706d0270 100644 --- a/packages/govuk-frontend/src/govuk/components/button/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/button/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/button', () => { let axeRules diff --git a/packages/govuk-frontend/src/govuk/components/button/button.test.js b/packages/govuk-frontend/src/govuk/components/button/button.test.js index db81c49c78..a15332a28c 100644 --- a/packages/govuk-frontend/src/govuk/components/button/button.test.js +++ b/packages/govuk-frontend/src/govuk/components/button/button.test.js @@ -3,7 +3,7 @@ const { goToComponent, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('/components/button', () => { let examples @@ -92,9 +92,9 @@ describe('/components/button', () => { counts.debounce++ el.dataset.debounceCount = `${counts.debounce}` } - }, - // Add listener during capture phase to spy on event + // Add listener during capture phase to spy on event + }, { capture: true } ), counts diff --git a/packages/govuk-frontend/src/govuk/components/button/template.test.js b/packages/govuk-frontend/src/govuk/components/button/template.test.js index ab74d58fe0..caa08a2927 100644 --- a/packages/govuk-frontend/src/govuk/components/button/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/button/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Button', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/character-count/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/character-count/accessibility.test.mjs index 7dca255c06..0d6235d56a 100644 --- a/packages/govuk-frontend/src/govuk/components/character-count/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/character-count/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/character-count', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js b/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js index fb039a90d0..6f2467c4fc 100644 --- a/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js +++ b/packages/govuk-frontend/src/govuk/components/character-count/character-count.test.js @@ -2,7 +2,7 @@ const { goToComponent, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Character count', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/character-count/template.test.js b/packages/govuk-frontend/src/govuk/components/character-count/template.test.js index 23cf13135b..7fb2d3715d 100644 --- a/packages/govuk-frontend/src/govuk/components/character-count/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/character-count/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/checkboxes/accessibility.test.mjs index 546e396268..0bc8bb9863 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/checkboxes', () => { let axeRules diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js index d30d9b5e77..1d9a51fc14 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/checkboxes.test.js @@ -6,7 +6,7 @@ const { isVisible, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files.js') +const { getExamples } = require('govuk-frontend-lib/components') describe('Checkboxes with conditional reveals', () => { describe('when JavaScript is unavailable or fails', () => { diff --git a/packages/govuk-frontend/src/govuk/components/checkboxes/template.test.js b/packages/govuk-frontend/src/govuk/components/checkboxes/template.test.js index aed2914241..c8bf4a65a8 100644 --- a/packages/govuk-frontend/src/govuk/components/checkboxes/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/checkboxes/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/components.template.test.js b/packages/govuk-frontend/src/govuk/components/components.template.test.js index fef99875dd..397653613e 100644 --- a/packages/govuk-frontend/src/govuk/components/components.template.test.js +++ b/packages/govuk-frontend/src/govuk/components/components.template.test.js @@ -5,7 +5,7 @@ const { nunjucksEnv, renderHTML } = require('govuk-frontend-helpers/nunjucks') const { getComponentsFixtures, getComponentNames -} = require('govuk-frontend-lib/files') +} = require('govuk-frontend-lib/components') const { HtmlValidate } = require('html-validate') // We can't use the render function from jest-helpers, because we need control // over the nunjucks environment. diff --git a/packages/govuk-frontend/src/govuk/components/cookie-banner/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/cookie-banner/accessibility.test.mjs index 0b6fe7a661..ddafe6fe02 100644 --- a/packages/govuk-frontend/src/govuk/components/cookie-banner/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/cookie-banner/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/cookie-banner', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/cookie-banner/template.test.js b/packages/govuk-frontend/src/govuk/components/cookie-banner/template.test.js index 619055ea02..e6e94d33d9 100644 --- a/packages/govuk-frontend/src/govuk/components/cookie-banner/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/cookie-banner/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Cookie Banner', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/date-input/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/date-input/accessibility.test.mjs index b4c1d0f6f3..59a142532e 100644 --- a/packages/govuk-frontend/src/govuk/components/date-input/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/date-input/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/date-input', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/date-input/template.test.js b/packages/govuk-frontend/src/govuk/components/date-input/template.test.js index 12dc8aa0f3..e31aa89562 100644 --- a/packages/govuk-frontend/src/govuk/components/date-input/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/date-input/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/details/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/details/accessibility.test.mjs index f11c7aa11e..f765aa1f44 100644 --- a/packages/govuk-frontend/src/govuk/components/details/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/details/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/details', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/details/template.test.js b/packages/govuk-frontend/src/govuk/components/details/template.test.js index 888d3f267d..86ba3bdc93 100644 --- a/packages/govuk-frontend/src/govuk/components/details/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/details/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Details', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/error-message/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/error-message/accessibility.test.mjs index 7f150b27ee..5d4b070d0a 100644 --- a/packages/govuk-frontend/src/govuk/components/error-message/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/error-message/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/error-message', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/error-message/template.test.js b/packages/govuk-frontend/src/govuk/components/error-message/template.test.js index 4bd5ab9d6e..4571881d92 100644 --- a/packages/govuk-frontend/src/govuk/components/error-message/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/error-message/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Error message', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/error-summary/accessibility.test.mjs index c1ad240df4..6536236def 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/error-summary/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/error-summary', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js index e6928ed737..eb30ba217d 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js +++ b/packages/govuk-frontend/src/govuk/components/error-summary/error-summary.test.js @@ -4,7 +4,7 @@ const { renderAndInitialise, goTo } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Error Summary', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js b/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js index a31445d52b..ebb52e7c67 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Error-summary', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/exit-this-page/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/exit-this-page/accessibility.test.mjs index 0e5ac02afc..207e683366 100644 --- a/packages/govuk-frontend/src/govuk/components/exit-this-page/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/exit-this-page/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/exit-this-page', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js index 87713e9c6d..a1b8c41a2a 100644 --- a/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js +++ b/packages/govuk-frontend/src/govuk/components/exit-this-page/exit-this-page.test.js @@ -3,7 +3,7 @@ const { goToExample, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files.js') +const { getExamples } = require('govuk-frontend-lib/components') const buttonClass = '.govuk-js-exit-this-page-button' const skiplinkClass = '.govuk-js-exit-this-page-skiplink' diff --git a/packages/govuk-frontend/src/govuk/components/exit-this-page/template.test.js b/packages/govuk-frontend/src/govuk/components/exit-this-page/template.test.js index 75c03933ea..6fceb1cc89 100644 --- a/packages/govuk-frontend/src/govuk/components/exit-this-page/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/exit-this-page/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Exit this page', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/fieldset/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/fieldset/accessibility.test.mjs index 24d42f3ffb..922dd1721e 100644 --- a/packages/govuk-frontend/src/govuk/components/fieldset/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/fieldset/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/fieldset', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js b/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js index 06a19c4833..1480ce4026 100644 --- a/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('fieldset', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/file-upload/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/file-upload/accessibility.test.mjs index 2903f1e350..d69fed9aea 100644 --- a/packages/govuk-frontend/src/govuk/components/file-upload/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/file-upload/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/file-upload', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/file-upload/template.test.js b/packages/govuk-frontend/src/govuk/components/file-upload/template.test.js index 06e972308b..ca4f8ee6a0 100644 --- a/packages/govuk-frontend/src/govuk/components/file-upload/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/file-upload/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/footer/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/footer/accessibility.test.mjs index b67a9159e5..122214a670 100644 --- a/packages/govuk-frontend/src/govuk/components/footer/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/footer/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/footer', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/footer/template.test.js b/packages/govuk-frontend/src/govuk/components/footer/template.test.js index a7edf8f4d0..02b90687d1 100644 --- a/packages/govuk-frontend/src/govuk/components/footer/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/footer/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('footer', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/header/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/header/accessibility.test.mjs index 8c4ac76c62..02ae181358 100644 --- a/packages/govuk-frontend/src/govuk/components/header/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/header/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/header', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/header/header.test.js b/packages/govuk-frontend/src/govuk/components/header/header.test.js index 20c369c458..d3e53e695c 100644 --- a/packages/govuk-frontend/src/govuk/components/header/header.test.js +++ b/packages/govuk-frontend/src/govuk/components/header/header.test.js @@ -2,7 +2,7 @@ const { goToComponent, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files.js') +const { getExamples } = require('govuk-frontend-lib/components') const { KnownDevices } = require('puppeteer') const iPhone = KnownDevices['iPhone 6'] diff --git a/packages/govuk-frontend/src/govuk/components/header/template.test.js b/packages/govuk-frontend/src/govuk/components/header/template.test.js index 8149d68f93..ad877bd12a 100644 --- a/packages/govuk-frontend/src/govuk/components/header/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/header/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('header', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/hint/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/hint/accessibility.test.mjs index 00d6689df1..bcc52c6d2e 100644 --- a/packages/govuk-frontend/src/govuk/components/hint/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/hint/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/hint', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/hint/template.test.js b/packages/govuk-frontend/src/govuk/components/hint/template.test.js index 703c4391ca..bb96616e4f 100644 --- a/packages/govuk-frontend/src/govuk/components/hint/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/hint/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Hint', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/input/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/input/accessibility.test.mjs index 567ed8d511..599948a1ce 100644 --- a/packages/govuk-frontend/src/govuk/components/input/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/input/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/input', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/input/template.test.js b/packages/govuk-frontend/src/govuk/components/input/template.test.js index 4d621ff1d1..cd16b92e30 100644 --- a/packages/govuk-frontend/src/govuk/components/input/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/input/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/inset-text/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/inset-text/accessibility.test.mjs index 27fe74a3c7..250049b5b6 100644 --- a/packages/govuk-frontend/src/govuk/components/inset-text/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/inset-text/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/inset-text', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js b/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js index 8963973d3c..efe9fd2e11 100644 --- a/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Inset text', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/label/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/label/accessibility.test.mjs index d3b020b902..b56937d589 100644 --- a/packages/govuk-frontend/src/govuk/components/label/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/label/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/label', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/label/template.test.js b/packages/govuk-frontend/src/govuk/components/label/template.test.js index 3110572973..6836c475e8 100644 --- a/packages/govuk-frontend/src/govuk/components/label/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/label/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Label', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/notification-banner/accessibility.test.mjs index 424226405d..acb1087b1a 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/notification-banner', () => { let axeRules diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js index 8b97f221c4..8a64c3c737 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/notification-banner.test.js @@ -2,7 +2,7 @@ const { renderAndInitialise, goToComponent } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Notification banner', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js b/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js index 9a324890a4..fd2770c704 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Notification-banner', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/pagination/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/pagination/accessibility.test.mjs index 1a4a99cd24..3b20018e3e 100644 --- a/packages/govuk-frontend/src/govuk/components/pagination/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/pagination/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/pagination', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/pagination/template.test.js b/packages/govuk-frontend/src/govuk/components/pagination/template.test.js index c9f4e0b45b..46111b260f 100644 --- a/packages/govuk-frontend/src/govuk/components/pagination/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/pagination/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Pagination', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/panel/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/panel/accessibility.test.mjs index 02cb6a39a4..7122a7d4a7 100644 --- a/packages/govuk-frontend/src/govuk/components/panel/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/panel/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/panel', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/panel/template.test.js b/packages/govuk-frontend/src/govuk/components/panel/template.test.js index 5a89c3803c..45c8c819f5 100644 --- a/packages/govuk-frontend/src/govuk/components/panel/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/panel/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Panel', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/phase-banner/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/phase-banner/accessibility.test.mjs index ec8f3a20cc..5ed50ee105 100644 --- a/packages/govuk-frontend/src/govuk/components/phase-banner/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/phase-banner/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/phase-banner', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/phase-banner/template.test.js b/packages/govuk-frontend/src/govuk/components/phase-banner/template.test.js index 97347a277f..aa105ea520 100644 --- a/packages/govuk-frontend/src/govuk/components/phase-banner/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/phase-banner/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Phase banner', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/radios/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/radios/accessibility.test.mjs index 89532cd5e3..e6742b55be 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/radios/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/radios', () => { let axeRules diff --git a/packages/govuk-frontend/src/govuk/components/radios/radios.test.js b/packages/govuk-frontend/src/govuk/components/radios/radios.test.js index 037876e83d..cdfc4a1dbb 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/radios.test.js +++ b/packages/govuk-frontend/src/govuk/components/radios/radios.test.js @@ -6,7 +6,7 @@ const { isVisible, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files.js') +const { getExamples } = require('govuk-frontend-lib/components') describe('Radios', () => { describe('with conditional reveals', () => { diff --git a/packages/govuk-frontend/src/govuk/components/radios/template.test.js b/packages/govuk-frontend/src/govuk/components/radios/template.test.js index f89676d1c2..60ddd5ed5a 100644 --- a/packages/govuk-frontend/src/govuk/components/radios/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/radios/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/select/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/select/accessibility.test.mjs index 88db5ad7ee..efec83a9cd 100644 --- a/packages/govuk-frontend/src/govuk/components/select/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/select/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/select', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/select/template.test.js b/packages/govuk-frontend/src/govuk/components/select/template.test.js index 1eeb60c16b..95da3bded6 100644 --- a/packages/govuk-frontend/src/govuk/components/select/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/select/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/skip-link/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/skip-link/accessibility.test.mjs index 61e7b55f2d..685a8756f3 100644 --- a/packages/govuk-frontend/src/govuk/components/skip-link/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/skip-link/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/skip-link', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js index f1d648147f..76f8900a9f 100644 --- a/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js +++ b/packages/govuk-frontend/src/govuk/components/skip-link/skip-link.test.js @@ -2,7 +2,7 @@ const { goToExample, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files.js') +const { getExamples } = require('govuk-frontend-lib/components') describe('Skip Link', () => { describe('/examples/template-default', () => { diff --git a/packages/govuk-frontend/src/govuk/components/skip-link/template.test.js b/packages/govuk-frontend/src/govuk/components/skip-link/template.test.js index 860c639a45..642e2497eb 100644 --- a/packages/govuk-frontend/src/govuk/components/skip-link/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/skip-link/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Skip link', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/summary-list/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/summary-list/accessibility.test.mjs index 76fb3bd424..60cfb82767 100644 --- a/packages/govuk-frontend/src/govuk/components/summary-list/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/summary-list/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/summary-list', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/summary-list/template.test.js b/packages/govuk-frontend/src/govuk/components/summary-list/template.test.js index 83f7fcf67f..702f44b80a 100644 --- a/packages/govuk-frontend/src/govuk/components/summary-list/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/summary-list/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Summary list', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/table/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/table/accessibility.test.mjs index 3cf2cfe019..bf4cb1a35a 100644 --- a/packages/govuk-frontend/src/govuk/components/table/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/table/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/table', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/table/template.test.js b/packages/govuk-frontend/src/govuk/components/table/template.test.js index 098af8ac3b..c2d0cef2e3 100644 --- a/packages/govuk-frontend/src/govuk/components/table/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/table/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Table', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/tabs/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/tabs/accessibility.test.mjs index 138caf605c..e2fbc499c3 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/tabs/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/tabs', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js b/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js index 842e86ed27..886584500a 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js +++ b/packages/govuk-frontend/src/govuk/components/tabs/tabs.test.js @@ -3,7 +3,7 @@ const { goToComponent, renderAndInitialise } = require('govuk-frontend-helpers/puppeteer') -const { getExamples } = require('govuk-frontend-lib/files.js') +const { getExamples } = require('govuk-frontend-lib/components') const { KnownDevices } = require('puppeteer') const iPhone = KnownDevices['iPhone 6'] diff --git a/packages/govuk-frontend/src/govuk/components/tabs/template.test.js b/packages/govuk-frontend/src/govuk/components/tabs/template.test.js index 525d70d99a..a7e694a9f5 100644 --- a/packages/govuk-frontend/src/govuk/components/tabs/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/tabs/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Tabs', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/tag/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/tag/accessibility.test.mjs index 2026226be5..d0eb1e507b 100644 --- a/packages/govuk-frontend/src/govuk/components/tag/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/tag/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/tag', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/tag/template.test.js b/packages/govuk-frontend/src/govuk/components/tag/template.test.js index 750ff798de..d0b6c9c581 100644 --- a/packages/govuk-frontend/src/govuk/components/tag/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/tag/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Tag', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/task-list/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/task-list/accessibility.test.mjs index 65762123c0..26893f4e51 100644 --- a/packages/govuk-frontend/src/govuk/components/task-list/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/task-list/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/task-list', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/task-list/template.test.js b/packages/govuk-frontend/src/govuk/components/task-list/template.test.js index 6b573ee4f9..f12c869947 100644 --- a/packages/govuk-frontend/src/govuk/components/task-list/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/task-list/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Task List', () => { let examples diff --git a/packages/govuk-frontend/src/govuk/components/textarea/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/textarea/accessibility.test.mjs index 402d27ecfd..d5c752a20a 100644 --- a/packages/govuk-frontend/src/govuk/components/textarea/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/textarea/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/textarea', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/textarea/template.test.js b/packages/govuk-frontend/src/govuk/components/textarea/template.test.js index 43eb12e0ff..f1eb2d5e1e 100644 --- a/packages/govuk-frontend/src/govuk/components/textarea/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/textarea/template.test.js @@ -1,6 +1,6 @@ const { render } = require('govuk-frontend-helpers/nunjucks') const { htmlWithClassName } = require('govuk-frontend-helpers/tests') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') const WORD_BOUNDARY = '\\b' const WHITESPACE = '\\s' diff --git a/packages/govuk-frontend/src/govuk/components/warning-text/accessibility.test.mjs b/packages/govuk-frontend/src/govuk/components/warning-text/accessibility.test.mjs index caf68a3de9..4a80270b97 100644 --- a/packages/govuk-frontend/src/govuk/components/warning-text/accessibility.test.mjs +++ b/packages/govuk-frontend/src/govuk/components/warning-text/accessibility.test.mjs @@ -1,5 +1,5 @@ import { axe, goToComponent } from 'govuk-frontend-helpers/puppeteer' -import { getExamples } from 'govuk-frontend-lib/files' +import { getExamples } from 'govuk-frontend-lib/components' describe('/components/warning-text', () => { describe('component examples', () => { diff --git a/packages/govuk-frontend/src/govuk/components/warning-text/template.test.js b/packages/govuk-frontend/src/govuk/components/warning-text/template.test.js index 2c66d9cbc2..55daed4aaa 100644 --- a/packages/govuk-frontend/src/govuk/components/warning-text/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/warning-text/template.test.js @@ -1,5 +1,5 @@ const { render } = require('govuk-frontend-helpers/nunjucks') -const { getExamples } = require('govuk-frontend-lib/files') +const { getExamples } = require('govuk-frontend-lib/components') describe('Warning text', () => { let examples diff --git a/packages/govuk-frontend/tasks/build/package.test.mjs b/packages/govuk-frontend/tasks/build/package.test.mjs index 163502ef7d..3afb96d05f 100644 --- a/packages/govuk-frontend/tasks/build/package.test.mjs +++ b/packages/govuk-frontend/tasks/build/package.test.mjs @@ -3,12 +3,8 @@ import { join } from 'path' import { paths, pkg } from 'govuk-frontend-config' import { compileSassFile } from 'govuk-frontend-helpers/tests' -import { - filterPath, - getComponentNames, - getListing, - mapPathTo -} from 'govuk-frontend-lib/files' +import { getComponentNames } from 'govuk-frontend-lib/components' +import { filterPath, getListing, mapPathTo } from 'govuk-frontend-lib/files' import { componentNameToClassName } from 'govuk-frontend-lib/names' import { outdent } from 'outdent' diff --git a/packages/govuk-frontend/tasks/fixtures.mjs b/packages/govuk-frontend/tasks/fixtures.mjs index 6fe6680b69..40878c4eaf 100644 --- a/packages/govuk-frontend/tasks/fixtures.mjs +++ b/packages/govuk-frontend/tasks/fixtures.mjs @@ -4,7 +4,7 @@ import { components, task } from 'govuk-frontend-tasks' import gulp from 'gulp' /** - * Component data and macro fixtures (for watch) + * Component fixtures and macro options (for watch) * * @type {import('govuk-frontend-tasks').TaskFunction} */ diff --git a/shared/lib/components.js b/shared/lib/components.js new file mode 100644 index 0000000000..af94e4c7be --- /dev/null +++ b/shared/lib/components.js @@ -0,0 +1,141 @@ +const { join } = require('path') + +const { getListing, getDirectories } = require('./files') +const { packageNameToPath } = require('./names') + +/** + * Load single component fixtures + * + * @param {string} componentName - Component name + * @returns {Promise} Component data + */ +const getComponentFixtures = async (componentName) => { + return require(join( + packageNameToPath('govuk-frontend'), + `dist/govuk/components/${componentName}/fixtures.json` + )) +} + +/** + * Load all components' data + * + * @returns {Promise<(ComponentFixtures)[]>} Components' data + */ +const getComponentsFixtures = async () => { + const componentNames = await getComponentNames() + return Promise.all(componentNames.map(getComponentFixtures)) +} + +/** + * Get component files + * + * @param {string} [componentName] - Component name + * @returns {Promise} Component files + */ +const getComponentFiles = (componentName = '') => + getListing( + join( + packageNameToPath('govuk-frontend'), + `dist/govuk/components/${componentName}/**/*` + ) + ) + +/** + * Get component names (with optional filter) + * + * @param {(componentName: string, componentFiles: string[]) => boolean} [filter] - Component names array filter + * @returns {Promise} Component names + */ +const getComponentNames = async (filter) => { + const componentNames = await getDirectories( + join(packageNameToPath('govuk-frontend'), '**/dist/govuk/components/') + ) + + if (filter) { + const componentFiles = await getComponentFiles() + + // Apply component names filter + return componentNames.filter((componentName) => + filter(componentName, componentFiles) + ) + } + + return componentNames +} + +/** + * Get examples from component fixtures + * + * @param {string} componentName - Component name + * @returns {Promise<{ [name: string]: ComponentFixture['options'] }>} Component examples as an object + */ +async function getExamples(componentName) { + const { fixtures } = await getComponentFixtures(componentName) + + /** @type {{ [name: string]: ComponentFixture['options'] }} */ + const examples = {} + + for (const example of fixtures) { + examples[example.name] = example.options + } + + return examples +} + +module.exports = { + getComponentFixtures, + getComponentsFixtures, + getComponentFiles, + getComponentNames, + getExamples +} + +/** + * Component data + * + * @typedef {object} ComponentData + * @property {ComponentOption[]} [params] - Nunjucks macro option (or param) configs + * @property {ComponentExample[]} [examples] - Component examples with Nunjucks macro options (or params) + * @property {string} [previewLayout] - Nunjucks layout for component preview + * @property {string} [accessibilityCriteria] - Accessibility criteria + */ + +/** + * Nunjucks macro option (or param) config + * + * @typedef {object} ComponentOption + * @property {string} name - Option name + * @property {'array' | 'boolean' | 'integer' | 'nunjucks-block' | 'object' | 'string'} type - Option type + * @property {boolean} required - Option required + * @property {string} description - Option description + * @property {boolean} [isComponent] - Option is another component + * @property {ComponentOption[]} [params] - Nunjucks macro option (or param) configs + */ + +/** + * Component examples with Nunjucks macro options (or params) + * + * @typedef {object} ComponentExample + * @property {string} name - Example name + * @property {string} [description] - Example description + * @property {boolean} [hidden] - Example hidden from review app + * @property {string[]} [previewLayoutModifiers] - Component preview layout class modifiers + * @property {{ [param: string]: unknown }} options - Nunjucks macro options (or params) + */ + +/** + * Component fixture + * (used by the Design System website) + * + * @typedef {Required & { html: string }} ComponentFixture + */ + +/** + * Component fixtures + * (used by the Design System website) + * + * @typedef {object} ComponentFixtures + * @property {string} component - Component name + * @property {ComponentFixture[]} fixtures - Component fixtures with Nunjucks macro options (or params) + * @property {string} [previewLayout] - Nunjucks layout for component preview + */ diff --git a/shared/lib/files.unit.test.js b/shared/lib/components.unit.test.js similarity index 94% rename from shared/lib/files.unit.test.js rename to shared/lib/components.unit.test.js index c4262a4366..5ba7f9b9db 100644 --- a/shared/lib/files.unit.test.js +++ b/shared/lib/components.unit.test.js @@ -1,4 +1,4 @@ -const { getComponentFixtures } = require('./files.js') +const { getComponentFixtures } = require('./components.js') describe('getComponentFixtures', () => { it('rejects if unable to load component fixtures', async () => { diff --git a/shared/lib/files.js b/shared/lib/files.js index cbb6f32f89..ce68178ec9 100644 --- a/shared/lib/files.js +++ b/shared/lib/files.js @@ -1,5 +1,5 @@ const { readFile } = require('fs/promises') -const { join, parse, relative, basename } = require('path') +const { parse, relative, basename } = require('path') const { glob } = require('glob') const { paths } = require('govuk-frontend-config') @@ -7,8 +7,6 @@ const yaml = require('js-yaml') const { minimatch } = require('minimatch') const slash = require('slash') -const { packageNameToPath } = require('./names') - /** * Directory listing for path * @@ -16,7 +14,7 @@ const { packageNameToPath } = require('./names') * @param {import('glob').GlobOptionsWithFileTypesUnset} [options] - Glob options * @returns {Promise} File paths */ -const getListing = async (directoryPath, options = {}) => { +async function getListing(directoryPath, options = {}) { const listing = await glob(slash(directoryPath), { absolute: true, nodir: true, @@ -38,7 +36,7 @@ const getListing = async (directoryPath, options = {}) => { * @param {string} directoryPath - Minimatch pattern to directory * @returns {Promise} Directory names */ -const getDirectories = async (directoryPath) => { +async function getDirectories(directoryPath) { const listing = await getListing(`${slash(directoryPath)}/*/`, { nodir: false }) @@ -79,148 +77,14 @@ const mapPathTo = (patterns, callback) => (entryPath) => { * @param {string} configPath - File path to config * @returns {Promise} Config from YAML file */ -const getYaml = async (configPath) => { +async function getYaml(configPath) { return yaml.load(await readFile(configPath, 'utf8'), { json: true }) } -/** - * Load single component fixtures - * - * @param {string} componentName - Component name - * @returns {Promise} Component data - */ -const getComponentFixtures = async (componentName) => { - return require(join( - packageNameToPath('govuk-frontend'), - `dist/govuk/components/${componentName}/fixtures.json` - )) -} - -/** - * Load all components' data - * - * @returns {Promise<(ComponentFixtures)[]>} Components' data - */ -const getComponentsFixtures = async () => { - const componentNames = await getComponentNames() - return Promise.all(componentNames.map(getComponentFixtures)) -} - -/** - * Get component files - * - * @param {string} [componentName] - Component name - * @returns {Promise} Component files - */ -const getComponentFiles = (componentName = '') => - getListing( - join( - packageNameToPath('govuk-frontend'), - `dist/govuk/components/${componentName}/**/*` - ) - ) - -/** - * Get component names (with optional filter) - * - * @param {(componentName: string, componentFiles: string[]) => boolean} [filter] - Component names array filter - * @returns {Promise} Component names - */ -const getComponentNames = async (filter) => { - const componentNames = await getDirectories( - join(packageNameToPath('govuk-frontend'), '**/dist/govuk/components/') - ) - - if (filter) { - const componentFiles = await getComponentFiles() - - // Apply component names filter - return componentNames.filter((componentName) => - filter(componentName, componentFiles) - ) - } - - return componentNames -} - -/** - * Get examples from component fixtures - * - * @param {string} componentName - Component name - * @returns {Promise<{ [name: string]: ComponentFixture['options'] }>} Component examples as an object - */ -async function getExamples(componentName) { - const { fixtures } = await getComponentFixtures(componentName) - - /** @type {{ [name: string]: ComponentFixture['options'] }} */ - const examples = {} - - for (const example of fixtures) { - examples[example.name] = example.options - } - - return examples -} - module.exports = { filterPath, - getComponentFixtures, - getComponentsFixtures, - getComponentFiles, - getComponentNames, getDirectories, - getExamples, getListing, getYaml, mapPathTo } - -/** - * Component data - * - * @typedef {object} ComponentData - * @property {ComponentOption[]} [params] - Nunjucks macro option (or param) configs - * @property {ComponentExample[]} [examples] - Component examples with Nunjucks macro options (or params) - * @property {string} [previewLayout] - Nunjucks layout for component preview - * @property {string} [accessibilityCriteria] - Accessibility criteria - */ - -/** - * Nunjucks macro option (or param) config - * - * @typedef {object} ComponentOption - * @property {string} name - Option name - * @property {'array' | 'boolean' | 'integer' | 'nunjucks-block' | 'object' | 'string'} type - Option type - * @property {boolean} required - Option required - * @property {string} description - Option description - * @property {boolean} [isComponent] - Option is another component - * @property {ComponentOption[]} [params] - Nunjucks macro option (or param) configs - */ - -/** - * Component examples with Nunjucks macro options (or params) - * - * @typedef {object} ComponentExample - * @property {string} name - Example name - * @property {string} [description] - Example description - * @property {boolean} [hidden] - Example hidden from review app - * @property {string[]} [previewLayoutModifiers] - Component preview layout class modifiers - * @property {{ [param: string]: unknown }} options - Nunjucks macro options (or params) - */ - -/** - * Component fixture - * (used by the Design System website) - * - * @typedef {Required & { html: string }} ComponentFixture - */ - -/** - * Component fixtures - * (used by the Design System website) - * - * @typedef {object} ComponentFixtures - * @property {string} component - Component name - * @property {ComponentFixture[]} fixtures - Component fixtures with Nunjucks macro options (or params) - * @property {string} [previewLayout] - Nunjucks layout for component preview - */ diff --git a/shared/lib/index.js b/shared/lib/index.js index 39289bc8f0..93421849a1 100644 --- a/shared/lib/index.js +++ b/shared/lib/index.js @@ -1,10 +1,10 @@ -const files = require('./files') +const components = require('./components') const names = require('./names') /** * Shared library */ module.exports = { - files, + components, names } diff --git a/shared/stats/src/index.mjs b/shared/stats/src/index.mjs index c4251834c0..f1f5b9c36c 100644 --- a/shared/stats/src/index.mjs +++ b/shared/stats/src/index.mjs @@ -1,11 +1,8 @@ import { join, parse } from 'path' import { paths } from 'govuk-frontend-config' -import { - getComponentNames, - filterPath, - getYaml -} from 'govuk-frontend-lib/files' +import { getComponentNames } from 'govuk-frontend-lib/components' +import { filterPath, getYaml } from 'govuk-frontend-lib/files' /** * Components with JavaScript diff --git a/shared/tasks/browser.mjs b/shared/tasks/browser.mjs index dd2e119312..1e6df7b918 100644 --- a/shared/tasks/browser.mjs +++ b/shared/tasks/browser.mjs @@ -3,11 +3,11 @@ import { waitForPercyIdle } from '@percy/sdk-utils' import { download } from 'govuk-frontend-helpers/jest/browser/download.mjs' import { goToComponent, goToExample } from 'govuk-frontend-helpers/puppeteer' import { - filterPath, getComponentFiles, getComponentNames, getExamples -} from 'govuk-frontend-lib/files' +} from 'govuk-frontend-lib/components' +import { filterPath } from 'govuk-frontend-lib/files' import puppeteer from 'puppeteer' /** diff --git a/shared/tasks/components.mjs b/shared/tasks/components.mjs index 6601e5e4cd..3e6bbd9407 100644 --- a/shared/tasks/components.mjs +++ b/shared/tasks/components.mjs @@ -151,9 +151,9 @@ async function generateMacroOption(componentDataPath, options) { /** * @typedef {import('./assets.mjs').AssetEntry} AssetEntry - * @typedef {import('govuk-frontend-lib/files').ComponentData} ComponentData - * @typedef {import('govuk-frontend-lib/files').ComponentOption} ComponentOption - * @typedef {import('govuk-frontend-lib/files').ComponentExample} ComponentExample - * @typedef {import('govuk-frontend-lib/files').ComponentFixture} ComponentFixture - * @typedef {import('govuk-frontend-lib/files').ComponentFixtures} ComponentFixtures + * @typedef {import('govuk-frontend-lib/components').ComponentData} ComponentData + * @typedef {import('govuk-frontend-lib/components').ComponentOption} ComponentOption + * @typedef {import('govuk-frontend-lib/components').ComponentExample} ComponentExample + * @typedef {import('govuk-frontend-lib/components').ComponentFixture} ComponentFixture + * @typedef {import('govuk-frontend-lib/components').ComponentFixtures} ComponentFixtures */ From a03177e7cc880035b89a72f66e495236719e4ead Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 4 Aug 2023 09:01:29 +0100 Subject: [PATCH 02/14] Move render functions into `govuk-frontend-lib/components` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- package-lock.json | 2 +- .../components/components.template.test.js | 5 +- .../src/govuk/macros/i18n.unit.test.mjs | 2 +- shared/helpers/nunjucks.js | 57 +------------------ shared/helpers/package.json | 1 - shared/helpers/puppeteer.js | 3 +- shared/lib/components.js | 56 +++++++++++++++++- shared/lib/package.json | 1 + 8 files changed, 62 insertions(+), 65 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef1b9844b0..35024b928b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28266,7 +28266,6 @@ "jest-environment-jsdom": "^29.6.2", "jest-environment-node-single-context": "^29.1.0", "jest-environment-puppeteer": "^9.0.0", - "nunjucks": "^3.2.4", "outdent": "^0.8.0", "puppeteer": "^21.0.1", "sass-embedded": "^1.64.2", @@ -28297,6 +28296,7 @@ "govuk-frontend-config": "*", "js-yaml": "^4.1.0", "minimatch": "^9.0.3", + "nunjucks": "^3.2.4", "slash": "^3.0.0" }, "engines": { diff --git a/packages/govuk-frontend/src/govuk/components/components.template.test.js b/packages/govuk-frontend/src/govuk/components/components.template.test.js index 397653613e..ca90f84d04 100644 --- a/packages/govuk-frontend/src/govuk/components/components.template.test.js +++ b/packages/govuk-frontend/src/govuk/components/components.template.test.js @@ -1,10 +1,11 @@ const { join } = require('path') const { paths } = require('govuk-frontend-config') -const { nunjucksEnv, renderHTML } = require('govuk-frontend-helpers/nunjucks') const { getComponentsFixtures, - getComponentNames + getComponentNames, + nunjucksEnv, + renderHTML } = require('govuk-frontend-lib/components') const { HtmlValidate } = require('html-validate') // We can't use the render function from jest-helpers, because we need control diff --git a/packages/govuk-frontend/src/govuk/macros/i18n.unit.test.mjs b/packages/govuk-frontend/src/govuk/macros/i18n.unit.test.mjs index b2fef5a9dc..816ed58562 100644 --- a/packages/govuk-frontend/src/govuk/macros/i18n.unit.test.mjs +++ b/packages/govuk-frontend/src/govuk/macros/i18n.unit.test.mjs @@ -1,4 +1,4 @@ -import { renderMacro } from 'govuk-frontend-helpers/nunjucks' +import { renderMacro } from 'govuk-frontend-lib/components' describe('i18n.njk', () => { describe('govukI18nAttributes', () => { diff --git a/shared/helpers/nunjucks.js b/shared/helpers/nunjucks.js index 8f99c2c20e..8b78ddcf2f 100644 --- a/shared/helpers/nunjucks.js +++ b/shared/helpers/nunjucks.js @@ -1,36 +1,7 @@ -const { join } = require('path') - const cheerio = require('cheerio') -const { - componentNameToMacroName, - packageNameToPath -} = require('govuk-frontend-lib/names') -const nunjucks = require('nunjucks') +const { nunjucksEnv, renderHTML } = require('govuk-frontend-lib/components') const { outdent } = require('outdent') -const nunjucksPaths = [join(packageNameToPath('govuk-frontend'), 'src')] - -const nunjucksEnv = nunjucks.configure(nunjucksPaths, { - trimBlocks: true, - lstripBlocks: true -}) - -/** - * Render component HTML - * - * @param {string} componentName - Component name - * @param {{ [key: string]: unknown }} options - options to pass to the component macro - * @param {string} [callBlock] - if provided, the macro is called using the - * Nunjucks call tag, with the callBlock passed as the contents of the block - * @returns {string} HTML rendered by the macro - */ -function renderHTML(componentName, options, callBlock) { - const macroName = componentNameToMacroName(componentName) - const macroPath = `govuk/components/${componentName}/macro.njk` - - return renderMacro(macroName, macroPath, options, callBlock) -} - /** * Render component HTML into cheerio * @@ -44,29 +15,6 @@ function render(componentName, options, callBlock) { return cheerio.load(renderHTML(componentName, options, callBlock)) } -/** - * Render the string result from calling a macro - * - * @param {string} macroName - The name of the macro - * @param {string} macroPath - The path to the file containing the macro - * @param {{ [param: string]: unknown }} options - Nunjucks macro options (or params) - * @param {string} [callBlock] - Content for an optional callBlock, if necessary for the macro to receive one - * @returns {string} The result of calling the macro - */ -function renderMacro(macroName, macroPath, options = {}, callBlock) { - const macroOptions = JSON.stringify(options, undefined, 2) - - let macroString = `{%- from "${macroPath}" import ${macroName} -%}` - - // If we're nesting child components or text, pass the children to the macro - // using the 'caller' Nunjucks feature - macroString += callBlock - ? `{%- call ${macroName}(${macroOptions}) -%}${callBlock}{%- endcall -%}` - : `{{- ${macroName}(${macroOptions}) -}}` - - return nunjucksEnv.renderString(macroString, {}) -} - /** * Render Nunjucks template HTML into cheerio * @@ -89,9 +37,6 @@ function renderTemplate(context = {}, blocks = {}) { } module.exports = { - nunjucksEnv, render, - renderHTML, - renderMacro, renderTemplate } diff --git a/shared/helpers/package.json b/shared/helpers/package.json index 338f14c798..63bbf0483a 100644 --- a/shared/helpers/package.json +++ b/shared/helpers/package.json @@ -24,7 +24,6 @@ "jest-environment-jsdom": "^29.6.2", "jest-environment-node-single-context": "^29.1.0", "jest-environment-puppeteer": "^9.0.0", - "nunjucks": "^3.2.4", "outdent": "^0.8.0", "puppeteer": "^21.0.1", "sass-embedded": "^1.64.2", diff --git a/shared/helpers/puppeteer.js b/shared/helpers/puppeteer.js index 43c48790b4..29029949ac 100644 --- a/shared/helpers/puppeteer.js +++ b/shared/helpers/puppeteer.js @@ -1,10 +1,9 @@ const { AxePuppeteer } = require('@axe-core/puppeteer') const { ports } = require('govuk-frontend-config') +const { renderHTML } = require('govuk-frontend-lib/components') const { componentNameToClassName } = require('govuk-frontend-lib/names') const slug = require('slug') -const { renderHTML } = require('./nunjucks') - /** * Axe Puppeteer reporter * diff --git a/shared/lib/components.js b/shared/lib/components.js index af94e4c7be..e541128596 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -1,7 +1,17 @@ const { join } = require('path') +const nunjucks = require('nunjucks') + const { getListing, getDirectories } = require('./files') -const { packageNameToPath } = require('./names') +const { packageNameToPath, componentNameToMacroName } = require('./names') + +const nunjucksEnv = nunjucks.configure( + [join(packageNameToPath('govuk-frontend'), 'src')], + { + trimBlocks: true, + lstripBlocks: true + } +) /** * Load single component fixtures @@ -82,12 +92,54 @@ async function getExamples(componentName) { return examples } +/** + * Render component HTML + * + * @param {string} componentName - Component name + * @param {{ [key: string]: unknown }} options - Nunjucks macro options (or params) + * @param {string} [callBlock] - if provided, the macro is called using the + * Nunjucks call tag, with the callBlock passed as the contents of the block + * @returns {string} HTML rendered by the macro + */ +function renderHTML(componentName, options, callBlock) { + const macroName = componentNameToMacroName(componentName) + const macroPath = `govuk/components/${componentName}/macro.njk` + + return renderMacro(macroName, macroPath, options, callBlock) +} + +/** + * Render the string result from calling a macro + * + * @param {string} macroName - The name of the macro + * @param {string} macroPath - The path to the file containing the macro + * @param {{ [param: string]: unknown }} options - Nunjucks macro options (or params) + * @param {string} [callBlock] - Content for an optional callBlock, if necessary for the macro to receive one + * @returns {string} The result of calling the macro + */ +function renderMacro(macroName, macroPath, options = {}, callBlock) { + const macroOptions = JSON.stringify(options, undefined, 2) + + let macroString = `{%- from "${macroPath}" import ${macroName} -%}` + + // If we're nesting child components or text, pass the children to the macro + // using the 'caller' Nunjucks feature + macroString += callBlock + ? `{%- call ${macroName}(${macroOptions}) -%}${callBlock}{%- endcall -%}` + : `{{- ${macroName}(${macroOptions}) -}}` + + return nunjucksEnv.renderString(macroString, {}) +} + module.exports = { getComponentFixtures, getComponentsFixtures, getComponentFiles, getComponentNames, - getExamples + getExamples, + nunjucksEnv, + renderHTML, + renderMacro } /** diff --git a/shared/lib/package.json b/shared/lib/package.json index 71f9588490..b7c2f33b20 100644 --- a/shared/lib/package.json +++ b/shared/lib/package.json @@ -17,6 +17,7 @@ "govuk-frontend-config": "*", "js-yaml": "^4.1.0", "minimatch": "^9.0.3", + "nunjucks": "^3.2.4", "slash": "^3.0.0" } } From a1744a9331322d07328aa53b3f6bb56ee3a7fce5 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 4 Aug 2023 09:01:55 +0100 Subject: [PATCH 03/14] Rename helper `renderHTML()` to `renderComponent()` --- .../src/govuk/components/components.template.test.js | 4 ++-- shared/helpers/nunjucks.js | 7 +++++-- shared/helpers/puppeteer.js | 4 ++-- shared/lib/components.js | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/components.template.test.js b/packages/govuk-frontend/src/govuk/components/components.template.test.js index ca90f84d04..0678f60e01 100644 --- a/packages/govuk-frontend/src/govuk/components/components.template.test.js +++ b/packages/govuk-frontend/src/govuk/components/components.template.test.js @@ -5,7 +5,7 @@ const { getComponentsFixtures, getComponentNames, nunjucksEnv, - renderHTML + renderComponent } = require('govuk-frontend-lib/components') const { HtmlValidate } = require('html-validate') // We can't use the render function from jest-helpers, because we need control @@ -139,7 +139,7 @@ describe('Components', () => { for (const { component: componentName, fixtures } of componentsFixtures) { const fixtureTasks = fixtures.map( async ({ name: exampleName, options }) => { - const html = renderHTML(componentName, options) + const html = renderComponent(componentName, options) // Validate HTML return expect({ diff --git a/shared/helpers/nunjucks.js b/shared/helpers/nunjucks.js index 8b78ddcf2f..3f1fa22620 100644 --- a/shared/helpers/nunjucks.js +++ b/shared/helpers/nunjucks.js @@ -1,5 +1,8 @@ const cheerio = require('cheerio') -const { nunjucksEnv, renderHTML } = require('govuk-frontend-lib/components') +const { + nunjucksEnv, + renderComponent +} = require('govuk-frontend-lib/components') const { outdent } = require('outdent') /** @@ -12,7 +15,7 @@ const { outdent } = require('outdent') * @returns {import('cheerio').CheerioAPI} HTML rendered by the macro */ function render(componentName, options, callBlock) { - return cheerio.load(renderHTML(componentName, options, callBlock)) + return cheerio.load(renderComponent(componentName, options, callBlock)) } /** diff --git a/shared/helpers/puppeteer.js b/shared/helpers/puppeteer.js index 29029949ac..64dee0c18d 100644 --- a/shared/helpers/puppeteer.js +++ b/shared/helpers/puppeteer.js @@ -1,6 +1,6 @@ const { AxePuppeteer } = require('@axe-core/puppeteer') const { ports } = require('govuk-frontend-config') -const { renderHTML } = require('govuk-frontend-lib/components') +const { renderComponent } = require('govuk-frontend-lib/components') const { componentNameToClassName } = require('govuk-frontend-lib/names') const slug = require('slug') @@ -80,7 +80,7 @@ async function axe(page, overrides = {}) { async function renderAndInitialise(page, componentName, options) { await goTo(page, '/tests/boilerplate') - const html = renderHTML(componentName, options.params) + const html = renderComponent(componentName, options.params) // Inject rendered HTML into the page await page.$eval( diff --git a/shared/lib/components.js b/shared/lib/components.js index e541128596..f4bea86709 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -101,7 +101,7 @@ async function getExamples(componentName) { * Nunjucks call tag, with the callBlock passed as the contents of the block * @returns {string} HTML rendered by the macro */ -function renderHTML(componentName, options, callBlock) { +function renderComponent(componentName, options, callBlock) { const macroName = componentNameToMacroName(componentName) const macroPath = `govuk/components/${componentName}/macro.njk` @@ -138,7 +138,7 @@ module.exports = { getComponentNames, getExamples, nunjucksEnv, - renderHTML, + renderComponent, renderMacro } From 8c4d74b29ba7a4002908053fe44b1b87274726b8 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 4 Aug 2023 09:44:02 +0100 Subject: [PATCH 04/14] Move Nunjucks environment to `govuk-frontend-lib/components` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gives us a single place to manage our Nunjucks environment so we don’t need to manage search paths from multiple places --- package-lock.json | 4 ++- packages/govuk-frontend-review/package.json | 4 ++- .../src/common/nunjucks/index.mjs | 27 ++++------------ .../components/components.template.test.js | 11 +++---- .../govuk-frontend/src/govuk/template.test.js | 17 ++++++---- packages/govuk-frontend/tasks/fixtures.mjs | 12 ++----- shared/helpers/nunjucks.js | 5 ++- shared/lib/components.js | 32 ++++++++++++++----- shared/tasks/components.mjs | 7 ++-- 9 files changed, 61 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 35024b928b..b189ffd6c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28211,7 +28211,6 @@ "iframe-resizer": "^4.3.6", "js-beautify": "^1.14.9", "marked": "^7.0.0", - "nunjucks": "^3.2.4", "outdent": "^0.8.0", "shuffle-seed": "^1.1.6", "slug": "^8.2.3" @@ -28239,6 +28238,9 @@ "engines": { "node": "^18.12.0", "npm": "^8.1.0 || ^9.1.0" + }, + "optionalDependencies": { + "nunjucks": "^3.2.4" } }, "shared/config": { diff --git a/packages/govuk-frontend-review/package.json b/packages/govuk-frontend-review/package.json index 26e71c2da5..9c63c96b3f 100644 --- a/packages/govuk-frontend-review/package.json +++ b/packages/govuk-frontend-review/package.json @@ -33,7 +33,6 @@ "iframe-resizer": "^4.3.6", "js-beautify": "^1.14.9", "marked": "^7.0.0", - "nunjucks": "^3.2.4", "outdent": "^0.8.0", "shuffle-seed": "^1.1.6", "slug": "^8.2.3" @@ -57,5 +56,8 @@ "slash": "^5.1.0", "supertest": "^6.3.3", "typedoc": "^0.24.8" + }, + "optionalDependencies": { + "nunjucks": "^3.2.4" } } diff --git a/packages/govuk-frontend-review/src/common/nunjucks/index.mjs b/packages/govuk-frontend-review/src/common/nunjucks/index.mjs index 00bcf7545a..981006af38 100644 --- a/packages/govuk-frontend-review/src/common/nunjucks/index.mjs +++ b/packages/govuk-frontend-review/src/common/nunjucks/index.mjs @@ -1,8 +1,7 @@ import { join } from 'path' import { paths } from 'govuk-frontend-config' -import { packageResolveToPath } from 'govuk-frontend-lib/names' -import nunjucks from 'nunjucks' +import { nunjucksEnv } from 'govuk-frontend-lib/components' import * as filters from './filters/index.mjs' import * as globals from './globals/index.mjs' @@ -14,25 +13,11 @@ import * as globals from './globals/index.mjs' * @returns {import('nunjucks').Environment} Nunjucks Environment */ export function renderer(app) { - const env = nunjucks.configure( - [ - join(paths.app, 'src/views'), - - // Remove `govuk/` suffix using `modulePath` - packageResolveToPath('govuk-frontend', { - modulePath: '../', - moduleRoot: paths.app - }) - ], - { - autoescape: true, // output with dangerous characters are escaped automatically - express: app, // the Express.js review app that nunjucks should install to - noCache: true, // never use a cache and recompile templates each time - trimBlocks: true, // automatically remove trailing newlines from a block/tag - lstripBlocks: true, // automatically remove leading whitespace from a block/tag - watch: true // reload templates when they are changed. needs chokidar dependency to be installed - } - ) + const env = nunjucksEnv([join(paths.app, 'src/views')], { + express: app, // the Express.js review app that nunjucks should install to + noCache: true, // never use a cache and recompile templates each time + watch: true // reload templates when they are changed. needs chokidar dependency to be installed + }) // Set view engine app.set('view engine', 'njk') diff --git a/packages/govuk-frontend/src/govuk/components/components.template.test.js b/packages/govuk-frontend/src/govuk/components/components.template.test.js index 0678f60e01..1f877dbd2c 100644 --- a/packages/govuk-frontend/src/govuk/components/components.template.test.js +++ b/packages/govuk-frontend/src/govuk/components/components.template.test.js @@ -8,9 +8,6 @@ const { renderComponent } = require('govuk-frontend-lib/components') const { HtmlValidate } = require('html-validate') -// We can't use the render function from jest-helpers, because we need control -// over the nunjucks environment. -const nunjucks = require('nunjucks') describe('Components', () => { let nunjucksEnvCustom @@ -19,10 +16,10 @@ describe('Components', () => { let componentNames beforeAll(async () => { - // Create a new Nunjucks environment that uses the src directory as its - // base path, rather than the components folder itself - nunjucksEnvCustom = nunjucks.configure(join(paths.package, 'src/govuk')) - nunjucksEnvDefault = nunjucksEnv + // Create a new Nunjucks environment that uses the `src/govuk` directory as + // its first search path, rather than default to `src` (no 'govuk' prefix) + nunjucksEnvCustom = nunjucksEnv([join(paths.package, 'src/govuk')]) + nunjucksEnvDefault = nunjucksEnv() // Components list componentNames = await getComponentNames() diff --git a/packages/govuk-frontend/src/govuk/template.test.js b/packages/govuk-frontend/src/govuk/template.test.js index 30943f1220..7ea01ddfc4 100644 --- a/packages/govuk-frontend/src/govuk/template.test.js +++ b/packages/govuk-frontend/src/govuk/template.test.js @@ -1,26 +1,29 @@ const crypto = require('crypto') -const { join } = require('path') -const { paths } = require('govuk-frontend-config') const { renderTemplate } = require('govuk-frontend-helpers/nunjucks') -const nunjucks = require('nunjucks') +const { nunjucksEnv } = require('govuk-frontend-lib/components') describe('Template', () => { describe('with default nunjucks configuration', () => { it('should not have any whitespace before the doctype', () => { - nunjucks.configure(join(paths.package, 'src/govuk')) - const output = nunjucks.render('./template.njk') + const env = nunjucksEnv([], { + trimBlocks: false, + lstripBlocks: false + }) + + const output = env.render('./govuk/template.njk') expect(output.charAt(0)).toEqual('<') }) }) describe('with nunjucks block trimming enabled', () => { it('should not have any whitespace before the doctype', () => { - nunjucks.configure(join(paths.package, 'src/govuk'), { + const env = nunjucksEnv([], { trimBlocks: true, lstripBlocks: true }) - const output = nunjucks.render('./template.njk') + + const output = env.render('./govuk/template.njk') expect(output.charAt(0)).toEqual('<') }) }) diff --git a/packages/govuk-frontend/tasks/fixtures.mjs b/packages/govuk-frontend/tasks/fixtures.mjs index 40878c4eaf..b2a32110a2 100644 --- a/packages/govuk-frontend/tasks/fixtures.mjs +++ b/packages/govuk-frontend/tasks/fixtures.mjs @@ -1,5 +1,3 @@ -import { join } from 'path' - import { components, task } from 'govuk-frontend-tasks' import gulp from 'gulp' @@ -14,19 +12,13 @@ export const compile = (options) => * Generate GOV.UK Frontend fixtures.json from ${componentName}.yaml */ task.name('compile:fixtures', () => - components.generateFixtures('**/*.yaml', { - srcPath: join(options.srcPath, 'govuk/components'), - destPath: join(options.destPath, 'govuk/components') - }) + components.generateFixtures('**/*.yaml', options) ), /** * Generate GOV.UK Frontend macro-options.json from ${componentName}.yaml */ task.name('compile:macro-options', () => - components.generateMacroOptions('**/*.yaml', { - srcPath: join(options.srcPath, 'govuk/components'), - destPath: join(options.destPath, 'govuk/components') - }) + components.generateMacroOptions('**/*.yaml', options) ) ) diff --git a/shared/helpers/nunjucks.js b/shared/helpers/nunjucks.js index 3f1fa22620..6b558cfa9e 100644 --- a/shared/helpers/nunjucks.js +++ b/shared/helpers/nunjucks.js @@ -5,6 +5,9 @@ const { } = require('govuk-frontend-lib/components') const { outdent } = require('outdent') +// Nunjucks default environment +const env = nunjucksEnv() + /** * Render component HTML into cheerio * @@ -36,7 +39,7 @@ function renderTemplate(context = {}, blocks = {}) { {%- endblock %}` } - return cheerio.load(nunjucksEnv.renderString(viewString, context)) + return cheerio.load(env.renderString(viewString, context)) } module.exports = { diff --git a/shared/lib/components.js b/shared/lib/components.js index f4bea86709..0545764724 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -5,13 +5,29 @@ const nunjucks = require('nunjucks') const { getListing, getDirectories } = require('./files') const { packageNameToPath, componentNameToMacroName } = require('./names') -const nunjucksEnv = nunjucks.configure( - [join(packageNameToPath('govuk-frontend'), 'src')], - { - trimBlocks: true, - lstripBlocks: true - } -) +// Nunjucks default environment +const env = nunjucksEnv() + +/** + * Nunjucks environment factory + * + * @param {string[]} [searchPaths] - Nunjucks search paths (optional) + * @param {import('nunjucks').ConfigureOptions} [nunjucksOptions] - Nunjucks options (optional) + * @returns {import('nunjucks').Environment} Nunjucks environment + */ +function nunjucksEnv(searchPaths = [], nunjucksOptions = {}) { + const packagePath = packageNameToPath('govuk-frontend') + + // Add to Nunjucks search paths + searchPaths.push(join(packagePath, 'src')) + + // Nunjucks environment + return nunjucks.configure(searchPaths, { + trimBlocks: true, // automatically remove trailing newlines from a block/tag + lstripBlocks: true, // automatically remove leading whitespace from a block/tag, + ...nunjucksOptions + }) +} /** * Load single component fixtures @@ -128,7 +144,7 @@ function renderMacro(macroName, macroPath, options = {}, callBlock) { ? `{%- call ${macroName}(${macroOptions}) -%}${callBlock}{%- endcall -%}` : `{{- ${macroName}(${macroOptions}) -}}` - return nunjucksEnv.renderString(macroString, {}) + return env.renderString(macroString, {}) } module.exports = { diff --git a/shared/tasks/components.mjs b/shared/tasks/components.mjs index 3e6bbd9407..634a1a4605 100644 --- a/shared/tasks/components.mjs +++ b/shared/tasks/components.mjs @@ -1,7 +1,7 @@ import { basename, dirname, join } from 'path' +import { nunjucksEnv } from 'govuk-frontend-lib/components' import { getListing, getYaml } from 'govuk-frontend-lib/files' -import nunjucks from 'nunjucks' import { files } from './index.mjs' @@ -90,6 +90,9 @@ async function generateFixture(componentDataPath, options) { throw new Error(`${componentDataPath} is missing "examples"`) } + // Nunjucks environment + const env = nunjucksEnv([options.srcPath]) + // Nunjucks template const template = join( options.srcPath, @@ -117,7 +120,7 @@ async function generateFixture(componentDataPath, options) { html: await new Promise((resolve, reject) => { const context = { params: example.options } - return nunjucks.render(template, context, (error, result) => { + return env.render(template, context, (error, result) => { return error ? reject(error) : resolve(result?.trim() ?? '') }) }) From c356b31e0f5baf47b2f910aa3d04df96418ed6d5 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 4 Aug 2023 09:02:53 +0100 Subject: [PATCH 05/14] Consistent params for component configs, macro options --- .../common/nunjucks/globals/get-html-code.mjs | 8 +++-- .../nunjucks/globals/get-nunjucks-code.mjs | 8 +++-- packages/govuk-frontend/src/govuk/all.mjs | 3 +- shared/helpers/nunjucks.js | 13 ++++--- shared/helpers/puppeteer.js | 10 ++++-- shared/lib/components.js | 35 +++++++++++-------- 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs b/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs index 8c229e4bba..9f3b00a682 100644 --- a/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs +++ b/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs @@ -7,8 +7,8 @@ import beautify from 'js-beautify' * * @this {{ env: import('nunjucks').Environment }} * @param {string} componentName - Component name - * @param {unknown} params - Component macro params - * @returns {string} Nunjucks code + * @param {MacroOptions} [params] - Nunjucks macro options (or params) + * @returns {string} HTML rendered by the component */ export function getHTMLCode(componentName, params) { const templatePath = packageTypeToPath('govuk-frontend', { @@ -32,3 +32,7 @@ export function getHTMLCode(componentName, params) { wrap_attributes: 'preserve' }) } + +/** + * @typedef {import('govuk-frontend-lib/components').MacroOptions} MacroOptions + */ diff --git a/packages/govuk-frontend-review/src/common/nunjucks/globals/get-nunjucks-code.mjs b/packages/govuk-frontend-review/src/common/nunjucks/globals/get-nunjucks-code.mjs index cdcaf71a36..0e4accc619 100644 --- a/packages/govuk-frontend-review/src/common/nunjucks/globals/get-nunjucks-code.mjs +++ b/packages/govuk-frontend-review/src/common/nunjucks/globals/get-nunjucks-code.mjs @@ -9,8 +9,8 @@ import { componentNameToMacroName } from '../filters/index.mjs' * Component Nunjucks code (formatted) * * @param {string} componentName - Component name - * @param {unknown} params - Component macro params - * @returns {string} Nunjucks code + * @param {MacroOptions} [params] - Nunjucks macro options (or params) + * @returns {string} Nunjucks code for the component */ export function getNunjucksCode(componentName, params) { const macroName = componentNameToMacroName(componentName) @@ -37,3 +37,7 @@ export function getNunjucksCode(componentName, params) { {{ ${macroFormatted.trim()} }} ` } + +/** + * @typedef {import('govuk-frontend-lib/components').MacroOptions} MacroOptions + */ diff --git a/packages/govuk-frontend/src/govuk/all.mjs b/packages/govuk-frontend/src/govuk/all.mjs index 3a1151f4c9..cd4b27ca24 100644 --- a/packages/govuk-frontend/src/govuk/all.mjs +++ b/packages/govuk-frontend/src/govuk/all.mjs @@ -19,7 +19,7 @@ import { Tabs } from './components/tabs/tabs.mjs' * Use the `data-module` attributes to find, instantiate and init all of the * components provided as part of GOV.UK Frontend. * - * @param {Config} [config] - Config for all components + * @param {Config & { scope?: Element }} [config] - Config for all components (with optional scope) */ function initAll(config) { config = typeof config !== 'undefined' ? config : {} @@ -124,7 +124,6 @@ export { * Config for all components via `initAll()` * * @typedef {object} Config - * @property {Element} [scope=document] - Scope to query for components * @property {AccordionConfig} [accordion] - Accordion config * @property {ButtonConfig} [button] - Button config * @property {CharacterCountConfig} [characterCount] - Character Count config diff --git a/shared/helpers/nunjucks.js b/shared/helpers/nunjucks.js index 6b558cfa9e..60c1b66c64 100644 --- a/shared/helpers/nunjucks.js +++ b/shared/helpers/nunjucks.js @@ -12,13 +12,12 @@ const env = nunjucksEnv() * Render component HTML into cheerio * * @param {string} componentName - Component name - * @param {object} options - options to pass to the component macro - * @param {string} [callBlock] - if provided, the macro is called using the - * Nunjucks call tag, with the callBlock passed as the contents of the block + * @param {MacroOptions} [params] - Nunjucks macro options (or params) + * @param {string} [callBlock] - Nunjucks macro `caller()` content (optional) * @returns {import('cheerio').CheerioAPI} HTML rendered by the macro */ -function render(componentName, options, callBlock) { - return cheerio.load(renderComponent(componentName, options, callBlock)) +function render(componentName, params, callBlock) { + return cheerio.load(renderComponent(componentName, params, callBlock)) } /** @@ -46,3 +45,7 @@ module.exports = { render, renderTemplate } + +/** + * @typedef {import('govuk-frontend-lib/components').MacroOptions} MacroOptions + */ diff --git a/shared/helpers/puppeteer.js b/shared/helpers/puppeteer.js index 64dee0c18d..807e880993 100644 --- a/shared/helpers/puppeteer.js +++ b/shared/helpers/puppeteer.js @@ -71,8 +71,8 @@ async function axe(page, overrides = {}) { * @param {import('puppeteer').Page} page - Puppeteer page object * @param {string} componentName - The kebab-cased name of the component * @param {object} options - Render and initialise options - * @param {object} options.params - Nunjucks macro params - * @param {object} [options.config] - Component instantiation config + * @param {MacroOptions} [options.params] - Nunjucks macro options (or params) + * @param {Config[ConfigKey]} [options.config] - Component config (optional) * @param {($module: Element) => void} [options.beforeInitialisation] - A function that'll run in the browser * before the component gets initialised * @returns {Promise} Puppeteer page object @@ -250,3 +250,9 @@ module.exports = { getAccessibleName, isVisible } + +/** + * @typedef {import('govuk-frontend-lib/components').MacroOptions} MacroOptions + * @typedef {import('govuk-frontend').Config} Config - Config for all components via `initAll()` + * @typedef {keyof Config} ConfigKey - Component config keys, e.g. `accordion` and `characterCount` + */ diff --git a/shared/lib/components.js b/shared/lib/components.js index 0545764724..04332d5cb3 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -112,37 +112,36 @@ async function getExamples(componentName) { * Render component HTML * * @param {string} componentName - Component name - * @param {{ [key: string]: unknown }} options - Nunjucks macro options (or params) - * @param {string} [callBlock] - if provided, the macro is called using the - * Nunjucks call tag, with the callBlock passed as the contents of the block - * @returns {string} HTML rendered by the macro + * @param {MacroOptions} [params] - Nunjucks macro options (or params) + * @param {string} [callBlock] - Nunjucks macro `caller()` content (optional) + * @returns {string} HTML rendered by the component */ -function renderComponent(componentName, options, callBlock) { +function renderComponent(componentName, params, callBlock) { const macroName = componentNameToMacroName(componentName) const macroPath = `govuk/components/${componentName}/macro.njk` - return renderMacro(macroName, macroPath, options, callBlock) + return renderMacro(macroName, macroPath, params, callBlock) } /** - * Render the string result from calling a macro + * Render macro HTML * * @param {string} macroName - The name of the macro * @param {string} macroPath - The path to the file containing the macro - * @param {{ [param: string]: unknown }} options - Nunjucks macro options (or params) - * @param {string} [callBlock] - Content for an optional callBlock, if necessary for the macro to receive one - * @returns {string} The result of calling the macro + * @param {MacroOptions} [params] - Nunjucks macro options (or params) + * @param {string} [callBlock] - Nunjucks macro `caller()` content (optional) + * @returns {string} HTML rendered by the macro */ -function renderMacro(macroName, macroPath, options = {}, callBlock) { - const macroOptions = JSON.stringify(options, undefined, 2) +function renderMacro(macroName, macroPath, params = {}, callBlock) { + const paramsFormatted = JSON.stringify(params, undefined, 2) let macroString = `{%- from "${macroPath}" import ${macroName} -%}` // If we're nesting child components or text, pass the children to the macro // using the 'caller' Nunjucks feature macroString += callBlock - ? `{%- call ${macroName}(${macroOptions}) -%}${callBlock}{%- endcall -%}` - : `{{- ${macroName}(${macroOptions}) -}}` + ? `{%- call ${macroName}(${paramsFormatted}) -%}${callBlock}{%- endcall -%}` + : `{{- ${macroName}(${paramsFormatted}) -}}` return env.renderString(macroString, {}) } @@ -188,7 +187,13 @@ module.exports = { * @property {string} [description] - Example description * @property {boolean} [hidden] - Example hidden from review app * @property {string[]} [previewLayoutModifiers] - Component preview layout class modifiers - * @property {{ [param: string]: unknown }} options - Nunjucks macro options (or params) + * @property {MacroOptions} options - Nunjucks macro options (or params) + */ + +/** + * Nunjucks macro options + * + * @typedef {{ [param: string]: unknown }} MacroOptions */ /** From 1bb6712fa97ed24cfae24af2283c1b15fa6ab4bd Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 4 Aug 2023 09:12:05 +0100 Subject: [PATCH 06/14] Add component render options param for `callBlock` etc --- .../govuk/components/details/template.test.js | 8 ++++++- .../components/error-summary/template.test.js | 4 +++- .../components/fieldset/template.test.js | 8 ++++++- .../components/inset-text/template.test.js | 4 +++- .../notification-banner/template.test.js | 4 +++- .../govuk/components/panel/template.test.js | 8 ++++++- shared/helpers/nunjucks.js | 7 ++++--- shared/lib/components.js | 21 ++++++++++++------- 8 files changed, 48 insertions(+), 16 deletions(-) diff --git a/packages/govuk-frontend/src/govuk/components/details/template.test.js b/packages/govuk-frontend/src/govuk/components/details/template.test.js index 86ba3bdc93..3fb50125a8 100644 --- a/packages/govuk-frontend/src/govuk/components/details/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/details/template.test.js @@ -45,7 +45,13 @@ describe('Details', () => { }) it('renders nested components using `call`', () => { - const $ = render('details', {}, '
') + const $ = render( + 'details', + {}, + { + callBlock: '
' + } + ) expect($('.govuk-details .app-nested-component').length).toBeTruthy() }) diff --git a/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js b/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js index ebb52e7c67..0a0f56d15b 100644 --- a/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/error-summary/template.test.js @@ -91,7 +91,9 @@ describe('Error-summary', () => { const $ = render( 'error-summary', {}, - '
' + { + callBlock: '
' + } ) expect( diff --git a/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js b/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js index 1480ce4026..bad15e59a8 100644 --- a/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/fieldset/template.test.js @@ -73,7 +73,13 @@ describe('fieldset', () => { }) it('renders nested components using `call`', () => { - const $ = render('fieldset', {}, '
') + const $ = render( + 'fieldset', + {}, + { + callBlock: '
' + } + ) expect($('.govuk-fieldset .app-nested-component').length).toBeTruthy() }) diff --git a/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js b/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js index efe9fd2e11..5b84cab05c 100644 --- a/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/inset-text/template.test.js @@ -29,7 +29,9 @@ describe('Inset text', () => { const $ = render( 'inset-text', {}, - '
' + { + callBlock: '
' + } ) expect($('.govuk-inset-text .app-nested-component').length).toBeTruthy() diff --git a/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js b/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js index fd2770c704..0d0abebdd6 100644 --- a/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/notification-banner/template.test.js @@ -172,7 +172,9 @@ describe('Notification-banner', () => { const $ = render( 'notification-banner', {}, - '
' + { + callBlock: '
' + } ) expect( diff --git a/packages/govuk-frontend/src/govuk/components/panel/template.test.js b/packages/govuk-frontend/src/govuk/components/panel/template.test.js index 45c8c819f5..a92800fda5 100644 --- a/packages/govuk-frontend/src/govuk/components/panel/template.test.js +++ b/packages/govuk-frontend/src/govuk/components/panel/template.test.js @@ -63,7 +63,13 @@ describe('Panel', () => { }) it('renders nested components using `call`', () => { - const $ = render('panel', {}, '
') + const $ = render( + 'panel', + {}, + { + callBlock: '
' + } + ) expect($('.govuk-panel .app-nested-component').length).toBeTruthy() }) diff --git a/shared/helpers/nunjucks.js b/shared/helpers/nunjucks.js index 60c1b66c64..6e08021ab7 100644 --- a/shared/helpers/nunjucks.js +++ b/shared/helpers/nunjucks.js @@ -13,11 +13,11 @@ const env = nunjucksEnv() * * @param {string} componentName - Component name * @param {MacroOptions} [params] - Nunjucks macro options (or params) - * @param {string} [callBlock] - Nunjucks macro `caller()` content (optional) + * @param {MacroRenderOptions} [options] - Nunjucks macro render options * @returns {import('cheerio').CheerioAPI} HTML rendered by the macro */ -function render(componentName, params, callBlock) { - return cheerio.load(renderComponent(componentName, params, callBlock)) +function render(componentName, params, options) { + return cheerio.load(renderComponent(componentName, params, options)) } /** @@ -48,4 +48,5 @@ module.exports = { /** * @typedef {import('govuk-frontend-lib/components').MacroOptions} MacroOptions + * @typedef {import('govuk-frontend-lib/components').MacroRenderOptions} MacroRenderOptions */ diff --git a/shared/lib/components.js b/shared/lib/components.js index 04332d5cb3..81ec82a372 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -113,14 +113,14 @@ async function getExamples(componentName) { * * @param {string} componentName - Component name * @param {MacroOptions} [params] - Nunjucks macro options (or params) - * @param {string} [callBlock] - Nunjucks macro `caller()` content (optional) + * @param {MacroRenderOptions} [options] - Nunjucks macro render options * @returns {string} HTML rendered by the component */ -function renderComponent(componentName, params, callBlock) { +function renderComponent(componentName, params, options) { const macroName = componentNameToMacroName(componentName) const macroPath = `govuk/components/${componentName}/macro.njk` - return renderMacro(macroName, macroPath, params, callBlock) + return renderMacro(macroName, macroPath, params, options) } /** @@ -129,18 +129,18 @@ function renderComponent(componentName, params, callBlock) { * @param {string} macroName - The name of the macro * @param {string} macroPath - The path to the file containing the macro * @param {MacroOptions} [params] - Nunjucks macro options (or params) - * @param {string} [callBlock] - Nunjucks macro `caller()` content (optional) + * @param {MacroRenderOptions} [options] - Nunjucks macro render options * @returns {string} HTML rendered by the macro */ -function renderMacro(macroName, macroPath, params = {}, callBlock) { +function renderMacro(macroName, macroPath, params = {}, options) { const paramsFormatted = JSON.stringify(params, undefined, 2) let macroString = `{%- from "${macroPath}" import ${macroName} -%}` // If we're nesting child components or text, pass the children to the macro // using the 'caller' Nunjucks feature - macroString += callBlock - ? `{%- call ${macroName}(${paramsFormatted}) -%}${callBlock}{%- endcall -%}` + macroString += options?.callBlock + ? `{%- call ${macroName}(${paramsFormatted}) -%}${options.callBlock}{%- endcall -%}` : `{{- ${macroName}(${paramsFormatted}) -}}` return env.renderString(macroString, {}) @@ -203,6 +203,13 @@ module.exports = { * @typedef {Required & { html: string }} ComponentFixture */ +/** + * Nunjucks macro render options + * + * @typedef {object} MacroRenderOptions + * @property {string} [callBlock] - Nunjucks macro `caller()` content (optional) + */ + /** * Component fixtures * (used by the Design System website) From cd1dd30bd4917d5f3c37cb42bbc98416b0e5c306 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 3 Aug 2023 13:51:10 +0100 Subject: [PATCH 07/14] Add helper `renderString()` for Nunjucks rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for a new “Package options” parameter so we can share the same helper but pass in a local Nunjucks environment where required --- shared/helpers/nunjucks.js | 9 +++------ shared/lib/components.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/shared/helpers/nunjucks.js b/shared/helpers/nunjucks.js index 6e08021ab7..5cea28470d 100644 --- a/shared/helpers/nunjucks.js +++ b/shared/helpers/nunjucks.js @@ -1,13 +1,10 @@ const cheerio = require('cheerio') const { - nunjucksEnv, - renderComponent + renderComponent, + renderString } = require('govuk-frontend-lib/components') const { outdent } = require('outdent') -// Nunjucks default environment -const env = nunjucksEnv() - /** * Render component HTML into cheerio * @@ -38,7 +35,7 @@ function renderTemplate(context = {}, blocks = {}) { {%- endblock %}` } - return cheerio.load(env.renderString(viewString, context)) + return cheerio.load(renderString(viewString, context)) } module.exports = { diff --git a/shared/lib/components.js b/shared/lib/components.js index 81ec82a372..f355be6da3 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -143,7 +143,18 @@ function renderMacro(macroName, macroPath, params = {}, options) { ? `{%- call ${macroName}(${paramsFormatted}) -%}${options.callBlock}{%- endcall -%}` : `{{- ${macroName}(${paramsFormatted}) -}}` - return env.renderString(macroString, {}) + return renderString(macroString) +} + +/** + * Render string + * + * @param {string} string - Nunjucks string to render + * @param {object} [context] - Nunjucks context object (optional) + * @returns {string} HTML rendered from the Nunjucks string + */ +function renderString(string, context) { + return env.renderString(string, context) } module.exports = { @@ -154,7 +165,8 @@ module.exports = { getExamples, nunjucksEnv, renderComponent, - renderMacro + renderMacro, + renderString } /** From 5dc8422fc9cc746d0602f093ad6efd9bd419a4cd Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 3 Aug 2023 13:05:16 +0100 Subject: [PATCH 08/14] Add helper `getComponentNamesFiltered()` for filtered components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- packages/govuk-frontend-review/src/app.mjs | 5 +-- .../tasks/build/package.test.mjs | 7 +++-- shared/lib/components.js | 31 +++++++++++-------- shared/stats/src/index.mjs | 4 +-- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/packages/govuk-frontend-review/src/app.mjs b/packages/govuk-frontend-review/src/app.mjs index ddd8ec9c55..b18d4fbb9a 100644 --- a/packages/govuk-frontend-review/src/app.mjs +++ b/packages/govuk-frontend-review/src/app.mjs @@ -1,7 +1,8 @@ import express from 'express' import { getComponentsFixtures, - getComponentNames + getComponentNames, + getComponentNamesFiltered } from 'govuk-frontend-lib/components' import { filterPath } from 'govuk-frontend-lib/files' import { componentNameToMacroName } from 'govuk-frontend-lib/names' @@ -30,7 +31,7 @@ export default async () => { getComponentNames(), // Components list (with JavaScript only) - getComponentNames((componentName, componentFiles) => + getComponentNamesFiltered((componentName, componentFiles) => componentFiles.some(filterPath([`**/${componentName}.mjs`])) ), diff --git a/packages/govuk-frontend/tasks/build/package.test.mjs b/packages/govuk-frontend/tasks/build/package.test.mjs index 3afb96d05f..be493270e7 100644 --- a/packages/govuk-frontend/tasks/build/package.test.mjs +++ b/packages/govuk-frontend/tasks/build/package.test.mjs @@ -3,7 +3,10 @@ import { join } from 'path' import { paths, pkg } from 'govuk-frontend-config' import { compileSassFile } from 'govuk-frontend-helpers/tests' -import { getComponentNames } from 'govuk-frontend-lib/components' +import { + getComponentNames, + getComponentNamesFiltered +} from 'govuk-frontend-lib/components' import { filterPath, getListing, mapPathTo } from 'govuk-frontend-lib/files' import { componentNameToClassName } from 'govuk-frontend-lib/names' import { outdent } from 'outdent' @@ -44,7 +47,7 @@ describe('packages/govuk-frontend/dist/', () => { componentNames = await getComponentNames() // Components list (with JavaScript only) - componentNamesWithJavaScript = await getComponentNames( + componentNamesWithJavaScript = await getComponentNamesFiltered( (componentName, componentFiles) => componentFiles.some(filterPath([`**/${componentName}.mjs`])) ) diff --git a/shared/lib/components.js b/shared/lib/components.js index f355be6da3..083ab978ac 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -67,26 +67,30 @@ const getComponentFiles = (componentName = '') => ) /** - * Get component names (with optional filter) + * Get component names * - * @param {(componentName: string, componentFiles: string[]) => boolean} [filter] - Component names array filter * @returns {Promise} Component names */ -const getComponentNames = async (filter) => { - const componentNames = await getDirectories( +async function getComponentNames() { + return getDirectories( join(packageNameToPath('govuk-frontend'), '**/dist/govuk/components/') ) +} - if (filter) { - const componentFiles = await getComponentFiles() - - // Apply component names filter - return componentNames.filter((componentName) => - filter(componentName, componentFiles) - ) - } +/** + * Get component names, filtered + * + * @param {(componentName: string, componentFiles: string[]) => boolean} filter - Component names array filter + * @returns {Promise} Component names + */ +async function getComponentNamesFiltered(filter) { + const componentNames = await getComponentNames() + const componentFiles = await getComponentFiles() - return componentNames + // Apply component names filter + return componentNames.filter((componentName) => + filter(componentName, componentFiles) + ) } /** @@ -162,6 +166,7 @@ module.exports = { getComponentsFixtures, getComponentFiles, getComponentNames, + getComponentNamesFiltered, getExamples, nunjucksEnv, renderComponent, diff --git a/shared/stats/src/index.mjs b/shared/stats/src/index.mjs index f1f5b9c36c..1db5613f3d 100644 --- a/shared/stats/src/index.mjs +++ b/shared/stats/src/index.mjs @@ -1,13 +1,13 @@ import { join, parse } from 'path' import { paths } from 'govuk-frontend-config' -import { getComponentNames } from 'govuk-frontend-lib/components' +import { getComponentNamesFiltered } from 'govuk-frontend-lib/components' import { filterPath, getYaml } from 'govuk-frontend-lib/files' /** * Components with JavaScript */ -const componentNamesWithJavaScript = await getComponentNames( +const componentNamesWithJavaScript = await getComponentNamesFiltered( (componentName, componentFiles) => componentFiles.some(filterPath([`**/${componentName}.mjs`])) ) From 2b1a5ee49eb2720b874a41717fcc9fa74d8f410d Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 3 Aug 2023 12:33:10 +0100 Subject: [PATCH 09/14] Use helper `renderComponent()` for previews and HTML code Our helpers should always share the same Nunjucks environment to prevent views from `packages/govuk-frontend` running JavaScript from a locally installed legacy version --- packages/govuk-frontend-review/src/app.mjs | 18 ++++++------------ .../common/nunjucks/globals/get-html-code.mjs | 11 +++-------- shared/lib/components.js | 9 ++++++--- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/packages/govuk-frontend-review/src/app.mjs b/packages/govuk-frontend-review/src/app.mjs index b18d4fbb9a..45f8dd7a25 100644 --- a/packages/govuk-frontend-review/src/app.mjs +++ b/packages/govuk-frontend-review/src/app.mjs @@ -2,12 +2,11 @@ import express from 'express' import { getComponentsFixtures, getComponentNames, - getComponentNamesFiltered + getComponentNamesFiltered, + renderComponent } from 'govuk-frontend-lib/components' import { filterPath } from 'govuk-frontend-lib/files' -import { componentNameToMacroName } from 'govuk-frontend-lib/names' import { getStats, modulePaths } from 'govuk-frontend-stats' -import { outdent } from 'outdent' import { getExampleNames, getFullPageExamples } from './common/lib/files.mjs' import * as middleware from './common/middleware/index.mjs' @@ -149,15 +148,10 @@ export default async () => { } // Construct and evaluate the component with the data for this example - const macroName = componentNameToMacroName(componentName) - const macroParameters = JSON.stringify(fixture.options, null, '\t') - - res.locals.componentView = env.renderString( - outdent` - {% from "govuk/components/${componentName}/macro.njk" import ${macroName} %} - {{ ${macroName}(${macroParameters}) }} - `, - {} + res.locals.componentView = renderComponent( + componentName, + fixture.options, + { env } ) let bodyClasses = 'app-template__body' diff --git a/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs b/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs index 9f3b00a682..f330f28ba8 100644 --- a/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs +++ b/packages/govuk-frontend-review/src/common/nunjucks/globals/get-html-code.mjs @@ -1,5 +1,4 @@ -import { paths } from 'govuk-frontend-config' -import { packageTypeToPath } from 'govuk-frontend-lib/names' +import { renderComponent } from 'govuk-frontend-lib/components' import beautify from 'js-beautify' /** @@ -11,14 +10,10 @@ import beautify from 'js-beautify' * @returns {string} HTML rendered by the component */ export function getHTMLCode(componentName, params) { - const templatePath = packageTypeToPath('govuk-frontend', { - modulePath: `components/${componentName}/template.njk`, - moduleRoot: paths.app + const html = renderComponent(componentName, params, { + env: this.env }) - // Render to HTML - const html = this.env.render(templatePath, { params }).trim() - // Default beautify options const options = beautify.html.defaultOptions() diff --git a/shared/lib/components.js b/shared/lib/components.js index 083ab978ac..904588323d 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -147,7 +147,7 @@ function renderMacro(macroName, macroPath, params = {}, options) { ? `{%- call ${macroName}(${paramsFormatted}) -%}${options.callBlock}{%- endcall -%}` : `{{- ${macroName}(${paramsFormatted}) -}}` - return renderString(macroString) + return renderString(macroString, {}, options) } /** @@ -155,10 +155,12 @@ function renderMacro(macroName, macroPath, params = {}, options) { * * @param {string} string - Nunjucks string to render * @param {object} [context] - Nunjucks context object (optional) + * @param {MacroRenderOptions} [options] - Nunjucks macro render options * @returns {string} HTML rendered from the Nunjucks string */ -function renderString(string, context) { - return env.renderString(string, context) +function renderString(string, context, options) { + const nunjucksEnv = options?.env ?? env + return nunjucksEnv.renderString(string, context) } module.exports = { @@ -225,6 +227,7 @@ module.exports = { * * @typedef {object} MacroRenderOptions * @property {string} [callBlock] - Nunjucks macro `caller()` content (optional) + * @property {import('nunjucks').Environment} [env] - Nunjucks environment (optional) */ /** From 86962073a3ce9353863bd0d13f75321ee1b7ba5e Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 4 Aug 2023 09:45:31 +0100 Subject: [PATCH 10/14] Use helper `renderComponent()` for fixtures HTML --- shared/tasks/components.mjs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/shared/tasks/components.mjs b/shared/tasks/components.mjs index 634a1a4605..e6df673000 100644 --- a/shared/tasks/components.mjs +++ b/shared/tasks/components.mjs @@ -1,6 +1,6 @@ import { basename, dirname, join } from 'path' -import { nunjucksEnv } from 'govuk-frontend-lib/components' +import { nunjucksEnv, renderComponent } from 'govuk-frontend-lib/components' import { getListing, getYaml } from 'govuk-frontend-lib/files' import { files } from './index.mjs' @@ -94,11 +94,6 @@ async function generateFixture(componentDataPath, options) { const env = nunjucksEnv([options.srcPath]) // Nunjucks template - const template = join( - options.srcPath, - dirname(componentDataPath), - 'template.njk' - ) const componentName = basename(dirname(componentDataPath)) // Loop examples @@ -116,14 +111,8 @@ async function generateFixture(componentDataPath, options) { description: example.description ?? '', previewLayoutModifiers: example.previewLayoutModifiers ?? [], - // Wait for render to complete - html: await new Promise((resolve, reject) => { - const context = { params: example.options } - - return env.render(template, context, (error, result) => { - return error ? reject(error) : resolve(result?.trim() ?? '') - }) - }) + // Render Nunjucks example + html: renderComponent(componentName, example.options, { env }) }) ) From 5bf44606d674f0bda61489ea01006a267eb39191 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 3 Aug 2023 13:08:24 +0100 Subject: [PATCH 11/14] Fix default glob in `getComponentFiles()` to include only component files The previous default `''` incorrectly included a double slash: ``` `src/govuk/components//**/*` ``` --- shared/lib/components.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/lib/components.js b/shared/lib/components.js index 904588323d..d9279f7fbd 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -58,7 +58,7 @@ const getComponentsFixtures = async () => { * @param {string} [componentName] - Component name * @returns {Promise} Component files */ -const getComponentFiles = (componentName = '') => +const getComponentFiles = (componentName = '*') => getListing( join( packageNameToPath('govuk-frontend'), From b762b5a82e467a5a56cdae28b38ac41c2fbab5ca Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 3 Aug 2023 15:37:31 +0100 Subject: [PATCH 12/14] Use locally installed `govuk-frontend` for component names, files, data 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 --- packages/govuk-frontend-review/src/app.mjs | 15 +++-- .../src/common/nunjucks/index.mjs | 16 +++-- shared/lib/components.js | 60 ++++++++++++------- shared/stats/src/index.mjs | 3 +- 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/packages/govuk-frontend-review/src/app.mjs b/packages/govuk-frontend-review/src/app.mjs index 45f8dd7a25..0164ab149b 100644 --- a/packages/govuk-frontend-review/src/app.mjs +++ b/packages/govuk-frontend-review/src/app.mjs @@ -1,4 +1,5 @@ import express from 'express' +import { paths } from 'govuk-frontend-config' import { getComponentsFixtures, getComponentNames, @@ -16,6 +17,10 @@ import * as routes from './routes/index.mjs' export default async () => { const app = express() + // Resolve GOV.UK Frontend from review app `node_modules` + // to allow previous versions to be installed locally + const packageOptions = { moduleRoot: paths.app } + // Cache mapped components and examples const [ componentsFixtures, @@ -24,14 +29,16 @@ export default async () => { exampleNames, fullPageExamples ] = await Promise.all([ - getComponentsFixtures(), + getComponentsFixtures(packageOptions), // Components list - getComponentNames(), + getComponentNames(packageOptions), // Components list (with JavaScript only) - getComponentNamesFiltered((componentName, componentFiles) => - componentFiles.some(filterPath([`**/${componentName}.mjs`])) + getComponentNamesFiltered( + (componentName, componentFiles) => + componentFiles.some(filterPath([`**/${componentName}.mjs`])), + packageOptions ), getExampleNames(), diff --git a/packages/govuk-frontend-review/src/common/nunjucks/index.mjs b/packages/govuk-frontend-review/src/common/nunjucks/index.mjs index 981006af38..b52bcdd4db 100644 --- a/packages/govuk-frontend-review/src/common/nunjucks/index.mjs +++ b/packages/govuk-frontend-review/src/common/nunjucks/index.mjs @@ -13,11 +13,17 @@ import * as globals from './globals/index.mjs' * @returns {import('nunjucks').Environment} Nunjucks Environment */ export function renderer(app) { - const env = nunjucksEnv([join(paths.app, 'src/views')], { - express: app, // the Express.js review app that nunjucks should install to - noCache: true, // never use a cache and recompile templates each time - watch: true // reload templates when they are changed. needs chokidar dependency to be installed - }) + const env = nunjucksEnv( + [join(paths.app, 'src/views')], + { + express: app, // the Express.js review app that nunjucks should install to + noCache: true, // never use a cache and recompile templates each time + watch: true // reload templates when they are changed. needs chokidar dependency to be installed + }, + { + moduleRoot: paths.app + } + ) // Set view engine app.set('view engine', 'njk') diff --git a/shared/lib/components.js b/shared/lib/components.js index d9279f7fbd..e5a538e10f 100644 --- a/shared/lib/components.js +++ b/shared/lib/components.js @@ -1,9 +1,9 @@ -const { join } = require('path') +const { dirname, join } = require('path') const nunjucks = require('nunjucks') const { getListing, getDirectories } = require('./files') -const { packageNameToPath, componentNameToMacroName } = require('./names') +const { packageTypeToPath, componentNameToMacroName } = require('./names') // Nunjucks default environment const env = nunjucksEnv() @@ -13,13 +13,16 @@ const env = nunjucksEnv() * * @param {string[]} [searchPaths] - Nunjucks search paths (optional) * @param {import('nunjucks').ConfigureOptions} [nunjucksOptions] - Nunjucks options (optional) + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {import('nunjucks').Environment} Nunjucks environment */ -function nunjucksEnv(searchPaths = [], nunjucksOptions = {}) { - const packagePath = packageNameToPath('govuk-frontend') +function nunjucksEnv(searchPaths = [], nunjucksOptions = {}, packageOptions) { + const packagePath = dirname( + packageTypeToPath('govuk-frontend', packageOptions) + ) - // Add to Nunjucks search paths - searchPaths.push(join(packagePath, 'src')) + // Add to Nunjucks search paths (without 'govuk' suffix) + searchPaths.push(join(packagePath, '../')) // Nunjucks environment return nunjucks.configure(searchPaths, { @@ -33,47 +36,58 @@ function nunjucksEnv(searchPaths = [], nunjucksOptions = {}) { * Load single component fixtures * * @param {string} componentName - Component name + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {Promise} Component data */ -const getComponentFixtures = async (componentName) => { +const getComponentFixtures = async (componentName, packageOptions) => { return require(join( - packageNameToPath('govuk-frontend'), - `dist/govuk/components/${componentName}/fixtures.json` + dirname(packageTypeToPath('govuk-frontend', packageOptions)), + `components/${componentName}/fixtures.json` )) } /** * Load all components' data * + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {Promise<(ComponentFixtures)[]>} Components' data */ -const getComponentsFixtures = async () => { - const componentNames = await getComponentNames() - return Promise.all(componentNames.map(getComponentFixtures)) +const getComponentsFixtures = async (packageOptions) => { + const componentNames = await getComponentNames(packageOptions) + return Promise.all( + componentNames.map((componentName) => + getComponentFixtures(componentName, packageOptions) + ) + ) } /** * Get component files * * @param {string} [componentName] - Component name + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {Promise} Component files */ -const getComponentFiles = (componentName = '*') => +const getComponentFiles = (componentName = '*', packageOptions) => getListing( join( - packageNameToPath('govuk-frontend'), - `dist/govuk/components/${componentName}/**/*` + dirname(packageTypeToPath('govuk-frontend', packageOptions)), + `components/${componentName}/**/*` ) ) /** * Get component names * + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {Promise} Component names */ -async function getComponentNames() { +async function getComponentNames(packageOptions) { return getDirectories( - join(packageNameToPath('govuk-frontend'), '**/dist/govuk/components/') + join( + dirname(packageTypeToPath('govuk-frontend', packageOptions)), + 'components/' + ) ) } @@ -81,11 +95,12 @@ async function getComponentNames() { * Get component names, filtered * * @param {(componentName: string, componentFiles: string[]) => boolean} filter - Component names array filter + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {Promise} Component names */ -async function getComponentNamesFiltered(filter) { - const componentNames = await getComponentNames() - const componentFiles = await getComponentFiles() +async function getComponentNamesFiltered(filter, packageOptions) { + const componentNames = await getComponentNames(packageOptions) + const componentFiles = await getComponentFiles('*', packageOptions) // Apply component names filter return componentNames.filter((componentName) => @@ -97,10 +112,11 @@ async function getComponentNamesFiltered(filter) { * Get examples from component fixtures * * @param {string} componentName - Component name + * @param {import('./names').PackageOptions} [packageOptions] - Package options (optional) * @returns {Promise<{ [name: string]: ComponentFixture['options'] }>} Component examples as an object */ -async function getExamples(componentName) { - const { fixtures } = await getComponentFixtures(componentName) +async function getExamples(componentName, packageOptions) { + const { fixtures } = await getComponentFixtures(componentName, packageOptions) /** @type {{ [name: string]: ComponentFixture['options'] }} */ const examples = {} diff --git a/shared/stats/src/index.mjs b/shared/stats/src/index.mjs index 1db5613f3d..5b4d374480 100644 --- a/shared/stats/src/index.mjs +++ b/shared/stats/src/index.mjs @@ -9,7 +9,8 @@ import { filterPath, getYaml } from 'govuk-frontend-lib/files' */ const componentNamesWithJavaScript = await getComponentNamesFiltered( (componentName, componentFiles) => - componentFiles.some(filterPath([`**/${componentName}.mjs`])) + componentFiles.some(filterPath([`**/${componentName}.mjs`])), + { moduleRoot: paths.stats } ) /** From 27c0ba7b3837f9fd4b79f9588a151208e46cb5c4 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Mon, 14 Aug 2023 14:58:36 +0100 Subject: [PATCH 13/14] Discover missing types from `govuk-frontend-tasks` Missed from: https://github.com/alphagov/govuk-frontend/pull/4069 --- tsconfig.base.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tsconfig.base.json b/tsconfig.base.json index 1c6c97f2e1..755b5ce2cd 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -16,13 +16,14 @@ "types": [], "paths": { "govuk-frontend": ["./packages/govuk-frontend/src/govuk/all.mjs"], - "govuk-frontend-stats": ["./shared/stats/src/index.mjs"], "govuk-frontend-config": ["./shared/config/index.js"], "govuk-frontend-helpers": ["./shared/helpers/index.js"], "govuk-frontend-helpers/*": ["./shared/helpers/*.js"], "govuk-frontend-helpers/jest/*": ["./shared/helpers/jest/*"], "govuk-frontend-lib": ["./shared/lib/index.js"], - "govuk-frontend-lib/*": ["./shared/lib/*.js"] + "govuk-frontend-lib/*": ["./shared/lib/*.js"], + "govuk-frontend-stats": ["./shared/stats/src/index.mjs"], + "govuk-frontend-tasks": ["./shared/tasks/index.mjs"] } }, "typeAcquisition": { From f93e00b4443bf1f6590f07e0bef75aeb15b304db Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Mon, 14 Aug 2023 15:01:49 +0100 Subject: [PATCH 14/14] Ensure component fixtures HTML uses `.trim()` We used to add `.trim()` before moving to `renderComponent()` --- shared/tasks/components.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/tasks/components.mjs b/shared/tasks/components.mjs index e6df673000..d70538dc55 100644 --- a/shared/tasks/components.mjs +++ b/shared/tasks/components.mjs @@ -112,7 +112,7 @@ async function generateFixture(componentDataPath, options) { previewLayoutModifiers: example.previewLayoutModifiers ?? [], // Render Nunjucks example - html: renderComponent(componentName, example.options, { env }) + html: renderComponent(componentName, example.options, { env }).trim() }) )