├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── lib └── index.js ├── package.json └── test ├── fixtures ├── noop │ ├── options.json │ ├── plain-class-extend │ │ ├── actual.js │ │ └── expected.js │ └── plain-class │ │ ├── actual.js │ │ └── expected.js └── reflect │ ├── app-drawer │ ├── actual.js │ └── expected.js │ ├── custom-progress-bar │ ├── actual.js │ ├── expected.js │ └── index.html │ ├── mocha │ ├── actual.html │ ├── actual.js │ ├── expected.html │ └── expected.js │ ├── multiple │ ├── actual.js │ └── expected.js │ └── options.json └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | - "6" 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 GitHub, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-transform-custom-element-classes 2 | 3 | Compile Custom Element classes that extend `HTMLElement` for ES5 environments. 4 | 5 | ### Problem 6 | 7 | Custom Elements were designed for native ES6 classes that can extend host objects in ways prototypical inheritance can not. Using the Babel `transform-es2015-classes` transform will not work as is. You'll likely see a runtime error like `"Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function."` when attempting to extend `HTMLElement` in a Babel transpiled class. 8 | 9 | ### Solution 10 | 11 | A workaround is to use `Reflect.construct` to build a new `HTMLElement` instance expected by the constructor. This transform wraps any ES6 classes extending `HTMLElement` with an intermediary class that shims this behavior. 12 | 13 | ## Compatibility 14 | 15 | ![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![IE](https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png) | ![Opera](https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Safari](https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png) 16 | --- | --- | --- | --- | --- | 17 | Latest ✅ | ❌ | ❌ | ❌ | 10.1+ TP ✅ | 18 | 19 | ### With [Custom Elements V1 polyfill](https://github.com/webcomponents/custom-elements) 20 | 21 | ![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![IE](https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png) | ![Opera](https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Safari](https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png) 22 | --- | --- | --- | --- | --- | 23 | Latest ✅ | Latest ✅ | 11 ✅ | Latest ✅ | 9.1+ ✅ | 24 | 25 | ## Installation 26 | 27 | ```sh 28 | $ npm install babel-plugin-transform-custom-element-classes 29 | ``` 30 | 31 | ## Usage 32 | 33 | ### Via `.babelrc` 34 | 35 | **.babelrc** 36 | 37 | ```js 38 | // include before transform-es2015-classes 39 | { 40 | "plugins": [ 41 | "transform-custom-element-classes", 42 | "transform-es2015-classes" 43 | ] 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const babelTemplate = require('babel-template') 2 | 3 | const buildHelper = babelTemplate(` 4 | function CLASS() { return Reflect.construct(HTMLElement, [], this.__proto__.constructor); }; 5 | Object.setPrototypeOf(CLASS.prototype, HTMLElement.prototype); 6 | Object.setPrototypeOf(CLASS, HTMLElement); 7 | `) 8 | 9 | const helpers = new WeakMap() 10 | 11 | function programCustomElementHelper(program) { 12 | let helperClass = helpers.get(program) 13 | if (!helperClass) { 14 | helperClass = program.scope.generateUidIdentifier('CustomElement') 15 | const helper = buildHelper({CLASS: helperClass}) 16 | program.unshiftContainer('body', helper) 17 | helpers.set(program, helperClass) 18 | } 19 | return helperClass.name 20 | } 21 | 22 | module.exports = function() { 23 | return { 24 | visitor: { 25 | Class: function(path) { 26 | const superClass = path.get('superClass') 27 | const match = superClass.isIdentifier({ name: 'HTMLElement' }) 28 | if (!match) return 29 | 30 | const name = programCustomElementHelper(path.scope.getProgramParent().path) 31 | superClass.replaceWith({ type: 'Identifier', name: name }) 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-transform-custom-element-classes", 3 | "version": "0.1.0", 4 | "description": "Compile ES6 HTMLElement class extensions to ES5", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "pretest": "rm node_modules/babel-plugin-transform-custom-element-classes ; ln -fs .. node_modules/babel-plugin-transform-custom-element-classes", 8 | "test": "mocha" 9 | }, 10 | "author": "GitHub, Inc", 11 | "license": "MIT", 12 | "directories": { 13 | "test": "test" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/github/babel-plugin-transform-custom-element-classes.git" 18 | }, 19 | "keywords": [ 20 | "babel-plugin" 21 | ], 22 | "bugs": { 23 | "url": "https://github.com/github/babel-plugin-transform-custom-element-classes/issues" 24 | }, 25 | "homepage": "https://github.com/github/babel-plugin-transform-custom-element-classes#readme", 26 | "dependencies": { 27 | "babel-template": "^6.16.0" 28 | }, 29 | "devDependencies": { 30 | "babel-helper-plugin-test-runner": "^6.18.0", 31 | "babel-plugin-transform-es2015-classes": "^6.18.0", 32 | "chai": "^3.5.0", 33 | "mocha": "^3.1.2" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/fixtures/noop/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-custom-element-classes", 4 | "transform-es2015-classes" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/noop/plain-class-extend/actual.js: -------------------------------------------------------------------------------- 1 | class Foo extends Bar { 2 | } 3 | -------------------------------------------------------------------------------- /test/fixtures/noop/plain-class-extend/expected.js: -------------------------------------------------------------------------------- 1 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2 | 3 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 4 | 5 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 6 | 7 | let Foo = function (_Bar) { 8 | _inherits(Foo, _Bar); 9 | 10 | function Foo() { 11 | _classCallCheck(this, Foo); 12 | 13 | return _possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).apply(this, arguments)); 14 | } 15 | 16 | return Foo; 17 | }(Bar); 18 | -------------------------------------------------------------------------------- /test/fixtures/noop/plain-class/actual.js: -------------------------------------------------------------------------------- 1 | class Foo { 2 | } 3 | -------------------------------------------------------------------------------- /test/fixtures/noop/plain-class/expected.js: -------------------------------------------------------------------------------- 1 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2 | 3 | let Foo = function Foo() { 4 | _classCallCheck(this, Foo); 5 | }; 6 | -------------------------------------------------------------------------------- /test/fixtures/reflect/app-drawer/actual.js: -------------------------------------------------------------------------------- 1 | class AppDrawer extends HTMLElement { 2 | 3 | // A getter/setter for an open property. 4 | get open() { 5 | return this.hasAttribute('open'); 6 | } 7 | 8 | set open(val) { 9 | // Reflect the value of the open property as an HTML attribute. 10 | if (val) { 11 | this.setAttribute('open', ''); 12 | } else { 13 | this.removeAttribute('open'); 14 | } 15 | this.toggleDrawer(); 16 | } 17 | 18 | // A getter/setter for a disabled property. 19 | get disabled() { 20 | return this.hasAttribute('disabled'); 21 | } 22 | 23 | set disabled(val) { 24 | // Reflect the value of the disabled property as an HTML attribute. 25 | if (val) { 26 | this.setAttribute('disabled', ''); 27 | } else { 28 | this.removeAttribute('disabled'); 29 | } 30 | } 31 | 32 | // Can define constructor arguments if you wish. 33 | constructor() { 34 | // If you define a ctor, always call super() first! 35 | // This is specific to CE and required by the spec. 36 | super(); 37 | 38 | // Setup a click listener on itself. 39 | this.addEventListener('click', e => { 40 | // Don't toggle the drawer if it's disabled. 41 | if (this.disabled) { 42 | return; 43 | } 44 | this.toggleDrawer(); 45 | }); 46 | } 47 | 48 | toggleDrawer() { 49 | } 50 | } 51 | 52 | customElements.define('app-drawer', AppDrawer); 53 | 54 | 55 | class FancyDrawer extends AppDrawer { 56 | constructor() { 57 | super(); // always call super() first in the ctor. This also calls the extended class' ctor. 58 | } 59 | 60 | toggleDrawer() { 61 | super.toggleDrawer() 62 | } 63 | 64 | anotherMethod() { 65 | } 66 | } 67 | 68 | customElements.define('fancy-app-drawer', FancyDrawer); 69 | -------------------------------------------------------------------------------- /test/fixtures/reflect/app-drawer/expected.js: -------------------------------------------------------------------------------- 1 | var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; 2 | 3 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 4 | 5 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6 | 7 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 8 | 9 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 10 | 11 | function _CustomElement() { 12 | return Reflect.construct(HTMLElement, [], this.__proto__.constructor); 13 | } 14 | 15 | ; 16 | Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype); 17 | Object.setPrototypeOf(_CustomElement, HTMLElement); 18 | 19 | let AppDrawer = function (_CustomElement2) { 20 | _inherits(AppDrawer, _CustomElement2); 21 | 22 | _createClass(AppDrawer, [{ 23 | key: 'open', 24 | 25 | 26 | // A getter/setter for an open property. 27 | get: function () { 28 | return this.hasAttribute('open'); 29 | }, 30 | set: function (val) { 31 | // Reflect the value of the open property as an HTML attribute. 32 | if (val) { 33 | this.setAttribute('open', ''); 34 | } else { 35 | this.removeAttribute('open'); 36 | } 37 | this.toggleDrawer(); 38 | } 39 | 40 | // A getter/setter for a disabled property. 41 | 42 | }, { 43 | key: 'disabled', 44 | get: function () { 45 | return this.hasAttribute('disabled'); 46 | }, 47 | set: function (val) { 48 | // Reflect the value of the disabled property as an HTML attribute. 49 | if (val) { 50 | this.setAttribute('disabled', ''); 51 | } else { 52 | this.removeAttribute('disabled'); 53 | } 54 | } 55 | 56 | // Can define constructor arguments if you wish. 57 | 58 | }]); 59 | 60 | function AppDrawer() { 61 | _classCallCheck(this, AppDrawer); 62 | 63 | // Setup a click listener on itself. 64 | var _this = _possibleConstructorReturn(this, (AppDrawer.__proto__ || Object.getPrototypeOf(AppDrawer)).call(this)); 65 | // If you define a ctor, always call super() first! 66 | // This is specific to CE and required by the spec. 67 | 68 | 69 | _this.addEventListener('click', e => { 70 | // Don't toggle the drawer if it's disabled. 71 | if (_this.disabled) { 72 | return; 73 | } 74 | _this.toggleDrawer(); 75 | }); 76 | return _this; 77 | } 78 | 79 | _createClass(AppDrawer, [{ 80 | key: 'toggleDrawer', 81 | value: function toggleDrawer() {} 82 | }]); 83 | 84 | return AppDrawer; 85 | }(_CustomElement); 86 | 87 | customElements.define('app-drawer', AppDrawer); 88 | 89 | let FancyDrawer = function (_AppDrawer) { 90 | _inherits(FancyDrawer, _AppDrawer); 91 | 92 | function FancyDrawer() { 93 | _classCallCheck(this, FancyDrawer); 94 | 95 | return _possibleConstructorReturn(this, (FancyDrawer.__proto__ || Object.getPrototypeOf(FancyDrawer)).call(this)); // always call super() first in the ctor. This also calls the extended class' ctor. 96 | } 97 | 98 | _createClass(FancyDrawer, [{ 99 | key: 'toggleDrawer', 100 | value: function toggleDrawer() { 101 | _get(FancyDrawer.prototype.__proto__ || Object.getPrototypeOf(FancyDrawer.prototype), 'toggleDrawer', this).call(this); 102 | } 103 | }, { 104 | key: 'anotherMethod', 105 | value: function anotherMethod() {} 106 | }]); 107 | 108 | return FancyDrawer; 109 | }(AppDrawer); 110 | 111 | customElements.define('fancy-app-drawer', FancyDrawer); -------------------------------------------------------------------------------- /test/fixtures/reflect/custom-progress-bar/actual.js: -------------------------------------------------------------------------------- 1 | class CustomProgressBar extends HTMLElement { 2 | constructor() { 3 | super(); 4 | const shadowRoot = this.attachShadow({ mode: 'closed' }); 5 | shadowRoot.innerHTML = ` 6 | 13 |
14 |
15 |
0%
16 |
17 | `; 18 | this._progressElement = shadowRoot.querySelector('.progress'); 19 | this._label = shadowRoot.querySelector('.label'); 20 | this._bar = shadowRoot.querySelector('.bar'); 21 | } 22 | 23 | get progress() { 24 | return this._progressElement.getAttribute('aria-valuenow'); 25 | } 26 | set progress(newPercentage) { 27 | this._progressElement.setAttribute('aria-valuenow', newPercentage); 28 | this._label.textContent = newPercentage + '%'; 29 | this._bar.style.width = newPercentage + '%'; 30 | } 31 | }; 32 | customElements.define('custom-progress-bar', CustomProgressBar); 33 | -------------------------------------------------------------------------------- /test/fixtures/reflect/custom-progress-bar/expected.js: -------------------------------------------------------------------------------- 1 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 2 | 3 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 4 | 5 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 6 | 7 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 8 | 9 | function _CustomElement() { 10 | return Reflect.construct(HTMLElement, [], this.__proto__.constructor); 11 | } 12 | 13 | ; 14 | Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype); 15 | Object.setPrototypeOf(_CustomElement, HTMLElement); 16 | 17 | let CustomProgressBar = function (_CustomElement2) { 18 | _inherits(CustomProgressBar, _CustomElement2); 19 | 20 | function CustomProgressBar() { 21 | _classCallCheck(this, CustomProgressBar); 22 | 23 | var _this = _possibleConstructorReturn(this, (CustomProgressBar.__proto__ || Object.getPrototypeOf(CustomProgressBar)).call(this)); 24 | 25 | const shadowRoot = _this.attachShadow({ mode: 'closed' }); 26 | shadowRoot.innerHTML = ` 27 | 34 |
35 |
36 |
0%
37 |
38 | `; 39 | _this._progressElement = shadowRoot.querySelector('.progress'); 40 | _this._label = shadowRoot.querySelector('.label'); 41 | _this._bar = shadowRoot.querySelector('.bar'); 42 | return _this; 43 | } 44 | 45 | _createClass(CustomProgressBar, [{ 46 | key: 'progress', 47 | get: function () { 48 | return this._progressElement.getAttribute('aria-valuenow'); 49 | }, 50 | set: function (newPercentage) { 51 | this._progressElement.setAttribute('aria-valuenow', newPercentage); 52 | this._label.textContent = newPercentage + '%'; 53 | this._bar.style.width = newPercentage + '%'; 54 | } 55 | }]); 56 | 57 | return CustomProgressBar; 58 | }(_CustomElement); 59 | 60 | ; 61 | customElements.define('custom-progress-bar', CustomProgressBar); 62 | -------------------------------------------------------------------------------- /test/fixtures/reflect/custom-progress-bar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/fixtures/reflect/mocha/actual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mocha Tests 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/fixtures/reflect/mocha/actual.js: -------------------------------------------------------------------------------- 1 | suite("FlagIcon", function() { 2 | class FlagIcon extends HTMLElement { 3 | constructor() { 4 | super() 5 | this._constructorDidRun = true 6 | } 7 | } 8 | customElements.define("flag-icon", FlagIcon) 9 | 10 | test("createElement", function() { 11 | var icon = document.createElement("flag-icon") 12 | chai.assert(icon instanceof HTMLElement) 13 | chai.assert(icon instanceof FlagIcon) 14 | chai.assert.equal(icon.tagName, "FLAG-ICON") 15 | chai.assert.equal(icon._constructorDidRun, true) 16 | }) 17 | 18 | test("constructor", function() { 19 | var icon = new FlagIcon() 20 | chai.assert(icon instanceof HTMLElement) 21 | chai.assert(icon instanceof FlagIcon) 22 | chai.assert.equal(icon.tagName, "FLAG-ICON") 23 | chai.assert.equal(icon._constructorDidRun, true) 24 | }) 25 | 26 | test("innerHTML", function() { 27 | var div = document.createElement("div") 28 | div.innerHTML = "" 29 | var icon = div.querySelector("flag-icon") 30 | 31 | chai.assert(icon instanceof HTMLElement) 32 | chai.assert(icon instanceof FlagIcon) 33 | chai.assert.equal(icon.tagName, "FLAG-ICON") 34 | chai.assert.equal(icon._constructorDidRun, true) 35 | }) 36 | }) 37 | -------------------------------------------------------------------------------- /test/fixtures/reflect/mocha/expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mocha Tests 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/fixtures/reflect/mocha/expected.js: -------------------------------------------------------------------------------- 1 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2 | 3 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 4 | 5 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 6 | 7 | function _CustomElement() { 8 | return Reflect.construct(HTMLElement, [], this.__proto__.constructor); 9 | } 10 | 11 | ; 12 | Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype); 13 | Object.setPrototypeOf(_CustomElement, HTMLElement); 14 | suite("FlagIcon", function () { 15 | let FlagIcon = function (_CustomElement2) { 16 | _inherits(FlagIcon, _CustomElement2); 17 | 18 | function FlagIcon() { 19 | _classCallCheck(this, FlagIcon); 20 | 21 | var _this = _possibleConstructorReturn(this, (FlagIcon.__proto__ || Object.getPrototypeOf(FlagIcon)).call(this)); 22 | 23 | _this._constructorDidRun = true; 24 | return _this; 25 | } 26 | 27 | return FlagIcon; 28 | }(_CustomElement); 29 | 30 | customElements.define("flag-icon", FlagIcon); 31 | 32 | test("createElement", function () { 33 | var icon = document.createElement("flag-icon"); 34 | chai.assert(icon instanceof HTMLElement); 35 | chai.assert(icon instanceof FlagIcon); 36 | chai.assert.equal(icon.tagName, "FLAG-ICON"); 37 | chai.assert.equal(icon._constructorDidRun, true); 38 | }); 39 | 40 | test("constructor", function () { 41 | var icon = new FlagIcon(); 42 | chai.assert(icon instanceof HTMLElement); 43 | chai.assert(icon instanceof FlagIcon); 44 | chai.assert.equal(icon.tagName, "FLAG-ICON"); 45 | chai.assert.equal(icon._constructorDidRun, true); 46 | }); 47 | 48 | test("innerHTML", function () { 49 | var div = document.createElement("div"); 50 | div.innerHTML = ""; 51 | var icon = div.querySelector("flag-icon"); 52 | 53 | chai.assert(icon instanceof HTMLElement); 54 | chai.assert(icon instanceof FlagIcon); 55 | chai.assert.equal(icon.tagName, "FLAG-ICON"); 56 | chai.assert.equal(icon._constructorDidRun, true); 57 | }); 58 | }); -------------------------------------------------------------------------------- /test/fixtures/reflect/multiple/actual.js: -------------------------------------------------------------------------------- 1 | class FlagIcon extends HTMLElement { 2 | constructor() { 3 | super(); 4 | this._countryCode = null; 5 | } 6 | } 7 | 8 | customElements.define("flag-icon", FlagIcon); 9 | 10 | 11 | class TacoButton extends HTMLElement { 12 | constructor() { 13 | super(); 14 | 15 | this.addEventListener("keydown", e => { 16 | if (e.keyCode === 32 || e.keyCode === 13) { 17 | this.dispatchEvent(new MouseEvent("click", { 18 | bubbles: true, 19 | cancelable: true 20 | })); 21 | } 22 | }); 23 | 24 | this.addEventListener("click", e => { 25 | if (this.disabled) { 26 | e.preventDefault(); 27 | e.stopPropagation(); 28 | } 29 | }); 30 | 31 | this._observer = new MutationObserver(() => { 32 | this.setAttribute("aria-label", this.textContent); 33 | }); 34 | } 35 | } 36 | customElements.define("taco-button", TacoButton); 37 | -------------------------------------------------------------------------------- /test/fixtures/reflect/multiple/expected.js: -------------------------------------------------------------------------------- 1 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2 | 3 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 4 | 5 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 6 | 7 | function _CustomElement() { 8 | return Reflect.construct(HTMLElement, [], this.__proto__.constructor); 9 | } 10 | 11 | ; 12 | Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype); 13 | Object.setPrototypeOf(_CustomElement, HTMLElement); 14 | 15 | let FlagIcon = function (_CustomElement2) { 16 | _inherits(FlagIcon, _CustomElement2); 17 | 18 | function FlagIcon() { 19 | _classCallCheck(this, FlagIcon); 20 | 21 | var _this = _possibleConstructorReturn(this, (FlagIcon.__proto__ || Object.getPrototypeOf(FlagIcon)).call(this)); 22 | 23 | _this._countryCode = null; 24 | return _this; 25 | } 26 | 27 | return FlagIcon; 28 | }(_CustomElement); 29 | 30 | customElements.define("flag-icon", FlagIcon); 31 | 32 | let TacoButton = function (_CustomElement3) { 33 | _inherits(TacoButton, _CustomElement3); 34 | 35 | function TacoButton() { 36 | _classCallCheck(this, TacoButton); 37 | 38 | var _this2 = _possibleConstructorReturn(this, (TacoButton.__proto__ || Object.getPrototypeOf(TacoButton)).call(this)); 39 | 40 | _this2.addEventListener("keydown", e => { 41 | if (e.keyCode === 32 || e.keyCode === 13) { 42 | _this2.dispatchEvent(new MouseEvent("click", { 43 | bubbles: true, 44 | cancelable: true 45 | })); 46 | } 47 | }); 48 | 49 | _this2.addEventListener("click", e => { 50 | if (_this2.disabled) { 51 | e.preventDefault(); 52 | e.stopPropagation(); 53 | } 54 | }); 55 | 56 | _this2._observer = new MutationObserver(() => { 57 | _this2.setAttribute("aria-label", _this2.textContent); 58 | }); 59 | return _this2; 60 | } 61 | 62 | return TacoButton; 63 | }(_CustomElement); 64 | 65 | customElements.define("taco-button", TacoButton); 66 | -------------------------------------------------------------------------------- /test/fixtures/reflect/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-custom-element-classes", 4 | "transform-es2015-classes" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('babel-helper-plugin-test-runner')(__dirname); 2 | --------------------------------------------------------------------------------