Unicorns
-All the things
-diff --git a/js/bower.json b/js/bower.json
index 1f67648e5e..9b8f9d96a6 100644
--- a/js/bower.json
+++ b/js/bower.json
@@ -2,7 +2,8 @@
"name": "gallery",
"homepage": "https://github.com/owncloud/gallery",
"authors": [
- "Olivier Paroz The two classes that are needed for zoomable images are:
- *
- * The two classes that are needed for zoomable VR panoramas (requires WebGL) are:
- *
- * Usage:
- *
- * @example
- * var bsi = new bigshot.Image (
- * new bigshot.ImageParameters ({
- * basePath : "/bigshot.php?file=myshot.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_div")
- * }));
- *
- * @param values named parameter map, see the fields below for parameter names and types.
- * @see bigshot.Image
- */
-bigshot.ImageParameters = function (values) {
- /**
- * Size of low resolution preview image along the longest image
- * dimension. The preview is assumed to have the same aspect
- * ratio as the full image (specified by width and height).
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type int
- * @public
- */
- this.posterSize = 0;
-
- /**
- * Url for the image tile to show while the tile is loading and no
- * low-resolution preview is available.
- *
- * @default Clicking (or tapping with a finger) on the outer region causes the viewport to zoom out.
- * Clicking anywhere within the middle, "pan", region centers the image on the spot clicked.
- * Finally, clicking in the center hotspot will center the image on the spot clicked and zoom
- * in half a zoom level.
- *
- * As before, you can drag to pan anywhere.
- *
- * If you have navigation tools for mouse users that hover over the image container, it
- * is recommended that any click events on them are kept from bubbling, otherwise the click
- * will propagate to the touch ui. One way is to use the
- * {@link bigshot.Browser#stopMouseEventBubbling} method:
- *
- * @example
- * var browser = new bigshot.Browser ();
- * browser.stopMouseEventBubbling (document.getElementById ("myBigshotControlDiv"));
- *
- * @see bigshot.ImageBase#showTouchUI
- *
- * @type boolean
- * @default true
- * @deprecated Bigshot supports all common touch-gestures.
- */
- this.touchUI = false;
-
- /**
- * Lets you "fling" the image.
- *
- * @type boolean
- * @default true
- */
- this.fling = true;
-
- /**
- * The maximum amount that a tile will be stretched until we try to show
- * the next more detailed level.
- *
- * @type float
- * @default 1.0
- */
- this.maxTextureMagnification = 1.0;
-
- if (values) {
- for (var k in values) {
- this[k] = values[k];
- }
- }
-
- this.merge = function (values, overwrite) {
- for (var k in values) {
- if (overwrite || !this[k]) {
- this[k] = values[k];
- }
- }
- }
- return this;
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic For unknown reasons (probably security), browsers will
- * not let you open a window that covers the entire screen.
- * Even when specifying "fullscreen=yes", all you get is a window
- * that has a title bar and only covers the desktop (not any task
- * bars or the like). For now, this is the best that I can do,
- * but should the situation change I'll update this to be
- * full-screen-ier.
- * @public
- */
- fullScreen : function (onClose) {
- if (this.fullScreenHandler) {
- return;
- }
-
- var message = document.createElement ("div");
- message.style.position = "absolute";
- message.style.fontSize = "16pt";
- message.style.top = "128px";
- message.style.width = "100%";
- message.style.color = "white";
- message.style.padding = "16px";
- message.style.zIndex = "9999";
- message.style.textAlign = "center";
- message.style.opacity = "0.75";
- message.innerHTML = "Press Esc to exit full screen mode.";
-
- var that = this;
-
- this.fullScreenHandler = new bigshot.FullScreen (this.container);
- this.fullScreenHandler.restoreSize = true;
-
- this.fullScreenHandler.addOnResize (function () {
- if (that.fullScreenHandler && that.fullScreenHandler.isFullScreen) {
- that.container.style.width = window.innerWidth + "px";
- that.container.style.height = window.innerHeight + "px";
- }
- that.onresize ();
- });
-
- this.fullScreenHandler.addOnClose (function () {
- if (message.parentNode) {
- try {
- div.removeChild (message);
- } catch (x) {
- }
- }
- that.fullScreenHandler = null;
- });
-
- if (onClose) {
- this.fullScreenHandler.addOnClose (function () {
- onClose ();
- });
- }
-
- this.removeEventListeners ();
- this.fullScreenHandler.open ();
- this.addEventListeners ();
- if (this.fullScreenHandler.getRootElement ()) {
- this.fullScreenHandler.getRootElement ().appendChild (message);
-
- setTimeout (function () {
- var opacity = 0.75;
- var iter = function () {
- opacity -= 0.02;
- if (message.parentNode) {
- if (opacity <= 0) {
- try {
- div.removeChild (message);
- } catch (x) {}
- } else {
- message.style.opacity = opacity;
- setTimeout (iter, 20);
- }
- }
- };
- setTimeout (iter, 20);
- }, 3500);
- }
-
- return function () {
- that.fullScreenHandler.close ();
- };
- },
-
- /**
- * Unregisters event handlers and other page-level hooks. The client need not call this
- * method unless bigshot images are created and removed from the page
- * dynamically. In that case, this method must be called when the client wishes to
- * free the resources allocated by the image. Otherwise the browser will garbage-collect
- * all resources automatically.
- * @public
- */
- dispose : function () {
- this.browser.unregisterListener (window, "resize", this.onresizeHandler, false);
- this.removeEventListeners ();
- }
-};
-
-/**
- * Fired when the user double-clicks on the image
- *
- * @name bigshot.ImageBase#dblclick
- * @event
- * @param {bigshot.ImageEvent} event the event object
- */
-
-/**
- * Fired when the user clicks on (but does not drag) the image
- *
- * @name bigshot.ImageBase#click
- * @event
- * @param {bigshot.ImageEvent} event the event object
- */
-
-bigshot.Object.extend (bigshot.ImageBase, bigshot.EventDispatcher);
-/*
- * Copyright 2010 - 2012 Leo Sutic If you have set the wrapX or wrapY parameters in the {@link bigshot.ImageParameters}, the
- * image must be an integer multiple of the tile size at the desired minimum zoom level, otherwise
- * there will be a gap at the wrap point:
- *
- * The way to figure out the proper input size is this:
- *
- * Decide on a tile size and call this tileSize. Decide on a minimum integer zoom level, and call this minZoom. Compute tileSize * 2-minZoom, call this S. The source image size along the wrapped axis must be evenly divisible by S. An example: I have an image that is 23148x3242 pixels. I chose 256x256 pixel tiles: tileSize = 256. When displaying the image, I want the user to be able to zoom out so that the
- * whole image is less than or equal to 600 pixels tall. Since the image is 3242 pixels
- * tall originally, I will need a minZoom of -3. A minZoom of -2 would only let me
- * zoom out to 1/4 (2-2), or an image that is 810 pixels tall. A minZoom of -3, however lets me
- * zoom out to 1/8 (2-3), or an image that is 405 pixels tall. Thus: minZoom = -3 Computing S gives: S = 256 * 23 = 256 * 8 = 2048 I want it to wrap along the X axis. Therefore I may have to adjust the width,
- * currently 23148 pixels. Rounding 23148 down to the nearest multiple of 2048 gives 22528. (23148 divided by 2048 is 11.3, and 11 times 2048 is 22528.) I will shrink my source image to be 22528 pixels wide before building the image pyramid,
- * and I will set the Usage:
- *
- * @example
- * var bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * basePath : "/bigshot.php?file=myvr.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_canvas")
- * }));
- * @param values named parameter map, see the fields below for parameter names and types.
- * @see bigshot.VRPanorama
- */
-bigshot.VRPanoramaParameters = function (values) {
- /**
- * Size of low resolution preview image along the longest image
- * dimension. The preview is assumed to have the same aspect
- * ratio as the full image (specified by width and height).
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type int
- * @public
- */
- this.posterSize = 0;
-
- /**
- * Url for the image tile to show while the tile is loading and no
- * low-resolution preview is available.
- *
- * @default The panorama consists of six image pyramids, one for each face of the VR cube.
- * Due to restrictions in WebGL, each texture tile must have a power-of-two (POT) size -
- * that is, 2, 4, ..., 128, 256, etc. Furthermore, due to the way the faces are tesselated
- * the largest image must consist of POT x POT tiles. The final restriction is that the
- * tiles must overlap for good seamless results.
- *
- * The MakeImagePyramid has some sensible defaults built-in. If you just use the
- * command line:
- *
- * You will get 2034 pixels per face, and a tile size of 256 pixels with 2 pixels
- * overlap. If you don't like that, you can use the A command line for the hypothetical scenario above would be:
- *
- * If your tile size numbers don't add up, you'll get a warning like:
- *
- * If your face size don't add up, you'll get another warning:
- *
- * SaladoPlayer is a cool
- * Flash-based VR panorama viewer that can display Deep Zoom Images.
- * It can be used as a fallback for Bigshot for browsers that don't
- * support WebGL.
- *
- * Since Bigshot can use a Deep Zoom Image (DZI) via a {@link bigshot.DeepZoomImageFileSystem}
- * adapter, the common file format is DZI. There are two cases: The first is
- * when the DZI is served up as a folder structure, the second when
- * we pack the DZI into a Bigshot archive and serve it using bigshot.php.
- *
- * This is an easy one. First, we generate the required DZIs:
- *
- * We'll assume that we have the six DZI folders in "temp/dzi", and that
- * they have "face_" as a common prefix (which is what Bigshot's MakeImagePyramid
- * outputs). So we have, for example, "temp/dzi/face_f.xml" and the tiles for face_f
- * in "temp/dzi/face_f/". Set up Bigshot like this:
- *
- * SaladoPlayer uses an XML config file, which in this case will
- * look something like this:
- *
- * This one is a bit more difficult. First we create a DZI as a bigshot archive:
- *
- * We'll assume that we have our Bigshot archive at
- * "temp/dzi.bigshot". For this we will use the "entry" parameter of bigshot.php
- * to serve up the right files:
- *
- * SaladoPlayer uses an XML config file, which in this case will
- * look something like this:
- *
- * For unknown reasons (probably security), browsers will
- * not let you open a window that covers the entire screen.
- * Even when specifying "fullscreen=yes", all you get is a window
- * that has a title bar and only covers the desktop (not any task
- * bars or the like). For now, this is the best that I can do,
- * but should the situation change I'll update this to be
- * full-screen-ier.
- *
- * @param {function()} [onClose] function that is called when the user
- * exits full-screen mode
- * @public
- */
- fullScreen : function (onClose) {
- if (this.fullScreenHandler) {
- return;
- }
-
- var message = document.createElement ("div");
- message.style.position = "absolute";
- message.style.fontSize = "16pt";
- message.style.top = "128px";
- message.style.width = "100%";
- message.style.color = "white";
- message.style.padding = "16px";
- message.style.zIndex = "9999";
- message.style.textAlign = "center";
- message.style.opacity = "0.75";
- message.innerHTML = "Press Esc to exit full screen mode.";
-
- var that = this;
-
- this.fullScreenHandler = new bigshot.FullScreen (this.container);
- this.fullScreenHandler.restoreSize = this.sizeContainer == null;
-
- this.fullScreenHandler.addOnResize (function () {
- that.onresize ();
- });
-
- this.fullScreenHandler.addOnClose (function () {
- if (message.parentNode) {
- try {
- div.removeChild (message);
- } catch (x) {
- }
- }
- that.fullScreenHandler = null;
- });
-
- if (onClose) {
- this.fullScreenHandler.addOnClose (function () {
- onClose ();
- });
- }
-
- this.removeEventListeners ();
- this.fullScreenHandler.open ();
- this.addEventListeners ();
- // Safari compatibility - must update after entering fullscreen.
- // 1s should be enough so we enter FS, but not enough for the
- // user to wonder if something is wrong.
- var r = function () {
- that.render ();
- };
- setTimeout (r, 1000);
- setTimeout (r, 2000);
- setTimeout (r, 3000);
-
- if (this.fullScreenHandler.getRootElement ()) {
- this.fullScreenHandler.getRootElement ().appendChild (message);
-
- setTimeout (function () {
- var opacity = 0.75;
- var iter = function () {
- opacity -= 0.02;
- if (message.parentNode) {
- if (opacity <= 0) {
- message.style.display = "none";
- try {
- div.removeChild (message);
- } catch (x) {}
- } else {
- message.style.opacity = opacity;
- setTimeout (iter, 20);
- }
- }
- };
- setTimeout (iter, 20);
- }, 3500);
- }
-
- return function () {
- that.removeEventListeners ();
- that.fullScreenHandler.close ();
- that.addEventListeners ();
- };
- },
-
- /**
- * Right-sizes the canvas container.
- * @private
- */
- onresize : function () {
- if (this.fullScreenHandler == null || !this.fullScreenHandler.isFullScreen) {
- if (this.sizeContainer) {
- var s = this.browser.getElementSize (this.sizeContainer);
- this.renderer.resize (s.w, s.h);
- }
- } else {
- this.container.style.width = window.innerWidth + "px";
- this.container.style.height = window.innerHeight + "px";
- var s = this.browser.getElementSize (this.container);
- this.renderer.resize (s.w, s.h);
- }
- this.renderer.onresize ();
- this.renderAsap ();
- },
-
- /**
- * Posts a render() call via a timeout or the requestAnimationFrame API.
- * Use when the render call must be done as soon as possible, but
- * can't be done in the current call context.
- */
- renderAsap : function () {
- if (!this.renderAsapPermitTaken && !this.disposed) {
- this.renderAsapPermitTaken = true;
- var that = this;
- this.browser.requestAnimationFrame (function () {
- that.renderAsapPermitTaken = false;
- that.render ();
- }, this.renderer.getElement ());
- }
- },
-
-
- /**
- * Automatically resizes the canvas element to the size of the
- * given element on resize.
- *
- * @param {HTMLElement} sizeContainer the element to use. Set to The monitor maintains two render modes - a high quality one with a fixed
- * level of detail, and a low(er) quality one with variable level of detail.
- * If the panorama is idle for more than a set interval, a high-quality render is
- * performed.
- *
- * @param {bigshot.AdaptiveLODMonitorParameters} parameters parameters for the LOD monitor.
- *
- * @see bigshot.AdaptiveLODMonitorParameters for a list of parameters
- *
- * @example
- * var bvr = new bigshot.VRPanorama ( ... );
- * var lodMonitor = new bigshot.AdaptiveLODMonitor (
- * new bigshot.AdaptiveLODMonitorParameters ({
- * vrPanorama : bvr,
- * targetFps : 30,
- * tolerance : 0.3,
- * rate : 0.1,
- * minMag : 1.5,
- * maxMag : 16
- * }));
- * bvr.addRenderListener (lodMonitor.getListener ());
- */
-bigshot.AdaptiveLODMonitor = function (parameters) {
- this.setParameters (parameters);
-
- /**
- * The current adaptive detail level.
- * @type float
- * @private
- */
- this.currentAdaptiveMagnification = parameters.vrPanorama.getMaxTextureMagnification ();
-
- /**
- * The number of frames that have been rendered.
- * @type int
- * @private
- */
- this.frames = 0;
-
- /**
- * The total number of times we have sampled the render time.
- * @type int
- * @private
- */
- this.samples = 0;
-
- /**
- * The sum of sample times from all samples of render time in milliseconds.
- * @type int
- * @private
- */
- this.renderTimeTotal = 0;
-
- /**
- * The sum of sample times from the recent sample pass in milliseconds.
- * @type int
- * @private
- */
- this.renderTimeLast = 0;
-
- /**
- * The number of samples currently done in the recent sample pass.
- * @type int
- * @private
- */
- this.samplesLast = 0;
-
- /**
- * The start time, in milliseconds, of the last sample.
- * @type int
- * @private
- */
- this.startTime = 0;
-
- /**
- * The time, in milliseconds, when the panorama was last rendered.
- * @type int
- * @private
- */
- this.lastRender = 0;
-
- this.hqRender = false;
- this.hqMode = false;
- this.hqRenderWaiting = false;
-
- /**
- * Flag to enable / disable the monitor.
- * @type boolean
- * @private
- */
- this.enabled = true;
-
- var that = this;
- this.listenerFunction = function (state, cause, data) {
- that.listener (state, cause, data);
- };
-};
-
-bigshot.AdaptiveLODMonitor.prototype = {
- averageRenderTime : function () {
- if (this.samples > 0) {
- return this.renderTimeTotal / this.samples;
- } else {
- return -1;
- }
- },
-
- /**
- * @param {bigshot.AdaptiveLODMonitorParameters} parameters
- */
- setParameters : function (parameters) {
- this.parameters = parameters;
- this.targetTime = 1000 / this.parameters.targetFps;
-
- this.lowerTime = this.targetTime / (1.0 + this.parameters.tolerance);
- this.upperTime = this.targetTime * (1.0 + this.parameters.tolerance);
- },
-
- setEnabled : function (enabled) {
- this.enabled = enabled;
- },
-
- averageRenderTimeLast : function () {
- if (this.samples > 0) {
- return this.renderTimeLast / this.samplesLast;
- } else {
- return -1;
- }
- },
-
- getListener : function () {
- return this.listenerFunction;
- },
-
- increaseDetail : function () {
- this.currentAdaptiveMagnification = Math.max (this.parameters.minMag, this.currentAdaptiveMagnification / (1.0 + this.parameters.rate));
- },
-
- decreaseDetail : function () {
- this.currentAdaptiveMagnification = Math.min (this.parameters.maxMag, this.currentAdaptiveMagnification * (1.0 + this.parameters.rate));
- },
-
- sample : function () {
- var deltat = new Date ().getTime () - this.startTime;
- this.samples++;
- this.renderTimeTotal += deltat;
-
- this.samplesLast++;
- this.renderTimeLast += deltat;
-
- if (this.samplesLast > 4) {
- var averageLast = this.renderTimeLast / this.samplesLast;
-
- if (averageLast < this.lowerTime) {
- this.increaseDetail ();
- } else if (averageLast > this.upperTime) {
- this.decreaseDetail ();
- }
-
- this.samplesLast = 0;
- this.renderTimeLast = 0;
- }
- },
-
- hqRenderTick : function () {
- if (this.lastRender < new Date ().getTime () - this.parameters.hqRenderDelay) {
- this.hqRender = true;
- this.hqMode = true;
- if (this.enabled) {
- this.parameters.vrPanorama.setMaxTextureMagnification (this.parameters.hqRenderMag);
- this.parameters.vrPanorama.render ();
- }
-
- this.hqRender = false;
- this.hqRenderWaiting = false;
- } else {
- var that = this;
- setTimeout (function () {
- that.hqRenderTick ();
- }, this.parameters.hqRenderInterval);
- }
- },
-
- listener : function (state, cause, data) {
- if (!this.enabled) {
- return;
- }
-
- if (this.hqRender) {
- return;
- }
-
- if (this.hqMode && cause == bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE) {
- this.parameters.vrPanorama.setMaxTextureMagnification (this.parameters.minMag);
- return;
- } else {
- this.hqMode = false;
- }
-
- this.parameters.vrPanorama.setMaxTextureMagnification (this.currentAdaptiveMagnification);
-
- this.frames++;
- if ((this.frames < 20 || this.frames % 5 == 0) && state == bigshot.VRPanorama.ONRENDER_BEGIN) {
- this.startTime = new Date ().getTime ();
- this.lastRender = this.startTime;
- var that = this;
- setTimeout (function () {
- that.sample ();
- }, 1);
- if (!this.hqRenderWaiting) {
- this.hqRenderWaiting = true;
- setTimeout (function () {
- that.hqRenderTick ();
- }, this.parameters.hqRenderInterval);
- }
- }
- }
-};
-}
diff --git a/js/vendor/commonmark/dist/commonmark.min.js b/js/vendor/commonmark/dist/commonmark.min.js
new file mode 100644
index 0000000000..e8c0e6e14e
--- /dev/null
+++ b/js/vendor/commonmark/dist/commonmark.min.js
@@ -0,0 +1,4 @@
+/* commonmark 0.22 https://github.com/jgm/CommonMark @license BSD3 */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.commonmark=e()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;r.length>o;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";function Parser(options){return{doc:new Document,blocks:blocks,blockStarts:blockStarts,tip:this.doc,oldtip:this.doc,currentLine:"",lineNumber:0,offset:0,column:0,nextNonspace:0,nextNonspaceColumn:0,indent:0,indented:!1,blank:!1,allClosed:!0,lastMatchedContainer:this.doc,refmap:{},lastLineLength:0,inlineParser:new InlineParser(options),findNextNonspace:findNextNonspace,advanceOffset:advanceOffset,advanceNextNonspace:advanceNextNonspace,breakOutOfLists:breakOutOfLists,addLine:addLine,addChild:addChild,incorporateLine:incorporateLine,finalize:finalize,processInlines:processInlines,closeUnmatchedBlocks:closeUnmatchedBlocks,parse:parse,options:options||{}}}var Node=require("./node"),unescapeString=require("./common").unescapeString,OPENTAG=require("./common").OPENTAG,CLOSETAG=require("./common").CLOSETAG,CODE_INDENT=4,C_NEWLINE=10,C_GREATERTHAN=62,C_LESSTHAN=60,C_SPACE=32,C_OPEN_BRACKET=91,InlineParser=require("./inlines"),reHtmlBlockOpen=[/./,/^<(?:script|pre|style)(?:\s|>|$)/i,/^/,/\?>/,/>/,/\]\]>/],reHrule=/^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/,reMaybeSpecial=/^[#`~*+_=<>0-9-]/,reNonSpace=/[^ \t\f\v\r\n]/,reBulletListMarker=/^[*+-]( +|$)/,reOrderedListMarker=/^(\d{1,9})([.)])( +|$)/,reATXHeaderMarker=/^#{1,6}(?: +|$)/,reCodeFence=/^`{3,}(?!.*`)|^~{3,}(?!.*~)/,reClosingCodeFence=/^(?:`{3,}|~{3,})(?= *$)/,reSetextHeaderLine=/^(?:=+|-+) *$/,reLineEnding=/\r\n|\n|\r/,isBlank=function(s){return!reNonSpace.test(s)},peek=function(ln,pos){return ln.length>pos?ln.charCodeAt(pos):-1},endsWithBlankLine=function(block){for(;block;){if(block._lastLineBlank)return!0;var t=block.type;if("List"!==t&&"Item"!==t)break;block=block._lastChild}return!1},breakOutOfLists=function(block){var b=block,last_list=null;do"List"===b.type&&(last_list=b),b=b._parent;while(b);if(last_list){for(;block!==last_list;)this.finalize(block,this.lineNumber),block=block._parent;this.finalize(last_list,this.lineNumber),this.tip=last_list._parent}},addLine=function(){this.tip._string_content+=this.currentLine.slice(this.offset)+"\n"},addChild=function(tag,offset){for(;!this.blocks[this.tip.type].canContain(tag);)this.finalize(this.tip,this.lineNumber-1);var column_number=offset+1,newBlock=new Node(tag,[[this.lineNumber,column_number],[0,0]]);return newBlock._string_content="",this.tip.appendChild(newBlock),this.tip=newBlock,newBlock},parseListMarker=function(ln,offset,indent){var match,spaces_after_marker,rest=ln.slice(offset),data={type:null,tight:!0,bulletChar:null,start:null,delimiter:null,padding:null,markerOffset:indent};if(match=rest.match(reBulletListMarker))spaces_after_marker=match[1].length,data.type="Bullet",data.bulletChar=match[0][0];else{if(!(match=rest.match(reOrderedListMarker)))return null;spaces_after_marker=match[3].length,data.type="Ordered",data.start=parseInt(match[1]),data.delimiter=match[2]}var blank_item=match[0].length===rest.length;return data.padding=spaces_after_marker>=5||1>spaces_after_marker||blank_item?match[0].length-spaces_after_marker+1:match[0].length,data},listsMatch=function(list_data,item_data){return list_data.type===item_data.type&&list_data.delimiter===item_data.delimiter&&list_data.bulletChar===item_data.bulletChar},closeUnmatchedBlocks=function(){if(!this.allClosed){for(;this.oldtip!==this.lastMatchedContainer;){var parent=this.oldtip._parent;this.finalize(this.oldtip,this.lineNumber-1),this.oldtip=parent}this.allClosed=!0}},blocks={Document:{"continue":function(){return 0},finalize:function(){},canContain:function(t){return"Item"!==t},acceptsLines:!1},List:{"continue":function(){return 0},finalize:function(parser,block){for(var item=block._firstChild;item;){if(endsWithBlankLine(item)&&item._next){block._listData.tight=!1;break}for(var subitem=item._firstChild;subitem;){if(endsWithBlankLine(subitem)&&(item._next||subitem._next)){block._listData.tight=!1;break}subitem=subitem._next}item=item._next}},canContain:function(t){return"Item"===t},acceptsLines:!1},BlockQuote:{"continue":function(parser){var ln=parser.currentLine;return parser.indented||peek(ln,parser.nextNonspace)!==C_GREATERTHAN?1:(parser.advanceNextNonspace(),parser.advanceOffset(1,!1),peek(ln,parser.offset)===C_SPACE&&parser.offset++,0)},finalize:function(){},canContain:function(t){return"Item"!==t},acceptsLines:!1},Item:{"continue":function(parser,container){if(parser.blank&&null!==container._firstChild)parser.advanceNextNonspace();else{if(!(parser.indent>=container._listData.markerOffset+container._listData.padding))return 1;parser.advanceOffset(container._listData.markerOffset+container._listData.padding,!0)}return 0},finalize:function(){},canContain:function(t){return"Item"!==t},acceptsLines:!1},Header:{"continue":function(){return 1},finalize:function(){},canContain:function(){return!1},acceptsLines:!1},HorizontalRule:{"continue":function(){return 1},finalize:function(){},canContain:function(){return!1},acceptsLines:!1},CodeBlock:{"continue":function(parser,container){var ln=parser.currentLine,indent=parser.indent;if(container._isFenced){var match=3>=indent&&ln.charAt(parser.nextNonspace)===container._fenceChar&&ln.slice(parser.nextNonspace).match(reClosingCodeFence);if(match&&match[0].length>=container._fenceLength)return parser.finalize(container,parser.lineNumber),2;for(var i=container._fenceOffset;i>0&&peek(ln,parser.offset)===C_SPACE;)parser.advanceOffset(1,!1),i--}else if(indent>=CODE_INDENT)parser.advanceOffset(CODE_INDENT,!0);else{if(!parser.blank)return 1;parser.advanceNextNonspace()}return 0},finalize:function(parser,block){if(block._isFenced){var content=block._string_content,newlinePos=content.indexOf("\n"),firstLine=content.slice(0,newlinePos),rest=content.slice(newlinePos+1);block.info=unescapeString(firstLine.trim()),block._literal=rest}else block._literal=block._string_content.replace(/(\n *)+$/,"\n");block._string_content=null},canContain:function(){return!1},acceptsLines:!0},HtmlBlock:{"continue":function(parser,container){return!parser.blank||6!==container._htmlBlockType&&7!==container._htmlBlockType?0:1},finalize:function(parser,block){block._literal=block._string_content.replace(/(\n *)+$/,""),block._string_content=null},canContain:function(){return!1},acceptsLines:!0},Paragraph:{"continue":function(parser){return parser.blank?1:0},finalize:function(parser,block){for(var pos,hasReferenceDefs=!1;peek(block._string_content,0)===C_OPEN_BRACKET&&(pos=parser.inlineParser.parseReference(block._string_content,parser.refmap));)block._string_content=block._string_content.slice(pos),hasReferenceDefs=!0;hasReferenceDefs&&isBlank(block._string_content)&&block.unlink()},canContain:function(){return!1},acceptsLines:!0}},blockStarts=[function(parser){return parser.indented||peek(parser.currentLine,parser.nextNonspace)!==C_GREATERTHAN?0:(parser.advanceNextNonspace(),parser.advanceOffset(1,!1),peek(parser.currentLine,parser.offset)===C_SPACE&&parser.advanceOffset(1,!1),parser.closeUnmatchedBlocks(),parser.addChild("BlockQuote",parser.nextNonspace),1)},function(parser){var match;if(!parser.indented&&(match=parser.currentLine.slice(parser.nextNonspace).match(reATXHeaderMarker))){parser.advanceNextNonspace(),parser.advanceOffset(match[0].length,!1),parser.closeUnmatchedBlocks();var container=parser.addChild("Header",parser.nextNonspace);return container.level=match[0].trim().length,container._string_content=parser.currentLine.slice(parser.offset).replace(/^ *#+ *$/,"").replace(/ +#+ *$/,""),parser.advanceOffset(parser.currentLine.length-parser.offset),2}return 0},function(parser){var match;if(!parser.indented&&(match=parser.currentLine.slice(parser.nextNonspace).match(reCodeFence))){var fenceLength=match[0].length;parser.closeUnmatchedBlocks();var container=parser.addChild("CodeBlock",parser.nextNonspace);return container._isFenced=!0,container._fenceLength=fenceLength,container._fenceChar=match[0][0],container._fenceOffset=parser.indent,parser.advanceNextNonspace(),parser.advanceOffset(fenceLength,!1),2}return 0},function(parser,container){if(!parser.indented&&peek(parser.currentLine,parser.nextNonspace)===C_LESSTHAN){var blockType,s=parser.currentLine.slice(parser.nextNonspace);for(blockType=1;7>=blockType;blockType++)if(reHtmlBlockOpen[blockType].test(s)&&(7>blockType||"Paragraph"!==container.type)){parser.closeUnmatchedBlocks();var b=parser.addChild("HtmlBlock",parser.offset);return b._htmlBlockType=blockType,2}}return 0},function(parser,container){var match;if(!parser.indented&&"Paragraph"===container.type&&container._string_content.indexOf("\n")===container._string_content.length-1&&(match=parser.currentLine.slice(parser.nextNonspace).match(reSetextHeaderLine))){parser.closeUnmatchedBlocks();var header=new Node("Header",container.sourcepos);return header.level="="===match[0][0]?1:2,header._string_content=container._string_content,container.insertAfter(header),container.unlink(),parser.tip=header,parser.advanceOffset(parser.currentLine.length-parser.offset,!1),2}return 0},function(parser){return!parser.indented&&reHrule.test(parser.currentLine.slice(parser.nextNonspace))?(parser.closeUnmatchedBlocks(),parser.addChild("HorizontalRule",parser.nextNonspace),parser.advanceOffset(parser.currentLine.length-parser.offset,!1),2):0},function(parser,container){var data,i;return!(data=parseListMarker(parser.currentLine,parser.nextNonspace,parser.indent))||parser.indented&&"List"!==container.type?0:(parser.closeUnmatchedBlocks(),parser.advanceNextNonspace(),i=parser.column,parser.advanceOffset(data.padding,!1),data.padding=parser.column-i,"List"===parser.tip.type&&listsMatch(container._listData,data)||(container=parser.addChild("List",parser.nextNonspace),container._listData=data),container=parser.addChild("Item",parser.nextNonspace),container._listData=data,1)},function(parser){return parser.indented&&"Paragraph"!==parser.tip.type&&!parser.blank?(parser.advanceOffset(CODE_INDENT,!0),parser.closeUnmatchedBlocks(),parser.addChild("CodeBlock",parser.offset),2):0}],advanceOffset=function(count,columns){for(var i=0,cols=0,currentLine=this.currentLine;columns?count>cols:count>i;)cols+=" "===currentLine[this.offset+i]?4-(this.column+cols)%4:1,i++;this.offset+=i,this.column+=cols},advanceNextNonspace=function(){this.offset=this.nextNonspace,this.column=this.nextNonspaceColumn},findNextNonspace=function(){for(var c,currentLine=this.currentLine,i=this.offset,cols=this.column;""!==(c=currentLine.charAt(i));)if(" "===c)i++,cols++;else{if(" "!==c)break;i++,cols+=4-cols%4}this.blank="\n"===c||"\r"===c||""===c,this.nextNonspace=i,this.nextNonspaceColumn=cols,this.indent=this.nextNonspaceColumn-this.column,this.indented=this.indent>=CODE_INDENT},incorporateLine=function(ln){var t,all_matched=!0,container=this.doc;this.oldtip=this.tip,this.offset=0,this.lineNumber+=1,-1!==ln.indexOf("\x00")&&(ln=ln.replace(/\0/g,"�")),this.currentLine=ln;for(var lastChild;(lastChild=container._lastChild)&&lastChild._open;){switch(container=lastChild,this.findNextNonspace(),this.blocks[container.type]["continue"](this,container)){case 0:break;case 1:all_matched=!1;break;case 2:return void(this.lastLineLength=ln.length);default:throw"continue returned illegal value, must be 0, 1, or 2"}if(!all_matched){container=container._parent;break}}this.allClosed=container===this.oldtip,this.lastMatchedContainer=container,this.blank&&container._lastLineBlank&&this.breakOutOfLists(container);for(var matchedLeaf="Paragraph"!==container.type&&blocks[container.type].acceptsLines,starts=this.blockStarts,startsLen=starts.length;!matchedLeaf;){if(this.findNextNonspace(),!this.indented&&!reMaybeSpecial.test(ln.slice(this.nextNonspace))){this.advanceNextNonspace();break}for(var i=0;startsLen>i;){var res=starts[i](this,container);if(1===res){container=this.tip;break}if(2===res){container=this.tip,matchedLeaf=!0;break}i++}if(i===startsLen){this.advanceNextNonspace();break}}if(this.allClosed||this.blank||"Paragraph"!==this.tip.type){this.closeUnmatchedBlocks(),this.blank&&container.lastChild&&(container.lastChild._lastLineBlank=!0),t=container.type;for(var lastLineBlank=this.blank&&!("BlockQuote"===t||"CodeBlock"===t&&container._isFenced||"Item"===t&&!container._firstChild&&container.sourcepos[0][0]===this.lineNumber),cont=container;cont;)cont._lastLineBlank=lastLineBlank,cont=cont._parent;this.blocks[t].acceptsLines?(this.addLine(),"HtmlBlock"===t&&container._htmlBlockType>=1&&5>=container._htmlBlockType&&reHtmlBlockClose[container._htmlBlockType].test(this.currentLine.slice(this.offset))&&this.finalize(container,this.lineNumber)):ln.length>this.offset&&!this.blank&&(container=this.addChild("Paragraph",this.offset),this.advanceNextNonspace(),this.addLine())}else this.addLine();this.lastLineLength=ln.length},finalize=function(block,lineNumber){var above=block._parent;block._open=!1,block.sourcepos[1]=[lineNumber,this.lastLineLength],this.blocks[block.type].finalize(this,block),this.tip=above},processInlines=function(block){var node,event,t,walker=block.walker();for(this.inlineParser.refmap=this.refmap,this.inlineParser.options=this.options;event=walker.next();)node=event.node,t=node.type,event.entering||"Paragraph"!==t&&"Header"!==t||this.inlineParser.parse(node)},Document=function(){var doc=new Node("Document",[[1,1],[0,0]]);return doc},parse=function(input){this.doc=new Document,this.tip=this.doc,this.refmap={},this.lineNumber=0,this.lastLineLength=0,this.offset=0,this.column=0,this.lastMatchedContainer=this.doc,this.currentLine="",this.options.time&&console.time("preparing input");var lines=input.split(reLineEnding),len=lines.length;input.charCodeAt(input.length-1)===C_NEWLINE&&(len-=1),this.options.time&&console.timeEnd("preparing input"),this.options.time&&console.time("block parsing");for(var i=0;len>i;i++)this.incorporateLine(lines[i]);for(;this.tip;)this.finalize(this.tip,len);return this.options.time&&console.timeEnd("block parsing"),this.options.time&&console.time("inline parsing"),this.processInlines(this.doc),this.options.time&&console.timeEnd("inline parsing"),this.doc};module.exports=Parser},{"./common":2,"./inlines":6,"./node":7}],2:[function(require,module,exports){"use strict";var encode=require("mdurl/encode"),decode=require("mdurl/decode"),C_BACKSLASH=92,decodeHTML=require("entities").decodeHTML,ENTITY="&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});",TAGNAME="[A-Za-z][A-Za-z0-9-]*",ATTRIBUTENAME="[a-zA-Z_:][a-zA-Z0-9:._-]*",UNQUOTEDVALUE="[^\"'=<>`\\x00-\\x20]+",SINGLEQUOTEDVALUE="'[^']*'",DOUBLEQUOTEDVALUE='"[^"]*"',ATTRIBUTEVALUE="(?:"+UNQUOTEDVALUE+"|"+SINGLEQUOTEDVALUE+"|"+DOUBLEQUOTEDVALUE+")",ATTRIBUTEVALUESPEC="(?:\\s*=\\s*"+ATTRIBUTEVALUE+")",ATTRIBUTE="(?:\\s+"+ATTRIBUTENAME+ATTRIBUTEVALUESPEC+"?)",OPENTAG="<"+TAGNAME+ATTRIBUTE+"*\\s*/?>",CLOSETAG=""+TAGNAME+"\\s*[>]",HTMLCOMMENT="|",PROCESSINGINSTRUCTION="[<][?].*?[?][>]",DECLARATION="]*>",CDATA="",HTMLTAG="(?:"+OPENTAG+"|"+CLOSETAG+"|"+HTMLCOMMENT+"|"+PROCESSINGINSTRUCTION+"|"+DECLARATION+"|"+CDATA+")",reHtmlTag=new RegExp("^"+HTMLTAG,"i"),reBackslashOrAmp=/[\\&]/,ESCAPABLE="[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]",reEntityOrEscapedChar=new RegExp("\\\\"+ESCAPABLE+"|"+ENTITY,"gi"),XMLSPECIAL='[&<>"]',reXmlSpecial=new RegExp(XMLSPECIAL,"g"),reXmlSpecialOrEntity=new RegExp(ENTITY+"|"+XMLSPECIAL,"gi"),unescapeChar=function(s){return s.charCodeAt(0)===C_BACKSLASH?s.charAt(1):decodeHTML(s)},unescapeString=function(s){return reBackslashOrAmp.test(s)?s.replace(reEntityOrEscapedChar,unescapeChar):s},normalizeURI=function(uri){try{return encode(decode(uri))}catch(err){return uri}},replaceUnsafeChar=function(s){switch(s){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";default:return s}},escapeXml=function(s,preserve_entities){return reXmlSpecial.test(s)?preserve_entities?s.replace(reXmlSpecialOrEntity,replaceUnsafeChar):s.replace(reXmlSpecial,replaceUnsafeChar):s};module.exports={unescapeString:unescapeString,normalizeURI:normalizeURI,escapeXml:escapeXml,reHtmlTag:reHtmlTag,OPENTAG:OPENTAG,CLOSETAG:CLOSETAG,ENTITY:ENTITY,ESCAPABLE:ESCAPABLE}},{entities:10,"mdurl/decode":18,"mdurl/encode":19}],3:[function(require,module,exports){"use strict";if(String.fromCodePoint)module.exports=function(_){try{return String.fromCodePoint(_)}catch(e){if(e instanceof RangeError)return String.fromCharCode(65533);throw e}};else{var stringFromCharCode=String.fromCharCode,floor=Math.floor,fromCodePoint=function(){var highSurrogate,lowSurrogate,MAX_SIZE=16384,codeUnits=[],index=-1,length=arguments.length;if(!length)return"";for(var result="";++index All the things I am using markdown. hello world item1 text item1 text world
- world item1 text item1 text world
- worldZoomable Images
- *
- *
- *
- *
- * For hotspots, see:
- *
- *
- *
- *
- * VR Panoramas
- *
- *
- *
- *
- * For hotspots, see:
- *
- *
- *
- */
- bigshot = {};
-
- /*
- * This is supposed to be processed using a minimalhttpd.IncludeProcessor
- * during development. The files must be listed in dependency order.
- */
-/*
- * Copyright 2010 - 2012 Leo Sutic self.
- *
- * @param {String} name the name to resolve
- * @type {Object}
- */
- resolve : function (name) {
- var c = name.split (".");
- var clazz = self;
- for (var i = 0; i < c.length; ++i) {
- clazz = clazz[c[i]];
- }
- return clazz;
- },
-
- validate : function (clazzName, iface) {
- },
-
- /**
- * Utility function to show an object's fields in a message box.
- *
- * @param {Object} o the object
- */
- alertr : function (o) {
- var sb = "";
- for (var k in o) {
- sb += k + ":" + o[k] + "\n";
- }
- alert (sb);
- },
-
- /**
- * Utility function to show an object's fields in the console log.
- *
- * @param {Object} o the object
- */
- logr : function (o) {
- var sb = "";
- for (var k in o) {
- sb += k + ":" + o[k] + "\n";
- }
- if (console) {
- console.log (sb);
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic width
- * set to 100px occupies 50 physical pixels, the function will return
- * 0.5.
- * @type number
- */
- getDevicePixelScale : function () {
- if (this.browserIsViewporting ()) {
- return screen.width / window.innerWidth;
- } else {
- return 1.0;
- }
- },
-
- /**
- * Requests an animation frame, if the API is supported
- * on the browser. If not, a setTimeout with
- * a timeout of zero is used.
- *
- * @param {function()} callback the animation frame render function
- * @param {HTMLElement} element the element to use when requesting an
- * animation frame
- */
- requestAnimationFrame : function (callback, element) {
- var raff = this.requestAnimationFrameFunction;
- raff (callback, element);
- },
-
- /**
- * Returns the position in pixels of the element relative
- * to the top left corner of the document.
- *
- * @param {HTMLElement} obj the element
- * @return a position object with two integer members, x and y.
- */
- getElementPosition : function (obj) {
- var position = new Object();
- position.x = 0;
- position.y = 0;
-
- var o = obj;
- while (o) {
- position.x += o.offsetLeft;
- position.y += o.offsetTop;
- if (o.clientLeft) {
- position.x += o.clientLeft;
- }
- if (o.clientTop) {
- position.y += o.clientTop;
- }
-
- if (o.x) {
- position.x += o.x;
- }
- if (o.y) {
- position.y += o.y;
- }
- o = o.offsetParent;
- }
- return position;
- },
-
- /**
- * Creates an XMLHttpRequest object.
- *
- * @type XMLHttpRequest
- * @returns a XMLHttpRequest object.
- */
- createXMLHttpRequest : function () {
- try {
- return new ActiveXObject("Msxml2.XMLHTTP");
- } catch (e) {
- }
-
- try {
- return new ActiveXObject("Microsoft.XMLHTTP");
- } catch (e) {
- }
-
- try {
- return new XMLHttpRequest();
- } catch(e) {
- }
-
- alert("XMLHttpRequest not supported");
-
- return null;
- },
-
- /**
- * Creates an opacity transition from opaque to transparent.
- * If CSS transitions aren't supported, the element is
- * immediately made transparent without a transition.
- *
- * @param {HTMLElement} element the element to fade out
- * @param {function()} onComplete function to call when
- * the transition is complete.
- */
- makeOpacityTransition : function (element, onComplete) {
- if (element.style.WebkitTransitionProperty != undefined) {
- element.style.opacity = 1.0;
- element.style.WebkitTransitionProperty = "opacity";
- element.style.WebkitTransitionTimingFunction = "linear";
- element.style.WebkitTransitionDuration = "1s";
- setTimeout (function () {
- element.addEventListener ("webkitTransitionEnd", function () {
- onComplete ();
- });
- element.style.opacity = 0.0;
- }, 0);
- } else {
- element.style.opacity = 0.0;
- onComplete ();
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic Array of listeners.
- *
- * @type Object
- */
- this.eventListeners = {};
-}
-
-bigshot.EventDispatcher.prototype = {
- /**
- * Adds an event listener to the specified event.
- *
- * @example
- * image.addEventListener ("click", function (event) { ... });
- *
- * @param {String} eventName the name of the event to add a listener for
- * @param {Function} handler function that is invoked with an event object
- * when the event is fired
- */
- addEventListener : function (eventName, handler) {
- if (this.eventListeners[eventName] == undefined) {
- this.eventListeners[eventName] = new Array ();
- }
- this.eventListeners[eventName].push (handler);
- },
-
- /**
- * Removes an event listener.
- * @param {String} eventName the name of the event to remove a listener for
- * @param {Function} handler the handler to remove
- */
- removeEventListener : function (eventName, handler) {
- if (this.eventListeners[eventName] != undefined) {
- var el = this.eventListeners[eventName];
- for (var i = 0; i < el.length; ++i) {
- if (el[i] === listener) {
- el.splice (i, 1);
- if (el.length == 0) {
- delete this.eventListeners[eventName];
- }
- break;
- }
- }
- }
- },
-
- /**
- * Fires an event.
- *
- * @param {String} eventName the name of the event to fire
- * @param {bigshot.Event} eventObject the event object to pass to the handlers
- */
- fireEvent : function (eventName, eventObject) {
- if (this.eventListeners[eventName] != undefined) {
- var el = this.eventListeners[eventName];
- for (var i = 0; i < el.length; ++i) {
- el[i](eventObject);
- }
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic new Date ().getTime ()
- * @type number
- */
- this.timeStamp = new Date ().getTime ();
-
- /**
- * The event type.
- * @default null
- * @type String
- */
- this.type = null;
-
- /**
- * Flag indicating origin of event.
- * @default false
- * @type boolean
- */
- this.isTrusted = false;
-
- for (var k in data) {
- this[k] = data[k];
- }
-}
-
-bigshot.Event.prototype = {
- /**
- * Prevents default handling of the event.
- */
- preventDefault : function () {
- this.defaultPrevented = true;
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic requestFullScreen
- * API - as standard or as moz- or webkit- extensions,
- * this will be used.
- *
- * @param {HTMLElement} container the element that is to be made full screen
- */
-bigshot.FullScreen = function (container) {
- this.container = container;
-
- this.isFullScreen = false;
- this.savedBodyStyle = null;
- this.savedParent = null;
- this.savedSize = null;
- this.expanderDiv = null;
- this.restoreSize = false;
-
- this.onCloseHandlers = new Array ();
- this.onResizeHandlers = new Array ();
-
- var findFunc = function (el, list) {
- for (var i = 0; i < list.length; ++i) {
- if (el[list[i]]) {
- return list[i];
- }
- }
- return null;
- };
-
- this.requestFullScreen = findFunc (container, ["requestFullScreen", "mozRequestFullScreen", "webkitRequestFullscreen"]);
- this.cancelFullScreen = findFunc (document, ["cancelFullScreen", "mozCancelFullScreen", "webkitCancelFullscreen"]);
-
- this.restoreSize = this.requestFullScreen != null;
-}
-
-bigshot.FullScreen.prototype = {
- browser : new bigshot.Browser (),
-
- getRootElement : function () {
- return this.div;
- },
-
- /**
- * Adds a function that will run when exiting full screen mode.
- *
- * @param {function()} onClose the function to call
- */
- addOnClose : function (onClose) {
- this.onCloseHandlers.push (onClose);
- },
-
- /**
- * Notifies all onClose handlers.
- *
- * @private
- */
- onClose : function () {
- for (var i = 0; i < this.onCloseHandlers.length; ++i) {
- this.onCloseHandlers[i] ();
- }
- },
-
- /**
- * Adds a function that will run when the element is resized.
- *
- * @param {function()} onResize the function to call
- */
- addOnResize : function (onResize) {
- this.onResizeHandlers.push (onResize);
- },
-
- /**
- * Notifies all resize handlers.
- *
- * @private
- */
- onResize : function () {
- for (var i = 0; i < this.onResizeHandlers.length; ++i) {
- this.onResizeHandlers[i] ();
- }
- },
-
- /**
- * Begins full screen mode.
- */
- open : function () {
- this.isFullScreen = true;
-
- if (this.requestFullScreen) {
- return this.openRequestFullScreen ();
- } else {
- return this.openCompat ();
- }
- },
-
- /**
- * Makes the element really full screen using the requestFullScreen
- * API.
- *
- * @private
- */
- openRequestFullScreen : function () {
- this.savedSize = {
- width : this.container.style.width,
- height : this.container.style.height
- };
-
- this.container.style.width = "100%";
- this.container.style.height = "100%";
-
- var that = this;
-
- if (this.requestFullScreen == "mozRequestFullScreen") {
- /**
- * @private
- */
- var errFun = function () {
- that.container.removeEventListener ("mozfullscreenerror", errFun);
- that.isFullScreen = false;
- that.exitFullScreenHandler ();
- that.onClose ();
- };
- this.container.addEventListener ("mozfullscreenerror", errFun);
-
- /**
- * @private
- */
- var changeFun = function () {
- if (document.mozFullScreenElement !== that.container) {
- document.removeEventListener ("mozfullscreenchange", changeFun);
- that.exitFullScreenHandler ();
- } else {
- that.onResize ();
- }
- };
- document.addEventListener ("mozfullscreenchange", changeFun);
- } else {
- /**
- * @private
- */
- var changeFun = function () {
- if (document.webkitCurrentFullScreenElement !== that.container) {
- that.container.removeEventListener ("webkitfullscreenchange", changeFun);
- that.exitFullScreenHandler ();
- } else {
- that.onResize ();
- }
- };
- this.container.addEventListener ("webkitfullscreenchange", changeFun);
- }
-
- this.exitFullScreenHandler = function () {
- if (that.isFullScreen) {
- that.isFullScreen = false;
- document[that.cancelFullScreen]();
- if (that.restoreSize) {
- that.container.style.width = that.savedSize.width;
- that.container.style.height = that.savedSize.height;
- }
- that.onResize ();
- that.onClose ();
- }
- };
- this.container[this.requestFullScreen](Element.ALLOW_KEYBOARD_INPUT);
- },
-
- /**
- * Makes the element "full screen" in older browsers by covering the browser's client area.
- *
- * @private
- */
- openCompat : function () {
- this.savedParent = this.container.parentNode;
-
- this.savedSize = {
- width : this.container.style.width,
- height : this.container.style.height
- };
- this.savedBodyStyle = document.body.style.cssText;
-
- document.body.style.overflow = "hidden";
-
- this.expanderDiv = document.createElement ("div");
- this.expanderDiv.style.position = "absolute";
- this.expanderDiv.style.top = "0px";
- this.expanderDiv.style.left = "0px";
- this.expanderDiv.style.width = Math.max (window.innerWidth, document.documentElement.clientWidth) + "px";
- this.expanderDiv.style.height = Math.max (window.innerHeight, document.documentElement.clientHeight) + "px";
-
- document.body.appendChild (this.expanderDiv);
-
- this.div = document.createElement ("div");
- this.div.style.position = "fixed";
- this.div.style.top = window.pageYOffset + "px";
- this.div.style.left = window.pageXOffset + "px";
-
- this.div.style.width = window.innerWidth + "px";
- this.div.style.height = window.innerHeight + "px";
- this.div.style.zIndex = 9998;
-
- this.div.appendChild (this.container);
-
- //this.container.style.width = window.innerWidth + "px";
- //this.container.style.height = window.innerHeight + "px";
-
- document.body.appendChild (this.div);
-
- var that = this;
- var resizeHandler = function (e) {
- setTimeout (function () {
- that.div.style.width = window.innerWidth + "px";
- that.div.style.height = window.innerHeight + "px";
- setTimeout (function () {
- that.onResize ();
- }, 1);
- }, 1);
- };
-
-
- var rotationHandler = function (e) {
- that.expanderDiv.style.width = Math.max (window.innerWidth, document.documentElement.clientWidth) + "px";
- that.expanderDiv.style.height = Math.max (window.innerHeight, document.documentElement.clientHeight) + "px";
- setTimeout (function () {
- that.div.style.top = window.pageYOffset + "px";
- that.div.style.left = window.pageXOffset + "px";
- that.div.style.width = window.innerWidth + "px";
- that.div.style.height = window.innerHeight + "px";
- setTimeout (function () {
- that.onResize ();
- }, 1);
- }, 1);
- };
-
- var escHandler = function (e) {
- if (e.keyCode == 27) {
- that.exitFullScreenHandler ();
- }
- };
-
- this.exitFullScreenHandler = function () {
- that.isFullScreen = false;
- that.browser.unregisterListener (document, "keydown", escHandler);
- that.browser.unregisterListener (window, "resize", resizeHandler);
- that.browser.unregisterListener (document.body, "orientationchange", rotationHandler);
- if (that.restoreSize) {
- that.container.style.width = that.savedSize.width;
- that.container.style.height = that.savedSize.height;
- }
-
- document.body.style.cssText = that.savedBodyStyle;
-
- that.savedParent.appendChild (that.container);
- document.body.removeChild (that.div);
- document.body.removeChild (that.expanderDiv);
-
- that.onResize ();
- that.onClose ();
- setTimeout (function () {
- that.onResize ();
- }, 1);
- };
-
- this.browser.registerListener (document, "keydown", escHandler, false);
- this.browser.registerListener (window, "resize", resizeHandler, false);
- this.browser.registerListener (document.body, "orientationchange", rotationHandler, false);
-
- this.onResize ();
-
- return this.exitFullScreenHandler;
- },
-
- /**
- * Ends full screen mode.
- */
- close : function () {
- this.exitFullScreenHandler ();
- }
-};
-
-/*
- * Copyright 2010 - 2012 Leo Sutic null, which results in an all-black image
- * @type String
- * @public
- */
- this.emptyImage = null;
-
- /**
- * Suffix to append to the tile filenames. Typically ".jpg" or
- * ".png".
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type String
- */
- this.suffix = null;
-
- /**
- * The width of the full image; in pixels.
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.width = 0;
-
- /**
- * The height of the full image; in pixels.
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.height = 0;
-
- /**
- * For {@link bigshot.Image} and {@link bigshot.SimpleImage}, the div
- * to use as a container for the image.
- *
- * @type HTMLDivElement
- */
- this.container = null;
-
- /**
- * The minimum zoom value. Zoom values are specified as a magnification; where
- * 2n is the magnification and n is the zoom value. So a zoom value of
- * 2 means a 4x magnification of the full image. -3 means showing an image that
- * is a eighth (1/8 or 1/23) of the full size.
- *
- * @type number
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- */
- this.minZoom = 0.0;
-
- /**
- * The maximum zoom value. Zoom values are specified as a magnification; where
- * 2n is the magnification and n is the zoom value. So a zoom value of
- * 2 means a 4x magnification of the full image. -3 means showing an image that
- * is a eighth (1/8 or 1/23) of the full size.
- *
- * @type number
- * @default 0.0
- */
- this.maxZoom = 0.0;
-
- /**
- * Size of one tile in pixels.
- *
- * @type int
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- */
- this.tileSize = 0;
-
- /**
- * Tile overlap. Not implemented.
- *
- * @type int
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- */
- this.overlap = 0;
-
- /**
- * Flag indicating that the image should wrap horizontally. The image wraps on tile
- * boundaries; so in order to get a seamless wrap at zoom level -n; the image width must
- * be evenly divisible by tileSize * 2^n. Set the minZoom value appropriately.
- *
- * @type boolean
- * @default false
- */
- this.wrapX = false;
-
- /**
- * Flag indicating that the image should wrap vertically. The image wraps on tile
- * boundaries; so in order to get a seamless wrap at zoom level -n; the image height must
- * be evenly divisible by tileSize * 2^n. Set the minZoom value appropriately.
- *
- * @type boolean
- * @default false
- */
- this.wrapY = false;
-
- /**
- * Base path for the image. This is filesystem dependent; but for the two most common cases
- * the following should be set
- *
- *
- *
- *
- * @type String
- */
- this.basePath = null;
-
- /**
- * The file system type. Used to create a filesystem instance unless
- * the fileSystem field is set. Possible values are "<path>/bigshot.php?file=<path-to-bigshot-archive-relative-to-bigshot.php>";
- * for example; "/bigshot.php?file=images/bigshot-sample.bigshot".
- * "<path-to-image-folder>";
- * for example; "/images/bigshot-sample".
- * "archive",
- * "folder" or "dzi".
- *
- * @type String
- * @default "folder"
- */
- this.fileSystemType = "folder";
-
- /**
- * A reference to a filesystem implementation. If set; it overrides the
- * fileSystemType field.
- *
- * @default set depending on value of bigshot.ImageParameters.fileSystemType
- * @type bigshot.FileSystem
- */
- this.fileSystem = null;
-
- /**
- * Object used to load data files.
- *
- * @default bigshot.DefaultDataLoader
- * @type bigshot.DataLoader
- */
- this.dataLoader = new bigshot.DefaultDataLoader ();
-
- /**
- * Enable the touch-friendly ui. The touch-friendly UI splits the viewport into
- * three click-sensitive regions:
- * 
false.
- */
- setZoom : function (zoom, updateViewport) {
- this.zoom = this.clampZoom (zoom);
- var zoomLevel = Math.ceil (this.zoom - this.getTextureStretch ());
- var zoomFactor = Math.pow (2, zoomLevel);
- var maxTileX = Math.ceil (zoomFactor * this.width / this.tileSize);
- var maxTileY = Math.ceil (zoomFactor * this.height / this.tileSize);
- for (var i = 0; i < this.layers.length; ++i) {
- this.layers[i].setMaxTiles (maxTileX, maxTileY);
- }
- if (updateViewport) {
- this.layout ();
- }
- },
-
- /**
- * Sets the maximum zoom value. The maximum magnification (of the full-size image)
- * is 2maxZoom. Set to 0.0 to avoid pixelation.
- *
- * @public
- * @param {number} maxZoom the maximum zoom value
- */
- setMaxZoom : function (maxZoom) {
- this.maxZoom = maxZoom;
- },
-
- /**
- * Gets the maximum zoom value. The maximum magnification (of the full-size image)
- * is 2maxZoom.
- *
- * @public
- * @type number
- */
- getMaxZoom : function () {
- return this.maxZoom;
- },
-
- /**
- * Sets the minimum zoom value. The minimum magnification (of the full-size image)
- * is 2minZoom, so a minZoom of -3 means that the smallest
- * image shown will be one-eighth of the full-size image.
- *
- * @public
- * @param {number} minZoom the minimum zoom value for this image
- */
- setMinZoom : function (minZoom) {
- this.minZoom = minZoom;
- },
-
- /**
- * Gets the minimum zoom value. The minimum magnification (of the full-size image)
- * is 2minZoom, so a minZoom of -3 means that the smallest
- * image shown will be one-eighth of the full-size image.
- *
- * @public
- * @type number
- */
- getMinZoom : function () {
- return this.minZoom;
- },
-
- /**
- * Adjusts a coordinate so that the center of zoom
- * remains constant during zooming operations. The
- * method is intended to be called twice, once for x
- * and once for y. The current and
- * centerOfZoom values will be the current
- * and the center for the x and y, respectively.
- *
- * @example
- * this.x = this.adjustCoordinateForZoom (this.x, zoomCenterX, oldZoom, newZoom);
- * this.y = this.adjustCoordinateForZoom (this.y, zoomCenterY, oldZoom, newZoom);
- *
- * @param {number} current the current value of the coordinate
- * @param {number} centerOfZoom the center of zoom along the coordinate axis
- * @param {number} oldZoom the old zoom value
- * @param {number} oldZoom the new zoom value
- * @type number
- * @returns the new value for the coordinate
- */
- adjustCoordinateForZoom : function (current, centerOfZoom, oldZoom, newZoom) {
- var zoomRatio = Math.pow (2, oldZoom) / Math.pow (2, newZoom);
- return centerOfZoom + (current - centerOfZoom) * zoomRatio;
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureStart : function (event) {
- this.currentGesture = {
- startZoom : this.zoom,
- scale : event.scale
- };
- },
-
- /**
- * Ends a gesture.
- *
- * @param {Event} event the gestureend event
- * @private
- */
- gestureEnd : function (event) {
- this.currentGesture = null;
- if (this.dragStart) {
- this.dragStart.hadGesture = true;
- }
- },
-
- /**
- * Adjusts the zoom level based on the scale property of the
- * gesture.
- *
- * @private
- */
- gestureChange : function (event) {
- if (this.currentGesture) {
- if (this.dragStart) {
- this.dragStart.hadGesture = true;
- }
-
- var newZoom = this.clampZoom (this.currentGesture.startZoom + Math.log (event.scale) / Math.log (2));
- var oldZoom = this.getZoom ();
- if (this.currentGesture.clientX !== undefined && this.currentGesture.clientY !== undefined) {
- var centerOfZoom = this.clientToImage (this.currentGesture.clientX, this.currentGesture.clientY);
-
- var nx = this.adjustCoordinateForZoom (this.x, centerOfZoom.x, oldZoom, newZoom);
- var ny = this.adjustCoordinateForZoom (this.y, centerOfZoom.y, oldZoom, newZoom);
-
- this.moveTo (nx, ny, newZoom);
- } else {
- this.setZoom (newZoom);
- this.layout ();
- }
- }
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- dragMouseDown : function (event) {
- this.dragStart = {
- x : event.clientX,
- y : event.clientY
- };
- this.dragLast = {
- clientX : event.clientX,
- clientY : event.clientY,
- dx : 0,
- dy : 0,
- dt : 1000000,
- time : new Date ().getTime ()
- };
- this.dragged = false;
- },
-
- /**
- * Handles a mouse drag event by panning the image.
- * Also sets the dragged flag to indicate that the
- * following click event should be ignored.
- * @private
- */
- dragMouseMove : function (event) {
- if (this.currentGesture != null && event.changedTouches != null && event.changedTouches.length > 0) {
- var cx = 0;
- var cy = 0;
- for (var i = 0; i < event.changedTouches.length; ++i) {
- cx += event.changedTouches[i].clientX;
- cy += event.changedTouches[i].clientY;
- }
- this.currentGesture.clientX = cx / event.changedTouches.length;
- this.currentGesture.clientY = cy / event.changedTouches.length;
- }
-
- if (this.currentGesture == null && this.dragStart != null) {
- var delta = {
- x : event.clientX - this.dragStart.x,
- y : event.clientY - this.dragStart.y
- };
- if (delta.x != 0 || delta.y != 0) {
- this.dragged = true;
- }
- var zoomFactor = Math.pow (2, this.zoom);
- var realX = delta.x / zoomFactor;
- var realY = delta.y / zoomFactor;
-
- this.dragStart = {
- x : event.clientX,
- y : event.clientY
- };
-
- var dt = new Date ().getTime () - this.dragLast.time;
- if (dt > 20) {
- this.dragLast = {
- dx : this.dragLast.clientX - event.clientX,
- dy : this.dragLast.clientY - event.clientY,
- dt : dt,
- clientX : event.clientX,
- clientY : event.clientY,
- time : new Date ().getTime ()
- };
- }
-
- this.moveTo (this.x - realX, this.y - realY);
- }
- },
-
- /**
- * Ends a drag event by freeing the associated structures.
- * @private
- */
- dragMouseUp : function (event) {
- if (this.currentGesture == null && !this.dragStart.hadGesture && this.dragStart != null) {
- this.dragStart = null;
- if (!this.dragged) {
- this.mouseClick (event);
- } else {
- var scale = Math.pow (2, this.zoom);
- var dx = this.dragLast.dx / scale;
- var dy = this.dragLast.dy / scale;
- var ds = Math.sqrt (dx * dx + dy * dy);
- var dt = this.dragLast.dt;
- var dtb = new Date ().getTime () - this.dragLast.time;
- this.dragLast = null;
-
- var v = dt > 0 ? (ds / dt) : 0;
- if (v > 0.05 && dtb < 250 && dt > 20 && this.parameters.fling) {
- var t0 = new Date ().getTime ();
-
- dx /= dt;
- dy /= dt;
-
- this.flyTo (this.x + dx * 250, this.y + dy * 250, this.zoom);
- }
- }
- }
- },
-
- /**
- * Mouse double-click handler. Pans to the clicked point and
- * zooms in half a zoom level (approx 40%).
- * @private
- */
- mouseDoubleClick : function (event) {
- var eventData = this.createImageEventData ({
- type : "dblclick",
- clientX : event.clientX,
- clientY : event.clientY
- });
- this.fireEvent ("dblclick", eventData);
- if (!eventData.defaultPrevented) {
- this.flyTo (eventData.imageX, eventData.imageY, this.zoom + 0.5);
- }
- },
-
- /**
- * Returns the current zoom level.
- *
- * @public
- * @type number
- */
- getZoom : function () {
- return this.zoom;
- },
-
- /**
- * Stops any current flyTo operation and sets the current position.
- *
- * @param [x] the new x-coordinate
- * @param [y] the new y-coordinate
- * @param [zoom] the new zoom level
- * @param [updateViewport=true] updates the viewport
- * @public
- */
- moveTo : function (x, y, zoom, updateViewport) {
- this.stopFlying ();
-
- if (x != null || y != null) {
- this.setPosition (x, y, false);
- }
- if (zoom != null) {
- this.setZoom (zoom, false);
- }
- if (updateViewport == undefined || updateViewport == true) {
- this.layout ();
- }
- },
-
- /**
- * Sets the current position.
- *
- * @param [x] the new x-coordinate
- * @param [y] the new y-coordinate
- * @param [updateViewport=true] if the viewport should be updated
- * @private
- */
- setPosition : function (x, y, updateViewport) {
- var clamped = this.clampXY (x, y);
-
- if (x != null) {
- if (this.parameters.wrapX) {
- if (x < 0 || x >= this.width) {
- x = (x + this.width) % this.width;
- }
- } else {
- x = clamped.x;
- }
- this.x = Math.max (0, Math.min (this.width, x));
- }
-
- if (y != null) {
- if (this.parameters.wrapY) {
- if (y < 0 || y >= this.height) {
- y = (y + this.height) % this.height;
- }
- } else {
- y = clamped.y;
- }
- this.y = Math.max (0, Math.min (this.height, y));
- }
-
- if (updateViewport != false) {
- this.layout ();
- }
- },
-
- /**
- * Helper function for calculating zoom levels.
- *
- * @public
- * @returns the zoom level at which the given number of full-image pixels
- * occupy the given number of screen pixels.
- * @param {number} imageDimension the image dimension in full-image pixels
- * @param {number} containerDimension the container dimension in screen pixels
- * @type number
- */
- fitZoom : function (imageDimension, containerDimension) {
- var scale = containerDimension / imageDimension;
- return Math.log (scale) / Math.LN2;
- },
-
- /**
- * Returns the maximum zoom level at which the full image
- * is visible in the viewport.
- * @public
- * @type number
- */
- getZoomToFitValue : function () {
- return Math.min (
- this.fitZoom (this.parameters.width, this.container.clientWidth),
- this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Returns the zoom level at which the image fills the whole
- * viewport.
- * @public
- * @type number
- */
- getZoomToFillValue : function () {
- return Math.max (
- this.fitZoom (this.parameters.width, this.container.clientWidth),
- this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Adjust the zoom level to fit the image in the viewport.
- * @public
- */
- zoomToFit : function () {
- this.moveTo (null, null, this.getZoomToFitValue ());
- },
-
- /**
- * Adjust the zoom level to fit the image in the viewport.
- * @public
- */
- zoomToFill : function () {
- this.moveTo (null, null, this.getZoomToFillValue ());
- },
-
- /**
- * Adjust the zoom level to fit the
- * image height in the viewport.
- * @public
- */
- zoomToFitHeight : function () {
- this.moveTo (null, null, this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Adjust the zoom level to fit the
- * image width in the viewport.
- * @public
- */
- zoomToFitWidth : function () {
- this.moveTo (null, null, this.fitZoom (this.parameters.width, this.container.clientWidth));
- },
-
- /**
- * Smoothly adjust the zoom level to fit the
- * image height in the viewport.
- * @public
- */
- flyZoomToFitHeight : function () {
- this.flyTo (null, this.parameters.height / 2, this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Smoothly adjust the zoom level to fit the
- * image width in the viewport.
- * @public
- */
- flyZoomToFitWidth : function () {
- this.flyTo (this.parameters.width / 2, null, this.fitZoom (this.parameters.width, this.container.clientWidth));
- },
-
- /**
- * Smoothly adjust the zoom level to fit the
- * full image in the viewport.
- * @public
- */
- flyZoomToFit : function () {
- this.flyTo (this.parameters.width / 2, this.parameters.height / 2, this.getZoomToFitValue ());
- },
-
- /**
- * Converts client-relative screen coordinates to image coordinates.
- *
- * @param {number} clientX the client x-coordinate
- * @param {number} clientY the client y-coordinate
- *
- * @returns {number} .x the image x-coordinate
- * @returns {number} .y the image y-coordinate
- * @type Object
- */
- clientToImage : function (clientX, clientY) {
- var zoomFactor = Math.pow (2, this.zoom);
- return {
- x : (clientX - this.container.clientWidth / 2) / zoomFactor + this.x,
- y : (clientY - this.container.clientHeight / 2) / zoomFactor + this.y
- };
- },
-
- /**
- * Handles mouse wheel actions.
- * @private
- */
- mouseWheelHandler : function (delta, event) {
- var zoomDelta = false;
- if (delta > 0) {
- zoomDelta = 0.5;
- } else if (delta < 0) {
- zoomDelta = -0.5;
- }
-
- if (zoomDelta) {
- var centerOfZoom = this.clientToImage (event.clientX, event.clientY);
- var newZoom = Math.min (this.maxZoom, Math.max (this.getZoom () + zoomDelta, this.minZoom));
-
- var nx = this.adjustCoordinateForZoom (this.x, centerOfZoom.x, this.getZoom (), newZoom);
- var ny = this.adjustCoordinateForZoom (this.y, centerOfZoom.y, this.getZoom (), newZoom);
-
- this.flyTo (nx, ny, newZoom, true);
- }
- },
-
- /**
- * Translates mouse wheel events.
- * @private
- */
- mouseWheel : function (event){
- var delta = 0;
- if (!event) /* For IE. */
- event = window.event;
- if (event.wheelDelta) { /* IE/Opera. */
- delta = event.wheelDelta / 120;
- /*
- * In Opera 9, delta differs in sign as compared to IE.
- */
- if (window.opera)
- delta = -delta;
- } else if (event.detail) { /* Mozilla case. */
- /*
- * In Mozilla, sign of delta is different than in IE.
- * Also, delta is multiple of 3.
- */
- delta = -event.detail;
- }
-
- /*
- * If delta is nonzero, handle it.
- * Basically, delta is now positive if wheel was scrolled up,
- * and negative, if wheel was scrolled down.
- */
- if (delta) {
- this.mouseWheelHandler (delta, event);
- }
-
- /*
- * Prevent default actions caused by mouse wheel.
- * That might be ugly, but we handle scrolls somehow
- * anyway, so don't bother here..
- */
- if (event.preventDefault) {
- event.preventDefault ();
- }
- event.returnValue = false;
- },
-
- /**
- * Triggers a right-sizing of all layers.
- * Called on window resize via the {@link bigshot.ImageBase#onresizeHandler} stub.
- * @public
- */
- onresize : function () {
- this.resize ();
- this.layout ();
- },
-
- /**
- * Returns the current x-coordinate, which is the full-image x coordinate
- * in the center of the viewport.
- * @public
- * @type number
- */
- getX : function () {
- return this.x;
- },
-
- /**
- * Returns the current y-coordinate, which is the full-image x coordinate
- * in the center of the viewport.
- * @public
- * @type number
- */
- getY : function () {
- return this.y;
- },
-
- /**
- * Interrupts the current {@link #flyTo}, if one is active.
- * @public
- */
- stopFlying : function () {
- this.flying++;
- },
-
- /**
- * Smoothly flies to the specified position.
- *
- * @public
- * @param {number} [x=current x] the new x-coordinate
- * @param {number} [y=current y] the new y-coordinate
- * @param {number} [zoom=current zoom] the new zoom level
- * @param {boolean} [uniformApproach=false] if true, uses the same interpolation curve for x, y and zoom.
- */
- flyTo : function (x, y, zoom, uniformApproach) {
- var that = this;
-
- x = x != null ? x : this.x;
- y = y != null ? y : this.y;
- zoom = zoom != null ? zoom : this.zoom;
- uniformApproach = uniformApproach != null ? uniformApproach : false;
-
- var startX = this.x;
- var startY = this.y;
- var startZoom = this.zoom;
-
- var clamped = this.clampXY (x, y);
- var targetX = this.parameters.wrapX ? x : clamped.x;
- var targetY = this.parameters.wrapY ? y : clamped.y;
- var targetZoom = Math.min (this.maxZoom, Math.max (zoom, this.minZoom));
-
- this.flying++;
- var flyingAtStart = this.flying;
-
- var t0 = new Date ().getTime ();
-
- var approach = function (start, target, dt, step, linear) {
- var delta = (target - start);
-
- var diff = - delta * Math.pow (2, -dt * step);
-
- var lin = dt * linear;
- if (delta < 0) {
- diff = Math.max (0, diff - lin);
- } else {
- diff = Math.min (0, diff + lin);
- }
-
- return target + diff;
- };
-
-
- var iter = function () {
- if (that.flying == flyingAtStart) {
- var dt = (new Date ().getTime () - t0) / 1000;
-
- var nx = approach (startX, targetX, dt, uniformApproach ? 10 : 4, uniformApproach ? 0.2 : 1.0);
- var ny = approach (startY, targetY, dt, uniformApproach ? 10 : 4, uniformApproach ? 0.2 : 1.0);
- var nz = approach (startZoom, targetZoom, dt, 10, 0.2);
- var done = true;
-
- var zoomFactor = Math.min (Math.pow (2, that.getZoom ()), 1);
-
- if (Math.abs (nx - targetX) < (0.5 * zoomFactor)) {
- nx = targetX;
- } else {
- done = false;
- }
- if (Math.abs (ny - targetY) < (0.5 * zoomFactor)) {
- ny = targetY;
- } else {
- done = false;
- }
- if (Math.abs (nz - targetZoom) < 0.02) {
- nz = targetZoom;
- } else {
- done = false;
- }
- that.setPosition (nx, ny, false);
- that.setZoom (nz, false);
- that.layout ();
- if (!done) {
- that.browser.requestAnimationFrame (iter, that.container);
- }
- };
- }
- this.browser.requestAnimationFrame (iter, this.container);
- },
-
- /**
- * Returns the maximum zoom level at which a rectangle with the given dimensions
- * fit into the viewport.
- *
- * @public
- * @param {number} w the width of the rectangle, given in full-image pixels
- * @param {number} h the height of the rectangle, given in full-image pixels
- * @type number
- * @returns the zoom level that will precisely fit the given rectangle
- */
- rectVisibleAtZoomLevel : function (w, h) {
- return Math.min (
- this.fitZoom (w, this.container.clientWidth),
- this.fitZoom (h, this.container.clientHeight));
- },
-
- /**
- * Returns the base size in screen pixels of the two zoom touch areas.
- * The zoom out border will be getTouchAreaBaseSize() pixels wide,
- * and the center zoom in hotspot will be 2*getTouchAreaBaseSize() pixels wide
- * and tall.
- * @deprecated
- * @type number
- * @public
- */
- getTouchAreaBaseSize : function () {
- var averageSize = ((this.container.clientWidth + this.container.clientHeight) / 2) * 0.2;
- return Math.min (averageSize, Math.min (this.container.clientWidth, this.container.clientHeight) / 6);
- },
-
- /**
- * Creates a new {@link bigshot.ImageEvent} using the supplied data object,
- * transforming the client x- and y-coordinates to local and image coordinates.
- * The returned event object will have the {@link bigshot.ImageEvent#localX},
- * {@link bigshot.ImageEvent#localY}, {@link bigshot.ImageEvent#imageX},
- * {@link bigshot.ImageEvent#imageY}, {@link bigshot.Event#target} and
- * {@link bigshot.Event#currentTarget} fields set.
- *
- * @param {Object} data data object with initial values for the event object
- * @param {number} data.clientX the clientX of the event
- * @param {number} data.clientY the clientY of the event
- * @returns the new event object
- * @type bigshot.ImageEvent
- */
- createImageEventData : function (data) {
- var elementPos = this.browser.getElementPosition (this.container);
- data.localX = data.clientX - elementPos.x;
- data.localY = data.clientY - elementPos.y;
-
- var scale = Math.pow (2, this.zoom);
-
- data.imageX = (data.localX - this.container.clientWidth / 2) / scale + this.x;
- data.imageY = (data.localY - this.container.clientHeight / 2) / scale + this.y;
-
- data.target = this;
- data.currentTarget = this;
-
- return new bigshot.ImageEvent (data);
- },
-
- /**
- * Handles mouse click events. If the touch UI is active,
- * we'll pan and/or zoom, as appropriate. If not, we just ignore
- * the event.
- * @private
- */
- mouseClick : function (event) {
- var eventData = this.createImageEventData ({
- type : "click",
- clientX : event.clientX,
- clientY : event.clientY
- });
- this.fireEvent ("click", eventData);
- /*
- if (!eventData.defaultPrevented) {
- if (!this.parameters.touchUI) {
- return;
- }
- if (this.dragged) {
- return;
- }
-
- var zoomOutBorderSize = this.getTouchAreaBaseSize ();
- var zoomInHotspotSize = this.getTouchAreaBaseSize ();
-
- if (Math.abs (clickPos.x) > (this.container.clientWidth / 2 - zoomOutBorderSize) || Math.abs (clickPos.y) > (this.container.clientHeight / 2 - zoomOutBorderSize)) {
- this.flyTo (this.x, this.y, this.zoom - 0.5);
- } else {
- var newZoom = this.zoom;
- if (Math.abs (clickPos.x) < zoomInHotspotSize && Math.abs (clickPos.y) < zoomInHotspotSize) {
- newZoom += 0.5;
- }
- var scale = Math.pow (2, this.zoom);
- clickPos.x /= scale;
- clickPos.y /= scale;
- this.flyTo (this.x + clickPos.x, this.y + clickPos.y, newZoom);
- }
- }
- */
- },
-
- /**
- * Briefly shows the touch ui zones. See the {@link bigshot.ImageParameters#touchUI}
- * documentation for an explanation of the touch ui.
- *
- * @public
- * @deprecated All common touch gestures are supported by default.
- * @see bigshot.ImageParameters#touchUI
- * @param {int} [delay] milliseconds before fading out
- * @param {int} [fadeOut] milliseconds to fade out the zone overlays in
- */
- showTouchUI : function (delay, fadeOut) {
- if (!delay) {
- delay = 2500;
- }
- if (!fadeOut) {
- fadeOut = 1000;
- }
-
- var zoomOutBorderSize = this.getTouchAreaBaseSize ();
- var zoomInHotspotSize = this.getTouchAreaBaseSize ();
- var centerX = this.container.clientWidth / 2;
- var centerY = this.container.clientHeight / 2;
-
- var frameDiv = document.createElement ("div");
- frameDiv.style.position = "absolute";
- frameDiv.style.zIndex = "9999";
- frameDiv.style.opacity = 0.9;
- frameDiv.style.width = this.container.clientWidth + "px";
- frameDiv.style.height = this.container.clientHeight + "px";
-
- var centerSpotAnchor = document.createElement ("div");
- centerSpotAnchor.style.position = "absolute";
-
- var centerSpot = document.createElement ("div");
- centerSpot.style.position = "relative";
- centerSpot.style.background = "black";
- centerSpot.style.textAlign = "center";
- centerSpot.style.top = (centerY - zoomInHotspotSize) + "px";
- centerSpot.style.left = (centerX - zoomInHotspotSize) + "px";
- centerSpot.style.width = (2 * zoomInHotspotSize) + "px";
- centerSpot.style.height = (2 * zoomInHotspotSize) + "px";
-
- frameDiv.appendChild (centerSpotAnchor);
- centerSpotAnchor.appendChild (centerSpot);
- centerSpot.innerHTML = "ZOOM IN";
-
- var zoomOutBorderAnchor = document.createElement ("div");
- zoomOutBorderAnchor.style.position = "absolute";
-
- var zoomOutBorder = document.createElement ("div");
- zoomOutBorder.style.position = "relative";
- zoomOutBorder.style.border = zoomOutBorderSize + "px solid black";
- zoomOutBorder.style.top = "0px";
- zoomOutBorder.style.left = "0px";
- zoomOutBorder.style.textAlign = "center";
- zoomOutBorder.style.width = this.container.clientWidth + "px";
- zoomOutBorder.style.height = this.container.clientHeight + "px";
- zoomOutBorder.style.MozBoxSizing =
- zoomOutBorder.style.boxSizing =
- zoomOutBorder.style.WebkitBoxSizing =
- "border-box";
-
- zoomOutBorder.innerHTML = "ZOOM OUT";
-
- zoomOutBorderAnchor.appendChild (zoomOutBorder);
- frameDiv.appendChild (zoomOutBorderAnchor);
-
- this.container.appendChild (frameDiv);
-
- var that = this;
- var opacity = 0.9;
- var fadeOutSteps = fadeOut / 50;
- if (fadeOutSteps < 1) {
- fadeOutSteps = 1;
- }
- var iter = function () {
- opacity = opacity - (0.9 / fadeOutSteps);
- if (opacity < 0.0) {
- that.container.removeChild (frameDiv);
- } else {
- frameDiv.style.opacity = opacity;
- setTimeout (iter, 50);
- }
- };
- setTimeout (iter, delay);
- },
-
- /**
- * Forces exit from full screen mode, if we're there.
- * @public
- */
- exitFullScreen : function () {
- if (this.fullScreenHandler) {
- this.removeEventListeners ();
- this.fullScreenHandler.close ();
- this.addEventListeners ();
- this.fullScreenHandler = null;
- return;
- }
- },
-
- /**
- * Maximizes the image to cover the browser viewport.
- * The container div is removed from its parent node upon entering
- * full screen mode. When leaving full screen mode, the container
- * is appended to its old parent node. To avoid rearranging the
- * nodes, wrap the container in an extra div.
- *
- * basePath and container.
- * If you intend to use the archive filesystem, you need to set the fileSystemType to "archive"
- * as well.
- * @see bigshot.ImageBase#dispose
- * @class A tiled, zoomable image viewer.
- *
- * Creating a Wrapping Image
- *
- *
- *
- *
- *
- *
- *
- * @augments bigshot.ImageBase
- */
-bigshot.Image = function (parameters) {
- bigshot.setupFileSystem (parameters);
- parameters.merge (parameters.fileSystem.getDescriptor (), false);
-
- bigshot.ImageBase.call (this, parameters);
-}
-
-bigshot.Image.prototype = {
- setupLayers : function () {
- var that = this;
- this.thisTileCache = new bigshot.ImageTileCache (function () {
- that.layout ();
- }, null, this.parameters);
-
- this.addLayer (
- new bigshot.TileLayer (this, this.parameters, 0, 0, this.thisTileCache)
- );
- }
-};
-
-bigshot.Object.extend (bigshot.Image, bigshot.ImageBase);
-
-/*
- * Copyright 2010 - 2012 Leo Sutic minZoom parameter to -3 in the {@link bigshot.ImageParameters} when creating
- * the image. (I will also set wrapX to true.)container.
- * If the imgElement parameter is not given, then basePath, width and height are also required. The
- * following parameters are not supported and should be left as defaults: fileSystem, fileSystemType,
- * maxTextureMagnification and tileSize. wrapX and wrapY may only be used if the imgElement is not
- * set.
- *
- * @param {HTMLImageElement} [imgElement] an img element to use. The element should have style.position = "absolute".
- * @see bigshot.ImageBase#dispose
- * @class A zoomable image viewer.
- * @augments bigshot.ImageBase
- */
-bigshot.SimpleImage = function (parameters, imgElement) {
- parameters.merge ({
- fileSystem : null,
- fileSystemType : "simple",
- maxTextureMagnification : 1.0,
- tileSize : 1024
- }, true);
-
- if (imgElement) {
- parameters.merge ({
- width : imgElement.width,
- height : imgElement.height
- });
- this.imgElement = imgElement;
- } else {
- if (parameters.width == 0 || parameters.height == 0) {
- throw new Error ("No imgElement and missing width or height in ImageParameters");
- }
- }
- bigshot.setupFileSystem (parameters);
-
- bigshot.ImageBase.call (this, parameters);
-}
-
-bigshot.SimpleImage.prototype = {
- setupLayers : function () {
- if (!this.imgElement) {
- /*
- this.imgElement = document.createElement ("img");
- this.imgElement.src = this.parameters.basePath;
- this.imgElement.style.position = "absolute";
- */
- this.imgElement = document.createElement ("div");
- this.imgElement.style.backgroundImage = "url('" + this.parameters.basePath + "')";
- this.imgElement.style.position = "absolute";
- if (!this.parameters.wrapX && !this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "no-repeat";
- } else if (this.parameters.wrapX && !this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "repeat-x";
- } else if (!this.parameters.wrapX && this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "repeat-y";
- } else if (this.parameters.wrapX && this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "repeat";
- }
- }
-
- this.addLayer (
- new bigshot.HTMLDivElementLayer (this, this.imgElement, this.parameters.width, this.parameters.height, this.parameters.wrapX, this.parameters.wrapY)
- );
- }
-};
-
-bigshot.Object.extend (bigshot.SimpleImage, bigshot.ImageBase);
-
-/*
- * Copyright 2010 - 2012 Leo Sutic .bigshot archive filesystem adapter.
- *
- * @class Bigshot archive filesystem.
- * @param {bigshot.ImageParameters|bigshot.VRPanoramaParameters} parameters the associated image parameters
- * @augments bigshot.FileSystem
- * @constructor
- */
-bigshot.ArchiveFileSystem = function (parameters) {
- this.indexSize = 0;
- this.offset = 0;
- this.index = {};
- this.prefix = "";
- this.suffix = "";
- this.parameters = parameters;
-
- var browser = new bigshot.Browser ();
- var req = browser.createXMLHttpRequest ();
- req.open("GET", this.parameters.basePath + "&start=0&length=24&type=text/plain", false);
- req.send(null);
- if(req.status == 200) {
- if (req.responseText.substring (0, 7) != "BIGSHOT") {
- alert ("\"" + this.parameters.basePath + "\" is not a valid bigshot file");
- return;
- }
- this.indexSize = parseInt (req.responseText.substring (8), 16);
- this.offset = this.indexSize + 24;
-
- req.open("GET", this.parameters.basePath + "&type=text/plain&start=24&length=" + this.indexSize, false);
- req.send(null);
- if(req.status == 200) {
- var substrings = req.responseText.split (":");
- for (var i = 0; i < substrings.length; i += 3) {
- this.index[substrings[i]] = {
- start : parseInt (substrings[i + 1]) + this.offset,
- length : parseInt (substrings[i + 2])
- };
- }
- } else {
- alert ("The index of \"" + this.parameters.basePath + "\" could not be loaded: " + req.status);
- }
- } else {
- alert ("The header of \"" + this.parameters.basePath + "\" could not be loaded: " + req.status);
- }
-};
-
-
-bigshot.ArchiveFileSystem.prototype = {
- getDescriptor : function () {
- this.browser = new bigshot.Browser ();
- var req = this.browser.createXMLHttpRequest ();
-
- req.open("GET", this.getFilename ("descriptor"), false);
- req.send(null);
- var descriptor = {};
- if(req.status == 200) {
- var substrings = req.responseText.split (":");
- for (var i = 0; i < substrings.length; i += 2) {
- if (substrings[i] == "suffix") {
- descriptor[substrings[i]] = substrings[i + 1];
- } else {
- descriptor[substrings[i]] = parseInt (substrings[i + 1]);
- }
- }
- this.suffix = descriptor.suffix;
- return descriptor;
- } else {
- throw new Error ("Unable to find descriptor.");
- }
- },
-
- getPosterFilename : function () {
- return this.getFilename ("poster" + this.suffix);
- },
-
- getFilename : function (name) {
- name = this.getPrefix () + name;
- if (!this.index[name] && console) {
- console.log ("Can't find " + name);
- }
- var f = this.parameters.basePath + "&start=" + this.index[name].start + "&length=" + this.index[name].length;
- if (name.substring (name.length - 4) == ".jpg") {
- f = f + "&type=image/jpeg";
- } else if (name.substring (name.length - 4) == ".png") {
- f = f + "&type=image/png";
- } else {
- f = f + "&type=text/plain";
- }
- return f;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- var key = (-zoomLevel) + "/" + tileX + "_" + tileY + this.suffix;
- return this.getFilename (key);
- },
-
- getPrefix : function () {
- if (this.prefix) {
- return this.prefix + "/";
- } else {
- return "";
- }
- },
-
- setPrefix : function (prefix) {
- this.prefix = prefix;
- }
-}
-
-bigshot.Object.validate ("bigshot.ArchiveFileSystem", bigshot.FileSystem);
-/*
- * Copyright 2010 - 2012 Leo Sutic null, which results in an all-black image
- * @type String
- * @public
- */
- this.emptyImage = null;
-
- /**
- * Suffix to append to the tile filenames. Typically ".jpg" or
- * ".png".
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type String
- */
- this.suffix = null;
-
- /**
- * The width of the full image; in pixels.
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.width = 0;
-
- /**
- * The height of the full image; in pixels.
- *
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.height = 0;
-
- /**
- * For {@link bigshot.VRPanorama}, the {@code div} to render into.
- *
- * @type HTMLDivElement
- */
- this.container = null;
-
- /**
- * The maximum number of times to split a cube face into four quads.
- *
- * @type int
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- */
- this.maxTesselation = -1;
-
- /**
- * Size of one tile in pixels.
- *
- * @type int
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- */
- this.tileSize = 0;
-
- /**
- * Tile overlap. Not implemented.
- *
- * @type int
- * @default Optional set by MakeImagePyramid and loaded from descriptor
- */
- this.overlap = 0;
-
- /**
- * Base path for the image. This is filesystem dependent; but for the two most common cases
- * the following should be set
- *
- *
- *
- *
- * @type String
- */
- this.basePath = null;
-
- /**
- * The file system type. Used to create a filesystem instance unless
- * the fileSystem field is set. Possible values are "<path>/bigshot.php?file=<path-to-bigshot-archive-relative-to-bigshot.php>";
- * for example; "/bigshot.php?file=images/bigshot-sample.bigshot".
- * "<path-to-image-folder>";
- * for example; "/images/bigshot-sample".
- * "archive",
- * "folder" or "dzi".
- *
- * @type String
- * @default "folder"
- */
- this.fileSystemType = "folder";
-
- /**
- * A reference to a filesystem implementation. If set; it overrides the
- * fileSystemType field.
- *
- * @default set depending on value of bigshot.VRPanoramaParameters#fileSystemType
- * @type bigshot.FileSystem
- */
- this.fileSystem = null;
-
- /**
- * Object used to load data files.
- *
- * @default bigshot.DefaultDataLoader
- * @type bigshot.DataLoader
- */
- this.dataLoader = new bigshot.DefaultDataLoader ();
-
- /**
- * The maximum magnification for the texture tiles making up the VR cube.
- * Used for level-of-detail tesselation.
- * A value of 1.0 means that textures will never be stretched (one texture pixel will
- * always be at most one screen pixel), unless there is no more detailed texture available.
- * A value of 2.0 means that textures may be stretched at most 2x (one texture pixel
- * will always be at most 2x2 screen pixels)
- * The bigger the value, the less texture data is required, but quality suffers.
- *
- * @type number
- * @default 1.0
- */
- this.maxTextureMagnification = 1.0;
-
- /**
- * The WebGL texture filter to use for magnifying textures.
- * Possible values are all values valid for TEXTURE_MAG_FILTER.
- * null means NEAREST.
- *
- * @default null / NEAREST.
- */
- this.textureMagFilter = null;
-
- /**
- * The WebGL texture filter to use for supersampling (minifying) textures.
- * Possible values are all values valid for TEXTURE_MIN_FILTER.
- * null means NEAREST.
- *
- * @default null / NEAREST.
- */
- this.textureMinFilter = null;
-
- /**
- * Minimum vertical field of view in degrees.
- *
- * @default 2.0
- * @type number
- */
- this.minFov = 2.0;
-
- /**
- * Maximum vertical field of view in degrees.
- *
- * @default 90.0
- * @type number
- */
- this.maxFov = 90;
-
- /**
- * Minimum pitch in degrees.
- *
- * @default -90
- * @type number
- */
- this.minPitch = -90;
-
- /**
- * Maximum pitch in degrees.
- *
- * @default 90.0
- * @type number
- */
- this.maxPitch = 90;
-
- /**
- * Minimum yaw in degrees. The number is interpreted modulo 360.
- * The default value, -360, is just to make sure that we won't accidentally
- * trip it. If the number is set to something in the interval 0-360,
- * the autoRotate function will pan back and forth.
- *
- * @default -360
- * @type number
- */
- this.minYaw = -360;
-
- /**
- * Maximum yaw in degrees. The number is interpreted modulo 360.
- * The default value, 720, is just to make sure that we won't accidentally
- * trip it. If the number is set to something in the interval 0-360,
- * the autoRotate function will pan back and forth.
- *
- * @default 720.0
- * @type number
- */
- this.maxYaw = 720;
-
- /**
- * Transform offset for yaw.
- * @default 0.0
- * @type number
- */
- this.yawOffset = 0.0;
-
- /**
- * Transform offset for pitch.
- * @default 0.0
- * @type number
- */
- this.pitchOffset = 0.0;
-
- /**
- * Transform offset for roll.
- * @default 0.0
- * @type number
- */
- this.rollOffset = 0.0;
-
- /**
- * Function to call when all six cube faces have loaded the base texture level
- * and can be rendered.
- *
- * @type function()
- * @default null
- */
- this.onload = null;
-
- /**
- * The rendering back end to use.
- * Values are "css" and "webgl".
- *
- * @type String
- * @default null
- */
- this.renderer = null;
-
- /**
- * Controls whether the panorama can be "flung" by quickly dragging and releasing.
- *
- * @type boolean
- * @default true
- */
- this.fling = true;
-
- /**
- * Controls the decay of the "flinging" animation. The fling animation decays
- * as 2^(-flingScale * t) where t is the time in milliseconds since the animation started.
- * For the animation to decay to half-speed in X seconds,
- * flingScale should then be set to 1 / (X*1000).
- *
- * @type float
- * @default 0.004
- */
- this.flingScale = 0.004;
-
- if (values) {
- for (var k in values) {
- this[k] = values[k];
- }
- }
-
- this.merge = function (values, overwrite) {
- for (var k in values) {
- if (overwrite || !this[k]) {
- this[k] = values[k];
- }
- }
- }
- return this;
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic Creating a Cube Map
- *
- *
- *
- *
- * java -jar bigshot.jar input.jpg temp/dzi \
- * --preset dzi-cubemap \
- * --format folders
- *
overlap, face-size
- * and tile-size parameters. Let's take these one by one:
- *
- *
- *
- *
- * overlap: Overlap defines how much tiles should overlap, just to avoid
- * seams in the rendered results caused by finite numeric precision. The default is 2, which
- * I've found works great for me.tile-size: First you need to decide what POT size the output should be.
- * Then subtract the overlap value. For example, if you set overlap to 1, tile-size
- * could be 127, 255, 511, or any 2n-1 value.face-size: Finally, we decide on a size for the full cube face. This should be
- * tile-size * 2n. Let's say we set n=3, which makes each face 8x8 tiles at the most zoomed-in
- * level. For a tile-size of 255, then, face-size is 255*23 = 255*8 = 2040.
- *
- *
- * java -jar bigshot.jar input.jpg temp/dzi \
- * --preset dzi-cubemap \
- * --overlap 1 \
- * --tile-size 255 \
- * --face-size 2040 \
- * --format folders
- *
- *
- *
- * WARNING: Resulting image tile size (tile-size + overlap) is not a power of two: 255
- *
- *
- *
- * WARNING: face-size is not an even multiple of tile-size: 2040 % 254 != 0
- *
Integration With SaladoPlayer
- *
- * Serving DZI as Folders
- *
- *
- *
- *
- * java -jar bigshot.jar input.jpg temp/dzi \
- * --preset dzi-cubemap \
- * --format folders
- *
- *
- *
- * bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * container : document.getElementById ("canvas"),
- * basePath : "temp/dzi",
- * fileSystemType : "dzi"
- * }));
- *
- *
- *
- * <SaladoPlayer>
- * <global debug="false" firstPanorama="pano"/>
- * <panoramas>
- * <panorama id="pano" path="temp/dzi/face_f.xml"/>
- * </panoramas>
- * </SaladoPlayer>
- *
Serving DZI as Archive
- *
- *
- *
- *
- * java -jar bigshot.jar input.jpg temp/dzi.bigshot \
- * --preset dzi-cubemap \
- * --format archive
- *
- *
- *
- * bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * container : document.getElementById ("canvas"),
- * basePath : "/bigshot.php?file=temp/dzi.bigshot&entry=",
- * fileSystemType : "dzi"
- * }));
- *
- *
- *
- * <SaladoPlayer>
- * <global debug="false" firstPanorama="pano"/>
- * <panoramas>
- * <panorama id="pano" path="/bigshot.php?file=dzi.bigshot&entry=face_f.xml"/>
- * </panoramas>
- * </SaladoPlayer>
- *
Usage example:
- * @example
- * var bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * basePath : "/bigshot.php?file=myvr.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_canvas")
- * }));
- * @class A cube-map VR panorama.
- * @extends bigshot.EventDispatcher
- *
- * @param {bigshot.VRPanoramaParameters} parameters the panorama parameters.
- *
- * @see bigshot.VRPanoramaParameters
- */
-bigshot.VRPanorama = function (parameters) {
- bigshot.EventDispatcher.call (this);
-
- var that = this;
-
- this.parameters = parameters;
- this.maxTextureMagnification = parameters.maxTextureMagnification;
- this.container = parameters.container;
- this.browser = new bigshot.Browser ();
- this.dragStart = null;
- this.dragDistance = 0;
- this.hotspots = [];
- this.disposed = false;
-
- this.transformOffsets = {
- y : parameters.yawOffset,
- p : parameters.pitchOffset,
- r : parameters.rollOffset
- };
-
- /**
- * Current camera state.
- * @private
- */
- this.state = {
- rotation : {
- /**
- * Pitch in degrees.
- * @type float
- * @private
- */
- p : 0.0,
-
- /**
- * Yaw in degrees.
- * @type float
- * @private
- */
- y : 0.0,
-
- r : 0
- },
-
- /**
- * Field of view (vertical) in degrees.
- * @type float
- * @private
- */
- fov : 45,
-
- translation : {
- /**
- * Translation along X-axis.
- * @private
- * @type float
- */
- x : 0.0,
-
- /**
- * Translation along Y-axis.
- * @private
- * @type float
- */
- y : 0.0,
-
- /**
- * Translation along Z-axis.
- * @private
- * @type float
- */
- z : 0.0
- }
- };
-
- /**
- * Renderer wrapper.
- * @private
- * @type bigshot.VRRenderer
- */
- this.renderer = null;
- if (this.parameters.renderer) {
- if (this.parameters.renderer == "css") {
- this.renderer = new bigshot.CSS3DVRRenderer (this.container);
- } else if (this.parameters.renderer == "webgl") {
- this.renderer = new bigshot.WebGLVRRenderer (this.container)
- } else {
- throw new Error ("Unknown renderer: " + this.parameters.renderer);
- }
- } else {
- this.renderer =
- bigshot.WebGLUtil.isWebGLSupported () ?
- new bigshot.WebGLVRRenderer (this.container)
- :
- new bigshot.CSS3DVRRenderer (this.container);
- }
-
- /**
- * List of render listeners to call at the start and end of each render.
- *
- * @private
- */
- this.renderListeners = new Array ();
-
- this.renderables = new Array ();
-
- /**
- * Current value of the idle counter.
- *
- * @private
- */
- this.idleCounter = 0;
-
- /**
- * Maximum value of the idle counter before any idle events start,
- * such as autorotation.
- *
- * @private
- */
- this.maxIdleCounter = -1;
-
-
- /**
- * Integer acting as a "permit". When the smoothRotate function
- * is called, the current value is incremented and saved. If the number changes
- * that particular call to smoothRotate stops. This way we avoid
- * having multiple smoothRotate rotations going in parallel.
- * @private
- * @type int
- */
- this.smoothrotatePermit = 0;
-
- /**
- * Helper function to consume events.
- * @private
- */
- var consumeEvent = function (event) {
- if (event.preventDefault) {
- event.preventDefault ();
- }
- return false;
- };
-
- /**
- * Full screen handler.
- *
- * @private
- */
- this.fullScreenHandler = null;
-
- this.renderAsapPermitTaken = false;
-
- /**
- * An element to use as reference when resizing the canvas element.
- * If non-null, any onresize() calls will result in the canvas being
- * resized to the size of this element.
- *
- * @private
- */
- this.sizeContainer = null;
-
- /**
- * The six cube faces.
- *
- * @type bigshot.VRFace[]
- * @private
- */
- var facesInit = {
- facesLeft : 6,
- faceLoaded : function () {
- this.facesLeft--;
- if (this.facesLeft == 0) {
- if (that.parameters.onload) {
- that.parameters.onload ();
- }
- }
- }
- };
- var onFaceLoad = function () {
- facesInit.faceLoaded ()
- };
-
- this.vrFaces = new Array ();
- this.vrFaces[0] = new bigshot.VRFace (this, "f", {x:-1, y:1, z:-1}, 2.0, {x:1, y:0, z:0}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[1] = new bigshot.VRFace (this, "b", {x:1, y:1, z:1}, 2.0, {x:-1, y:0, z:0}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[2] = new bigshot.VRFace (this, "l", {x:-1, y:1, z:1}, 2.0, {x:0, y:0, z:-1}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[3] = new bigshot.VRFace (this, "r", {x:1, y:1, z:-1}, 2.0, {x:0, y:0, z:1}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[4] = new bigshot.VRFace (this, "u", {x:-1, y:1, z:1}, 2.0, {x:1, y:0, z:0}, {x:0, y:0, z:-1}, onFaceLoad);
- this.vrFaces[5] = new bigshot.VRFace (this, "d", {x:-1, y:-1, z:-1}, 2.0, {x:1, y:0, z:0}, {x:0, y:0, z:1}, onFaceLoad);
-
- /**
- * Helper function to translate touch events to mouse-like events.
- * @private
- */
- var translateEvent = function (event) {
- if (event.clientX) {
- return event;
- } else {
- return {
- clientX : event.changedTouches[0].clientX,
- clientY : event.changedTouches[0].clientY
- };
- };
- };
-
- this.lastTouchStartAt = -1;
-
- this.allListeners = {
- "mousedown" : function (e) {
- that.smoothRotate ();
- that.resetIdle ();
- that.dragMouseDown (e);
- return consumeEvent (e);
- },
- "mouseup" : function (e) {
- that.resetIdle ();
- that.dragMouseUp (e);
- return consumeEvent (e);
- },
- "mousemove" : function (e) {
- that.resetIdle ();
- that.dragMouseMove (e);
- return consumeEvent (e);
- },
- "gesturestart" : function (e) {
- that.gestureStart (e);
- return consumeEvent (e);
- },
- "gesturechange" : function (e) {
- that.gestureChange (e);
- return consumeEvent (e);
- },
- "gestureend" : function (e) {
- that.gestureEnd (e);
- return consumeEvent (e);
- },
-
- "DOMMouseScroll" : function (e) {
- that.resetIdle ();
- that.mouseWheel (e);
- return consumeEvent (e);
- },
- "mousewheel" : function (e) {
- that.resetIdle ();
- that.mouseWheel (e);
- return consumeEvent (e);
- },
- "dblclick" : function (e) {
- that.mouseDoubleClick (e);
- return consumeEvent (e);
- },
-
- "touchstart" : function (e) {
- that.smoothRotate ();
- that.lastTouchStartAt = new Date ().getTime ();
- that.resetIdle ();
- that.dragMouseDown (translateEvent (e));
- return consumeEvent (e);
- },
- "touchend" : function (e) {
- that.resetIdle ();
- var handled = that.dragMouseUp (translateEvent (e));
- if (!handled && (that.lastTouchStartAt > new Date().getTime() - 350)) {
- that.mouseDoubleClick (translateEvent (e));
- }
- that.lastTouchStartAt = -1;
- return consumeEvent (e);
- },
- "touchmove" : function (e) {
- if (that.dragDistance > 24) {
- that.lastTouchStartAt = -1;
- }
- that.resetIdle ();
- that.dragMouseMove (translateEvent (e));
- return consumeEvent (e);
- }
- };
- this.addEventListeners ();
-
- /**
- * Stub function to call onresize on this instance.
- *
- * @private
- */
- this.onresizeHandler = function (e) {
- that.onresize ();
- };
-
- this.browser.registerListener (window, 'resize', this.onresizeHandler, false);
- this.browser.registerListener (document.body, 'orientationchange', this.onresizeHandler, false);
-
- this.setPitch (0.0);
- this.setYaw (0.0);
- this.setFov (45.0);
-}
-
-/*
- * Statics
- */
-
-/**
- * When the mouse is pressed and dragged, the camera rotates
- * proportionally to the length of the dragging.
- *
- * @constant
- * @public
- * @static
- */
-bigshot.VRPanorama.DRAG_GRAB = "grab";
-
-/**
- * When the mouse is pressed and dragged, the camera continuously
- * rotates with a speed that is proportional to the length of the
- * dragging.
- *
- * @constant
- * @public
- * @static
- */
-bigshot.VRPanorama.DRAG_PAN = "pan";
-
-/**
- * @name bigshot.VRPanorama.RenderState
- * @class The state the renderer is in when a {@link bigshot.VRPanorama.RenderListener} is called.
- *
- * @see bigshot.VRPanorama.ONRENDER_BEGIN
- * @see bigshot.VRPanorama.ONRENDER_END
- */
-
-/**
- * A RenderListener state parameter value used at the start of each render.
- *
- * @constant
- * @public
- * @static
- * @type bigshot.VRPanorama.RenderState
- */
-bigshot.VRPanorama.ONRENDER_BEGIN = 0;
-
-/**
- * A RenderListener state parameter value used at the end of each render.
- *
- * @constant
- * @public
- * @static
- * @type bigshot.VRPanorama.RenderState
- */
-bigshot.VRPanorama.ONRENDER_END = 1;
-
-/**
- * A RenderListener cause parameter indicating that a previously requested
- * texture has loaded and a render is forced. The data parameter is not used.
- *
- * @constant
- * @public
- * @static
- * @param {bigshot.VRPanorama.RenderCause}
- */
-bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE = 0;
-
-/**
- * @name bigshot.VRPanorama.RenderCause
- * @class The reason why the {@link bigshot.VRPanorama} is being rendered.
- * Due to the events outside of the panorama, the VR panorama may be forced to
- * re-render itself. When this happens, the {@link bigshot.VRPanorama.RenderListener}s
- * receive a constant indicating the cause of the rendering.
- *
- * @see bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE
- */
-
-/**
- * Specification for functions passed to {@link bigshot.VRPanorama#addRenderListener}.
- *
- * @name bigshot.VRPanorama.RenderListener
- * @function
- * @param {bigshot.VRPanorama.RenderState} state The state of the renderer. Can be {@link bigshot.VRPanorama.ONRENDER_BEGIN} or {@link bigshot.VRPanorama.ONRENDER_END}
- * @param {bigshot.VRPanorama.RenderCause} [cause] The reason for rendering the scene. Can be undefined or {@link bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE}
- * @param {Object} [data] An optional data object that is dependent on the cause. See the documentation
- * for the different causes.
- */
-
-/**
- * Specification for functions passed to {@link bigshot.VRPanorama#addRenderable}.
- *
- * @name bigshot.VRPanorama.Renderable
- * @function
- * @param {bigshot.VRRenderer} renderer The renderer object to use.
- * @param {bigshot.TexturedQuadScene} scene The scene to render into.
- */
-
-/** */
-bigshot.VRPanorama.prototype = {
- /**
- * Adds a hotstpot.
- *
- * @param {bigshot.VRHotspot} hs the hotspot to add
- */
- addHotspot : function (hs) {
- this.hotspots.push (hs);
- },
-
- /**
- * Returns the {@link bigshot.VRPanoramaParameters} object used by this instance.
- *
- * @type bigshot.VRPanoramaParameters
- */
- getParameters : function () {
- return this.parameters;
- },
-
- /**
- * Sets the view translation.
- *
- * @param x translation of the viewer along the X axis
- * @param y translation of the viewer along the Y axis
- * @param z translation of the viewer along the Z axis
- */
- setTranslation : function (x, y, z) {
- this.state.translation.x = x;
- this.state.translation.y = y;
- this.state.translation.z = z;
- },
-
- /**
- * Returns the current view translation as an x-y-z triplet.
- *
- * @returns {number} x translation of the viewer along the X axis
- * @returns {number} y translation of the viewer along the Y axis
- * @returns {number} z translation of the viewer along the Z axis
- */
- getTranslation : function () {
- return this.state.translation;
- },
-
- /**
- * Sets the field of view.
- *
- * @param {number} fov the vertical field of view, in degrees
- */
- setFov : function (fov) {
- fov = Math.min (this.parameters.maxFov, fov);
- fov = Math.max (this.parameters.minFov, fov);
- this.state.fov = fov;
- },
-
- /**
- * Gets the field of view.
- *
- * @return {number} the vertical field of view, in degrees
- */
- getFov : function () {
- return this.state.fov;
- },
-
- /**
- * Returns the angle (yaw, pitch) for a given pixel coordinate.
- *
- * @param {number} x the x-coordinate of the pixel, measured in pixels
- * from the left edge of the panorama.
- * @param {number} y the y-coordinate of the pixel, measured in pixels
- * from the top edge of the panorama.
- * @return {number} .yaw the yaw angle of the pixel (0 <= yaw < 360)
- * @return {number} .pitch the pitch angle of the pixel (-180 <= pitch <= 180)
- *
- * @example
- * var container = ...; // an HTML element
- * var pano = ...; // a bigshot.VRPanorama
- * ...
- * container.addEventListener ("click", function (e) {
- * var clickX = e.clientX - container.offsetX;
- * var clickY = e.clientY - container.offsetY;
- * var polar = pano.screenToPolar (clickX, clickY);
- * alert ("You clicked at: " +
- * "Yaw: " + polar.yaw +
- * " Pitch: " + polar.pitch);
- * });
- */
- screenToPolar : function (x, y) {
- var dray = this.screenToRayDelta (x, y);
- var ray = $V([dray.x, dray.y, dray.z, 1.0]);
-
- ray = Matrix.RotationX (this.getPitch () * Math.PI / 180.0).ensure4x4 ().x (ray);
- ray = Matrix.RotationY (-this.getYaw () * Math.PI / 180.0).ensure4x4 ().x (ray);
-
- var dx = ray.e(1);
- var dy = ray.e(2);
- var dz = ray.e(3);
-
- var dxz = Math.sqrt (dx * dx + dz * dz);
-
- var dyaw = Math.atan2 (dx, -dz) * 180 / Math.PI;
- var dpitch = Math.atan2 (dy, dxz) * 180 / Math.PI;
-
- var res = {};
- res.yaw = (dyaw + 360) % 360.0;
- res.pitch = dpitch;
-
- return res;
- },
-
- /**
- * Restricts the pitch value to be between the minPitch and maxPitch parameters.
- *
- * @param {number} p the pitch value
- * @returns the constrained pitch value.
- */
- snapPitch : function (p) {
- p = Math.min (this.parameters.maxPitch, p);
- p = Math.max (this.parameters.minPitch, p);
- return p;
- },
-
- /**
- * Sets the current camera pitch.
- *
- * @param {number} p the pitch, in degrees
- */
- setPitch : function (p) {
- this.state.rotation.p = this.snapPitch (p);
- },
-
- /**
- * Subtraction mod 360, sort of...
- *
- * @private
- * @returns the angular distance with smallest magnitude to add to p0 to get to p1 % 360
- */
- circleDistance : function (p0, p1) {
- if (p1 > p0) {
- // p1 is somewhere clockwise to p0
- var d1 = (p1 - p0); // move clockwise
- var d2 = ((p1 - 360) - p0); // move counterclockwise, first -p0 to get to 0, then p1 - 360.
- return Math.abs (d1) < Math.abs (d2) ? d1 : d2;
- } else {
- // p1 is somewhere counterclockwise to p0
- var d1 = (p1 - p0); // move counterclockwise
- var d2 = (360 - p0) + p1; // move clockwise, first (360-p= to get to 0, then another p1 degrees
- return Math.abs (d1) < Math.abs (d2) ? d1 : d2;
- }
- },
-
- /**
- * Subtraction mod 360, sort of...
- *
- * @private
- */
- circleSnapTo : function (p, p1, p2) {
- var d1 = this.circleDistance (p, p1);
- var d2 = this.circleDistance (p, p2);
- return Math.abs (d1) < Math.abs (d2) ? p1 : p2;
- },
-
- /**
- * Constrains a yaw value to the required minimum and maximum values.
- *
- * @private
- */
- snapYaw : function (y) {
- y %= 360;
- if (y < 0) {
- y += 360;
- }
- if (this.parameters.minYaw < this.parameters.maxYaw) {
- if (y > this.parameters.maxYaw || y < this.parameters.minYaw) {
- y = circleSnapTo (y, this.parameters.minYaw, this.parameters.maxYaw);
- }
- } else {
- // The only time when minYaw > maxYaw is when the interval
- // contains the 0 angle.
- if (y > this.parameters.minYaw) {
- // ok, we're somewhere between minYaw and 0.0
- } else if (y > this.parameters.maxYaw) {
- // we're somewhere between maxYaw and minYaw
- // (but on the wrong side).
- // figure out the nearest point and snap to it
- y = circleSnapTo (y, this.parameters.minYaw, this.parameters.maxYaw);
- } else {
- // ok, we're somewhere between 0.0 and maxYaw
- }
- }
- return y;
- },
-
- /**
- * Sets the current camera yaw. The yaw is normalized between
- * 0 <= y < 360.
- *
- * @param {number} y the yaw, in degrees
- */
- setYaw : function (y) {
- this.state.rotation.y = this.snapYaw (y);
- },
-
- /**
- * Gets the current camera yaw.
- *
- * @return {number} the yaw, in degrees
- */
- getYaw : function () {
- return this.state.rotation.y;
- },
-
- /**
- * Gets the current camera pitch.
- *
- * @return {number} the pitch, in degrees
- */
- getPitch : function () {
- return this.state.rotation.p;
- },
-
- /**
- * Unregisters event handlers and other page-level hooks. The client need not call this
- * method unless bigshot images are created and removed from the page
- * dynamically. In that case, this method must be called when the client wishes to
- * free the resources allocated by the image. Otherwise the browser will garbage-collect
- * all resources automatically.
- * @public
- */
- dispose : function () {
- this.disposed = true;
- this.browser.unregisterListener (window, "resize", this.onresizeHandler, false);
- this.browser.unregisterListener (document.body, "orientationchange", this.onresizeHandler, false);
- this.removeEventListeners ();
-
- for (var i = 0; i < this.vrFaces.length; ++i) {
- this.vrFaces[i].dispose ();
- }
- this.renderer.dispose ();
- },
-
- /**
- * Creates and initializes a {@link bigshot.VREvent} object.
- * The {@link bigshot.VREvent#ray}, {@link bigshot.VREvent#yaw},
- * {@link bigshot.VREvent#pitch}, {@link bigshot.Event#target} and
- * {@link bigshot.Event#currentTarget} fields are set.
- *
- * @param {Object} data the data object for the event
- * @param {number} data.clientX the client x-coordinate of the event
- * @param {number} data.clientY the client y-coordinate of the event
- * @returns the new event object
- * @type bigshot.VREvent
- */
- createVREventData : function (data) {
- var elementPos = this.browser.getElementPosition (this.container);
- data.localX = data.clientX - elementPos.x;
- data.localY = data.clientY - elementPos.y;
-
- data.ray = this.screenToRay (data.localX, data.localY);
-
- var polar = this.screenToPolar (data.localX, data.localY);
- data.yaw = polar.yaw;
- data.pitch = polar.pitch;
- data.target = this;
- data.currentTarget = this;
-
- return new bigshot.VREvent (data);
- },
-
-
- /**
- * Sets up transformation matrices etc. Calls all render listeners with a state parameter
- * of {@link bigshot.VRPanorama.ONRENDER_BEGIN}.
- *
- * @private
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- beginRender : function (cause, data) {
- this.onrender (bigshot.VRPanorama.ONRENDER_BEGIN, cause, data);
- this.renderer.beginRender (this.state.rotation, this.state.fov, this.state.translation, this.transformOffsets);
- },
-
-
- /**
- * Add a function that will be called at various times during the render.
- *
- * @param {bigshot.VRPanorama.RenderListener} listener the listener function
- */
- addRenderListener : function (listener) {
- var rl = new Array ();
- rl = rl.concat (this.renderListeners);
- rl.push (listener);
- this.renderListeners = rl;
- },
-
- /**
- * Removes a function that will be called at various times during the render.
- *
- * @param {bigshot.VRPanorama.RenderListener} listener the listener function
- */
- removeRenderListener : function (listener) {
- var rl = new Array ();
- rl = rl.concat (this.renderListeners);
- for (var i = 0; i < rl.length; ++i) {
- if (rl[i] === listener) {
- rl.splice (i, 1);
- break;
- }
- }
- this.renderListeners = rl;
- },
-
- /**
- * Called at the start and end of every render.
- *
- * @event
- * @private
- * @type function()
- * @param {bigshot.VRPanorama.RenderState} state the current render state
- */
- onrender : function (state, cause, data) {
- var rl = this.renderListeners;
- for (var i = 0; i < rl.length; ++i) {
- rl[i](state, cause, data);
- }
- },
-
- /**
- * Performs per-render cleanup. Calls all render listeners with a state parameter
- * of {@link bigshot.VRPanorama.ONRENDER_END}.
- *
- * @private
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- endRender : function (cause, data) {
- for (var f in this.vrFaces) {
- this.vrFaces[f].endRender ();
- }
- this.renderer.endRender ();
- this.onrender (bigshot.VRPanorama.ONRENDER_END, cause, data);
- },
-
- /**
- * Add a function that will be called to render any additional quads.
- *
- * @param {bigshot.VRPanorama.Renderable} renderable The renderable, a function responsible for
- * rendering additional scene elements.
- */
- addRenderable : function (renderable) {
- var rl = new Array ();
- rl.concat (this.renderables);
- rl.push (renderable);
- this.renderables = rl;
- },
-
- /**
- * Removes a function that will be called to render any additional quads.
- *
- * @param {bigshot.VRPanorama.Renderable} renderable The renderable added using
- * {@link bigshot.VRPanorama#addRenderable}.
- */
- removeRenderable : function (renderable) {
- var rl = new Array ();
- rl.concat (this.renderables);
- for (var i = 0; i < rl.length; ++i) {
- if (rl[i] == listener) {
- rl.splice (i, 1);
- break;
- }
- }
- this.renderables = rl;
- },
-
- /**
- * Renders the VR cube.
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- render : function (cause, data) {
- if (!this.disposed) {
- this.beginRender (cause, data);
-
- var scene = this.renderer.createTexturedQuadScene ();
-
- for (var f in this.vrFaces) {
- this.vrFaces[f].render (scene);
- }
-
- for (var i = 0; i < this.renderables.length; ++i) {
- this.renderables[i](this.renderer, scene);
- }
-
- scene.render ();
-
- for (var i = 0; i < this.hotspots.length; ++i) {
- this.hotspots[i].layout ();
- }
-
- this.endRender (cause, data);
- }
- },
-
- /**
- * Render updated faces. Called as tiles are loaded from the server.
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- renderUpdated : function (cause, data) {
- if (!this.disposed && this.renderer.supportsUpdate ()) {
- this.beginRender (cause, data);
-
- var scene = this.renderer.createTexturedQuadScene ();
-
- for (var f in this.vrFaces) {
- if (this.vrFaces[f].isUpdated ()) {
- this.vrFaces[f].render (scene);
- }
- }
-
- scene.render ();
-
- for (var i = 0; i < this.hotspots.length; ++i) {
- this.hotspots[i].layout ();
- }
-
- this.endRender (cause, data);
- } else {
- this.render (cause, data);
- }
- },
-
- /**
- * The current drag mode.
- *
- * @private
- */
- dragMode : bigshot.VRPanorama.DRAG_GRAB,
-
- /**
- * Sets the mouse dragging mode.
- *
- * @param mode one of {@link bigshot.VRPanorama.DRAG_PAN} or {@link bigshot.VRPanorama.DRAG_GRAB}.
- */
- setDragMode : function (mode) {
- this.dragMode = mode;
- },
-
- addEventListeners : function () {
- for (var k in this.allListeners) {
- this.browser.registerListener (this.container, k, this.allListeners[k], false);
- }
- },
-
- removeEventListeners : function () {
- for (var k in this.allListeners) {
- this.browser.unregisterListener (this.container, k, this.allListeners[k], false);
- }
- },
-
- dragMouseDown : function (e) {
- this.dragStart = {
- clientX : e.clientX,
- clientY : e.clientY
- };
- this.dragLast = {
- clientX : e.clientX,
- clientY : e.clientY,
- dx : 0,
- dy : 0,
- dt : 1000000,
- time : new Date ().getTime ()
- };
- this.dragDistance = 0;
- },
-
- dragMouseUp : function (e) {
- // In case we got a mouse up with out a previous mouse down,
- // for example, double-click on title bar to maximize the
- // window
- if (this.dragStart == null || this.dragLast == null) {
- this.dragStart = null;
- this.dragLast = null;
- return;
- }
-
- this.dragStart = null;
- var dx = this.dragLast.dx;
- var dy = this.dragLast.dy;
- var ds = Math.sqrt (dx * dx + dy * dy);
- var dt = this.dragLast.dt;
- var dtb = new Date ().getTime () - this.dragLast.time;
- this.dragLast = null;
-
- var v = dt > 0 ? (ds / dt) : 0;
- if (v > 0.05 && dtb < 250 && dt > 20 && this.parameters.fling) {
- var scale = this.state.fov / this.renderer.getViewportHeight ();
-
- var t0 = new Date ().getTime ();
-
- var flingScale = this.parameters.flingScale;
-
- dx /= dt;
- dy /= dt;
-
- this.smoothRotate (function (dat) {
- var dt = new Date ().getTime () - t0;
- var fact = Math.pow (2, -dt * flingScale);
- var d = (dx * dat * scale) * fact;
- return fact > 0.01 ? d : null;
- }, function (dat) {
- var dt = new Date ().getTime () - t0;
- var fact = Math.pow (2, -dt * flingScale);
- var d = (dy * dat * scale) * fact;
- return fact > 0.01 ? d : null;
- }, function () {
- return null;
- });
- return true;
- } else {
- this.smoothRotate ();
- return false;
- }
- },
-
- dragMouseMove : function (e) {
- if (this.dragStart != null && this.currentGesture == null) {
- if (this.dragMode == bigshot.VRPanorama.DRAG_GRAB) {
- this.smoothRotate ();
- var scale = this.state.fov / this.renderer.getViewportHeight ();
- var dx = e.clientX - this.dragStart.clientX;
- var dy = e.clientY - this.dragStart.clientY;
- this.dragDistance += dx + dy;
- this.setYaw (this.getYaw () - dx * scale);
- this.setPitch (this.getPitch () - dy * scale);
- this.renderAsap ();
- this.dragStart = e;
- var dt = new Date ().getTime () - this.dragLast.time;
- if (dt > 20) {
- this.dragLast = {
- dx : this.dragLast.clientX - e.clientX,
- dy : this.dragLast.clientY - e.clientY,
- dt : dt,
- clientX : e.clientX,
- clientY : e.clientY,
- time : new Date ().getTime ()
- };
- }
- } else {
- var scale = 0.1 * this.state.fov / this.renderer.getViewportHeight ();
- var dx = e.clientX - this.dragStart.clientX;
- var dy = e.clientY - this.dragStart.clientY;
- this.dragDistance = dx + dy;
- this.smoothRotate (
- function () {
- return dx * scale;
- },
- function () {
- return dy * scale;
- });
- }
- }
- },
-
- onMouseDoubleClick : function (e, x, y) {
- var eventData = this.createVREventData ({
- type : "dblclick",
- clientX : e.clientX,
- clientY : e.clientY
- });
- this.fireEvent ("dblclick", eventData);
- if (!eventData.defaultPrevented) {
- this.smoothRotateToXY (x, y);
- }
- },
-
- mouseDoubleClick : function (e) {
- var pos = this.browser.getElementPosition (this.container);
- this.onMouseDoubleClick (e, e.clientX - pos.x, e.clientY - pos.y);
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureStart : function (event) {
- this.currentGesture = {
- startFov : this.getFov (),
- scale : event.scale
- };
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureEnd : function (event) {
- this.currentGesture = null;
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureChange : function (event) {
- if (this.currentGesture) {
- var newFov = this.currentGesture.startFov / event.scale;
- this.setFov (newFov);
- this.renderAsap ();
- }
- },
-
- /**
- * Sets the maximum texture magnification.
- *
- * @param {number} v the maximum texture magnification
- * @see bigshot.VRPanoramaParameters#maxTextureMagnification
- */
- setMaxTextureMagnification : function (v) {
- this.maxTextureMagnification = v;
- },
-
- /**
- * Gets the current maximum texture magnification.
- *
- * @type number
- * @see bigshot.VRPanoramaParameters#maxTextureMagnification
- */
- getMaxTextureMagnification : function () {
- return this.maxTextureMagnification;
- },
-
- /**
- * Computes the minimum field of view where the resulting image will not
- * have to stretch the textures more than given by the
- * {@link bigshot.VRPanoramaParameters#maxTextureMagnification} parameter.
- *
- * @type number
- * @return the minimum FOV, below which it is necessary to stretch the
- * vr cube texture more than the given {@link bigshot.VRPanoramaParameters#maxTextureMagnification}
- */
- getMinFovFromViewportAndImage : function () {
- var halfHeight = this.renderer.getViewportHeight () / 2;
-
- var minFaceHeight = this.vrFaces[0].parameters.height;
- for (var i in this.vrFaces) {
- minFaceHeight = Math.min (minFaceHeight, this.vrFaces[i].parameters.height);
- }
-
- var edgeSizeY = this.maxTextureMagnification * minFaceHeight / 2;
-
- var wy = halfHeight / edgeSizeY;
-
- var mz = Math.atan (wy) * 180 / Math.PI;
-
- return mz * 2;
- },
-
- /**
- * Transforms screen coordinates to a world-coordinate ray.
- * @private
- */
- screenToRay : function (x, y) {
- var dray = this.screenToRayDelta (x, y);
- var ray = this.renderer.transformToWorld (dray);
- ray = Matrix.RotationY (-this.transformOffsets.y * Math.PI / 180.0).ensure4x4 ().xPoint3Dhom1 (ray);
- ray = Matrix.RotationX (-this.transformOffsets.p * Math.PI / 180.0).ensure4x4 ().xPoint3Dhom1 (ray);
- ray = Matrix.RotationZ (-this.transformOffsets.r * Math.PI / 180.0).ensure4x4 ().xPoint3Dhom1 (ray);
- return ray;
- },
-
- /**
- * @private
- */
- screenToRayDelta : function (x, y) {
- var halfHeight = this.renderer.getViewportHeight () / 2;
- var halfWidth = this.renderer.getViewportWidth () / 2;
- var x = (x - halfWidth);
- var y = (y - halfHeight);
-
- var edgeSizeY = Math.tan ((this.state.fov / 2) * Math.PI / 180);
- var edgeSizeX = edgeSizeY * this.renderer.getViewportWidth () / this.renderer.getViewportHeight ();
-
- var wx = x * edgeSizeX / halfWidth;
- var wy = y * edgeSizeY / halfHeight;
- var wz = -1.0;
-
- return {
- x : wx,
- y : wy,
- z : wz
- };
- },
-
- /**
- * Smoothly rotates the panorama so that the
- * point given by x and y, in pixels relative to the top left corner
- * of the panorama, ends up in the center of the viewport.
- *
- * @param {int} x the x-coordinate, in pixels from the left edge
- * @param {int} y the y-coordinate, in pixels from the top edge
- */
- smoothRotateToXY : function (x, y) {
- var polar = this.screenToPolar (x, y);
-
- this.smoothRotateTo (this.snapYaw (polar.yaw), this.snapPitch (polar.pitch), this.getFov (), this.state.fov / 200);
- },
-
- /**
- * Gives the step to take to slowly approach the
- * target value.
- *
- * @example
- * current = current + this.ease (current, target, 1.0);
- * @private
- */
- ease : function (current, target, speed, snapFrom) {
- var easingFrom = speed * 40;
- if (!snapFrom) {
- snapFrom = speed / 5;
- }
- var ignoreFrom = speed / 1000;
-
- var distance = current - target;
- if (distance > easingFrom) {
- distance = -speed;
- } else if (distance < -easingFrom) {
- distance = speed;
- } else if (Math.abs (distance) < snapFrom) {
- distance = -distance;
- } else if (Math.abs (distance) < ignoreFrom) {
- distance = 0;
- } else {
- distance = - (speed * distance) / (easingFrom);
- }
- return distance;
- },
-
- /**
- * Resets the "idle" clock.
- * @private
- */
- resetIdle : function () {
- this.idleCounter = 0;
- },
-
- /**
- * Idle clock.
- * @private
- */
- idleTick : function () {
- if (this.maxIdleCounter < 0) {
- return;
- }
- ++this.idleCounter;
- if (this.idleCounter == this.maxIdleCounter) {
- this.autoRotate ();
- }
- var that = this;
- setTimeout (function () {
- that.idleTick ();
- }, 1000);
- },
-
- /**
- * Sets the panorama to auto-rotate after a certain time has
- * elapsed with no user interaction. Default is disabled.
- *
- * @param {int} delay the delay in seconds. Set to < 0 to disable
- * auto-rotation when idle
- */
- autoRotateWhenIdle : function (delay) {
- this.maxIdleCounter = delay;
- this.idleCounter = 0;
- if (delay < 0) {
- return;
- } else if (this.maxIdleCounter > 0) {
- var that = this;
- setTimeout (function () {
- that.idleTick ();
- }, 1000);
- }
- },
-
- /**
- * Starts auto-rotation of the camera. If the yaw is constrained,
- * will pan back and forth between the yaw endpoints. Call
- * {@link #smoothRotate}() to stop the rotation.
- */
- autoRotate : function () {
- var that = this;
- var scale = this.state.fov / 400;
-
- var speed = scale;
- var dy = speed;
- this.smoothRotate (
- function () {
- var nextPos = that.getYaw () + dy;
- if (that.parameters.minYaw < that.parameters.maxYaw) {
- if (nextPos > that.parameters.maxYaw || nextPos < that.parameters.minYaw) {
- dy = -dy;
- }
- } else {
- // The only time when minYaw > maxYaw is when the interval
- // contains the 0 angle.
- if (nextPos > that.parameters.minYaw) {
- // ok, we're somewhere between minYaw and 0.0
- } else if (nextPos > that.parameters.maxYaw) {
- dy = -dy;
- } else {
- // ok, we're somewhere between 0.0 and maxYaw
- }
- }
- return dy;
- }, function () {
- return that.ease (that.getPitch (), 0.0, speed);
- }, function () {
- return that.ease (that.getFov (), 45.0, 0.1);
- });
- },
-
- /**
- * Smoothly rotates the panorama to the given state.
- *
- * @param {number} yaw the target yaw
- * @param {number} pitch the target pitch
- * @param {number} fov the target vertical field of view
- * @param {number} the speed to rotate with
- */
- smoothRotateTo : function (yaw, pitch, fov, speed) {
- var that = this;
- this.smoothRotate (
- function () {
- var distance = that.circleDistance (yaw, that.getYaw ());
- var d = -that.ease (0, distance, speed);
- return Math.abs (d) > 0.01 ? d : null;
- }, function () {
- var d = that.ease (that.getPitch (), pitch, speed);
- return Math.abs (d) > 0.01 ? d : null;
- }, function () {
- var d = that.ease (that.getFov (), fov, speed);
- return Math.abs (d) > 0.01 ? d : null;
- }
- );
- },
-
-
- /**
- * Smoothly rotates the camera. If all of the dp, dy and df functions are null, stops
- * any smooth rotation.
- *
- * @param {function()} [dy] function giving the yaw increment for the next frame
- * or null if no further yaw movement is required
- * @param {function()} [dp] function giving the pitch increment for the next frame
- * or null if no further pitch movement is required
- * @param {function()} [df] function giving the field of view (degrees) increment
- * for the next frame or null if no further fov adjustment is required
- */
- smoothRotate : function (dy, dp, df) {
- ++this.smoothrotatePermit;
- var savedPermit = this.smoothrotatePermit;
- if (!dp && !dy && !df) {
- return;
- }
-
- var that = this;
- var fs = {
- dy : dy,
- dp : dp,
- df : df,
- t : new Date ().getTime ()
- };
- var stepper = function () {
- if (that.smoothrotatePermit == savedPermit) {
- var now = new Date ().getTime ();
- var dat = now - fs.t;
- fs.t = now;
-
- var anyFunc = false;
- if (fs.dy) {
- var d = fs.dy(dat);
- if (d != null) {
- anyFunc = true;
- that.setYaw (that.getYaw () + d);
- } else {
- fs.dy = null;
- }
- }
-
- if (fs.dp) {
- var d = fs.dp(dat);
- if (d != null) {
- anyFunc = true;
- that.setPitch (that.getPitch () + d);
- } else {
- fs.dp = null;
- }
- }
-
- if (fs.df) {
- var d = fs.df(dat);
- if (d != null) {
- anyFunc = true;
- that.setFov (that.getFov () + d);
- } else {
- fs.df = null;
- }
- }
- that.render ();
- if (anyFunc) {
- that.browser.requestAnimationFrame (stepper, that.renderer.getElement ());
- }
- }
- };
- stepper ();
- },
-
- /**
- * Translates mouse wheel events.
- * @private
- */
- mouseWheel : function (event){
- var delta = 0;
- if (!event) /* For IE. */
- event = window.event;
- if (event.wheelDelta) { /* IE/Opera. */
- delta = event.wheelDelta / 120;
- /*
- * In Opera 9, delta differs in sign as compared to IE.
- */
- if (window.opera)
- delta = -delta;
- } else if (event.detail) { /* Mozilla case. */
- /*
- * In Mozilla, sign of delta is different than in IE.
- * Also, delta is multiple of 3.
- */
- delta = -event.detail;
- }
-
- /*
- * If delta is nonzero, handle it.
- * Basically, delta is now positive if wheel was scrolled up,
- * and negative, if wheel was scrolled down.
- */
- if (delta) {
- this.mouseWheelHandler (delta);
- }
-
- /*
- * Prevent default actions caused by mouse wheel.
- * That might be ugly, but we handle scrolls somehow
- * anyway, so don't bother here..
- */
- if (event.preventDefault) {
- event.preventDefault ();
- }
- event.returnValue = false;
- },
-
- /**
- * Utility function to interpret mouse wheel events.
- * @private
- */
- mouseWheelHandler : function (delta) {
- var that = this;
- var target = null;
- if (delta > 0) {
- if (this.getFov () > this.parameters.minFov) {
- target = this.getFov () * 0.9;
- }
- }
- if (delta < 0) {
- if (this.getFov () < this.parameters.maxFov) {
- target = this.getFov () / 0.9;
- }
- }
- if (target != null) {
- this.smoothRotate (null, null, function () {
- var df = (target - that.getFov ()) / 1.5;
- return Math.abs (df) > 0.01 ? df : null;
- });
- }
- },
-
- /**
- * Maximizes the image to cover the browser viewport.
- * The container div is removed from its parent node upon entering
- * full screen mode. When leaving full screen mode, the container
- * is appended to its old parent node. To avoid rearranging the
- * nodes, wrap the container in an extra div.
- *
- * null
- * to disable.
- */
- autoResizeContainer : function (sizeContainer) {
- this.sizeContainer = sizeContainer;
- }
-}
-
-/**
- * Fired when the user double-clicks on the panorama.
- *
- * @name bigshot.VRPanorama#dblclick
- * @event
- * @param {bigshot.VREvent} event the event object
- */
-
-bigshot.Object.extend (bigshot.VRPanorama, bigshot.EventDispatcher);
-/*
- * Copyright 2010 - 2012 Leo Sutic frac of its area is visible.
- *
- * @param {number} frac the fraction (0.0 - 1.0) of the hotspot that must be visible for
- * it to be shown.
- * @type function(clipData)
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_FRACTION = function (panorama, frac) {
- return function (clipData) {
- var r = {
- x0 : Math.max (clipData.x, 0),
- y0 : Math.max (clipData.y, 0),
- x1 : Math.min (clipData.x + clipData.w, panorama.renderer.getViewportWidth ()),
- y1 : Math.min (clipData.y + clipData.h, panorama.renderer.getViewportHeight ())
- };
- var full = clipData.w * clipData.h;
- var visibleWidth = (r.x1 - r.x0);
- var visibleHeight = (r.y1 - r.y0);
- if (visibleWidth > 0 && visibleHeight > 0) {
- var visible = visibleWidth * visibleHeight;
-
- return (visible / full) >= frac;
- } else {
- return false;
- }
- }
-};
-
-/**
- * Hides the hotspot if its center is outside the viewport.
- *
- * @type function(clipData)
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_CENTER = function (panorama) {
- return function (clipData) {
- var c = {
- x : clipData.x + clipData.w / 2,
- y : clipData.y + clipData.h / 2
- };
- return c.x >= 0 && c.x < panorama.renderer.getViewportWidth () &&
- c.y >= 0 && c.y < panorama.renderer.getViewportHeight ();
- }
-}
-
-/**
- * Resizes the hotspot to fit in the viewport. Hides the hotspot if
- * it is completely outside the viewport.
- *
- * @type function(clipData)
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_ADJUST = function (panorama) {
- return function (clipData) {
- if (clipData.x < 0) {
- clipData.w -= -clipData.x;
- clipData.x = 0;
- }
- if (clipData.y < 0) {
- clipData.h -= -clipData.y;
- clipData.y = 0;
- }
- if (clipData.x + clipData.w > panorama.renderer.getViewportWidth ()) {
- clipData.w = panorama.renderer.getViewportWidth () - clipData.x - 1;
- }
- if (clipData.y + clipData.h > panorama.renderer.getViewportHeight ()) {
- clipData.h = panorama.renderer.getViewportHeight () - clipData.y - 1;
- }
-
- return clipData.w > 0 && clipData.h > 0;
- }
-}
-
-/**
- * Shrinks the hotspot as it approaches the viewport edges.
- *
- * @param s The full size of the hotspot.
- * @param s.w The full width of the hotspot, in pixels.
- * @param s.h The full height of the hotspot, in pixels.
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_ZOOM = function (panorama, s, maxDistanceInViewportHeights) {
- return function (clipData) {
- if (clipData.x >= 0 && clipData.y >= 0 && (clipData.x + s.w) < panorama.renderer.getViewportWidth ()
- && (clipData.y + s.h) < panorama.renderer.getViewportHeight ()) {
- clipData.w = s.w;
- clipData.h = s.h;
- return true;
- }
-
- var distance = 0;
- if (clipData.x < 0) {
- distance = Math.max (-clipData.x, distance);
- }
- if (clipData.y < 0) {
- distance = Math.max (-clipData.y, distance);
- }
- if (clipData.x + s.w > panorama.renderer.getViewportWidth ()) {
- distance = Math.max (clipData.x + s.w - panorama.renderer.getViewportWidth (), distance);
- }
- if (clipData.y + s.h > panorama.renderer.getViewportHeight ()) {
- distance = Math.max (clipData.y + s.h - panorama.renderer.getViewportHeight (), distance);
- }
-
- distance /= panorama.renderer.getViewportHeight ();
- if (distance > maxDistanceInViewportHeights) {
- return false;
- }
-
- var scale = 1 / (1 + distance);
-
- clipData.w = s.w * scale;
- clipData.h = s.w * scale;
- if (clipData.x < 0) {
- clipData.x = 0;
- }
- if (clipData.y < 0) {
- clipData.y = 0;
- }
- if (clipData.x + clipData.w > panorama.renderer.getViewportWidth ()) {
- clipData.x = panorama.renderer.getViewportWidth () - clipData.w;
- }
- if (clipData.y + clipData.h > panorama.renderer.getViewportHeight ()) {
- clipData.y = panorama.renderer.getViewportHeight () - clipData.h;
- }
-
- return true;
- }
-}
-
-/**
- * Progressively fades the hotspot as it gets closer to the viewport edges.
- *
- * @param {number} borderSizeInPixels the distance from the edge, in pixels,
- * where the hotspot is completely opaque.
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_FADE = function (panorama, borderSizeInPixels) {
- return function (clipData) {
- var distance = Math.min (
- clipData.x,
- clipData.y,
- panorama.renderer.getViewportWidth () - (clipData.x + clipData.w),
- panorama.renderer.getViewportHeight () - (clipData.y + clipData.h));
-
- if (distance <= 0) {
- return false;
- } else if (distance <= borderSizeInPixels) {
- clipData.opacity = (distance / borderSizeInPixels);
- return true;
- } else {
- clipData.opacity = 1.0;
- return true;
- }
- }
-}
-
-bigshot.VRHotspot.prototype = {
-
- /**
- * Layout and resize the hotspot. Called by the panorama.
- */
- layout : function () {},
-
- /**
- * Helper function to rotate a point around an axis.
- *
- * @param {number} ang the angle
- * @param {bigshot.Point3D} vector the vector to rotate around
- * @param {Vector} point the point
- * @type Vector
- * @private
- */
- rotate : function (ang, vector, point) {
- var arad = ang * Math.PI / 180.0;
- var m = Matrix.Rotation(arad, $V([vector.x, vector.y, vector.z])).ensure4x4 ();
- return m.xPoint3Dhom1 (point);
- },
-
- /**
- * Converts the polar coordinates to world coordinates.
- * The distance is assumed to be 1.0.
- *
- * @param yaw the yaw, in degrees
- * @param pitch the pitch, in degrees
- * @type bigshot.Point3D
- */
- toVector : function (yaw, pitch) {
- var point = { x : 0, y : 0, z : -1 };
- point = this.rotate (-pitch, { x : 1, y : 0, z : 0 }, point);
- point = this.rotate (-yaw, { x : 0, y : 1, z : 0 }, point);
- return point;
- },
-
- /**
- * Converts the world-coordinate point p to screen coordinates.
- *
- * @param {bigshot.Point3D} p the world-coordinate point
- * @type point
- */
- toScreen : function (p) {
- var res = this.panorama.renderer.transformToScreen (p)
- return res;
- },
-
- /**
- * Clips the hotspot against the viewport. Both parameters
- * are in/out. Clipping is done by adjusting the values of the
- * parameters.
- *
- * @param clipData Information about the hotspot.
- * @param {number} clipData.x the x-coordinate of the top-left corner of the hotspot, in pixels.
- * @param {number} clipData.y the y-coordinate of the top-left corner of the hotspot, in pixels.
- * @param {number} clipData.w the width of the hotspot, in pixels.
- * @param {number} clipData.h the height of the hotspot, in pixels.
- * @param {number} [clipData.opacity] the opacity of the hotspot, ranging from 0.0 (transparent)
- * to 1.0 (opaque). If set, the opacity of the hotspot element is adjusted.
- * @type boolean
- * @return true if the hotspot is visible, false otherwise
- */
- clip : function (clipData) {
- return this.clippingStrategy (clipData);
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic style.top and style.left
- * values.
- *
- * @augments bigshot.VRHotspot
- * @param {bigshot.VRPanorama} panorama the panorama to attach this hotspot to
- * @param {number} yaw the yaw coordinate of the hotspot
- * @param {number} pitch the pitch coordinate of the hotspot
- * @param {HTMLElement} element the HTML element
- * @param {number} offsetX the offset to add to the screen coordinate corresponding
- * to the hotspot's polar coordinates. Use this to center the hotspot horizontally.
- * @param {number} offsetY the offset to add to the screen coordinate corresponding
- * to the hotspot's polar coordinates. Use this to center the hotspot vertically.
- */
-bigshot.VRPointHotspot = function (panorama, yaw, pitch, element, offsetX, offsetY) {
- bigshot.VRHotspot.call (this, panorama);
- this.element = element;
- this.offsetX = offsetX;
- this.offsetY = offsetY;
- this.point = this.toVector (yaw, pitch);
-}
-
-bigshot.VRPointHotspot.prototype = {
- layout : function () {
- var p = this.toScreen (this.point);
-
- var visible = false;
- if (p != null) {
- var s = this.panorama.browser.getElementSize (this.element);
- p.w = s.w;
- p.h = s.h;
-
- p.x += this.offsetX;
- p.y += this.offsetY;
-
- if (this.clip (p)) {
- this.element.style.top = (p.y) + "px";
- this.element.style.left = (p.x) + "px";
- this.element.style.width = (p.w) + "px";
- this.element.style.height = (p.h) + "px";
- if (p.opacity) {
- this.element.style.opacity = p.opacity;
- }
- this.element.style.visibility = "inherit";
- visible = true;
- }
- }
-
- if (!visible) {
- this.element.style.visibility = "hidden";
- }
- }
-}
-
-bigshot.Object.extend (bigshot.VRPointHotspot, bigshot.VRHotspot);
-bigshot.Object.validate ("bigshot.VRPointHotspot", bigshot.VRHotspot);
-/*
- * Copyright 2010 - 2012 Leo Sutic style.top and style.left
- * values, and resized by setting its style.width and style.height
- * values.
- *
- * @augments bigshot.VRHotspot
- * @param {bigshot.VRPanorama} panorama the panorama to attach this hotspot to
- * @param {number} yaw0 the yaw coordinate of the top-left corner of the hotspot
- * @param {number} pitch0 the pitch coordinate of the top-left corner of the hotspot
- * @param {number} yaw1 the yaw coordinate of the bottom-right corner of the hotspot
- * @param {number} pitch1 the pitch coordinate of the bottom-right corner of the hotspot
- * @param {HTMLElement} element the HTML element
- */
-bigshot.VRRectangleHotspot = function (panorama, yaw0, pitch0, yaw1, pitch1, element) {
- bigshot.VRHotspot.call (this, panorama);
-
- this.element = element;
- this.point0 = this.toVector (yaw0, pitch0);
- this.point1 = this.toVector (yaw1, pitch1);
-}
-
-bigshot.VRRectangleHotspot.prototype = {
- layout : function () {
- var p = this.toScreen (this.point0);
- var p1 = this.toScreen (this.point1);
-
- var visible = false;
- if (p != null && p1 != null) {
- var cd = {
- x : p.x,
- y : p.y,
- opacity : 1.0,
- w : p1.x - p.x,
- h : p1.y - p.y
- };
-
- if (this.clip (cd)) {
- this.element.style.top = (cd.y) + "px";
- this.element.style.left = (cd.x) + "px";
- this.element.style.width = (cd.w) + "px";
- this.element.style.height = (cd.h) + "px";
- this.element.style.visibility = "inherit";
- visible = true;
- }
- }
-
- if (!visible) {
- this.element.style.visibility = "hidden";
- }
- }
-}
-
-bigshot.Object.extend (bigshot.VRRectangleHotspot, bigshot.VRHotspot);
-bigshot.Object.validate ("bigshot.VRRectangleHotspot", bigshot.VRHotspot);
-/*
- * Copyright 2010 - 2012 Leo Sutic ')));break;case"Code":out(tag("code")+esc(node.literal,!1)+tag("/code"));break;case"Document":break;case"Paragraph":if(grandparent=node.parent.parent,null!==grandparent&&"List"===grandparent.type&&grandparent.listTight)break;entering?(cr(),out(tag("p",attrs))):(out(tag("/p")),cr());break;case"BlockQuote":entering?(cr(),out(tag("blockquote",attrs)),cr()):(cr(),out(tag("/blockquote")),cr());break;case"Item":entering?out(tag("li",attrs)):(out(tag("/li")),cr());break;case"List":if(tagname="Bullet"===node.listType?"ul":"ol",entering){var start=node.listStart;null!==start&&1!==start&&attrs.push(["start",start.toString()]),cr(),out(tag(tagname,attrs)),cr()}else cr(),out(tag("/"+tagname)),cr();break;case"Header":tagname="h"+node.level,entering?(cr(),out(tag(tagname,attrs))):(out(tag("/"+tagname)),cr());break;case"CodeBlock":info_words=node.info?node.info.split(/\s+/):[],info_words.length>0&&info_words[0].length>0&&attrs.push(["class","language-"+esc(info_words[0],!0)]),cr(),out(tag("pre")+tag("code",attrs)),out(esc(node.literal,!1)),out(tag("/code")+tag("/pre")),cr();break;case"HtmlBlock":cr(),out(options.safe?"":node.literal),cr();break;case"HorizontalRule":cr(),out(tag("hr",attrs,!0)),cr();break;default:throw"Unknown node type "+node.type}}return options.time&&console.timeEnd("rendering"),buffer};module.exports=HtmlRenderer},{"./common":2}],5:[function(require,module,exports){"use strict";module.exports.Node=require("./node"),module.exports.Parser=require("./blocks"),module.exports.HtmlRenderer=require("./html"),module.exports.XmlRenderer=require("./xml")},{"./blocks":1,"./html":4,"./node":7,"./xml":9}],6:[function(require,module,exports){"use strict";function InlineParser(options){return{subject:"",delimiters:null,pos:0,refmap:{},match:match,peek:peek,spnl:spnl,parseBackticks:parseBackticks,parseBackslash:parseBackslash,parseAutolink:parseAutolink,parseHtmlTag:parseHtmlTag,scanDelims:scanDelims,handleDelim:handleDelim,parseLinkTitle:parseLinkTitle,parseLinkDestination:parseLinkDestination,parseLinkLabel:parseLinkLabel,parseOpenBracket:parseOpenBracket,parseCloseBracket:parseCloseBracket,parseBang:parseBang,parseEntity:parseEntity,parseString:parseString,parseNewline:parseNewline,parseReference:parseReference,parseInline:parseInline,processEmphasis:processEmphasis,removeDelimiter:removeDelimiter,options:options||{},parse:parseInlines}}var Node=require("./node"),common=require("./common"),normalizeReference=require("./normalize-reference"),normalizeURI=common.normalizeURI,unescapeString=common.unescapeString,fromCodePoint=require("./from-code-point.js"),decodeHTML=require("entities").decodeHTML;require("string.prototype.repeat");var C_NEWLINE=10,C_ASTERISK=42,C_UNDERSCORE=95,C_BACKTICK=96,C_OPEN_BRACKET=91,C_CLOSE_BRACKET=93,C_LESSTHAN=60,C_BANG=33,C_BACKSLASH=92,C_AMPERSAND=38,C_OPEN_PAREN=40,C_CLOSE_PAREN=41,C_COLON=58,C_SINGLEQUOTE=39,C_DOUBLEQUOTE=34,ESCAPABLE=common.ESCAPABLE,ESCAPED_CHAR="\\\\"+ESCAPABLE,REG_CHAR="[^\\\\()\\x00-\\x20]",IN_PARENS_NOSP="\\(("+REG_CHAR+"|"+ESCAPED_CHAR+"|\\\\)*\\)",ENTITY=common.ENTITY,reHtmlTag=common.reHtmlTag,rePunctuation=new RegExp(/^[\u2000-\u206F\u2E00-\u2E7F\\'!"#\$%&\(\)\*\+,\-\.\/:;<=>\?@\[\]\^_`\{\|\}~]/),reLinkTitle=new RegExp('^(?:"('+ESCAPED_CHAR+'|[^"\\x00])*"|\'('+ESCAPED_CHAR+"|[^'\\x00])*'|\\(("+ESCAPED_CHAR+"|[^)\\x00])*\\))"),reLinkDestinationBraces=new RegExp("^(?:[<](?:[^<>\\n\\\\\\x00]|"+ESCAPED_CHAR+"|\\\\)*[>])"),reLinkDestination=new RegExp("^(?:"+REG_CHAR+"+|"+ESCAPED_CHAR+"|\\\\|"+IN_PARENS_NOSP+")*"),reEscapable=new RegExp("^"+ESCAPABLE),reEntityHere=new RegExp("^"+ENTITY,"i"),reTicks=/`+/,reTicksHere=/^`+/,reEllipses=/\.\.\./g,reDash=/--+/g,reEmailAutolink=/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/,reAutolink=/^<(?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris.beep|iris.xpc|iris.xpcs|iris.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap.beep|soap.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc.beep|xmlrpc.beeps|xmpp|z39.50r|z39.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr):[^<>\x00-\x20]*>/i,reSpnl=/^ *(?:\n *)?/,reWhitespaceChar=/^\s/,reWhitespace=/\s+/g,reFinalSpace=/ *$/,reInitialSpace=/^ */,reSpaceAtEndOfLine=/^ *(?:\n|$)/,reLinkLabel=new RegExp("^\\[(?:[^\\\\\\[\\]]|"+ESCAPED_CHAR+"|\\\\){0,1000}\\]"),reMain=/^[^\n`\[\]\\!<&*_'"]+/m,text=function(s){var node=new Node("Text");return node._literal=s,node},match=function(re){var m=re.exec(this.subject.slice(this.pos));return null===m?null:(this.pos+=m.index+m[0].length,m[0])},peek=function(){return this.subject.length>this.pos?this.subject.charCodeAt(this.pos):-1},spnl=function(){return this.match(reSpnl),!0},parseBackticks=function(block){var ticks=this.match(reTicksHere);if(null===ticks)return!1;for(var matched,node,afterOpenTicks=this.pos;null!==(matched=this.match(reTicks));)if(matched===ticks)return node=new Node("Code"),node._literal=this.subject.slice(afterOpenTicks,this.pos-ticks.length).trim().replace(reWhitespace," "),block.appendChild(node),!0;return this.pos=afterOpenTicks,block.appendChild(text(ticks)),!0},parseBackslash=function(block){var node,subj=this.subject;return this.pos+=1,this.peek()===C_NEWLINE?(this.pos+=1,node=new Node("Hardbreak"),block.appendChild(node)):reEscapable.test(subj.charAt(this.pos))?(block.appendChild(text(subj.charAt(this.pos))),this.pos+=1):block.appendChild(text("\\")),!0},parseAutolink=function(block){var m,dest,node;return(m=this.match(reEmailAutolink))?(dest=m.slice(1,m.length-1),node=new Node("Link"),node._destination=normalizeURI("mailto:"+dest),node._title="",node.appendChild(text(dest)),block.appendChild(node),!0):(m=this.match(reAutolink))?(dest=m.slice(1,m.length-1),node=new Node("Link"),node._destination=normalizeURI(dest),node._title="",node.appendChild(text(dest)),block.appendChild(node),!0):!1},parseHtmlTag=function(block){var m=this.match(reHtmlTag);if(null===m)return!1;var node=new Node("Html");return node._literal=m,block.appendChild(node),!0},scanDelims=function(cc){var char_before,char_after,cc_after,left_flanking,right_flanking,can_open,can_close,after_is_whitespace,after_is_punctuation,before_is_whitespace,before_is_punctuation,numdelims=0,startpos=this.pos;if(cc===C_SINGLEQUOTE||cc===C_DOUBLEQUOTE)numdelims++,this.pos++;else for(;this.peek()===cc;)numdelims++,this.pos++;return 0===numdelims?null:(char_before=0===startpos?"\n":this.subject.charAt(startpos-1),cc_after=this.peek(),char_after=-1===cc_after?"\n":fromCodePoint(cc_after),after_is_whitespace=reWhitespaceChar.test(char_after),after_is_punctuation=rePunctuation.test(char_after),before_is_whitespace=reWhitespaceChar.test(char_before),before_is_punctuation=rePunctuation.test(char_before),left_flanking=!(after_is_whitespace||after_is_punctuation&&!before_is_whitespace&&!before_is_punctuation),right_flanking=!(before_is_whitespace||before_is_punctuation&&!after_is_whitespace&&!after_is_punctuation),cc===C_UNDERSCORE?(can_open=left_flanking&&(!right_flanking||before_is_punctuation),can_close=right_flanking&&(!left_flanking||after_is_punctuation)):cc===C_SINGLEQUOTE||cc===C_DOUBLEQUOTE?(can_open=left_flanking&&!right_flanking,can_close=right_flanking):(can_open=left_flanking,can_close=right_flanking),this.pos=startpos,{numdelims:numdelims,can_open:can_open,can_close:can_close})},handleDelim=function(cc,block){var res=this.scanDelims(cc);if(!res)return!1;var contents,numdelims=res.numdelims,startpos=this.pos;this.pos+=numdelims,contents=cc===C_SINGLEQUOTE?"’":cc===C_DOUBLEQUOTE?"“":this.subject.slice(startpos,this.pos);var node=text(contents);return block.appendChild(node),this.delimiters={cc:cc,numdelims:numdelims,node:node,previous:this.delimiters,next:null,can_open:res.can_open,can_close:res.can_close,active:!0},null!==this.delimiters.previous&&(this.delimiters.previous.next=this.delimiters),!0},removeDelimiter=function(delim){null!==delim.previous&&(delim.previous.next=delim.next),null===delim.next?this.delimiters=delim.previous:delim.next.previous=delim.previous},removeDelimitersBetween=function(bottom,top){bottom.next!==top&&(bottom.next=top,top.previous=bottom)},processEmphasis=function(stack_bottom){var opener,closer,old_closer,opener_inl,closer_inl,tempstack,use_delims,tmp,next,opener_found,openers_bottom=[];for(openers_bottom[C_UNDERSCORE]=stack_bottom,openers_bottom[C_ASTERISK]=stack_bottom,openers_bottom[C_SINGLEQUOTE]=stack_bottom,openers_bottom[C_DOUBLEQUOTE]=stack_bottom,closer=this.delimiters;null!==closer&&closer.previous!==stack_bottom;)closer=closer.previous;for(;null!==closer;){var closercc=closer.cc;if(!closer.can_close||closercc!==C_UNDERSCORE&&closercc!==C_ASTERISK&&closercc!==C_SINGLEQUOTE&&closercc!==C_DOUBLEQUOTE)closer=closer.next;else{for(opener=closer.previous,opener_found=!1;null!==opener&&opener!==stack_bottom&&opener!==openers_bottom[closercc];){if(opener.cc===closer.cc&&opener.can_open){opener_found=!0;break}opener=opener.previous}if(old_closer=closer,closercc===C_ASTERISK||closercc===C_UNDERSCORE)if(opener_found){use_delims=3>closer.numdelims||3>opener.numdelims?opener.numdelims>=closer.numdelims?closer.numdelims:opener.numdelims:closer.numdelims%2===0?2:1,opener_inl=opener.node,closer_inl=closer.node,opener.numdelims-=use_delims,closer.numdelims-=use_delims,opener_inl._literal=opener_inl._literal.slice(0,opener_inl._literal.length-use_delims),closer_inl._literal=closer_inl._literal.slice(0,closer_inl._literal.length-use_delims);var emph=new Node(1===use_delims?"Emph":"Strong");for(tmp=opener_inl._next;tmp&&tmp!==closer_inl;)next=tmp._next,tmp.unlink(),emph.appendChild(tmp),tmp=next;opener_inl.insertAfter(emph),removeDelimitersBetween(opener,closer),0===opener.numdelims&&(opener_inl.unlink(),this.removeDelimiter(opener)),0===closer.numdelims&&(closer_inl.unlink(),tempstack=closer.next,this.removeDelimiter(closer),closer=tempstack)}else closer=closer.next;else closercc===C_SINGLEQUOTE?(closer.node._literal="’",opener_found&&(opener.node._literal="‘"),closer=closer.next):closercc===C_DOUBLEQUOTE&&(closer.node._literal="”",opener_found&&(opener.node.literal="“"),closer=closer.next);opener_found||(openers_bottom[closercc]=old_closer.previous,old_closer.can_open||this.removeDelimiter(old_closer))}}for(;null!==this.delimiters&&this.delimiters!==stack_bottom;)this.removeDelimiter(this.delimiters)},parseLinkTitle=function(){var title=this.match(reLinkTitle);return null===title?null:unescapeString(title.substr(1,title.length-2))},parseLinkDestination=function(){var res=this.match(reLinkDestinationBraces);return null===res?(res=this.match(reLinkDestination),null===res?null:normalizeURI(unescapeString(res))):normalizeURI(unescapeString(res.substr(1,res.length-2)))},parseLinkLabel=function(){var m=this.match(reLinkLabel);
+return null===m||m.length>1001?0:m.length},parseOpenBracket=function(block){var startpos=this.pos;this.pos+=1;var node=text("[");return block.appendChild(node),this.delimiters={cc:C_OPEN_BRACKET,numdelims:1,node:node,previous:this.delimiters,next:null,can_open:!0,can_close:!1,index:startpos,active:!0},null!==this.delimiters.previous&&(this.delimiters.previous.next=this.delimiters),!0},parseBang=function(block){var startpos=this.pos;if(this.pos+=1,this.peek()===C_OPEN_BRACKET){this.pos+=1;var node=text("![");block.appendChild(node),this.delimiters={cc:C_BANG,numdelims:1,node:node,previous:this.delimiters,next:null,can_open:!0,can_close:!1,index:startpos+1,active:!0},null!==this.delimiters.previous&&(this.delimiters.previous.next=this.delimiters)}else block.appendChild(text("!"));return!0},parseCloseBracket=function(block){var startpos,is_image,dest,title,reflabel,opener,matched=!1;for(this.pos+=1,startpos=this.pos,opener=this.delimiters;null!==opener&&opener.cc!==C_OPEN_BRACKET&&opener.cc!==C_BANG;)opener=opener.previous;if(null===opener)return block.appendChild(text("]")),!0;if(!opener.active)return block.appendChild(text("]")),this.removeDelimiter(opener),!0;if(is_image=opener.cc===C_BANG,this.peek()===C_OPEN_PAREN)this.pos++,this.spnl()&&null!==(dest=this.parseLinkDestination())&&this.spnl()&&this.spnl()&&this.peek()===C_CLOSE_PAREN&&(this.pos+=1,matched=!0);else{var savepos=this.pos;this.spnl();var beforelabel=this.pos,n=this.parseLinkLabel();reflabel=0===n||2===n?this.subject.slice(opener.index,startpos):this.subject.slice(beforelabel,beforelabel+n),0===n&&(this.pos=savepos);var link=this.refmap[normalizeReference(reflabel)];link&&(dest=link.destination,title=link.title,matched=!0)}if(matched){var node=new Node(is_image?"Image":"Link");node._destination=dest,node._title=title||"";var tmp,next;for(tmp=opener.node._next;tmp;)next=tmp._next,tmp.unlink(),node.appendChild(tmp),tmp=next;if(block.appendChild(node),this.processEmphasis(opener.previous),opener.node.unlink(),!is_image)for(opener=this.delimiters;null!==opener;)opener.cc===C_OPEN_BRACKET&&(opener.active=!1),opener=opener.previous;return!0}return this.removeDelimiter(opener),this.pos=startpos,block.appendChild(text("]")),!0},parseEntity=function(block){var m;return(m=this.match(reEntityHere))?(block.appendChild(text(decodeHTML(m))),!0):!1},parseString=function(block){var m;return(m=this.match(reMain))?(block.appendChild(text(this.options.smart?m.replace(reEllipses,"…").replace(reDash,function(chars){var enCount=0,emCount=0;return chars.length%3===0?emCount=chars.length/3:chars.length%2===0?enCount=chars.length/2:chars.length%3===2?(enCount=1,emCount=(chars.length-2)/3):(enCount=2,emCount=(chars.length-4)/3),"—".repeat(emCount)+"–".repeat(enCount)}):m)),!0):!1},parseNewline=function(block){this.pos+=1;var lastc=block._lastChild;if(lastc&&"Text"===lastc.type&&" "===lastc._literal[lastc._literal.length-1]){var hardbreak=" "===lastc._literal[lastc._literal.length-2];lastc._literal=lastc._literal.replace(reFinalSpace,""),block.appendChild(new Node(hardbreak?"Hardbreak":"Softbreak"))}else block.appendChild(new Node("Softbreak"));return this.match(reInitialSpace),!0},parseReference=function(s,refmap){this.subject=s,this.pos=0;var rawlabel,dest,title,matchChars,startpos=this.pos;if(matchChars=this.parseLinkLabel(),0===matchChars)return 0;if(rawlabel=this.subject.substr(0,matchChars),this.peek()!==C_COLON)return this.pos=startpos,0;if(this.pos++,this.spnl(),dest=this.parseLinkDestination(),null===dest||0===dest.length)return this.pos=startpos,0;var beforetitle=this.pos;this.spnl(),title=this.parseLinkTitle(),null===title&&(title="",this.pos=beforetitle);var atLineEnd=!0;if(null===this.match(reSpaceAtEndOfLine)&&(""===title?atLineEnd=!1:(title="",this.pos=beforetitle,atLineEnd=null!==this.match(reSpaceAtEndOfLine))),!atLineEnd)return this.pos=startpos,0;var normlabel=normalizeReference(rawlabel);return""===normlabel?(this.pos=startpos,0):(refmap[normlabel]||(refmap[normlabel]={destination:dest,title:title}),this.pos-startpos)},parseInline=function(block){var res=!1,c=this.peek();if(-1===c)return!1;switch(c){case C_NEWLINE:res=this.parseNewline(block);break;case C_BACKSLASH:res=this.parseBackslash(block);break;case C_BACKTICK:res=this.parseBackticks(block);break;case C_ASTERISK:case C_UNDERSCORE:res=this.handleDelim(c,block);break;case C_SINGLEQUOTE:case C_DOUBLEQUOTE:res=this.options.smart&&this.handleDelim(c,block);break;case C_OPEN_BRACKET:res=this.parseOpenBracket(block);break;case C_BANG:res=this.parseBang(block);break;case C_CLOSE_BRACKET:res=this.parseCloseBracket(block);break;case C_LESSTHAN:res=this.parseAutolink(block)||this.parseHtmlTag(block);break;case C_AMPERSAND:res=this.parseEntity(block);break;default:res=this.parseString(block)}return res||(this.pos+=1,block.appendChild(text(fromCodePoint(c)))),!0},parseInlines=function(block){for(this.subject=block._string_content.trim(),this.pos=0,this.delimiters=null;this.parseInline(block););block._string_content=null,this.processEmphasis(null)};module.exports=InlineParser},{"./common":2,"./from-code-point.js":3,"./node":7,"./normalize-reference":8,entities:10,"string.prototype.repeat":20}],7:[function(require,module,exports){"use strict";function isContainer(node){switch(node._type){case"Document":case"BlockQuote":case"List":case"Item":case"Paragraph":case"Header":case"Emph":case"Strong":case"Link":case"Image":return!0;default:return!1}}var resumeAt=function(node,entering){this.current=node,this.entering=entering===!0},next=function(){var cur=this.current,entering=this.entering;if(null===cur)return null;var container=isContainer(cur);return entering&&container?cur._firstChild?(this.current=cur._firstChild,this.entering=!0):this.entering=!1:cur===this.root?this.current=null:null===cur._next?(this.current=cur._parent,this.entering=!1):(this.current=cur._next,this.entering=!0),{entering:entering,node:cur}},NodeWalker=function(root){return{current:root,root:root,entering:!0,next:next,resumeAt:resumeAt}},Node=function(nodeType,sourcepos){this._type=nodeType,this._parent=null,this._firstChild=null,this._lastChild=null,this._prev=null,this._next=null,this._sourcepos=sourcepos,this._lastLineBlank=!1,this._open=!0,this._string_content=null,this._literal=null,this._listData=null,this._info=null,this._destination=null,this._title=null,this._isFenced=!1,this._fenceChar=null,this._fenceLength=0,this._fenceOffset=null,this._level=null},proto=Node.prototype;Object.defineProperty(proto,"isContainer",{get:function(){return isContainer(this)}}),Object.defineProperty(proto,"type",{get:function(){return this._type}}),Object.defineProperty(proto,"firstChild",{get:function(){return this._firstChild}}),Object.defineProperty(proto,"lastChild",{get:function(){return this._lastChild}}),Object.defineProperty(proto,"next",{get:function(){return this._next}}),Object.defineProperty(proto,"prev",{get:function(){return this._prev}}),Object.defineProperty(proto,"parent",{get:function(){return this._parent}}),Object.defineProperty(proto,"sourcepos",{get:function(){return this._sourcepos}}),Object.defineProperty(proto,"literal",{get:function(){return this._literal},set:function(s){this._literal=s}}),Object.defineProperty(proto,"destination",{get:function(){return this._destination},set:function(s){this._destination=s}}),Object.defineProperty(proto,"title",{get:function(){return this._title},set:function(s){this._title=s}}),Object.defineProperty(proto,"info",{get:function(){return this._info},set:function(s){this._info=s}}),Object.defineProperty(proto,"level",{get:function(){return this._level},set:function(s){this._level=s}}),Object.defineProperty(proto,"listType",{get:function(){return this._listData.type},set:function(t){this._listData.type=t}}),Object.defineProperty(proto,"listTight",{get:function(){return this._listData.tight},set:function(t){this._listData.tight=t}}),Object.defineProperty(proto,"listStart",{get:function(){return this._listData.start},set:function(n){this._listData.start=n}}),Object.defineProperty(proto,"listDelimiter",{get:function(){return this._listData.delimiter},set:function(delim){this._listData.delimiter=delim}}),Node.prototype.appendChild=function(child){child.unlink(),child._parent=this,this._lastChild?(this._lastChild._next=child,child._prev=this._lastChild,this._lastChild=child):(this._firstChild=child,this._lastChild=child)},Node.prototype.prependChild=function(child){child.unlink(),child._parent=this,this._firstChild?(this._firstChild._prev=child,child._next=this._firstChild,this._firstChild=child):(this._firstChild=child,this._lastChild=child)},Node.prototype.unlink=function(){this._prev?this._prev._next=this._next:this._parent&&(this._parent._firstChild=this._next),this._next?this._next._prev=this._prev:this._parent&&(this._parent._lastChild=this._prev),this._parent=null,this._next=null,this._prev=null},Node.prototype.insertAfter=function(sibling){sibling.unlink(),sibling._next=this._next,sibling._next&&(sibling._next._prev=sibling),sibling._prev=this,this._next=sibling,sibling._parent=this._parent,sibling._next||(sibling._parent._lastChild=sibling)},Node.prototype.insertBefore=function(sibling){sibling.unlink(),sibling._prev=this._prev,sibling._prev&&(sibling._prev._next=sibling),sibling._next=this,this._prev=sibling,sibling._parent=this._parent,sibling._prev||(sibling._parent._firstChild=sibling)},Node.prototype.walker=function(){var walker=new NodeWalker(this);return walker},module.exports=Node},{}],8:[function(require,module,exports){"use strict";var regex=/[ \t\r\n]+|[A-Z\xB5\xC0-\xD6\xD8-\xDF\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u0149\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u017F\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C5\u01C7\u01C8\u01CA\u01CB\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F0-\u01F2\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0345\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03AB\u03B0\u03C2\u03CF-\u03D1\u03D5\u03D6\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F0\u03F1\u03F4\u03F5\u03F7\u03F9\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u0587\u10A0-\u10C5\u10C7\u10CD\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E96-\u1E9B\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F50\u1F52\u1F54\u1F56\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1F80-\u1FAF\u1FB2-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD2\u1FD3\u1FD6-\u1FDB\u1FE2-\u1FE4\u1FE6-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A\u212B\u2132\u2160-\u216F\u2183\u24B6-\u24CF\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AD\uA7B0\uA7B1\uFB00-\uFB06\uFB13-\uFB17\uFF21-\uFF3A]|\uD801[\uDC00-\uDC27]|\uD806[\uDCA0-\uDCBF]/g,map={A:"a",B:"b",C:"c",D:"d",E:"e",F:"f",G:"g",H:"h",I:"i",J:"j",K:"k",L:"l",M:"m",N:"n",O:"o",P:"p",Q:"q",R:"r",S:"s",T:"t",U:"u",V:"v",W:"w",X:"x",Y:"y",Z:"z","µ":"μ","À":"à","Á":"á","Â":"â","Ã":"ã","Ä":"ä","Å":"å","Æ":"æ","Ç":"ç","È":"è","É":"é","Ê":"ê","Ë":"ë","Ì":"ì","Í":"í","Î":"î","Ï":"ï","Ð":"ð","Ñ":"ñ","Ò":"ò","Ó":"ó","Ô":"ô","Õ":"õ","Ö":"ö","Ø":"ø","Ù":"ù","Ú":"ú","Û":"û","Ü":"ü","Ý":"ý","Þ":"þ","Ā":"ā","Ă":"ă","Ą":"ą","Ć":"ć","Ĉ":"ĉ","Ċ":"ċ","Č":"č","Ď":"ď","Đ":"đ","Ē":"ē","Ĕ":"ĕ","Ė":"ė","Ę":"ę","Ě":"ě","Ĝ":"ĝ","Ğ":"ğ","Ġ":"ġ","Ģ":"ģ","Ĥ":"ĥ","Ħ":"ħ","Ĩ":"ĩ","Ī":"ī","Ĭ":"ĭ","Į":"į","IJ":"ij","Ĵ":"ĵ","Ķ":"ķ","Ĺ":"ĺ","Ļ":"ļ","Ľ":"ľ","Ŀ":"ŀ","Ł":"ł","Ń":"ń","Ņ":"ņ","Ň":"ň","Ŋ":"ŋ","Ō":"ō","Ŏ":"ŏ","Ő":"ő","Œ":"œ","Ŕ":"ŕ","Ŗ":"ŗ","Ř":"ř","Ś":"ś","Ŝ":"ŝ","Ş":"ş","Š":"š","Ţ":"ţ","Ť":"ť","Ŧ":"ŧ","Ũ":"ũ","Ū":"ū","Ŭ":"ŭ","Ů":"ů","Ű":"ű","Ų":"ų","Ŵ":"ŵ","Ŷ":"ŷ","Ÿ":"ÿ","Ź":"ź","Ż":"ż","Ž":"ž","ſ":"s","Ɓ":"ɓ","Ƃ":"ƃ","Ƅ":"ƅ","Ɔ":"ɔ","Ƈ":"ƈ","Ɖ":"ɖ","Ɗ":"ɗ","Ƌ":"ƌ","Ǝ":"ǝ","Ə":"ə","Ɛ":"ɛ","Ƒ":"ƒ","Ɠ":"ɠ","Ɣ":"ɣ","Ɩ":"ɩ","Ɨ":"ɨ","Ƙ":"ƙ","Ɯ":"ɯ","Ɲ":"ɲ","Ɵ":"ɵ","Ơ":"ơ","Ƣ":"ƣ","Ƥ":"ƥ","Ʀ":"ʀ","Ƨ":"ƨ","Ʃ":"ʃ","Ƭ":"ƭ","Ʈ":"ʈ","Ư":"ư","Ʊ":"ʊ","Ʋ":"ʋ","Ƴ":"ƴ","Ƶ":"ƶ","Ʒ":"ʒ","Ƹ":"ƹ","Ƽ":"ƽ","DŽ":"dž","Dž":"dž","LJ":"lj","Lj":"lj","NJ":"nj","Nj":"nj","Ǎ":"ǎ","Ǐ":"ǐ","Ǒ":"ǒ","Ǔ":"ǔ","Ǖ":"ǖ","Ǘ":"ǘ","Ǚ":"ǚ","Ǜ":"ǜ","Ǟ":"ǟ","Ǡ":"ǡ","Ǣ":"ǣ","Ǥ":"ǥ","Ǧ":"ǧ","Ǩ":"ǩ","Ǫ":"ǫ","Ǭ":"ǭ","Ǯ":"ǯ","DZ":"dz","Dz":"dz","Ǵ":"ǵ","Ƕ":"ƕ","Ƿ":"ƿ","Ǹ":"ǹ","Ǻ":"ǻ","Ǽ":"ǽ","Ǿ":"ǿ","Ȁ":"ȁ","Ȃ":"ȃ","Ȅ":"ȅ","Ȇ":"ȇ","Ȉ":"ȉ","Ȋ":"ȋ","Ȍ":"ȍ","Ȏ":"ȏ","Ȑ":"ȑ","Ȓ":"ȓ","Ȕ":"ȕ","Ȗ":"ȗ","Ș":"ș","Ț":"ț","Ȝ":"ȝ","Ȟ":"ȟ","Ƞ":"ƞ","Ȣ":"ȣ","Ȥ":"ȥ","Ȧ":"ȧ","Ȩ":"ȩ","Ȫ":"ȫ","Ȭ":"ȭ","Ȯ":"ȯ","Ȱ":"ȱ","Ȳ":"ȳ","Ⱥ":"ⱥ","Ȼ":"ȼ","Ƚ":"ƚ","Ⱦ":"ⱦ","Ɂ":"ɂ","Ƀ":"ƀ","Ʉ":"ʉ","Ʌ":"ʌ","Ɇ":"ɇ","Ɉ":"ɉ","Ɋ":"ɋ","Ɍ":"ɍ","Ɏ":"ɏ","ͅ":"ι","Ͱ":"ͱ","Ͳ":"ͳ","Ͷ":"ͷ","Ϳ":"ϳ","Ά":"ά","Έ":"έ","Ή":"ή","Ί":"ί","Ό":"ό","Ύ":"ύ","Ώ":"ώ","Α":"α","Β":"β","Γ":"γ","Δ":"δ","Ε":"ε","Ζ":"ζ","Η":"η","Θ":"θ","Ι":"ι","Κ":"κ","Λ":"λ","Μ":"μ","Ν":"ν","Ξ":"ξ","Ο":"ο","Π":"π","Ρ":"ρ","Σ":"σ","Τ":"τ","Υ":"υ","Φ":"φ","Χ":"χ","Ψ":"ψ","Ω":"ω","Ϊ":"ϊ","Ϋ":"ϋ","ς":"σ","Ϗ":"ϗ","ϐ":"β","ϑ":"θ","ϕ":"φ","ϖ":"π","Ϙ":"ϙ","Ϛ":"ϛ","Ϝ":"ϝ","Ϟ":"ϟ","Ϡ":"ϡ","Ϣ":"ϣ","Ϥ":"ϥ","Ϧ":"ϧ","Ϩ":"ϩ","Ϫ":"ϫ","Ϭ":"ϭ","Ϯ":"ϯ","ϰ":"κ","ϱ":"ρ","ϴ":"θ","ϵ":"ε","Ϸ":"ϸ","Ϲ":"ϲ","Ϻ":"ϻ","Ͻ":"ͻ","Ͼ":"ͼ","Ͽ":"ͽ","Ѐ":"ѐ","Ё":"ё","Ђ":"ђ","Ѓ":"ѓ","Є":"є","Ѕ":"ѕ","І":"і","Ї":"ї","Ј":"ј","Љ":"љ","Њ":"њ","Ћ":"ћ","Ќ":"ќ","Ѝ":"ѝ","Ў":"ў","Џ":"џ","А":"а","Б":"б","В":"в","Г":"г","Д":"д","Е":"е","Ж":"ж","З":"з","И":"и","Й":"й","К":"к","Л":"л","М":"м","Н":"н","О":"о","П":"п","Р":"р","С":"с","Т":"т","У":"у","Ф":"ф","Х":"х","Ц":"ц","Ч":"ч","Ш":"ш","Щ":"щ","Ъ":"ъ","Ы":"ы","Ь":"ь","Э":"э","Ю":"ю","Я":"я","Ѡ":"ѡ","Ѣ":"ѣ","Ѥ":"ѥ","Ѧ":"ѧ","Ѩ":"ѩ","Ѫ":"ѫ","Ѭ":"ѭ","Ѯ":"ѯ","Ѱ":"ѱ","Ѳ":"ѳ","Ѵ":"ѵ","Ѷ":"ѷ","Ѹ":"ѹ","Ѻ":"ѻ","Ѽ":"ѽ","Ѿ":"ѿ","Ҁ":"ҁ","Ҋ":"ҋ","Ҍ":"ҍ","Ҏ":"ҏ","Ґ":"ґ","Ғ":"ғ","Ҕ":"ҕ","Җ":"җ","Ҙ":"ҙ","Қ":"қ","Ҝ":"ҝ","Ҟ":"ҟ","Ҡ":"ҡ","Ң":"ң","Ҥ":"ҥ","Ҧ":"ҧ","Ҩ":"ҩ","Ҫ":"ҫ","Ҭ":"ҭ","Ү":"ү","Ұ":"ұ","Ҳ":"ҳ","Ҵ":"ҵ","Ҷ":"ҷ","Ҹ":"ҹ","Һ":"һ","Ҽ":"ҽ","Ҿ":"ҿ","Ӏ":"ӏ","Ӂ":"ӂ","Ӄ":"ӄ","Ӆ":"ӆ","Ӈ":"ӈ","Ӊ":"ӊ","Ӌ":"ӌ","Ӎ":"ӎ","Ӑ":"ӑ","Ӓ":"ӓ","Ӕ":"ӕ","Ӗ":"ӗ","Ә":"ә","Ӛ":"ӛ","Ӝ":"ӝ","Ӟ":"ӟ","Ӡ":"ӡ","Ӣ":"ӣ","Ӥ":"ӥ","Ӧ":"ӧ","Ө":"ө","Ӫ":"ӫ","Ӭ":"ӭ","Ӯ":"ӯ","Ӱ":"ӱ","Ӳ":"ӳ","Ӵ":"ӵ","Ӷ":"ӷ","Ӹ":"ӹ","Ӻ":"ӻ","Ӽ":"ӽ","Ӿ":"ӿ","Ԁ":"ԁ","Ԃ":"ԃ","Ԅ":"ԅ","Ԇ":"ԇ","Ԉ":"ԉ","Ԋ":"ԋ","Ԍ":"ԍ","Ԏ":"ԏ","Ԑ":"ԑ","Ԓ":"ԓ","Ԕ":"ԕ","Ԗ":"ԗ","Ԙ":"ԙ","Ԛ":"ԛ","Ԝ":"ԝ","Ԟ":"ԟ","Ԡ":"ԡ","Ԣ":"ԣ","Ԥ":"ԥ","Ԧ":"ԧ","Ԩ":"ԩ","Ԫ":"ԫ","Ԭ":"ԭ","Ԯ":"ԯ","Ա":"ա","Բ":"բ","Գ":"գ","Դ":"դ","Ե":"ե","Զ":"զ","Է":"է","Ը":"ը","Թ":"թ","Ժ":"ժ","Ի":"ի","Լ":"լ","Խ":"խ","Ծ":"ծ","Կ":"կ","Հ":"հ","Ձ":"ձ","Ղ":"ղ","Ճ":"ճ","Մ":"մ","Յ":"յ","Ն":"ն","Շ":"շ","Ո":"ո","Չ":"չ","Պ":"պ","Ջ":"ջ","Ռ":"ռ","Ս":"ս","Վ":"վ","Տ":"տ","Ր":"ր","Ց":"ց","Ւ":"ւ","Փ":"փ","Ք":"ք","Օ":"օ","Ֆ":"ֆ","Ⴀ":"ⴀ","Ⴁ":"ⴁ","Ⴂ":"ⴂ","Ⴃ":"ⴃ","Ⴄ":"ⴄ","Ⴅ":"ⴅ","Ⴆ":"ⴆ","Ⴇ":"ⴇ","Ⴈ":"ⴈ","Ⴉ":"ⴉ","Ⴊ":"ⴊ","Ⴋ":"ⴋ","Ⴌ":"ⴌ","Ⴍ":"ⴍ","Ⴎ":"ⴎ","Ⴏ":"ⴏ","Ⴐ":"ⴐ","Ⴑ":"ⴑ","Ⴒ":"ⴒ","Ⴓ":"ⴓ","Ⴔ":"ⴔ","Ⴕ":"ⴕ","Ⴖ":"ⴖ","Ⴗ":"ⴗ","Ⴘ":"ⴘ","Ⴙ":"ⴙ","Ⴚ":"ⴚ","Ⴛ":"ⴛ","Ⴜ":"ⴜ","Ⴝ":"ⴝ","Ⴞ":"ⴞ","Ⴟ":"ⴟ","Ⴠ":"ⴠ","Ⴡ":"ⴡ","Ⴢ":"ⴢ","Ⴣ":"ⴣ","Ⴤ":"ⴤ","Ⴥ":"ⴥ","Ⴧ":"ⴧ","Ⴭ":"ⴭ","Ḁ":"ḁ","Ḃ":"ḃ","Ḅ":"ḅ","Ḇ":"ḇ","Ḉ":"ḉ","Ḋ":"ḋ","Ḍ":"ḍ","Ḏ":"ḏ","Ḑ":"ḑ","Ḓ":"ḓ","Ḕ":"ḕ","Ḗ":"ḗ","Ḙ":"ḙ","Ḛ":"ḛ","Ḝ":"ḝ","Ḟ":"ḟ","Ḡ":"ḡ","Ḣ":"ḣ","Ḥ":"ḥ","Ḧ":"ḧ","Ḩ":"ḩ","Ḫ":"ḫ","Ḭ":"ḭ","Ḯ":"ḯ","Ḱ":"ḱ","Ḳ":"ḳ","Ḵ":"ḵ","Ḷ":"ḷ","Ḹ":"ḹ","Ḻ":"ḻ","Ḽ":"ḽ","Ḿ":"ḿ","Ṁ":"ṁ","Ṃ":"ṃ","Ṅ":"ṅ","Ṇ":"ṇ","Ṉ":"ṉ","Ṋ":"ṋ","Ṍ":"ṍ","Ṏ":"ṏ","Ṑ":"ṑ","Ṓ":"ṓ","Ṕ":"ṕ","Ṗ":"ṗ","Ṙ":"ṙ","Ṛ":"ṛ","Ṝ":"ṝ","Ṟ":"ṟ","Ṡ":"ṡ","Ṣ":"ṣ","Ṥ":"ṥ","Ṧ":"ṧ","Ṩ":"ṩ","Ṫ":"ṫ","Ṭ":"ṭ","Ṯ":"ṯ","Ṱ":"ṱ","Ṳ":"ṳ","Ṵ":"ṵ","Ṷ":"ṷ","Ṹ":"ṹ","Ṻ":"ṻ","Ṽ":"ṽ","Ṿ":"ṿ","Ẁ":"ẁ","Ẃ":"ẃ","Ẅ":"ẅ","Ẇ":"ẇ","Ẉ":"ẉ","Ẋ":"ẋ","Ẍ":"ẍ","Ẏ":"ẏ","Ẑ":"ẑ","Ẓ":"ẓ","Ẕ":"ẕ","ẛ":"ṡ","Ạ":"ạ","Ả":"ả","Ấ":"ấ","Ầ":"ầ","Ẩ":"ẩ","Ẫ":"ẫ","Ậ":"ậ","Ắ":"ắ","Ằ":"ằ","Ẳ":"ẳ","Ẵ":"ẵ","Ặ":"ặ","Ẹ":"ẹ","Ẻ":"ẻ","Ẽ":"ẽ","Ế":"ế","Ề":"ề","Ể":"ể","Ễ":"ễ","Ệ":"ệ","Ỉ":"ỉ","Ị":"ị","Ọ":"ọ","Ỏ":"ỏ","Ố":"ố","Ồ":"ồ","Ổ":"ổ","Ỗ":"ỗ","Ộ":"ộ","Ớ":"ớ","Ờ":"ờ","Ở":"ở","Ỡ":"ỡ","Ợ":"ợ","Ụ":"ụ","Ủ":"ủ","Ứ":"ứ","Ừ":"ừ","Ử":"ử","Ữ":"ữ","Ự":"ự","Ỳ":"ỳ","Ỵ":"ỵ","Ỷ":"ỷ","Ỹ":"ỹ","Ỻ":"ỻ","Ỽ":"ỽ","Ỿ":"ỿ","Ἀ":"ἀ","Ἁ":"ἁ","Ἂ":"ἂ","Ἃ":"ἃ","Ἄ":"ἄ","Ἅ":"ἅ","Ἆ":"ἆ","Ἇ":"ἇ","Ἐ":"ἐ","Ἑ":"ἑ","Ἒ":"ἒ","Ἓ":"ἓ","Ἔ":"ἔ","Ἕ":"ἕ","Ἠ":"ἠ","Ἡ":"ἡ","Ἢ":"ἢ","Ἣ":"ἣ","Ἤ":"ἤ","Ἥ":"ἥ","Ἦ":"ἦ","Ἧ":"ἧ","Ἰ":"ἰ","Ἱ":"ἱ","Ἲ":"ἲ","Ἳ":"ἳ","Ἴ":"ἴ","Ἵ":"ἵ","Ἶ":"ἶ","Ἷ":"ἷ","Ὀ":"ὀ","Ὁ":"ὁ","Ὂ":"ὂ","Ὃ":"ὃ","Ὄ":"ὄ","Ὅ":"ὅ","Ὑ":"ὑ","Ὓ":"ὓ","Ὕ":"ὕ","Ὗ":"ὗ","Ὠ":"ὠ","Ὡ":"ὡ","Ὢ":"ὢ","Ὣ":"ὣ","Ὤ":"ὤ","Ὥ":"ὥ","Ὦ":"ὦ","Ὧ":"ὧ","Ᾰ":"ᾰ","Ᾱ":"ᾱ","Ὰ":"ὰ","Ά":"ά","ι":"ι","Ὲ":"ὲ","Έ":"έ","Ὴ":"ὴ","Ή":"ή","Ῐ":"ῐ","Ῑ":"ῑ","Ὶ":"ὶ","Ί":"ί","Ῠ":"ῠ","Ῡ":"ῡ","Ὺ":"ὺ","Ύ":"ύ","Ῥ":"ῥ","Ὸ":"ὸ","Ό":"ό","Ὼ":"ὼ","Ώ":"ώ","Ω":"ω","K":"k","Å":"å","Ⅎ":"ⅎ","Ⅰ":"ⅰ","Ⅱ":"ⅱ","Ⅲ":"ⅲ","Ⅳ":"ⅳ","Ⅴ":"ⅴ","Ⅵ":"ⅵ","Ⅶ":"ⅶ","Ⅷ":"ⅷ","Ⅸ":"ⅸ","Ⅹ":"ⅹ","Ⅺ":"ⅺ","Ⅻ":"ⅻ","Ⅼ":"ⅼ","Ⅽ":"ⅽ","Ⅾ":"ⅾ","Ⅿ":"ⅿ","Ↄ":"ↄ","Ⓐ":"ⓐ","Ⓑ":"ⓑ","Ⓒ":"ⓒ","Ⓓ":"ⓓ","Ⓔ":"ⓔ","Ⓕ":"ⓕ","Ⓖ":"ⓖ","Ⓗ":"ⓗ","Ⓘ":"ⓘ","Ⓙ":"ⓙ","Ⓚ":"ⓚ","Ⓛ":"ⓛ","Ⓜ":"ⓜ","Ⓝ":"ⓝ","Ⓞ":"ⓞ","Ⓟ":"ⓟ","Ⓠ":"ⓠ","Ⓡ":"ⓡ","Ⓢ":"ⓢ","Ⓣ":"ⓣ","Ⓤ":"ⓤ","Ⓥ":"ⓥ","Ⓦ":"ⓦ","Ⓧ":"ⓧ","Ⓨ":"ⓨ","Ⓩ":"ⓩ","Ⰰ":"ⰰ","Ⰱ":"ⰱ","Ⰲ":"ⰲ","Ⰳ":"ⰳ","Ⰴ":"ⰴ","Ⰵ":"ⰵ","Ⰶ":"ⰶ","Ⰷ":"ⰷ","Ⰸ":"ⰸ","Ⰹ":"ⰹ","Ⰺ":"ⰺ","Ⰻ":"ⰻ","Ⰼ":"ⰼ","Ⰽ":"ⰽ","Ⰾ":"ⰾ","Ⰿ":"ⰿ","Ⱀ":"ⱀ","Ⱁ":"ⱁ","Ⱂ":"ⱂ","Ⱃ":"ⱃ","Ⱄ":"ⱄ","Ⱅ":"ⱅ","Ⱆ":"ⱆ","Ⱇ":"ⱇ","Ⱈ":"ⱈ","Ⱉ":"ⱉ","Ⱊ":"ⱊ","Ⱋ":"ⱋ","Ⱌ":"ⱌ","Ⱍ":"ⱍ","Ⱎ":"ⱎ","Ⱏ":"ⱏ","Ⱐ":"ⱐ","Ⱑ":"ⱑ","Ⱒ":"ⱒ","Ⱓ":"ⱓ","Ⱔ":"ⱔ","Ⱕ":"ⱕ","Ⱖ":"ⱖ","Ⱗ":"ⱗ","Ⱘ":"ⱘ","Ⱙ":"ⱙ","Ⱚ":"ⱚ","Ⱛ":"ⱛ","Ⱜ":"ⱜ","Ⱝ":"ⱝ","Ⱞ":"ⱞ","Ⱡ":"ⱡ","Ɫ":"ɫ","Ᵽ":"ᵽ","Ɽ":"ɽ","Ⱨ":"ⱨ","Ⱪ":"ⱪ","Ⱬ":"ⱬ","Ɑ":"ɑ","Ɱ":"ɱ","Ɐ":"ɐ","Ɒ":"ɒ","Ⱳ":"ⱳ","Ⱶ":"ⱶ","Ȿ":"ȿ","Ɀ":"ɀ","Ⲁ":"ⲁ","Ⲃ":"ⲃ","Ⲅ":"ⲅ","Ⲇ":"ⲇ","Ⲉ":"ⲉ","Ⲋ":"ⲋ","Ⲍ":"ⲍ","Ⲏ":"ⲏ","Ⲑ":"ⲑ","Ⲓ":"ⲓ","Ⲕ":"ⲕ","Ⲗ":"ⲗ","Ⲙ":"ⲙ","Ⲛ":"ⲛ","Ⲝ":"ⲝ","Ⲟ":"ⲟ","Ⲡ":"ⲡ","Ⲣ":"ⲣ","Ⲥ":"ⲥ","Ⲧ":"ⲧ","Ⲩ":"ⲩ","Ⲫ":"ⲫ","Ⲭ":"ⲭ","Ⲯ":"ⲯ","Ⲱ":"ⲱ","Ⲳ":"ⲳ","Ⲵ":"ⲵ","Ⲷ":"ⲷ","Ⲹ":"ⲹ","Ⲻ":"ⲻ","Ⲽ":"ⲽ","Ⲿ":"ⲿ","Ⳁ":"ⳁ","Ⳃ":"ⳃ","Ⳅ":"ⳅ","Ⳇ":"ⳇ","Ⳉ":"ⳉ","Ⳋ":"ⳋ","Ⳍ":"ⳍ","Ⳏ":"ⳏ","Ⳑ":"ⳑ","Ⳓ":"ⳓ","Ⳕ":"ⳕ","Ⳗ":"ⳗ","Ⳙ":"ⳙ","Ⳛ":"ⳛ","Ⳝ":"ⳝ","Ⳟ":"ⳟ","Ⳡ":"ⳡ","Ⳣ":"ⳣ","Ⳬ":"ⳬ","Ⳮ":"ⳮ","Ⳳ":"ⳳ","Ꙁ":"ꙁ","Ꙃ":"ꙃ","Ꙅ":"ꙅ","Ꙇ":"ꙇ","Ꙉ":"ꙉ","Ꙋ":"ꙋ","Ꙍ":"ꙍ","Ꙏ":"ꙏ","Ꙑ":"ꙑ","Ꙓ":"ꙓ","Ꙕ":"ꙕ","Ꙗ":"ꙗ","Ꙙ":"ꙙ","Ꙛ":"ꙛ","Ꙝ":"ꙝ","Ꙟ":"ꙟ","Ꙡ":"ꙡ","Ꙣ":"ꙣ","Ꙥ":"ꙥ","Ꙧ":"ꙧ","Ꙩ":"ꙩ","Ꙫ":"ꙫ","Ꙭ":"ꙭ","Ꚁ":"ꚁ","Ꚃ":"ꚃ","Ꚅ":"ꚅ","Ꚇ":"ꚇ","Ꚉ":"ꚉ","Ꚋ":"ꚋ","Ꚍ":"ꚍ","Ꚏ":"ꚏ","Ꚑ":"ꚑ","Ꚓ":"ꚓ","Ꚕ":"ꚕ","Ꚗ":"ꚗ","Ꚙ":"ꚙ","Ꚛ":"ꚛ","Ꜣ":"ꜣ","Ꜥ":"ꜥ","Ꜧ":"ꜧ","Ꜩ":"ꜩ","Ꜫ":"ꜫ","Ꜭ":"ꜭ","Ꜯ":"ꜯ","Ꜳ":"ꜳ","Ꜵ":"ꜵ","Ꜷ":"ꜷ","Ꜹ":"ꜹ","Ꜻ":"ꜻ","Ꜽ":"ꜽ","Ꜿ":"ꜿ","Ꝁ":"ꝁ","Ꝃ":"ꝃ","Ꝅ":"ꝅ","Ꝇ":"ꝇ","Ꝉ":"ꝉ","Ꝋ":"ꝋ","Ꝍ":"ꝍ","Ꝏ":"ꝏ","Ꝑ":"ꝑ","Ꝓ":"ꝓ","Ꝕ":"ꝕ","Ꝗ":"ꝗ","Ꝙ":"ꝙ","Ꝛ":"ꝛ","Ꝝ":"ꝝ","Ꝟ":"ꝟ","Ꝡ":"ꝡ","Ꝣ":"ꝣ","Ꝥ":"ꝥ","Ꝧ":"ꝧ","Ꝩ":"ꝩ","Ꝫ":"ꝫ","Ꝭ":"ꝭ","Ꝯ":"ꝯ","Ꝺ":"ꝺ","Ꝼ":"ꝼ","Ᵹ":"ᵹ","Ꝿ":"ꝿ","Ꞁ":"ꞁ","Ꞃ":"ꞃ","Ꞅ":"ꞅ","Ꞇ":"ꞇ","Ꞌ":"ꞌ","Ɥ":"ɥ","Ꞑ":"ꞑ","Ꞓ":"ꞓ","Ꞗ":"ꞗ","Ꞙ":"ꞙ","Ꞛ":"ꞛ","Ꞝ":"ꞝ","Ꞟ":"ꞟ","Ꞡ":"ꞡ","Ꞣ":"ꞣ","Ꞥ":"ꞥ","Ꞧ":"ꞧ","Ꞩ":"ꞩ","Ɦ":"ɦ","Ɜ":"ɜ","Ɡ":"ɡ","Ɬ":"ɬ","Ʞ":"ʞ","Ʇ":"ʇ","A":"a","B":"b","C":"c","D":"d","E":"e","F":"f","G":"g","H":"h","I":"i","J":"j","K":"k","L":"l","M":"m","N":"n","O":"o","P":"p","Q":"q","R":"r","S":"s","T":"t","U":"u","V":"v","W":"w","X":"x","Y":"y","Z":"z","𐐀":"𐐨","𐐁":"𐐩","𐐂":"𐐪","𐐃":"𐐫","𐐄":"𐐬","𐐅":"𐐭","𐐆":"𐐮","𐐇":"𐐯","𐐈":"𐐰","𐐉":"𐐱","𐐊":"𐐲","𐐋":"𐐳","𐐌":"𐐴","𐐍":"𐐵","𐐎":"𐐶","𐐏":"𐐷","𐐐":"𐐸","𐐑":"𐐹","𐐒":"𐐺","𐐓":"𐐻","𐐔":"𐐼","𐐕":"𐐽","𐐖":"𐐾","𐐗":"𐐿","𐐘":"𐑀","𐐙":"𐑁","𐐚":"𐑂","𐐛":"𐑃","𐐜":"𐑄","𐐝":"𐑅","𐐞":"𐑆","𐐟":"𐑇","𐐠":"𐑈","𐐡":"𐑉","𐐢":"𐑊","𐐣":"𐑋","𐐤":"𐑌","𐐥":"𐑍","𐐦":"𐑎","𐐧":"𐑏","𑢠":"𑣀","𑢡":"𑣁","𑢢":"𑣂","𑢣":"𑣃","𑢤":"𑣄","𑢥":"𑣅","𑢦":"𑣆","𑢧":"𑣇","𑢨":"𑣈","𑢩":"𑣉","𑢪":"𑣊","𑢫":"𑣋","𑢬":"𑣌","𑢭":"𑣍","𑢮":"𑣎","𑢯":"𑣏","𑢰":"𑣐","𑢱":"𑣑","𑢲":"𑣒","𑢳":"𑣓","𑢴":"𑣔","𑢵":"𑣕","𑢶":"𑣖","𑢷":"𑣗","𑢸":"𑣘","𑢹":"𑣙","𑢺":"𑣚","𑢻":"𑣛","𑢼":"𑣜","𑢽":"𑣝","𑢾":"𑣞","𑢿":"𑣟","ß":"ss","İ":"i̇","ʼn":"ʼn","ǰ":"ǰ","ΐ":"ΐ","ΰ":"ΰ","և":"եւ","ẖ":"ẖ","ẗ":"ẗ","ẘ":"ẘ","ẙ":"ẙ","ẚ":"aʾ","ẞ":"ss","ὐ":"ὐ","ὒ":"ὒ","ὔ":"ὔ","ὖ":"ὖ","ᾀ":"ἀι","ᾁ":"ἁι","ᾂ":"ἂι","ᾃ":"ἃι","ᾄ":"ἄι","ᾅ":"ἅι","ᾆ":"ἆι","ᾇ":"ἇι","ᾈ":"ἀι","ᾉ":"ἁι","ᾊ":"ἂι","ᾋ":"ἃι","ᾌ":"ἄι","ᾍ":"ἅι","ᾎ":"ἆι","ᾏ":"ἇι","ᾐ":"ἠι","ᾑ":"ἡι","ᾒ":"ἢι","ᾓ":"ἣι","ᾔ":"ἤι","ᾕ":"ἥι","ᾖ":"ἦι","ᾗ":"ἧι","ᾘ":"ἠι","ᾙ":"ἡι","ᾚ":"ἢι","ᾛ":"ἣι","ᾜ":"ἤι","ᾝ":"ἥι","ᾞ":"ἦι","ᾟ":"ἧι","ᾠ":"ὠι","ᾡ":"ὡι","ᾢ":"ὢι","ᾣ":"ὣι","ᾤ":"ὤι","ᾥ":"ὥι","ᾦ":"ὦι","ᾧ":"ὧι","ᾨ":"ὠι","ᾩ":"ὡι","ᾪ":"ὢι","ᾫ":"ὣι","ᾬ":"ὤι","ᾭ":"ὥι","ᾮ":"ὦι","ᾯ":"ὧι","ᾲ":"ὰι","ᾳ":"αι","ᾴ":"άι","ᾶ":"ᾶ","ᾷ":"ᾶι","ᾼ":"αι","ῂ":"ὴι","ῃ":"ηι","ῄ":"ήι","ῆ":"ῆ","ῇ":"ῆι","ῌ":"ηι","ῒ":"ῒ","ΐ":"ΐ","ῖ":"ῖ","ῗ":"ῗ","ῢ":"ῢ","ΰ":"ΰ","ῤ":"ῤ","ῦ":"ῦ","ῧ":"ῧ","ῲ":"ὼι","ῳ":"ωι","ῴ":"ώι","ῶ":"ῶ","ῷ":"ῶι","ῼ":"ωι","ff":"ff","fi":"fi","fl":"fl","ffi":"ffi","ffl":"ffl","ſt":"st","st":"st","ﬓ":"մն","ﬔ":"մե","ﬕ":"մի","ﬖ":"վն","ﬗ":"մխ"};module.exports=function(string){return string.slice(1,string.length-1).trim().replace(regex,function($0){return map[$0]||" "})}},{}],9:[function(require,module,exports){"use strict";function XmlRenderer(options){return{softbreak:"\n",escape:escapeXml,options:options||{},render:renderNodes}}var escapeXml=require("./common").escapeXml,tag=function(name,attrs,selfclosing){var result="<"+name;if(attrs&&attrs.length>0)for(var attrib,i=0;void 0!==(attrib=attrs[i]);)result+=" "+attrib[0]+'="'+attrib[1]+'"',i++;return selfclosing&&(result+=" /"),result+=">"},reXMLTag=/\<[^>]*\>/,toTagName=function(s){return s.replace(/([a-z])([A-Z])/g,"$1_$2").toLowerCase()},renderNodes=function(block){var attrs,tagname,event,node,entering,unescapedContents,container,selfClosing,nodetype,walker=block.walker(),buffer="",lastOut="\n",disableTags=0,indentLevel=0,indent=" ",out=function(s){buffer+=disableTags>0?s.replace(reXMLTag,""):s,lastOut=s},esc=this.escape,cr=function(){if("\n"!==lastOut){buffer+="\n",lastOut="\n";for(var i=indentLevel;i>0;i--)buffer+=indent}},options=this.options;for(options.time&&console.time("rendering"),buffer+='\n',buffer+='\n';event=walker.next();)if(entering=event.entering,node=event.node,nodetype=node.type,container=node.isContainer,selfClosing="HorizontalRule"===nodetype||"Hardbreak"===nodetype||"Softbreak"===nodetype,unescapedContents="Html"===nodetype||"HtmlInline"===nodetype,tagname=toTagName(nodetype),entering){switch(attrs=[],nodetype){case"List":null!==node.listType&&attrs.push(["type",node.listType.toLowerCase()]),null!==node.listStart&&attrs.push(["start",String(node.listStart)]),null!==node.listTight&&attrs.push(["tight",node.listTight?"true":"false"]);var delim=node.listDelimiter;if(null!==delim){var delimword="";delimword="."===delim?"period":"paren",attrs.push(["delimiter",delimword])}break;case"CodeBlock":node.info&&attrs.push(["info",node.info]);break;case"Header":attrs.push(["level",String(node.level)]);break;case"Link":case"Image":attrs.push(["destination",node.destination]),attrs.push(["title",node.title])}if(options.sourcepos){var pos=node.sourcepos;pos&&attrs.push(["sourcepos",String(pos[0][0])+":"+String(pos[0][1])+"-"+String(pos[1][0])+":"+String(pos[1][1])])}if(cr(),out(tag(tagname,attrs,selfClosing)),container)indentLevel+=1;else if(!container&&!selfClosing){var lit=node.literal;lit&&out(unescapedContents?lit:esc(lit)),out(tag("/"+tagname))}}else indentLevel-=1,cr(),out(tag("/"+tagname));return options.time&&console.timeEnd("rendering"),buffer+="\n"};module.exports=XmlRenderer},{"./common":2}],10:[function(require,module,exports){var encode=require("./lib/encode.js"),decode=require("./lib/decode.js");exports.decode=function(data,level){return(!level||0>=level?decode.XML:decode.HTML)(data)},exports.decodeStrict=function(data,level){return(!level||0>=level?decode.XML:decode.HTMLStrict)(data)},exports.encode=function(data,level){return(!level||0>=level?encode.XML:encode.HTML)(data)},exports.encodeXML=encode.XML,exports.encodeHTML4=exports.encodeHTML5=exports.encodeHTML=encode.HTML,exports.decodeXML=exports.decodeXMLStrict=decode.XML,exports.decodeHTML4=exports.decodeHTML5=exports.decodeHTML=decode.HTML,exports.decodeHTML4Strict=exports.decodeHTML5Strict=exports.decodeHTMLStrict=decode.HTMLStrict,exports.escape=encode.escape},{"./lib/decode.js":11,"./lib/encode.js":13}],11:[function(require,module,exports){function getStrictDecoder(map){var keys=Object.keys(map).join("|"),replace=getReplacer(map);keys+="|#[xX][\\da-fA-F]+|#\\d+";var re=new RegExp("&(?:"+keys+");","g");return function(str){return String(str).replace(re,replace)}}function sorter(a,b){return b>a?1:-1}function getReplacer(map){return function(str){return"#"===str.charAt(1)?decodeCodePoint("X"===str.charAt(2)||"x"===str.charAt(2)?parseInt(str.substr(3),16):parseInt(str.substr(2),10)):map[str.slice(1,-1)]}}var entityMap=require("../maps/entities.json"),legacyMap=require("../maps/legacy.json"),xmlMap=require("../maps/xml.json"),decodeCodePoint=require("./decode_codepoint.js"),decodeXMLStrict=getStrictDecoder(xmlMap),decodeHTMLStrict=getStrictDecoder(entityMap),decodeHTML=function(){function replacer(str){return";"!==str.substr(-1)&&(str+=";"),replace(str)}for(var legacy=Object.keys(legacyMap).sort(sorter),keys=Object.keys(entityMap).sort(sorter),i=0,j=0;keys.length>i;i++)legacy[j]===keys[i]?(keys[i]+=";?",j++):keys[i]+=";";var re=new RegExp("&(?:"+keys.join("|")+"|#[xX][\\da-fA-F]+;?|#\\d+;?)","g"),replace=getReplacer(entityMap);return function(str){return String(str).replace(re,replacer)}}();module.exports={XML:decodeXMLStrict,HTML:decodeHTML,HTMLStrict:decodeHTMLStrict}},{"../maps/entities.json":15,"../maps/legacy.json":16,"../maps/xml.json":17,"./decode_codepoint.js":12}],12:[function(require,module,exports){function decodeCodePoint(codePoint){if(codePoint>=55296&&57343>=codePoint||codePoint>1114111)return"�";codePoint in decodeMap&&(codePoint=decodeMap[codePoint]);var output="";return codePoint>65535&&(codePoint-=65536,output+=String.fromCharCode(codePoint>>>10&1023|55296),codePoint=56320|1023&codePoint),output+=String.fromCharCode(codePoint)}var decodeMap=require("../maps/decode.json");module.exports=decodeCodePoint},{"../maps/decode.json":14}],13:[function(require,module,exports){function getInverseObj(obj){return Object.keys(obj).sort().reduce(function(inverse,name){return inverse[obj[name]]="&"+name+";",inverse},{})}function getInverseReplacer(inverse){var single=[],multiple=[];return Object.keys(inverse).forEach(function(k){1===k.length?single.push("\\"+k):multiple.push(k)}),multiple.unshift("["+single.join("")+"]"),new RegExp(multiple.join("|"),"g")}function singleCharReplacer(c){return""+c.charCodeAt(0).toString(16).toUpperCase()+";"}function astralReplacer(c){var high=c.charCodeAt(0),low=c.charCodeAt(1),codePoint=1024*(high-55296)+low-56320+65536;return""+codePoint.toString(16).toUpperCase()+";"}function getInverse(inverse,re){function func(name){return inverse[name]}return function(data){return data.replace(re,func).replace(re_astralSymbols,astralReplacer).replace(re_nonASCII,singleCharReplacer)}}function escapeXML(data){return data.replace(re_xmlChars,singleCharReplacer).replace(re_astralSymbols,astralReplacer).replace(re_nonASCII,singleCharReplacer)}var inverseXML=getInverseObj(require("../maps/xml.json")),xmlReplacer=getInverseReplacer(inverseXML);exports.XML=getInverse(inverseXML,xmlReplacer);var inverseHTML=getInverseObj(require("../maps/entities.json")),htmlReplacer=getInverseReplacer(inverseHTML);exports.HTML=getInverse(inverseHTML,htmlReplacer);var re_nonASCII=/[^\0-\x7F]/g,re_astralSymbols=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,re_xmlChars=getInverseReplacer(inverseXML);exports.escape=escapeXML},{"../maps/entities.json":15,"../maps/xml.json":17}],14:[function(require,module,exports){module.exports={0:65533,128:8364,130:8218,131:402,132:8222,133:8230,134:8224,135:8225,136:710,137:8240,138:352,139:8249,140:338,142:381,145:8216,146:8217,147:8220,148:8221,149:8226,150:8211,151:8212,152:732,153:8482,154:353,155:8250,156:339,158:382,159:376}},{}],15:[function(require,module,exports){module.exports={Aacute:"Á",aacute:"á",Abreve:"Ă",abreve:"ă",ac:"∾",acd:"∿",acE:"∾̳",Acirc:"Â",acirc:"â",acute:"´",Acy:"А",acy:"а",AElig:"Æ",aelig:"æ",af:"",Afr:"𝔄",afr:"𝔞",Agrave:"À",agrave:"à",alefsym:"ℵ",aleph:"ℵ",Alpha:"Α",alpha:"α",Amacr:"Ā",amacr:"ā",amalg:"⨿",amp:"&",AMP:"&",andand:"⩕",And:"⩓",and:"∧",andd:"⩜",andslope:"⩘",andv:"⩚",ang:"∠",ange:"⦤",angle:"∠",angmsdaa:"⦨",angmsdab:"⦩",angmsdac:"⦪",angmsdad:"⦫",angmsdae:"⦬",angmsdaf:"⦭",angmsdag:"⦮",angmsdah:"⦯",angmsd:"∡",angrt:"∟",angrtvb:"⊾",angrtvbd:"⦝",angsph:"∢",angst:"Å",angzarr:"⍼",Aogon:"Ą",aogon:"ą",Aopf:"𝔸",aopf:"𝕒",apacir:"⩯",ap:"≈",apE:"⩰",ape:"≊",apid:"≋",apos:"'",ApplyFunction:"",approx:"≈",approxeq:"≊",Aring:"Å",aring:"å",Ascr:"𝒜",ascr:"𝒶",Assign:"≔",ast:"*",asymp:"≈",asympeq:"≍",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",awconint:"∳",awint:"⨑",backcong:"≌",backepsilon:"϶",backprime:"‵",backsim:"∽",backsimeq:"⋍",Backslash:"∖",Barv:"⫧",barvee:"⊽",barwed:"⌅",Barwed:"⌆",barwedge:"⌅",bbrk:"⎵",bbrktbrk:"⎶",bcong:"≌",Bcy:"Б",bcy:"б",bdquo:"„",becaus:"∵",because:"∵",Because:"∵",bemptyv:"⦰",bepsi:"϶",bernou:"ℬ",Bernoullis:"ℬ",Beta:"Β",beta:"β",beth:"ℶ",between:"≬",Bfr:"𝔅",bfr:"𝔟",bigcap:"⋂",bigcirc:"◯",bigcup:"⋃",bigodot:"⨀",bigoplus:"⨁",bigotimes:"⨂",bigsqcup:"⨆",bigstar:"★",bigtriangledown:"▽",bigtriangleup:"△",biguplus:"⨄",bigvee:"⋁",bigwedge:"⋀",bkarow:"⤍",blacklozenge:"⧫",blacksquare:"▪",blacktriangle:"▴",blacktriangledown:"▾",blacktriangleleft:"◂",blacktriangleright:"▸",blank:"␣",blk12:"▒",blk14:"░",blk34:"▓",block:"█",bne:"=⃥",bnequiv:"≡⃥",bNot:"⫭",bnot:"⌐",Bopf:"𝔹",bopf:"𝕓",bot:"⊥",bottom:"⊥",bowtie:"⋈",boxbox:"⧉",boxdl:"┐",boxdL:"╕",boxDl:"╖",boxDL:"╗",boxdr:"┌",boxdR:"╒",boxDr:"╓",boxDR:"╔",boxh:"─",boxH:"═",boxhd:"┬",boxHd:"╤",boxhD:"╥",boxHD:"╦",boxhu:"┴",boxHu:"╧",boxhU:"╨",boxHU:"╩",boxminus:"⊟",boxplus:"⊞",boxtimes:"⊠",boxul:"┘",boxuL:"╛",boxUl:"╜",boxUL:"╝",boxur:"└",boxuR:"╘",boxUr:"╙",boxUR:"╚",boxv:"│",boxV:"║",boxvh:"┼",boxvH:"╪",boxVh:"╫",boxVH:"╬",boxvl:"┤",boxvL:"╡",boxVl:"╢",boxVL:"╣",boxvr:"├",boxvR:"╞",boxVr:"╟",boxVR:"╠",bprime:"‵",breve:"˘",Breve:"˘",brvbar:"¦",bscr:"𝒷",Bscr:"ℬ",bsemi:"⁏",bsim:"∽",bsime:"⋍",bsolb:"⧅",bsol:"\\",bsolhsub:"⟈",bull:"•",bullet:"•",bump:"≎",bumpE:"⪮",bumpe:"≏",Bumpeq:"≎",bumpeq:"≏",Cacute:"Ć",cacute:"ć",capand:"⩄",capbrcup:"⩉",capcap:"⩋",cap:"∩",Cap:"⋒",capcup:"⩇",capdot:"⩀",CapitalDifferentialD:"ⅅ",caps:"∩︀",caret:"⁁",caron:"ˇ",Cayleys:"ℭ",ccaps:"⩍",Ccaron:"Č",ccaron:"č",Ccedil:"Ç",ccedil:"ç",Ccirc:"Ĉ",ccirc:"ĉ",Cconint:"∰",ccups:"⩌",ccupssm:"⩐",Cdot:"Ċ",cdot:"ċ",cedil:"¸",Cedilla:"¸",cemptyv:"⦲",cent:"¢",centerdot:"·",CenterDot:"·",cfr:"𝔠",Cfr:"ℭ",CHcy:"Ч",chcy:"ч",check:"✓",checkmark:"✓",Chi:"Χ",chi:"χ",circ:"ˆ",circeq:"≗",circlearrowleft:"↺",circlearrowright:"↻",circledast:"⊛",circledcirc:"⊚",circleddash:"⊝",CircleDot:"⊙",circledR:"®",circledS:"Ⓢ",CircleMinus:"⊖",CirclePlus:"⊕",CircleTimes:"⊗",cir:"○",cirE:"⧃",cire:"≗",cirfnint:"⨐",cirmid:"⫯",cirscir:"⧂",ClockwiseContourIntegral:"∲",CloseCurlyDoubleQuote:"”",CloseCurlyQuote:"’",clubs:"♣",clubsuit:"♣",colon:":",Colon:"∷",Colone:"⩴",colone:"≔",coloneq:"≔",comma:",",commat:"@",comp:"∁",compfn:"∘",complement:"∁",complexes:"ℂ",cong:"≅",congdot:"⩭",Congruent:"≡",conint:"∮",Conint:"∯",ContourIntegral:"∮",copf:"𝕔",Copf:"ℂ",coprod:"∐",Coproduct:"∐",copy:"©",COPY:"©",copysr:"℗",CounterClockwiseContourIntegral:"∳",crarr:"↵",cross:"✗",Cross:"⨯",Cscr:"𝒞",cscr:"𝒸",csub:"⫏",csube:"⫑",csup:"⫐",csupe:"⫒",ctdot:"⋯",cudarrl:"⤸",cudarrr:"⤵",cuepr:"⋞",cuesc:"⋟",cularr:"↶",cularrp:"⤽",cupbrcap:"⩈",cupcap:"⩆",CupCap:"≍",cup:"∪",Cup:"⋓",cupcup:"⩊",cupdot:"⊍",cupor:"⩅",cups:"∪︀",curarr:"↷",curarrm:"⤼",curlyeqprec:"⋞",curlyeqsucc:"⋟",curlyvee:"⋎",curlywedge:"⋏",curren:"¤",curvearrowleft:"↶",curvearrowright:"↷",cuvee:"⋎",cuwed:"⋏",cwconint:"∲",cwint:"∱",cylcty:"⌭",dagger:"†",Dagger:"‡",daleth:"ℸ",darr:"↓",Darr:"↡",dArr:"⇓",dash:"‐",Dashv:"⫤",dashv:"⊣",dbkarow:"⤏",dblac:"˝",Dcaron:"Ď",dcaron:"ď",Dcy:"Д",dcy:"д",ddagger:"‡",ddarr:"⇊",DD:"ⅅ",dd:"ⅆ",DDotrahd:"⤑",ddotseq:"⩷",deg:"°",Del:"∇",Delta:"Δ",delta:"δ",demptyv:"⦱",dfisht:"⥿",Dfr:"𝔇",dfr:"𝔡",dHar:"⥥",dharl:"⇃",dharr:"⇂",DiacriticalAcute:"´",DiacriticalDot:"˙",DiacriticalDoubleAcute:"˝",DiacriticalGrave:"`",DiacriticalTilde:"˜",diam:"⋄",diamond:"⋄",Diamond:"⋄",diamondsuit:"♦",diams:"♦",die:"¨",DifferentialD:"ⅆ",digamma:"ϝ",disin:"⋲",div:"÷",divide:"÷",divideontimes:"⋇",divonx:"⋇",DJcy:"Ђ",djcy:"ђ",dlcorn:"⌞",dlcrop:"⌍",dollar:"$",Dopf:"𝔻",dopf:"𝕕",Dot:"¨",dot:"˙",DotDot:"⃜",doteq:"≐",doteqdot:"≑",DotEqual:"≐",dotminus:"∸",dotplus:"∔",dotsquare:"⊡",doublebarwedge:"⌆",DoubleContourIntegral:"∯",DoubleDot:"¨",DoubleDownArrow:"⇓",DoubleLeftArrow:"⇐",DoubleLeftRightArrow:"⇔",DoubleLeftTee:"⫤",DoubleLongLeftArrow:"⟸",DoubleLongLeftRightArrow:"⟺",DoubleLongRightArrow:"⟹",DoubleRightArrow:"⇒",DoubleRightTee:"⊨",DoubleUpArrow:"⇑",DoubleUpDownArrow:"⇕",DoubleVerticalBar:"∥",DownArrowBar:"⤓",downarrow:"↓",DownArrow:"↓",Downarrow:"⇓",DownArrowUpArrow:"⇵",DownBreve:"̑",downdownarrows:"⇊",downharpoonleft:"⇃",downharpoonright:"⇂",DownLeftRightVector:"⥐",DownLeftTeeVector:"⥞",DownLeftVectorBar:"⥖",DownLeftVector:"↽",DownRightTeeVector:"⥟",DownRightVectorBar:"⥗",DownRightVector:"⇁",DownTeeArrow:"↧",DownTee:"⊤",drbkarow:"⤐",drcorn:"⌟",drcrop:"⌌",Dscr:"𝒟",dscr:"𝒹",DScy:"Ѕ",dscy:"ѕ",dsol:"⧶",Dstrok:"Đ",dstrok:"đ",dtdot:"⋱",dtri:"▿",dtrif:"▾",duarr:"⇵",duhar:"⥯",dwangle:"⦦",DZcy:"Џ",dzcy:"џ",dzigrarr:"⟿",Eacute:"É",eacute:"é",easter:"⩮",Ecaron:"Ě",ecaron:"ě",Ecirc:"Ê",ecirc:"ê",ecir:"≖",ecolon:"≕",Ecy:"Э",ecy:"э",eDDot:"⩷",Edot:"Ė",edot:"ė",eDot:"≑",ee:"ⅇ",efDot:"≒",Efr:"𝔈",efr:"𝔢",eg:"⪚",Egrave:"È",egrave:"è",egs:"⪖",egsdot:"⪘",el:"⪙",Element:"∈",elinters:"⏧",ell:"ℓ",els:"⪕",elsdot:"⪗",Emacr:"Ē",emacr:"ē",empty:"∅",emptyset:"∅",EmptySmallSquare:"◻",emptyv:"∅",EmptyVerySmallSquare:"▫",emsp13:" ",emsp14:" ",emsp:" ",ENG:"Ŋ",eng:"ŋ",ensp:" ",Eogon:"Ę",eogon:"ę",Eopf:"𝔼",eopf:"𝕖",epar:"⋕",eparsl:"⧣",eplus:"⩱",epsi:"ε",Epsilon:"Ε",epsilon:"ε",epsiv:"ϵ",eqcirc:"≖",eqcolon:"≕",eqsim:"≂",eqslantgtr:"⪖",eqslantless:"⪕",Equal:"⩵",equals:"=",EqualTilde:"≂",equest:"≟",Equilibrium:"⇌",equiv:"≡",equivDD:"⩸",eqvparsl:"⧥",erarr:"⥱",erDot:"≓",escr:"ℯ",Escr:"ℰ",esdot:"≐",Esim:"⩳",esim:"≂",Eta:"Η",eta:"η",ETH:"Ð",eth:"ð",Euml:"Ë",euml:"ë",euro:"€",excl:"!",exist:"∃",Exists:"∃",expectation:"ℰ",exponentiale:"ⅇ",ExponentialE:"ⅇ",fallingdotseq:"≒",Fcy:"Ф",fcy:"ф",female:"♀",ffilig:"ffi",fflig:"ff",ffllig:"ffl",Ffr:"𝔉",ffr:"𝔣",filig:"fi",FilledSmallSquare:"◼",FilledVerySmallSquare:"▪",fjlig:"fj",flat:"♭",fllig:"fl",fltns:"▱",fnof:"ƒ",Fopf:"𝔽",fopf:"𝕗",forall:"∀",ForAll:"∀",fork:"⋔",forkv:"⫙",Fouriertrf:"ℱ",fpartint:"⨍",frac12:"½",frac13:"⅓",frac14:"¼",frac15:"⅕",frac16:"⅙",frac18:"⅛",frac23:"⅔",frac25:"⅖",frac34:"¾",frac35:"⅗",frac38:"⅜",frac45:"⅘",frac56:"⅚",frac58:"⅝",frac78:"⅞",frasl:"⁄",frown:"⌢",fscr:"𝒻",Fscr:"ℱ",gacute:"ǵ",Gamma:"Γ",gamma:"γ",Gammad:"Ϝ",gammad:"ϝ",gap:"⪆",Gbreve:"Ğ",gbreve:"ğ",Gcedil:"Ģ",Gcirc:"Ĝ",gcirc:"ĝ",Gcy:"Г",gcy:"г",Gdot:"Ġ",gdot:"ġ",ge:"≥",gE:"≧",gEl:"⪌",gel:"⋛",geq:"≥",geqq:"≧",geqslant:"⩾",gescc:"⪩",ges:"⩾",gesdot:"⪀",gesdoto:"⪂",gesdotol:"⪄",gesl:"⋛︀",gesles:"⪔",Gfr:"𝔊",gfr:"𝔤",gg:"≫",Gg:"⋙",ggg:"⋙",gimel:"ℷ",GJcy:"Ѓ",gjcy:"ѓ",gla:"⪥",gl:"≷",glE:"⪒",glj:"⪤",gnap:"⪊",gnapprox:"⪊",gne:"⪈",gnE:"≩",gneq:"⪈",gneqq:"≩",gnsim:"⋧",Gopf:"𝔾",gopf:"𝕘",grave:"`",GreaterEqual:"≥",GreaterEqualLess:"⋛",GreaterFullEqual:"≧",GreaterGreater:"⪢",GreaterLess:"≷",GreaterSlantEqual:"⩾",GreaterTilde:"≳",Gscr:"𝒢",gscr:"ℊ",gsim:"≳",gsime:"⪎",gsiml:"⪐",gtcc:"⪧",gtcir:"⩺",gt:">",GT:">",Gt:"≫",gtdot:"⋗",gtlPar:"⦕",gtquest:"⩼",gtrapprox:"⪆",gtrarr:"⥸",gtrdot:"⋗",gtreqless:"⋛",gtreqqless:"⪌",gtrless:"≷",gtrsim:"≳",gvertneqq:"≩︀",gvnE:"≩︀",Hacek:"ˇ",hairsp:" ",half:"½",hamilt:"ℋ",HARDcy:"Ъ",hardcy:"ъ",harrcir:"⥈",harr:"↔",hArr:"⇔",harrw:"↭",Hat:"^",hbar:"ℏ",Hcirc:"Ĥ",hcirc:"ĥ",hearts:"♥",heartsuit:"♥",hellip:"…",hercon:"⊹",hfr:"𝔥",Hfr:"ℌ",HilbertSpace:"ℋ",hksearow:"⤥",hkswarow:"⤦",hoarr:"⇿",homtht:"∻",hookleftarrow:"↩",hookrightarrow:"↪",hopf:"𝕙",Hopf:"ℍ",horbar:"―",HorizontalLine:"─",hscr:"𝒽",Hscr:"ℋ",hslash:"ℏ",Hstrok:"Ħ",hstrok:"ħ",HumpDownHump:"≎",HumpEqual:"≏",hybull:"⁃",hyphen:"‐",Iacute:"Í",iacute:"í",ic:"",Icirc:"Î",icirc:"î",Icy:"И",icy:"и",Idot:"İ",IEcy:"Е",iecy:"е",iexcl:"¡",iff:"⇔",ifr:"𝔦",Ifr:"ℑ",Igrave:"Ì",igrave:"ì",ii:"ⅈ",iiiint:"⨌",iiint:"∭",iinfin:"⧜",iiota:"℩",IJlig:"IJ",ijlig:"ij",Imacr:"Ī",imacr:"ī",image:"ℑ",ImaginaryI:"ⅈ",imagline:"ℐ",imagpart:"ℑ",imath:"ı",Im:"ℑ",imof:"⊷",imped:"Ƶ",Implies:"⇒",incare:"℅","in":"∈",infin:"∞",infintie:"⧝",inodot:"ı",intcal:"⊺","int":"∫",Int:"∬",integers:"ℤ",Integral:"∫",intercal:"⊺",Intersection:"⋂",intlarhk:"⨗",intprod:"⨼",InvisibleComma:"",InvisibleTimes:"",IOcy:"Ё",iocy:"ё",Iogon:"Į",iogon:"į",Iopf:"𝕀",iopf:"𝕚",Iota:"Ι",iota:"ι",iprod:"⨼",iquest:"¿",iscr:"𝒾",Iscr:"ℐ",isin:"∈",isindot:"⋵",isinE:"⋹",isins:"⋴",isinsv:"⋳",isinv:"∈",it:"",Itilde:"Ĩ",itilde:"ĩ",Iukcy:"І",iukcy:"і",Iuml:"Ï",iuml:"ï",Jcirc:"Ĵ",jcirc:"ĵ",Jcy:"Й",jcy:"й",Jfr:"𝔍",jfr:"𝔧",jmath:"ȷ",Jopf:"𝕁",jopf:"𝕛",Jscr:"𝒥",jscr:"𝒿",Jsercy:"Ј",jsercy:"ј",Jukcy:"Є",jukcy:"є",Kappa:"Κ",kappa:"κ",kappav:"ϰ",Kcedil:"Ķ",kcedil:"ķ",Kcy:"К",kcy:"к",Kfr:"𝔎",kfr:"𝔨",kgreen:"ĸ",KHcy:"Х",khcy:"х",KJcy:"Ќ",kjcy:"ќ",Kopf:"𝕂",kopf:"𝕜",Kscr:"𝒦",kscr:"𝓀",lAarr:"⇚",Lacute:"Ĺ",lacute:"ĺ",laemptyv:"⦴",lagran:"ℒ",Lambda:"Λ",lambda:"λ",lang:"⟨",Lang:"⟪",langd:"⦑",langle:"⟨",lap:"⪅",Laplacetrf:"ℒ",laquo:"«",larrb:"⇤",larrbfs:"⤟",larr:"←",Larr:"↞",lArr:"⇐",larrfs:"⤝",larrhk:"↩",larrlp:"↫",larrpl:"⤹",larrsim:"⥳",larrtl:"↢",latail:"⤙",lAtail:"⤛",lat:"⪫",late:"⪭",lates:"⪭︀",lbarr:"⤌",lBarr:"⤎",lbbrk:"❲",lbrace:"{",lbrack:"[",lbrke:"⦋",lbrksld:"⦏",lbrkslu:"⦍",Lcaron:"Ľ",lcaron:"ľ",Lcedil:"Ļ",lcedil:"ļ",lceil:"⌈",lcub:"{",Lcy:"Л",lcy:"л",ldca:"⤶",ldquo:"“",ldquor:"„",ldrdhar:"⥧",ldrushar:"⥋",ldsh:"↲",le:"≤",lE:"≦",LeftAngleBracket:"⟨",LeftArrowBar:"⇤",leftarrow:"←",LeftArrow:"←",Leftarrow:"⇐",LeftArrowRightArrow:"⇆",leftarrowtail:"↢",LeftCeiling:"⌈",LeftDoubleBracket:"⟦",LeftDownTeeVector:"⥡",LeftDownVectorBar:"⥙",LeftDownVector:"⇃",LeftFloor:"⌊",leftharpoondown:"↽",leftharpoonup:"↼",leftleftarrows:"⇇",leftrightarrow:"↔",LeftRightArrow:"↔",Leftrightarrow:"⇔",leftrightarrows:"⇆",leftrightharpoons:"⇋",leftrightsquigarrow:"↭",LeftRightVector:"⥎",LeftTeeArrow:"↤",LeftTee:"⊣",LeftTeeVector:"⥚",leftthreetimes:"⋋",LeftTriangleBar:"⧏",LeftTriangle:"⊲",LeftTriangleEqual:"⊴",LeftUpDownVector:"⥑",LeftUpTeeVector:"⥠",LeftUpVectorBar:"⥘",LeftUpVector:"↿",LeftVectorBar:"⥒",LeftVector:"↼",lEg:"⪋",leg:"⋚",leq:"≤",leqq:"≦",leqslant:"⩽",lescc:"⪨",les:"⩽",lesdot:"⩿",lesdoto:"⪁",lesdotor:"⪃",lesg:"⋚︀",lesges:"⪓",lessapprox:"⪅",lessdot:"⋖",lesseqgtr:"⋚",lesseqqgtr:"⪋",LessEqualGreater:"⋚",LessFullEqual:"≦",LessGreater:"≶",lessgtr:"≶",LessLess:"⪡",lesssim:"≲",LessSlantEqual:"⩽",LessTilde:"≲",lfisht:"⥼",lfloor:"⌊",Lfr:"𝔏",lfr:"𝔩",lg:"≶",lgE:"⪑",lHar:"⥢",lhard:"↽",lharu:"↼",lharul:"⥪",lhblk:"▄",LJcy:"Љ",ljcy:"љ",llarr:"⇇",ll:"≪",Ll:"⋘",llcorner:"⌞",Lleftarrow:"⇚",llhard:"⥫",lltri:"◺",Lmidot:"Ŀ",lmidot:"ŀ",lmoustache:"⎰",lmoust:"⎰",lnap:"⪉",lnapprox:"⪉",lne:"⪇",lnE:"≨",lneq:"⪇",lneqq:"≨",lnsim:"⋦",loang:"⟬",loarr:"⇽",lobrk:"⟦",longleftarrow:"⟵",LongLeftArrow:"⟵",Longleftarrow:"⟸",longleftrightarrow:"⟷",LongLeftRightArrow:"⟷",Longleftrightarrow:"⟺",longmapsto:"⟼",longrightarrow:"⟶",LongRightArrow:"⟶",Longrightarrow:"⟹",looparrowleft:"↫",looparrowright:"↬",lopar:"⦅",Lopf:"𝕃",lopf:"𝕝",loplus:"⨭",lotimes:"⨴",lowast:"∗",lowbar:"_",LowerLeftArrow:"↙",LowerRightArrow:"↘",loz:"◊",lozenge:"◊",lozf:"⧫",lpar:"(",lparlt:"⦓",lrarr:"⇆",lrcorner:"⌟",lrhar:"⇋",lrhard:"⥭",lrm:"",lrtri:"⊿",lsaquo:"‹",lscr:"𝓁",Lscr:"ℒ",lsh:"↰",Lsh:"↰",lsim:"≲",lsime:"⪍",lsimg:"⪏",lsqb:"[",lsquo:"‘",lsquor:"‚",Lstrok:"Ł",lstrok:"ł",ltcc:"⪦",ltcir:"⩹",lt:"<",LT:"<",Lt:"≪",ltdot:"⋖",lthree:"⋋",ltimes:"⋉",ltlarr:"⥶",ltquest:"⩻",ltri:"◃",ltrie:"⊴",ltrif:"◂",ltrPar:"⦖",lurdshar:"⥊",luruhar:"⥦",lvertneqq:"≨︀",lvnE:"≨︀",macr:"¯",male:"♂",malt:"✠",maltese:"✠",Map:"⤅",map:"↦",mapsto:"↦",mapstodown:"↧",mapstoleft:"↤",mapstoup:"↥",marker:"▮",mcomma:"⨩",Mcy:"М",mcy:"м",mdash:"—",mDDot:"∺",measuredangle:"∡",MediumSpace:" ",Mellintrf:"ℳ",Mfr:"𝔐",mfr:"𝔪",mho:"℧",micro:"µ",midast:"*",midcir:"⫰",mid:"∣",middot:"·",minusb:"⊟",minus:"−",minusd:"∸",minusdu:"⨪",MinusPlus:"∓",mlcp:"⫛",mldr:"…",mnplus:"∓",models:"⊧",Mopf:"𝕄",mopf:"𝕞",mp:"∓",mscr:"𝓂",Mscr:"ℳ",mstpos:"∾",Mu:"Μ",mu:"μ",multimap:"⊸",mumap:"⊸",nabla:"∇",Nacute:"Ń",nacute:"ń",nang:"∠⃒",nap:"≉",napE:"⩰̸",napid:"≋̸",napos:"ʼn",napprox:"≉",natural:"♮",naturals:"ℕ",natur:"♮",nbsp:" ",nbump:"≎̸",nbumpe:"≏̸",ncap:"⩃",Ncaron:"Ň",ncaron:"ň",Ncedil:"Ņ",ncedil:"ņ",ncong:"≇",ncongdot:"⩭̸",ncup:"⩂",Ncy:"Н",ncy:"н",ndash:"–",nearhk:"⤤",nearr:"↗",neArr:"⇗",nearrow:"↗",ne:"≠",nedot:"≐̸",NegativeMediumSpace:"",NegativeThickSpace:"",NegativeThinSpace:"",NegativeVeryThinSpace:"",nequiv:"≢",nesear:"⤨",nesim:"≂̸",NestedGreaterGreater:"≫",NestedLessLess:"≪",NewLine:"\n",nexist:"∄",nexists:"∄",Nfr:"𝔑",nfr:"𝔫",ngE:"≧̸",nge:"≱",ngeq:"≱",ngeqq:"≧̸",ngeqslant:"⩾̸",nges:"⩾̸",nGg:"⋙̸",ngsim:"≵",nGt:"≫⃒",ngt:"≯",ngtr:"≯",nGtv:"≫̸",nharr:"↮",nhArr:"⇎",nhpar:"⫲",ni:"∋",nis:"⋼",nisd:"⋺",niv:"∋",NJcy:"Њ",njcy:"њ",nlarr:"↚",nlArr:"⇍",nldr:"‥",nlE:"≦̸",nle:"≰",nleftarrow:"↚",nLeftarrow:"⇍",nleftrightarrow:"↮",nLeftrightarrow:"⇎",nleq:"≰",nleqq:"≦̸",nleqslant:"⩽̸",nles:"⩽̸",nless:"≮",nLl:"⋘̸",nlsim:"≴",nLt:"≪⃒",nlt:"≮",nltri:"⋪",nltrie:"⋬",nLtv:"≪̸",nmid:"∤",NoBreak:"",NonBreakingSpace:" ",nopf:"𝕟",Nopf:"ℕ",Not:"⫬",not:"¬",NotCongruent:"≢",NotCupCap:"≭",NotDoubleVerticalBar:"∦",NotElement:"∉",NotEqual:"≠",NotEqualTilde:"≂̸",NotExists:"∄",NotGreater:"≯",NotGreaterEqual:"≱",NotGreaterFullEqual:"≧̸",NotGreaterGreater:"≫̸",NotGreaterLess:"≹",NotGreaterSlantEqual:"⩾̸",NotGreaterTilde:"≵",NotHumpDownHump:"≎̸",NotHumpEqual:"≏̸",notin:"∉",notindot:"⋵̸",notinE:"⋹̸",notinva:"∉",notinvb:"⋷",notinvc:"⋶",NotLeftTriangleBar:"⧏̸",NotLeftTriangle:"⋪",NotLeftTriangleEqual:"⋬",NotLess:"≮",NotLessEqual:"≰",NotLessGreater:"≸",NotLessLess:"≪̸",NotLessSlantEqual:"⩽̸",NotLessTilde:"≴",NotNestedGreaterGreater:"⪢̸",NotNestedLessLess:"⪡̸",notni:"∌",notniva:"∌",notnivb:"⋾",notnivc:"⋽",NotPrecedes:"⊀",NotPrecedesEqual:"⪯̸",NotPrecedesSlantEqual:"⋠",NotReverseElement:"∌",NotRightTriangleBar:"⧐̸",NotRightTriangle:"⋫",NotRightTriangleEqual:"⋭",NotSquareSubset:"⊏̸",NotSquareSubsetEqual:"⋢",NotSquareSuperset:"⊐̸",NotSquareSupersetEqual:"⋣",NotSubset:"⊂⃒",NotSubsetEqual:"⊈",NotSucceeds:"⊁",NotSucceedsEqual:"⪰̸",NotSucceedsSlantEqual:"⋡",NotSucceedsTilde:"≿̸",NotSuperset:"⊃⃒",NotSupersetEqual:"⊉",NotTilde:"≁",NotTildeEqual:"≄",NotTildeFullEqual:"≇",NotTildeTilde:"≉",NotVerticalBar:"∤",nparallel:"∦",npar:"∦",nparsl:"⫽⃥",npart:"∂̸",npolint:"⨔",npr:"⊀",nprcue:"⋠",nprec:"⊀",npreceq:"⪯̸",npre:"⪯̸",nrarrc:"⤳̸",nrarr:"↛",nrArr:"⇏",nrarrw:"↝̸",nrightarrow:"↛",nRightarrow:"⇏",nrtri:"⋫",nrtrie:"⋭",nsc:"⊁",nsccue:"⋡",nsce:"⪰̸",Nscr:"𝒩",nscr:"𝓃",nshortmid:"∤",nshortparallel:"∦",nsim:"≁",nsime:"≄",nsimeq:"≄",nsmid:"∤",nspar:"∦",nsqsube:"⋢",nsqsupe:"⋣",nsub:"⊄",nsubE:"⫅̸",nsube:"⊈",nsubset:"⊂⃒",nsubseteq:"⊈",nsubseteqq:"⫅̸",nsucc:"⊁",nsucceq:"⪰̸",nsup:"⊅",nsupE:"⫆̸",nsupe:"⊉",nsupset:"⊃⃒",nsupseteq:"⊉",nsupseteqq:"⫆̸",ntgl:"≹",Ntilde:"Ñ",ntilde:"ñ",ntlg:"≸",ntriangleleft:"⋪",ntrianglelefteq:"⋬",ntriangleright:"⋫",ntrianglerighteq:"⋭",Nu:"Ν",nu:"ν",num:"#",numero:"№",numsp:" ",nvap:"≍⃒",nvdash:"⊬",nvDash:"⊭",nVdash:"⊮",nVDash:"⊯",nvge:"≥⃒",nvgt:">⃒",nvHarr:"⤄",nvinfin:"⧞",nvlArr:"⤂",nvle:"≤⃒",nvlt:"<⃒",nvltrie:"⊴⃒",nvrArr:"⤃",nvrtrie:"⊵⃒",nvsim:"∼⃒",nwarhk:"⤣",nwarr:"↖",nwArr:"⇖",nwarrow:"↖",nwnear:"⤧",Oacute:"Ó",oacute:"ó",oast:"⊛",Ocirc:"Ô",ocirc:"ô",ocir:"⊚",Ocy:"О",ocy:"о",odash:"⊝",Odblac:"Ő",odblac:"ő",odiv:"⨸",odot:"⊙",odsold:"⦼",OElig:"Œ",oelig:"œ",ofcir:"⦿",Ofr:"𝔒",ofr:"𝔬",ogon:"˛",Ograve:"Ò",ograve:"ò",ogt:"⧁",ohbar:"⦵",ohm:"Ω",oint:"∮",olarr:"↺",olcir:"⦾",olcross:"⦻",oline:"‾",olt:"⧀",Omacr:"Ō",omacr:"ō",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",omid:"⦶",ominus:"⊖",Oopf:"𝕆",oopf:"𝕠",opar:"⦷",OpenCurlyDoubleQuote:"“",OpenCurlyQuote:"‘",operp:"⦹",oplus:"⊕",orarr:"↻",Or:"⩔",or:"∨",ord:"⩝",order:"ℴ",orderof:"ℴ",ordf:"ª",ordm:"º",origof:"⊶",oror:"⩖",orslope:"⩗",orv:"⩛",oS:"Ⓢ",Oscr:"𝒪",oscr:"ℴ",Oslash:"Ø",oslash:"ø",osol:"⊘",Otilde:"Õ",otilde:"õ",otimesas:"⨶",Otimes:"⨷",otimes:"⊗",Ouml:"Ö",ouml:"ö",ovbar:"⌽",OverBar:"‾",OverBrace:"⏞",OverBracket:"⎴",OverParenthesis:"⏜",para:"¶",parallel:"∥",par:"∥",parsim:"⫳",parsl:"⫽",part:"∂",PartialD:"∂",Pcy:"П",pcy:"п",percnt:"%",period:".",permil:"‰",perp:"⊥",pertenk:"‱",Pfr:"𝔓",pfr:"𝔭",Phi:"Φ",phi:"φ",phiv:"ϕ",phmmat:"ℳ",phone:"☎",Pi:"Π",pi:"π",pitchfork:"⋔",piv:"ϖ",planck:"ℏ",planckh:"ℎ",plankv:"ℏ",plusacir:"⨣",plusb:"⊞",pluscir:"⨢",plus:"+",plusdo:"∔",plusdu:"⨥",pluse:"⩲",PlusMinus:"±",plusmn:"±",plussim:"⨦",plustwo:"⨧",pm:"±",Poincareplane:"ℌ",pointint:"⨕",popf:"𝕡",Popf:"ℙ",pound:"£",prap:"⪷",Pr:"⪻",pr:"≺",prcue:"≼",precapprox:"⪷",prec:"≺",preccurlyeq:"≼",Precedes:"≺",PrecedesEqual:"⪯",PrecedesSlantEqual:"≼",PrecedesTilde:"≾",preceq:"⪯",precnapprox:"⪹",precneqq:"⪵",precnsim:"⋨",pre:"⪯",prE:"⪳",precsim:"≾",prime:"′",Prime:"″",primes:"ℙ",prnap:"⪹",prnE:"⪵",prnsim:"⋨",prod:"∏",Product:"∏",profalar:"⌮",profline:"⌒",profsurf:"⌓",prop:"∝",Proportional:"∝",Proportion:"∷",propto:"∝",prsim:"≾",prurel:"⊰",Pscr:"𝒫",pscr:"𝓅",Psi:"Ψ",psi:"ψ",puncsp:" ",Qfr:"𝔔",qfr:"𝔮",qint:"⨌",qopf:"𝕢",Qopf:"ℚ",qprime:"⁗",Qscr:"𝒬",qscr:"𝓆",quaternions:"ℍ",quatint:"⨖",quest:"?",questeq:"≟",quot:'"',QUOT:'"',rAarr:"⇛",race:"∽̱",Racute:"Ŕ",racute:"ŕ",radic:"√",raemptyv:"⦳",rang:"⟩",Rang:"⟫",rangd:"⦒",range:"⦥",rangle:"⟩",raquo:"»",rarrap:"⥵",rarrb:"⇥",rarrbfs:"⤠",rarrc:"⤳",rarr:"→",Rarr:"↠",rArr:"⇒",rarrfs:"⤞",rarrhk:"↪",rarrlp:"↬",rarrpl:"⥅",rarrsim:"⥴",Rarrtl:"⤖",rarrtl:"↣",rarrw:"↝",ratail:"⤚",rAtail:"⤜",ratio:"∶",rationals:"ℚ",rbarr:"⤍",rBarr:"⤏",RBarr:"⤐",rbbrk:"❳",rbrace:"}",rbrack:"]",rbrke:"⦌",rbrksld:"⦎",rbrkslu:"⦐",Rcaron:"Ř",rcaron:"ř",Rcedil:"Ŗ",rcedil:"ŗ",rceil:"⌉",rcub:"}",Rcy:"Р",rcy:"р",rdca:"⤷",rdldhar:"⥩",rdquo:"”",rdquor:"”",rdsh:"↳",real:"ℜ",realine:"ℛ",realpart:"ℜ",reals:"ℝ",Re:"ℜ",rect:"▭",reg:"®",REG:"®",ReverseElement:"∋",ReverseEquilibrium:"⇋",ReverseUpEquilibrium:"⥯",rfisht:"⥽",rfloor:"⌋",rfr:"𝔯",Rfr:"ℜ",rHar:"⥤",rhard:"⇁",rharu:"⇀",rharul:"⥬",Rho:"Ρ",rho:"ρ",rhov:"ϱ",RightAngleBracket:"⟩",RightArrowBar:"⇥",rightarrow:"→",RightArrow:"→",Rightarrow:"⇒",RightArrowLeftArrow:"⇄",rightarrowtail:"↣",RightCeiling:"⌉",RightDoubleBracket:"⟧",RightDownTeeVector:"⥝",RightDownVectorBar:"⥕",RightDownVector:"⇂",RightFloor:"⌋",rightharpoondown:"⇁",rightharpoonup:"⇀",rightleftarrows:"⇄",rightleftharpoons:"⇌",rightrightarrows:"⇉",rightsquigarrow:"↝",RightTeeArrow:"↦",RightTee:"⊢",RightTeeVector:"⥛",rightthreetimes:"⋌",RightTriangleBar:"⧐",RightTriangle:"⊳",RightTriangleEqual:"⊵",RightUpDownVector:"⥏",RightUpTeeVector:"⥜",RightUpVectorBar:"⥔",RightUpVector:"↾",RightVectorBar:"⥓",RightVector:"⇀",ring:"˚",risingdotseq:"≓",rlarr:"⇄",rlhar:"⇌",rlm:"",rmoustache:"⎱",rmoust:"⎱",rnmid:"⫮",roang:"⟭",roarr:"⇾",robrk:"⟧",ropar:"⦆",ropf:"𝕣",Ropf:"ℝ",roplus:"⨮",rotimes:"⨵",RoundImplies:"⥰",rpar:")",rpargt:"⦔",rppolint:"⨒",rrarr:"⇉",Rrightarrow:"⇛",rsaquo:"›",rscr:"𝓇",Rscr:"ℛ",rsh:"↱",Rsh:"↱",rsqb:"]",rsquo:"’",rsquor:"’",rthree:"⋌",rtimes:"⋊",rtri:"▹",rtrie:"⊵",rtrif:"▸",rtriltri:"⧎",RuleDelayed:"⧴",ruluhar:"⥨",rx:"℞",Sacute:"Ś",sacute:"ś",sbquo:"‚",scap:"⪸",Scaron:"Š",scaron:"š",Sc:"⪼",sc:"≻",sccue:"≽",sce:"⪰",scE:"⪴",Scedil:"Ş",scedil:"ş",Scirc:"Ŝ",scirc:"ŝ",scnap:"⪺",scnE:"⪶",scnsim:"⋩",scpolint:"⨓",scsim:"≿",Scy:"С",scy:"с",sdotb:"⊡",sdot:"⋅",sdote:"⩦",searhk:"⤥",searr:"↘",seArr:"⇘",searrow:"↘",sect:"§",semi:";",seswar:"⤩",setminus:"∖",setmn:"∖",sext:"✶",Sfr:"𝔖",sfr:"𝔰",sfrown:"⌢",sharp:"♯",SHCHcy:"Щ",shchcy:"щ",SHcy:"Ш",shcy:"ш",ShortDownArrow:"↓",ShortLeftArrow:"←",shortmid:"∣",shortparallel:"∥",ShortRightArrow:"→",ShortUpArrow:"↑",shy:"",Sigma:"Σ",sigma:"σ",sigmaf:"ς",sigmav:"ς",sim:"∼",simdot:"⩪",sime:"≃",simeq:"≃",simg:"⪞",simgE:"⪠",siml:"⪝",simlE:"⪟",simne:"≆",simplus:"⨤",simrarr:"⥲",slarr:"←",SmallCircle:"∘",smallsetminus:"∖",smashp:"⨳",smeparsl:"⧤",smid:"∣",smile:"⌣",smt:"⪪",smte:"⪬",smtes:"⪬︀",SOFTcy:"Ь",softcy:"ь",solbar:"⌿",solb:"⧄",sol:"/",Sopf:"𝕊",sopf:"𝕤",spades:"♠",spadesuit:"♠",spar:"∥",sqcap:"⊓",sqcaps:"⊓︀",sqcup:"⊔",sqcups:"⊔︀",Sqrt:"√",sqsub:"⊏",sqsube:"⊑",sqsubset:"⊏",sqsubseteq:"⊑",sqsup:"⊐",sqsupe:"⊒",sqsupset:"⊐",sqsupseteq:"⊒",square:"□",Square:"□",SquareIntersection:"⊓",SquareSubset:"⊏",SquareSubsetEqual:"⊑",SquareSuperset:"⊐",SquareSupersetEqual:"⊒",SquareUnion:"⊔",squarf:"▪",squ:"□",squf:"▪",srarr:"→",Sscr:"𝒮",sscr:"𝓈",ssetmn:"∖",ssmile:"⌣",sstarf:"⋆",Star:"⋆",star:"☆",starf:"★",straightepsilon:"ϵ",straightphi:"ϕ",strns:"¯",sub:"⊂",Sub:"⋐",subdot:"⪽",subE:"⫅",sube:"⊆",subedot:"⫃",submult:"⫁",subnE:"⫋",subne:"⊊",subplus:"⪿",subrarr:"⥹",subset:"⊂",Subset:"⋐",subseteq:"⊆",subseteqq:"⫅",SubsetEqual:"⊆",subsetneq:"⊊",subsetneqq:"⫋",subsim:"⫇",subsub:"⫕",subsup:"⫓",succapprox:"⪸",succ:"≻",succcurlyeq:"≽",Succeeds:"≻",SucceedsEqual:"⪰",SucceedsSlantEqual:"≽",SucceedsTilde:"≿",succeq:"⪰",succnapprox:"⪺",succneqq:"⪶",succnsim:"⋩",succsim:"≿",SuchThat:"∋",sum:"∑",Sum:"∑",sung:"♪",sup1:"¹",sup2:"²",sup3:"³",sup:"⊃",Sup:"⋑",supdot:"⪾",supdsub:"⫘",supE:"⫆",supe:"⊇",supedot:"⫄",Superset:"⊃",SupersetEqual:"⊇",suphsol:"⟉",suphsub:"⫗",suplarr:"⥻",supmult:"⫂",supnE:"⫌",supne:"⊋",supplus:"⫀",supset:"⊃",Supset:"⋑",supseteq:"⊇",supseteqq:"⫆",supsetneq:"⊋",supsetneqq:"⫌",supsim:"⫈",supsub:"⫔",supsup:"⫖",swarhk:"⤦",swarr:"↙",swArr:"⇙",swarrow:"↙",swnwar:"⤪",szlig:"ß",Tab:" ",target:"⌖",Tau:"Τ",tau:"τ",tbrk:"⎴",Tcaron:"Ť",tcaron:"ť",Tcedil:"Ţ",tcedil:"ţ",Tcy:"Т",tcy:"т",tdot:"⃛",telrec:"⌕",Tfr:"𝔗",tfr:"𝔱",there4:"∴",therefore:"∴",Therefore:"∴",Theta:"Θ",theta:"θ",thetasym:"ϑ",thetav:"ϑ",thickapprox:"≈",thicksim:"∼",ThickSpace:" ",ThinSpace:" ",thinsp:" ",thkap:"≈",thksim:"∼",THORN:"Þ",thorn:"þ",tilde:"˜",Tilde:"∼",TildeEqual:"≃",TildeFullEqual:"≅",TildeTilde:"≈",timesbar:"⨱",timesb:"⊠",times:"×",timesd:"⨰",tint:"∭",toea:"⤨",topbot:"⌶",topcir:"⫱",top:"⊤",Topf:"𝕋",topf:"𝕥",topfork:"⫚",tosa:"⤩",tprime:"‴",trade:"™",TRADE:"™",triangle:"▵",triangledown:"▿",triangleleft:"◃",trianglelefteq:"⊴",triangleq:"≜",triangleright:"▹",trianglerighteq:"⊵",tridot:"◬",trie:"≜",triminus:"⨺",TripleDot:"⃛",triplus:"⨹",trisb:"⧍",tritime:"⨻",trpezium:"⏢",Tscr:"𝒯",tscr:"𝓉",TScy:"Ц",tscy:"ц",TSHcy:"Ћ",tshcy:"ћ",Tstrok:"Ŧ",tstrok:"ŧ",twixt:"≬",twoheadleftarrow:"↞",twoheadrightarrow:"↠",Uacute:"Ú",uacute:"ú",uarr:"↑",Uarr:"↟",uArr:"⇑",Uarrocir:"⥉",Ubrcy:"Ў",ubrcy:"ў",Ubreve:"Ŭ",ubreve:"ŭ",Ucirc:"Û",ucirc:"û",Ucy:"У",ucy:"у",udarr:"⇅",Udblac:"Ű",udblac:"ű",udhar:"⥮",ufisht:"⥾",Ufr:"𝔘",ufr:"𝔲",Ugrave:"Ù",ugrave:"ù",uHar:"⥣",uharl:"↿",uharr:"↾",uhblk:"▀",ulcorn:"⌜",ulcorner:"⌜",ulcrop:"⌏",ultri:"◸",Umacr:"Ū",umacr:"ū",uml:"¨",UnderBar:"_",UnderBrace:"⏟",UnderBracket:"⎵",UnderParenthesis:"⏝",Union:"⋃",UnionPlus:"⊎",Uogon:"Ų",uogon:"ų",Uopf:"𝕌",uopf:"𝕦",UpArrowBar:"⤒",uparrow:"↑",UpArrow:"↑",Uparrow:"⇑",UpArrowDownArrow:"⇅",updownarrow:"↕",UpDownArrow:"↕",Updownarrow:"⇕",UpEquilibrium:"⥮",upharpoonleft:"↿",upharpoonright:"↾",uplus:"⊎",UpperLeftArrow:"↖",UpperRightArrow:"↗",upsi:"υ",Upsi:"ϒ",upsih:"ϒ",Upsilon:"Υ",upsilon:"υ",UpTeeArrow:"↥",UpTee:"⊥",upuparrows:"⇈",urcorn:"⌝",urcorner:"⌝",urcrop:"⌎",Uring:"Ů",uring:"ů",urtri:"◹",Uscr:"𝒰",uscr:"𝓊",utdot:"⋰",Utilde:"Ũ",utilde:"ũ",utri:"▵",utrif:"▴",uuarr:"⇈",Uuml:"Ü",uuml:"ü",uwangle:"⦧",vangrt:"⦜",varepsilon:"ϵ",varkappa:"ϰ",varnothing:"∅",varphi:"ϕ",varpi:"ϖ",varpropto:"∝",varr:"↕",vArr:"⇕",varrho:"ϱ",varsigma:"ς",varsubsetneq:"⊊︀",varsubsetneqq:"⫋︀",varsupsetneq:"⊋︀",varsupsetneqq:"⫌︀",vartheta:"ϑ",vartriangleleft:"⊲",vartriangleright:"⊳",vBar:"⫨",Vbar:"⫫",vBarv:"⫩",Vcy:"В",vcy:"в",vdash:"⊢",vDash:"⊨",Vdash:"⊩",VDash:"⊫",Vdashl:"⫦",veebar:"⊻",vee:"∨",Vee:"⋁",veeeq:"≚",vellip:"⋮",verbar:"|",Verbar:"‖",vert:"|",Vert:"‖",VerticalBar:"∣",VerticalLine:"|",VerticalSeparator:"❘",VerticalTilde:"≀",VeryThinSpace:" ",Vfr:"𝔙",vfr:"𝔳",vltri:"⊲",vnsub:"⊂⃒",vnsup:"⊃⃒",Vopf:"𝕍",vopf:"𝕧",vprop:"∝",vrtri:"⊳",Vscr:"𝒱",vscr:"𝓋",vsubnE:"⫋︀",vsubne:"⊊︀",vsupnE:"⫌︀",vsupne:"⊋︀",Vvdash:"⊪",vzigzag:"⦚",Wcirc:"Ŵ",wcirc:"ŵ",wedbar:"⩟",wedge:"∧",Wedge:"⋀",wedgeq:"≙",weierp:"℘",Wfr:"𝔚",wfr:"𝔴",Wopf:"𝕎",wopf:"𝕨",wp:"℘",wr:"≀",wreath:"≀",Wscr:"𝒲",wscr:"𝓌",xcap:"⋂",xcirc:"◯",xcup:"⋃",xdtri:"▽",Xfr:"𝔛",xfr:"𝔵",xharr:"⟷",xhArr:"⟺",Xi:"Ξ",xi:"ξ",xlarr:"⟵",xlArr:"⟸",xmap:"⟼",xnis:"⋻",xodot:"⨀",Xopf:"𝕏",xopf:"𝕩",xoplus:"⨁",xotime:"⨂",xrarr:"⟶",xrArr:"⟹",Xscr:"𝒳",xscr:"𝓍",xsqcup:"⨆",xuplus:"⨄",xutri:"△",xvee:"⋁",xwedge:"⋀",Yacute:"Ý",yacute:"ý",YAcy:"Я",yacy:"я",Ycirc:"Ŷ",ycirc:"ŷ",Ycy:"Ы",ycy:"ы",yen:"¥",Yfr:"𝔜",yfr:"𝔶",YIcy:"Ї",yicy:"ї",Yopf:"𝕐",yopf:"𝕪",Yscr:"𝒴",yscr:"𝓎",YUcy:"Ю",yucy:"ю",yuml:"ÿ",Yuml:"Ÿ",Zacute:"Ź",zacute:"ź",Zcaron:"Ž",zcaron:"ž",Zcy:"З",zcy:"з",Zdot:"Ż",zdot:"ż",zeetrf:"ℨ",ZeroWidthSpace:"",Zeta:"Ζ",zeta:"ζ",zfr:"𝔷",Zfr:"ℨ",ZHcy:"Ж",zhcy:"ж",zigrarr:"⇝",zopf:"𝕫",Zopf:"ℤ",Zscr:"𝒵",zscr:"𝓏",zwj:"",zwnj:""}
+},{}],16:[function(require,module,exports){module.exports={Aacute:"Á",aacute:"á",Acirc:"Â",acirc:"â",acute:"´",AElig:"Æ",aelig:"æ",Agrave:"À",agrave:"à",amp:"&",AMP:"&",Aring:"Å",aring:"å",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",brvbar:"¦",Ccedil:"Ç",ccedil:"ç",cedil:"¸",cent:"¢",copy:"©",COPY:"©",curren:"¤",deg:"°",divide:"÷",Eacute:"É",eacute:"é",Ecirc:"Ê",ecirc:"ê",Egrave:"È",egrave:"è",ETH:"Ð",eth:"ð",Euml:"Ë",euml:"ë",frac12:"½",frac14:"¼",frac34:"¾",gt:">",GT:">",Iacute:"Í",iacute:"í",Icirc:"Î",icirc:"î",iexcl:"¡",Igrave:"Ì",igrave:"ì",iquest:"¿",Iuml:"Ï",iuml:"ï",laquo:"«",lt:"<",LT:"<",macr:"¯",micro:"µ",middot:"·",nbsp:" ",not:"¬",Ntilde:"Ñ",ntilde:"ñ",Oacute:"Ó",oacute:"ó",Ocirc:"Ô",ocirc:"ô",Ograve:"Ò",ograve:"ò",ordf:"ª",ordm:"º",Oslash:"Ø",oslash:"ø",Otilde:"Õ",otilde:"õ",Ouml:"Ö",ouml:"ö",para:"¶",plusmn:"±",pound:"£",quot:'"',QUOT:'"',raquo:"»",reg:"®",REG:"®",sect:"§",shy:"",sup1:"¹",sup2:"²",sup3:"³",szlig:"ß",THORN:"Þ",thorn:"þ",times:"×",Uacute:"Ú",uacute:"ú",Ucirc:"Û",ucirc:"û",Ugrave:"Ù",ugrave:"ù",uml:"¨",Uuml:"Ü",uuml:"ü",Yacute:"Ý",yacute:"ý",yen:"¥",yuml:"ÿ"}},{}],17:[function(require,module,exports){module.exports={amp:"&",apos:"'",gt:">",lt:"<",quot:'"'}},{}],18:[function(require,module,exports){"use strict";function getDecodeCache(exclude){var i,ch,cache=decodeCache[exclude];if(cache)return cache;for(cache=decodeCache[exclude]=[],i=0;128>i;i++)ch=String.fromCharCode(i),cache.push(ch);for(i=0;exclude.length>i;i++)ch=exclude.charCodeAt(i),cache[ch]="%"+("0"+ch.toString(16).toUpperCase()).slice(-2);return cache}function decode(string,exclude){var cache;return"string"!=typeof exclude&&(exclude=decode.defaultChars),cache=getDecodeCache(exclude),string.replace(/(%[a-f0-9]{2})+/gi,function(seq){var i,l,b1,b2,b3,b4,char,result="";for(i=0,l=seq.length;l>i;i+=3)b1=parseInt(seq.slice(i+1,i+3),16),128>b1?result+=cache[b1]:192===(224&b1)&&l>i+3&&(b2=parseInt(seq.slice(i+4,i+6),16),128===(192&b2))?(char=b1<<6&1984|63&b2,result+=128>char?"��":String.fromCharCode(char),i+=3):224===(240&b1)&&l>i+6&&(b2=parseInt(seq.slice(i+4,i+6),16),b3=parseInt(seq.slice(i+7,i+9),16),128===(192&b2)&&128===(192&b3))?(char=b1<<12&61440|b2<<6&4032|63&b3,result+=2048>char||char>=55296&&57343>=char?"���":String.fromCharCode(char),i+=6):240===(248&b1)&&l>i+9&&(b2=parseInt(seq.slice(i+4,i+6),16),b3=parseInt(seq.slice(i+7,i+9),16),b4=parseInt(seq.slice(i+10,i+12),16),128===(192&b2)&&128===(192&b3)&&128===(192&b4))?(char=b1<<18&1835008|b2<<12&258048|b3<<6&4032|63&b4,65536>char||char>1114111?result+="����":(char-=65536,result+=String.fromCharCode(55296+(char>>10),56320+(1023&char))),i+=9):result+="�";return result})}var decodeCache={};decode.defaultChars=";/?:@&=+$,#",decode.componentChars="",module.exports=decode},{}],19:[function(require,module,exports){"use strict";function getEncodeCache(exclude){var i,ch,cache=encodeCache[exclude];if(cache)return cache;for(cache=encodeCache[exclude]=[],i=0;128>i;i++)ch=String.fromCharCode(i),cache.push(/^[0-9a-z]$/i.test(ch)?ch:"%"+("0"+i.toString(16).toUpperCase()).slice(-2));for(i=0;exclude.length>i;i++)cache[exclude.charCodeAt(i)]=exclude[i];return cache}function encode(string,exclude,keepEscaped){var i,l,code,nextCode,cache,result="";for("string"!=typeof exclude&&(keepEscaped=exclude,exclude=encode.defaultChars),"undefined"==typeof keepEscaped&&(keepEscaped=!0),cache=getEncodeCache(exclude),i=0,l=string.length;l>i;i++)if(code=string.charCodeAt(i),keepEscaped&&37===code&&l>i+2&&/^[0-9a-f]{2}$/i.test(string.slice(i+1,i+3)))result+=string.slice(i,i+3),i+=2;else if(128>code)result+=cache[code];else if(code>=55296&&57343>=code){if(code>=55296&&56319>=code&&l>i+1&&(nextCode=string.charCodeAt(i+1),nextCode>=56320&&57343>=nextCode)){result+=encodeURIComponent(string[i]+string[i+1]),i++;continue}result+="%EF%BF%BD"}else result+=encodeURIComponent(string[i]);return result}var encodeCache={};encode.defaultChars=";/?:@&=+$,-_.!~*'()#",encode.componentChars="-_.!~*'()",module.exports=encode},{}],20:[function(require,module,exports){String.prototype.repeat||!function(){"use strict";var defineProperty=function(){try{var object={},$defineProperty=Object.defineProperty,result=$defineProperty(object,object,object)&&$defineProperty}catch(error){}return result}(),repeat=function(count){if(null==this)throw TypeError();var string=String(this),n=count?Number(count):0;if(n!=n&&(n=0),0>n||1/0==n)throw RangeError();for(var result="";n;)n%2==1&&(result+=string),n>1&&(string+=string),n>>=1;return result};defineProperty?defineProperty(String.prototype,"repeat",{value:repeat,configurable:!0,writable:!0}):String.prototype.repeat=repeat}()},{}]},{},[5])(5)});
\ No newline at end of file
diff --git a/js/vendor/dompurify/purify.js b/js/vendor/dompurify/purify.js
new file mode 100644
index 0000000000..552eaafe33
--- /dev/null
+++ b/js/vendor/dompurify/purify.js
@@ -0,0 +1,694 @@
+;(function(factory) {
+ 'use strict';
+ /* global window: false, define: false, module: false */
+ var root = typeof window === 'undefined' ? null : window;
+
+ if (typeof define === 'function' && define.amd) {
+ define(function(){ return factory(root); });
+ } else if (typeof module !== 'undefined') {
+ module.exports = factory(root);
+ } else {
+ root.DOMPurify = factory(root);
+ }
+}(function factory(window) {
+ 'use strict';
+
+ var DOMPurify = function(window) {
+ return factory(window);
+ };
+
+ /**
+ * Version label, exposed for easier checks
+ * if DOMPurify is up to date or not
+ */
+ DOMPurify.version = '0.6.5';
+
+ if (!window || !window.document || window.document.nodeType !== 9) {
+ // not running in a browser, provide a factory function
+ // so that you can pass your own Window
+ DOMPurify.isSupported = false;
+ return DOMPurify;
+ }
+
+ var document = window.document;
+ var originalDocument = document;
+ var DocumentFragment = window.DocumentFragment;
+ var HTMLTemplateElement = window.HTMLTemplateElement;
+ var NodeFilter = window.NodeFilter;
+ var NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap;
+ var Text = window.Text;
+ var Comment = window.Comment;
+
+ // As per issue #47, the web-components registry is inherited by a
+ // new document created via createHTMLDocument. As per the spec
+ // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
+ // a new empty registry is used when creating a template contents owner
+ // document, so we use that as our parent document to ensure nothing
+ // is inherited.
+ if (typeof HTMLTemplateElement === 'function') {
+ document = document.createElement('template').content.ownerDocument;
+ }
+ var implementation = document.implementation;
+ var createNodeIterator = document.createNodeIterator;
+ var getElementsByTagName = document.getElementsByTagName;
+ var createDocumentFragment = document.createDocumentFragment;
+ var importNode = originalDocument.importNode;
+
+ var hooks = {};
+
+ /**
+ * Expose whether this browser supports running the full DOMPurify.
+ */
+ DOMPurify.isSupported =
+ typeof implementation.createHTMLDocument !== 'undefined' &&
+ document.documentMode !== 9;
+
+ /* Add properties to a lookup table */
+ var _addToSet = function(set, array) {
+ var l = array.length;
+ while (l--) {
+ set[array[l]] = true;
+ }
+ return set;
+ };
+
+ /* Shallow clone an object */
+ var _cloneObj = function(object) {
+ var newObject = {};
+ var property;
+ for (property in object) {
+ if (object.hasOwnProperty(property)) {
+ newObject[property] = object[property];
+ }
+ }
+ return newObject;
+ };
+
+ /**
+ * We consider the elements and attributes below to be safe. Ideally
+ * don't add any new ones but feel free to remove unwanted ones.
+ */
+
+ /* allowed element names */
+ var ALLOWED_TAGS = null;
+ var DEFAULT_ALLOWED_TAGS = _addToSet({}, [
+
+ // HTML
+ 'a','abbr','acronym','address','area','article','aside','audio','b',
+ 'bdi','bdo','big','blink','blockquote','body','br','button','canvas',
+ 'caption','center','cite','code','col','colgroup','content','data',
+ 'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',
+ 'element','em','fieldset','figcaption','figure','font','footer','form',
+ 'h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','i',
+ 'img','input','ins','kbd','label','legend','li','main','map','mark',
+ 'marquee','menu','menuitem','meter','nav','nobr','ol','optgroup',
+ 'option','output','p','pre','progress','q','rp','rt','ruby','s','samp',
+ 'section','select','shadow','small','source','spacer','span','strike',
+ 'strong','style','sub','summary','sup','table','tbody','td','template',
+ 'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',
+ 'video','wbr',
+
+ // SVG
+ 'svg','altglyph','altglyphdef','altglyphitem','animatecolor',
+ 'animatemotion','animatetransform','circle','clippath','defs','desc',
+ 'ellipse','font','g','glyph','glyphref','hkern','image','line',
+ 'lineargradient','marker','mask','metadata','mpath','path','pattern',
+ 'polygon','polyline','radialgradient','rect','stop','switch','symbol',
+ 'text','textpath','title','tref','tspan','view','vkern',
+
+ //MathML
+ 'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',
+ 'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',
+ 'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',
+ 'mtext','mtr','munder','munderover',
+
+ //Text
+ '#text'
+ ]);
+
+ /* Allowed attribute names */
+ var ALLOWED_ATTR = null;
+ var DEFAULT_ALLOWED_ATTR = _addToSet({}, [
+
+ // HTML
+ 'accept','action','align','alt','autocomplete','background','bgcolor',
+ 'border','cellpadding','cellspacing','checked','cite','class','clear','color',
+ 'cols','colspan','coords','datetime','default','dir','disabled',
+ 'download','enctype','face','for','headers','height','hidden','high','href',
+ 'hreflang','id','ismap','label','lang','list','loop', 'low','max',
+ 'maxlength','media','method','min','multiple','name','noshade','novalidate',
+ 'nowrap','open','optimum','pattern','placeholder','poster','preload','pubdate',
+ 'radiogroup','readonly','rel','required','rev','reversed','rows',
+ 'rowspan','spellcheck','scope','selected','shape','size','span',
+ 'srclang','start','src','step','style','summary','tabindex','title',
+ 'type','usemap','valign','value','width','xmlns',
+
+ // SVG
+ 'accent-height','accumulate','additivive','alignment-baseline',
+ 'ascent','azimuth','baseline-shift','bias','clip','clip-path',
+ 'clip-rule','color','color-interpolation','color-interpolation-filters',
+ 'color-profile','color-rendering','cx','cy','d','dy','dy','direction',
+ 'display','divisor','dur','elevation','end','fill','fill-opacity',
+ 'fill-rule','filter','flood-color','flood-opacity','font-family',
+ 'font-size','font-size-adjust','font-stretch','font-style','font-variant',
+ 'font-weight','image-rendering','in','in2','k1','k2','k3','k4','kerning',
+ 'letter-spacing','lighting-color','local','marker-end','marker-mid',
+ 'marker-start','max','mask','mode','min','offset','operator','opacity',
+ 'order','overflow','paint-order','path','points','r','rx','ry','radius',
+ 'restart','scale','seed','shape-rendering','stop-color','stop-opacity',
+ 'stroke-dasharray','stroke-dashoffset','stroke-linecap','stroke-linejoin',
+ 'stroke-miterlimit','stroke-opacity','stroke','stroke-width','transform',
+ 'text-anchor','text-decoration','text-rendering','u1','u2','viewbox',
+ 'visibility','word-spacing','wrap','writing-mode','x','x1','x2','y',
+ 'y1','y2','z',
+
+ // MathML
+ 'accent','accentunder','bevelled','close','columnsalign','columnlines',
+ 'columnspan','denomalign','depth','display','displaystyle','fence',
+ 'frame','largeop','length','linethickness','lspace','lquote',
+ 'mathbackground','mathcolor','mathsize','mathvariant','maxsize',
+ 'minsize','movablelimits','notation','numalign','open','rowalign',
+ 'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',
+ 'scriptminsize','scriptsizemultiplier','selection','separator',
+ 'separators','stretchy','subscriptshift','supscriptshift','symmetric',
+ 'voffset',
+
+ // XML
+ 'xlink:href','xml:id','xlink:title','xml:space'
+ ]);
+
+ /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
+ var FORBID_TAGS = null;
+
+ /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
+ var FORBID_ATTR = null;
+
+ /* Decide if custom data attributes are okay */
+ var ALLOW_DATA_ATTR = true;
+
+ /* Output should be safe for jQuery's $() factory? */
+ var SAFE_FOR_JQUERY = false;
+
+ /* Decide if document with ... should be returned */
+ var WHOLE_DOCUMENT = false;
+
+ /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.
+ * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
+ */
+ var RETURN_DOM = false;
+
+ /* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */
+ var RETURN_DOM_FRAGMENT = false;
+
+ /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
+ * `Node` is imported into the current `Document`. If this flag is not enabled the
+ * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
+ * DOMPurify. */
+ var RETURN_DOM_IMPORT = false;
+
+ /* Output should be free from DOM clobbering attacks? */
+ var SANITIZE_DOM = true;
+
+ /* Keep element content when removing element? */
+ var KEEP_CONTENT = true;
+
+ /* Tags to ignore content of when KEEP_CONTENT is true */
+ var FORBID_CONTENTS = _addToSet({}, [
+ 'audio', 'head', 'math', 'script', 'style', 'svg', 'video'
+ ]);
+
+ /* Keep a reference to config to pass to hooks */
+ var CONFIG = null;
+
+ /* Ideally, do not touch anything below this line */
+ /* ______________________________________________ */
+
+ var formElement = document.createElement('form');
+
+ /**
+ * _parseConfig
+ *
+ * @param optional config literal
+ */
+ var _parseConfig = function(cfg) {
+ /* Shield configuration object from tampering */
+ if (typeof cfg !== 'object') {
+ cfg = {};
+ }
+
+ /* Set configuration parameters */
+ ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ?
+ _addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
+ ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ?
+ _addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
+ FORBID_TAGS = 'FORBID_TAGS' in cfg ?
+ _addToSet({}, cfg.FORBID_TAGS) : {};
+ FORBID_ATTR = 'FORBID_ATTR' in cfg ?
+ _addToSet({}, cfg.FORBID_ATTR) : {};
+ ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
+ SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
+ WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
+ RETURN_DOM = cfg.RETURN_DOM || false; // Default false
+ RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
+ RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
+ SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
+ KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
+
+ if (RETURN_DOM_FRAGMENT) {
+ RETURN_DOM = true;
+ }
+
+ /* Merge configuration parameters */
+ if (cfg.ADD_TAGS) {
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
+ ALLOWED_TAGS = _cloneObj(ALLOWED_TAGS);
+ }
+ _addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
+ }
+ if (cfg.ADD_ATTR) {
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
+ ALLOWED_ATTR = _cloneObj(ALLOWED_ATTR);
+ }
+ _addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
+ }
+
+ /* Add #text in case KEEP_CONTENT is set to true */
+ if (KEEP_CONTENT) { ALLOWED_TAGS['#text'] = true; }
+
+ // Prevent further manipulation of configuration.
+ // Not available in IE8, Safari 5, etc.
+ if (Object && 'freeze' in Object) { Object.freeze(cfg); }
+
+ CONFIG = cfg;
+ };
+
+ /**
+ * _forceRemove
+ *
+ * @param a DOM node
+ */
+ var _forceRemove = function(node) {
+ try {
+ node.parentNode.removeChild(node);
+ } catch (e) {
+ node.outerHTML = '';
+ }
+ };
+
+ /**
+ * _initDocument
+ *
+ * @param a string of dirty markup
+ * @return a DOM, filled with the dirty markup
+ */
+ var _initDocument = function(dirty) {
+ /* Create new document to parse markup to */
+ var doc = implementation.createHTMLDocument('');
+
+ /* Set content */
+ var body = doc.body;
+ body.parentNode.removeChild(body.parentNode.firstElementChild);
+ body.outerHTML = dirty;
+
+ /* Work on whole document or just its body */
+ return getElementsByTagName.call(doc,
+ WHOLE_DOCUMENT ? 'html' : 'body')[0];
+ };
+
+ /**
+ * _createIterator
+ *
+ * @param document/fragment to create iterator for
+ * @return iterator instance
+ */
+ var _createIterator = function(root) {
+ return createNodeIterator.call(root.ownerDocument || root,
+ root,
+ NodeFilter.SHOW_ELEMENT
+ | NodeFilter.SHOW_COMMENT
+ | NodeFilter.SHOW_TEXT,
+ function() { return NodeFilter.FILTER_ACCEPT; },
+ false
+ );
+ };
+
+ /**
+ * _isClobbered
+ *
+ * @param element to check for clobbering attacks
+ * @return true if clobbered, false if safe
+ */
+ var _isClobbered = function(elm) {
+ if (elm instanceof Text || elm instanceof Comment) {
+ return false;
+ }
+ if ( typeof elm.nodeName !== 'string'
+ || typeof elm.textContent !== 'string'
+ || typeof elm.removeChild !== 'function'
+ || !(elm.attributes instanceof NamedNodeMap)
+ || typeof elm.removeAttribute !== 'function'
+ || typeof elm.setAttribute !== 'function'
+ ) {
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * _sanitizeElements
+ *
+ * @protect nodeName
+ * @protect textContent
+ * @protect removeChild
+ *
+ * @param node to check for permission to exist
+ * @return true if node was killed, false if left alive
+ */
+ var _sanitizeElements = function(currentNode) {
+ /* Execute a hook if present */
+ _executeHook('beforeSanitizeElements', currentNode, null);
+
+ /* Check if element is clobbered or can clobber */
+ if (_isClobbered(currentNode)) {
+ _forceRemove(currentNode);
+ return true;
+ }
+
+ /* Now let's check the element's type and name */
+ var tagName = currentNode.nodeName.toLowerCase();
+
+ /* Execute a hook if present */
+ _executeHook('uponSanitizeElement', currentNode, {
+ tagName: tagName
+ });
+
+ /* Remove element if anything forbids its presence */
+ if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
+ /* Keep content except for black-listed elements */
+ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
+ && typeof currentNode.insertAdjacentHTML === 'function') {
+ try {
+ currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);
+ } catch (e) {}
+ }
+ _forceRemove(currentNode);
+ return true;
+ }
+
+ /* Finally, convert markup to cover jQuery behavior */
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild) {
+ currentNode.innerHTML = currentNode.textContent.replace(/ tag that has an "id"
+ // attribute at the time.
+ if (lcName === 'name' &&
+ currentNode.nodeName === 'IMG' && attributes.id) {
+ idAttr = attributes.id;
+ attributes = Array.prototype.slice.apply(attributes);
+ currentNode.removeAttribute('id');
+ currentNode.removeAttribute(name);
+ if (attributes.indexOf(idAttr) > l) {
+ currentNode.setAttribute('id', idAttr.value);
+ }
+ } else {
+ currentNode.removeAttribute(name);
+ }
+
+ /* Did the hooks approve of the attribute? */
+ if (!hookEvent.keepAttr) {
+ continue;
+ }
+
+ /* Make sure attribute cannot clobber */
+ if (SANITIZE_DOM &&
+ (lcName === 'id' || lcName === 'name') &&
+ (value in window || value in document || value in formElement)) {
+ continue;
+ }
+
+ if (
+ /* Check the name is permitted */
+ (
+ (ALLOWED_ATTR[lcName] && !FORBID_ATTR[lcName]) ||
+ /* Allow potentially valid data-* attributes
+ * At least one character after "-" (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
+ * XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) */
+ (ALLOW_DATA_ATTR && DATA_ATTR.test(lcName))
+ ) &&
+ /* Get rid of script and data URIs */
+ (
+ !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE,'')) ||
+ /* Keep image data URIs alive if src is allowed */
+ (lcName === 'src' && value.indexOf('data:') === 0 &&
+ currentNode.nodeName === 'IMG')
+ )
+ ) {
+ /* Handle invalid data-* attribute set by try-catching it */
+ try {
+ currentNode.setAttribute(name, value);
+ } catch (e) {}
+ }
+ }
+
+ /* Execute a hook if present */
+ _executeHook('afterSanitizeAttributes', currentNode, null);
+ };
+ var DATA_ATTR = /^data-[\w.\u00B7-\uFFFF-]/;
+ var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
+ /* This needs to be extensive thanks to Webkit/Blink's behavior */
+ var ATTR_WHITESPACE = /[\x00-\x20\xA0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
+
+ /**
+ * _sanitizeShadowDOM
+ *
+ * @param fragment to iterate over recursively
+ * @return void
+ */
+ var _sanitizeShadowDOM = function(fragment) {
+ var shadowNode;
+ var shadowIterator = _createIterator(fragment);
+
+ /* Execute a hook if present */
+ _executeHook('beforeSanitizeShadowDOM', fragment, null);
+
+ while ( (shadowNode = shadowIterator.nextNode()) ) {
+ /* Execute a hook if present */
+ _executeHook('uponSanitizeShadowNode', shadowNode, null);
+
+ /* Sanitize tags and elements */
+ if (_sanitizeElements(shadowNode)) {
+ continue;
+ }
+
+ /* Deep shadow DOM detected */
+ if (shadowNode.content instanceof DocumentFragment) {
+ _sanitizeShadowDOM(shadowNode.content);
+ }
+
+ /* Check attributes, sanitize if necessary */
+ _sanitizeAttributes(shadowNode);
+ }
+
+ /* Execute a hook if present */
+ _executeHook('afterSanitizeShadowDOM', fragment, null);
+ };
+
+ /**
+ * _executeHook
+ * Execute user configurable hooks
+ *
+ * @param {String} entryPoint Name of the hook's entry point
+ * @param {Node} currentNode
+ */
+ var _executeHook = function(entryPoint, currentNode, data) {
+ if (!hooks[entryPoint]) { return; }
+
+ hooks[entryPoint].forEach(function(hook) {
+ hook.call(DOMPurify, currentNode, data, CONFIG);
+ });
+ };
+
+ /**
+ * sanitize
+ * Public method providing core sanitation functionality
+ *
+ * @param {String} dirty string
+ * @param {Object} configuration object
+ */
+ DOMPurify.sanitize = function(dirty, cfg) {
+ /* Check we can run. Otherwise fall back or ignore */
+ if (!DOMPurify.isSupported) {
+ if (typeof window.toStaticHTML === 'function' && typeof dirty === 'string') {
+ return window.toStaticHTML(dirty);
+ }
+ return dirty;
+ }
+
+ /* Assign config vars */
+ _parseConfig(cfg);
+
+ /* Exit directly if we have nothing to do */
+ if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
+ return dirty;
+ }
+
+ /* Initialize the document to work on */
+ var body = _initDocument(dirty);
+
+ /* Check we have a DOM node from the data */
+ if (!body) {
+ return RETURN_DOM ? null : '';
+ }
+
+ /* Get node iterator */
+ var currentNode;
+ var nodeIterator = _createIterator(body);
+
+ /* Now start iterating over the created document */
+ while ( (currentNode = nodeIterator.nextNode()) ) {
+ /* Sanitize tags and elements */
+ if (_sanitizeElements(currentNode)) {
+ continue;
+ }
+
+ /* Shadow DOM detected, sanitize it */
+ if (currentNode.content instanceof DocumentFragment) {
+ _sanitizeShadowDOM(currentNode.content);
+ }
+
+ /* Check attributes, sanitize if necessary */
+ _sanitizeAttributes(currentNode);
+ }
+
+ /* Return sanitized string or DOM */
+ var returnNode;
+ if (RETURN_DOM) {
+
+ if (RETURN_DOM_FRAGMENT) {
+ returnNode = createDocumentFragment.call(body.ownerDocument);
+
+ while (body.firstChild) {
+ returnNode.appendChild(body.firstChild);
+ }
+ } else {
+ returnNode = body;
+ }
+
+ if (RETURN_DOM_IMPORT) {
+ /* adoptNode() is not used because internal state is not reset
+ (e.g. the past names map of a HTMLFormElement), this is safe
+ in theory but we would rather not risk another attack vector.
+ The state that is cloned by importNode() is explicitly defined
+ by the specs. */
+ returnNode = importNode.call(originalDocument, returnNode, true);
+ }
+
+ return returnNode;
+ }
+
+ return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
+ };
+
+ /**
+ * addHook
+ * Public method to add DOMPurify hooks
+ *
+ * @param {String} entryPoint
+ * @param {Function} hookFunction
+ */
+ DOMPurify.addHook = function(entryPoint, hookFunction) {
+ if (typeof hookFunction !== 'function') { return; }
+ hooks[entryPoint] = hooks[entryPoint] || [];
+ hooks[entryPoint].push(hookFunction);
+ };
+
+ /**
+ * removeHook
+ * Public method to remove a DOMPurify hook at a given entryPoint
+ * (pops it from the stack of hooks if more are present)
+ *
+ * @param {String} entryPoint
+ * @return void
+ */
+ DOMPurify.removeHook = function(entryPoint) {
+ if (hooks[entryPoint]) {
+ hooks[entryPoint].pop();
+ }
+ };
+
+ /**
+ * removeHooks
+ * Public method to remove all DOMPurify hooks at a given entryPoint
+ *
+ * @param {String} entryPoint
+ * @return void
+ */
+ DOMPurify.removeHooks = function(entryPoint) {
+ if (hooks[entryPoint]) {
+ hooks[entryPoint] = [];
+ }
+ };
+
+ /**
+ * removeAllHooks
+ * Public method to remove all DOMPurify hooks
+ *
+ * @return void
+ */
+ DOMPurify.removeAllHooks = function() {
+ hooks = [];
+ };
+
+ return DOMPurify;
+}));
diff --git a/js/vendor/eventsource-polyfill/.bower.json b/js/vendor/eventsource-polyfill/.bower.json
deleted file mode 100644
index 86a5d3d5c9..0000000000
--- a/js/vendor/eventsource-polyfill/.bower.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "name": "eventsource-polyfill",
- "homepage": "https://github.com/amvtek/EventSource",
- "authors": [
- "amvtek
](http://sindresorhus.com/github-markdown-css)
-
-## [Demo](http://sindresorhus.com/github-markdown-css)
-
-
-## Install
-
-Download [manually](https://raw.githubusercontent.com/sindresorhus/github-markdown-css/gh-pages/github-markdown.css) or with a package-manager.
-
-```sh
-$ npm install --save github-markdown-css
-```
-
-```sh
-$ bower install --save github-markdown-css
-```
-
-
-## Usage
-
-Import the `github-markdown.css` file and add a `markdown-body` class to the container of your rendered Markdown and set a width for it. GitHub uses `790px` width and `30px` padding.
-
-```html
-
-
-Unicorns
-
-
-
-
-
- heading+
-
-```
-
-#### Block level renderer methods
-
-- code(*string* code, *string* language)
-- blockquote(*string* quote)
-- html(*string* html)
-- heading(*string* text, *number* level)
-- hr()
-- list(*string* body, *boolean* ordered)
-- listitem(*string* text)
-- paragraph(*string* text)
-- table(*string* header, *string* body)
-- tablerow(*string* content)
-- tablecell(*string* content, *object* flags)
-
-`flags` has the following properties:
-
-```js
-{
- header: true || false,
- align: 'center' || 'left' || 'right'
-}
-```
-
-#### Inline level renderer methods
-
-- strong(*string* text)
-- em(*string* text)
-- codespan(*string* code)
-- br()
-- del(*string* text)
-- link(*string* href, *string* title, *string* text)
-- image(*string* href, *string* title, *string* text)
-
-### gfm
-
-Type: `boolean`
-Default: `true`
-
-Enable [GitHub flavored markdown][gfm].
-
-### tables
-
-Type: `boolean`
-Default: `true`
-
-Enable GFM [tables][tables].
-This option requires the `gfm` option to be true.
-
-### breaks
-
-Type: `boolean`
-Default: `false`
-
-Enable GFM [line breaks][breaks].
-This option requires the `gfm` option to be true.
-
-### pedantic
-
-Type: `boolean`
-Default: `false`
-
-Conform to obscure parts of `markdown.pl` as much as possible. Don't fix any of
-the original markdown bugs or poor behavior.
-
-### sanitize
-
-Type: `boolean`
-Default: `false`
-
-Sanitize the output. Ignore any HTML that has been input.
-
-### smartLists
-
-Type: `boolean`
-Default: `true`
-
-Use smarter list behavior than the original markdown. May eventually be
-default with the old behavior moved into `pedantic`.
-
-### smartypants
-
-Type: `boolean`
-Default: `false`
-
-Use "smart" typograhic punctuation for things like quotes and dashes.
-
-## Access to lexer and parser
-
-You also have direct access to the lexer and parser if you so desire.
-
-``` js
-var tokens = marked.lexer(text, options);
-console.log(marked.parser(tokens));
-```
-
-``` js
-var lexer = new marked.Lexer(options);
-var tokens = lexer.lex(text);
-console.log(tokens);
-console.log(lexer.rules);
-```
-
-## CLI
-
-``` bash
-$ marked -o hello.html
-hello world
-^D
-$ cat hello.html
-
-
-
-
-
-
-```
-
-Which looks correct to you?
-
-- - -
-
-```
-$ markdown.pl
-* hello
- > world
-^D
-
-
-
-
-
-```
-
-```
-$ marked
-* hello
- > world
-^D
-
-
-```
-
-Again, which looks correct to you?
-
-- - -
-
-EXAMPLE:
-
-```
-$ markdown.pl
-* hello
- * world
- * hi
- code
-^D
-
-
-
-
-```
-
-The code isn't a code block even though it's after the bullet margin. I know,
-lets give it two more spaces, effectively making it 8 spaces past the bullet.
-
-```
-$ markdown.pl
-* hello
- * world
- * hi
- code
-^D
-
-
-
-```
-
-And, it's still not a code block. Did you also notice that the 3rd item isn't
-even its own list? Markdown screws that up too because of its indentation
-unaware parsing.
-
-- - -
-
-Let's look at some more examples of markdown's list parsing:
-
-```
-$ markdown.pl
-
- * item1
-
- * item2
-
- text
-^D
-
-
-
-
-
-
-
-```
-
-Which looks correct to you?
-
-- - -
-
-```
-$ markdown.pl
-* hello
- > world
-^D
-
-
-
-
-
-```
-
-More misnested tags.
-
-
-```
-$ marked
-* hello
- > world
-^D
-
-
-```
-
-Again, which looks correct to you?
-
-- - -
-
-# Why quality matters - Part 2
-
-``` bash
-$ markdown.pl
-* hello
- > world
-^D
-
-
-
-
--``` - -``` bash -$ sundown # upskirt -* hello - > world -^D -world -
-
world
code>var a = 1;
<div>hello</div>
- -<span>hello</span>
-``` - -``` bash -$ marked -hello -
-``` - -- - - - -See: https://github.com/evilstreak/markdown-js/issues/27 - -``` bash -$ markdown.js -[](/link) -^D - -``` - -``` bash -$ marked -[](/link) -^D - -``` - -- - - - -See: https://github.com/evilstreak/markdown-js/issues/24 - -``` bash -$ markdown.js -> a - -> b - -> c -^D --``` - -``` bash -$ marked -> a - -> b - -> c -^D -a
bundefined> c
-a - -
-b - -
-``` - -- - - - -``` bash -$ markdown.pl -* hello - * world - how - - are - you - - * today -* hi -^D -c -
hello
- -are -you
- -hello
-world -how
-are -you
-today
-'
- + (escaped ? code : escape(code, true))
- + '\n';
- }
-
- return ''
- + (escaped ? code : escape(code, true))
- + '\n\n';
-};
-
-Renderer.prototype.blockquote = function(quote) {
- return '\n' + quote + '\n'; -}; - -Renderer.prototype.html = function(html) { - return html; -}; - -Renderer.prototype.heading = function(text, level, raw) { - return '
' + text + '
\n'; -}; - -Renderer.prototype.table = function(header, body) { - return '' + text + '';
-};
-
-Renderer.prototype.br = function() {
- return this.options.xhtml ? 'An error occured:
' - + escape(e.message + '', true) - + ''; - } - throw e; - } -} - -/** - * Options - */ - -marked.options = -marked.setOptions = function(opt) { - merge(marked.defaults, opt); - return marked; -}; - -marked.defaults = { - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - smartLists: false, - silent: false, - highlight: null, - langPrefix: 'lang-', - smartypants: false, - headerPrefix: '', - renderer: new Renderer, - xhtml: false -}; - -/** - * Expose - */ - -marked.Parser = Parser; -marked.parser = Parser.parse; - -marked.Renderer = Renderer; - -marked.Lexer = Lexer; -marked.lexer = Lexer.lex; - -marked.InlineLexer = InlineLexer; -marked.inlineLexer = InlineLexer.output; - -marked.parse = marked; - -if (typeof module !== 'undefined' && typeof exports === 'object') { - module.exports = marked; -} else if (typeof define === 'function' && define.amd) { - define(function() { return marked; }); -} else { - this.marked = marked; -} - -}).call(function() { - return this || (typeof window !== 'undefined' ? window : global); -}()); diff --git a/js/vendor/marked/man/marked.1 b/js/vendor/marked/man/marked.1 deleted file mode 100644 index f89f1a7b9a..0000000000 --- a/js/vendor/marked/man/marked.1 +++ /dev/null @@ -1,88 +0,0 @@ -.ds q \N'34' -.TH marked 1 "2014-01-31" "v0.3.1" "marked.js" - -.SH NAME -marked \- a javascript markdown parser - -.SH SYNOPSIS -.B marked -[\-o \fI