All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.polymer.public.bower_components.hydrolysis.hydrolysis.js Maven / Gradle / Ivy

The newest version!
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) {
                    console.error("Only one base tag per document!");
                    throw "Multiple base tags in " + href;
                } else if (parsed.base.length == 1) {
                    var baseHref = dom5.getAttribute(parsed.base[0], "href");
                    if (baseHref) {
                        baseHref = baseHref + "/";
                        baseUri = url.resolve(baseUri, baseHref);
                    }
                }
                var _iteratorNormalCompletion2 = true;
                var _didIteratorError2 = false;
                var _iteratorError2 = undefined;

                try {
                    for (var _iterator2 = parsed.import[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                        var link = _step2.value;

                        var linkurl = dom5.getAttribute(link, 'href');
                        if (linkurl) {
                            var resolvedUrl = url.resolve(baseUri, linkurl);
                            depHrefs.push(resolvedUrl);
                            depsLoaded.push(this._dependenciesLoadedFor(resolvedUrl, href));
                        }
                    }
                } catch (err) {
                    _didIteratorError2 = true;
                    _iteratorError2 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion2 && _iterator2.return) {
                            _iterator2.return();
                        }
                    } finally {
                        if (_didIteratorError2) {
                            throw _iteratorError2;
                        }
                    }
                }

                var _iteratorNormalCompletion3 = true;
                var _didIteratorError3 = false;
                var _iteratorError3 = undefined;

                try {
                    for (var _iterator3 = parsed.style[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                        var styleElement = _step3.value;

                        if (polymerExternalStyle(styleElement)) {
                            var styleHref = dom5.getAttribute(styleElement, 'href');
                            if (href) {
                                styleHref = url.resolve(baseUri, styleHref);
                                depsLoaded.push(this.loader.request(styleHref).then(function (content) {
                                    _this2._content[styleHref] = content;
                                    return {};
                                }));
                            }
                        }
                    }
                } catch (err) {
                    _didIteratorError3 = true;
                    _iteratorError3 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion3 && _iterator3.return) {
                            _iterator3.return();
                        }
                    } finally {
                        if (_didIteratorError3) {
                            throw _iteratorError3;
                        }
                    }
                }
            }
            var depsStrLoaded = Promise.all(depsLoaded).then(function () {
                return depHrefs;
            }).catch(function (err) {
                throw err;
            });
            this.parsedDocuments[href] = parsed.ast;
            this.html[href] = {
                href: href,
                htmlLoaded: htmlLoaded,
                metadataLoaded: metadataLoaded,
                depHrefs: depHrefs,
                depsLoaded: depsStrLoaded
            };
            return this.html[href];
        }
    }, {
        key: '_processScripts',
        value: function _processScripts(scripts, href) {
            var _this3 = this;

            var scriptPromises = [];
            scripts.forEach(function (script) {
                scriptPromises.push(_this3._processScript(script, href));
            });
            return Promise.all(scriptPromises).then(function (metadataList) {
                // TODO(ajo) remove this cast.
                var list = metadataList;
                return list.reduce(reduceMetadata, EMPTY_METADATA);
            });
        }
    }, {
        key: '_processScript',
        value: function _processScript(script, href) {
            var _this4 = this;

            var src = dom5.getAttribute(script, 'src');
            var parsedJs;
            if (!src) {
                try {
                    parsedJs = js_parse_1.jsParse(script.childNodes.length ? script.childNodes[0].value : '');
                } catch (err) {
                    // Figure out the correct line number for the error.
                    var line = 0;
                    var col = 0;
                    if (script.__ownerDocument && script.__ownerDocument == href) {
                        line = script.__locationDetail.line - 1;
                        col = script.__locationDetail.column - 1;
                    }
                    line += err.lineNumber;
                    col += err.column;
                    var message = "Error parsing script in " + href + " at " + line + ":" + col;
                    message += "\n" + err.stack;
                    var fixedErr = new Error(message);
                    fixedErr.location = { line: line, column: col };
                    fixedErr.ownerDocument = script.__ownerDocument;
                    return Promise.reject(fixedErr);
                }
                if (parsedJs.elements) {
                    parsedJs.elements.forEach(function (element) {
                        element.scriptElement = script;
                        element.contentHref = href;
                        _this4.elements.push(element);
                        if (element.is in _this4.elementsByTagName) {
                            console.warn('Ignoring duplicate element definition: ' + element.is);
                        } else {
                            _this4.elementsByTagName[element.is] = element;
                        }
                    });
                }
                if (parsedJs.features) {
                    parsedJs.features.forEach(function (feature) {
                        feature.contentHref = href;
                        feature.scriptElement = script;
                    });
                    this.features = this.features.concat(parsedJs.features);
                }
                if (parsedJs.behaviors) {
                    parsedJs.behaviors.forEach(function (behavior) {
                        behavior.contentHref = href;
                        _this4.behaviorsByName[behavior.is] = behavior;
                        _this4.behaviorsByName[behavior.symbol] = behavior;
                    });
                    this.behaviors = this.behaviors.concat(parsedJs.behaviors);
                }
                if (!Object.hasOwnProperty.call(this.parsedScripts, href)) {
                    this.parsedScripts[href] = [];
                }
                var scriptElement;
                if (script.__ownerDocument && script.__ownerDocument == href) {
                    scriptElement = script;
                }
                this.parsedScripts[href].push({
                    ast: parsedJs.parsedScript,
                    scriptElement: scriptElement
                });
                return Promise.resolve(parsedJs);
            }
            if (this.loader) {
                var resolvedSrc = url.resolve(href, src);
                return this.loader.request(resolvedSrc).then(function (content) {
                    _this4._content[resolvedSrc] = content;
                    var scriptText = dom5.constructors.text(content);
                    dom5.append(script, scriptText);
                    dom5.removeAttribute(script, 'src');
                    script.__hydrolysisInlined = src;
                    return _this4._processScript(script, resolvedSrc);
                }).catch(function (err) {
                    throw err;
                });
            } else {
                return Promise.resolve(EMPTY_METADATA);
            }
        }
    }, {
        key: '_dependenciesLoadedFor',
        value: function _dependenciesLoadedFor(href, root) {
            var _this5 = this;

            var found = {};
            if (root !== undefined) {
                found[root] = true;
            }
            return this._getDependencies(href, found).then(function (deps) {
                var depPromises = deps.map(function (depHref) {
                    return _this5.load(depHref).then(function (htmlMonomer) {
                        return htmlMonomer.metadataLoaded;
                    });
                });
                return Promise.all(depPromises);
            });
        }
    }, {
        key: '_getDependencies',

        /**
         * List all the html dependencies for the document at `href`.
         * @param  {string}                   href      The href to get dependencies for.
         * @param  {Object.=} found     An object keyed by URL of the
         *     already resolved dependencies.
         * @param  {boolean=}                transitive Whether to load transitive
         *     dependencies. Defaults to true.
         * @return {Array.}  A list of all the html dependencies.
         */
        value: function _getDependencies(href, found, transitive) {
            var _this6 = this;

            if (found === undefined) {
                found = {};
                found[href] = true;
            }
            if (transitive === undefined) {
                transitive = true;
            }
            var deps = [];
            return this.load(href).then(function (htmlMonomer) {
                var transitiveDeps = [];
                htmlMonomer.depHrefs.forEach(function (depHref) {
                    if (found[depHref]) {
                        return;
                    }
                    deps.push(depHref);
                    found[depHref] = true;
                    if (transitive) {
                        transitiveDeps.push(_this6._getDependencies(depHref, found));
                    }
                });
                return Promise.all(transitiveDeps);
            }).then(function (transitiveDeps) {
                var alldeps = transitiveDeps.reduce(function (a, b) {
                    return a.concat(b);
                }, []).concat(deps);
                return alldeps;
            });
        }
    }, {
        key: 'elementsForFolder',

        /**
         * Returns the elements defined in the folder containing `href`.
         * @param {string} href path to search.
         */
        value: function elementsForFolder(href) {
            return this.elements.filter(function (element) {
                return matchesDocumentFolder(element, href);
            });
        }
    }, {
        key: 'behaviorsForFolder',

        /**
         * Returns the behaviors defined in the folder containing `href`.
         * @param {string} href path to search.
         * @return {Array.}
         */
        value: function behaviorsForFolder(href) {
            return this.behaviors.filter(function (behavior) {
                return matchesDocumentFolder(behavior, href);
            });
        }
    }, {
        key: 'metadataTree',

        /**
         * Returns a promise that resolves to a POJO representation of the import
         * tree, in a format that maintains the ordering of the HTML imports spec.
         * @param {string} href the import to get metadata for.
         * @return {Promise}
         */
        value: function metadataTree(href) {
            var _this7 = this;

            return this.load(href).then(function (monomer) {
                var loadedHrefs = {};
                loadedHrefs[href] = true;
                return _this7._metadataTree(monomer, loadedHrefs);
            });
        }
    }, {
        key: '_metadataTree',
        value: function _metadataTree(htmlMonomer, loadedHrefs) {
            return __awaiter(this, void 0, void 0, regeneratorRuntime.mark(function _callee() {
                var metadata, hrefs, depMetadata, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, href, metadataPromise;

                return regeneratorRuntime.wrap(function _callee$(_context) {
                    while (1) {
                        switch (_context.prev = _context.next) {
                            case 0:
                                if (loadedHrefs === undefined) {
                                    loadedHrefs = {};
                                }
                                _context.next = 3;
                                return htmlMonomer.metadataLoaded;

                            case 3:
                                metadata = _context.sent;

                                metadata = {
                                    elements: metadata.elements,
                                    features: metadata.features,
                                    behaviors: [],
                                    href: htmlMonomer.href
                                };
                                _context.next = 7;
                                return htmlMonomer.depsLoaded;

                            case 7:
                                hrefs = _context.sent;
                                depMetadata = [];
                                _iteratorNormalCompletion4 = true;
                                _didIteratorError4 = false;
                                _iteratorError4 = undefined;
                                _context.prev = 12;
                                _iterator4 = hrefs[Symbol.iterator]();

                            case 14:
                                if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
                                    _context.next = 29;
                                    break;
                                }

                                href = _step4.value;
                                metadataPromise = undefined;

                                if (loadedHrefs[href]) {
                                    _context.next = 24;
                                    break;
                                }

                                loadedHrefs[href] = true;
                                metadataPromise = this._metadataTree(this.html[href], loadedHrefs);
                                _context.next = 22;
                                return metadataPromise;

                            case 22:
                                _context.next = 25;
                                break;

                            case 24:
                                metadataPromise = Promise.resolve({});

                            case 25:
                                depMetadata.push(metadataPromise);

                            case 26:
                                _iteratorNormalCompletion4 = true;
                                _context.next = 14;
                                break;

                            case 29:
                                _context.next = 35;
                                break;

                            case 31:
                                _context.prev = 31;
                                _context.t0 = _context['catch'](12);
                                _didIteratorError4 = true;
                                _iteratorError4 = _context.t0;

                            case 35:
                                _context.prev = 35;
                                _context.prev = 36;

                                if (!_iteratorNormalCompletion4 && _iterator4.return) {
                                    _iterator4.return();
                                }

                            case 38:
                                _context.prev = 38;

                                if (!_didIteratorError4) {
                                    _context.next = 41;
                                    break;
                                }

                                throw _iteratorError4;

                            case 41:
                                return _context.finish(38);

                            case 42:
                                return _context.finish(35);

                            case 43:
                                return _context.abrupt('return', Promise.all(depMetadata).then(function (importMetadata) {
                                    // TODO(ajo): remove this when tsc stops having issues.
                                    metadata.imports = importMetadata;
                                    return htmlMonomer.htmlLoaded.then(function (parsedHtml) {
                                        metadata.html = parsedHtml;
                                        if (metadata.elements) {
                                            metadata.elements.forEach(function (element) {
                                                attachDomModule(parsedHtml, element);
                                            });
                                        }
                                        return metadata;
                                    });
                                }));

                            case 44:
                            case 'end':
                                return _context.stop();
                        }
                    }
                }, _callee, this, [[12, 31, 35, 43], [36,, 38, 42]]);
            }));
        }
    }, {
        key: '_inlineStyles',
        value: function _inlineStyles(ast, href) {
            var _this8 = this;

            var cssLinks = dom5.queryAll(ast, polymerExternalStyle);
            cssLinks.forEach(function (link) {
                var linkHref = dom5.getAttribute(link, 'href');
                var uri = url.resolve(href, linkHref);
                var content = _this8._content[uri];
                var style = dom5.constructors.element('style');
                dom5.setTextContent(style, '\n' + content + '\n');
                dom5.replace(link, style);
            });
            return cssLinks.length > 0;
        }
    }, {
        key: '_inlineScripts',
        value: function _inlineScripts(ast, href) {
            var _this9 = this;

            var scripts = dom5.queryAll(ast, externalScript);
            scripts.forEach(function (script) {
                var scriptHref = dom5.getAttribute(script, 'src');
                var uri = url.resolve(href, scriptHref);
                var content = _this9._content[uri];
                var inlined = dom5.constructors.element('script');
                dom5.setTextContent(inlined, '\n' + content + '\n');
                dom5.replace(script, inlined);
            });
            return scripts.length > 0;
        }
    }, {
        key: '_inlineImports',
        value: function _inlineImports(ast, href, loaded) {
            var _this10 = this;

            var imports = dom5.queryAll(ast, isHtmlImportNode);
            imports.forEach(function (htmlImport) {
                var importHref = dom5.getAttribute(htmlImport, 'href');
                var uri = url.resolve(href, importHref);
                if (loaded[uri]) {
                    dom5.remove(htmlImport);
                    return;
                }
                var content = _this10.getLoadedAst(uri, loaded);
                dom5.replace(htmlImport, content);
            });
            return imports.length > 0;
        }
    }, {
        key: 'getLoadedAst',

        /**
         * Returns a promise resolving to a form of the AST with all links replaced
         * with the document they link to. .css and .script files become <style> and
         * <script>, respectively.
         *
         * The elements in the loaded document are unmodified from their original
         * documents.
         *
         * @param {string} href The document to load.
         * @param {Object.=} loaded An object keyed by already loaded documents.
         * @return {Promise.}
         */
        value: function getLoadedAst(href, loaded) {
            if (!loaded) {
                loaded = {};
            }
            loaded[href] = true;
            var parsedDocument = this.parsedDocuments[href];
            var analyzedDocument = this.html[href];
            var astCopy = dom5.parse(dom5.serialize(parsedDocument));
            // Whenever we inline something, reset inlined to true to know that anoather
            // inlining pass is needed;
            this._inlineStyles(astCopy, href);
            this._inlineScripts(astCopy, href);
            this._inlineImports(astCopy, href, loaded);
            return astCopy;
        }
    }, {
        key: 'nodeWalkDocuments',

        /**
         * Calls `dom5.nodeWalkAll` on each document that `Anayzler` has laoded.
         */
        value: function nodeWalkDocuments(predicate) {
            var results = [];
            for (var href in this.parsedDocuments) {
                var newNodes = dom5.nodeWalkAll(this.parsedDocuments[href], predicate);
                results = results.concat(newNodes);
            }
            return results;
        }
    }, {
        key: 'nodeWalkAllDocuments',

        /**
         * Calls `dom5.nodeWalkAll` on each document that `Anayzler` has laoded.
         *
         * TODO: make nodeWalkAll & nodeWalkAllDocuments distict, or delete one.
         */
        value: function nodeWalkAllDocuments(predicate) {
            var results = [];
            for (var href in this.parsedDocuments) {
                var newNodes = dom5.nodeWalkAll(this.parsedDocuments[href], predicate);
                results = results.concat(newNodes);
            }
            return results;
        }
    }, {
        key: 'annotate',

        /** Annotates all loaded metadata with its documentation. */
        value: function annotate() {
            var _this11 = this;

            if (this.features.length > 0) {
                var featureEl = docs.featureElement(this.features);
                this.elements.unshift(featureEl);
                this.elementsByTagName[featureEl.is] = featureEl;
            }
            var behaviorsByName = this.behaviorsByName;
            var elementHelper = function elementHelper(descriptor) {
                docs.annotateElement(descriptor, behaviorsByName);
            };
            this.elements.forEach(elementHelper);
            this.behaviors.forEach(elementHelper); // Same shape.
            this.behaviors.forEach(function (behavior) {
                if (behavior.is !== behavior.symbol && behavior.symbol) {
                    _this11.behaviorsByName[behavior.symbol] = undefined;
                }
            });
        }
    }, {
        key: 'clean',

        /** Removes redundant properties from the collected descriptors. */
        value: function clean() {
            this.elements.forEach(docs.cleanElement);
        }
    }]);

    return Analyzer;
}();
/**
 * Shorthand for transitively loading and processing all imports beginning at
 * `href`.
 *
 * In order to properly filter paths, `href` _must_ be an absolute URI.
 *
 * @param {string} href The root import to begin loading from.
 * @param {LoadOptions=} options Any additional options for the load.
 * @return {Promise} A promise that will resolve once `href` and its
 *     dependencies have been loaded and analyzed.
 */


Analyzer.analyze = function analyze(href, options) {
    options = options || {};
    options.filter = options.filter || _defaultFilter(href);
    var loader = new file_loader_1.FileLoader();
    var resolver = options.resolver;
    if (resolver === undefined) {
        if (typeof window === 'undefined') {
            resolver = 'fs';
        } else {
            resolver = 'xhr';
        }
    }
    var primaryResolver = undefined;
    if (resolver === 'fs') {
        primaryResolver = new fs_resolver_1.FSResolver(options);
    } else if (resolver === 'xhr') {
        primaryResolver = new xhr_resolver_1.XHRResolver(options);
    } else if (resolver === 'permissive') {
        primaryResolver = new error_swallowing_fs_resolver_1.ErrorSwallowingFSResolver(options);
    } else {
        throw new Error("Resolver must be one of 'fs', 'xhr', or 'permissive'");
    }
    loader.addResolver(primaryResolver);
    if (options.content) {
        loader.addResolver(new string_resolver_1.StringResolver({ url: href, content: options.content }));
    }
    loader.addResolver(new noop_resolver_1.NoopResolver({ test: options.filter }));
    var analyzer = new Analyzer(false, loader);
    return analyzer.metadataTree(href).then(function (root) {
        if (!options.noAnnotations) {
            analyzer.annotate();
        }
        if (options.clean) {
            analyzer.clean();
        }
        return Promise.resolve(analyzer);
    });
};
exports.Analyzer = Analyzer;
;
/**
 * @private
 * @param {string} href
 * @return {function(string): boolean}
 */
function _defaultFilter(href) {
    // Everything up to the last `/` or `\`.
    var base = href.match(/^(.*?)[^\/\\]*$/)[1];
    return function (uri) {
        return uri.indexOf(base) !== 0;
    };
}
function matchesDocumentFolder(descriptor, href) {
    if (!descriptor.contentHref) {
        return false;
    }
    var descriptorDoc = url.parse(descriptor.contentHref);
    if (!descriptorDoc || !descriptorDoc.pathname) {
        return false;
    }
    var searchDoc = url.parse(href);
    if (!searchDoc || !searchDoc.pathname) {
        return false;
    }
    var searchPath = searchDoc.pathname;
    var lastSlash = searchPath.lastIndexOf("/");
    if (lastSlash > 0) {
        searchPath = searchPath.slice(0, lastSlash);
    }
    return descriptorDoc.pathname.indexOf(searchPath) === 0;
}
// TODO(ajo): Refactor out of vulcanize into dom5.
var polymerExternalStyle = dom5.predicates.AND(dom5.predicates.hasTagName('link'), dom5.predicates.hasAttrValue('rel', 'import'), dom5.predicates.hasAttrValue('type', 'css'));
var externalScript = dom5.predicates.AND(dom5.predicates.hasTagName('script'), dom5.predicates.hasAttr('src'));
var isHtmlImportNode = dom5.predicates.AND(dom5.predicates.hasTagName('link'), dom5.predicates.hasAttrValue('rel', 'import'), dom5.predicates.NOT(dom5.predicates.hasAttrValue('type', 'css')));
function attachDomModule(parsedImport, element) {
    var domModules = parsedImport['dom-module'];
    var _iteratorNormalCompletion5 = true;
    var _didIteratorError5 = false;
    var _iteratorError5 = undefined;

    try {
        for (var _iterator5 = domModules[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
            var domModule = _step5.value;

            if (dom5.getAttribute(domModule, 'id') === element.is) {
                element.domModule = domModule;
                return;
            }
        }
    } catch (err) {
        _didIteratorError5 = true;
        _iteratorError5 = err;
    } finally {
        try {
            if (!_iteratorNormalCompletion5 && _iterator5.return) {
                _iterator5.return();
            }
        } finally {
            if (_didIteratorError5) {
                throw _iteratorError5;
            }
        }
    }
}
},{"./ast-utils/docs":6,"./ast-utils/import-parse":10,"./ast-utils/js-parse":11,"./loader/error-swallowing-fs-resolver":13,"./loader/file-loader":14,"./loader/fs-resolver":15,"./loader/noop-resolver":16,"./loader/string-resolver":19,"./loader/xhr-resolver":20,"dom5":227,"url":286}],2:[function(require,module,exports){
/**
 * @license
 * Copyright (c) 2015 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
 */
'use strict';

var esutil = require('./esutil');
var astValue = require('./ast-value');
function analyzeProperties(node) {
    var analyzedProps = [];
    if (node.type != 'ObjectExpression') {
        return analyzedProps;
    }
    var obEx = node;
    for (var i = 0; i < obEx.properties.length; i++) {
        var property = obEx.properties[i];
        var prop = esutil.toPropertyDescriptor(property);
        prop.published = true;
        if (property.value.type == 'ObjectExpression') {
            /**
             * Parse the expression inside a property object block. e.g.
             * property: {
             *   key: {
             *     type: String,
             *     notify: true,
             *     value: -1,
             *     readOnly: true,
             *     reflectToAttribute: true
             *   }
             * }
             */
            var propDescExpr = property.value;
            for (var j = 0; j < propDescExpr.properties.length; j++) {
                var propertyArg = propDescExpr.properties[j];
                var propertyKey = esutil.objectKeyToString(propertyArg.key);
                switch (propertyKey) {
                    case 'type':
                        {
                            prop.type = esutil.objectKeyToString(propertyArg.value);
                            if (prop.type === undefined) {
                                throw {
                                    message: 'Invalid type in property object.',
                                    location: propertyArg.loc.start
                                };
                            }
                        }
                        break;
                    case 'notify':
                        {
                            prop.notify = astValue.expressionToValue(propertyArg.value);
                            if (prop.notify === undefined) prop.notify = astValue.CANT_CONVERT;
                        }
                        break;
                    case 'observer':
                        {
                            prop.observer = astValue.expressionToValue(propertyArg.value);
                            prop.observerNode = propertyArg.value;
                            if (prop.observer === undefined) prop.observer = astValue.CANT_CONVERT;
                        }
                        break;
                    case 'readOnly':
                        {
                            prop.readOnly = astValue.expressionToValue(propertyArg.value);
                            if (prop.readOnly === undefined) prop.readOnly = astValue.CANT_CONVERT;
                        }
                        break;
                    case 'reflectToAttribute':
                        {
                            prop.reflectToAttribute = astValue.expressionToValue(propertyArg);
                            if (prop.reflectToAttribute === undefined) prop.reflectToAttribute = astValue.CANT_CONVERT;
                        }
                        break;
                    case 'value':
                        {
                            prop.default = astValue.expressionToValue(propertyArg.value);
                            if (prop.default === undefined) prop.default = astValue.CANT_CONVERT;
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        if (!prop.type) {
            throw {
                message: 'Unable to determine name for property key.',
                location: node.loc.start
            };
        }
        analyzedProps.push(prop);
    }
    return analyzedProps;
}
exports.analyzeProperties = analyzeProperties;
;
},{"./ast-value":3,"./esutil":8}],3:[function(require,module,exports){
/**
 * @license
 * Copyright (c) 2015 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
 */
'use strict';
// useful tool to visualize AST: http://esprima.org/demo/parse.html
/**
 * converts literal: {"type": "Literal", "value": 5,  "raw": "5" }
 * to string
 */

function literalToValue(literal) {
    return literal.value;
}
/**
 * converts unary to string
 */
function unaryToValue(unary) {
    var argValue = expressionToValue(unary.argument);
    if (argValue === undefined) return;
    return unary.operator + argValue;
}
/**
 * converts identifier to its value
 * identifier { "type": "Identifier", "name": "Number }
 */
function identifierToValue(identifier) {
    return identifier.name;
}
/**
 * Function is a block statement.
 */
function functionDeclarationToValue(fn) {
    if (fn.body.type == "BlockStatement") return blockStatementToValue(fn.body);
}
function functionExpressionToValue(fn) {
    if (fn.body.type == "BlockStatement") return blockStatementToValue(fn.body);
}
/**
 * Block statement: find last return statement, and return its value
 */
function blockStatementToValue(block) {
    for (var i = block.body.length - 1; i >= 0; i--) {
        if (block.body[i].type === "ReturnStatement") return returnStatementToValue(block.body[i]);
    }
}
/**
 * Evaluates return's argument
 */
function returnStatementToValue(ret) {
    return expressionToValue(ret.argument);
}
/**
 * Enclose containing values in []
 */
function arrayExpressionToValue(arry) {
    var value = '[';
    for (var i = 0; i < arry.elements.length; i++) {
        var v = expressionToValue(arry.elements[i]);
        if (v === undefined) continue;
        if (i !== 0) value += ', ';
        value += v;
    }
    value += ']';
    return value;
}
/**
 * Make it look like an object
 */
function objectExpressionToValue(obj) {
    var value = '{';
    for (var i = 0; i < obj.properties.length; i++) {
        var k = expressionToValue(obj.properties[i].key);
        var v = expressionToValue(obj.properties[i].value);
        if (v === undefined) continue;
        if (i !== 0) value += ', ';
        value += '"' + k + '": ' + v;
    }
    value += '}';
    return value;
}
/**
 * BinaryExpressions are of the form "literal" + "literal"
 */
function binaryExpressionToValue(member) {
    if (member.operator == "+") {
        // We need to cast to `any` here because, while it's usually not the right
        // thing to do to use '+' on two values of a mix of types because it's
        // unpredictable, that is what the original code we're evaluating does.
        return expressionToValue(member.left) + expressionToValue(member.right);
    }
    return;
}
/**
 * MemberExpression references a variable with name
 */
function memberExpressionToValue(member) {
    return expressionToValue(member.object) + "." + expressionToValue(member.property);
}
/**
 * Tries to get the value of an expression. Returns undefined on failure.
 */
function expressionToValue(valueExpression) {
    switch (valueExpression.type) {
        case 'Literal':
            return literalToValue(valueExpression);
        case 'UnaryExpression':
            return unaryToValue(valueExpression);
        case 'Identifier':
            return identifierToValue(valueExpression);
        case 'FunctionDeclaration':
            return functionDeclarationToValue(valueExpression);
        case 'FunctionExpression':
            return functionExpressionToValue(valueExpression);
        case 'ArrayExpression':
            return arrayExpressionToValue(valueExpression);
        case 'ObjectExpression':
            return objectExpressionToValue(valueExpression);
        case 'Identifier':
            return identifierToValue(valueExpression);
        case 'MemberExpression':
            return memberExpressionToValue(valueExpression);
        case 'BinaryExpression':
            return binaryExpressionToValue(valueExpression);
        default:
            return;
    }
}
exports.expressionToValue = expressionToValue;
exports.CANT_CONVERT = 'UNKNOWN';
},{}],4:[function(require,module,exports){
/**
 * @license
 * Copyright (c) 2015 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
 */
'use strict';

var docs = require('./docs');
var esutil = require('./esutil');
var jsdoc = require('./jsdoc');
var astValue = require('./ast-value');
var declaration_property_handlers_1 = require('./declaration-property-handlers');
function dedupe(array, keyFunc) {
    var bucket = {};
    array.forEach(function (el) {
        var key = keyFunc(el);
        if (key in bucket) {
            return;
        }
        bucket[key] = el;
    });
    var returned = [];
    Object.keys(bucket).forEach(function (k) {
        returned.push(bucket[k]);
    });
    return returned;
}
// TODO(rictic): turn this into a class.
function behaviorFinder() {
    /** The behaviors we've found. */
    var behaviors = [];
    var currentBehavior = null;
    var propertyHandlers = null;
    /**
     * merges behavior with preexisting behavior with the same name.
     * here to support multiple @polymerBehavior tags referring
     * to same behavior. See iron-multi-selectable for example.
     */
    function mergeBehavior(newBehavior) {
        var isBehaviorImpl = function isBehaviorImpl(b) {
            // filter out BehaviorImpl
            return b.indexOf(newBehavior.is) === -1;
        };
        for (var i = 0; i < behaviors.length; i++) {
            if (newBehavior.is !== behaviors[i].is) continue;
            // merge desc, longest desc wins
            if (newBehavior.desc) {
                if (behaviors[i].desc) {
                    if (newBehavior.desc.length > behaviors[i].desc.length) behaviors[i].desc = newBehavior.desc;
                } else {
                    behaviors[i].desc = newBehavior.desc;
                }
            }
            // merge demos
            behaviors[i].demos = (behaviors[i].demos || []).concat(newBehavior.demos || []);
            // merge events,
            behaviors[i].events = (behaviors[i].events || []).concat(newBehavior.events || []);
            behaviors[i].events = dedupe(behaviors[i].events, function (e) {
                return e.name;
            });
            // merge properties
            behaviors[i].properties = (behaviors[i].properties || []).concat(newBehavior.properties || []);
            // merge observers
            behaviors[i].observers = (behaviors[i].observers || []).concat(newBehavior.observers || []);
            // merge behaviors
            behaviors[i].behaviors = (behaviors[i].behaviors || []).concat(newBehavior.behaviors || []).filter(isBehaviorImpl);
            return behaviors[i];
        }
        return newBehavior;
    }
    /**
     * gets the expression representing a behavior from a node.
     */
    function behaviorExpression(node) {
        switch (node.type) {
            case 'ExpressionStatement':
                // need to cast to `any` here because ExpressionStatement is super
                // super general. this code is suspicious.
                return node.expression.right;
            case 'VariableDeclaration':
                var n = node;
                return n.declarations.length > 0 ? n.declarations[0].init : null;
        }
    }
    /**
     * checks whether an expression is a simple array containing only member
     * expressions or identifiers.
     */
    function isSimpleBehaviorArray(expression) {
        if (!expression || expression.type !== 'ArrayExpression') return false;
        var arrayExpr = expression;
        for (var i = 0; i < arrayExpr.elements.length; i++) {
            if (arrayExpr.elements[i].type !== 'MemberExpression' && arrayExpr.elements[i].type !== 'Identifier') {
                return false;
            }
        }
        return true;
    }
    var templatizer = "Polymer.Templatizer";
    function _parseChainedBehaviors(node) {
        // if current behavior is part of an array, it gets extended by other behaviors
        // inside the array. Ex:
        // Polymer.IronMultiSelectableBehavior = [ {....}, Polymer.IronSelectableBehavior]
        // We add these to behaviors array
        var expression = behaviorExpression(node);
        var chained = [];
        if (expression && expression.type === 'ArrayExpression') {
            var arrExpr = expression;
            for (var i = 0; i < arrExpr.elements.length; i++) {
                if (arrExpr.elements[i].type === 'MemberExpression' || arrExpr.elements[i].type === 'Identifier') {
                    chained.push(astValue.expressionToValue(arrExpr.elements[i]));
                }
            }
            if (chained.length > 0) currentBehavior.behaviors = chained;
        }
    }
    function _initBehavior(node, getName) {
        var comment = esutil.getAttachedComment(node);
        var symbol = getName();
        // Quickly filter down to potential candidates.
        if (!comment || comment.indexOf('@polymerBehavior') === -1) {
            if (symbol !== templatizer) {
                return;
            }
        }
        currentBehavior = {
            type: 'behavior',
            desc: comment,
            events: esutil.getEventComments(node).map(function (event) {
                return { desc: event };
            })
        };
        propertyHandlers = declaration_property_handlers_1.declarationPropertyHandlers(currentBehavior);
        docs.annotateBehavior(currentBehavior);
        // Make sure that we actually parsed a behavior tag!
        if (!jsdoc.hasTag(currentBehavior.jsdoc, 'polymerBehavior') && symbol !== templatizer) {
            currentBehavior = null;
            propertyHandlers = null;
            return;
        }
        var name = jsdoc.getTag(currentBehavior.jsdoc, 'polymerBehavior', 'name');
        currentBehavior.symbol = symbol;
        if (!name) {
            name = currentBehavior.symbol;
        }
        if (!name) {
            console.warn('Unable to determine name for @polymerBehavior:', comment);
        }
        currentBehavior.is = name;
        _parseChainedBehaviors(node);
        currentBehavior = mergeBehavior(currentBehavior);
        propertyHandlers = declaration_property_handlers_1.declarationPropertyHandlers(currentBehavior);
        // Some behaviors are just lists of other behaviors. If this is one then
        // add it to behaviors right away.
        if (isSimpleBehaviorArray(behaviorExpression(node))) {
            // TODO(ajo): Add a test to confirm the presence of `properties`
            if (!currentBehavior.observers) currentBehavior.observers = [];
            if (!currentBehavior.properties) currentBehavior.properties = [];
            if (behaviors.indexOf(currentBehavior) === -1) behaviors.push(currentBehavior);
            currentBehavior = null;
            propertyHandlers = null;
        }
    }
    var visitors = {
        /**
         * Look for object declarations with @behavior in the docs.
         */
        enterVariableDeclaration: function enterVariableDeclaration(node, parent) {
            if (node.declarations.length !== 1) return; // Ambiguous.
            _initBehavior(node, function () {
                return esutil.objectKeyToString(node.declarations[0].id);
            });
        },
        /**
         * Look for object assignments with @polymerBehavior in the docs.
         */
        enterAssignmentExpression: function enterAssignmentExpression(node, parent) {
            _initBehavior(parent, function () {
                return esutil.objectKeyToString(node.left);
            });
        },
        /**
         * We assume that the object expression after such an assignment is the
         * behavior's declaration. Seems to be a decent assumption for now.
         */
        enterObjectExpression: function enterObjectExpression(node, parent) {
            if (!currentBehavior || currentBehavior.properties) return;
            currentBehavior.properties = currentBehavior.properties || [];
            currentBehavior.observers = currentBehavior.observers || [];
            for (var i = 0; i < node.properties.length; i++) {
                var prop = node.properties[i];
                var name = esutil.objectKeyToString(prop.key);
                if (!name) {
                    throw {
                        message: 'Cant determine name for property key.',
                        location: node.loc.start
                    };
                }
                if (name in propertyHandlers) {
                    propertyHandlers[name](prop.value);
                } else {
                    currentBehavior.properties.push(esutil.toPropertyDescriptor(prop));
                }
            }
            behaviors.push(currentBehavior);
            currentBehavior = null;
        }
    };
    return { visitors: visitors, behaviors: behaviors };
}
exports.behaviorFinder = behaviorFinder;
;
},{"./ast-value":3,"./declaration-property-handlers":5,"./docs":6,"./esutil":8,"./jsdoc":12}],5:[function(require,module,exports){
/**
 * @license
 * Copyright (c) 2015 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
 */
'use strict';

var astValue = require('./ast-value');
var analyze_properties_1 = require('./analyze-properties');
/**
 * Returns an object containing functions that will annotate `declaration` with
 * the polymer-specificmeaning of the value nodes for the named properties.
 *
 * @param  {ElementDescriptor} declaration The descriptor to annotate.
 * @return {object.}      An object containing property
 *                                         handlers.
 */
function declarationPropertyHandlers(declaration) {
    return {
        is: function is(node) {
            if (node.type == 'Literal') {
                declaration.is = node.value.toString();
            }
        },
        properties: function properties(node) {
            var props = analyze_properties_1.analyzeProperties(node);
            for (var i = 0; i < props.length; i++) {
                declaration.properties.push(props[i]);
            }
        },
        behaviors: function behaviors(node) {
            if (node.type != 'ArrayExpression') {
                return;
            }
            var arrNode = node;
            var _iteratorNormalCompletion = true;
            var _didIteratorError = false;
            var _iteratorError = undefined;

            try {
                for (var _iterator = arrNode.elements[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                    var element = _step.value;

                    var v = astValue.expressionToValue(element);
                    if (v === undefined) {
                        v = astValue.CANT_CONVERT;
                    }
                    declaration.behaviors.push(v);
                }
            } catch (err) {
                _didIteratorError = true;
                _iteratorError = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion && _iterator.return) {
                        _iterator.return();
                    }
                } finally {
                    if (_didIteratorError) {
                        throw _iteratorError;
                    }
                }
            }
        },
        observers: function observers(node) {
            if (node.type != 'ArrayExpression') {
                return;
            }
            var arrNode = node;
            var _iteratorNormalCompletion2 = true;
            var _didIteratorError2 = false;
            var _iteratorError2 = undefined;

            try {
                for (var _iterator2 = arrNode.elements[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                    var element = _step2.value;

                    var v = astValue.expressionToValue(element);
                    if (v === undefined) v = astValue.CANT_CONVERT;
                    declaration.observers.push({
                        javascriptNode: element,
                        expression: v
                    });
                }
            } catch (err) {
                _didIteratorError2 = true;
                _iteratorError2 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion2 && _iterator2.return) {
                        _iterator2.return();
                    }
                } finally {
                    if (_didIteratorError2) {
                        throw _iteratorError2;
                    }
                }
            }
        }
    };
}
exports.declarationPropertyHandlers = declarationPropertyHandlers;
},{"./analyze-properties":2,"./ast-value":3}],6:[function(require,module,exports){
/**
 * @license
 * Copyright (c) 2015 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
 */
'use strict';

var jsdoc = require('./jsdoc');
var dom5 = require('dom5');
/** Properties on element prototypes that are purely configuration. */
var ELEMENT_CONFIGURATION = ['attached', 'attributeChanged', 'beforeRegister', 'configure', 'constructor', 'created', 'detached', 'enableCustomStyleProperties', 'extends', 'hostAttributes', 'is', 'listeners', 'mixins', 'properties', 'ready', 'registered'];
/** Tags understood by the annotation process, to be removed during `clean`. */
var HANDLED_TAGS = ['param', 'return', 'type'];
/**
 * Annotates Hydrolysis descriptors, processing any `desc` properties as JSDoc.
 *
 * You probably want to use a more specialized version of this, such as
 * `annotateElement`.
 *
 * Processed JSDoc values will be made available via the `jsdoc` property on a
 * descriptor node.
 *
 * @param {Object} descriptor The descriptor node to process.
 * @return {Object} The descriptor that was given.
 */
function annotate(descriptor) {
    if (!descriptor || descriptor.jsdoc) return descriptor;
    if (typeof descriptor.desc === 'string') {
        descriptor.jsdoc = jsdoc.parseJsdoc(descriptor.desc);
        // We want to present the normalized form of a descriptor.
        descriptor.jsdoc.orig = descriptor.desc;
        descriptor.desc = descriptor.jsdoc.description;
    }
    return descriptor;
}
exports.annotate = annotate;
/**
 * Annotates @event, @hero, & @demo tags
 */
function annotateElementHeader(descriptor) {
    if (descriptor.events) {
        descriptor.events.forEach(function (event) {
            _annotateEvent(event);
        });
        descriptor.events.sort(function (a, b) {
            return a.name.localeCompare(b.name);
        });
    }
    descriptor.demos = [];
    if (descriptor.jsdoc && descriptor.jsdoc.tags) {
        descriptor.jsdoc.tags.forEach(function (tag) {
            switch (tag.tag) {
                case 'hero':
                    descriptor.hero = tag.name || 'hero.png';
                    break;
                case 'demo':
                    descriptor.demos.push({
                        desc: tag.description || 'demo',
                        path: tag.name || 'demo/index.html'
                    });
                    break;
            }
        });
    }
}
exports.annotateElementHeader = annotateElementHeader;
function copyProperties(from, to, behaviorsByName) {
    if (from.properties) {
        from.properties.forEach(function (fromProp) {
            for (var toProp, i = 0; i < to.properties.length; i++) {
                toProp = to.properties[i];
                if (fromProp.name === toProp.name) {
                    return;
                }
            }
            var newProp = { __fromBehavior: from.is };
            if (fromProp.__fromBehavior) {
                return;
            }
            Object.keys(fromProp).forEach(function (propertyField) {
                newProp[propertyField] = fromProp[propertyField];
            });
            to.properties.push(newProp);
        });
        from.events.forEach(function (fromEvent) {
            for (var toEvent, i = 0; i < to.events.length; i++) {
                toEvent = to.events[i];
                if (fromEvent.name === toEvent.name) {
                    return;
                }
            }
            if (fromEvent.__fromBehavior) {
                return;
            }
            var newEvent = { __fromBehavior: from.is };
            Object.keys(fromEvent).forEach(function (eventField) {
                newEvent[eventField] = fromEvent[eventField];
            });
            to.events.push(newEvent);
        });
    }
    if (!from.behaviors) {
        return;
    }
    for (var i = from.behaviors.length - 1; i >= 0; i--) {
        // TODO: what's up with behaviors sometimes being a literal, and sometimes
        // being a descriptor object?
        var localBehavior = from.behaviors[i];
        var definedBehavior = behaviorsByName[localBehavior] || behaviorsByName[localBehavior.symbol];
        if (!definedBehavior) {
            console.warn("Behavior " + localBehavior + " not found when mixing " + "properties into " + to.is + "!");
            return;
        }
        copyProperties(definedBehavior, to, behaviorsByName);
    }
}
function mixinBehaviors(descriptor, behaviorsByName) {
    if (descriptor.behaviors) {
        for (var i = descriptor.behaviors.length - 1; i >= 0; i--) {
            var behavior = descriptor.behaviors[i];
            if (!behaviorsByName[behavior]) {
                console.warn("Behavior " + behavior + " not found when mixing " + "properties into " + descriptor.is + "!");
                break;
            }
            var definedBehavior = behaviorsByName[behavior];
            copyProperties(definedBehavior, descriptor, behaviorsByName);
        }
    }
}
/**
 * Annotates documentation found within a Hydrolysis element descriptor. Also
 * supports behaviors.
 *
 * If the element was processed via `hydrolize`, the element's documentation
 * will also be extracted via its .
 *
 * @param {Object} descriptor The element descriptor.
 * @return {Object} The descriptor that was given.
 */
function annotateElement(descriptor, behaviorsByName) {
    if (!descriptor.desc && descriptor.type === 'element') {
        descriptor.desc = _findElementDocs(descriptor.is, descriptor.domModule, descriptor.scriptElement);
    }
    annotate(descriptor);
    // The `` is too low level for most needs, and it is _not_
    // serializable. So we drop it now that we've extracted all the useful bits
    // from it.
    // TODO: Don't worry about serializability here, provide an API to get JSON.
    delete descriptor.domModule;
    mixinBehaviors(descriptor, behaviorsByName);
    // Descriptors that should have their `desc` properties parsed as JSDoc.
    descriptor.properties.forEach(function (property) {
        // Feature properties are special, configuration is really just a matter of
        // inheritance...
        annotateProperty(property, descriptor.abstract);
    });
    // It may seem like overkill to always sort, but we have an assumption that
    // these properties are typically being consumed by user-visible tooling.
    // As such, it's good to have consistent output/ordering to aid the user.
    descriptor.properties.sort(function (a, b) {
        // Private properties are always last.
        if (a.private && !b.private) {
            return 1;
        } else if (!a.private && b.private) {
            return -1;
        } else {
            return a.name.localeCompare(b.name);
        }
    });
    annotateElementHeader(descriptor);
    return descriptor;
}
exports.annotateElement = annotateElement;
/**
 * Annotates behavior descriptor.
 * @param {Object} descriptor behavior descriptor
 * @return {Object} descriptor passed in as param
 */
function annotateBehavior(descriptor) {
    annotate(descriptor);
    annotateElementHeader(descriptor);
    return descriptor;
}
exports.annotateBehavior = annotateBehavior;
/**
 * Annotates event documentation
 */
function _annotateEvent(descriptor) {
    annotate(descriptor);
    // process @event
    var eventTag = jsdoc.getTag(descriptor.jsdoc, 'event');
    descriptor.name = eventTag ? eventTag.description : "N/A";
    // process @params
    descriptor.params = (descriptor.jsdoc.tags || []).filter(function (tag) {
        return tag.tag === 'param';
    }).map(function (tag) {
        return {
            type: tag.type || "N/A",
            desc: tag.description,
            name: tag.name || "N/A"
        };
    });
    // process @params
    return descriptor;
}
/**
 * Annotates documentation found about a Hydrolysis property descriptor.
 *
 * @param {Object} descriptor The property descriptor.
 * @param {boolean} ignoreConfiguration If true, `configuration` is not set.
 * @return {Object} The descriptior that was given.
 */
function annotateProperty(descriptor, ignoreConfiguration) {
    annotate(descriptor);
    if (descriptor.name[0] === '_' || jsdoc.hasTag(descriptor.jsdoc, 'private')) {
        descriptor.private = true;
    }
    if (!ignoreConfiguration && ELEMENT_CONFIGURATION.indexOf(descriptor.name) !== -1) {
        descriptor.private = true;
        descriptor.configuration = true;
    }
    // @type JSDoc wins
    descriptor.type = jsdoc.getTag(descriptor.jsdoc, 'type', 'type') || descriptor.type;
    if (descriptor.type.match(/^function/i)) {
        _annotateFunctionProperty(descriptor);
    }
    // @default JSDoc wins
    var defaultTag = jsdoc.getTag(descriptor.jsdoc, 'default');
    if (defaultTag !== null) {
        var newDefault = (defaultTag.name || '') + (defaultTag.description || '');
        if (newDefault !== '') {
            descriptor.default = newDefault;
        }
    }
    return descriptor;
}
function _annotateFunctionProperty(descriptor) {
    descriptor.function = true;
    var returnTag = jsdoc.getTag(descriptor.jsdoc, 'return');
    if (returnTag) {
        descriptor.return = {
            type: returnTag.type,
            desc: returnTag.description
        };
    }
    var paramsByName = {};
    (descriptor.params || []).forEach(function (param) {
        paramsByName[param.name] = param;
    });
    (descriptor.jsdoc && descriptor.jsdoc.tags || []).forEach(function (tag) {
        if (tag.tag !== 'param') return;
        var param = paramsByName[tag.name];
        if (!param) {
            return;
        }
        param.type = tag.type || param.type;
        param.desc = tag.description;
    });
}
/**
 * Converts raw features into an abstract `Polymer.Base` element.
 *
 * Note that docs on this element _are not processed_. You must call
 * `annotateElement` on it yourself if you wish that.
 *
 * @param {Array} features
 * @return {ElementDescriptor}
 */
function featureElement(features) {
    var properties = features.reduce(function (result, feature) {
        return result.concat(feature.properties);
    }, []);
    return {
        type: 'element',
        is: 'Polymer.Base',
        abstract: true,
        properties: properties,
        desc: '`Polymer.Base` acts as a base prototype for all Polymer ' + 'elements. It is composed via various calls to ' + '`Polymer.Base._addFeature()`.\n' + '\n' + 'The properties reflected here are the combined view of all ' + 'features found in this library. There may be more properties ' + 'added via other libraries, as well.'
    };
}
exports.featureElement = featureElement;
/**
 * Cleans redundant properties from a descriptor, assuming that you have already
 * called `annotate`.
 *
 * @param {Object} descriptor
 */
function clean(descriptor) {
    if (!descriptor.jsdoc) return;
    // The doctext was written to `descriptor.desc`
    delete descriptor.jsdoc.description;
    delete descriptor.jsdoc.orig;
    var cleanTags = [];
    (descriptor.jsdoc.tags || []).forEach(function (tag) {
        // Drop any tags we've consumed.
        if (HANDLED_TAGS.indexOf(tag.tag) !== -1) return;
        cleanTags.push(tag);
    });
    if (cleanTags.length === 0) {
        // No tags? no docs left!
        delete descriptor.jsdoc;
    } else {
        descriptor.jsdoc.tags = cleanTags;
    }
}
exports.clean = clean;
/**
 * Cleans redundant properties from an element, assuming that you have already
 * called `annotateElement`.
 *
 * @param {ElementDescriptor|BehaviorDescriptor} element
 */
function cleanElement(element) {
    clean(element);
    element.properties.forEach(cleanProperty);
}
exports.cleanElement = cleanElement;
/**
 * Cleans redundant properties from a property, assuming that you have already
 * called `annotateProperty`.
 *
 * @param {PropertyDescriptor} property
 */
function cleanProperty(property) {
    clean(property);
}
/**
 * Parse elements defined only in comments.
 * @param  {comments} Array A list of comments to parse.
 * @return {ElementDescriptor}      A list of pseudo-elements.
 */
function parsePseudoElements(comments) {
    var elements = [];
    comments.forEach(function (comment) {
        var parsedJsdoc = jsdoc.parseJsdoc(comment);
        var pseudoTag = jsdoc.getTag(parsedJsdoc, 'pseudoElement', 'name');
        if (pseudoTag) {
            var element = {
                is: pseudoTag,
                type: 'element',
                jsdoc: { description: parsedJsdoc.description, tags: parsedJsdoc.tags },
                properties: [],
                desc: parsedJsdoc.description
            };
            annotateElementHeader(element);
            elements.push(element);
        }
    });
    return elements;
}
exports.parsePseudoElements = parsePseudoElements;
/**
 * @param {string} elementId
 * @param {DocumentAST} domModule
 * @param {DocumentAST} scriptElement The script that the element was
 *     defined in.
 */
function _findElementDocs(elementId, domModule, scriptElement) {
    // Note that we concatenate docs from all sources if we find them.
    // element can be defined in:
    // html comment right before dom-module
    // html commnet right before script defining the module,
    // if dom-module is empty
    var found = [];
    // Do we have a HTML comment on the `` or `