Skip to content

Commit

Permalink
proof of concept for multi-init and multi-comp
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickpatrickpatrick committed Sep 10, 2024
1 parent febb002 commit 1c9f255
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 11 deletions.
35 changes: 33 additions & 2 deletions packages/govuk-frontend/src/govuk/common/index.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
import { normaliseString } from './normalise-string.mjs'

/**
* Convert a kebab-cased string to a PascalCased one TEMP BECAUSE JSDOC WAS BEING ANNOYING
*
* @param {string} value - Input kebab-cased string
* @returns {string} Output PascalCased string
*/
function kebabCaseToPascalCase(value) {
return (
value
.toLowerCase()
.split('-')
// capitalize each 'word'
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join('')
)
}

/**
* Convert a kebab-cased string to a camelCased one TEMP BECAUSE JSDOC WAS BEING ANNOYING
*
* @param {string} value - Input kebab-cased string
* @returns {string} Output camelCased string
*/
function kebabCaseToCamelCase(value) {
return kebabCaseToPascalCase(value).replace(/^./, (str) => str.toLowerCase())
}

/**
* Common helpers which do not require polyfill.
*
Expand Down Expand Up @@ -193,10 +220,14 @@ export function setFocus($element, options = {}) {
*
* @internal
* @param {Element} $module - HTML element to be checked
* @param {string} moduleName - name of component module
* @returns {boolean} Whether component is already initialised
*/
export function isInitialised($module) {
return $module instanceof HTMLElement && 'moduleInit' in $module.dataset
export function isInitialised($module, moduleName) {
return (
$module instanceof HTMLElement &&
`${kebabCaseToCamelCase(moduleName)}Init` in $module.dataset
)
}

/**
Expand Down
14 changes: 10 additions & 4 deletions packages/govuk-frontend/src/govuk/errors/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,17 @@ export class InitError extends GOVUKFrontendError {

/**
* @internal
* @param {Element} $module - HTML element already initialised
* @param {string|undefined} moduleName - name of the component module
* @param {string} [className] - name of the component module
*/
constructor($module) {
const moduleName = $module.getAttribute('data-module')
super(`Root element (\`$module\`) already initialised (\`${moduleName}\`)`)
constructor(moduleName, className) {
let errorText = `moduleName not defined in component ${className}`

if (typeof moduleName === 'string') {
errorText = `Root element (\`$module\`) already initialised (\`${moduleName}\`)`
}

super(errorText)
}
}

Expand Down
23 changes: 19 additions & 4 deletions packages/govuk-frontend/src/govuk/govuk-frontend-component.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { InitError, SupportError } from './errors/index.mjs'
* @abstract
*/
export class GOVUKFrontendComponent {
/**
* @type {string|undefined}
*/
static moduleName
/**
* Constructs a new component, validating that GOV.UK Frontend is supported
*
Expand All @@ -20,8 +24,15 @@ export class GOVUKFrontendComponent {
this.checkSupport()
this.checkInitialised($module)

// Mark component as initialised in HTML
$module?.setAttribute('data-module-init', 'true')
const moduleName = /** @type {typeof GOVUKFrontendComponent} */ (
this.constructor
).moduleName

if (typeof moduleName === 'string') {
moduleName && $module?.setAttribute(`data-${moduleName}-init`, 'true')
} else {
throw new InitError(moduleName, this.constructor.name)
}
}

/**
Expand All @@ -32,8 +43,12 @@ export class GOVUKFrontendComponent {
* @throws {InitError} when component is already initialised
*/
checkInitialised($module) {
if ($module && isInitialised($module)) {
throw new InitError($module)
const moduleName = /** @type {typeof GOVUKFrontendComponent} */ (
this.constructor
).moduleName

if ($module && moduleName && isInitialised($module, moduleName)) {
throw new InitError(moduleName)
}
}

Expand Down
3 changes: 2 additions & 1 deletion shared/lib/names.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ module.exports = {
componentNameToMacroName,
packageResolveToPath,
packageTypeToPath,
packageNameToPath
packageNameToPath,
kebabCaseToCamelCase
}

/**
Expand Down

0 comments on commit 1c9f255

Please sign in to comment.