Skip to content

Commit

Permalink
Merge pull request #2658 from alphagov/full-resolve-js-path
Browse files Browse the repository at this point in the history
Add missing mandatory file extensions for ESM JavaScript
  • Loading branch information
Vanita Barrett-Smith committed Jun 20, 2022
2 parents da32bb0 + b4e1dec commit 9a091c3
Show file tree
Hide file tree
Showing 34 changed files with 95 additions and 87 deletions.
18 changes: 14 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

### New features

#### Help users navigate through pages with pagination

You can now use [pagination](https://design-system.service.gov.uk/components/pagination/) to help users navigate forwards and backwards through a series of pages. For example, in search results or guidance that's divided into multiple website pages.

This was added in [pull request #2610: Add pagination component](https://github.com/alphagov/govuk-frontend/pull/2610).

#### Check checkboxes by using the `values` Nunjucks option

When using the `govukCheckboxes` Nunjucks macro, you can now use the `values` option to indicate which checkboxes should be checked when the page loads.
Expand Down Expand Up @@ -44,13 +50,17 @@ We've deprecated the `govuk-header__link--service-name` class, and will remove i

This change was introduced in [pull request #2617: Do not make the service name in the header a link if no `serviceUrl` is provided](https://github.com/alphagov/govuk-frontend/pull/2617).

### New features
#### File extensions added for JavaScript ES Module imports

#### Help users navigate through pages with pagination
We have updated our component ES module JavaScript to include [missing file extensions](https://nodejs.org/api/esm.html#mandatory-file-extensions) not provided in release 4.1.0. If you have received an error similar to the one below, this fix should resolve the issue.

You can now use [pagination](https://design-system.service.gov.uk/components/pagination/) to help users navigate forwards and backwards through a series of pages. For example, in search results or guidance that's divided into multiple website pages.
```
Cannot find module '../node_modules/govuk-frontend/govuk-esm/common' imported from ../node_modules/govuk-frontend/govuk-esm/all.mjs
```

This was added in [pull request #2610: Add pagination component](https://github.com/alphagov/govuk-frontend/pull/2610).
You should not need to make any changes if you are successfully importing our JavaScript as ES modules with version 4.1.0, but there still might be config you can remove. For example, removing `fullySpecified: false` from your Webpack config file.

This change was introduced in [pull request #2658: Add missing mandatory file extensions for ESM JavaScript](https://github.com/alphagov/govuk-frontend/pull/2658)

### Fixes

Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/coding-standards/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ When creating your component, you should create the following files in the compo

If your component uses JavaScript, you must also create the following files in the component’s folder:

- `_[component-name].js`
- `_[component-name].mjs`
- `_[component-name].test.js`

## Building your components
Expand Down
10 changes: 6 additions & 4 deletions docs/contributing/coding-standards/js.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ JavaScript files have the same name as the component's folder name. Test files h

```
checkboxes
├── checkboxes.js
├── checkboxes.mjs
└── checkboxes.test.js
```

## Skeleton

```js
import { nodeListForEach } from '../vendor/common'
import { nodeListForEach } from '../vendor/common.mjs'

function Checkboxes ($module) {
// code goes here
Expand Down Expand Up @@ -109,13 +109,15 @@ var myCheckbox = new Checkbox().init()
Use ES6 modules (`import`/`export`) over a non-standard module system. You can always transpile to your preferred module system.

```js
import { nodeListForEach } from '../vendor/common'
import { nodeListForEach } from '../vendor/common.mjs'
// code goes here
export default Checkboxes
```

Avoid using wildcard (`import * as nodeListForEach`) imports.

You must specify the file extension for a file when importing it.

Use default export over named export.

## Polyfilling
Expand All @@ -125,7 +127,7 @@ If you need to support older browsers, import the necessary [polyfills](/src/gov
For example, if you want to polyfill `addEventListener` for IE8, import the Event polyfills.

```js
import '../vendor/polyfills/Event'
import '../vendor/polyfills/Event.mjs'
```

If you need polyfills for features that are not yet included in this project, please see the following guide on [how to add polyfills](../polyfilling.md).
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ This task will:
**`gulp watch`**

This task will:
- watch for changes in .js, .scss and .njk files and run below tasks.
- watch for changes in .mjs, .scss and .njk files and run below tasks.

**`gulp styles`**

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"/dist/**/*.js",
"/package/**/*.js",
"/package/**/*.mjs",
"/src/govuk/vendor/polyfills/**/*.js"
"/src/govuk/vendor/polyfills/**/*.mjs"
]
},
"jest": {
Expand Down
24 changes: 12 additions & 12 deletions src/govuk/all.js → src/govuk/all.mjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { nodeListForEach } from './common'
import Accordion from './components/accordion/accordion'
import Button from './components/button/button'
import Details from './components/details/details'
import CharacterCount from './components/character-count/character-count'
import Checkboxes from './components/checkboxes/checkboxes'
import ErrorSummary from './components/error-summary/error-summary'
import NotificationBanner from './components/notification-banner/notification-banner'
import Header from './components/header/header'
import Radios from './components/radios/radios'
import SkipLink from './components/skip-link/skip-link'
import Tabs from './components/tabs/tabs'
import { nodeListForEach } from './common.mjs'
import Accordion from './components/accordion/accordion.mjs'
import Button from './components/button/button.mjs'
import Details from './components/details/details.mjs'
import CharacterCount from './components/character-count/character-count.mjs'
import Checkboxes from './components/checkboxes/checkboxes.mjs'
import ErrorSummary from './components/error-summary/error-summary.mjs'
import NotificationBanner from './components/notification-banner/notification-banner.mjs'
import Header from './components/header/header.mjs'
import Radios from './components/radios/radios.mjs'
import SkipLink from './components/skip-link/skip-link.mjs'
import Tabs from './components/tabs/tabs.mjs'

function initAll (options) {
// Set the options to an empty object by default if no options are passed.
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
*/

import { nodeListForEach } from '../../common'
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Element/prototype/classList'
import { nodeListForEach } from '../../common.mjs'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'

function Accordion ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import '../../vendor/polyfills/Event' // addEventListener and event.target normaliziation
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normaliziation
import '../../vendor/polyfills/Function/prototype/bind.mjs'

var KEY_SPACE = 32
var DEBOUNCE_TIMEOUT_IN_SECONDS = 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Event' // addEventListener and event.target normaliziation
import '../../vendor/polyfills/Element/prototype/classList'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normaliziation
import '../../vendor/polyfills/Element/prototype/classList.mjs'

function CharacterCount ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
// addEventListener, event.target normalization and DOMContentLoaded
import '../../vendor/polyfills/Event'
import '../../vendor/polyfills/Element/prototype/classList'
import { nodeListForEach } from '../../common'
import '../../vendor/polyfills/Event.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'
import { nodeListForEach } from '../../common.mjs'

function Checkboxes ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
*
* http://caniuse.com/#feat=details
*/
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Event' // addEventListener and event.target normaliziation
import { generateUniqueID } from '../../common'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normaliziation
import { generateUniqueID } from '../../common.mjs'

var KEY_ENTER = 13
var KEY_SPACE = 32
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Event' // addEventListener
import '../../vendor/polyfills/Element/prototype/closest'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Event.mjs' // addEventListener
import '../../vendor/polyfills/Element/prototype/closest.mjs'

function ErrorSummary ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../../vendor/polyfills/Event'
import '../../vendor/polyfills/Element/prototype/classList'
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Event.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'
import '../../vendor/polyfills/Function/prototype/bind.mjs'

function Header ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '../../vendor/polyfills/Event' // addEventListener
import '../../vendor/polyfills/Event.mjs' // addEventListener

function NotificationBanner ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
// addEventListener, event.target normalization and DOMContentLoaded
import '../../vendor/polyfills/Event'
import '../../vendor/polyfills/Element/prototype/classList'
import { nodeListForEach } from '../../common'
import '../../vendor/polyfills/Event.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'
import { nodeListForEach } from '../../common.mjs'

function Radios ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Element/prototype/classList'
import '../../vendor/polyfills/Event' // addEventListener and event.target normalization
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'
import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normalization

function SkipLink ($module) {
this.$module = $module
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import '../../vendor/polyfills/Function/prototype/bind'
import '../../vendor/polyfills/Element/prototype/classList'
import '../../vendor/polyfills/Element/prototype/nextElementSibling'
import '../../vendor/polyfills/Element/prototype/previousElementSibling'
import '../../vendor/polyfills/Event' // addEventListener and event.target normaliziation
import { nodeListForEach } from '../../common'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/Element/prototype/classList.mjs'
import '../../vendor/polyfills/Element/prototype/nextElementSibling.mjs'
import '../../vendor/polyfills/Element/prototype/previousElementSibling.mjs'
import '../../vendor/polyfills/Event.mjs' // addEventListener and event.target normaliziation
import { nodeListForEach } from '../../common.mjs'

function Tabs ($module) {
this.$module = $module
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import './Document'
import './Document.mjs'

(function(undefined) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../../Object/defineProperty'
import '../../DOMTokenList'
import '../../Element'
import '../../Object/defineProperty.mjs'
import '../../DOMTokenList.mjs'
import '../../Element.mjs'

(function(undefined) {

Expand Down Expand Up @@ -90,4 +90,4 @@ import '../../Element'
addProp(global.HTMLAreaElement, "relList", "rel");
}(this));

}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import './matches'
import './matches.mjs'

(function(undefined) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import '../../Object/defineProperty'
import '../../Element'
import '../../Object/defineProperty.mjs'
import '../../Element.mjs'

(function(undefined) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import '../../Object/defineProperty'
import '../../Element'
import '../../Object/defineProperty.mjs'
import '../../Element.mjs'

(function(undefined) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './Window'
import './Element'
import './Object/defineProperty'
import './Window.mjs'
import './Element.mjs'
import './Object/defineProperty.mjs'

(function(undefined) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '../../Object/defineProperty'
import '../../Object/defineProperty.mjs'

(function(undefined) {
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Function/prototype/bind/detect.js
Expand Down
File renamed without changes.
9 changes: 3 additions & 6 deletions tasks/gulp/__tests__/after-build-package.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,11 @@ describe('package/', () => {
var fileWithoutSrc = file.replace(/^src\//, '')

// Account for govuk-esm folder
if (fileWithoutSrc.split('.').pop() === 'js') {
if (fileWithoutSrc.split('.').pop() === 'mjs') {
var esmFile = fileWithoutSrc.replace('govuk/', 'govuk-esm/')
var umdFile = fileWithoutSrc.replace('.mjs', '.js')

if (!esmFile.includes('vendor/')) {
esmFile = esmFile.replace('.js', '.mjs')
}

return [fileWithoutSrc, esmFile]
return [umdFile, esmFile]
} else {
return fileWithoutSrc
}
Expand Down
5 changes: 4 additions & 1 deletion tasks/gulp/compile-assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ gulp.task('scss:compile', function (done) {
// --------------------------------------
gulp.task('js:compile', (done) => {
// For dist/ folder we only want compiled 'all.js'
const fileLookup = isDist ? configPaths.src + 'all.js' : configPaths.src + '**/!(*.test).js'
const fileLookup = isDist ? configPaths.src + 'all.mjs' : configPaths.src + '**/!(*.test).mjs'

// Perform a synchronous search and return an array of matching file names
const srcFiles = glob.sync(fileLookup)
Expand Down Expand Up @@ -225,6 +225,9 @@ gulp.task('js:compile', (done) => {
extname: '.min.js'
})
))
.pipe(rename({
extname: '.js'
}))
.pipe(eol())
.pipe(gulp.dest(destinationPath() + newDirectoryPath))
})
Expand Down
10 changes: 3 additions & 7 deletions tasks/gulp/copy-to-destination.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ gulp.task('copy-files', () => {
return gulp.src([
configPaths.src + '**/*',
'!**/.DS_Store',
'!**/*.test.js',
'!**/*.mjs',
'!**/*.test.*',
'!' + configPaths.src + 'README.md', // Don't override the existing README in /package
'!' + configPaths.components + '**/__snapshots__/**',
'!' + configPaths.components + '**/__snapshots__/'
Expand Down Expand Up @@ -86,12 +87,7 @@ function generateFixtures (file) {
}

gulp.task('js:copy-esm', () => {
return gulp.src([configPaths.src + '**/*.js', '!' + configPaths.src + '/**/*.test.js'])
.pipe(rename(function (path) {
if (!path.dirname.includes('vendor')) {
path.extname = '.mjs'
}
}))
return gulp.src([configPaths.src + '**/*.mjs', configPaths.src + '**/*.js', '!' + configPaths.src + '/**/*.test.js'])
.pipe(gulp.dest(taskArguments.destination + '/govuk-esm/'))
})

Expand Down
2 changes: 1 addition & 1 deletion tasks/gulp/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ const configPaths = require('../../config/paths.json')
// ---------------------------------------
gulp.task('watch', () => Promise.all([
gulp.watch([configPaths.src + '**/**/*.scss', configPaths.app + 'assets/scss/**/*.scss', configPaths.fullPageExamples + '**/*.scss'], gulp.parallel('styles', 'sassdoc')),
gulp.watch([configPaths.src + '**/**/*.js'], gulp.series('scripts'))
gulp.watch([configPaths.src + '**/**/*.mjs'], gulp.series('scripts'))
]))

0 comments on commit 9a091c3

Please sign in to comment.