This commit is contained in:
Andy Butland
2025-07-08 15:53:52 +02:00
9 changed files with 30 additions and 34 deletions

View File

@@ -23,13 +23,14 @@ module.exports = {
if (isCustomElementDecorator) { if (isCustomElementDecorator) {
const elementName = node.arguments[0].value; const elementName = node.arguments[0].value;
// check if the element name starts with 'umb-', or 'test-', to be allow tests to have custom elements: // check if the element name starts with 'umb-', 'ufm-', or 'test-', to be allow tests to have custom elements:
const isElementNameValid = elementName.startsWith('umb-') ? true : elementName.startsWith('test-'); const prefixes = ['umb-', 'ufm-', 'test-'];
const isElementNameValid = prefixes.some((prefix) => elementName.startsWith(prefix));
if (!isElementNameValid) { if (!isElementNameValid) {
context.report({ context.report({
node, node,
message: 'Custom Element name should start with "umb-".', message: 'Custom Element name should start with "umb-" or "ufm-".',
// There is no fixer on purpose because it's not safe to automatically rename the element name. // There is no fixer on purpose because it's not safe to automatically rename the element name.
// Renaming should be done manually with consideration of potential impacts. // Renaming should be done manually with consideration of potential impacts.
}); });

View File

@@ -11,7 +11,6 @@ export class UmbCustomUfmComponent extends UmbUfmComponentBase {
} }
} }
// eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name
@customElement('ufm-custom-component') @customElement('ufm-custom-component')
export class UmbCustomUfmComponentElement extends UmbLitElement { export class UmbCustomUfmComponentElement extends UmbLitElement {
@property() @property()

View File

@@ -6,9 +6,7 @@ import { UmbId } from '@umbraco-cms/backoffice/id';
import { UmbMediaItemRepository, UMB_MEDIA_ENTITY_TYPE } from '@umbraco-cms/backoffice/media'; import { UmbMediaItemRepository, UMB_MEDIA_ENTITY_TYPE } from '@umbraco-cms/backoffice/media';
import { UmbMemberItemRepository, UMB_MEMBER_ENTITY_TYPE } from '@umbraco-cms/backoffice/member'; import { UmbMemberItemRepository, UMB_MEMBER_ENTITY_TYPE } from '@umbraco-cms/backoffice/member';
const elementName = 'ufm-content-name'; @customElement('ufm-content-name')
@customElement(elementName)
export class UmbUfmContentNameElement extends UmbUfmElementBase { export class UmbUfmContentNameElement extends UmbUfmElementBase {
@property() @property()
alias?: string; alias?: string;
@@ -95,6 +93,6 @@ export { UmbUfmContentNameElement as element };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
[elementName]: UmbUfmContentNameElement; 'ufm-content-name': UmbUfmContentNameElement;
} }
} }

View File

@@ -2,9 +2,7 @@ import { UMB_UFM_RENDER_CONTEXT } from '../ufm-render/ufm-render.context.js';
import { UmbUfmElementBase } from '../ufm-element-base.js'; import { UmbUfmElementBase } from '../ufm-element-base.js';
import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { customElement, property } from '@umbraco-cms/backoffice/external/lit';
const elementName = 'ufm-label-value'; @customElement('ufm-label-value')
@customElement(elementName)
export class UmbUfmLabelValueElement extends UmbUfmElementBase { export class UmbUfmLabelValueElement extends UmbUfmElementBase {
@property() @property()
alias?: string; alias?: string;
@@ -32,6 +30,6 @@ export { UmbUfmLabelValueElement as element };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
[elementName]: UmbUfmLabelValueElement; 'ufm-label-value': UmbUfmLabelValueElement;
} }
} }

View File

@@ -5,9 +5,7 @@ import { UmbDocumentItemRepository, UMB_DOCUMENT_ENTITY_TYPE } from '@umbraco-cm
import { UmbMediaItemRepository, UMB_MEDIA_ENTITY_TYPE } from '@umbraco-cms/backoffice/media'; import { UmbMediaItemRepository, UMB_MEDIA_ENTITY_TYPE } from '@umbraco-cms/backoffice/media';
import type { UmbLinkPickerLink } from '@umbraco-cms/backoffice/multi-url-picker'; import type { UmbLinkPickerLink } from '@umbraco-cms/backoffice/multi-url-picker';
const elementName = 'ufm-link'; @customElement('ufm-link')
@customElement(elementName)
export class UmbUfmLinkElement extends UmbUfmElementBase { export class UmbUfmLinkElement extends UmbUfmElementBase {
@property() @property()
alias?: string; alias?: string;
@@ -79,6 +77,6 @@ export { UmbUfmLinkElement as element };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
[elementName]: UmbUfmLinkElement; 'ufm-link': UmbUfmLinkElement;
} }
} }

View File

@@ -1,9 +1,7 @@
import { UmbUfmElementBase } from '../ufm-element-base.js'; import { UmbUfmElementBase } from '../ufm-element-base.js';
import { customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { customElement, property } from '@umbraco-cms/backoffice/external/lit';
const elementName = 'ufm-localize'; @customElement('ufm-localize')
@customElement(elementName)
export class UmbUfmLocalizeElement extends UmbUfmElementBase { export class UmbUfmLocalizeElement extends UmbUfmElementBase {
@property() @property()
public set alias(value: string | undefined) { public set alias(value: string | undefined) {
@@ -21,6 +19,6 @@ export { UmbUfmLocalizeElement as element };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
[elementName]: UmbUfmLocalizeElement; 'ufm-localize': UmbUfmLocalizeElement;
} }
} }

View File

@@ -1,10 +1,12 @@
import { UMB_UFM_CONTEXT } from '../contexts/ufm.context.js'; import { UMB_UFM_CONTEXT } from '../contexts/ufm.context.js';
import { nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; import { property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
export abstract class UmbUfmElementBase extends UmbLitElement { export abstract class UmbUfmElementBase extends UmbLitElement {
#filterFuncArgs?: Array<{ alias: string; args: Array<string> }>; #filterFuncArgs?: Array<{ alias: string; args: Array<string> }>;
#ufmContext?: typeof UMB_UFM_CONTEXT.TYPE;
@property() @property()
public set filters(value: string | undefined) { public set filters(value: string | undefined) {
this.#filters = value; this.#filters = value;
@@ -25,8 +27,6 @@ export abstract class UmbUfmElementBase extends UmbLitElement {
@state() @state()
value?: unknown; value?: unknown;
#ufmContext?: typeof UMB_UFM_CONTEXT.TYPE;
constructor() { constructor() {
super(); super();
@@ -36,16 +36,23 @@ export abstract class UmbUfmElementBase extends UmbLitElement {
} }
override render() { override render() {
if (!this.#ufmContext) return nothing;
let values = Array.isArray(this.value) ? this.value : [this.value]; let values = Array.isArray(this.value) ? this.value : [this.value];
if (this.#filterFuncArgs) { if (this.#filterFuncArgs) {
const missing = new Set<string>();
for (const item of this.#filterFuncArgs) { for (const item of this.#filterFuncArgs) {
const filter = this.#ufmContext.getFilterByAlias(item.alias); const filter = this.#ufmContext?.getFilterByAlias(item.alias);
if (filter) { if (filter) {
values = values.map((value) => filter(value, ...item.args)); values = values.map((value) => filter(value, ...item.args));
} else {
missing.add(item.alias);
} }
} }
if (missing.size > 0) {
console.warn(`UFM filters with aliases "${Array.from(missing).join('", "')}" were not found.`);
}
} }
return values.join(', '); return values.join(', ');

View File

@@ -4,9 +4,7 @@ import { css, customElement, nothing, property, unsafeHTML, until } from '@umbra
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
const elementName = 'umb-ufm-render'; @customElement('umb-ufm-render')
@customElement(elementName)
export class UmbUfmRenderElement extends UmbLitElement { export class UmbUfmRenderElement extends UmbLitElement {
#context = new UmbUfmRenderContext(this); #context = new UmbUfmRenderContext(this);
@@ -16,7 +14,8 @@ export class UmbUfmRenderElement extends UmbLitElement {
@property() @property()
markdown?: string; markdown?: string;
// No reactive property declaration cause its causing a re-render that is not needed. This just works as a shortcut to set the values on the context. [NL] // No reactive property declaration because it's causing a re-render that is not needed.
// This just works as a shortcut to set the values on the context. [NL]
public set value(value: string | unknown | undefined) { public set value(value: string | unknown | undefined) {
this.#context.setValue(value); this.#context.setValue(value);
} }
@@ -75,6 +74,6 @@ export { UmbUfmRenderElement as element };
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
[elementName]: UmbUfmRenderElement; 'umb-ufm-render': UmbUfmRenderElement;
} }
} }

View File

@@ -32,9 +32,7 @@ export const UmbMarked = new Marked({
gfm: true, gfm: true,
breaks: true, breaks: true,
hooks: { hooks: {
postprocess: (markup) => { postprocess: (markup) => UmbDomPurify.sanitize(markup, UmbDomPurifyConfig),
return UmbDomPurify.sanitize(markup, UmbDomPurifyConfig) as string;
},
}, },
}); });