Skip to content

Commit

Permalink
Add mixin to automatically detect capitalized HTML attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
TimvdLippe committed Feb 21, 2018
1 parent 821f335 commit 37fd5ff
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 1 deletion.
17 changes: 16 additions & 1 deletion externs/closure-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -1374,4 +1374,19 @@ Polymer_ArraySelectorMixin.prototype.select = function(item){};
* @param {number} idx Index from `items` array to select
* @return {void}
*/
Polymer_ArraySelectorMixin.prototype.selectIndex = function(idx){};
Polymer_ArraySelectorMixin.prototype.selectIndex = function(idx){};
/**
* @interface
* @extends {Polymer_PropertyEffects}
*/
function Polymer_AttributeCapitalization(){}
/**
* @override
* @param {Node} node Node to parse
* @param {TemplateInfo} templateInfo Template metadata for current template
* @param {NodeInfo} nodeInfo Node metadata for current template node
* @param {*} name
* @param {*} value
* @return {boolean}
*/
Polymer_AttributeCapitalization._parseTemplateNodeAttribute = function(node, templateInfo, nodeInfo, name, value){};
80 changes: 80 additions & 0 deletions lib/utils/attribute-capitalization-mixin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="boot.html">
<link rel="import" href="mixin.html">
<link rel="import" href="../mixins/property-effects.html">

<script>
(function() {

'use strict';

const regex = /[A-Z]/;

/**
* Mixin that uses an heuristic to determine the capitalization of HTML
* attributes. By default, all attributes are lowercased. However, some
* native attributes have capitalization. `Element.attributes` only returns
* capitalized attributes if the attribute name is exactly equal to the attribute.
* In other words, `viewBox$` will be lowercased to `viewbox$`. Therefore, if
* an attribute name still has capitaliation, we use an attribute effect to
* update the bindings.
*
* @mixinFunction
* @polymer
* @appliesMixin Polymer.PropertyEffects
* @memberof Polymer
* @summary Class mixin that uses an heuristic to determine the capitalization
* of HTML attributes.
*/
Polymer.AttributeCapitalization = Polymer.dedupingMixin(superClass => {

/**
* @constructor
* @extends {superClass}
* @implements {Polymer_PropertyEffects}
* @unrestricted
*/
const base = Polymer.PropertyEffects(superClass);

/**
* @polymer
* @mixinClass
* @implements {Polymer_PropertyEffects}
* @extends {propertyEffectsBase}
* @unrestricted
*/
class AttributeCapitalization extends base {
/**
* Overrides default `PropertyEffects` implementation to automatically
* detect capitalized attributes.
*
* @override
* @param {Node} node Node to parse
* @param {TemplateInfo} templateInfo Template metadata for current template
* @param {NodeInfo} nodeInfo Node metadata for current template node
* @return {boolean} `true` if the visited node added node-specific
* metadata to `nodeInfo`
* @protected
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
*/
static _parseTemplateNodeAttribute(node, templateInfo, nodeInfo, name, value) {
if (regex.test(name)) {
node.removeAttribute(name);
name = name + '$';
}
return super._parseTemplateNodeAttribute(node, templateInfo, nodeInfo, name, value);
}
}

return AttributeCapitalization;
});
})();
</script>
58 changes: 58 additions & 0 deletions test/unit/attribute-capitalization.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!doctype html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta charset="utf-8">
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer.html">
<link rel="import" href="../../lib/utils/attribute-capitalization-mixin.html">
</head>
<body>

<dom-module id="svg-element">
<template>
<svg id="svg" viewBox="[[value]]"></svg>
</template>
<script>
class SVGElement extends Polymer.AttributeCapitalization(Polymer.Element) {
static get is() { return 'svg-element'; }
static get properties() {
return {
value: {
type: String,
value: '0 0 50 50'
}
};
}
}
customElements.define(SVGElement.is, SVGElement);
</script>
</dom-module>

<script>
suite('automated attribute capitalization detection', function() {
let el;

setup(function() {
el = document.createElement('svg-element');
document.body.appendChild(el);
});

teardown(function() {
document.body.removeChild(el);
});

test('can handle capitalized HTML attribute', function() {
assert.equal(el.$.svg.getAttribute('viewBox'), el.value);
});
});
</script>
47 changes: 47 additions & 0 deletions types/lib/utils/attribute-capitalization-mixin.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* DO NOT EDIT
*
* This file was automatically generated by
* https://github.com/Polymer/gen-typescript-declarations
*
* To modify these typings, edit the source file(s):
* lib/utils/attribute-capitalization-mixin.html
*/

/// <reference path="boot.d.ts" />
/// <reference path="mixin.d.ts" />
/// <reference path="../mixins/property-effects.d.ts" />

declare namespace Polymer {


/**
* Mixin that uses an heuristic to determine the capitalization of HTML
* attributes. By default, all attributes are lowercased. However, some
* native attributes have capitalization. `Element.attributes` only returns
* capitalized attributes if the attribute name is exactly equal to the attribute.
* In other words, `viewBox$` will be lowercased to `viewbox$`. Therefore, if
* an attribute name still has capitaliation, we use an attribute effect to
* update the bindings.
*/
function AttributeCapitalization<T extends new (...args: any[]) => {}>(base: T): T & AttributeCapitalizationConstructor & Polymer.PropertyEffectsConstructor & Polymer.TemplateStampConstructor & Polymer.PropertyAccessorsConstructor & Polymer.PropertiesChangedConstructor;

interface AttributeCapitalizationConstructor {
new(...args: any[]): AttributeCapitalization;

/**
* Overrides default `PropertyEffects` implementation to automatically
* detect capitalized attributes.
*
* @param node Node to parse
* @param templateInfo Template metadata for current template
* @param nodeInfo Node metadata for current template node
* @returns `true` if the visited node added node-specific
* metadata to `nodeInfo`
*/
_parseTemplateNodeAttribute(node: Node|null, templateInfo: TemplateInfo|null, nodeInfo: NodeInfo|null, name: any, value: any): boolean;
}

interface AttributeCapitalization {
}
}

0 comments on commit 37fd5ff

Please sign in to comment.