Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove GOVUKFrontend prefix from GOVUKFrontendComponent #5515

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions docs/contributing/managing-change.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@ If possible, update the mixin or function to maintain the existing functionality
}
```

### Deprecating a JavaScript file being removed

Removing a JavaScript file may happen because the module is no longer needed, or has been moved to another place in the project.

Awaiting for the next breaking, the file needs to remain included in the built package, marked as deprecated.

1. To ensure the file remains in the package, add its path within `src/govuk` to the list of paths in `packages/tasks/config/deprecated-scripts.mjs`. For example:

```mjs
export const deprecatedFilesPaths = [
'govuk-frontend-component.mjs'
]
```

This will build the file individually when creating the package, as it is no longer being discovered automatically by Rollup when building `all.mjs`.

2. To mark the file as deprecated, add the following JSDoc comment at the top of the file:

```js
/**
* @deprecated - Optionally describe where the file has been moved to or why it's been removed
* @module
*/
```

## Renaming things

When renaming things, keep the old name available as an alias and mark it as deprecated, following the steps above to [make sure we remember to remove the deprecated feature](#make-sure-we-remember-to-remove-the-deprecated-feature).
Expand Down
30 changes: 18 additions & 12 deletions packages/govuk-frontend/rollup.publish.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { babel } from '@rollup/plugin-babel'
import replace from '@rollup/plugin-replace'
import { defineConfig } from 'rollup'

import { isDeprecated } from './tasks/config/deprecated-scripts.mjs'

/**
* Rollup config for npm publish
*/
Expand All @@ -28,26 +30,30 @@ export default defineConfig(({ i: input }) => ({
* ECMAScript (ES) module bundles for browser <script type="module">
* or using `import` for modern browsers and Node.js scripts
*/
{
format: 'es',
isDeprecated(input)
? null
: {
format: 'es',

// Bundled modules
preserveModules: false
},
// Bundled modules
preserveModules: false
},

/**
* Universal Module Definition (UMD) bundle for browser <script>
* `window` globals and compatibility with CommonJS and AMD `require()`
*/
{
format: 'umd',
isDeprecated(input)
? null
: {
format: 'umd',

// Bundled modules
preserveModules: false,
// Bundled modules
preserveModules: false,

// Export via `window.GOVUKFrontend.${exportName}`
name: 'GOVUKFrontend'
}
// Export via `window.GOVUKFrontend.${exportName}`
name: 'GOVUKFrontend'
}
],

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/govuk-frontend/src/govuk/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export { SkipLink } from './components/skip-link/skip-link.mjs'
export { Tabs } from './components/tabs/tabs.mjs'
export { initAll, createAll } from './init.mjs'
export { isSupported } from './common/index.mjs'
export { GOVUKFrontendComponent as Component } from './govuk-frontend-component.mjs'
export { Component } from './component.mjs'
export { ConfigurableComponent } from './common/configuration.mjs'

/**
Expand Down
8 changes: 4 additions & 4 deletions packages/govuk-frontend/src/govuk/common/configuration.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component } from '../component.mjs'
import { ConfigError } from '../errors/index.mjs'
import { GOVUKFrontendComponent } from '../govuk-frontend-component.mjs'

import { isObject, formatErrorMessage } from './index.mjs'

Expand All @@ -13,9 +13,9 @@ export const configOverride = Symbol.for('configOverride')
* @virtual
* @template {ObjectNested} [ConfigurationType={}]
* @template {Element & { dataset: DOMStringMap }} [RootElementType=HTMLElement]
* @augments GOVUKFrontendComponent<RootElementType>
* @augments Component<RootElementType>
*/
export class ConfigurableComponent extends GOVUKFrontendComponent {
export class ConfigurableComponent extends Component {
/**
* configOverride
*
Expand Down Expand Up @@ -354,5 +354,5 @@ export function extractConfigByNamespace(schema, dataset, namespace) {

/**
* @template {ObjectNested} [ConfigurationType={}]
* @typedef {typeof GOVUKFrontendComponent & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
* @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
*/
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component } from './component.mjs'
import { SupportError } from './errors/index.mjs'
import { GOVUKFrontendComponent } from './govuk-frontend-component.mjs'

describe('GOVUKFrontendComponent', () => {
describe('Component', () => {
describe('checkSupport()', () => {
beforeEach(() => {
// Jest does not tidy the JSDOM document between tests
Expand All @@ -10,7 +10,7 @@ describe('GOVUKFrontendComponent', () => {
})

describe('default implementation', () => {
class ServiceComponent extends GOVUKFrontendComponent {
class ServiceComponent extends Component {
static moduleName = 'app-service-component'
}

Expand All @@ -27,7 +27,7 @@ describe('GOVUKFrontendComponent', () => {

describe('when overriden', () => {
it('Allows child classes to define their own condition for support', () => {
class ServiceComponent extends GOVUKFrontendComponent {
class ServiceComponent extends Component {
static moduleName = 'app-service-component'

static checkSupport() {
Expand Down
113 changes: 113 additions & 0 deletions packages/govuk-frontend/src/govuk/component.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { isInitialised, isSupported } from './common/index.mjs'
import { ElementError, InitError, SupportError } from './errors/index.mjs'

/**
* Base Component class
*
* Centralises the behaviours shared by our components
*
* @virtual
* @template {Element} [RootElementType=HTMLElement]
*/
export class Component {
/**
* @type {typeof Element}
*/
static elementType = HTMLElement

// allows Typescript user to work around the lack of types
// in GOVUKFrontend package, Typescript is not aware of $root
// in components that extend GOVUKFrontendComponent
/**
* Returns the root element of the component
*
* @protected
* @returns {RootElementType} - the root element of component
*/
get $root() {
return this._$root
}

/**
* @protected
* @type {RootElementType}
*/
_$root

/**
* Constructs a new component, validating that GOV.UK Frontend is supported
*
* @internal
* @param {Element | null} [$root] - HTML element to use for component
*/
constructor($root) {
const childConstructor = /** @type {ChildClassConstructor} */ (
this.constructor
)

// TypeScript does not enforce that inheriting classes will define a `moduleName`
// (even if we add a `@virtual` `static moduleName` property to this class).
// While we trust users to do this correctly, we do a little check to provide them
// a helpful error message.
//
// After this, we'll be sure that `childConstructor` has a `moduleName`
// as expected of the `ChildClassConstructor` we've cast `this.constructor` to.
if (typeof childConstructor.moduleName !== 'string') {
throw new InitError(`\`moduleName\` not defined in component`)
}

if (!($root instanceof childConstructor.elementType)) {
throw new ElementError({
element: $root,
component: childConstructor,
identifier: 'Root element (`$root`)',
expectedType: childConstructor.elementType.name
})
} else {
this._$root = /** @type {RootElementType} */ ($root)
}

childConstructor.checkSupport()

this.checkInitialised()

const moduleName = childConstructor.moduleName

this.$root.setAttribute(`data-${moduleName}-init`, '')
}

/**
* Validates whether component is already initialised
*
* @private
* @throws {InitError} when component is already initialised
*/
checkInitialised() {
const constructor = /** @type {ChildClassConstructor} */ (this.constructor)
const moduleName = constructor.moduleName

if (moduleName && isInitialised(this.$root, moduleName)) {
throw new InitError(constructor)
}
}

/**
* Validates whether components are supported
*
* @throws {SupportError} when the components are not supported
*/
static checkSupport() {
if (!isSupported()) {
throw new SupportError()
}
}
}

/**
* @typedef ChildClass
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
*/

/**
* @typedef {typeof Component & ChildClass} ChildClassConstructor
*/
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Component } from '../../component.mjs'
import { ElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Checkboxes component
*
* @preserve
*/
export class Checkboxes extends GOVUKFrontendComponent {
export class Checkboxes extends Component {
/** @private */
$inputs

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getBreakpoint } from '../../common/index.mjs'
import { Component } from '../../component.mjs'
import { ElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Header component
*
* @preserve
*/
export class Header extends GOVUKFrontendComponent {
export class Header extends Component {
/** @private */
$menuButton

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Component } from '../../component.mjs'
import { ElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Radios component
*
* @preserve
*/
export class Radios extends GOVUKFrontendComponent {
export class Radios extends Component {
/** @private */
$inputs

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getBreakpoint } from '../../common/index.mjs'
import { Component } from '../../component.mjs'
import { ElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Service Navigation component
*
* @preserve
*/
export class ServiceNavigation extends GOVUKFrontendComponent {
export class ServiceNavigation extends Component {
/** @private */
$menuButton

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { getFragmentFromUrl, setFocus } from '../../common/index.mjs'
import { Component } from '../../component.mjs'
import { ElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Skip link component
*
* @preserve
* @augments GOVUKFrontendComponent<HTMLAnchorElement>
* @augments Component<HTMLAnchorElement>
*/
export class SkipLink extends GOVUKFrontendComponent {
export class SkipLink extends Component {
static elementType = HTMLAnchorElement

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/govuk-frontend/src/govuk/components/tabs/tabs.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getBreakpoint, getFragmentFromUrl } from '../../common/index.mjs'
import { Component } from '../../component.mjs'
import { ElementError } from '../../errors/index.mjs'
import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'

/**
* Tabs component
*
* @preserve
*/
export class Tabs extends GOVUKFrontendComponent {
export class Tabs extends Component {
/** @private */
$tabs

Expand Down
Loading