Skip to content

Commit

Permalink
Merge pull request #281 from github/add-deprecated-data-prefixed-attr…
Browse files Browse the repository at this point in the history
…s-decorator

Add deprecatedDataPrefixedAttrs decorator
  • Loading branch information
keithamus authored Sep 22, 2022
2 parents a501418 + 502f655 commit c220489
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
{
"path": "lib/index.js",
"import": "{controller, attr, target, targets}",
"limit": "2.5kb"
"limit": "3.0kb"
},
{
"path": "lib/abilities.js",
Expand Down
24 changes: 20 additions & 4 deletions src/attrable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,27 @@ 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<PropertyKey, unknown>): void
}

export interface AttrableClass {
new (): Attrable
}

export const deprecatedDataPrefixedAttrs = createAbility(
<T extends CustomElementClass>(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<Element, Map<string, PropertyKey>>()
Expand Down Expand Up @@ -47,7 +58,7 @@ const [attr, getAttr, initializeAttrs] = createMark<Element & Attrable>(
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())
Expand Down Expand Up @@ -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<PropertyKey, unknown>) {
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))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
29 changes: 28 additions & 1 deletion test/attrable.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
{
Expand Down Expand Up @@ -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`<deprecated-naming-attr-test />`)
})

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')
})
})
})

0 comments on commit c220489

Please sign in to comment.