UNPKG

mini-program-cljs

Version:

1 lines 162 kB
["^ ","~:foreign-libs",[],"~:externs",[],"~:resources",[["^ ","~:cache-key",[1569048148000],"~:output-name","goog.svgpan.svgpan.js","~:resource-id",["~:shadow.build.classpath/resource","goog/svgpan/svgpan.js"],"~:resource-name","goog/svgpan/svgpan.js","~:type","~:goog","~:source","/**\n *  SVGPan library 1.2.2\n * ======================\n *\n * Given an unique existing element with a given id (or by default, the first\n * g-element), including the library into any SVG adds the following\n * capabilities:\n *\n *  - Mouse panning\n *  - Mouse zooming (using the wheel)\n *  - Object dragging\n *\n * You can configure the behaviour of the pan/zoom/drag via setOptions().\n *\n * Known issues:\n *\n *  - Zooming (while panning) on Safari has still some issues\n *\n * Releases:\n *\n * 1.2.2, Tue Aug 30 17:21:56 CEST 2011, Andrea Leofreddi\n *  - Fixed viewBox on root tag (#7)\n *  - Improved zoom speed (#2)\n *\n * 1.2.1, Mon Jul  4 00:33:18 CEST 2011, Andrea Leofreddi\n *  - Fixed a regression with mouse wheel (now working on Firefox 5)\n *  - Working with viewBox attribute (#4)\n *  - Added \"use strict;\" and fixed resulting warnings (#5)\n *  - Added configuration variables, dragging is disabled by default (#3)\n *\n * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui\n *  Fixed a bug with browser mouse handler interaction\n *\n * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui\n *  Updated the zoom code to support the mouse wheel on Safari/Chrome\n *\n * 1.0, Andrea Leofreddi\n *  First release\n */\n\n/**\n * @license\n * This code is licensed under the following BSD license:\n * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights\n * reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *    1. Redistributions of source code must retain the above copyright notice,\n *       this list of conditions and the following disclaimer.\n *\n *    2. Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n * EVENT SHALL Andrea Leofreddi OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation are\n * those of the authors and should not be interpreted as representing official\n * policies, either expressed or implied, of Andrea Leofreddi.\n *\n */\n\ngoog.provide('svgpan.SvgPan');\n\ngoog.require('goog.Disposable');\ngoog.require('goog.events');\ngoog.require('goog.events.EventType');\ngoog.require('goog.events.MouseWheelHandler');\n\n\n\n/**\n * Instantiates an SvgPan object.\n * @param {string=} opt_graphElementId The id of the graph element.\n * @param {Element=} opt_root An optional document root.\n * @constructor\n * @extends {goog.Disposable}\n */\nsvgpan.SvgPan = function(opt_graphElementId, opt_root) {\n  svgpan.SvgPan.base(this, 'constructor');\n\n  /** @private {Element} */\n  this.root_ = opt_root || document.documentElement;\n\n  /** @private {?string} */\n  this.graphElementId_ = opt_graphElementId || null;\n\n  /** @private {boolean} */\n  this.cancelNextClick_ = false;\n\n  /** @private {boolean} */\n  this.enablePan_ = true;\n\n  /** @private {boolean} */\n  this.enableZoom_ = true;\n\n  /** @private {boolean} */\n  this.enableDrag_ = false;\n\n  /** @private {number} */\n  this.zoomScale_ = 0.4;\n\n  /** @private {svgpan.SvgPan.State} */\n  this.state_ = svgpan.SvgPan.State.NONE;\n\n  /** @private {Element} */\n  this.svgRoot_ = null;\n\n  /** @private {Element} */\n  this.stateTarget_ = null;\n\n  /** @private {SVGPoint} */\n  this.stateOrigin_ = null;\n\n  /** @private {SVGMatrix} */\n  this.stateTf_ = null;\n\n  /** @private {goog.events.MouseWheelHandler} */\n  this.mouseWheelHandler_ = null;\n\n  this.setupHandlers_();\n};\ngoog.inherits(svgpan.SvgPan, goog.Disposable);\n\n\n/** @override */\nsvgpan.SvgPan.prototype.disposeInternal = function() {\n  svgpan.SvgPan.base(this, 'disposeInternal');\n  goog.events.removeAll(this.root_);\n  this.mouseWheelHandler_.dispose();\n};\n\n\n/**\n * @enum {string}\n */\nsvgpan.SvgPan.State = {\n  NONE: 'none',\n  PAN: 'pan',\n  DRAG: 'drag'\n};\n\n\n/**\n * Enables/disables panning the entire SVG (default = true).\n * @param {boolean} enabled Whether or not to allow panning.\n */\nsvgpan.SvgPan.prototype.setPanEnabled = function(enabled) {\n  this.enablePan_ = enabled;\n};\n\n\n/**\n * Enables/disables zooming (default = true).\n * @param {boolean} enabled Whether or not to allow zooming (default = true).\n */\nsvgpan.SvgPan.prototype.setZoomEnabled = function(enabled) {\n  this.enableZoom_ = enabled;\n};\n\n\n/**\n * Enables/disables dragging individual SVG objects (default = false).\n * @param {boolean} enabled Whether or not to allow dragging of objects.\n */\nsvgpan.SvgPan.prototype.setDragEnabled = function(enabled) {\n  this.enableDrag_ = enabled;\n};\n\n\n/**\n * Sets the sensitivity of mousewheel zooming (default = 0.4).\n * @param {number} scale The new zoom scale.\n */\nsvgpan.SvgPan.prototype.setZoomScale = function(scale) {\n  this.zoomScale_ = scale;\n};\n\n\n/**\n * Registers mouse event handlers.\n * @private\n */\nsvgpan.SvgPan.prototype.setupHandlers_ = function() {\n  goog.events.listen(this.root_, goog.events.EventType.CLICK,\n      goog.bind(this.handleMouseClick_, this));\n  goog.events.listen(this.root_, goog.events.EventType.MOUSEUP,\n      goog.bind(this.handleMouseUp_, this));\n  goog.events.listen(this.root_, goog.events.EventType.MOUSEDOWN,\n      goog.bind(this.handleMouseDown_, this));\n  goog.events.listen(this.root_, goog.events.EventType.MOUSEMOVE,\n      goog.bind(this.handleMouseMove_, this));\n  this.mouseWheelHandler_ = new goog.events.MouseWheelHandler(this.root_);\n  goog.events.listen(this.mouseWheelHandler_,\n      goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,\n      goog.bind(this.handleMouseWheel_, this));\n};\n\n\n/**\n * Retrieves the root element for SVG manipulation. The element is then cached.\n * @param {Document} svgDoc The document.\n * @return {Element} The svg root.\n * @private\n */\nsvgpan.SvgPan.prototype.getRoot_ = function(svgDoc) {\n  if (!this.svgRoot_) {\n    var r = this.graphElementId_ ?\n        svgDoc.getElementById(this.graphElementId_) : svgDoc.documentElement;\n    var t = r;\n    while (t != svgDoc) {\n      if (t.getAttribute('viewBox')) {\n        this.setCtm_(r, r.getCTM());\n        t.removeAttribute('viewBox');\n      }\n      t = t.parentNode;\n    }\n    this.svgRoot_ = r;\n  }\n  return this.svgRoot_;\n};\n\n\n/**\n * Instantiates an SVGPoint object with given event coordinates.\n * @param {!goog.events.Event} evt The event with coordinates.\n * @return {SVGPoint} The created point.\n * @private\n */\nsvgpan.SvgPan.prototype.getEventPoint_ = function(evt) {\n  return this.newPoint_(evt.clientX, evt.clientY);\n};\n\n\n/**\n * Instantiates an SVGPoint object with given coordinates.\n * @param {number} x The x coordinate.\n * @param {number} y The y coordinate.\n * @return {SVGPoint} The created point.\n * @private\n */\nsvgpan.SvgPan.prototype.newPoint_ = function(x, y) {\n  var p = this.root_.createSVGPoint();\n  p.x = x;\n  p.y = y;\n  return p;\n};\n\n\n/**\n * Sets the current transform matrix of an element.\n * @param {Element} element The element.\n * @param {SVGMatrix} matrix The transform matrix.\n * @private\n */\nsvgpan.SvgPan.prototype.setCtm_ = function(element, matrix) {\n  var s = 'matrix(' + matrix.a + ',' + matrix.b + ',' + matrix.c + ',' +\n      matrix.d + ',' + matrix.e + ',' + matrix.f + ')';\n  element.setAttribute('transform', s);\n};\n\n\n/**\n * Handle mouse wheel event.\n * @param {!goog.events.Event} evt The event.\n * @private\n */\nsvgpan.SvgPan.prototype.handleMouseWheel_ = function(evt) {\n  if (!this.enableZoom_)\n    return;\n\n  // Prevents scrolling.\n  evt.preventDefault();\n\n  var svgDoc = evt.target.ownerDocument;\n\n  var delta = evt.deltaY / -9;\n  var z = Math.pow(1 + this.zoomScale_, delta);\n  var g = this.getRoot_(svgDoc);\n  var p = this.getEventPoint_(evt);\n  p = p.matrixTransform(g.getCTM().inverse());\n\n  // Compute new scale matrix in current mouse position\n  var k = this.root_.createSVGMatrix().translate(\n      p.x, p.y).scale(z).translate(-p.x, -p.y);\n  this.setCtm_(g, g.getCTM().multiply(k));\n\n  if (typeof(this.stateTf_) == 'undefined') {\n    this.stateTf_ = g.getCTM().inverse();\n  }\n  this.stateTf_ =\n      this.stateTf_ ? this.stateTf_.multiply(k.inverse()) : this.stateTf_;\n};\n\n\n/**\n * Handle mouse move event.\n * @param {!goog.events.Event} evt The event.\n * @private\n */\nsvgpan.SvgPan.prototype.handleMouseMove_ = function(evt) {\n  if (evt.button != 0) {\n    return;\n  }\n  this.handleMove(evt.clientX, evt.clientY, evt.target.ownerDocument);\n};\n\n\n/**\n * Handles mouse motion for the given coordinates.\n * @param {number} x The x coordinate.\n * @param {number} y The y coordinate.\n * @param {Document} svgDoc The svg document.\n */\nsvgpan.SvgPan.prototype.handleMove = function(x, y, svgDoc) {\n  var g = this.getRoot_(svgDoc);\n  if (this.state_ == svgpan.SvgPan.State.PAN && this.enablePan_) {\n    // Pan mode\n    var p = this.newPoint_(x, y).matrixTransform(\n        /** @type {!SVGMatrix} */ (this.stateTf_));\n    this.setCtm_(g, this.stateTf_.inverse().translate(\n        p.x - this.stateOrigin_.x, p.y - this.stateOrigin_.y));\n    this.cancelNextClick_ = true;\n  } else if (this.state_ == svgpan.SvgPan.State.DRAG && this.enableDrag_) {\n    // Drag mode\n    var p = this.newPoint_(x, y).matrixTransform(g.getCTM().inverse());\n    this.setCtm_(this.stateTarget_, this.root_.createSVGMatrix().translate(\n        p.x - this.stateOrigin_.x, p.y - this.stateOrigin_.y).multiply(\n        g.getCTM().inverse()).multiply(this.stateTarget_.getCTM()));\n    this.stateOrigin_ = p;\n  }\n};\n\n\n/**\n * Handle click event.\n * @param {!goog.events.Event} evt The event.\n * @private\n */\nsvgpan.SvgPan.prototype.handleMouseDown_ = function(evt) {\n  if (evt.button != 0) {\n    return;\n  }\n  // Prevent selection while dragging.\n  evt.preventDefault();\n  var svgDoc = evt.target.ownerDocument;\n\n  var g = this.getRoot_(svgDoc);\n\n  if (evt.target.tagName == 'svg' || !this.enableDrag_) {\n    // Pan mode\n    this.state_ = svgpan.SvgPan.State.PAN;\n    this.stateTf_ = g.getCTM().inverse();\n    this.stateOrigin_ = this.getEventPoint_(evt).matrixTransform(\n        /** @type {!SVGMatrix} */ (this.stateTf_));\n  } else {\n    // Drag mode\n    this.state_ = svgpan.SvgPan.State.DRAG;\n    this.stateTarget_ = /** @type {Element} */ (evt.target);\n    this.stateTf_ = g.getCTM().inverse();\n    this.stateOrigin_ = this.getEventPoint_(evt).matrixTransform(\n        /** @type {!SVGMatrix} */ (this.stateTf_));\n  }\n};\n\n\n/**\n * Handle mouse button release event.\n * @param {!goog.events.Event} evt The event.\n * @private\n */\nsvgpan.SvgPan.prototype.handleMouseUp_ = function(evt) {\n  if (this.state_ != svgpan.SvgPan.State.NONE) {\n    this.endPanOrDrag();\n  }\n};\n\n\n/**\n * Ends pan/drag mode.\n */\nsvgpan.SvgPan.prototype.endPanOrDrag = function() {\n  if (this.state_ != svgpan.SvgPan.State.NONE) {\n    this.state_ = svgpan.SvgPan.State.NONE;\n  }\n};\n\n\n/**\n * Handle mouse clicks.\n * @param {!goog.events.Event} evt The event.\n * @private\n */\nsvgpan.SvgPan.prototype.handleMouseClick_ = function(evt) {\n  // We only set cancelNextClick_ after panning occurred, and use it to prevent\n  // the default action that would otherwise take place when clicking on the\n  // element (for instance, navigation on clickable links, but also any click\n  // handler that may be set on an SVG element, in the case of active SVG\n  // content)\n  if (this.cancelNextClick_) {\n    // Cancel potential click handler on active SVG content.\n    evt.stopPropagation();\n    // Cancel navigation when panning on clickable links.\n    evt.preventDefault();\n  }\n  this.cancelNextClick_ = false;\n};\n\n\n/**\n * Returns the current state.\n * @return {!svgpan.SvgPan.State}\n */\nsvgpan.SvgPan.prototype.getState = function() {\n  return this.state_;\n};\n","~:last-modified",1569048148000,"~:requires",["~#set",["~$goog","~$goog.events.EventType","~$goog.events.MouseWheelHandler","~$goog.Disposable","~$goog.events"]],"~:pom-info",["^ ","~:description","\n        The Google Closure Library is a collection of JavaScript code\n        designed for use with the Google Closure JavaScript Compiler.\n\n        This non-official distribution was prepared by the ClojureScript\n        team at http://clojure.org/\n\n        This package contains extensions to the Google Closure Library\n        using third-party components, which may be distributed under\n        licenses other than the Apache license. Licenses for individual\n        library components may be found in source-code comments.\n    ","~:group-id","~$org.clojure","~:artifact-id","~$google-closure-library-third-party","~:name","Google Closure Library Third-Party Extensions","~:id","~$org.clojure/google-closure-library-third-party","~:url","http://code.google.com/p/closure-library/","~:parent-group-id","~$org.sonatype.oss","~:coordinate",["^K","0.0-20190213-2033d5d9"],"~:version","0.0-20190213-2033d5d9"],"^L",["~#url","jar:file:/Users/clojure/.m2/repository/org/clojure/google-closure-library-third-party/0.0-20190213-2033d5d9/google-closure-library-third-party-0.0-20190213-2033d5d9.jar!/goog/svgpan/svgpan.js"],"~:provides",["^=",["~$svgpan.SvgPan"]],"~:from-jar",true,"~:deps",["^>","^A","^B","^?","^@"]],["^ ","^3",[1569048148000],"^4","goog.mochikit.async.deferredlist.js","^5",["^6","goog/mochikit/async/deferredlist.js"],"^7","goog/mochikit/async/deferredlist.js","^8","^9","^:","// Copyright 2005 Bob Ippolito. All Rights Reserved.\n// Modifications Copyright 2009 The Closure Library Authors.\n// All Rights Reserved.\n\n/**\n * Portions of this code are from MochiKit, received by The Closure\n * Library Authors under the MIT license. All other code is Copyright\n * 2005-2009 The Closure Library Authors. All Rights Reserved.\n */\n\n/**\n * @fileoverview Class for tracking multiple asynchronous operations and\n * handling the results. The DeferredList object here is patterned after the\n * DeferredList object in the Twisted python networking framework.\n *\n * Based on the MochiKit code.\n *\n * See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html\n *\n * @author brenneman@google.com (Shawn Brenneman)\n */\n\ngoog.provide('goog.async.DeferredList');\n\ngoog.require('goog.async.Deferred');\n\n\n\n/**\n * Constructs an object that waits on the results of multiple asynchronous\n * operations and marshals the results. It is itself a <code>Deferred</code>,\n * and may have an execution sequence of callback functions added to it. Each\n * <code>DeferredList</code> instance is single use and may be fired only once.\n *\n * The default behavior of a <code>DeferredList</code> is to wait for a success\n * or error result from every <code>Deferred</code> in its input list. Once\n * every result is available, the <code>DeferredList</code>'s execution sequence\n * is fired with a list of <code>[success, result]</code> array pairs, where\n * <code>success</code> is a boolean indicating whether <code>result</code> was\n * the product of a callback or errback. The list's completion criteria and\n * result list may be modified by setting one or more of the boolean options\n * documented below.\n *\n * <code>Deferred</code> instances passed into a <code>DeferredList</code> are\n * independent, and may have additional callbacks and errbacks added to their\n * execution sequences after they are passed as inputs to the list.\n *\n * @param {!Array<!goog.async.Deferred>} list An array of deferred results to\n *     wait for.\n * @param {boolean=} opt_fireOnOneCallback Whether to stop waiting as soon as\n *     one input completes successfully. In this case, the\n *     <code>DeferredList</code>'s callback chain will be called with a two\n *     element array, <code>[index, result]</code>, where <code>index</code>\n *     identifies which input <code>Deferred</code> produced the successful\n *     <code>result</code>.\n * @param {boolean=} opt_fireOnOneErrback Whether to stop waiting as soon as one\n *     input reports an error. The failing result is passed to the\n *     <code>DeferredList</code>'s errback sequence.\n * @param {boolean=} opt_consumeErrors When true, any errors fired by a\n *     <code>Deferred</code> in the input list will be captured and replaced\n *     with a succeeding null result. Any callbacks added to the\n *     <code>Deferred</code> after its use in the <code>DeferredList</code> will\n *     receive null instead of the error.\n * @param {Function=} opt_canceler A function that will be called if the\n *     <code>DeferredList</code> is canceled. @see goog.async.Deferred#cancel\n * @param {Object=} opt_defaultScope The default scope to invoke callbacks or\n *     errbacks in.\n * @constructor\n * @extends {goog.async.Deferred}\n */\ngoog.async.DeferredList = function(\n    list, opt_fireOnOneCallback, opt_fireOnOneErrback, opt_consumeErrors,\n    opt_canceler, opt_defaultScope) {\n\n  goog.async.DeferredList.base(this, 'constructor',\n      opt_canceler, opt_defaultScope);\n\n  /**\n   * The list of Deferred objects to wait for.\n   * @const {!Array<!goog.async.Deferred>}\n   * @private\n   */\n  this.list_ = list;\n\n  /**\n   * The stored return values of the Deferred objects.\n   * @const {!Array}\n   * @private\n   */\n  this.deferredResults_ = [];\n\n  /**\n   * Whether to fire on the first successful callback instead of waiting for\n   * every Deferred to complete.\n   * @const {boolean}\n   * @private\n   */\n  this.fireOnOneCallback_ = !!opt_fireOnOneCallback;\n\n  /**\n   * Whether to fire on the first error result received instead of waiting for\n   * every Deferred to complete.\n   * @const {boolean}\n   * @private\n   */\n  this.fireOnOneErrback_ = !!opt_fireOnOneErrback;\n\n  /**\n   * Whether to stop error propagation on the input Deferred objects. If the\n   * DeferredList sees an error from one of the Deferred inputs, the error will\n   * be captured, and the Deferred will be returned to success state with a null\n   * return value.\n   * @const {boolean}\n   * @private\n   */\n  this.consumeErrors_ = !!opt_consumeErrors;\n\n  /**\n   * The number of input deferred objects that have fired.\n   * @private {number}\n   */\n  this.numFinished_ = 0;\n\n  for (var i = 0; i < list.length; i++) {\n    var d = list[i];\n    d.addCallbacks(goog.bind(this.handleCallback_, this, i, true),\n                   goog.bind(this.handleCallback_, this, i, false));\n  }\n\n  if (list.length == 0 && !this.fireOnOneCallback_) {\n    this.callback(this.deferredResults_);\n  }\n};\ngoog.inherits(goog.async.DeferredList, goog.async.Deferred);\n\n\n/**\n * Registers the result from an input deferred callback or errback. The result\n * is returned and may be passed to additional handlers in the callback chain.\n *\n * @param {number} index The index of the firing deferred object in the input\n *     list.\n * @param {boolean} success Whether the result is from a callback or errback.\n * @param {*} result The result of the callback or errback.\n * @return {*} The result, to be handled by the next handler in the deferred's\n *     callback chain (if any). If consumeErrors is set, an error result is\n *     replaced with null.\n * @private\n */\ngoog.async.DeferredList.prototype.handleCallback_ = function(\n    index, success, result) {\n\n  this.numFinished_++;\n  this.deferredResults_[index] = [success, result];\n\n  if (!this.hasFired()) {\n    if (this.fireOnOneCallback_ && success) {\n      this.callback([index, result]);\n    } else if (this.fireOnOneErrback_ && !success) {\n      this.errback(result);\n    } else if (this.numFinished_ == this.list_.length) {\n      this.callback(this.deferredResults_);\n    }\n  }\n\n  if (this.consumeErrors_ && !success) {\n    result = null;\n  }\n\n  return result;\n};\n\n\n/** @override */\ngoog.async.DeferredList.prototype.errback = function(res) {\n  goog.async.DeferredList.base(this, 'errback', res);\n\n  // On error, cancel any pending requests.\n  for (var i = 0; i < this.list_.length; i++) {\n    this.list_[i].cancel();\n  }\n};\n\n\n/**\n * Creates a <code>DeferredList</code> that gathers results from multiple\n * <code>Deferred</code> inputs. If all inputs succeed, the callback is fired\n * with the list of results as a flat array. If any input fails, the list's\n * errback is fired immediately with the offending error, and all other pending\n * inputs are canceled.\n *\n * @param {!Array<!goog.async.Deferred>} list The list of <code>Deferred</code>\n *     inputs to wait for.\n * @return {!goog.async.Deferred} The deferred list of results from the inputs\n *     if they all succeed, or the error result of the first input to fail.\n */\ngoog.async.DeferredList.gatherResults = function(list) {\n  return new goog.async.DeferredList(list, false, true).\n      addCallback(function(results) {\n        var output = [];\n        for (var i = 0; i < results.length; i++) {\n          output[i] = results[i][1];\n        }\n        return output;\n      });\n};\n","^;",1569048148000,"^<",["^=",["^>","~$goog.async.Deferred"]],"^C",["^ ","^D","\n        The Google Closure Library is a collection of JavaScript code\n        designed for use with the Google Closure JavaScript Compiler.\n\n        This non-official distribution was prepared by the ClojureScript\n        team at http://clojure.org/\n\n        This package contains extensions to the Google Closure Library\n        using third-party components, which may be distributed under\n        licenses other than the Apache license. Licenses for individual\n        library components may be found in source-code comments.\n    ","^E","^F","^G","^H","^I","Google Closure Library Third-Party Extensions","^J","^K","^L","http://code.google.com/p/closure-library/","^M","^N","^O",["^K","0.0-20190213-2033d5d9"],"^P","0.0-20190213-2033d5d9"],"^L",["^Q","jar:file:/Users/clojure/.m2/repository/org/clojure/google-closure-library-third-party/0.0-20190213-2033d5d9/google-closure-library-third-party-0.0-20190213-2033d5d9.jar!/goog/mochikit/async/deferredlist.js"],"^R",["^=",["~$goog.async.DeferredList"]],"^T",true,"^U",["^>","^V"]],["^ ","^3",[1569048148000],"^4","goog.mochikit.async.deferred.js","^5",["^6","goog/mochikit/async/deferred.js"],"^7","goog/mochikit/async/deferred.js","^8","^9","^:","// Copyright 2007 Bob Ippolito. All Rights Reserved.\n// Modifications Copyright 2009 The Closure Library Authors. All Rights\n// Reserved.\n\n/**\n * @license Portions of this code are from MochiKit, received by\n * The Closure Authors under the MIT license. All other code is Copyright\n * 2005-2009 The Closure Authors. All Rights Reserved.\n */\n\n/**\n * @fileoverview Classes for tracking asynchronous operations and handling the\n * results. The Deferred object here is patterned after the Deferred object in\n * the Twisted python networking framework.\n *\n * See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html\n *\n * Based on the Dojo code which in turn is based on the MochiKit code.\n *\n * @author arv@google.com (Erik Arvidsson)\n * @author brenneman@google.com (Shawn Brenneman)\n */\n\ngoog.provide('goog.async.Deferred');\ngoog.provide('goog.async.Deferred.AlreadyCalledError');\ngoog.provide('goog.async.Deferred.CanceledError');\n\ngoog.require('goog.Promise');\ngoog.require('goog.Thenable');\ngoog.require('goog.array');\ngoog.require('goog.asserts');\ngoog.require('goog.debug.Error');\n\n\n\n/**\n * A Deferred represents the result of an asynchronous operation. A Deferred\n * instance has no result when it is created, and is \"fired\" (given an initial\n * result) by calling `callback` or `errback`.\n *\n * Once fired, the result is passed through a sequence of callback functions\n * registered with `addCallback` or `addErrback`. The functions may\n * mutate the result before it is passed to the next function in the sequence.\n *\n * Callbacks and errbacks may be added at any time, including after the Deferred\n * has been \"fired\". If there are no pending actions in the execution sequence\n * of a fired Deferred, any new callback functions will be called with the last\n * computed result. Adding a callback function is the only way to access the\n * result of the Deferred.\n *\n * If a Deferred operation is canceled, an optional user-provided cancellation\n * function is invoked which may perform any special cleanup, followed by firing\n * the Deferred's errback sequence with a `CanceledError`. If the\n * Deferred has already fired, cancellation is ignored.\n *\n * Deferreds may be templated to a specific type they produce using generics\n * with syntax such as:\n *\n *    /** @type {goog.async.Deferred<string>} *\\\n *    var d = new goog.async.Deferred();\n *    // Compiler can infer that foo is a string.\n *    d.addCallback(function(foo) {...});\n *    d.callback('string');  // Checked to be passed a string\n *\n * Since deferreds are often used to produce different values across a chain,\n * the type information is not propagated across chains, but rather only\n * associated with specifically cast objects.\n *\n * @param {Function=} opt_onCancelFunction A function that will be called if the\n *     Deferred is canceled. If provided, this function runs before the\n *     Deferred is fired with a `CanceledError`.\n * @param {Object=} opt_defaultScope The default object context to call\n *     callbacks and errbacks in.\n * @constructor\n * @implements {goog.Thenable<VALUE>}\n * @template VALUE\n */\ngoog.async.Deferred = function(opt_onCancelFunction, opt_defaultScope) {\n  /**\n   * Entries in the sequence are arrays containing a callback, an errback, and\n   * an optional scope. The callback or errback in an entry may be null.\n   * @type {!Array<!Array>}\n   * @private\n   */\n  this.sequence_ = [];\n\n  /**\n   * Optional function that will be called if the Deferred is canceled.\n   * @type {Function|undefined}\n   * @private\n   */\n  this.onCancelFunction_ = opt_onCancelFunction;\n\n  /**\n   * The default scope to execute callbacks and errbacks in.\n   * @type {Object}\n   * @private\n   */\n  this.defaultScope_ = opt_defaultScope || null;\n\n  /**\n   * Whether the Deferred has been fired.\n   * @type {boolean}\n   * @private\n   */\n  this.fired_ = false;\n\n  /**\n   * Whether the last result in the execution sequence was an error.\n   * @type {boolean}\n   * @private\n   */\n  this.hadError_ = false;\n\n  /**\n   * The current Deferred result, updated as callbacks and errbacks are\n   * executed.\n   * @type {*}\n   * @private\n   */\n  this.result_ = undefined;\n\n  /**\n   * Whether the Deferred is blocked waiting on another Deferred to fire. If a\n   * callback or errback returns a Deferred as a result, the execution sequence\n   * is blocked until that Deferred result becomes available.\n   * @type {boolean}\n   * @private\n   */\n  this.blocked_ = false;\n\n  /**\n   * Whether this Deferred is blocking execution of another Deferred. If this\n   * instance was returned as a result in another Deferred's execution\n   * sequence,that other Deferred becomes blocked until this instance's\n   * execution sequence completes. No additional callbacks may be added to a\n   * Deferred once it is blocking another instance.\n   * @type {boolean}\n   * @private\n   */\n  this.blocking_ = false;\n\n  /**\n   * Whether the Deferred has been canceled without having a custom cancel\n   * function.\n   * @type {boolean}\n   * @private\n   */\n  this.silentlyCanceled_ = false;\n\n  /**\n   * If an error is thrown during Deferred execution with no errback to catch\n   * it, the error is rethrown after a timeout. Reporting the error after a\n   * timeout allows execution to continue in the calling context (empty when\n   * no error is scheduled).\n   * @type {number}\n   * @private\n   */\n  this.unhandledErrorId_ = 0;\n\n  /**\n   * If this Deferred was created by branch(), this will be the \"parent\"\n   * Deferred.\n   * @type {?goog.async.Deferred}\n   * @private\n   */\n  this.parent_ = null;\n\n  /**\n   * The number of Deferred objects that have been branched off this one. This\n   * will be decremented whenever a branch is fired or canceled.\n   * @type {number}\n   * @private\n   */\n  this.branches_ = 0;\n\n  if (goog.async.Deferred.LONG_STACK_TRACES) {\n    /**\n     * Holds the stack trace at time of deferred creation if the JS engine\n     * provides the Error.captureStackTrace API.\n     * @private {?string}\n     */\n    this.constructorStack_ = null;\n    if (Error.captureStackTrace) {\n      var target = { stack: '' };\n      Error.captureStackTrace(target, goog.async.Deferred);\n      // Check if Error.captureStackTrace worked. It fails in gjstest.\n      if (typeof target.stack == 'string') {\n        // Remove first line and force stringify to prevent memory leak due to\n        // holding on to actual stack frames.\n        this.constructorStack_ = target.stack.replace(/^[^\\n]*\\n/, '');\n      }\n    }\n  }\n};\n\n\n/**\n * @define {boolean} Whether unhandled errors should always get rethrown to the\n * global scope. Defaults to false.\n */\ngoog.define('goog.async.Deferred.STRICT_ERRORS', false);\n\n\n/**\n * @define {boolean} Whether to attempt to make stack traces long.  Defaults to\n * false.\n */\ngoog.define('goog.async.Deferred.LONG_STACK_TRACES', false);\n\n\n/**\n * Cancels a Deferred that has not yet been fired, or is blocked on another\n * deferred operation. If this Deferred is waiting for a blocking Deferred to\n * fire, the blocking Deferred will also be canceled.\n *\n * If this Deferred was created by calling branch() on a parent Deferred with\n * opt_propagateCancel set to true, the parent may also be canceled. If\n * opt_deepCancel is set, cancel() will be called on the parent (as well as any\n * other ancestors if the parent is also a branch). If one or more branches were\n * created with opt_propagateCancel set to true, the parent will be canceled if\n * cancel() is called on all of those branches.\n *\n * @param {boolean=} opt_deepCancel If true, cancels this Deferred's parent even\n *     if cancel() hasn't been called on some of the parent's branches. Has no\n *     effect on a branch without opt_propagateCancel set to true.\n */\ngoog.async.Deferred.prototype.cancel = function(opt_deepCancel) {\n  if (!this.hasFired()) {\n    if (this.parent_) {\n      // Get rid of the parent reference before potentially running the parent's\n      // canceler function to ensure that this cancellation isn't\n      // double-counted.\n      var parent = this.parent_;\n      delete this.parent_;\n      if (opt_deepCancel) {\n        parent.cancel(opt_deepCancel);\n      } else {\n        parent.branchCancel_();\n      }\n    }\n\n    if (this.onCancelFunction_) {\n      // Call in user-specified scope.\n      this.onCancelFunction_.call(this.defaultScope_, this);\n    } else {\n      this.silentlyCanceled_ = true;\n    }\n    if (!this.hasFired()) {\n      this.errback(new goog.async.Deferred.CanceledError(this));\n    }\n  } else if (this.result_ instanceof goog.async.Deferred) {\n    this.result_.cancel();\n  }\n};\n\n\n/**\n * Handle a single branch being canceled. Once all branches are canceled, this\n * Deferred will be canceled as well.\n *\n * @private\n */\ngoog.async.Deferred.prototype.branchCancel_ = function() {\n  this.branches_--;\n  if (this.branches_ <= 0) {\n    this.cancel();\n  }\n};\n\n\n/**\n * Called after a blocking Deferred fires. Unblocks this Deferred and resumes\n * its execution sequence.\n *\n * @param {boolean} isSuccess Whether the result is a success or an error.\n * @param {*} res The result of the blocking Deferred.\n * @private\n */\ngoog.async.Deferred.prototype.continue_ = function(isSuccess, res) {\n  this.blocked_ = false;\n  this.updateResult_(isSuccess, res);\n};\n\n\n/**\n * Updates the current result based on the success or failure of the last action\n * in the execution sequence.\n *\n * @param {boolean} isSuccess Whether the new result is a success or an error.\n * @param {*} res The result.\n * @private\n */\ngoog.async.Deferred.prototype.updateResult_ = function(isSuccess, res) {\n  this.fired_ = true;\n  this.result_ = res;\n  this.hadError_ = !isSuccess;\n  this.fire_();\n};\n\n\n/**\n * Verifies that the Deferred has not yet been fired.\n *\n * @private\n * @throws {Error} If this has already been fired.\n */\ngoog.async.Deferred.prototype.check_ = function() {\n  if (this.hasFired()) {\n    if (!this.silentlyCanceled_) {\n      throw new goog.async.Deferred.AlreadyCalledError(this);\n    }\n    this.silentlyCanceled_ = false;\n  }\n};\n\n\n/**\n * Fire the execution sequence for this Deferred by passing the starting result\n * to the first registered callback.\n * @param {VALUE=} opt_result The starting result.\n */\ngoog.async.Deferred.prototype.callback = function(opt_result) {\n  this.check_();\n  this.assertNotDeferred_(opt_result);\n  this.updateResult_(true /* isSuccess */, opt_result);\n};\n\n\n/**\n * Fire the execution sequence for this Deferred by passing the starting error\n * result to the first registered errback.\n * @param {*=} opt_result The starting error.\n */\ngoog.async.Deferred.prototype.errback = function(opt_result) {\n  this.check_();\n  this.assertNotDeferred_(opt_result);\n  this.makeStackTraceLong_(opt_result);\n  this.updateResult_(false /* isSuccess */, opt_result);\n};\n\n\n/**\n * Attempt to make the error's stack trace be long in that it contains the\n * stack trace from the point where the deferred was created on top of the\n * current stack trace to give additional context.\n * @param {*} error\n * @private\n */\ngoog.async.Deferred.prototype.makeStackTraceLong_ = function(error) {\n  if (!goog.async.Deferred.LONG_STACK_TRACES) {\n    return;\n  }\n  if (this.constructorStack_ && goog.isObject(error) && error.stack &&\n      // Stack looks like it was system generated. See\n      // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi\n      (/^[^\\n]+(\\n   [^\\n]+)+/).test(error.stack)) {\n    error.stack = error.stack + '\\nDEFERRED OPERATION:\\n' +\n        this.constructorStack_;\n  }\n};\n\n\n/**\n * Asserts that an object is not a Deferred.\n * @param {*} obj The object to test.\n * @throws {Error} Throws an exception if the object is a Deferred.\n * @private\n */\ngoog.async.Deferred.prototype.assertNotDeferred_ = function(obj) {\n  goog.asserts.assert(\n      !(obj instanceof goog.async.Deferred),\n      'An execution sequence may not be initiated with a blocking Deferred.');\n};\n\n\n/**\n * Register a callback function to be called with a successful result. If no\n * value is returned by the callback function, the result value is unchanged. If\n * a new value is returned, it becomes the Deferred result and will be passed to\n * the next callback in the execution sequence.\n *\n * If the function throws an error, the error becomes the new result and will be\n * passed to the next errback in the execution chain.\n *\n * If the function returns a Deferred, the execution sequence will be blocked\n * until that Deferred fires. Its result will be passed to the next callback (or\n * errback if it is an error result) in this Deferred's execution sequence.\n *\n * @param {function(this:T,VALUE):?} cb The function to be called with a\n *     successful result.\n * @param {T=} opt_scope An optional scope to call the callback in.\n * @return {!goog.async.Deferred} This Deferred.\n * @template T\n */\ngoog.async.Deferred.prototype.addCallback = function(cb, opt_scope) {\n  return this.addCallbacks(cb, null, opt_scope);\n};\n\n\n/**\n * Register a callback function to be called with an error result. If no value\n * is returned by the function, the error result is unchanged. If a new error\n * value is returned or thrown, that error becomes the Deferred result and will\n * be passed to the next errback in the execution sequence.\n *\n * If the errback function handles the error by returning a non-error value,\n * that result will be passed to the next normal callback in the sequence.\n *\n * If the function returns a Deferred, the execution sequence will be blocked\n * until that Deferred fires. Its result will be passed to the next callback (or\n * errback if it is an error result) in this Deferred's execution sequence.\n *\n * @param {function(this:T,?):?} eb The function to be called on an\n *     unsuccessful result.\n * @param {T=} opt_scope An optional scope to call the errback in.\n * @return {!goog.async.Deferred<VALUE>} This Deferred.\n * @template T\n */\ngoog.async.Deferred.prototype.addErrback = function(eb, opt_scope) {\n  return this.addCallbacks(null, eb, opt_scope);\n};\n\n\n/**\n * Registers one function as both a callback and errback.\n *\n * @param {function(this:T,?):?} f The function to be called on any result.\n * @param {T=} opt_scope An optional scope to call the function in.\n * @return {!goog.async.Deferred} This Deferred.\n * @template T\n */\ngoog.async.Deferred.prototype.addBoth = function(f, opt_scope) {\n  return this.addCallbacks(f, f, opt_scope);\n};\n\n\n/**\n * Like addBoth, but propagates uncaught exceptions in the errback.\n *\n * @param {function(this:T,?):?} f The function to be called on any result.\n * @param {T=} opt_scope An optional scope to call the function in.\n * @return {!goog.async.Deferred<VALUE>} This Deferred.\n * @template T\n */\ngoog.async.Deferred.prototype.addFinally = function(f, opt_scope) {\n  return this.addCallbacks(f, function(err) {\n    var result = f.call(/** @type {?} */ (this), err);\n    if (!goog.isDef(result)) {\n      throw err;\n    }\n    return result;\n  }, opt_scope);\n};\n\n\n/**\n * Registers a callback function and an errback function at the same position\n * in the execution sequence. Only one of these functions will execute,\n * depending on the error state during the execution sequence.\n *\n * NOTE: This is not equivalent to {@code def.addCallback().addErrback()}! If\n * the callback is invoked, the errback will be skipped, and vice versa.\n *\n * @param {?(function(this:T,VALUE):?)} cb The function to be called on a\n *     successful result.\n * @param {?(function(this:T,?):?)} eb The function to be called on an\n *     unsuccessful result.\n * @param {T=} opt_scope An optional scope to call the functions in.\n * @return {!goog.async.Deferred} This Deferred.\n * @template T\n */\ngoog.async.Deferred.prototype.addCallbacks = function(cb, eb, opt_scope) {\n  goog.asserts.assert(!this.blocking_, 'Blocking Deferreds can not be re-used');\n  this.sequence_.push([cb, eb, opt_scope]);\n  if (this.hasFired()) {\n    this.fire_();\n  }\n  return this;\n};\n\n\n/**\n * Implements {@see goog.Thenable} for seamless integration with\n * {@see goog.Promise}.\n * Deferred results are mutable and may represent multiple values over\n * their lifetime. Calling `then` on a Deferred returns a Promise\n * with the result of the Deferred at that point in its callback chain.\n * Note that if the Deferred result is never mutated, and only\n * `then` calls are made, the Deferred will behave like a Promise.\n *\n * @override\n */\ngoog.async.Deferred.prototype.then = function(opt_onFulfilled, opt_onRejected,\n    opt_context) {\n  var resolve, reject;\n  var promise = new goog.Promise(function(res, rej) {\n    // Copying resolvers to outer scope, so that they are available when the\n    // deferred callback fires (which may be synchronous).\n    resolve = res;\n    reject = rej;\n  });\n  this.addCallbacks(resolve, function(reason) {\n    if (reason instanceof goog.async.Deferred.CanceledError) {\n      promise.cancel();\n    } else {\n      reject(reason);\n    }\n  });\n  return promise.then(opt_onFulfilled, opt_onRejected, opt_context);\n};\ngoog.Thenable.addImplementation(goog.async.Deferred);\n\n\n/**\n * Links another Deferred to the end of this Deferred's execution sequence. The\n * result of this execution sequence will be passed as the starting result for\n * the chained Deferred, invoking either its first callback or errback.\n *\n * @param {!goog.async.Deferred} otherDeferred The Deferred to chain.\n * @return {!goog.async.Deferred} This Deferred.\n */\ngoog.async.Deferred.prototype.chainDeferred = function(otherDeferred) {\n  this.addCallbacks(\n      otherDeferred.callback, otherDeferred.errback, otherDeferred);\n  return this;\n};\n\n\n/**\n * Makes this Deferred wait for another Deferred's execution sequence to\n * complete before continuing.\n *\n * This is equivalent to adding a callback that returns `otherDeferred`,\n * but doesn't prevent additional callbacks from being added to\n * `otherDeferred`.\n *\n * @param {!goog.async.Deferred|!goog.Thenable} otherDeferred The Deferred\n *     to wait for.\n * @return {!goog.async.Deferred} This Deferred.\n */\ngoog.async.Deferred.prototype.awaitDeferred = function(otherDeferred) {\n  if (!(otherDeferred instanceof goog.async.Deferred)) {\n    // The Thenable case.\n    return this.addCallback(function() {\n      return otherDeferred;\n    });\n  }\n  return this.addCallback(goog.bind(otherDeferred.branch, otherDeferred));\n};\n\n\n/**\n * Creates a branch off this Deferred's execution sequence, and returns it as a\n * new Deferred. The branched Deferred's starting result will be shared with the\n * parent at the point of the branch, even if further callbacks are added to the\n * parent.\n *\n * All branches at the same stage in the execution sequence will receive the\n * same starting value.\n *\n * @param {boolean=} opt_propagateCancel If cancel() is called on every child\n *     branch created with opt_propagateCancel, the parent will be canceled as\n *     well.\n * @return {!goog.async.Deferred<VALUE>} A Deferred that will be started with\n *     the computed result from this stage in the execution sequence.\n */\ngoog.async.Deferred.prototype.branch = function(opt_propagateCancel) {\n  var d = new goog.async.Deferred();\n  this.chainDeferred(d);\n  if (opt_propagateCancel) {\n    d.parent_ = this;\n    this.branches_++;\n  }\n  return d;\n};\n\n\n/**\n * @return {boolean} Whether the execution sequence has been started on this\n *     Deferred by invoking `callback` or `errback`.\n */\ngoog.async.Deferred.prototype.hasFired = function() {\n  return this.fired_;\n};\n\n\n/**\n * @param {*} res The latest result in the execution sequence.\n * @return {boolean} Whether the current result is an error that should cause\n *     the next errback to fire. May be overridden by subclasses to handle\n *     special error types.\n * @protected\n */\ngoog.async.Deferred.prototype.isError = function(res) {\n  return res instanceof Error;\n};\n\n\n/**\n * @return {boolean} Whether an errback exists in the remaining sequence.\n * @private\n */\ngoog.async.Deferred.prototype.hasErrback_ = function() {\n  return goog.array.some(this.sequence_, function(sequenceRow) {\n    // The errback is the second element in the array.\n    return goog.isFunction(sequenceRow[1]);\n  });\n};\n\n\n/**\n * Exhausts the execution sequence while a result is available. The result may\n * be modified by callbacks or errbacks, and execution will block if the\n * returned result is an incomplete Deferred.\n *\n * @private\n */\ngoog.async.Deferred.prototype.fire_ = function() {\n  if (this.unhandledErrorId_ && this.hasFired() && this.hasErrback_()) {\n    // It is possible to add errbacks after the Deferred has fired. If a new\n    // errback is added immediately after the Deferred encountered an unhandled\n    // error, but before that error is rethrown, the error is unscheduled.\n    goog.async.Deferred.unscheduleError_(this.unhandledErrorId_);\n    this.unhandledErrorId_ = 0;\n  }\n\n  if (this.parent_) {\n    this.parent_.branches_--;\n    delete this.parent_;\n  }\n\n  var res = this.result_;\n  var unhandledException = false;\n  var isNewlyBlocked = false;\n\n  while (this.sequence_.length && !this.blocked_) {\n    var sequenceEntry = this.sequence_.shift();\n\n    var callback = sequenceEntry[0];\n    var errback = sequenceEntry[1];\n    var scope = sequenceEntry[2];\n\n    var f = this.hadError_ ? errback : callback;\n    if (f) {\n\n      try {\n        var ret = f.call(scope || this.defaultScope_, res);\n\n        // If no result, then use previous result.\n        if (goog.isDef(ret)) {\n          // Bubble up the error as long as the return value hasn't changed.\n          this.hadError_ = this.hadError_ && (ret == res || this.isError(ret));\n          this.result_ = res = ret;\n        }\n\n        if (goog.Thenable.isImplementedBy(res) ||\n            (typeof goog.global['Promise'] === 'function' &&\n            res instanceof goog.global['Promise'])) {\n          isNewlyBlocked = true;\n          this.blocked_ = true;\n        }\n\n      } catch (ex) {\n        res = ex;\n        this.hadError_ = true;\n        this.makeStackTraceLong_(res);\n\n        if (!this.hasErrback_()) {\n          // If an error is thrown with no additional errbacks in the queue,\n          // prepare to rethrow the error.\n          unhandledException = true;\n        }\n      }\n    }\n  }\n\n  this.result_ = res;\n\n  if (isNewlyBlocked) {\n    var onCallback = goog.bind(this.continue_, this, true /* isSuccess */);\n    var onErrback = goog.bind(this.continue_, this, false /* isSuccess */);\n\n    if (res instanceof goog.async.Deferred) {\n      res.addCallbacks(onCallback, onErrback);\n      res.blocking_ = true;\n    } else {\n      /** @type {!IThenable} */ (res).then(onCallback, onErrback);\n    }\n  } else if (goog.async.Deferred.STRICT_ERRORS && this.isError(res) &&\n      !(res instanceof goog.async.Deferred.CanceledError)) {\n    this.hadError_ = true;\n    unhandledException = true;\n  }\n\n  if (unhandledException) {\n    // Rethrow the unhandled error after a timeout. Execution will continue, but\n    // the error will be seen by global handlers and the user. The throw will\n    // be canceled if another errback is appended before the timeout executes.\n    // The error's original stack trace is preserved where available.\n    this.unhandledErrorId_ = goog.async.Deferred.scheduleError_(res);\n  }\n};\n\n\n/**\n * Creates a Deferred that has an initial result.\n *\n * @param {*=} opt_result The result.\n * @return {!goog.async.Deferred} The new Deferred.\n */\ngoog.async.Deferred.succeed = function(opt_result) {\n  var d = new goog.async.Deferred();\n  d.callback(opt_result);\n  return d;\n};\n\n\n/**\n * Creates a Deferred that fires when the given promise resolves.\n * Use only during migration to Promises.\n *\n * Note: If the promise resolves to a thenable value (which is not allowed by\n * conforming promise implementations), then the deferred may behave\n * unexpectedly as it tries to wait on it. This should not be a risk when using\n * goog.Promise, goog.async.Deferred, or native Promise objects.\n *\n * @param {!IThenable<T>} promise\n * @return {!goog.async.Deferred<T>} The new Deferred.\n * @template T\n */\ngoog.async.Deferred.fromPromise = function(promise) {\n  var d = new goog.async.Deferred();\n  promise.then(\n      function(value) {\n        d.callback(value);\n      },\n      function(error) {\n        d.errback(error);\n      });\n  return d;\n};\n\n\n/**\n * Creates a Deferred that has an initial error result.\n *\n * @param {*} res The error result.\n * @return {!goog.async.Deferred} The new Deferred.\n */\ngoog.async.Deferred.fail = function(res) {\n  var d = new goog.async.Deferred();\n  d.errback(res);\n  return d;\n};\n\n\n/**\n * Creates a Deferred that has already been canceled.\n *\n * @return {!goog.async.Deferred} The new Deferred.\n */\ngoog.async.Deferred.canceled = function() {\n  var d = new goog.async.Deferred();\n  d.cancel();\n  return d;\n};\n\n\n/**\n * Normalizes values that may or may not be Deferreds.\n *\n * If the input value is a Deferred, the Deferred is branched (so the original\n * execution sequence is not modified) and the input callback added to the new\n * branch. The branch is returned to the caller.\n *\n * If the input value is not a Deferred, the callback will be executed\n * immediately and an already firing Deferred will be returned to the caller.\n *\n * In the following (contrived) example, if <code>isImmediate</code> is true\n * then 3 is alerted immediately, otherwise 6 is alerted after a 2-second delay.\n *\n * <pre>\n * var value;\n * if (isImmediate) {\n *   value = 3;\n * } else {\n *   value = new goog.async.Deferred();\n *   setTimeout(function() { value.callback(6); }, 2000);\n * }\n *\n * var d = goog.async.Deferred.when(value, alert);\n * </pre>\n *\n * @param {*} value Deferred or normal value to pass to the callback.\n * @param {function(this:T, ?):?} callback The callback to execute.\n * @param {T=} opt_scope An optional scope to call the callback in.\n * @return {!goog.async.Deferred} A new Deferred that will call the input\n *     callback with the input value.\n * @template T\n */\ngoog.async.Deferred.when = function(value, callback, opt_scope) {\n  if (value instanceof goog.async.Deferred) {\n    return value.branch(true).addCallback(callback, opt_scope);\n  } else {\n    return goog.async.Deferred.succeed(value).addCallback(callback, opt_scope);\n  }\n};\n\n\n\n/**\n * An error sub class that is used when a Deferred has already been called.\n * @param {!goog.async.Deferred} deferred The Deferred.\n *\n * @constructor\n * @extends {goog.debug.Error}\n */\ngoog.async.Deferred.AlreadyCalledError = function(deferred) {\n  goog.debug.Error.call(this);\n\n  /**\n   * The Deferred that raised this error.\n   * @type {goog.async.Deferred}\n   */\n  this.deferred = deferred;\n};\ngoog.inherits(goog.async.Deferred.AlreadyCalledError, goog.debug.Error);\n\n\n/** @override */\ngoog.async.Deferred.AlreadyCalledError.prototype.message =\n    'Deferred has already fired';\n\n\n/** @override */\ngoog.async.Deferred.AlreadyCalledError.prototype.name = 'AlreadyCalledError';\n\n\n\n/**\n * An error sub class that is used when a Deferred is canceled.\n *\n * @param {!goog.async.Deferred} deferred The Deferred object.\n * @constructor\n * @extends {goog.debug.Error}\n */\ngoog.async.Deferred.CanceledError = function(deferred) {\n  goog.debug.Error.call(this);\n\n  /**\n   * The Deferred that raised this error.\n   * @type {goog.async.Deferred}\n   */\n  this.deferred = deferred;\n};\ngoog.inherits(goog.async.Deferred.CanceledError, goog.debug.Error);\n\n\n/** @override */\ngoog.async.Deferred.CanceledError.prototype.message = 'Deferred was canceled';\n\n\n/** @override */\ngoog.async.Deferred.CanceledError.prototype.name = 'CanceledError';\n\n\n\n/**\n * Wrapper around errors that are scheduled to be thrown by failing deferreds\n * after a timeout.\n *\n * @param {*} error Error from a failing deferred.\n * @constructor\n * @final\n * @private\n * @struct\n */\ngoog.async.Deferred.Error_ = function(error) {\n  /** @const @private {number} */\n  this.id_ = goog.global.setTimeout(goog.bind(this.throwError, this), 0);\n\n  /** @const @private {*} */\n  this.error_ = error;\n};\n\n\n/**\n * Actually throws the error and removes it from the list of pending\n * deferred errors.\n */\ngoog.async.Deferred.Error_.prototype.throwError = function() {\n  goog.asserts.assert(goog.async.Deferred.errorMap_[this.id_],\n      'Cannot throw an error that is not scheduled.');\n  delete goog.async.Deferred.errorMap_[this.id_];\n  throw this.error_;\n};\n\n\n/**\n * Resets the error throw timer.\n */\ngoog.async.Deferred.Error_.prototype.resetTimer = function() {\n  goog.global.clearTimeout(this.id_);\n};\n\n\n/**\n * Map of unhandled errors scheduled to be rethrown in a future timestep.\n * @private {!Object<(number|string), goog.async.Deferred.Error_>}\n */\ngoog.async.Deferred.errorMap_ = {};\n\n\n/**\n * Schedules an error to be thrown after a delay.\n * @param {*} error Error from a failing deferred.\n * @return {number} Id of the error.\n * @private\n */\ngoog.async.Deferred.scheduleError_ = function(error) {\n  var deferredError = new goog.async.Deferred.Error_(error);\n  goog.async.Deferred.errorMap_[deferredError.id_] = deferredError;\n  return deferredError.id_;\n};\n\n\n/**\n * Unschedules an error from being thrown.\n * @param {number} id Id of the deferred error to unschedule.\n * @private\n */\ngoog.async.Deferred.unscheduleError_ = function(id) {\n  var error = goog.async.Deferred.errorMap_[id];\n  if (error) {\n    error.resetTimer();\n    delete goog.async.Deferred.errorMap_[id];\n  }\n};\n\n\n/**\n * Asserts that there are no pending deferred errors. If there are any\n * scheduled errors, one will be thrown immediately to make this function fail.\n */\ngoog.async.Deferred.assertNoErrors = function() {\n  var map = goog.async.Deferred.errorMap_;\n  for (var key in map) {\n    var error = map[key];\n    error.resetTimer();\n    error.throwError();\n  }\n};\n","^;",1569048148000,"^<",["^=",["~$goog.asserts","^>","~$goog.debug.Error","~$goog.Promise","~$goog.array","~$goog.Thenable"]],"^C",["^ ","^D","\n        The Google Closure Library is a collection of JavaScript code\n        designed for use with the Google Closure JavaScript Compiler.\n\n        This non-official distribution was prepared by the ClojureScript\n        team at http://clojure.org/\n\n        This package contains extensions to the Google Closure Library\n        using third-party components, which may be distributed under\n        licenses other than the Apache license. Licenses for individual\n        library components may be found in source-code comments.\n    ","^E","^F","^G","^H","^I","Google Closure Library Third-Party Extensions","^J","^K","^L","http://code.google.com/p/closure-library/","^M","^N","^O",["^K","0.0-20190213-2033d5d9"],"^P","0.0-20190213-2033d5d9"],"^L",["^Q","jar:file:/Users/clojure/.m2/repository/org/clojure/google-closure-library-third-party/0.0-20190213-2033d5d9/google-closure-library-third-party-0.0-20190213-2033d5d9.jar!/goog/mochikit/async/deferred.js"],"^R",["^=",["~$goog.async.Deferred.CanceledError","^V","~$goog.async.Deferred.AlreadyCalledError"]],"^T",true,"^U",["^>","^Z","^10","^[","^X","^Y"]],["^ ","^3",[1569048148000],"^4","goog.dojo.dom.query.js","^5",["^6","goog/dojo/dom/query.js"],"^7","goog/dojo/dom/query.js","^8","^9","^:","// Copyright 2005-2009, The Dojo Foundation\n// Modifications Copyright 2008 The Closure Library Authors.\n// All Rights Reserved.\n\n/**\n * @license Portions of this code are from the Dojo Toolkit, received by\n * The Closure Library Authors under the BSD license. All other code is\n * Copyright 2005-2009 The Closure Library Authors. All Rights Reserved.\n\nThe \"New\" BSD License:\n\nCopyright (c) 2005-2009, The Dojo Foundation\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright notice, this\n    list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright notice,\n    this list of conditions and the following disclaimer in the documentation\n    and/or other materials provided with the distribution.\n  * Neither the name of the Dojo Foundation nor the names of its contributors\n    may be used to endorse or promote products derived from this software\n    without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/**\n * @fileoverview This code was ported from the Dojo Toolkit\n   http://dojotoolkit.org and modified slightly for Closure.\n *\n *  goog.dom.query is a relatively full-featured CSS3 query function. It is\n *  designed to take any valid CSS3 selector and return the nodes matching\n *  the selector. To do this quickly, it processes queries in several\n *  steps, applying caching where profitable.\n *    The steps (roughly in reverse order of the way they appear in the code):\n *    1.) check to see if we already have a \"query dispatcher\"\n *      - if so, use that with the given parameterization. Skip to step 4.\n *    2.) attempt to determine which branch to dispatch the query to:\n *      - JS (optimized DOM iteration)\n *      - native (FF3.1, Safari 3.2+, Chrome, some IE 8 doctypes). If native,\n *        skip to step 4, using a stub dispatcher for QSA queries.\n *    3.) tokenize and convert to executable \"query dispatcher\"\n *        assembled as a chain of \"yes/no\" test functions pertaining to\n *        a section of a simple query statement (\".blah:nth-child(odd)\"\n *        but not \"div div\", which is 2 simple statements).\n *    4.) the resulting query dispatcher is called in the passed scope\n *        (by default the top-level document)\n *      - for DOM queries, this results in a recursive, top-down\n *        evaluation of nodes based on each simple query section\n *      - querySelectorAll is used instead of DOM where possible. If a query\n *        fails in this mode, it is re-run against the DOM evaluator and all\n *        future queries using the same selector evaluate against the DOM branch\n *        too.\n *    5.) matched nodes are pruned to ensure they are unique\n * @deprecated This is an all-software query selector. When developing for\n *     recent browsers, use document.querySelector. See information at\n *     http://caniuse.com/queryselector and\n *     https://developer.mozilla.org/en-US/docs/DOM/Document.querySelector .\n */\n\ngoog.provide('goog.dom.query');\n\ngoog.require('goog.array');\ngoog.require('goog.dom');\ngoog.require('goog.functions');\ngoog.require('goog.string');\ngoog.require('goog.userAgent');\n\n/**\n   * Returns nodes which match the given CSS3 selector, searching the\n   * entire document by default but optionally taking a node to scope\n   * the search by.\n   *\n   * dojo.query() is the swiss army knife of DOM node manipulation in\n   * Dojo. Much like Prototype's \"$$\" (bling-bling) function or JQuery's\n   * \"$\" function, dojo.query provides robust, high-performance\n   * CSS-based node selector support with the option of scoping searches\n   * to a particular sub-tree of a document.\n   *\n   * Supported Selectors:\n   * --------------------\n   *\n   * dojo.query() supports a rich set of CSS3 selectors, including:\n   *\n   *   * class selectors (e.g., `.foo`)\n   *   * node type selectors like `span`\n   *   * ` ` descendant selectors\n   *   * `>` child element selectors\n   *   * `#foo` style ID selectors\n   *   * `*` universal selector\n   *   * `~`, the immediately preceded-by sibling selector\n   *   * `+`, the preceded-by sibling selector\n   *   * attribute queries:\n   *      * `[foo]` attribute presence selector\n   *      * `[foo='bar']` attribute value exact match\n   *      * `[foo~='bar']` attribute value list item match\n   *      * `[foo^='bar']` attribute start match\n   *      * `[foo$='bar']` attribute end match\n   *      * `[foo*='bar']` attribute substring match\n   *   * `:first-child`, `:last-child` positional selectors\n   *   * `:empty` content empty selector\n   *   * `:empty` content empty selector\n   *   * `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations\n   *   * `:nth-child(even)`, `:nth-child(odd)` positional selectors\n   *   * `:not(...)` negation pseudo selectors\n   *\n   * Any legal combination of these selectors will work with\n   * `dojo.query()`, including compound selectors (\",\" delimited).\n   * Very complex and useful searches can be constructed with this\n   * palette of selectors.\n   *\n   * Unsupported Selectors:\n   * ----------------------\n   *\n   * While dojo.query handles many CSS3 selectors, some fall outside of\n   * what's reasonable for a programmatic node querying engine to\n   * handle. Currently unsupported selectors include:\n   *\n   *   * namespace-differentiated selectors of any form\n   *   * all `::` pseudo-element selectors\n   *   * certain pseudo-selectors which don't get a lot of day-to-day use:\n   *      * `:root`, `:lang()`, `:target`, `:focus`\n   *   * all visual and state selectors:\n   *      * `:root`, `:active`, `:hover`, `:visited`, `:link`,\n   *       `:enabled`, `:disabled`, `:checked`\n   *   * `:*-of-type` pseudo selectors\n   *\n   * dojo.query and XML Documents:\n   * -----------------------------\n   *\n   * `dojo.query` currently only supports searching XML documents\n   * whose tags and attributes are 100% lower-case. This is a known\n   * limitation and will [be addressed soon]\n   * (http://trac.dojotoolkit.org/ticket/3866)\n   *\n   * Non-selector Queries:\n   * ---------------------\n   *\n   * If something other than a String is passed for the query,\n   * `dojo.query` will return a new array constructed from\n   * that parameter alone and all further processing will stop. This\n   * means that if you have a reference to a node or array or nodes, you\n   * can quickly construct a new array of nodes from the original by\n   * calling `dojo.query(node)` or `dojo.query(array)`.\n   *\n   * __Example:__ search the entire document for elements with the class \"foo\":\n   *\n   *    dojo.query(\".foo\");\n   *\n   * these elements will match:\n   *\n   *    <span class=\"foo\"></span>\n   *    <span class=\"foo bar\"></span>\n   *    <p class=\"thud foo\"></p>\n   *\n   * __Example:__ search the entire document for elements with the classes \"foo\"\n   * _and_ \"bar\":\n   *\n   *    dojo.query(\".foo.bar\");\n   *\n   * these elements will match:\n   *\n   *    <span class=\"foo bar\"></span>\n   *\n   * while these will not:\n   *\n   *    <span class=\"foo\"></span>\n   *    <p class=\"thud foo\"></p>\n   *\n   * __Example:__ find `<span>` elements which are descendants of paragraphs and\n   * which have a \"highlighted\" class:\n   *\n   *    dojo.query(\"p span.highlighted\");\n   *\n   * the innermost span in this fragment matches:\n   *\n   *    <p class=\"foo\">\n   *      <span>...\n   *        <span class=\"highlighted foo bar\">...</span>\n   *      </span>\n   *    </p>\n   *\n   * __Example:__ find all odd table rows inside of the table `#tabular_data`,\n   * using the `>` (direct child) selector to avoid affecting any nested tables:\n   *\n   *    dojo.query(\"#tabular_data > tbody > tr:nth-child(odd)\");\n   *\n   * @param {string|Array} query The CSS3 expression to match against.\n   *     For details on the syntax of CSS3 selectors, see\n   *     http://www.w3.org/TR/css3-selectors/#selectors.\n   * @param {(string|Node)=} opt_root A Node (or node id) to scope the search\n   *     from (optional).\n   * @return { {length: number} } The elements that matched the query.\n   *\n   * @deprecated This is an all-software query selector. Use\n   *     document.querySelector. See\n   *     https://developer.mozilla.org/en-US/docs/DOM/Document.querySelector .\n   */\ngoog.dom.query = (function() {\n  ////////////////////////////////////////////////////////////////////////\n  // Global utilities\n  ////////////////////////////////////////////////////////////////////////\n\n  var cssCaseBug = (goog.userAgent.WEBKIT &&\n                     ((goog.dom.getDocument().compatMode) == 'BackCompat')\n                   );\n\n  var legacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');\n\n  // On browsers that support the \"children\" collection we can avoid a lot of\n  // iteration on chaff (non-element) nodes.\n  var childNodesName =\n      goog.dom.getDocument().firstChild['children'] ? 'children' : 'childNodes';\n\n  var specials = '>~+';\n\n  // Global thunk to determine whether we should treat the current query as\n  // case sensitive or not. This switch is flipped by the query evaluator based\n  // on the document passed as the context to search.\n  var caseSensitive = false;\n\n\n  ////////////////////////////////////////////////////////////////////////\n  // Tokenizer\n  ////////////////////////////////////////////////////////////////////////\n\n  var getQueryParts = function(query) {\n    //  summary:\n    //    state machine for query tokenization\n    //  description:\n    //    instead of using a brittle and slow regex-based CSS parser,\n    //    dojo.query implements an AST-style query representation. This\n    //    representation is only generated once per query. For example,\n    //    the same query run multiple times or under different root nodes\n    //    does not re-parse the selector expression but instead uses the\n    //    cached data structure. The state machine implemented here\n    //    terminates on the last \" \" (space) character and returns an\n    //    ordered array of query component structures (or \"parts\"). Each\n    //    part represents an operator or a simple CSS filtering\n    //    expression. The structure for parts is documented in the code\n    //    below.\n\n\n    // NOTE:\n    //    this code is designed to run fast and compress well. Sacrifices\n    //    to readability and maintainability have been made.\n    if (specials.indexOf(query.slice(-1)) >= 0) {\n      // If we end with a \">\", \"+\", or \"~\", that means we're implicitly\n      // searching all children, so make it explicit.\n      query += ' * ';\n    } else {\n      // if you have not provided a terminator, one will be provided for\n      // you...\n      query += ' ';\n    }\n\n    var ts = function(/*Integer*/ s, /*Integer*/ e) {\n      // trim and slice.\n\n      // take an index to start a string slice from and an end position\n      // and return a trimmed copy of that sub-string\n      return goog.string.trim(query.slice(s, e));\n    };\n\n    // The overall data graph of the full query, as represented by queryPart\n    // objects.\n    var queryParts = [];\n\n\n    // state keeping vars\n    var inBrackets = -1,\n        inParens = -1,\n        inMatchFor = -1,\n        inPseudo = -1,\n        inClass = -1,\n        inId = -1,\n        inTag = -1,\n        lc = '',\n        cc = '',\n        pStart;\n\n    // iteration vars\n    var x = 0, // index in the query\n        ql = query.length,\n        currentPart = null, // data structure representing the entire clause\n        cp = null; // the current pseudo or attr matcher\n\n    // several temporary variables are assigned to this structure during a\n    // potential sub-expression match:\n    //    attr:\n    //      a string representing the current full attribute match in a\n    //      bracket expression\n    //    type:\n    //      if there's an operator in a bracket expression, this is\n    //      used to keep track of it\n    //    value:\n    //      the internals of parenthetical expression for a pseudo. for\n    //      :nth-child(2n+1), value might be '2n+1'\n\n    var endTag = function() {\n      // called when the tokenizer hits the end of a particular tag name.\n      // Re-sets state variables for tag matching and sets up the matcher\n      // to handle the next type of token (tag or operator).\n      if (inTag >= 0) {\n        var tv = (inTag == x) ? null : ts(inTag, x);\n        if (specials.indexOf(tv) < 0) {\n          currentPart.tag = tv;\n        } else {\n          currentPart.oper = tv;\n        }\n        inTag = -1;\n      }\n    };\n\n    var endId = function() {\n      // Called when the tokenizer might be at the end of an ID portion of a\n      // match.\n      if (inId >= 0) {\n        currentPart.id = ts(inId, x).replace(/\\\\/g, '');\n        inId = -1;\n      }\n    };\n\n    var endClass = function() {\n      // Called when the tokenizer might be at the end of a class name\n      // match. CSS allows for multiple classes, so we augment the\n      // current item with another class in its list.\n      if (inClass >= 0) {\n        currentPart.classes.push(ts(inClass + 1, x).replace(/\\\\/g, ''));\n        inClass = -1;\n      }\n    };\n\n    var endAll = function() {\n      // at the end of a simple fragment, so wall off the matches\n      endId(); endTag(); endClass();\n    };\n\n    var endPart = function() {\n      endAll();\n      if (inPseudo >= 0) {\n        currentPart.pseudos.push({ name: ts(inPseudo + 1, x) });\n      }\n      // Hint to the selector engine to tell it whether or not it\n      // needs to do any iteration. Many simple selectors don't, and\n      // we can avoid significant construction-time work by advising\n      // the system to skip them.\n      currentPart.loops = currentPart.pseudos.length ||\n                          currentPart.attrs.length ||\n                          currentPart.classes.length;\n\n      // save the full expression as a string\n      currentPart.oquery = currentPart.query = ts(pStart, x);\n\n\n      // otag/tag are hints to suggest to the system whether or not\n      // it's an operator or a tag. We save a copy of otag since the\n      // tag name is cast to upper-case in regular HTML matches. The\n      // system has a global switch to figure out if the current\n      // expression needs to be case sensitive or not and it will use\n      // otag or tag accordingly\n      currentPart.otag = currentPart.tag = (currentPart.oper) ?\n                                                     null :\n                                                     (currentPart.tag || '*');\n\n      if (currentPart.tag) {\n        // if we're in a case-insensitive HTML doc, we likely want\n        // the toUpperCase when matching on element.tagName. If we\n        // do it here, we can skip the string op per node\n        // comparison\n        currentPart.tag = currentPart.tag.toUpperCase();\n      }\n\n      // add the part to the list\n      if (queryParts.length && (queryParts[queryParts.length - 1].oper)) {\n        // operators are always infix, so we remove them from the\n        // list and attach them to the next match. The evaluator is\n        // responsible for sorting out how to handle them.\n        currentPart.infixOper = queryParts.pop();\n        currentPart.query = currentPart.infixOper.query + ' ' +\n            currentPart.query;\n      }\n      queryParts.push(currentPart);\n\n      currentPart = null;\n    };\n\n    // iterate over the query, character by character, building up a\n    // list of query part objects\n    for (; lc = cc, cc = query.charAt(x), x < ql; x++) {\n      //    cc: the current character in the match\n      //    lc: the last character (if any)\n\n      // someone is trying to escape something, so don't try to match any\n      // fragments. We assume we're inside a literal.\n      if (lc == '\\\\') {\n        continue;\n      }\n      if (!currentPart) { // a part was just ended or none has yet been created\n        // NOTE: I hate all this alloc, but it's shorter than writing tons of\n        // if's\n        pStart = x;\n        //  rules describe full CSS sub-expressions, like:\n        //    #someId\n        //    .className:first-child\n        //  but not:\n        //    thinger > div.howdy[type=thinger]\n        //  the individual components of the previous query would be\n        //  split into 3 parts that would be represented a structure\n        //  like:\n        //    [\n        //      {\n        //        query: 'thinger',\n        //        tag: 'thinger',\n        //      },\n        //      {\n        //        query: 'div.howdy[type=thinger]',\n        //        classes: ['howdy'],\n        //        infixOper: {\n        //          query: '>',\n        //          oper: '>',\n        //        }\n        //      },\n        //    ]\n        currentPart = {\n          query: null, // the full text of the part's rule\n          pseudos: [], // CSS supports multiple pseudo-class matches in a single\n              // rule\n          attrs: [],  // CSS supports multi-attribute match, so we need an array\n          classes: [], // class matches may be additive,\n              // e.g.: .thinger.blah.howdy\n          tag: null,  // only one tag...\n          oper: null, // ...or operator per component. Note that these wind up\n              // being exclusive.\n          id: null,   // the id component of a rule\n          getTag: function() {\n            return (caseSensitive) ? this.otag : this.tag;\n          }\n        };\n\n        // if we don't have a part, we assume we're going to start at\n        // the beginning of a match, which should be a tag name. This\n        // might fault a little later on, but we detect that and this\n        // iteration will still be fine.\n        inTag = x;\n      }\n\n      if (inBrackets >= 0) {\n        // look for a the close first\n        if (cc == ']') { // if we're in a [...] clause and we end, do assignment\n          if (!cp.attr) {\n            // no attribute match was previously begun, so we\n            // assume this is an attribute existence match in the\n            // form of [someAttributeName]\n            cp.attr = ts(inBrackets + 1, x);\n          } else {\n            // we had an attribute already, so we know that we're\n            // matching some sort of value, as in [attrName=howdy]\n            cp.matchFor = ts((inMatchFor || inBrackets + 1), x);\n          }\n          var cmf = cp.matchFor;\n          if (cmf) {\n            // try to strip quotes from the matchFor value. We want\n            // [attrName=howdy] to match the same\n            //  as [attrName = 'howdy' ]\n            if ((cmf.charAt(0) == '\"') || (cmf.charAt(0) == \"'\")) {\n              cp.matchFor = cmf.slice(1, -1);\n            }\n          }\n          // end the attribute by adding it to the list of attributes.\n          currentPart.attrs.push(cp);\n          cp = null; // necessary?\n          inBrackets = inMatchFor = -1;\n        } else if (cc == '=') {\n          // if the last char was an operator prefix, make sure we\n          // record it along with the '=' operator.\n          var addToCc = ('|~^$*'.indexOf(lc) >= 0) ? lc : '';\n          cp.type = addToCc + cc;\n          cp.attr = ts(inBrackets + 1, x - addToCc.length);\n          inMatchFor = x + 1;\n        }\n        // now look for other clause parts\n      } else if (inParens >= 0) {\n        // if we're in a parenthetical expression, we need to figure\n        // out if it's attached to a pseudo-selector rule like\n        // :nth-child(1)\n        if (cc == ')') {\n          if (inPseudo >= 0) {\n            cp.value = ts(inParens + 1, x);\n          }\n          inPseudo = inParens = -1;\n        }\n      } else if (cc == '#') {\n        // start of an ID match\n        endAll();\n        inId = x + 1;\n      } else if (cc == '.') {\n        // start of a class match\n        endAll();\n        inClass = x;\n      } else if (cc == ':') {\n        // start of a pseudo-selector match\n        endAll();\n        inPseudo = x;\n      } else if (cc == '[') {\n        // start of an attribute match.\n        endAll();\n        inBrackets = x;\n        // provide a new structure for the attribute match to fill-in\n        cp = {\n          /*=====\n          attr: null, type: null, matchFor: null\n          =====*/\n        };\n      } else if (cc == '(') {\n        // we really only care if we've entered a parenthetical\n        // expression if we're already inside a pseudo-selector match\n        if (inPseudo >= 0) {\n          // provide a new structure for the pseudo match to fill-in\n          cp = {name: ts(inPseudo + 1, x), value: null};\n          currentPart.pseudos.push(cp);\n        }\n        inParens = x;\n      } else if (\n        (cc == ' ') &&\n        // if it's a space char and the last char is too, consume the\n        // current one without doing more work\n        (lc != cc)\n      ) {\n        endPart();\n      }\n    }\n    return queryParts;\n  };\n\n\n  ////////////////////////////////////////////////////////////////////////\n  // DOM query infrastructure\n  ////////////////////////////////////////////////////////////////////////\n\n  var agree = function(first, second) {\n    // the basic building block of the yes/no chaining system. agree(f1,\n    // f2) generates a new function which returns the boolean results of\n    // both of the passed functions to a single logical-anded result. If\n    // either are not passed, the other is used exclusively.\n    if (!first) {\n      return second;\n    }\n    if (!second) {\n      return first;\n    }\n\n    return function() {\n      return first.apply(window, arguments) && second.apply(window, arguments);\n    }\n  };\n\n  /**\n   * @param {(number|string|Node)} i\n   * @param {Array=} opt_arr\n   */\n  function getArr(i, opt_arr) {\n    // helps us avoid array alloc when we don't need it\n    var r = opt_arr || [];\n    if (i) {\n      r.push(i);\n    }\n    return r;\n  }\n\n  var isElement = function(n) {\n    return (1 == n.nodeType);\n  };\n\n  // FIXME: need to coalesce getAttr with defaultGetter\n  var blank = '';\n  var getAttr = function(elem, attr) {\n    if (!elem) {\n      return blank;\n    }\n    if (attr == 'class') {\n      return elem.className || blank;\n    }\n    if (attr == 'for') {\n      return elem.htmlFor || blank;\n    }\n    if (attr == 'style') {\n      return elem.style.cssText || blank;\n    }\n    return (caseSensitive ? elem.getAttribute(attr) :\n        elem.getAttribute(attr, 2)) || blank;\n  };\n\n  var attrs = {\n    '*=': function(attr, value) {\n      return function(elem) {\n        // E[foo*=\"bar\"]\n        //    an E element whose \"foo\" attribute value contains\n        //    the substring \"bar\"\n        return (getAttr(elem, attr).indexOf(value) >= 0);\n      }\n    },\n    '^=': function(attr, value) {\n      // E[foo^=\"bar\"]\n      //    an E element whose \"foo\" attribute value begins exactly\n      //    with the string \"bar\"\n      return function(elem) {\n        return (getAttr(elem, attr).indexOf(value) == 0);\n      }\n    },\n    '$=': function(attr, value) {\n      // E[foo$=\"bar\"]\n      //    an E element whose \"foo\" attribute value ends exactly\n      //    with the string \"bar\"\n      var tval = ' ' + value;\n      return function(elem) {\n        var ea = ' ' + getAttr(elem, attr);\n        return (ea.lastIndexOf(tval) == (ea.length - tval.length));\n      }\n    },\n    '~=': function(attr, value) {\n      // E[foo~=\"bar\"]\n      //    an E element whose \"foo\" attribute value is a list of\n      //    space-separated values, one of which is exactly equal\n      //    to \"bar\"\n\n      var tval = ' ' + value + ' ';\n      return function(elem) {\n        var ea = ' ' + getAttr(elem, attr) + ' ';\n        return (ea.indexOf(tval) >= 0);\n      }\n    },\n    '|=': function(attr, value) {\n      // E[hreflang|=\"en\"]\n      //    an E element whose \"hreflang\" attribute has a\n      //    hyphen-separated list of values beginning (from the\n      //    left) with \"en\"\n      value = ' ' + value;\n      return function(elem) {\n        var ea = ' ' + getAttr(elem, attr);\n        return (\n          (ea == value) ||\n          (ea.indexOf(value + '-') == 0)\n        );\n      }\n    },\n    '=': function(attr, value) {\n      return function(elem) {\n        return (getAttr(elem, attr) == value);\n      }\n    }\n  };\n\n  // avoid testing for node type if we can. Defining this in the negative\n  // here to avoid negation in the fast path.\n  var noNextElementSibling = (\n    typeof goog.dom.getDocument().firstChild.nextElementSibling == 'undefined'\n  );\n  var nSibling = !noNextElementSibling ? 'nextElementSibling' : 'nextSibling';\n  var pSibling = !noNextElementSibling ?\n                    'previousElementSibling' :\n                    'previousSibling';\n  var simpleNodeTest = (noNextElementSibling ? isElement : goog.functions.TRUE);\n\n  var _lookLeft = function(node) {\n    while (node = node[pSibling]) {\n      if (simpleNodeTest(node)) {\n        return false;\n      }\n    }\n    return true;\n  };\n\n  var _lookRight = function(node) {\n    while (node = node[nSibling]) {\n      if (simpleNodeTest(node)) {\n        return false;\n      }\n    }\n    return true;\n  };\n\n  var getNodeIndex = function(node) {\n    var root = node.parentNode;\n    var i = 0,\n        tret = root[childNodesName],\n        ci = (node['_i'] || -1),\n        cl = (root['_l'] || -1);\n\n    if (!tret) {\n      return -1;\n    }\n    var l = tret.length;\n\n    // we calculate the parent length as a cheap way to invalidate the\n    // cache. It's not 100% accurate, but it's much more honest than what\n    // other libraries do\n    if (cl == l && ci >= 0 && cl >= 0) {\n      // if it's legit, tag and release\n      return ci;\n    }\n\n    // else re-key things\n    root['_l'] = l;\n    ci = -1;\n    var te = root['firstElementChild'] || root['firstChild'];\n    for (; te; te = te[nSibling]) {\n      if (simpleNodeTest(te)) {\n        te['_i'] = ++i;\n        if (node === te) {\n          // NOTE:\n          //  shortcutting the return at this step in indexing works\n          //  very well for benchmarking but we avoid it here since\n          //  it leads to potential O(n^2) behavior in sequential\n          //  getNodexIndex operations on a previously un-indexed\n          //  parent. We may revisit this at a later time, but for\n          //  now we just want to get the right answer more often\n          //  than not.\n          ci = i;\n        }\n      }\n    }\n    return ci;\n  };\n\n  var isEven = function(elem) {\n    return !((getNodeIndex(elem)) % 2);\n  };\n\n  var isOdd = function(elem) {\n    return (getNodeIndex(elem)) % 2;\n  };\n\n  var pseudos = {\n    'checked': function(name, condition) {\n      return function(elem) {\n        return elem.checked || elem.attributes['checked'];\n      }\n    },\n    'first-child': function() {\n      return _lookLeft;\n    },\n    'last-child': function() {\n      return _lookRight;\n    },\n    'only-child': function(name, condition) {\n      return function(node) {\n        if (!_lookLeft(node)) {\n          return false;\n        }\n        if (!_lookRight(node)) {\n          return false;\n        }\n        return true;\n      };\n    },\n    'empty': function(name, condition) {\n      return function(elem) {\n        // DomQuery and jQuery get this wrong, oddly enough.\n        // The CSS 3 selectors spec is pretty explicit about it, too.\n        var cn = elem.childNodes;\n        var cnl = elem.childNodes.length;\n        // if(!cnl) { return true; }\n        for (var x = cnl - 1; x >= 0; x--) {\n          var nt = cn[x].nodeType;\n          if ((nt === 1) || (nt == 3)) {\n            return false;\n          }\n        }\n        return true;\n      }\n    },\n    'contains': function(name, condition) {\n      var cz = condition.charAt(0);\n      if (cz == '\"' || cz == \"'\") { // Remove quotes.\n        condition = condition.slice(1, -1);\n      }\n      return function(elem) {\n        return (elem.innerHTML.indexOf(condition) >= 0);\n      }\n    },\n    'not': function(name, condition) {\n      var p = getQueryParts(condition)[0];\n      var ignores = { el: 1 };\n      if (p.tag != '*') {\n        ignores.tag = 1;\n      }\n      if (!p.classes.length) {\n        ignores.classes = 1;\n      }\n      var ntf = getSimpleFilterFunc(p, ignores);\n      return function(elem) {\n        return !ntf(elem);\n      }\n    },\n    'nth-child': function(name, condition) {\n      function pi(n) {\n        return parseInt(n, 10);\n      }\n      // avoid re-defining function objects if we can\n      if (condition == 'odd') {\n        return isOdd;\n      } else if (condition == 'even') {\n        return isEven;\n      }\n      // FIXME: can we shorten this?\n      if (condition.indexOf('n') != -1) {\n        var tparts = condition.split('n', 2);\n        var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1;\n        var idx = tparts[1] ? pi(tparts[1]) : 0;\n        var lb = 0, ub = -1;\n        if (pred > 0) {\n          if (idx < 0) {\n            idx = (idx % pred) && (pred + (idx % pred));\n          } else if (idx > 0) {\n            if (idx >= pred) {\n              lb = idx - idx % pred;\n            }\n            idx = idx % pred;\n          }\n        } else if (pred < 0) {\n          pred *= -1;\n          // idx has to be greater than 0 when pred is negative;\n          // shall we throw an error here?\n          if (idx > 0) {\n            ub = idx;\n            idx = idx % pred;\n          }\n        }\n        if (pred > 0) {\n          return function(elem) {\n            var i = getNodeIndex(elem);\n            return (i >= lb) && (ub < 0 || i <= ub) && ((i % pred) == idx);\n          }\n        } else {\n          condition = idx;\n        }\n      }\n      var ncount = pi(condition);\n      return function(elem) {\n        return (getNodeIndex(elem) == ncount);\n      }\n    }\n  };\n\n  var defaultGetter = (legacyIE) ? function(cond) {\n    var clc = cond.toLowerCase();\n    if (clc == 'class') {\n      cond = 'className';\n    }\n    return function(elem) {\n      return caseSensitive ? elem.getAttribute(cond) : elem[cond] || elem[clc];\n    }\n  } : function(cond) {\n    return function(elem) {\n      return elem && elem.getAttribute && elem.hasAttribute(cond);\n    }\n  };\n\n  var getSimpleFilterFunc = function(query, ignores) {\n    // Generates a node tester function based on the passed query part. The\n    // query part is one of the structures generated by the query parser when it\n    // creates the query AST. The 'ignores' object specifies which (if any)\n    // tests to skip, allowing the system to avoid duplicating work where it\n    // may have already been taken into account by other factors such as how\n    // the nodes to test were fetched in the first place.\n    if (!query) {\n      return goog.functions.TRUE;\n    }\n    ignores = ignores || {};\n\n    var ff = null;\n\n    if (!ignores.el) {\n      ff = agree(ff, isElement);\n    }\n\n    if (!ignores.tag) {\n      if (query.tag != '*') {\n        ff = agree(ff, function(elem) {\n          return (elem && (elem.tagName == query.getTag()));\n        });\n      }\n    }\n\n    if (!ignores.classes) {\n      goog.array.forEach(query.classes, function(cname, idx, arr) {\n        // Get the class name.\n        var re = new RegExp('(?:^|\\\\s)' + cname + '(?:\\\\s|$)');\n        ff = agree(ff, function(elem) {\n          return re.test(elem.className);\n        });\n        ff.count = idx;\n      });\n    }\n\n    if (!ignores.pseudos) {\n      goog.array.forEach(query.pseudos, function(pseudo) {\n        var pn = pseudo.name;\n        if (pseudos[pn]) {\n          ff = agree(ff, pseudos[pn](pn, pseudo.value));\n        }\n      });\n    }\n\n    if (!ignores.attrs) {\n      goog.array.forEach(query.attrs, function(attr) {\n        var matcher;\n        var a = attr.attr;\n        // type, attr, matchFor\n        if (attr.type && attrs[attr.type]) {\n          matcher = attrs[attr.type](a, attr.matchFor);\n        } else if (a.length) {\n          matcher = defaultGetter(a);\n        }\n        if (matcher) {\n          ff = agree(ff, matcher);\n        }\n      });\n    }\n\n    if (!ignores.id) {\n      if (query.id) {\n        ff = agree(ff, function(elem) {\n          return (!!elem && (elem.id == query.id));\n        });\n      }\n    }\n\n    if (!ff) {\n      if (!('default' in ignores)) {\n        ff = goog.functions.TRUE;\n      }\n    }\n    return ff;\n  };\n\n  var nextSiblingIterator = function(filterFunc) {\n    return function(node, ret, bag) {\n      while (node = node[nSibling]) {\n        if (noNextElementSibling && (!isElement(node))) {\n          continue;\n        }\n        if (\n          (!bag || _isUnique(node, bag)) &&\n          filterFunc(node)\n        ) {\n          ret.push(node);\n        }\n        break;\n      }\n      return ret;\n    };\n  };\n\n  var nextSiblingsIterator = function(filterFunc) {\n    return function(root, ret, bag) {\n      var te = root[nSibling];\n      while (te) {\n        if (simpleNodeTest(te)) {\n          if (bag && !_isUnique(te, bag)) {\n            break;\n          }\n          if (filterFunc(te)) {\n            ret.push(te);\n          }\n        }\n        te = te[nSibling];\n      }\n      return ret;\n    };\n  };\n\n  // Get an array of child *elements*, skipping text and comment nodes\n  var _childElements = function(filterFunc) {\n    filterFunc = filterFunc || goog.functions.TRUE;\n    return function(root, ret, bag) {\n      var te, x = 0, tret = root[childNodesName];\n      while (te = tret[x++]) {\n        if (\n          simpleNodeTest(te) &&\n          (!bag || _isUnique(te, bag)) &&\n          (filterFunc(te, x))\n        ) {\n          ret.push(te);\n        }\n      }\n      return ret;\n    };\n  };\n\n  // test to see if node is below root\n  var _isDescendant = function(node, root) {\n    var pn = node.parentNode;\n    while (pn) {\n      if (pn == root) {\n        break;\n      }\n      pn = pn.parentNode;\n    }\n    return !!pn;\n  };\n\n  var _getElementsFuncCache = {};\n\n  var getElementsFunc = function(query) {\n    var retFunc = _getElementsFuncCache[query.query];\n    // If we've got a cached dispatcher, just use that.\n    if (retFunc) {\n      return retFunc;\n    }\n    // Else, generate a new one.\n\n    // NOTE:\n    //    This function returns a function that searches for nodes and\n    //    filters them. The search may be specialized by infix operators\n    //    (\">\", \"~\", or \"+\") else it will default to searching all\n    //    descendants (the \" \" selector). Once a group of children is\n    //    found, a test function is applied to weed out the ones we\n    //    don't want. Many common cases can be fast-pathed. We spend a\n    //    lot of cycles to create a dispatcher that doesn't do more work\n    //    than necessary at any point since, unlike this function, the\n    //    dispatchers will be called every time. The logic of generating\n    //    efficient dispatchers looks like this in pseudo code:\n    //\n    //    # if it's a purely descendant query (no \">\", \"+\", or \"~\" modifiers)\n    //    if infixOperator == \" \":\n    //      if only(id):\n    //        return def(root):\n    //          return d.byId(id, root);\n    //\n    //      elif id:\n    //        return def(root):\n    //          return filter(d.byId(id, root));\n    //\n    //      elif cssClass && getElementsByClassName:\n    //        return def(root):\n    //          return filter(root.getElementsByClassName(cssClass));\n    //\n    //      elif only(tag):\n    //        return def(root):\n    //          return root.getElementsByTagName(tagName);\n    //\n    //      else:\n    //        # search by tag name, then filter\n    //        return def(root):\n    //          return filter(root.getElementsByTagName(tagName||\"*\"));\n    //\n    //    elif infixOperator == \">\":\n    //      # search direct children\n    //      return def(root):\n    //        return filter(root.children);\n    //\n    //    elif infixOperator == \"+\":\n    //      # search next sibling\n    //      return def(root):\n    //        return filter(root.nextElementSibling);\n    //\n    //    elif infixOperator == \"~\":\n    //      # search rightward siblings\n    //      return def(root):\n    //        return filter(nextSiblings(root));\n\n    var io = query.infixOper;\n    var oper = (io ? io.oper : '');\n    // The default filter func which tests for all conditions in the query\n    // part. This is potentially inefficient, so some optimized paths may\n    // re-define it to test fewer things.\n    var filterFunc = getSimpleFilterFunc(query, { el: 1 });\n    var qt = query.tag;\n    var wildcardTag = ('*' == qt);\n    var ecs = goog.dom.getDocument()['getElementsByClassName'];\n\n    if (!oper) {\n      // If there's no infix operator, then it's a descendant query. ID\n      // and \"elements by class name\" variants can be accelerated so we\n      // call them out explicitly:\n      if (query.id) {\n        // Testing shows that the overhead of goog.functions.TRUE() is\n        // acceptable and can save us some bytes vs. re-defining the function\n        // everywhere.\n        filterFunc = (!query.loops && wildcardTag) ?\n          goog.functions.TRUE :\n          getSimpleFilterFunc(query, { el: 1, id: 1 });\n\n        retFunc = function(root, arr) {\n          var te = goog.dom.getDomHelper(root).getElement(query.id);\n          if (!te || !filterFunc(te)) {\n            return;\n          }\n          if (9 == root.nodeType) { // If root's a doc, we just return directly.\n            return getArr(te, arr);\n          } else { // otherwise check ancestry\n            if (_isDescendant(te, root)) {\n              return getArr(te, arr);\n            }\n          }\n        };\n      } else if (\n        ecs &&\n        // isAlien check. Workaround for Prototype.js being totally evil/dumb.\n        /\\{\\s*\\[native code\\]\\s*\\}/.test(String(ecs)) &&\n        query.classes.length &&\n        // WebKit bug where quirks-mode docs select by class w/o case\n        // sensitivity.\n        !cssCaseBug\n      ) {\n        // it's a class-based query and we've got a fast way to run it.\n\n        // ignore class and ID filters since we will have handled both\n        filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 });\n        var classesString = query.classes.join(' ');\n        retFunc = function(root, arr) {\n          var ret = getArr(0, arr), te, x = 0;\n          var tret = root.getElementsByClassName(classesString);\n          while ((te = tret[x++])) {\n            if (filterFunc(te, root)) {\n              ret.push(te);\n            }\n          }\n          return ret;\n        };\n\n      } else if (!wildcardTag && !query.loops) {\n        // it's tag only. Fast-path it.\n        retFunc = function(root, arr) {\n          var ret = getArr(0, arr), te, x = 0;\n          var tret = root.getElementsByTagName(query.getTag());\n          while ((te = tret[x++])) {\n            ret.push(te);\n          }\n          return ret;\n        };\n      } else {\n        // the common case:\n        //    a descendant selector without a fast path. By now it's got\n        //    to have a tag selector, even if it's just \"*\" so we query\n        //    by that and filter\n        filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 });\n        retFunc = function(root, arr) {\n          var ret = getArr(0, arr), te, x = 0;\n          // we use getTag() to avoid case sensitivity issues\n          var tret = root.getElementsByTagName(query.getTag());\n          while (te = tret[x++]) {\n            if (filterFunc(te, root)) {\n              ret.push(te);\n            }\n          }\n          return ret;\n        };\n      }\n    } else {\n      // the query is scoped in some way. Instead of querying by tag we\n      // use some other collection to find candidate nodes\n      var skipFilters = { el: 1 };\n      if (wildcardTag) {\n        skipFilters.tag = 1;\n      }\n      filterFunc = getSimpleFilterFunc(query, skipFilters);\n      if ('+' == oper) {\n        retFunc = nextSiblingIterator(filterFunc);\n      } else if ('~' == oper) {\n        retFunc = nextSiblingsIterator(filterFunc);\n      } else if ('>' == oper) {\n        retFunc = _childElements(filterFunc);\n      }\n    }\n    // cache it and return\n    return _getElementsFuncCache[query.query] = retFunc;\n  };\n\n  var filterDown = function(root, queryParts) {\n    // NOTE:\n    //    this is the guts of the DOM query system. It takes a list of\n    //    parsed query parts and a root and finds children which match\n    //    the selector represented by the parts\n    var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret;\n\n    for (var i = 0; i < qpl; i++) {\n      ret = [];\n      qp = queryParts[i];\n      x = candidates.length - 1;\n      if (x > 0) {\n        // if we have more than one root at this level, provide a new\n        // hash to use for checking group membership but tell the\n        // system not to post-filter us since we will already have been\n        // guaranteed to be unique\n        bag = {};\n        ret.nozip = true;\n      }\n      var gef = getElementsFunc(qp);\n      for (var j = 0; te = candidates[j]; j++) {\n        // for every root, get the elements that match the descendant\n        // selector, adding them to the 'ret' array and filtering them\n        // via membership in this level's bag. If there are more query\n        // parts, then this level's return will be used as the next\n        // level's candidates\n        gef(te, ret, bag);\n      }\n      if (!ret.length) { break; }\n      candidates = ret;\n    }\n    return ret;\n  };\n\n  ////////////////////////////////////////////////////////////////////////\n  // the query runner\n  ////////////////////////////////////////////////////////////////////////\n\n  // these are the primary caches for full-query results. The query\n  // dispatcher functions are generated then stored here for hash lookup in\n  // the future\n  var _queryFuncCacheDOM = {},\n    _queryFuncCacheQSA = {};\n\n  // this is the second level of splitting, from full-length queries (e.g.,\n  // 'div.foo .bar') into simple query expressions (e.g., ['div.foo',\n  // '.bar'])\n  var getStepQueryFunc = function(query) {\n    var qparts = getQueryParts(goog.string.trim(query));\n\n    // if it's trivial, avoid iteration and zipping costs\n    if (qparts.length == 1) {\n      // We optimize this case here to prevent dispatch further down the\n      // chain, potentially slowing things down. We could more elegantly\n      // handle this in filterDown(), but it's slower for simple things\n      // that need to be fast (e.g., '#someId').\n      var tef = getElementsFunc(qparts[0]);\n      return function(root) {\n        var r = tef(root, []);\n        if (r) { r.nozip = true; }\n        return r;\n      }\n    }\n\n    // otherwise, break it up and return a runner that iterates over the parts\n    // recursively\n    return function(root) {\n      return filterDown(root, qparts);\n    }\n  };\n\n  // NOTES:\n  //  * we can't trust QSA for anything but document-rooted queries, so\n  //    caching is split into DOM query evaluators and QSA query evaluators\n  //  * caching query results is dirty and leak-prone (or, at a minimum,\n  //    prone to unbounded growth). Other toolkits may go this route, but\n  //    they totally destroy their own ability to manage their memory\n  //    footprint. If we implement it, it should only ever be with a fixed\n  //    total element reference # limit and an LRU-style algorithm since JS\n  //    has no weakref support. Caching compiled query evaluators is also\n  //    potentially problematic, but even on large documents the size of the\n  //    query evaluators is often < 100 function objects per evaluator (and\n  //    LRU can be applied if it's ever shown to be an issue).\n  //  * since IE's QSA support is currently only for HTML documents and even\n  //    then only in IE 8's 'standards mode', we have to detect our dispatch\n  //    route at query time and keep 2 separate caches. Ugg.\n\n  var qsa = 'querySelectorAll';\n\n  // some versions of Safari provided QSA, but it was buggy and crash-prone.\n  // We need to detect the right 'internal' webkit version to make this work.\n  var qsaAvail = (\n    !!goog.dom.getDocument()[qsa] &&\n    // see #5832\n    (!goog.userAgent.WEBKIT || goog.userAgent.isVersionOrHigher('526'))\n  );\n\n  /**\n   * @param {(string|Array)} query\n   * @param {boolean=} opt_forceDOM\n   * @return {function((string|Node)): !Array}\n   */\n  var getQueryFunc = function(query, opt_forceDOM) {\n\n    if (qsaAvail) {\n      // if we've got a cached variant and we think we can do it, run it!\n      var qsaCached = _queryFuncCacheQSA[query];\n      if (qsaCached && !opt_forceDOM) {\n        return qsaCached;\n      }\n    }\n\n    // else if we've got a DOM cached variant, assume that we already know\n    // all we need to and use it\n    var domCached = _queryFuncCacheDOM[query];\n    if (domCached) {\n      return domCached;\n    }\n\n    // TODO:\n    //    today we're caching DOM and QSA branches separately so we\n    //    recalc useQSA every time. If we had a way to tag root+query\n    //    efficiently, we'd be in good shape to do a global cache.\n\n    var qcz = query.charAt(0);\n    var nospace = (-1 == query.indexOf(' '));\n\n    // byId searches are wicked fast compared to QSA, even when filtering\n    // is required\n    if ((query.indexOf('#') >= 0) && (nospace)) {\n      opt_forceDOM = true;\n    }\n\n    var useQSA = (\n      qsaAvail && (!opt_forceDOM) &&\n      // as per CSS 3, we can't currently start w/ combinator:\n      //    http://www.w3.org/TR/css3-selectors/#w3cselgrammar\n      (specials.indexOf(qcz) == -1) &&\n      // IE's QSA impl sucks on pseudos\n      (!legacyIE || (query.indexOf(':') == -1)) &&\n\n      (!(cssCaseBug && (query.indexOf('.') >= 0))) &&\n\n      // FIXME:\n      //    need to tighten up browser rules on ':contains' and '|=' to\n      //    figure out which aren't good\n      (query.indexOf(':contains') == -1) &&\n      (query.indexOf('|=') == -1) // some browsers don't understand it\n    );\n\n    // TODO:\n    //    if we've got a descendant query (e.g., '> .thinger' instead of\n    //    just '.thinger') in a QSA-able doc, but are passed a child as a\n    //    root, it should be possible to give the item a synthetic ID and\n    //    trivially rewrite the query to the form '#synid > .thinger' to\n    //    use the QSA branch\n\n\n    if (useQSA) {\n      var tq = (specials.indexOf(query.charAt(query.length - 1)) >= 0) ?\n            (query + ' *') : query;\n      return _queryFuncCacheQSA[query] = function(root) {\n        try {\n          // the QSA system contains an egregious spec bug which\n          // limits us, effectively, to only running QSA queries over\n          // entire documents.  See:\n          //    http://ejohn.org/blog/thoughts-on-queryselectorall/\n          //  despite this, we can also handle QSA runs on simple\n          //  selectors, but we don't want detection to be expensive\n          //  so we're just checking for the presence of a space char\n          //  right now. Not elegant, but it's cheaper than running\n          //  the query parser when we might not need to\n          if (!((9 == root.nodeType) || nospace)) {\n            throw new Error('');\n          }\n          var r = root[qsa](tq);\n          // IE QSA queries may incorrectly include comment nodes, so we throw\n          // the zipping function into 'remove' comments mode instead of the\n          // normal 'skip it' which every other QSA-clued browser enjoys\n          // skip expensive duplication checks and just wrap in an array.\n          if (legacyIE) {\n            r.commentStrip = true;\n          } else {\n            r.nozip = true;\n          }\n          return r;\n        } catch (e) {\n          // else run the DOM branch on this query, ensuring that we\n          // default that way in the future\n          return getQueryFunc(query, true)(root);\n        }\n      };\n    } else {\n      // DOM branch\n      var parts = query.split(/\\s*,\\s*/);\n      return _queryFuncCacheDOM[query] =\n                 ((parts.length < 2) ?\n                      // if not a compound query (e.g., '.foo, .bar'), cache and\n                      // return a dispatcher\n                      getStepQueryFunc(query) :\n                      // if it *is* a complex query, break it up into its\n                      // constituent parts and return a dispatcher that will\n                      // merge the parts when run\n                      function(root) {\n                        var pindex =\n                                0,  // avoid array alloc for every invocation\n                            ret = [],\n                            tp;\n                        while (tp = parts[pindex++]) {\n                          ret = ret.concat(getStepQueryFunc(tp)(root));\n                        }\n                        return ret;\n                      });\n    }\n  };\n\n  var _zipIdx = 0;\n\n  // NOTE:\n  //    this function is Moo inspired, but our own impl to deal correctly\n  //    with XML in IE\n  var _nodeUID = legacyIE ? function(node) {\n    if (caseSensitive) {\n      // XML docs don't have uniqueID on their nodes\n      return node.getAttribute('_uid') ||\n          node.setAttribute('_uid', ++_zipIdx) || _zipIdx;\n\n    } else {\n      return node.uniqueID;\n    }\n  } :\n  function(node) {\n    return (node['_uid'] || (node['_uid'] = ++_zipIdx));\n  };\n\n  // determine if a node in is unique in a 'bag'. In this case we don't want\n  // to flatten a list of unique items, but rather just tell if the item in\n  // question is already in the bag. Normally we'd just use hash lookup to do\n  // this for us but IE's DOM is busted so we can't really count on that. On\n  // the upside, it gives us a built in unique ID function.\n  var _isUnique = function(node, bag) {\n    if (!bag) {\n      return 1;\n    }\n    var id = _nodeUID(node);\n    if (!bag[id]) {\n      return bag[id] = 1;\n    }\n    return 0;\n  };\n\n  // attempt to efficiently determine if an item in a list is a dupe,\n  // returning a list of 'uniques', hopefully in document order\n  var _zipIdxName = '_zipIdx';\n  var _zip = function(arr) {\n    if (arr && arr.nozip) {\n      return arr;\n    }\n    var ret = [];\n    if (!arr || !arr.length) {\n      return ret;\n    }\n    if (arr[0]) {\n      ret.push(arr[0]);\n    }\n    if (arr.length < 2) {\n      return ret;\n    }\n\n    _zipIdx++;\n\n    // we have to fork here for IE and XML docs because we can't set\n    // expandos on their nodes (apparently). *sigh*\n    if (legacyIE && caseSensitive) {\n      var szidx = _zipIdx + '';\n      arr[0].setAttribute(_zipIdxName, szidx);\n      for (var x = 1, te; te = arr[x]; x++) {\n        if (arr[x].getAttribute(_zipIdxName) != szidx) {\n          ret.push(te);\n        }\n        te.setAttribute(_zipIdxName, szidx);\n      }\n    } else if (legacyIE && arr.commentStrip) {\n      try {\n        for (var x = 1, te; te = arr[x]; x++) {\n          if (isElement(te)) {\n            ret.push(te);\n          }\n        }\n      } catch (e) { /* squelch */ }\n    } else {\n      if (arr[0]) {\n        arr[0][_zipIdxName] = _zipIdx;\n      }\n      for (var x = 1, te; te = arr[x]; x++) {\n        if (arr[x][_zipIdxName] != _zipIdx) {\n          ret.push(te);\n        }\n        te[_zipIdxName] = _zipIdx;\n      }\n    }\n    return ret;\n  };\n\n  /**\n   * The main executor. Type specification from above.\n   * @param {string|Array} query The query.\n   * @param {(string|Node)=} opt_root The root.\n   * @return {!Array} The elements that matched the query.\n   */\n  var query = function(query, opt_root) {\n    // NOTE: elementsById is not currently supported\n    // NOTE: ignores xpath-ish queries for now\n\n    //Set list constructor to desired value. This can change\n    //between calls, so always re-assign here.\n\n    if (!query) {\n      return [];\n    }\n\n    if (query.constructor == Array) {\n      return /** @type {!Array} */ (query);\n    }\n\n    if (!goog.isString(query)) {\n      return [query];\n    }\n\n    var root = opt_root;\n    if (goog.isString(root)) {\n      root = goog.dom.getElement(root);\n      if (!root) {\n        return [];\n      }\n    }\n\n    root = root || goog.dom.getDocument();\n    var od = root.ownerDocument || root.documentElement;\n\n    // throw the big case sensitivity switch\n\n    // NOTE:\n    //    Opera in XHTML mode doesn't detect case-sensitivity correctly\n    //    and it's not clear that there's any way to test for it\n    caseSensitive =\n        root.contentType && root.contentType == 'application/xml' ||\n        goog.userAgent.OPERA &&\n          (root.doctype || od.toString() == '[object XMLDocument]') ||\n        !!od &&\n        (legacyIE ? od.xml : (root.xmlVersion || od.xmlVersion));\n\n    // NOTE:\n    //    adding 'true' as the 2nd argument to getQueryFunc is useful for\n    //    testing the DOM branch without worrying about the\n    //    behavior/performance of the QSA branch.\n    var r = getQueryFunc(query)(root);\n\n    // FIXME(slightlyoff):\n    //    need to investigate this branch WRT dojo:#8074 and dojo:#8075\n    if (r && r.nozip) {\n      return r;\n    }\n    return _zip(r);\n  };\n\n  // FIXME: need to add infrastructure for post-filtering pseudos, ala :last\n  query.pseudos = pseudos;\n\n  return query;\n})();\n\n// TODO(arv): Please don't export here since it clobbers dead code elimination.\ngoog.exportSymbol('goog.dom.query', goog.dom.query);\ngoog.exportSymbol('goog.dom.query.pseudos', goog.dom.query.pseudos);\n","^;",1569048148000,"^<",["^=",["~$goog.dom","~$goog.functions","~$goog.string","^>","~$goog.userAgent","^["]],"^C",["^ ","^D","\n        The Google Closure Library is a collection of JavaScript code\n        designed for use with the Google Closure JavaScript Compiler.\n\n        This non-official distribution was prepared by the ClojureScript\n        team at http://clojure.org/\n\n        This package contains extensions to the Google Closure Library\n        using third-party components, which may be distributed under\n        licenses other than the Apache license. Licenses for individual\n        library components may be found in source-code comments.\n    ","^E","^F","^G","^H","^I","Google Closure Library Third-Party Extensions","^J","^K","^L","http://code.google.com/p/closure-library/","^M","^N","^O",["^K","0.0-20190213-2033d5d9"],"^P","0.0-20190213-2033d5d9"],"^L",["^Q","jar:file:/Users/clojure/.m2/repository/org/clojure/google-closure-library-third-party/0.0-20190213-2033d5d9/google-closure-library-third-party-0.0-20190213-2033d5d9.jar!/goog/dojo/dom/query.js"],"^R",["^=",["~$goog.dom.query"]],"^T",true,"^U",["^>","^[","^13","^14","^15","^16"]],["^ ","^3",[1569048148000],"^4","goog.loremipsum.text.loremipsum.js","^5",["^6","goog/loremipsum/text/loremipsum.js"],"^7","goog/loremipsum/text/loremipsum.js","^8","^9","^:","//   Copyright 2009 The Closure Library Authors. All Rights Reserved.\n\n/**\n * @fileoverview A generator of lorem ipsum text based on the python\n * implementation at http://code.google.com/p/lorem-ipsum-generator/.\n *\n */\n\ngoog.provide('goog.text.LoremIpsum');\n\ngoog.require('goog.array');\ngoog.require('goog.math');\ngoog.require('goog.string');\ngoog.require('goog.structs.Map');\ngoog.require('goog.structs.Set');\n\n\n\n/**\n * Generates random strings of \"lorem ipsum\" text, based on the word\n * distribution of a sample text, using the words in a dictionary.\n * @constructor\n */\ngoog.text.LoremIpsum = function() {\n  this.generateChains_(this.sample_);\n  this.generateStatistics_(this.sample_);\n\n  this.initializeDictionary_(this.dictionary_);\n};\n\n\n/**\n * Delimiters that end sentences.\n * @type {Array<string>}\n * @private\n */\ngoog.text.LoremIpsum.DELIMITERS_SENTENCES_ = ['.', '?', '!'];\n\n\n/**\n * Regular expression for spliting a text into sentences.\n * @type {RegExp}\n * @private\n */\ngoog.text.LoremIpsum.SENTENCE_SPLIT_REGEX_ = /[\\.\\?\\!]/;\n\n\n/**\n * Delimiters that end words.\n * @type {Array<string>}\n * @private\n */\ngoog.text.LoremIpsum.DELIMITERS_WORDS_ = [',', '.', '?', '!'];\n\n\n/**\n * Regular expression for spliting text into words.\n * @type {RegExp}\n * @private\n */\ngoog.text.LoremIpsum.WORD_SPLIT_REGEX_ = /\\s/;\n\n\n/**\n * Words that can be used in the generated output.\n * Maps a word-length to a list of words of that length.\n * @type {goog.structs.Map}\n * @private\n */\ngoog.text.LoremIpsum.prototype.words_;\n\n\n/**\n * Chains of three words that appear in the sample text\n * Maps a pair of word-lengths to a third word-length and an optional\n * piece of trailing punctuation (for example, a period, comma, etc.).\n * @type {goog.structs.Map}\n * @private\n */\ngoog.text.LoremIpsum.prototype.chains_;\n\n\n/** @private {!Object<string, !Array>} */\ngoog.text.LoremIpsum.prototype.chainKeys_;\n\n\n/**\n * Pairs of word-lengths that can appear at the beginning of sentences.\n * @type {Array}\n */\ngoog.text.LoremIpsum.prototype.starts_;\n\n\n/**\n * Averange sentence length in words.\n * @type {number}\n * @private\n */\ngoog.text.LoremIpsum.prototype.sentenceMean_;\n\n\n/**\n * Sigma (sqrt of variance) for the sentence length in words.\n * @type {number}\n * @private\n */\ngoog.text.LoremIpsum.prototype.sentenceSigma_;\n\n\n/**\n * Averange paragraph length in sentences.\n * @type {number}\n * @private\n */\ngoog.text.LoremIpsum.prototype.paragraphMean_;\n\n\n/**\n * Sigma (sqrt of variance) for the paragraph length in sentences.\n * @type {number}\n * @private\n */\ngoog.text.LoremIpsum.prototype.paragraphSigma_;\n\n\n/**\n * Generates the chains and starts values required for sentence generation.\n * @param {string} sample The same text.\n * @private\n */\ngoog.text.LoremIpsum.prototype.generateChains_ = function(sample) {\n  var words = goog.text.LoremIpsum.splitWords_(sample);\n  var wordInfo = goog.array.map(words, goog.text.LoremIpsum.getWordInfo_);\n\n  /** @type {!Array<number>} */\n  var previous = [0, 0];\n  var previousKey = previous.join('-');\n  var chains = new goog.structs.Map();\n  var starts = [previousKey];\n  var chainKeys = {};\n\n  goog.array.forEach(wordInfo, function(pair) {\n    var chain = chains.get(previousKey);\n    if (chain) {\n      chain.push(pair);\n    } else {\n      chain = [pair];\n      chains.set(previousKey, chain);\n    }\n\n    if (goog.array.contains(\n        goog.text.LoremIpsum.DELIMITERS_SENTENCES_, pair[1])) {\n      starts.push(previousKey);\n    }\n    chainKeys[previousKey] = previous;\n    previous = [previous[1], pair[0]];\n    previousKey = previous.join('-');\n  });\n\n  if (chains.getCount() > 0) {\n    this.chains_ = chains;\n    this.starts_ = starts;\n    this.chainKeys_ = chainKeys;\n  } else {\n    throw Error('Could not generate chains from sample text.');\n  }\n};\n\n\n/**\n * Calculates the mean and standard deviation of sentence and paragraph lengths.\n * @param {string} sample The same text.\n * @private\n */\ngoog.text.LoremIpsum.prototype.generateStatistics_ = function(sample) {\n  this.generateSentenceStatistics_(sample);\n  this.generateParagraphStatistics_(sample);\n};\n\n\n/**\n * Calculates the mean and standard deviation of the lengths of sentences\n * (in words) in a sample text.\n * @param {string} sample The same text.\n * @private\n */\ngoog.text.LoremIpsum.prototype.generateSentenceStatistics_ = function(sample) {\n  var sentences = goog.array.filter(\n      goog.text.LoremIpsum.splitSentences_(sample),\n      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);\n\n  var sentenceLengths = goog.array.map(\n      goog.array.map(sentences, goog.text.LoremIpsum.splitWords_),\n      goog.text.LoremIpsum.arrayLength_);\n  this.sentenceMean_ = goog.math.average.apply(null, sentenceLengths);\n  this.sentenceSigma_ = goog.math.standardDeviation.apply(\n      null, sentenceLengths);\n};\n\n\n/**\n * Calculates the mean and standard deviation of the lengths of paragraphs\n * (in sentences) in a sample text.\n * @param {string} sample The same text.\n * @private\n */\ngoog.text.LoremIpsum.prototype.generateParagraphStatistics_ = function(sample) {\n  var paragraphs = goog.array.filter(\n      goog.text.LoremIpsum.splitParagraphs_(sample),\n      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);\n\n  var paragraphLengths = goog.array.map(\n      goog.array.map(paragraphs, goog.text.LoremIpsum.splitSentences_),\n      goog.text.LoremIpsum.arrayLength_);\n\n  this.paragraphMean_ = goog.math.average.apply(null, paragraphLengths);\n  this.paragraphSigma_ = goog.math.standardDeviation.apply(\n      null, paragraphLengths);\n};\n\n\n/**\n * Sets the generator to use a given selection of words for generating\n * sentences with.\n * @param {string} dictionary The dictionary to use.\n * @private\n */\ngoog.text.LoremIpsum.prototype.initializeDictionary_ = function(dictionary) {\n  var dictionaryWords = goog.text.LoremIpsum.splitWords_(dictionary);\n\n  var words = new goog.structs.Map();\n  goog.array.forEach(dictionaryWords, function(word) {\n    var set = words.get(word.length);\n    if (!set) {\n      set = new goog.structs.Set();\n      words.set(word.length, set);\n    }\n    set.add(word);\n  });\n\n  this.words_ = words;\n};\n\n\n/**\n * Picks a random starting chain.\n * @return {Array<string>} The starting key.\n * @private\n */\ngoog.text.LoremIpsum.prototype.chooseRandomStart_ = function() {\n  var key = /** @type {string} */ (goog.text.LoremIpsum.randomChoice_(\n      this.starts_));\n  return this.chainKeys_[key];\n};\n\n\n/**\n * Generates a single sentence, of random length.\n * @param {boolean=} opt_startWithLorem Whether to start the setnence with the\n *     standard \"Lorem ipsum...\" first sentence.\n * @return {string} The generated sentence.\n */\ngoog.text.LoremIpsum.prototype.generateSentence = function(opt_startWithLorem) {\n  if (this.chains_.getCount() == 0 || this.starts_.length == 0) {\n    throw Error('No chains created');\n  }\n\n  if (this.words_.getCount() == 0) {\n    throw Error('No dictionary');\n  }\n\n  // The length of the sentence is a normally distributed random variable.\n  var sentenceLength = goog.text.LoremIpsum.randomNormal_(\n      this.sentenceMean_, this.sentenceSigma_);\n  sentenceLength = Math.max(Math.floor(sentenceLength), 1);\n\n  var wordDelimiter = ''; // Defined here in case while loop doesn't run\n\n  // Start the sentence with \"Lorem ipsum...\", if desired\n  var sentence;\n  if (opt_startWithLorem) {\n    var lorem = 'lorem ipsum dolor sit amet, consecteteur adipiscing elit';\n    sentence = goog.text.LoremIpsum.splitWords_(lorem);\n    if (sentence.length > sentenceLength) {\n      sentence.length = sentenceLength;\n    }\n    var lastWord = sentence[sentence.length - 1];\n    var lastChar = lastWord.substring(lastWord.length - 1);\n    if (goog.array.contains(goog.text.LoremIpsum.DELIMITERS_WORDS_, lastChar)) {\n      wordDelimiter = lastChar;\n    }\n  } else {\n    sentence = [];\n  }\n\n  var previous = [];\n  var previousKey = '';\n  // Generate a sentence from the \"chains\"\n  while (sentence.length < sentenceLength) {\n    // If the current starting point is invalid, choose another randomly\n    if (!this.chains_.containsKey(previousKey)) {\n      previous = this.chooseRandomStart_();\n      previousKey = previous.join('-');\n    }\n\n    // Choose the next \"chain\" to go to. This determines the next word\n    // length we'll use, and whether there is e.g. a comma at the end of\n    // the word.\n    var chain = /** @type {Array} */ (goog.text.LoremIpsum.randomChoice_(\n        /** @type {Array} */ (this.chains_.get(previousKey))));\n    var wordLength = chain[0];\n\n    // If the word delimiter contained in the chain is also a sentence\n    // delimiter, then we don't include it because we don't want the\n    // sentence to end prematurely (we want the length to match the\n    // sentence_length value).\n    //debugger;\n    if (goog.array.contains(goog.text.LoremIpsum.DELIMITERS_SENTENCES_,\n        chain[1])) {\n      wordDelimiter = '';\n    } else {\n      wordDelimiter = chain[1];\n    }\n\n    // Choose a word randomly that matches (or closely matches) the\n    // length we're after.\n    var closestLength = goog.text.LoremIpsum.chooseClosest(\n        this.words_.getKeys(), wordLength);\n    var word = goog.text.LoremIpsum.randomChoice_(\n        this.words_.get(closestLength).getValues());\n\n    sentence.push(word + wordDelimiter);\n    previous = [previous[1], wordLength];\n    previousKey = previous.join('-');\n  }\n\n  // Finish the sentence off with capitalisation, a period and\n  // form it into a string\n  sentence = sentence.join(' ');\n  sentence = sentence.slice(0, 1).toUpperCase() + sentence.slice(1);\n  if (sentence.substring(sentence.length - 1) == wordDelimiter) {\n    sentence = sentence.slice(0, sentence.length - 1);\n  }\n  return sentence + '.';\n};\n\n\n/**\n * Generates a single lorem ipsum paragraph, of random length.\n * @param {boolean=} opt_startWithLorem Whether to start the sentence with the\n *     standard \"Lorem ipsum...\" first sentence.\n * @return {string} The generated sentence.\n */\ngoog.text.LoremIpsum.prototype.generateParagraph = function(\n    opt_startWithLorem) {\n  // The length of the paragraph is a normally distributed random variable.\n  var paragraphLength = goog.text.LoremIpsum.randomNormal_(\n      this.paragraphMean_, this.paragraphSigma_);\n  paragraphLength = Math.max(Math.floor(paragraphLength), 1);\n\n  // Construct a paragraph from a number of sentences.\n  var paragraph = [];\n  var startWithLorem = opt_startWithLorem;\n  while (paragraph.length < paragraphLength) {\n    var sentence = this.generateSentence(startWithLorem);\n    paragraph.push(sentence);\n    startWithLorem = false;\n  }\n\n  // Form the paragraph into a string.\n  paragraph = paragraph.join(' ');\n  return paragraph;\n};\n\n\n/**\n * Splits a piece of text into paragraphs.\n * @param {string} text The text to split.\n * @return {Array<string>} An array of paragraphs.\n * @private\n */\ngoog.text.LoremIpsum.splitParagraphs_ = function(text) {\n  return text.split('\\n');\n};\n\n\n/**\n * Splits a piece of text into sentences.\n * @param {string} text The text to split.\n * @return {Array<string>} An array of sentences.\n * @private\n */\ngoog.text.LoremIpsum.splitSentences_ = function(text) {\n  return goog.array.filter(\n      text.split(goog.text.LoremIpsum.SENTENCE_SPLIT_REGEX_),\n      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);\n};\n\n\n/**\n * Splits a piece of text into words..\n * @param {string} text The text to split.\n * @return {Array<string>} An array of words.\n * @private\n */\ngoog.text.LoremIpsum.splitWords_ = function(text) {\n  return goog.array.filter(\n      text.split(goog.text.LoremIpsum.WORD_SPLIT_REGEX_),\n      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);\n};\n\n\n/**\n * Returns the text is not empty or just whitespace.\n * @param {string} text The text to check.\n * @return {boolean} Whether the text is nether empty nor whitespace.\n * @private\n */\ngoog.text.LoremIpsum.isNotEmptyOrWhitepace_ = function(text) {\n  return goog.string.trim(text).length > 0;\n};\n\n\n/**\n * Returns the length of an array. Written as a function so it can be used\n * as a function parameter.\n * @param {Array} array The array to check.\n * @return {number} The length of the array.\n * @private\n */\ngoog.text.LoremIpsum.arrayLength_ = function(array) {\n  return array.length;\n};\n\n\n/**\n * Find the number in the list of values that is closest to the target.\n * @param {Array<number>|Array<string>} values The values.\n * @param {number} target The target value.\n * @return {number} The closest value.\n */\ngoog.text.LoremIpsum.chooseClosest = function(values, target) {\n  var closest = Number(values[0]);\n  goog.array.forEach(values, function(value) {\n    if (Math.abs(target - Number(value)) < Math.abs(target - closest)) {\n      closest = value;\n    }\n  });\n\n  return closest;\n};\n\n\n/**\n * Gets info about a word used as part of the lorem ipsum algorithm.\n * @param {string} word The word to check.\n * @return {Array} A two element array. The first element is the size of the\n *    word. The second element is the delimter used in the word.\n * @private\n */\ngoog.text.LoremIpsum.getWordInfo_ = function(word) {\n  var ret;\n  goog.array.some(goog.text.LoremIpsum.DELIMITERS_WORDS_,\n      function(delimiter) {\n        if (goog.string.endsWith(word, delimiter)) {\n          ret = [word.length - delimiter.length, delimiter];\n          return true;\n        }\n        return false;\n      }\n  );\n  return ret || [word.length, ''];\n};\n\n\n/**\n * Constant used for {@link #randomNormal_}.\n * @type {number}\n * @private\n */\ngoog.text.LoremIpsum.NV_MAGICCONST_ = 4 * Math.exp(-0.5) / Math.sqrt(2.0);\n\n\n/**\n * Generates a random number for a normal distribution with the specified\n * mean and sigma.\n * @param {number} mu The mean of the distribution.\n * @param {number} sigma The sigma of the distribution.\n * @return {number}\n * @private\n */\ngoog.text.LoremIpsum.randomNormal_ = function(mu, sigma) {\n  while (true) {\n    var u1 = Math.random();\n    var u2 = 1.0 - Math.random();\n    var z = goog.text.LoremIpsum.NV_MAGICCONST_ * (u1 - 0.5) / u2;\n    var zz = z * z / 4.0;\n    if (zz <= -Math.log(u2)) {\n      break;\n    }\n  }\n  return mu + z * sigma;\n};\n\n\n/**\n * Picks a random element of the array.\n * @param {Array} array The array to pick from.\n * @return {*} An element from the array.\n * @private\n */\ngoog.text.LoremIpsum.randomChoice_ = function(array) {\n  return array[goog.math.randomInt(array.length)];\n};\n\n\n/**\n * Dictionary of words for lorem ipsum.\n * @private {string}\n */\ngoog.text.LoremIpsum.DICT_ =\n    'a ac accumsan ad adipiscing aenean aliquam aliquet amet ante ' +\n    'aptent arcu at auctor augue bibendum blandit class commodo ' +\n    'condimentum congue consectetuer consequat conubia convallis cras ' +\n    'cubilia cum curabitur curae cursus dapibus diam dictum dictumst ' +\n    'dignissim dis dolor donec dui duis egestas eget eleifend elementum ' +\n    'elit eni enim erat eros est et etiam eu euismod facilisi facilisis ' +\n    'fames faucibus felis fermentum feugiat fringilla fusce gravida ' +\n    'habitant habitasse hac hendrerit hymenaeos iaculis id imperdiet ' +\n    'in inceptos integer interdum ipsum justo lacinia lacus laoreet ' +\n    'lectus leo libero ligula litora lobortis lorem luctus maecenas ' +\n    'magna magnis malesuada massa mattis mauris metus mi molestie ' +\n    'mollis montes morbi mus nam nascetur natoque nec neque netus ' +\n    'nibh nisi nisl non nonummy nostra nulla nullam nunc odio orci ' +\n    'ornare parturient pede pellentesque penatibus per pharetra ' +\n    'phasellus placerat platea porta porttitor posuere potenti praesent ' +\n    'pretium primis proin pulvinar purus quam quis quisque rhoncus ' +\n    'ridiculus risus rutrum sagittis sapien scelerisque sed sem semper ' +\n    'senectus sit sociis sociosqu sodales sollicitudin suscipit ' +\n    'suspendisse taciti tellus tempor tempus tincidunt torquent tortor ' +\n    'tristique turpis ullamcorper ultrices ultricies urna ut varius ve ' +\n    'vehicula vel velit venenatis vestibulum vitae vivamus viverra ' +\n    'volutpat vulputate';\n\n\n/**\n * A sample to use for generating the distribution of word and sentence lengths\n * in lorem ipsum.\n * @type {string}\n * @private\n */\ngoog.text.LoremIpsum.SAMPLE_ =\n    'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean ' +\n    'commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus ' +\n    'et magnis dis parturient montes, nascetur ridiculus mus. Donec quam ' +\n    'felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla ' +\n    'consequat massa quis enim. Donec pede justo, fringilla vel, aliquet ' +\n    'nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, ' +\n    'venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. ' +\n    'Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean ' +\n    'vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat ' +\n    'vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra ' +\n    'quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius ' +\n    'laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel ' +\n    'augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.\\n\\n' +\n\n    'Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem ' +\n    'quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam ' +\n    'nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec ' +\n    'odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis ' +\n    'faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus ' +\n    'tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales ' +\n    'sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit ' +\n    'cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend ' +\n    'sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, ' +\n    'metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis ' +\n    'hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci ' +\n    'luctus et ultrices posuere cubilia Curae; In ac dui quis mi ' +\n    'consectetuer lacinia.\\n\\n' +\n\n    'Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet ' +\n    'nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ' +\n    'ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent ' +\n    'adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy ' +\n    'metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros ' +\n    'et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, ' +\n    'nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit ' +\n    'risus. Phasellus nec sem in justo pellentesque facilisis. Etiam ' +\n    'imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus ' +\n    'non, auctor et, hendrerit quis, nisi.\\n\\n' +\n\n    'Curabitur ligula sapien, tincidunt non, euismod vitae, posuere ' +\n    'imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed ' +\n    'cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus ' +\n    'accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci ' +\n    'luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis ' +\n    'porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis ' +\n    'orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, ' +\n    'bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede ' +\n    'sit amet augue. In turpis. Pellentesque posuere. Praesent turpis.\\n\\n' +\n\n    'Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu ' +\n    'sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales ' +\n    'nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse ' +\n    'pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, ' +\n    'nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in ' +\n    'faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id ' +\n    'purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum ' +\n    'mollis diam. Pellentesque ut neque. Pellentesque habitant morbi ' +\n    'tristique senectus et netus et malesuada fames ac turpis egestas.\\n\\n' +\n\n    'In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac ' +\n    'felis quis tortor malesuada pretium. Pellentesque auctor neque nec ' +\n    'urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean ' +\n    'viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et ' +\n    'netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis ' +\n    'pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna.\\n\\n' +\n\n    'In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare ' +\n    'lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ' +\n    'ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. ' +\n    'Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, ' +\n    'quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at ' +\n    'pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo ' +\n    'quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam ' +\n    'sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce ' +\n    'risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis ' +\n    'vulputate lorem.\\n\\n' +\n\n    'Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, ' +\n    'dui et placerat feugiat, eros pede varius nisi, condimentum viverra ' +\n    'felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, ' +\n    'varius ut, felis. In auctor lobortis lacus. Quisque libero metus, ' +\n    'condimentum nec, tempor a, commodo mollis, magna. Vestibulum ' +\n    'ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia ' +\n    'erat. Praesent blandit laoreet nibh.\\n\\n' +\n\n    'Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, ' +\n    'neque sit amet convallis pulvinar, justo nulla eleifend augue, ac ' +\n    'auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. ' +\n    'Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. ' +\n    'Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In ' +\n    'hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis ' +\n    'mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat ' +\n    'nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, ' +\n    'lacus.\\n\\n' +\n\n    'Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, ' +\n    'dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi ' +\n    'congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin ' +\n    'fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit ' +\n    'amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam ' +\n    'gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac ' +\n    'sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus ' +\n    'blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in ' +\n    'libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In ' +\n    'consectetuer turpis ut velit. Nulla sit amet est. Praesent metus ' +\n    'tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ' +\n    'ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse ' +\n    'feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum ' +\n    'nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac ' +\n    'massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, ' +\n    'iaculis quis, molestie non, velit.\\n\\n' +\n\n    'Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. ' +\n    'Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus ' +\n    'at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet ' +\n    'velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. ' +\n    'Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, ' +\n    'sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla ' +\n    'facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere ' +\n    'iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. ' +\n    'Curabitur suscipit suscipit tellus.\\n\\n' +\n\n    'Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id ' +\n    'nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu ' +\n    'pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante ' +\n    'odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque ' +\n    'suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ' +\n    'ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu ' +\n    'quis ligula mattis placerat. Duis lobortis massa imperdiet quam. ' +\n    'Suspendisse potenti.\\n\\n' +\n\n    'Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, ' +\n    'lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat ' +\n    'volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam ' +\n    'eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ' +\n    'ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta ' +\n    'dolor. Class aptent taciti sociosqu ad litora torquent per conubia ' +\n    'nostra, per inceptos hymenaeos.\\n\\n' +\n\n    'Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. ' +\n    'Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. ' +\n    'Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, ' +\n    'elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum ' +\n    'sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus ' +\n    'non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. ' +\n    'Vestibulum eu odio.\\n\\n' +\n\n    'Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. ' +\n    'Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique ' +\n    'sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse ' +\n    'faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, ' +\n    'vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce ' +\n    'fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae ' +\n    'odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. ' +\n    'Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus ' +\n    'consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna ' +\n    'cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit ' +\n    'quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar ' +\n    'varius.\\n\\n';\n\n\n/**\n * Sample that the generated text is based on .\n * @private {string}\n */\ngoog.text.LoremIpsum.prototype.sample_ = goog.text.LoremIpsum.SAMPLE_;\n\n\n/**\n * Dictionary of words.\n * @private {string}\n */\ngoog.text.LoremIpsum.prototype.dictionary_ = goog.text.LoremIpsum.DICT_;\n","^;",1569048148000,"^<",["^=",["^15","~$goog.structs.Map","^>","~$goog.math","^[","~$goog.structs.Set"]],"^C",["^ ","^D","\n        The Google Closure Library is a collection of JavaScript code\n        designed for use with the Google Closure JavaScript Compiler.\n\n        This non-official distribution was prepared by the ClojureScript\n        team at http://clojure.org/\n\n        This package contains extensions to the Google Closure Library\n        using third-party components, which may be distributed under\n        licenses other than the Apache license. Licenses for individual\n        library components may be found in source-code comments.\n    ","^E","^F","^G","^H","^I","Google Closure Library Third-Party Extensions","^J","^K","^L","http://code.google.com/p/closure-library/","^M","^N","^O",["^K","0.0-20190213-2033d5d9"],"^P","0.0-20190213-2033d5d9"],"^L",["^Q","jar:file:/Users/clojure/.m2/repository/org/clojure/google-closure-library-third-party/0.0-20190213-2033d5d9/google-closure-library-third-party-0.0-20190213-2033d5d9.jar!/goog/loremipsum/text/loremipsum.js"],"^R",["^=",["~$goog.text.LoremIpsum"]],"^T",true,"^U",["^>","^[","^19","^15","^18","^1:"]],["^ ","^3",[1569048148000],"^4","goog.caja.string.html.htmlparser.js","^5",["^6","goog/caja/string/html/htmlparser.js"],"^7","goog/caja/string/html/htmlparser.js","^8","^9","^:","// Copyright 2006-2008, The Google Caja project.\n// Modifications Copyright 2009 The Closure Library Authors.\n// All Rights Reserved\n\n/**\n * @license Portions of this code are from the google-caja project, received by\n * Google under the Apache license (http://code.google.com/p/google-caja/).\n * All other code is Copyright 2009 Google, Inc. All Rights Reserved.\n\n// Copyright (C) 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n */\n\n/**\n * @fileoverview A Html SAX parser.\n *\n * Examples of usage of the `goog.string.html.HtmlParser`:\n * <pre>\n *   var handler = new MyCustomHtmlVisitorHandlerThatExtendsHtmlSaxHandler();\n *   var parser = new goog.string.html.HtmlParser();\n *   parser.parse(handler, '<html><a href=\"google.com\">link found!</a></html>');\n * </pre>\n *\n * TODO(user, msamuel): validate sanitizer regex against the HTML5 grammar at\n * http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html\n * http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html\n * http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html\n * http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html\n *\n * @author msamuel@google.com (Mike Samuel)\n * @supported IE6+, FF1.5+, Chrome 3.0+, Safari and Opera 10.\n */\n\ngoog.provide('goog.string.html');\ngoog.provide('goog.string.html.HtmlParser');\ngoog.provide('goog.string.html.HtmlParser.EFlags');\ngoog.provide('goog.string.html.HtmlParser.Elements');\ngoog.provide('goog.string.html.HtmlParser.Entities');\ngoog.provide('goog.string.html.HtmlSaxHandler');\n\n\n\n/**\n * An Html parser: `parse` takes a string and calls methods on\n * `goog.string.html.HtmlSaxHandler` while it is visiting it.\n *\n * @constructor\n */\ngoog.string.html.HtmlParser = function() {\n};\n\n\n/**\n * HTML entities that are encoded/decoded.\n * TODO(user): use `goog.string.htmlEncode` instead.\n * @type {!Object<string, string>}\n */\ngoog.string.html.HtmlParser.Entities = {\n  'lt': '<',\n  'gt': '>',\n  'amp': '&',\n  'nbsp': '\\u00a0',\n  'quot': '\"',\n  'apos': '\\''\n};\n\n\n/**\n * The html eflags, used internally on the parser.\n * @enum {number}\n */\ngoog.string.html.HtmlParser.EFlags = {\n  OPTIONAL_ENDTAG: 1,\n  EMPTY: 2,\n  CDATA: 4,\n  RCDATA: 8,\n  UNSAFE: 16,\n  FOLDABLE: 32\n};\n\n\n/**\n * A map of element to a bitmap of flags it has, used internally on the parser.\n * @type {Object<string,number>}\n */\ngoog.string.html.HtmlParser.Elements = {\n  'a': 0,\n  'abbr': 0,\n  'acronym': 0,\n  'address': 0,\n  'applet': goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'area': goog.string.html.HtmlParser.EFlags.EMPTY,\n  'b': 0,\n  'base': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'basefont': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'bdo': 0,\n  'big': 0,\n  'blockquote': 0,\n  'body': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |\n      goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.FOLDABLE,\n  'br': goog.string.html.HtmlParser.EFlags.EMPTY,\n  'button': 0,\n  'canvas': 0,\n  'caption': 0,\n  'center': 0,\n  'cite': 0,\n  'code': 0,\n  'col': goog.string.html.HtmlParser.EFlags.EMPTY,\n  'colgroup': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'dd': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'del': 0,\n  'dfn': 0,\n  'dir': 0,\n  'div': 0,\n  'dl': 0,\n  'dt': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'em': 0,\n  'fieldset': 0,\n  'font': 0,\n  'form': 0,\n  'frame': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'frameset': goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'h1': 0,\n  'h2': 0,\n  'h3': 0,\n  'h4': 0,\n  'h5': 0,\n  'h6': 0,\n  'head': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |\n      goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.FOLDABLE,\n  'hr': goog.string.html.HtmlParser.EFlags.EMPTY,\n  'html': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |\n      goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.FOLDABLE,\n  'i': 0,\n  'iframe': goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.CDATA,\n  'img': goog.string.html.HtmlParser.EFlags.EMPTY,\n  'input': goog.string.html.HtmlParser.EFlags.EMPTY,\n  'ins': 0,\n  'isindex': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'kbd': 0,\n  'label': 0,\n  'legend': 0,\n  'li': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'link': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'map': 0,\n  'menu': 0,\n  'meta': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'noframes': goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.CDATA,\n  'noscript': goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.CDATA,\n  'object': goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'ol': 0,\n  'optgroup': 0,\n  'option': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'p': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'param': goog.string.html.HtmlParser.EFlags.EMPTY |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'pre': 0,\n  'q': 0,\n  's': 0,\n  'samp': 0,\n  'script': goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.CDATA,\n  'select': 0,\n  'small': 0,\n  'span': 0,\n  'strike': 0,\n  'strong': 0,\n  'style': goog.string.html.HtmlParser.EFlags.UNSAFE |\n      goog.string.html.HtmlParser.EFlags.CDATA,\n  'sub': 0,\n  'sup': 0,\n  'table': 0,\n  'tbody': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'td': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'textarea': goog.string.html.HtmlParser.EFlags.RCDATA,\n  'tfoot': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'th': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'thead': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'title': goog.string.html.HtmlParser.EFlags.RCDATA |\n      goog.string.html.HtmlParser.EFlags.UNSAFE,\n  'tr': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,\n  'tt': 0,\n  'u': 0,\n  'ul': 0,\n  'var': 0\n};\n\n\n/**\n * Regular expression that matches &s.\n * @type {RegExp}\n * @package\n */\ngoog.string.html.HtmlParser.AMP_RE = /&/g;\n\n\n/**\n * Regular expression that matches loose &s.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.LOOSE_AMP_RE_ =\n    /&([^a-z#]|#(?:[^0-9x]|x(?:[^0-9a-f]|$)|$)|$)/gi;\n\n\n/**\n * Regular expression that matches <.\n * @type {RegExp}\n * @package\n */\ngoog.string.html.HtmlParser.LT_RE = /</g;\n\n\n/**\n * Regular expression that matches >.\n * @type {RegExp}\n * @package\n */\ngoog.string.html.HtmlParser.GT_RE = />/g;\n\n\n/**\n * Regular expression that matches \".\n * @type {RegExp}\n * @package\n */\ngoog.string.html.HtmlParser.QUOTE_RE = /\\\"/g;\n\n\n/**\n * Regular expression that matches =.\n * @type {RegExp}\n * @package\n */\ngoog.string.html.HtmlParser.EQUALS_RE = /=/g;\n\n\n/**\n * Regular expression that matches null characters.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.NULL_RE_ = /\\0/g;\n\n\n/**\n * Regular expression that matches entities.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.ENTITY_RE_ = /&(#\\d+|#x[0-9A-Fa-f]+|\\w+);/g;\n\n\n/**\n * Regular expression that matches decimal numbers.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.DECIMAL_ESCAPE_RE_ = /^#(\\d+)$/;\n\n\n/**\n * Regular expression that matches hexadecimal numbers.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.HEX_ESCAPE_RE_ = /^#x([0-9A-Fa-f]+)$/;\n\n\n/**\n * Regular expression that matches the next token to be processed.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.INSIDE_TAG_TOKEN_ = new RegExp(\n    // Don't capture space.\n    '^\\\\s*(?:' +\n    // Capture an attribute name in group 1, and value in group 3.\n    // We capture the fact that there was an attribute in group 2, since\n    // interpreters are inconsistent in whether a group that matches nothing\n    // is null, undefined, or the empty string.\n    ('(?:' +\n    '([a-z][a-z-]*)' +                   // attribute name\n    ('(' +                               // optionally followed\n    '\\\\s*=\\\\s*' +\n    ('(' +\n             // A double quoted string.\n             '\\\"[^\\\"]*\\\"' +\n             // A single quoted string.\n             '|\\'[^\\']*\\'' +\n             // The positive lookahead is used to make sure that in\n             // <foo bar= baz=boo>, the value for bar is blank, not \"baz=boo\".\n             '|(?=[a-z][a-z-]*\\\\s*=)' +\n             // An unquoted value that is not an attribute name.\n             // We know it is not an attribute name because the previous\n             // zero-width match would've eliminated that possibility.\n             '|[^>\\\"\\'\\\\s]*' +\n             ')'\n             ) +\n    ')'\n    ) + '?' +\n    ')'\n    ) +\n    // End of tag captured in group 3.\n    '|(/?>)' +\n    // Don't capture cruft\n    '|[^a-z\\\\s>]+)',\n    'i');\n\n\n/**\n * Regular expression that matches the next token to be processed when we are\n * outside a tag.\n * @type {RegExp}\n * @private\n */\ngoog.string.html.HtmlParser.OUTSIDE_TAG_TOKEN_ = new RegExp(\n    '^(?:' +\n    // Entity captured in group 1.\n    '&(\\\\#[0-9]+|\\\\#[x][0-9a-f]+|\\\\w+);' +\n    // Comment, doctypes, and processing instructions not captured.\n    '|<[!]--[\\\\s\\\\S]*?-->|<!\\\\w[^>]*>|<\\\\?[^>*]*>' +\n    // '/' captured in group 2 for close tags, and name captured in group 3.\n    '|<(/)?([a-z][a-z0-9]*)' +\n    // Text captured in group 4.\n    '|([^<&>]+)' +\n    // Cruft captured in group 5.\n    '|([<&>]))',\n    'i');\n\n\n/**\n * Given a SAX-like `goog.string.html.HtmlSaxHandler` parses a\n * `htmlText` and lets the `handler` know the structure while\n * visiting the nodes.\n *\n * @param {goog.string.html.HtmlSaxHandler} handler The HtmlSaxHandler that will\n *     receive the events.\n * @param {string} htmlText The html text.\n */\ngoog.string.html.HtmlParser.prototype.parse = function(handler, htmlText) {\n  var htmlLower = null;\n  var inTag = false;  // True iff we're currently processing a tag.\n  var attribs = [];  // Accumulates attribute names and values.\n  /** @type {string|undefined} */\n  var tagName = undefined;  // The name of the tag currently being processed.\n  var eflags;  // The element flags for the current tag.\n  var openTag;  // True if the current tag is an open tag.\n\n  // Lets the handler know that we are starting to parse the document.\n  handler.startDoc();\n\n  // Consumes tokens from the htmlText and stops once all tokens are processed.\n  while (htmlText) {\n    var regex = inTag ?\n        goog.string.html.HtmlParser.INSIDE_TAG_TOKEN_ :\n        goog.string.html.HtmlParser.OUTSIDE_TAG_TOKEN_;\n    // Gets the next token\n    var m = htmlText.match(regex);\n    // And removes it from the string\n    htmlText = htmlText.substring(m[0].length);\n\n    // TODO(goto): cleanup this code breaking it into separate methods.\n    if (inTag) {\n      if (m[1]) { // Attribute.\n        // SetAttribute with uppercase names doesn't work on IE6.\n        var attribName = goog.string.html.toLowerCase(m[1]);\n        var decodedValue;\n        if (m[2]) {\n          var encodedValue = m[3];\n          switch (encodedValue.charCodeAt(0)) {  // Strip quotes.\n            case 34: case 39:\n              encodedValue = encodedValue.substring(\n                  1, encodedValue.length - 1);\n              break;\n          }\n          decodedValue = this.unescapeEntities_(this.stripNULs_(encodedValue));\n        } else {\n          // Use name as value for valueless attribs, so\n          //   <input type=checkbox checked>\n          // gets attributes ['type', 'checkbox', 'checked', 'checked']\n          decodedValue = attribName;\n        }\n        attribs.push(attribName, decodedValue);\n      } else if (m[4]) {\n        if (eflags !== void 0) {  // False if not in whitelist.\n          if (openTag) {\n            if (handler.startTag) {\n              handler.startTag(/** @type {string} */ (tagName), attribs);\n            }\n          } else {\n            if (handler.endTag) {\n              handler.endTag(/** @type {string} */ (tagName));\n            }\n          }\n        }\n\n        if (openTag && (eflags &\n            (goog.string.html.HtmlParser.EFlags.CDATA |\n             goog.string.html.HtmlParser.EFlags.RCDATA))) {\n          if (htmlLower === null) {\n            htmlLower = goog.string.html.toLowerCase(htmlText);\n          } else {\n            htmlLower = htmlLower.substring(\n                htmlLower.length - htmlText.length);\n          }\n          var dataEnd = htmlLower.indexOf('</' + tagName);\n          if (dataEnd < 0) {\n            dataEnd = htmlText.length;\n          }\n          if (eflags & goog.string.html.HtmlParser.EFlags.CDATA) {\n            if (handler.cdata) {\n              handler.cdata(htmlText.substring(0, dataEnd));\n            }\n          } else if (handler.rcdata) {\n            handler.rcdata(\n                this.normalizeRCData_(htmlText.substring(0, dataEnd)));\n          }\n          htmlText = htmlText.substring(dataEnd);\n        }\n\n        tagName = eflags = openTag = void 0;\n        attribs.length = 0;\n        inTag = false;\n      }\n    } else {\n      if (m[1]) {  // Entity.\n        handler.pcdata(m[0]);\n      } else if (m[3]) {  // Tag.\n        openTag = !m[2];\n        inTag = true;\n        tagName = goog.string.html.toLowerCase(m[3]);\n        eflags = goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName) ?\n            goog.string.html.HtmlParser.Elements[tagName] : void 0;\n      } else if (m[4]) {  // Text.\n        handler.pcdata(m[4]);\n      } else if (m[5]) {  // Cruft.\n        switch (m[5]) {\n          case '<': handler.pcdata('&lt;'); break;\n          case '>': handler.pcdata('&gt;'); break;\n          default: handler.pcdata('&amp;'); break;\n        }\n      }\n    }\n  }\n\n  // Lets the handler know that we are done parsing the document.\n  handler.endDoc();\n};\n\n\n/**\n * Decodes an HTML entity.\n *\n * @param {string} name The content between the '&' and the ';'.\n * @return {string} A single unicode code-point as a string.\n * @private\n */\ngoog.string.html.HtmlParser.prototype.lookupEntity_ = function(name) {\n  // TODO(goto): use {goog.string.htmlDecode} instead ?\n  // TODO(goto): &pi; is different from &Pi;\n  name = goog.string.html.toLowerCase(name);\n  if (goog.string.html.HtmlParser.Entities.hasOwnProperty(name)) {\n    return goog.string.html.HtmlParser.Entities[name];\n  }\n  var m = name.match(goog.string.html.HtmlParser.DECIMAL_ESCAPE_RE_);\n  if (m) {\n    return String.fromCharCode(parseInt(m[1], 10));\n  } else if (m = name.match(goog.string.html.HtmlParser.HEX_ESCAPE_RE_)) {\n    return String.fromCharCode(parseInt(m[1], 16));\n  }\n  return '';\n};\n\n\n/**\n * Removes null characters on the string.\n * @param {string} s The string to have the null characters removed.\n * @return {string} A string without null characters.\n * @private\n */\ngoog.string.html.HtmlParser.prototype.stripNULs_ = function(s) {\n  return s.replace(goog.string.html.HtmlParser.NULL_RE_, '');\n};\n\n\n/**\n * The plain text of a chunk of HTML CDATA which possibly containing.\n *\n * TODO(goto): use `goog.string.unescapeEntities` instead ?\n * @param {string} s A chunk of HTML CDATA.  It must not start or end inside\n *   an HTML entity.\n * @return {string} The unescaped entities.\n * @private\n */\ngoog.string.html.HtmlParser.prototype.unescapeEntities_ = function(s) {\n  return s.replace(\n      goog.string.html.HtmlParser.ENTITY_RE_, goog.bind(\n          function(fullEntity, name) {\n               return this.lookupEntity_(name);\n          }, this));\n};\n\n\n/**\n * Escape entities in RCDATA that can be escaped without changing the meaning.\n * @param {string} rcdata The RCDATA string we want to normalize.\n * @return {string} A normalized version of RCDATA.\n * @private\n */\ngoog.string.html.HtmlParser.prototype.normalizeRCData_ = function(rcdata) {\n  return rcdata.\n      replace(goog.string.html.HtmlParser.LOOSE_AMP_RE_, '&amp;$1').\n      replace(goog.string.html.HtmlParser.LT_RE, '&lt;').\n      replace(goog.string.html.HtmlParser.GT_RE, '&gt;');\n};\n\n\n/**\n * TODO(goto): why isn't this in the string package ? does this solves any\n * real problem ? move it to the goog.string package if it does.\n *\n * @param {string} str The string to lower case.\n * @return {string} The str in lower case format.\n */\ngoog.string.html.toLowerCase = function(str) {\n  // The below may not be true on browsers in the Turkish locale.\n  if ('script' === 'SCRIPT'.toLowerCase()) {\n    return str.toLowerCase();\n  } else {\n    return str.replace(/[A-Z]/g, function(ch) {\n      return String.fromCharCode(ch.charCodeAt(0) | 32);\n    });\n  }\n};\n\n\n\n/**\n * An interface to the `goog.string.html.HtmlParser` visitor, that gets\n * called while the HTML is being parsed.\n *\n * @interface\n */\ngoog.string.html.HtmlSaxHandler = function() {\n};\n\n\n/**\n * Handler called when the parser found a new tag.\n * @param {string} name The name of the tag that is starting.\n * @param {Array<string>} attributes The attributes of the tag.\n */\ngoog.string.html.HtmlSaxHandler.prototype.startTag = goog.abstractMethod;\n\n\n/**\n * Handler called when the parser found a closing tag.\n * @param {string} name The name of the tag that is ending.\n */\ngoog.string.html.HtmlSaxHandler.prototype.endTag = goog.abstractMethod;\n\n\n/**\n * Handler called when PCDATA is found.\n * @param {string} text The PCDATA text found.\n */\ngoog.string.html.HtmlSaxHandler.prototype.pcdata = goog.abstractMethod;\n\n\n/**\n * Handler called when RCDATA is found.\n * @param {string} text The RCDATA text found.\n */\ngoog.string.html.HtmlSaxHandler.prototype.rcdata = goog.abstractMethod;\n\n\n/**\n * Handler called when CDATA is found.\n * @param {string} text The CDATA text found.\n */\ngoog.string.html.HtmlSaxHandler.prototype.cdata = goog.abstractMethod;\n\n\n/**\n * Handler called when the parser is starting to parse the document.\n */\ngoog.string.html.HtmlSaxHandler.prototype.startDoc = goog.abstractMethod;\n\n\n/**\n * Handler called when the parsing is done.\n */\ngoog.string.html.HtmlSaxHandler.prototype.endDoc = goog.abstractMethod;\n","^;",1569048148000,"^<",["^=",["^>"]],"^C",["^ ","^D","\n        The Google Closure Library is a collection of JavaScript code\n        designed for use with the Google Closure JavaScript Compiler.\n\n        This non-official distribution was prepared by the ClojureScript\n        team at http://clojure.org/\n\n        This package contains extensions to the Google Closure Library\n        using third-party components, which may be distributed under\n        licenses other than the Apache license. Licenses for individual\n        library components may be found in source-code comments.\n    ","^E","^F","^G","^H","^I","Google Closure Library Third-Party Extensions","^J","^K","^L","http://code.google.com/p/closure-library/","^M","^N","^O",["^K","0.0-20190213-2033d5d9"],"^P","0.0-20190213-2033d5d9"],"^L",["^Q","jar:file:/Users/clojure/.m2/repository/org/clojure/google-closure-library-third-party/0.0-20190213-2033d5d9/google-closure-library-third-party-0.0-20190213-2033d5d9.jar!/goog/caja/string/html/htmlparser.js"],"^R",["^=",["~$goog.string.html.HtmlParser.EFlags","~$goog.string.html","~$goog.string.html.HtmlParser.Elements","~$goog.string.html.HtmlParser","~$goog.string.html.HtmlSaxHandler","~$goog.string.html.HtmlParser.Entities"]],"^T",true,"^U",["^>"]]],"~:data-readers",null,"~:shadow.build.classpath/CACHE-TIMESTAMP",1569150978000]