Skip to content

Commit 180d09c

Browse files
Merge pull request #2997 from alphagov/fix-types-i18n
Various JSDoc + type checking fixes (for v4.4.0 only)
2 parents fefdb30 + a80ecde commit 180d09c

File tree

11 files changed

+148
-69
lines changed

11 files changed

+148
-69
lines changed

jsdoc.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@ module.exports = {
1010
source: {
1111
includePattern: '.+\\.m?js$',
1212
excludePattern: '.+\\.test.m?js$'
13+
},
14+
templates: {
15+
cleverLinks: true
1316
}
1417
}

src/govuk/all.mjs

+13-7
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,7 @@ import Tabs from './components/tabs/tabs.mjs'
1717
* Use the `data-module` attributes to find, instantiate and init all of the
1818
* components provided as part of GOV.UK Frontend.
1919
*
20-
* @param {object} [config] - Config
21-
* @param {HTMLElement} [config.scope=document] - Scope to query for components
22-
* @param {object} [config.accordion] - Accordion config
23-
* @param {object} [config.button] - Button config
24-
* @param {object} [config.characterCount] - Character Count config
25-
* @param {object} [config.errorSummary] - Error Summary config
26-
* @param {object} [config.notificationBanner] - Notification Banner config
20+
* @param {Config} [config] - Config for all components
2721
*/
2822
function initAll (config) {
2923
config = typeof config !== 'undefined' ? config : {}
@@ -103,3 +97,15 @@ export {
10397
SkipLink,
10498
Tabs
10599
}
100+
101+
/**
102+
* Config for all components
103+
*
104+
* @typedef {object} Config
105+
* @property {HTMLElement} [scope=document] - Scope to query for components
106+
* @property {import('./components/accordion/accordion.mjs').AccordionConfig} [accordion] - Accordion config
107+
* @property {import('./components/button/button.mjs').ButtonConfig} [button] - Button config
108+
* @property {import('./components/character-count/character-count.mjs').CharacterCountConfig} [characterCount] - Character Count config
109+
* @property {import('./components/error-summary/error-summary.mjs').ErrorSummaryConfig} [errorSummary] - Error Summary config
110+
* @property {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} [notificationBanner] - Notification Banner config
111+
*/

src/govuk/components/accordion/accordion.mjs

+15-5
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ import '../../vendor/polyfills/String/prototype/trim.mjs'
66
import { normaliseDataset } from '../../common/normalise-dataset.mjs'
77

88
/**
9+
* @constant
910
* @type {AccordionTranslations}
11+
* @see Default value for {@link AccordionConfig.i18n}
12+
* @default
1013
*/
11-
var TRANSLATIONS_DEFAULT = {
14+
var ACCORDION_TRANSLATIONS = {
1215
hideAllSections: 'Hide all sections',
1316
hideSection: 'Hide',
1417
hideSectionAriaLabel: 'Hide this section',
@@ -31,17 +34,15 @@ var TRANSLATIONS_DEFAULT = {
3134
*
3235
* @class
3336
* @param {HTMLElement} $module - HTML element to use for accordion
34-
* @param {object} config - Accordion config
35-
* @param {AccordionTranslations} config.i18n - Translations
37+
* @param {AccordionConfig} [config] - Accordion config
3638
*/
3739
function Accordion ($module, config) {
3840
this.$module = $module
3941
this.$sections = $module.querySelectorAll('.govuk-accordion__section')
40-
this.$showAllButton = ''
4142
this.browserSupportsSessionStorage = helper.checkForSessionStorage()
4243

4344
var defaultConfig = {
44-
i18n: TRANSLATIONS_DEFAULT
45+
i18n: ACCORDION_TRANSLATIONS
4546
}
4647
this.config = mergeConfigs(
4748
defaultConfig,
@@ -404,6 +405,15 @@ Accordion.prototype.getButtonPunctuationEl = function () {
404405
export default Accordion
405406

406407
/**
408+
* Accordion config
409+
*
410+
* @typedef {object} AccordionConfig
411+
* @property {AccordionTranslations} [i18n = ACCORDION_TRANSLATIONS] - See constant {@link ACCORDION_TRANSLATIONS}
412+
*/
413+
414+
/**
415+
* Accordion translations
416+
*
407417
* @typedef {object} AccordionTranslations
408418
*
409419
* Messages used by the component for the labels of its buttons. This includes

src/govuk/components/button/button.mjs

+10-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ var DEBOUNCE_TIMEOUT_IN_SECONDS = 1
1111
*
1212
* @class
1313
* @param {HTMLElement} $module - The element this component controls
14-
* @param {object} config - Button config
15-
* @param {boolean} [config.preventDoubleClick=false] -
16-
* Prevent accidental double clicks on submit buttons from submitting forms
17-
* multiple times.
14+
* @param {ButtonConfig} config - Button config
1815
*/
1916
function Button ($module, config) {
2017
if (!$module) {
@@ -93,3 +90,12 @@ Button.prototype.debounce = function (event) {
9390
}
9491

9592
export default Button
93+
94+
/**
95+
* Button config
96+
*
97+
* @typedef {object} ButtonConfig
98+
* @property {boolean} [preventDoubleClick = false] -
99+
* Prevent accidental double clicks on submit buttons from submitting forms
100+
* multiple times.
101+
*/

src/govuk/components/character-count/character-count.mjs

+44-15
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ import { normaliseDataset } from '../../common/normalise-dataset.mjs'
88
import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'
99

1010
/**
11+
* @constant
1112
* @type {CharacterCountTranslations}
13+
* @see Default value for {@link CharacterCountConfig.i18n}
14+
* @default
1215
*/
13-
var TRANSLATIONS_DEFAULT = {
16+
var CHARACTER_COUNT_TRANSLATIONS = {
1417
// Characters
1518
charactersUnderLimit: {
1619
one: 'You have %{count} character remaining',
@@ -48,13 +51,7 @@ var TRANSLATIONS_DEFAULT = {
4851
*
4952
* @class
5053
* @param {HTMLElement} $module - The element this component controls
51-
* @param {object} config - Character count config
52-
* @param {number} config.maxlength - The maximum number of characters. If maxwords is provided, the maxlength option will be ignored.
53-
* @param {number} config.maxwords - The maximum number of words. If maxwords is provided, the maxlength option will be ignored.
54-
* @param {number} [config.threshold=0] - The percentage value of the limit at
55-
* which point the count message is displayed. If this attribute is set, the
56-
* count message will be hidden by default.
57-
* @param {CharacterCountTranslations} [config.i18n = DEFAULT_TRANSLATIONS]
54+
* @param {CharacterCountConfig} [config] - Character count config
5855
*/
5956
function CharacterCount ($module, config) {
6057
if (!$module) {
@@ -63,7 +60,7 @@ function CharacterCount ($module, config) {
6360

6461
var defaultConfig = {
6562
threshold: 0,
66-
i18n: TRANSLATIONS_DEFAULT
63+
i18n: CHARACTER_COUNT_TRANSLATIONS
6764
}
6865

6966
// Read config set using dataset ('data-' values)
@@ -376,12 +373,44 @@ CharacterCount.prototype.isOverThreshold = function () {
376373
export default CharacterCount
377374

378375
/**
376+
* Character count config
377+
*
378+
* @typedef {CharacterCountConfigWithMaxLength | CharacterCountConfigWithMaxWords} CharacterCountConfig
379+
*/
380+
381+
/**
382+
* Character count config (with maximum number of characters)
383+
*
384+
* @typedef {object} CharacterCountConfigWithMaxLength
385+
* @property {number} [maxlength] - The maximum number of characters.
386+
* If maxwords is provided, the maxlength option will be ignored.
387+
* @property {number} [threshold = 0] - The percentage value of the limit at
388+
* which point the count message is displayed. If this attribute is set, the
389+
* count message will be hidden by default.
390+
* @property {CharacterCountTranslations} [i18n = CHARACTER_COUNT_TRANSLATIONS] - See constant {@link CHARACTER_COUNT_TRANSLATIONS}
391+
*/
392+
393+
/**
394+
* Character count config (with maximum number of words)
395+
*
396+
* @typedef {object} CharacterCountConfigWithMaxWords
397+
* @property {number} [maxwords] - The maximum number of words. If maxwords is
398+
* provided, the maxlength option will be ignored.
399+
* @property {number} [threshold = 0] - The percentage value of the limit at
400+
* which point the count message is displayed. If this attribute is set, the
401+
* count message will be hidden by default.
402+
* @property {CharacterCountTranslations} [i18n = CHARACTER_COUNT_TRANSLATIONS] - See constant {@link CHARACTER_COUNT_TRANSLATIONS}
403+
*/
404+
405+
/**
406+
* Character count translations
407+
*
379408
* @typedef {object} CharacterCountTranslations
380409
*
381410
* Messages shown to users as they type. It provides feedback on how many words
382411
* or characters they have remaining or if they are over the limit. This also
383412
* includes a message used as an accessible description for the textarea.
384-
* @property {PluralisedTranslation} [charactersUnderLimit] - Message displayed
413+
* @property {TranslationPluralForms} [charactersUnderLimit] - Message displayed
385414
* when the number of characters is under the configured maximum, `maxlength`.
386415
* This message is displayed visually and through assistive technologies. The
387416
* component will replace the `%{count}` placeholder with the number of
@@ -390,13 +419,13 @@ export default CharacterCount
390419
* @property {string} [charactersAtLimit] - Message displayed when the number of
391420
* characters reaches the configured maximum, `maxlength`. This message is
392421
* displayed visually and through assistive technologies.
393-
* @property {PluralisedTranslation} [charactersOverLimit] - Message displayed
422+
* @property {TranslationPluralForms} [charactersOverLimit] - Message displayed
394423
* when the number of characters is over the configured maximum, `maxlength`.
395424
* This message is displayed visually and through assistive technologies. The
396425
* component will replace the `%{count}` placeholder with the number of
397426
* remaining characters. This is a [pluralised list of
398427
* messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).
399-
* @property {PluralisedTranslation} [wordsUnderLimit] - Message displayed when
428+
* @property {TranslationPluralForms} [wordsUnderLimit] - Message displayed when
400429
* the number of words is under the configured maximum, `maxlength`. This
401430
* message is displayed visually and through assistive technologies. The
402431
* component will replace the `%{count}` placeholder with the number of
@@ -405,13 +434,13 @@ export default CharacterCount
405434
* @property {string} [wordsAtLimit] - Message displayed when the number of
406435
* words reaches the configured maximum, `maxlength`. This message is
407436
* displayed visually and through assistive technologies.
408-
* @property {PluralisedTranslation} [wordsOverLimit] - Message displayed when
437+
* @property {TranslationPluralForms} [wordsOverLimit] - Message displayed when
409438
* the number of words is over the configured maximum, `maxlength`. This
410439
* message is displayed visually and through assistive technologies. The
411440
* component will replace the `%{count}` placeholder with the number of
412441
* remaining words. This is a [pluralised list of
413442
* messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).
414-
* @property {PluralisedTranslation} [textareaDescription] - Message made
443+
* @property {TranslationPluralForms} [textareaDescription] - Message made
415444
* available to assistive technologies, if none is already present in the
416445
* HTML, to describe that the component accepts only a limited amount of
417446
* content. It is visible on the page when JavaScript is unavailable. The
@@ -420,5 +449,5 @@ export default CharacterCount
420449
*/
421450

422451
/**
423-
* @typedef {import('../../i18n.mjs').PluralisedTranslation} PluralisedTranslation
452+
* @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
424453
*/

src/govuk/components/character-count/character-count.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ describe('Character count', () => {
663663

664664
await renderAndInitialise(page, 'character-count', {
665665
nunjucksParams: examples.default,
666-
config: {
666+
javascriptConfig: {
667667
// Override maxlength to 10
668668
maxlength: 10
669669
},

src/govuk/components/character-count/character-count.unit.test.mjs

+10-7
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ describe('CharacterCount', () => {
3838
describe('JavaScript configuration', () => {
3939
it('overrides the default translation keys', () => {
4040
const component = new CharacterCount(document.createElement('div'), {
41-
i18n: { charactersUnderLimit: { one: 'Custom text. Count: %{count}' } },
42-
'i18n.charactersOverLimit.other': 'Different custom text. Count: %{count}'
41+
i18n: { charactersUnderLimit: { one: 'Custom text. Count: %{count}' } }
4342
})
4443

4544
expect(component.formatCountMessage(1, 'characters')).toEqual('Custom text. Count: 1')
46-
expect(component.formatCountMessage(-10, 'characters')).toEqual('Different custom text. Count: 10')
4745
// Other keys remain untouched
4846
expect(component.formatCountMessage(10, 'characters')).toEqual('You have 10 characters remaining')
4947
})
5048

5149
it('uses specific keys for when limit is reached', () => {
5250
const component = new CharacterCount(document.createElement('div'), {
53-
i18n: { charactersAtLimit: 'Custom text.' },
54-
'i18n.wordsAtLimit': 'Different custom text.'
51+
i18n: {
52+
charactersAtLimit: 'Custom text.',
53+
wordsAtLimit: 'Different custom text.'
54+
}
5555
})
5656

5757
expect(component.formatCountMessage(0, 'characters')).toEqual('Custom text.')
@@ -101,12 +101,15 @@ describe('CharacterCount', () => {
101101

102102
const component = new CharacterCount($div, {
103103
i18n: {
104-
charactersUnderLimitOne: 'Different custom text. Count: %{count}'
104+
charactersUnderLimit: {
105+
one: 'Different custom text. Count: %{count}'
106+
}
105107
}
106108
})
107109
expect(component.formatCountMessage(1, 'characters')).toEqual('Custom text. Count: 1')
108110
// Other keys remain untouched
109-
expect(component.formatCountMessage(10, 'characters')).toEqual('You have 10 characters remaining')
111+
expect(component.formatCountMessage(-10, 'characters')).toEqual('You have 10 characters too many')
112+
expect(component.formatCountMessage(0, 'characters')).toEqual('You have 0 characters remaining')
110113
})
111114
})
112115
})

src/govuk/components/error-summary/error-summary.mjs

+9-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ import { normaliseDataset } from '../../common/normalise-dataset.mjs'
1212
*
1313
* @class
1414
* @param {HTMLElement} $module - The element this component controls
15-
* @param {object} config - Error summary config
16-
* @param {boolean} [config.disableAutoFocus=false] - If set to `true` the error summary will not be focussed when the page loads.
15+
* @param {ErrorSummaryConfig} config - Error summary config
1716
*/
1817
function ErrorSummary ($module, config) {
1918
// Some consuming code may not be passing a module,
@@ -201,3 +200,11 @@ ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
201200
}
202201

203202
export default ErrorSummary
203+
204+
/**
205+
* Error summary config
206+
*
207+
* @typedef {object} ErrorSummaryConfig
208+
* @property {boolean} [disableAutoFocus = false] -
209+
* If set to `true` the error summary will not be focussed when the page loads.
210+
*/

src/govuk/components/notification-banner/notification-banner.mjs

+12-6
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@ import { normaliseDataset } from '../../common/normalise-dataset.mjs'
88
*
99
* @class
1010
* @param {HTMLElement} $module - HTML element to use for notification banner
11-
* @param {object} config - Error summary config
12-
* @param {boolean} [config.disableAutoFocus=false] -
13-
* If set to `true` the notification banner will not be focussed when the page
14-
* loads. This only applies if the component has a `role` of `alert` – in
15-
* other cases the component will not be focused on page load, regardless of
16-
* this option.
11+
* @param {NotificationBannerConfig} config - Notification banner config
1712
*/
1813
function NotificationBanner ($module, config) {
1914
this.$module = $module
@@ -77,3 +72,14 @@ NotificationBanner.prototype.setFocus = function () {
7772
}
7873

7974
export default NotificationBanner
75+
76+
/**
77+
* Notification banner config
78+
*
79+
* @typedef {object} NotificationBannerConfig
80+
* @property {boolean} [disableAutoFocus = false] -
81+
* If set to `true` the notification banner will not be focussed when the page
82+
* loads. This only applies if the component has a `role` of `alert` – in
83+
* other cases the component will not be focused on page load, regardless of
84+
* this option.
85+
*/

src/govuk/i18n.mjs

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
*
55
* @class
66
* @private
7-
* @param {object} translations - Key-value pairs of the translation strings to use.
8-
* @param {object} config - Configuration options for the function.
7+
* @param {TranslationsFlattened} translations - Key-value pairs of the translation strings to use.
8+
* @param {object} [config] - Configuration options for the function.
99
* @param {string} config.locale - An overriding locale for the PluralRules functionality.
1010
*/
1111
export function I18n (translations, config) {
12-
config = config || {}
13-
1412
// Make list of translations available throughout function
1513
this.translations = translations || {}
1614

1715
// The locale to use for PluralRules and NumberFormat
18-
this.locale = config.locale || document.documentElement.lang || 'en'
16+
this.locale = (config && config.locale) || document.documentElement.lang || 'en'
1917
}
2018

2119
/**
@@ -261,7 +259,7 @@ I18n.prototype.getPluralRulesForLocale = function () {
261259
* Spanish: European Portuguese (pt-PT), Italian (it), Spanish (es)
262260
* Welsh: Welsh (cy)
263261
*
264-
* @type {Object<string, string[]>}
262+
* @type {Object<PluralRuleName, string[]>}
265263
*/
266264
I18n.pluralRulesMap = {
267265
arabic: ['ar'],
@@ -360,16 +358,23 @@ I18n.pluralRules = {
360358
*/
361359

362360
/**
363-
* Associates translated messages to plural type they correspond to.
361+
* Translated message by plural rule they correspond to.
364362
*
365363
* Allows to group pluralised messages under a single key when passing
366364
* translations to a component's constructor
367365
*
368-
* @typedef {object} PluralisedTranslation
369-
* @property {string} other - General plural form
366+
* @typedef {object} TranslationPluralForms
367+
* @property {string} [other] - General plural form
370368
* @property {string} [zero] - Plural form used with 0
371369
* @property {string} [one] - Plural form used with 1
372370
* @property {string} [two] - Plural form used with 2
373371
* @property {string} [few] - Plural form used for a few
374372
* @property {string} [many] - Plural form used for many
375373
*/
374+
375+
/**
376+
* Translated messages (flattened)
377+
*
378+
* @private
379+
* @typedef {Object<string, string> | {}} TranslationsFlattened
380+
*/

0 commit comments

Comments
 (0)