From 6559e53d878afbe738db7d917f105501cf3d0765 Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Wed, 7 Sep 2022 10:30:10 +0100 Subject: [PATCH 1/2] Add deprecatedDataPrefixedAttrs decorator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows classes to opt-in to old-style `data-` prefixed attr serialised names. Co-authored-by: Kristján Oddsson --- src/attrable.ts | 24 ++++++++++++++++++++---- src/index.ts | 2 +- test/attrable.ts | 29 ++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/attrable.ts b/src/attrable.ts index ba8637b3..ac833f21 100644 --- a/src/attrable.ts +++ b/src/attrable.ts @@ -6,9 +6,11 @@ import {createMark} from './mark.js' import {createAbility} from './ability.js' const attrChangedCallback = Symbol() +const serializeAttributeName = Symbol() export interface Attrable { [key: PropertyKey]: unknown + [serializeAttributeName](name: PropertyKey): string [attrChangedCallback](changed: Map): void } @@ -16,6 +18,15 @@ export interface AttrableClass { new (): Attrable } +export const deprecatedDataPrefixedAttrs = createAbility( + (Class: T): T => + class extends controllable(Class) { + [serializeAttributeName](name: PropertyKey) { + return `data-${dasherize(name)}` + } + } +) + const Identity = (v: unknown) => v let setFromMutation = false const attrs = new WeakMap>() @@ -47,7 +58,7 @@ const [attr, getAttr, initializeAttrs] = createMark( initialValue = access.value } let value = initialValue - const attributeName = dasherize(name) + const attributeName = instance[serializeAttributeName](name) const setCallback = (kind === 'method' ? access.value : access.set) || Identity const getCallback = access.get || (() => value) if (!attrs.get(instance)) attrs.set(instance, new Map()) @@ -97,16 +108,21 @@ export const attrable = createAbility( constructor() { super() initializeAttrs(this) - observer.observe(this, {attributeFilter: Array.from(getAttr(this)).map(dasherize)}) + const attributeFilter = Array.from(getAttr(this)).map(name => this[serializeAttributeName](name)) + observer.observe(this, {attributeFilter}) + } + + [serializeAttributeName](name: PropertyKey) { + return dasherize(name) } [attrChangedCallback](changed: Map) { if (!this.isConnected) return for (const [name, value] of changed) { if (typeof value === 'boolean') { - this.toggleAttribute(dasherize(name), value) + this.toggleAttribute(this[serializeAttributeName](name), value) } else { - this.setAttribute(dasherize(name), String(value)) + this.setAttribute(this[serializeAttributeName](name), String(value)) } } } diff --git a/src/index.ts b/src/index.ts index 1c3f12ae..3c4288ee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,7 +15,7 @@ export { targetsChangedCallback, targetable } from './targetable.js' -export {attr, getAttr, attrable, attrChangedCallback} from './attrable.js' +export {attr, getAttr, attrable, attrChangedCallback, deprecatedDataPrefixedAttrs} from './attrable.js' export {lazyDefine} from './lazy-define.js' export type {CustomElement, CustomElementClass} from './custom-element.js' diff --git a/test/attrable.ts b/test/attrable.ts index 1a497ccc..d985ef71 100644 --- a/test/attrable.ts +++ b/test/attrable.ts @@ -1,5 +1,5 @@ import {expect, fixture, html} from '@open-wc/testing' -import {attr, attrable} from '../src/attrable.js' +import {attr, attrable, deprecatedDataPrefixedAttrs} from '../src/attrable.js' describe('Attrable', () => { { @@ -295,4 +295,31 @@ describe('Attrable', () => { expect(instance.getAttributeNames()).to.include('clip-x') }) }) + + describe('deprecated naming', () => { + @deprecatedDataPrefixedAttrs + @attrable + class DeprecatedNamingAttrTest extends HTMLElement { + @attr fooBarBazBing = 'a' + @attr URLBar = 'b' + @attr ClipX = 'c' + } + window.customElements.define('deprecated-naming-attr-test', DeprecatedNamingAttrTest) + + let instance: DeprecatedNamingAttrTest + beforeEach(async () => { + instance = await fixture(html``) + }) + + it('prefixes all attrs with data-', async () => { + expect(instance.fooBarBazBing).to.equal('a') + instance.fooBarBazBing = 'bar' + instance.URLBar = 'bar' + instance.ClipX = 'bar' + await Promise.resolve() + expect(instance.getAttributeNames()).to.include('data-foo-bar-baz-bing') + expect(instance.getAttributeNames()).to.include('data-url-bar') + expect(instance.getAttributeNames()).to.include('data-clip-x') + }) + }) }) From 502f655bdb31129e23f5af8c4237e9bed39dc29a Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Wed, 7 Sep 2022 14:55:54 +0100 Subject: [PATCH 2/2] 3kb! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b487ad71..2a5c62ff 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ { "path": "lib/index.js", "import": "{controller, attr, target, targets}", - "limit": "2.5kb" + "limit": "3.0kb" }, { "path": "lib/abilities.js",