From ed9c75a0a63b4c67ab78248b9378007810ad7998 Mon Sep 17 00:00:00 2001 From: Taylor Dawson Date: Sun, 19 Jan 2020 21:07:29 -0800 Subject: [PATCH] Add core functionality and css tweeks to embedabble: - Web3 integration - detects whether or not asset is owned by the account - Adds ability to buy the token - Adds ability to view/manage token if it is not for sale or owned - Additional dynamic content rendering logic for price and traits - Adds more component properties for increased customisation - Fixes backface blead from asset contract name - Moves from rollup to webpack for building and running dev server - Update readme with more usage details - [WIP] Adds some linting --- .eslintignore | 4 + .prettierrc | 3 + README.md | 35 +- babel.config.js | 14 +- dist/nft-card.js | 3869 +---------- dist/nft-card.js.map | 2 +- example/index.html | 22 +- package-lock.json | 15089 +++++++++++++++++++++++++++++++--------- package.json | 44 +- rollup.config.js | 40 +- src/nft-card-back.ts | 453 +- src/nft-card-front.ts | 244 +- src/nft-card.ts | 266 +- src/pill.ts | 68 +- tsconfig.json | 1 + webpack.config.js | 36 + webpack.dev.config.js | 47 + 17 files changed, 12995 insertions(+), 7242 deletions(-) create mode 100644 .eslintignore create mode 100644 .prettierrc create mode 100644 webpack.config.js create mode 100644 webpack.dev.config.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..b968eb3 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +.gitignore +/dist +.git +/example diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..480d45d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +# .prettierrc +semi: false +useTabs: false \ No newline at end of file diff --git a/README.md b/README.md index d825db6..86ec12e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,43 @@ # Embeddable NFTs Easily embed OpenSea listings in your website! +### Component inputs + +`vertical` - If this is present the card will be rendered vertically. + +`width` - The width of the embeddable. Ex. values `100%` `250px` + +`height` - The height of the embeddable. Ex. values `40vh` `300px` + +`contractAddress`\*- The token Id of the asset. + +`tokenId`\* - The token Id of the asset. + +`network` - The name of the network the asset is on `mainnet` or `rinkeby`. Defaults to `mainnet`. + +\*Required inputs + +Example: +``` + + +``` + ### Development -For developers looking to contribute or modify the code use the following commands: +For developers looking to contribute or modify the code, or view the example use the following commands: ```bash git clone https://github.com/ProjectOpenSea/embeddable_nfts.git cd embeddable_nfts npm install - npm start + npm run dev:demo ``` #### Development server -This project uses [rollup.js](https://rollupjs.org/guide/en/) for building and running a development server. Once the server starts, any changes made will trigger a rebuild after which those changes should be reflected in your browser. +This project uses webpack for building and running a development server. Once the server starts, any changes made will trigger a rebuild after which those changes should be reflected in your browser. diff --git a/babel.config.js b/babel.config.js index 2516bf6..e5d35f1 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,16 +1,16 @@ const presets = [ - "@babel/preset-typescript", + '@babel/preset-typescript', [ - "@babel/preset-env", + '@babel/preset-env', { - "targets": "last 2 Chrome version", - "modules": false + targets: 'last 2 Chrome version', + modules: false } ] ] const plugins = [ '@babel/plugin-proposal-class-properties', - ['@babel/proposal-decorators', { decoratorsBeforeExport: true } ], -]; + ['@babel/proposal-decorators', {decoratorsBeforeExport: true}] +] -module.exports = { plugins, presets }; +module.exports = {plugins, presets} diff --git a/dist/nft-card.js b/dist/nft-card.js index a3f7700..878dfc6 100644 --- a/dist/nft-card.js +++ b/dist/nft-card.js @@ -1,3161 +1,209 @@ - -(function(l, r) { if (l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (window.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.head.appendChild(r) })(window.document); -(function (exports) { - 'use strict'; - - function _toArray(arr) { - return _arrayWithHoles(arr) || _iterableToArray(arr) || _nonIterableRest(); - } - - function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; - } - - function _iterableToArray(iter) { - if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); - } - - function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - - function _toPrimitive(input, hint) { - if (typeof input !== "object" || input === null) return input; - var prim = input[Symbol.toPrimitive]; - - if (prim !== undefined) { - var res = prim.call(input, hint || "default"); - if (typeof res !== "object") return res; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - - return (hint === "string" ? String : Number)(input); - } - - function _toPropertyKey(arg) { - var key = _toPrimitive(arg, "string"); - - return typeof key === "symbol" ? key : String(key); - } - - function _decorate(decorators, factory, superClass, mixins) { - var api = _getDecoratorsApi(); - - if (mixins) { - for (var i = 0; i < mixins.length; i++) { - api = mixins[i](api); - } - } - - var r = factory(function initialize(O) { - api.initializeInstanceElements(O, decorated.elements); - }, superClass); - var decorated = api.decorateClass(_coalesceClassElements(r.d.map(_createElementDescriptor)), decorators); - api.initializeClassElements(r.F, decorated.elements); - return api.runClassFinishers(r.F, decorated.finishers); - } - - function _getDecoratorsApi() { - _getDecoratorsApi = function () { - return api; - }; - - var api = { - elementsDefinitionOrder: [["method"], ["field"]], - initializeInstanceElements: function (O, elements) { - ["method", "field"].forEach(function (kind) { - elements.forEach(function (element) { - if (element.kind === kind && element.placement === "own") { - this.defineClassElement(O, element); - } - }, this); - }, this); - }, - initializeClassElements: function (F, elements) { - var proto = F.prototype; - ["method", "field"].forEach(function (kind) { - elements.forEach(function (element) { - var placement = element.placement; - - if (element.kind === kind && (placement === "static" || placement === "prototype")) { - var receiver = placement === "static" ? F : proto; - this.defineClassElement(receiver, element); - } - }, this); - }, this); - }, - defineClassElement: function (receiver, element) { - var descriptor = element.descriptor; - - if (element.kind === "field") { - var initializer = element.initializer; - descriptor = { - enumerable: descriptor.enumerable, - writable: descriptor.writable, - configurable: descriptor.configurable, - value: initializer === void 0 ? void 0 : initializer.call(receiver) - }; - } - - Object.defineProperty(receiver, element.key, descriptor); - }, - decorateClass: function (elements, decorators) { - var newElements = []; - var finishers = []; - var placements = { - static: [], - prototype: [], - own: [] - }; - elements.forEach(function (element) { - this.addElementPlacement(element, placements); - }, this); - elements.forEach(function (element) { - if (!_hasDecorators(element)) return newElements.push(element); - var elementFinishersExtras = this.decorateElement(element, placements); - newElements.push(elementFinishersExtras.element); - newElements.push.apply(newElements, elementFinishersExtras.extras); - finishers.push.apply(finishers, elementFinishersExtras.finishers); - }, this); - - if (!decorators) { - return { - elements: newElements, - finishers: finishers - }; - } - - var result = this.decorateConstructor(newElements, decorators); - finishers.push.apply(finishers, result.finishers); - result.finishers = finishers; - return result; - }, - addElementPlacement: function (element, placements, silent) { - var keys = placements[element.placement]; - - if (!silent && keys.indexOf(element.key) !== -1) { - throw new TypeError("Duplicated element (" + element.key + ")"); - } - - keys.push(element.key); - }, - decorateElement: function (element, placements) { - var extras = []; - var finishers = []; - - for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) { - var keys = placements[element.placement]; - keys.splice(keys.indexOf(element.key), 1); - var elementObject = this.fromElementDescriptor(element); - var elementFinisherExtras = this.toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject); - element = elementFinisherExtras.element; - this.addElementPlacement(element, placements); - - if (elementFinisherExtras.finisher) { - finishers.push(elementFinisherExtras.finisher); - } - - var newExtras = elementFinisherExtras.extras; - - if (newExtras) { - for (var j = 0; j < newExtras.length; j++) { - this.addElementPlacement(newExtras[j], placements); - } - - extras.push.apply(extras, newExtras); - } - } - - return { - element: element, - finishers: finishers, - extras: extras - }; - }, - decorateConstructor: function (elements, decorators) { - var finishers = []; - - for (var i = decorators.length - 1; i >= 0; i--) { - var obj = this.fromClassDescriptor(elements); - var elementsAndFinisher = this.toClassDescriptor((0, decorators[i])(obj) || obj); - - if (elementsAndFinisher.finisher !== undefined) { - finishers.push(elementsAndFinisher.finisher); - } - - if (elementsAndFinisher.elements !== undefined) { - elements = elementsAndFinisher.elements; - - for (var j = 0; j < elements.length - 1; j++) { - for (var k = j + 1; k < elements.length; k++) { - if (elements[j].key === elements[k].key && elements[j].placement === elements[k].placement) { - throw new TypeError("Duplicated element (" + elements[j].key + ")"); - } - } - } - } - } - - return { - elements: elements, - finishers: finishers - }; - }, - fromElementDescriptor: function (element) { - var obj = { - kind: element.kind, - key: element.key, - placement: element.placement, - descriptor: element.descriptor - }; - var desc = { - value: "Descriptor", - configurable: true - }; - Object.defineProperty(obj, Symbol.toStringTag, desc); - if (element.kind === "field") obj.initializer = element.initializer; - return obj; - }, - toElementDescriptors: function (elementObjects) { - if (elementObjects === undefined) return; - return _toArray(elementObjects).map(function (elementObject) { - var element = this.toElementDescriptor(elementObject); - this.disallowProperty(elementObject, "finisher", "An element descriptor"); - this.disallowProperty(elementObject, "extras", "An element descriptor"); - return element; - }, this); - }, - toElementDescriptor: function (elementObject) { - var kind = String(elementObject.kind); - - if (kind !== "method" && kind !== "field") { - throw new TypeError('An element descriptor\'s .kind property must be either "method" or' + ' "field", but a decorator created an element descriptor with' + ' .kind "' + kind + '"'); - } - - var key = _toPropertyKey(elementObject.key); - - var placement = String(elementObject.placement); - - if (placement !== "static" && placement !== "prototype" && placement !== "own") { - throw new TypeError('An element descriptor\'s .placement property must be one of "static",' + ' "prototype" or "own", but a decorator created an element descriptor' + ' with .placement "' + placement + '"'); - } - - var descriptor = elementObject.descriptor; - this.disallowProperty(elementObject, "elements", "An element descriptor"); - var element = { - kind: kind, - key: key, - placement: placement, - descriptor: Object.assign({}, descriptor) - }; - - if (kind !== "field") { - this.disallowProperty(elementObject, "initializer", "A method descriptor"); - } else { - this.disallowProperty(descriptor, "get", "The property descriptor of a field descriptor"); - this.disallowProperty(descriptor, "set", "The property descriptor of a field descriptor"); - this.disallowProperty(descriptor, "value", "The property descriptor of a field descriptor"); - element.initializer = elementObject.initializer; - } - - return element; - }, - toElementFinisherExtras: function (elementObject) { - var element = this.toElementDescriptor(elementObject); - - var finisher = _optionalCallableProperty(elementObject, "finisher"); - - var extras = this.toElementDescriptors(elementObject.extras); - return { - element: element, - finisher: finisher, - extras: extras - }; - }, - fromClassDescriptor: function (elements) { - var obj = { - kind: "class", - elements: elements.map(this.fromElementDescriptor, this) - }; - var desc = { - value: "Descriptor", - configurable: true - }; - Object.defineProperty(obj, Symbol.toStringTag, desc); - return obj; - }, - toClassDescriptor: function (obj) { - var kind = String(obj.kind); - - if (kind !== "class") { - throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator' + ' created a class descriptor with .kind "' + kind + '"'); - } - - this.disallowProperty(obj, "key", "A class descriptor"); - this.disallowProperty(obj, "placement", "A class descriptor"); - this.disallowProperty(obj, "descriptor", "A class descriptor"); - this.disallowProperty(obj, "initializer", "A class descriptor"); - this.disallowProperty(obj, "extras", "A class descriptor"); - - var finisher = _optionalCallableProperty(obj, "finisher"); - - var elements = this.toElementDescriptors(obj.elements); - return { - elements: elements, - finisher: finisher - }; - }, - runClassFinishers: function (constructor, finishers) { - for (var i = 0; i < finishers.length; i++) { - var newConstructor = (0, finishers[i])(constructor); - - if (newConstructor !== undefined) { - if (typeof newConstructor !== "function") { - throw new TypeError("Finishers must return a constructor."); - } - - constructor = newConstructor; - } - } - - return constructor; - }, - disallowProperty: function (obj, name, objectType) { - if (obj[name] !== undefined) { - throw new TypeError(objectType + " can't have a ." + name + " property."); - } - } - }; - return api; - } - - function _createElementDescriptor(def) { - var key = _toPropertyKey(def.key); - - var descriptor; - - if (def.kind === "method") { - descriptor = { - value: def.value, - writable: true, - configurable: true, - enumerable: false - }; - } else if (def.kind === "get") { - descriptor = { - get: def.value, - configurable: true, - enumerable: false - }; - } else if (def.kind === "set") { - descriptor = { - set: def.value, - configurable: true, - enumerable: false - }; - } else if (def.kind === "field") { - descriptor = { - configurable: true, - writable: true, - enumerable: true - }; - } - - var element = { - kind: def.kind === "field" ? "field" : "method", - key: key, - placement: def.static ? "static" : def.kind === "field" ? "own" : "prototype", - descriptor: descriptor - }; - if (def.decorators) element.decorators = def.decorators; - if (def.kind === "field") element.initializer = def.value; - return element; - } - - function _coalesceGetterSetter(element, other) { - if (element.descriptor.get !== undefined) { - other.descriptor.get = element.descriptor.get; - } else { - other.descriptor.set = element.descriptor.set; - } - } - - function _coalesceClassElements(elements) { - var newElements = []; - - var isSameElement = function (other) { - return other.kind === "method" && other.key === element.key && other.placement === element.placement; - }; - - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - var other; - - if (element.kind === "method" && (other = newElements.find(isSameElement))) { - if (_isDataDescriptor(element.descriptor) || _isDataDescriptor(other.descriptor)) { - if (_hasDecorators(element) || _hasDecorators(other)) { - throw new ReferenceError("Duplicated methods (" + element.key + ") can't be decorated."); - } - - other.descriptor = element.descriptor; - } else { - if (_hasDecorators(element)) { - if (_hasDecorators(other)) { - throw new ReferenceError("Decorators can't be placed on different accessors with for " + "the same property (" + element.key + ")."); - } - - other.decorators = element.decorators; - } - - _coalesceGetterSetter(element, other); - } - } else { - newElements.push(element); - } - } - - return newElements; - } - - function _hasDecorators(element) { - return element.decorators && element.decorators.length; - } - - function _isDataDescriptor(desc) { - return desc !== undefined && !(desc.value === undefined && desc.writable === undefined); - } - - function _optionalCallableProperty(obj, name) { - var value = obj[name]; - - if (value !== undefined && typeof value !== "function") { - throw new TypeError("Expected '" + name + "' to be a function"); - } - - return value; - } - - /** - * @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 - */ - const directives = new WeakMap(); - /** - * Brands a function as a directive factory function so that lit-html will call - * the function during template rendering, rather than passing as a value. - * - * A _directive_ is a function that takes a Part as an argument. It has the - * signature: `(part: Part) => void`. - * - * A directive _factory_ is a function that takes arguments for data and - * configuration and returns a directive. Users of directive usually refer to - * the directive factory as the directive. For example, "The repeat directive". - * - * Usually a template author will invoke a directive factory in their template - * with relevant arguments, which will then return a directive function. - * - * Here's an example of using the `repeat()` directive factory that takes an - * array and a function to render an item: - * - * ```js - * html`` - * ``` - * - * When `repeat` is invoked, it returns a directive function that closes over - * `items` and the template function. When the outer template is rendered, the - * return directive function is called with the Part for the expression. - * `repeat` then performs it's custom logic to render multiple items. - * - * @param f The directive factory function. Must be a function that returns a - * function of the signature `(part: Part) => void`. The returned function will - * be called with the part object. - * - * @example - * - * import {directive, html} from 'lit-html'; - * - * const immutable = directive((v) => (part) => { - * if (part.value !== v) { - * part.setValue(v) - * } - * }); - */ - const directive = (f) => ((...args) => { - const d = f(...args); - directives.set(d, true); - return d; - }); - const isDirective = (o) => { - return typeof o === 'function' && directives.has(o); - }; - //# sourceMappingURL=directive.js.map - - /** - * @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 - */ - /** - * True if the custom elements polyfill is in use. - */ - const isCEPolyfill = window.customElements !== undefined && - window.customElements.polyfillWrapFlushCallback !== - undefined; - /** - * Removes nodes, starting from `start` (inclusive) to `end` (exclusive), from - * `container`. - */ - const removeNodes = (container, start, end = null) => { - while (start !== end) { - const n = start.nextSibling; - container.removeChild(start); - start = n; - } - }; - //# sourceMappingURL=dom.js.map - - /** - * @license - * Copyright (c) 2018 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 - */ - /** - * A sentinel value that signals that a value was handled by a directive and - * should not be written to the DOM. - */ - const noChange = {}; - /** - * A sentinel value that signals a NodePart to fully clear its content. - */ - const nothing = {}; - //# sourceMappingURL=part.js.map - - /** - * @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 - */ - /** - * An expression marker with embedded unique key to avoid collision with - * possible text in templates. - */ - const marker = `{{lit-${String(Math.random()).slice(2)}}}`; - /** - * An expression marker used text-positions, multi-binding attributes, and - * attributes with markup-like text values. - */ - const nodeMarker = ``; - const markerRegex = new RegExp(`${marker}|${nodeMarker}`); - /** - * Suffix appended to all bound attribute names. - */ - const boundAttributeSuffix = '$lit$'; - /** - * An updateable Template that tracks the location of dynamic parts. - */ - class Template { - constructor(result, element) { - this.parts = []; - this.element = element; - const nodesToRemove = []; - const stack = []; - // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null - const walker = document.createTreeWalker(element.content, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false); - // Keeps track of the last index associated with a part. We try to delete - // unnecessary nodes, but we never want to associate two different parts - // to the same index. They must have a constant node between. - let lastPartIndex = 0; - let index = -1; - let partIndex = 0; - const { strings, values: { length } } = result; - while (partIndex < length) { - const node = walker.nextNode(); - if (node === null) { - // We've exhausted the content inside a nested template element. - // Because we still have parts (the outer for-loop), we know: - // - There is a template in the stack - // - The walker will find a nextNode outside the template - walker.currentNode = stack.pop(); - continue; - } - index++; - if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { - if (node.hasAttributes()) { - const attributes = node.attributes; - const { length } = attributes; - // Per - // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap, - // attributes are not guaranteed to be returned in document order. - // In particular, Edge/IE can return them out of order, so we cannot - // assume a correspondence between part index and attribute index. - let count = 0; - for (let i = 0; i < length; i++) { - if (endsWith(attributes[i].name, boundAttributeSuffix)) { - count++; - } - } - while (count-- > 0) { - // Get the template literal section leading up to the first - // expression in this attribute - const stringForPart = strings[partIndex]; - // Find the attribute name - const name = lastAttributeNameRegex.exec(stringForPart)[2]; - // Find the corresponding attribute - // All bound attributes have had a suffix added in - // TemplateResult#getHTML to opt out of special attribute - // handling. To look up the attribute value we also need to add - // the suffix. - const attributeLookupName = name.toLowerCase() + boundAttributeSuffix; - const attributeValue = node.getAttribute(attributeLookupName); - node.removeAttribute(attributeLookupName); - const statics = attributeValue.split(markerRegex); - this.parts.push({ type: 'attribute', index, name, strings: statics }); - partIndex += statics.length - 1; - } - } - if (node.tagName === 'TEMPLATE') { - stack.push(node); - walker.currentNode = node.content; - } - } - else if (node.nodeType === 3 /* Node.TEXT_NODE */) { - const data = node.data; - if (data.indexOf(marker) >= 0) { - const parent = node.parentNode; - const strings = data.split(markerRegex); - const lastIndex = strings.length - 1; - // Generate a new text node for each literal section - // These nodes are also used as the markers for node parts - for (let i = 0; i < lastIndex; i++) { - let insert; - let s = strings[i]; - if (s === '') { - insert = createMarker(); - } - else { - const match = lastAttributeNameRegex.exec(s); - if (match !== null && endsWith(match[2], boundAttributeSuffix)) { - s = s.slice(0, match.index) + match[1] + - match[2].slice(0, -boundAttributeSuffix.length) + match[3]; - } - insert = document.createTextNode(s); - } - parent.insertBefore(insert, node); - this.parts.push({ type: 'node', index: ++index }); - } - // If there's no text, we must insert a comment to mark our place. - // Else, we can trust it will stick around after cloning. - if (strings[lastIndex] === '') { - parent.insertBefore(createMarker(), node); - nodesToRemove.push(node); - } - else { - node.data = strings[lastIndex]; - } - // We have a part for each match found - partIndex += lastIndex; - } - } - else if (node.nodeType === 8 /* Node.COMMENT_NODE */) { - if (node.data === marker) { - const parent = node.parentNode; - // Add a new marker node to be the startNode of the Part if any of - // the following are true: - // * We don't have a previousSibling - // * The previousSibling is already the start of a previous part - if (node.previousSibling === null || index === lastPartIndex) { - index++; - parent.insertBefore(createMarker(), node); - } - lastPartIndex = index; - this.parts.push({ type: 'node', index }); - // If we don't have a nextSibling, keep this node so we have an end. - // Else, we can remove it to save future costs. - if (node.nextSibling === null) { - node.data = ''; - } - else { - nodesToRemove.push(node); - index--; - } - partIndex++; - } - else { - let i = -1; - while ((i = node.data.indexOf(marker, i + 1)) !== -1) { - // Comment node has a binding marker inside, make an inactive part - // The binding won't work, but subsequent bindings will - // TODO (justinfagnani): consider whether it's even worth it to - // make bindings in comments work - this.parts.push({ type: 'node', index: -1 }); - partIndex++; - } - } - } - } - // Remove text binding nodes after the walk to not disturb the TreeWalker - for (const n of nodesToRemove) { - n.parentNode.removeChild(n); - } - } - } - const endsWith = (str, suffix) => { - const index = str.length - suffix.length; - return index >= 0 && str.slice(index) === suffix; - }; - const isTemplatePartActive = (part) => part.index !== -1; - // Allows `document.createComment('')` to be renamed for a - // small manual size-savings. - const createMarker = () => document.createComment(''); - /** - * This regex extracts the attribute name preceding an attribute-position - * expression. It does this by matching the syntax allowed for attributes - * against the string literal directly preceding the expression, assuming that - * the expression is in an attribute-value position. - * - * See attributes in the HTML spec: - * https://www.w3.org/TR/html5/syntax.html#elements-attributes - * - * " \x09\x0a\x0c\x0d" are HTML space characters: - * https://www.w3.org/TR/html5/infrastructure.html#space-characters - * - * "\0-\x1F\x7F-\x9F" are Unicode control characters, which includes every - * space character except " ". - * - * So an attribute is: - * * The name: any character except a control character, space character, ('), - * ("), ">", "=", or "/" - * * Followed by zero or more space characters - * * Followed by "=" - * * Followed by zero or more space characters - * * Followed by: - * * Any character except space, ('), ("), "<", ">", "=", (`), or - * * (") then any non-("), or - * * (') then any non-(') - */ - const lastAttributeNameRegex = /([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/; - //# sourceMappingURL=template.js.map - - /** - * @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 - */ - /** - * An instance of a `Template` that can be attached to the DOM and updated - * with new values. - */ - class TemplateInstance { - constructor(template, processor, options) { - this.__parts = []; - this.template = template; - this.processor = processor; - this.options = options; - } - update(values) { - let i = 0; - for (const part of this.__parts) { - if (part !== undefined) { - part.setValue(values[i]); - } - i++; - } - for (const part of this.__parts) { - if (part !== undefined) { - part.commit(); - } - } - } - _clone() { - // There are a number of steps in the lifecycle of a template instance's - // DOM fragment: - // 1. Clone - create the instance fragment - // 2. Adopt - adopt into the main document - // 3. Process - find part markers and create parts - // 4. Upgrade - upgrade custom elements - // 5. Update - set node, attribute, property, etc., values - // 6. Connect - connect to the document. Optional and outside of this - // method. - // - // We have a few constraints on the ordering of these steps: - // * We need to upgrade before updating, so that property values will pass - // through any property setters. - // * We would like to process before upgrading so that we're sure that the - // cloned fragment is inert and not disturbed by self-modifying DOM. - // * We want custom elements to upgrade even in disconnected fragments. - // - // Given these constraints, with full custom elements support we would - // prefer the order: Clone, Process, Adopt, Upgrade, Update, Connect - // - // But Safari dooes not implement CustomElementRegistry#upgrade, so we - // can not implement that order and still have upgrade-before-update and - // upgrade disconnected fragments. So we instead sacrifice the - // process-before-upgrade constraint, since in Custom Elements v1 elements - // must not modify their light DOM in the constructor. We still have issues - // when co-existing with CEv0 elements like Polymer 1, and with polyfills - // that don't strictly adhere to the no-modification rule because shadow - // DOM, which may be created in the constructor, is emulated by being placed - // in the light DOM. - // - // The resulting order is on native is: Clone, Adopt, Upgrade, Process, - // Update, Connect. document.importNode() performs Clone, Adopt, and Upgrade - // in one step. - // - // The Custom Elements v1 polyfill supports upgrade(), so the order when - // polyfilled is the more ideal: Clone, Process, Adopt, Upgrade, Update, - // Connect. - const fragment = isCEPolyfill ? - this.template.element.content.cloneNode(true) : - document.importNode(this.template.element.content, true); - const stack = []; - const parts = this.template.parts; - // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null - const walker = document.createTreeWalker(fragment, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false); - let partIndex = 0; - let nodeIndex = 0; - let part; - let node = walker.nextNode(); - // Loop through all the nodes and parts of a template - while (partIndex < parts.length) { - part = parts[partIndex]; - if (!isTemplatePartActive(part)) { - this.__parts.push(undefined); - partIndex++; - continue; - } - // Progress the tree walker until we find our next part's node. - // Note that multiple parts may share the same node (attribute parts - // on a single element), so this loop may not run at all. - while (nodeIndex < part.index) { - nodeIndex++; - if (node.nodeName === 'TEMPLATE') { - stack.push(node); - walker.currentNode = node.content; - } - if ((node = walker.nextNode()) === null) { - // We've exhausted the content inside a nested template element. - // Because we still have parts (the outer for-loop), we know: - // - There is a template in the stack - // - The walker will find a nextNode outside the template - walker.currentNode = stack.pop(); - node = walker.nextNode(); - } - } - // We've arrived at our part's node. - if (part.type === 'node') { - const part = this.processor.handleTextExpression(this.options); - part.insertAfterNode(node.previousSibling); - this.__parts.push(part); - } - else { - this.__parts.push(...this.processor.handleAttributeExpressions(node, part.name, part.strings, this.options)); - } - partIndex++; - } - if (isCEPolyfill) { - document.adoptNode(fragment); - customElements.upgrade(fragment); - } - return fragment; - } - } - //# sourceMappingURL=template-instance.js.map - - /** - * @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 - */ - const commentMarker = ` ${marker} `; - /** - * The return type of `html`, which holds a Template and the values from - * interpolated expressions. - */ - class TemplateResult { - constructor(strings, values, type, processor) { - this.strings = strings; - this.values = values; - this.type = type; - this.processor = processor; - } - /** - * Returns a string of HTML used to create a `