Skip to content

Commit c220489

Browse files
authored
Merge pull request #281 from github/add-deprecated-data-prefixed-attrs-decorator
Add deprecatedDataPrefixedAttrs decorator
2 parents a501418 + 502f655 commit c220489

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
{
5555
"path": "lib/index.js",
5656
"import": "{controller, attr, target, targets}",
57-
"limit": "2.5kb"
57+
"limit": "3.0kb"
5858
},
5959
{
6060
"path": "lib/abilities.js",

src/attrable.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,27 @@ import {createMark} from './mark.js'
66
import {createAbility} from './ability.js'
77

88
const attrChangedCallback = Symbol()
9+
const serializeAttributeName = Symbol()
910

1011
export interface Attrable {
1112
[key: PropertyKey]: unknown
13+
[serializeAttributeName](name: PropertyKey): string
1214
[attrChangedCallback](changed: Map<PropertyKey, unknown>): void
1315
}
1416

1517
export interface AttrableClass {
1618
new (): Attrable
1719
}
1820

21+
export const deprecatedDataPrefixedAttrs = createAbility(
22+
<T extends CustomElementClass>(Class: T): T =>
23+
class extends controllable(Class) {
24+
[serializeAttributeName](name: PropertyKey) {
25+
return `data-${dasherize(name)}`
26+
}
27+
}
28+
)
29+
1930
const Identity = (v: unknown) => v
2031
let setFromMutation = false
2132
const attrs = new WeakMap<Element, Map<string, PropertyKey>>()
@@ -47,7 +58,7 @@ const [attr, getAttr, initializeAttrs] = createMark<Element & Attrable>(
4758
initialValue = access.value
4859
}
4960
let value = initialValue
50-
const attributeName = dasherize(name)
61+
const attributeName = instance[serializeAttributeName](name)
5162
const setCallback = (kind === 'method' ? access.value : access.set) || Identity
5263
const getCallback = access.get || (() => value)
5364
if (!attrs.get(instance)) attrs.set(instance, new Map())
@@ -97,16 +108,21 @@ export const attrable = createAbility(
97108
constructor() {
98109
super()
99110
initializeAttrs(this)
100-
observer.observe(this, {attributeFilter: Array.from(getAttr(this)).map(dasherize)})
111+
const attributeFilter = Array.from(getAttr(this)).map(name => this[serializeAttributeName](name))
112+
observer.observe(this, {attributeFilter})
113+
}
114+
115+
[serializeAttributeName](name: PropertyKey) {
116+
return dasherize(name)
101117
}
102118

103119
[attrChangedCallback](changed: Map<PropertyKey, unknown>) {
104120
if (!this.isConnected) return
105121
for (const [name, value] of changed) {
106122
if (typeof value === 'boolean') {
107-
this.toggleAttribute(dasherize(name), value)
123+
this.toggleAttribute(this[serializeAttributeName](name), value)
108124
} else {
109-
this.setAttribute(dasherize(name), String(value))
125+
this.setAttribute(this[serializeAttributeName](name), String(value))
110126
}
111127
}
112128
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export {
1515
targetsChangedCallback,
1616
targetable
1717
} from './targetable.js'
18-
export {attr, getAttr, attrable, attrChangedCallback} from './attrable.js'
18+
export {attr, getAttr, attrable, attrChangedCallback, deprecatedDataPrefixedAttrs} from './attrable.js'
1919
export {lazyDefine} from './lazy-define.js'
2020

2121
export type {CustomElement, CustomElementClass} from './custom-element.js'

test/attrable.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {expect, fixture, html} from '@open-wc/testing'
2-
import {attr, attrable} from '../src/attrable.js'
2+
import {attr, attrable, deprecatedDataPrefixedAttrs} from '../src/attrable.js'
33

44
describe('Attrable', () => {
55
{
@@ -295,4 +295,31 @@ describe('Attrable', () => {
295295
expect(instance.getAttributeNames()).to.include('clip-x')
296296
})
297297
})
298+
299+
describe('deprecated naming', () => {
300+
@deprecatedDataPrefixedAttrs
301+
@attrable
302+
class DeprecatedNamingAttrTest extends HTMLElement {
303+
@attr fooBarBazBing = 'a'
304+
@attr URLBar = 'b'
305+
@attr ClipX = 'c'
306+
}
307+
window.customElements.define('deprecated-naming-attr-test', DeprecatedNamingAttrTest)
308+
309+
let instance: DeprecatedNamingAttrTest
310+
beforeEach(async () => {
311+
instance = await fixture(html`<deprecated-naming-attr-test />`)
312+
})
313+
314+
it('prefixes all attrs with data-', async () => {
315+
expect(instance.fooBarBazBing).to.equal('a')
316+
instance.fooBarBazBing = 'bar'
317+
instance.URLBar = 'bar'
318+
instance.ClipX = 'bar'
319+
await Promise.resolve()
320+
expect(instance.getAttributeNames()).to.include('data-foo-bar-baz-bing')
321+
expect(instance.getAttributeNames()).to.include('data-url-bar')
322+
expect(instance.getAttributeNames()).to.include('data-clip-x')
323+
})
324+
})
298325
})

0 commit comments

Comments
 (0)