From 7f82124d5ade37428de5e1fc2340a17287ef5a54 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 19 Nov 2025 10:54:32 +0000 Subject: [PATCH 1/3] Adds a `umbIgnorePasswordManagers` Lit directive so that password manager / browser extensions can ignore the RTE contents. --- .../ignore-password-managers.lit-directive.ts | 23 +++++++++++++++++++ .../core/lit-element/directives/index.ts | 3 ++- .../input-tiptap/input-tiptap.element.ts | 4 ++-- 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts new file mode 100644 index 000000000000..6f63a20ce517 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts @@ -0,0 +1,23 @@ +import { directive, AsyncDirective, nothing } from '@umbraco-cms/backoffice/external/lit'; +import type { ElementPart } from '@umbraco-cms/backoffice/external/lit'; + +class UmbIgnorePasswordManagersDirective extends AsyncDirective { + #attributes = [ + { name: 'data-1p-ignore', value: '' }, + { name: 'data-bwignore', value: '' }, + { name: 'data-form-type', value: 'other' }, + { name: 'data-lpignore', value: 'true' }, + ]; + + override render() { + return nothing; + } + + override update(part: ElementPart) { + this.#attributes.forEach((attr) => { + part.element.setAttribute(attr.name, attr.value); + }); + } +} + +export const umbIgnorePasswordManagers = directive(UmbIgnorePasswordManagersDirective); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts index f6877c9c117e..6a83c8be2404 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts @@ -1,2 +1,3 @@ -export * from './focus.lit-directive.js'; export * from './destroy.lit-directive.js'; +export * from './focus.lit-directive.js'; +export * from './ignore-password-managers.lit-directive.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index 89996511511c..1409144cd0a4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -16,7 +16,7 @@ import { import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { umbIgnorePasswordManagers, UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @@ -204,7 +204,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin html`
`)} ${when(!loading, () => html`${this.#renderStyles()}${this.#renderToolbar()}`)} -
+
${when(!loading, () => this.#renderStatusbar())} `; } From c53d962531228cb962d0b2faa00ba38316d8812d Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 19 Nov 2025 11:12:39 +0000 Subject: [PATCH 2/3] Added comments for each browser extension --- .../directives/ignore-password-managers.lit-directive.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts index 6f63a20ce517..760797a37785 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts @@ -3,10 +3,10 @@ import type { ElementPart } from '@umbraco-cms/backoffice/external/lit'; class UmbIgnorePasswordManagersDirective extends AsyncDirective { #attributes = [ - { name: 'data-1p-ignore', value: '' }, - { name: 'data-bwignore', value: '' }, - { name: 'data-form-type', value: 'other' }, - { name: 'data-lpignore', value: 'true' }, + { name: 'data-1p-ignore', value: '' }, // 1Password + { name: 'data-bwignore', value: '' }, // Bitwarden + { name: 'data-form-type', value: 'other' }, // Dashlane + { name: 'data-lpignore', value: 'true' }, // LastPass ]; override render() { From 72d4550a4c0b645ead10af66cd82a711ba4aa7f9 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 20 Nov 2025 10:34:16 +0000 Subject: [PATCH 3/3] Refactored... - Adds JSDocs - changed to use `Directive` - constructor checks if the directive is being used on an element - return `noChange` from update --- .../src/external/lit/index.ts | 3 ++- .../ignore-password-managers.lit-directive.ts | 21 ++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/lit/index.ts b/src/Umbraco.Web.UI.Client/src/external/lit/index.ts index a1f349289879..5bfaa54c6e66 100644 --- a/src/Umbraco.Web.UI.Client/src/external/lit/index.ts +++ b/src/Umbraco.Web.UI.Client/src/external/lit/index.ts @@ -1,6 +1,7 @@ export * from 'lit'; export * from 'lit/decorators.js'; -export { directive, AsyncDirective, type PartInfo } from 'lit/async-directive.js'; +export { directive, AsyncDirective, Directive, PartType } from 'lit/async-directive.js'; +export type { PartInfo } from 'lit/async-directive.js'; export * from 'lit/directives/class-map.js'; export * from 'lit/directives/if-defined.js'; export * from 'lit/directives/map.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts index 760797a37785..17771984cb62 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/ignore-password-managers.lit-directive.ts @@ -1,7 +1,10 @@ -import { directive, AsyncDirective, nothing } from '@umbraco-cms/backoffice/external/lit'; -import type { ElementPart } from '@umbraco-cms/backoffice/external/lit'; +import { directive, Directive, noChange, nothing, PartType } from '@umbraco-cms/backoffice/external/lit'; +import type { ElementPart, PartInfo } from '@umbraco-cms/backoffice/external/lit'; -class UmbIgnorePasswordManagersDirective extends AsyncDirective { +/** + * @description The directive applies attributes to ignore password managers on the given element. + */ +class UmbIgnorePasswordManagersDirective extends Directive { #attributes = [ { name: 'data-1p-ignore', value: '' }, // 1Password { name: 'data-bwignore', value: '' }, // Bitwarden @@ -9,6 +12,13 @@ class UmbIgnorePasswordManagersDirective extends AsyncDirective { { name: 'data-lpignore', value: 'true' }, // LastPass ]; + constructor(partInfo: PartInfo) { + super(partInfo); + if (partInfo.type != PartType.ELEMENT) { + throw new Error('The `umbIgnorePasswordManagers` directive can only be used in element parts'); + } + } + override render() { return nothing; } @@ -17,7 +27,12 @@ class UmbIgnorePasswordManagersDirective extends AsyncDirective { this.#attributes.forEach((attr) => { part.element.setAttribute(attr.name, attr.value); }); + return noChange; } } +/** + * @description A Lit directive which applies password manager ignore attributes to an element. + * @example html`
` + */ export const umbIgnorePasswordManagers = directive(UmbIgnorePasswordManagersDirective);