From 36cd68cdcb019499a7bfaff73801ae8ffa0dc9db Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 19 Sep 2019 15:32:31 -0400 Subject: [PATCH 01/20] Get Cesium Viewer working using ES6 One of my first goals for ES6 was simply getting Cesium Viewer working as an ES6 application. Which proved easier than I thought. 1. Update GLSL shader gulp task to generate ES6 modules instead of AMD. 2. Update Cesium.js build task to generate ES6 Source/Cesium.js instead of AMD 3. Add rollup as a new dependency that will ultimately replace requirejs. 4. Create a simplified `createWorkers` task that runs as part of `build` this generates one AMD module per-worker that is then loaded by `TaskProcessor` just as before. This step is way faster than I expected and also extracts common code into separate bundles, reducing overall file size and load time. We will make this more robust when we go to build the release/minified workers, right now I just care about running locally as a dev. I had to modify `TastProcessor._defaultWorkerModulePrefix` to point to `Workers/Build` instead of `Workers`, we'll have to change this somehow when we do a release build. 5. Updated our mostly manual shims on Source/ThirdParty files to use ES6 instead of requirejs. 6. I'm using `import.meta.url` in buildModuleUrl, which may not be the ideal solution but gets the job down for now. It's only a stage 3 proposal so eslint fails to aprt it. Open to any ideas on an alternate approach here (or should ES6 apps just always set CESIUM_BASE_URL before including anything) 7. Also updated eslint to treat most of our code base as ES6, there are still some errors but nothing that won't go away on its own as we progress. --- .eslintignore | 1 + .eslintrc.json | 3 + .gitignore | 8 +-- Apps/CesiumViewer/CesiumViewer.js | 55 ++++++-------- Apps/CesiumViewer/CesiumViewerStartup.js | 12 ---- Apps/CesiumViewer/index.html | 2 +- Apps/Sandcastle/.eslintrc.json | 3 + Source/Core/Matrix4.js | 2 +- Source/Core/TaskProcessor.js | 7 +- Source/ThirdParty/Autolinker.js | 7 +- Source/ThirdParty/LercDecode.js | 5 ++ Source/ThirdParty/NoSleep.js | 66 +++++++++++++---- Source/ThirdParty/Tween.js | 5 +- Source/ThirdParty/Uri.js | 4 +- Source/ThirdParty/bitmap-sdf.js | 6 +- Source/ThirdParty/crunch.js | 5 +- Source/ThirdParty/earcut-2.1.1.js | 6 +- Source/ThirdParty/jsep.js | 9 +-- Source/ThirdParty/kdbush.js | 6 +- Source/ThirdParty/knockout-3.5.0.js | 5 ++ Source/ThirdParty/knockout-es5.js | 6 +- Source/ThirdParty/knockout.js | 23 +++--- Source/ThirdParty/measureText.js | 6 +- Source/ThirdParty/mersenne-twister.js | 5 +- Source/ThirdParty/pako_inflate.js | 5 ++ Source/ThirdParty/protobuf-minimal.js | 5 +- Source/ThirdParty/purify.js | 11 +-- Source/ThirdParty/quickselect.js | 5 +- Source/ThirdParty/rbush.js | 6 +- Source/ThirdParty/sprintf.js | 5 +- Source/ThirdParty/topojson.js | 6 +- Source/ThirdParty/when.js | 13 +--- Source/ThirdParty/zip.js | 14 ++-- gulpfile.js | 91 ++++++++++-------------- package.json | 1 + 35 files changed, 183 insertions(+), 236 deletions(-) delete mode 100644 Apps/CesiumViewer/CesiumViewerStartup.js diff --git a/.eslintignore b/.eslintignore index 71525bb5214..66f85f5764a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,6 +5,7 @@ Documentation/** Source/Shaders/** Source/ThirdParty/** Source/Workers/cesiumWorkerBootstrapper.js +Source/Workers/Build/** ThirdParty/** Tools/** Apps/Sandcastle/jsHintOptions.js diff --git a/.eslintrc.json b/.eslintrc.json index 01a053756fc..f3ddd763a13 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,6 +3,9 @@ "plugins": [ "html" ], + "parserOptions": { + "sourceType": "module" + }, "rules": { "no-unused-vars": ["error", {"vars": "all", "args": "none"}] } diff --git a/.gitignore b/.gitignore index 3d22bfa7d15..456a6ba74c8 100644 --- a/.gitignore +++ b/.gitignore @@ -14,12 +14,10 @@ Thumbs.db /Source/Cesium.js -/Source/Shaders/*.js -/Source/Shaders/*/*.js -/Source/Shaders/*/*/*.js -/Source/ThirdParty/Shaders/*.js - /Specs/SpecList.js +/Source/Shaders/**/*.js +/Source/ThirdParty/Shaders/**/*.js +/Source/Workers/Build /node_modules npm-debug.log diff --git a/Apps/CesiumViewer/CesiumViewer.js b/Apps/CesiumViewer/CesiumViewer.js index f1e5b3c1c6b..5f97f0af818 100644 --- a/Apps/CesiumViewer/CesiumViewer.js +++ b/Apps/CesiumViewer/CesiumViewer.js @@ -1,36 +1,21 @@ -define([ - 'Cesium/Core/Cartesian3', - 'Cesium/Core/createWorldTerrain', - 'Cesium/Core/defined', - 'Cesium/Core/formatError', - 'Cesium/Core/Math', - 'Cesium/Core/objectToQuery', - 'Cesium/Core/queryToObject', - 'Cesium/DataSources/CzmlDataSource', - 'Cesium/DataSources/GeoJsonDataSource', - 'Cesium/DataSources/KmlDataSource', - 'Cesium/Scene/TileMapServiceImageryProvider', - 'Cesium/Widgets/Viewer/Viewer', - 'Cesium/Widgets/Viewer/viewerCesiumInspectorMixin', - 'Cesium/Widgets/Viewer/viewerDragDropMixin', - 'domReady!' - ], function( - Cartesian3, - createWorldTerrain, - defined, - formatError, - CesiumMath, - objectToQuery, - queryToObject, - CzmlDataSource, - GeoJsonDataSource, - KmlDataSource, - TileMapServiceImageryProvider, - Viewer, - viewerCesiumInspectorMixin, - viewerDragDropMixin) { - 'use strict'; - +import { + Cartesian3, + createWorldTerrain, + defined, + formatError, + Math as CesiumMath, + objectToQuery, + queryToObject, + CzmlDataSource, + GeoJsonDataSource, + KmlDataSource, + TileMapServiceImageryProvider, + Viewer, + viewerCesiumInspectorMixin, + viewerDragDropMixin +} from '../../Source/Cesium.js'; + +function main() { /* Options parsed from query string: source=url The URL of a CZML/GeoJSON/KML data source to load at startup. @@ -218,4 +203,6 @@ define([ } loadingIndicator.style.display = 'none'; -}); +} + +main(); diff --git a/Apps/CesiumViewer/CesiumViewerStartup.js b/Apps/CesiumViewer/CesiumViewerStartup.js deleted file mode 100644 index f387d66ce37..00000000000 --- a/Apps/CesiumViewer/CesiumViewerStartup.js +++ /dev/null @@ -1,12 +0,0 @@ -/*global require*/ -/*eslint-disable strict*/ -require({ - baseUrl : '.', - paths : { - domReady : '../../ThirdParty/requirejs-2.1.20/domReady', - Cesium : '../../Source' - } -}, [ - 'CesiumViewer' - ], function() { -}); diff --git a/Apps/CesiumViewer/index.html b/Apps/CesiumViewer/index.html index 1851db5ea96..99a6b82bcfd 100644 --- a/Apps/CesiumViewer/index.html +++ b/Apps/CesiumViewer/index.html @@ -10,7 +10,7 @@ Cesium Viewer - +
diff --git a/Apps/Sandcastle/.eslintrc.json b/Apps/Sandcastle/.eslintrc.json index b2f72019ab4..0983ac08d13 100644 --- a/Apps/Sandcastle/.eslintrc.json +++ b/Apps/Sandcastle/.eslintrc.json @@ -7,6 +7,9 @@ "Sandcastle": true, "Cesium": true }, + "parserOptions": { + "sourceType": "script" + }, "rules": { "no-alert": ["off"], "no-implicit-globals": "off", diff --git a/Source/Core/Matrix4.js b/Source/Core/Matrix4.js index 2407a114277..41b8c1d46f9 100644 --- a/Source/Core/Matrix4.js +++ b/Source/Core/Matrix4.js @@ -4,7 +4,7 @@ import Check from './Check.js'; import defaultValue from './defaultValue.js'; import defined from './defined.js'; import defineProperties from './defineProperties.js'; -import deprecationWarning from './deprecationWarning'; +import deprecationWarning from './deprecationWarning.js'; import freezeObject from './freezeObject.js'; import CesiumMath from './Math.js'; import Matrix3 from './Matrix3.js'; diff --git a/Source/Core/TaskProcessor.js b/Source/Core/TaskProcessor.js index 6aee28d6aa1..bac229ab380 100644 --- a/Source/Core/TaskProcessor.js +++ b/Source/Core/TaskProcessor.js @@ -130,11 +130,6 @@ import RuntimeError from './RuntimeError.js'; if (defined(TaskProcessor._loaderConfig)) { bootstrapMessage.loaderConfig = TaskProcessor._loaderConfig; } else { - if (!(defined(define.amd) && !define.amd.toUrlUndefined && defined(require.toUrl))) { - bootstrapMessage.loaderConfig.paths = { - 'Workers': buildModuleUrl('Workers') - }; - } bootstrapMessage.loaderConfig.baseUrl = buildModuleUrl.getCesiumBaseUrl().url; } @@ -339,7 +334,7 @@ import RuntimeError from './RuntimeError.js'; TaskProcessor.taskCompletedEvent = taskCompletedEvent; // exposed for testing purposes - TaskProcessor._defaultWorkerModulePrefix = 'Workers/'; + TaskProcessor._defaultWorkerModulePrefix = 'Workers/Build/'; TaskProcessor._workerModulePrefix = TaskProcessor._defaultWorkerModulePrefix; TaskProcessor._loaderConfig = undefined; TaskProcessor._canTransferArrayBuffer = undefined; diff --git a/Source/ThirdParty/Autolinker.js b/Source/ThirdParty/Autolinker.js index 6b2ec1ba542..76d76b6b0ff 100644 --- a/Source/ThirdParty/Autolinker.js +++ b/Source/ThirdParty/Autolinker.js @@ -1,3 +1,6 @@ +var exports = {}; +var module = { exports: exports }; + (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module unless amdModuleId is set @@ -2749,8 +2752,10 @@ Autolinker.match.Url = Autolinker.Util.extend( Autolinker.match.Match, { } return anchorText; } - + } ); return Autolinker; })); + +export default module.exports; diff --git a/Source/ThirdParty/LercDecode.js b/Source/ThirdParty/LercDecode.js index a83a6437b48..e6945720a8c 100644 --- a/Source/ThirdParty/LercDecode.js +++ b/Source/ThirdParty/LercDecode.js @@ -26,6 +26,9 @@ Contributors: Johannes Schmid, (LERC v1) /* Copyright 2015-2018 Esri. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 @preserve */ +var exports = {}; +var module = { exports: exports }; + /** * a module for decoding LERC blobs * @module Lerc @@ -2111,3 +2114,5 @@ Contributors: Johannes Schmid, (LERC v1) } })(); + +export default module.exports; diff --git a/Source/ThirdParty/NoSleep.js b/Source/ThirdParty/NoSleep.js index 2cb7ce1a73c..5f658cd365c 100644 --- a/Source/ThirdParty/NoSleep.js +++ b/Source/ThirdParty/NoSleep.js @@ -1,14 +1,17 @@ -/*! NoSleep.js v0.7.0 - git.io/vfn01 - Rich Tibbett - MIT license */ +var exports = {}; +var module = { exports: exports }; + +/*! NoSleep.js v0.9.0 - git.io/vfn01 - Rich Tibbett - MIT license */ (function webpackUniversalModuleDefinition(root, factory) { - /* if(typeof exports === 'object' && typeof module === 'object') + if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); - else */ if(typeof define === 'function' && define.amd) + else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["NoSleep"] = factory(); else root["NoSleep"] = factory(); -})(this, function() { +})(typeof self !== 'undefined' ? self : this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; @@ -85,13 +88,19 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var mediaFile = __webpack_require__(1); +var _require = __webpack_require__(1), + webm = _require.webm, + mp4 = _require.mp4; // Detect iOS browsers < version 10 + + var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream; var NoSleep = function () { function NoSleep() { + var _this = this; + _classCallCheck(this, NoSleep); if (oldIOS) { @@ -100,25 +109,48 @@ var NoSleep = function () { // Set up no sleep video element this.noSleepVideo = document.createElement('video'); + this.noSleepVideo.setAttribute('muted', ''); + this.noSleepVideo.setAttribute('title', 'No Sleep'); this.noSleepVideo.setAttribute('playsinline', ''); - this.noSleepVideo.setAttribute('src', mediaFile); - this.noSleepVideo.addEventListener('timeupdate', function (e) { - if (this.noSleepVideo.currentTime > 0.5) { - this.noSleepVideo.currentTime = Math.random(); + this._addSourceToVideo(this.noSleepVideo, 'webm', webm); + this._addSourceToVideo(this.noSleepVideo, 'mp4', mp4); + + this.noSleepVideo.addEventListener('loadedmetadata', function () { + if (_this.noSleepVideo.duration <= 1) { + // webm source + _this.noSleepVideo.setAttribute('loop', ''); + } else { + // mp4 source + _this.noSleepVideo.addEventListener('timeupdate', function () { + if (_this.noSleepVideo.currentTime > 0.5) { + _this.noSleepVideo.currentTime = Math.random(); + } + }); } - }.bind(this)); + }); } } _createClass(NoSleep, [{ + key: '_addSourceToVideo', + value: function _addSourceToVideo(element, type, dataURI) { + var source = document.createElement('source'); + source.src = dataURI; + source.type = 'video/' + type; + element.appendChild(source); + } + }, { key: 'enable', value: function enable() { if (oldIOS) { this.disable(); + console.warn('\n NoSleep enabled for older iOS devices. This can interrupt\n active or long-running network requests from completing successfully.\n See https://github.com/richtr/NoSleep.js/issues/15 for more details.\n '); this.noSleepTimer = window.setInterval(function () { - window.location.href = '/'; - window.setTimeout(window.stop, 0); + if (!document.hidden) { + window.location.href = window.location.href.split('#')[0]; + window.setTimeout(window.stop, 0); + } }, 15000); } else { this.noSleepVideo.play(); @@ -129,6 +161,7 @@ var NoSleep = function () { value: function disable() { if (oldIOS) { if (this.noSleepTimer) { + console.warn('\n NoSleep now disabled for older iOS devices.\n '); window.clearInterval(this.noSleepTimer); this.noSleepTimer = null; } @@ -152,8 +185,13 @@ module.exports = NoSleep; "use strict"; -module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA='; +module.exports = { + webm: 'data:video/webm;base64,GkXfo0AgQoaBAUL3gQFC8oEEQvOBCEKCQAR3ZWJtQoeBAkKFgQIYU4BnQI0VSalmQCgq17FAAw9CQE2AQAZ3aGFtbXlXQUAGd2hhbW15RIlACECPQAAAAAAAFlSua0AxrkAu14EBY8WBAZyBACK1nEADdW5khkAFVl9WUDglhohAA1ZQOIOBAeBABrCBCLqBCB9DtnVAIueBAKNAHIEAAIAwAQCdASoIAAgAAUAmJaQAA3AA/vz0AAA=', + mp4: 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA=' +}; /***/ }) /******/ ]); -}); \ No newline at end of file +}); + +export default module.exports; diff --git a/Source/ThirdParty/Tween.js b/Source/ThirdParty/Tween.js index 98dac2eca3c..f2e21f0a191 100644 --- a/Source/ThirdParty/Tween.js +++ b/Source/ThirdParty/Tween.js @@ -39,8 +39,6 @@ THE SOFTWARE. * @author Ben Delarre / http://delarre.net */ -define(function() { - // Date.now shim for (ahem) Internet Explo(d|r)er if ( Date.now === undefined ) { @@ -788,5 +786,4 @@ define(function() { }; -return TWEEN; -}); +export default TWEEN; diff --git a/Source/ThirdParty/Uri.js b/Source/ThirdParty/Uri.js index f281308f531..74dc3115019 100644 --- a/Source/ThirdParty/Uri.js +++ b/Source/ThirdParty/Uri.js @@ -22,7 +22,6 @@ * limitations under the License. * */ -define(function() { /** * Constructs a URI object. @@ -271,5 +270,4 @@ define(function() { return result; }; -return URI; -}); +export default URI; diff --git a/Source/ThirdParty/bitmap-sdf.js b/Source/ThirdParty/bitmap-sdf.js index 85a36902ad0..3c310c7e285 100644 --- a/Source/ThirdParty/bitmap-sdf.js +++ b/Source/ThirdParty/bitmap-sdf.js @@ -3,9 +3,6 @@ * Calculate SDF for image/bitmap/bw data * This project is a fork of MapBox's TinySDF that works directly on an input Canvas instead of generating the glyphs themselves. */ -define([], function() { - - 'use strict' var INF = 1e20; @@ -144,5 +141,4 @@ define([], function() { } } - return calcSDF; -}); + export default calcSDF; diff --git a/Source/ThirdParty/crunch.js b/Source/ThirdParty/crunch.js index 893255093b7..37b89fefef4 100644 --- a/Source/ThirdParty/crunch.js +++ b/Source/ThirdParty/crunch.js @@ -27,8 +27,6 @@ // The C++ code was compiled to Javascript with Emcripten. // For instructions, see: https://github.com/BinomialLLC/crunch -define([], function() { - var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=console.log;if(!Module["printErr"])Module["printErr"]=console.warn;var nodeFS;var nodePath;Module["read"]=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function shell_read(){throw"no read() available"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof quit==="function"){Module["quit"]=(function(status,toThrow){quit(status)})}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){Module["readBinary"]=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response)}else{onerror()}};xhr.onerror=onerror;xhr.send(null)};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function shell_print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function shell_printErr(x){console.warn(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){eval.call(null,x)}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}if(!Module["quit"]){Module["quit"]=(function(status,toThrow){throw toThrow})}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var Runtime={setTempRet0:(function(value){tempRet0=value;return value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[],addFunction:(function(func){for(var i=0;i>2];var end=(ret+size+15|0)&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];if(!func){try{func=eval("_"+ident)}catch(e){}}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=Runtime.stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc==="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr>2]=0}stop=ret+size;while(ptr>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function demangle(func){var __cxa_demangle_func=Module["___cxa_demangle"]||Module["__cxa_demangle"];if(__cxa_demangle_func){try{var s=func.substr(1);var len=lengthBytesUTF8(s)+1;var buf=_malloc(len);stringToUTF8(s,buf,len);var status=_malloc(4);var ret=__cxa_demangle_func(buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}return func}Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/__Z[\w\d_]+/g;return text.replace(regex,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}Module["stackTrace"]=stackTrace;var WASM_PAGE_SIZE=65536;var ASMJS_PAGE_SIZE=16777216;var MIN_TOTAL_MEMORY=16777216;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBuffer(buf){Module["buffer"]=buffer=buf}function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}if(!Module["reallocBuffer"])Module["reallocBuffer"]=(function(size){var ret;try{if(ArrayBuffer.transfer){ret=ArrayBuffer.transfer(buffer,size)}else{var oldHEAP8=HEAP8;ret=new ArrayBuffer(size);var temp=new Int8Array(ret);temp.set(oldHEAP8)}}catch(e){return false}var success=_emscripten_replace_memory(ret);if(!success)return false;return ret});function enlargeMemory(){var PAGE_MULTIPLE=Module["usingWasm"]?WASM_PAGE_SIZE:ASMJS_PAGE_SIZE;var LIMIT=2147483648-PAGE_MULTIPLE;if(HEAP32[DYNAMICTOP_PTR>>2]>LIMIT){return false}var OLD_TOTAL_MEMORY=TOTAL_MEMORY;TOTAL_MEMORY=Math.max(TOTAL_MEMORY,MIN_TOTAL_MEMORY);while(TOTAL_MEMORY>2]){if(TOTAL_MEMORY<=536870912){TOTAL_MEMORY=alignUp(2*TOTAL_MEMORY,PAGE_MULTIPLE)}else{TOTAL_MEMORY=Math.min(alignUp((3*TOTAL_MEMORY+2147483648)/4,PAGE_MULTIPLE),LIMIT)}}var replacement=Module["reallocBuffer"](TOTAL_MEMORY);if(!replacement||replacement.byteLength!=TOTAL_MEMORY){TOTAL_MEMORY=OLD_TOTAL_MEMORY;return false}updateGlobalBuffer(replacement);updateGlobalBufferViews();return true}var byteLength;try{byteLength=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get);byteLength(new ArrayBuffer(4))}catch(e){byteLength=(function(buffer){return buffer.byteLength})}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(TOTAL_MEMORY0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var lastChar,end;if(dontAddNull){end=buffer+lengthBytesUTF8(string);lastChar=HEAP8[end]}stringToUTF8(string,buffer,Infinity);if(dontAddNull)HEAP8[end]=lastChar}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];if(!Math["trunc"])Math["trunc"]=(function(x){return x<0?Math.ceil(x):Math.floor(x)});Math.trunc=Math["trunc"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var ASM_CONSTS=[];STATIC_BASE=Runtime.GLOBAL_BASE;STATICTOP=STATIC_BASE+6192;__ATINIT__.push();allocate([228,2,0,0,81,16,0,0,12,3,0,0,177,16,0,0,32,0,0,0,0,0,0,0,12,3,0,0,94,16,0,0,48,0,0,0,0,0,0,0,228,2,0,0,127,16,0,0,12,3,0,0,140,16,0,0,16,0,0,0,0,0,0,0,12,3,0,0,183,17,0,0,32,0,0,0,0,0,0,0,12,3,0,0,147,17,0,0,72,0,0,0,0,0,0,0,108,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,32,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,1,0,0,5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,40,20,0,0,0,4,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,16,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,56,0,0,0,1,0,0,0,5,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,37,115,40,37,117,41,58,32,65,115,115,101,114,116,105,111,110,32,102,97,105,108,117,114,101,58,32,34,37,115,34,10,0,109,95,115,105,122,101,32,60,61,32,109,95,99,97,112,97,99,105,116,121,0,46,47,105,110,99,92,99,114,110,95,100,101,99,111,109,112,46,104,0,109,105,110,95,110,101,119,95,99,97,112,97,99,105,116,121,32,60,32,40,48,120,55,70,70,70,48,48,48,48,85,32,47,32,101,108,101,109,101,110,116,95,115,105,122,101,41,0,110,101,119,95,99,97,112,97,99,105,116,121,32,38,38,32,40,110,101,119,95,99,97,112,97,99,105,116,121,32,62,32,109,95,99,97,112,97,99,105,116,121,41,0,110,117,109,95,99,111,100,101,115,91,99,93,0,115,111,114,116,101,100,95,112,111,115,32,60,32,116,111,116,97,108,95,117,115,101,100,95,115,121,109,115,0,112,67,111,100,101,115,105,122,101,115,91,115,121,109,95,105,110,100,101,120,93,32,61,61,32,99,111,100,101,115,105,122,101,0,116,32,60,32,40,49,85,32,60,60,32,116,97,98,108,101,95,98,105,116,115,41,0,109,95,108,111,111,107,117,112,91,116,93,32,61,61,32,99,85,73,78,84,51,50,95,77,65,88,0,99,114,110,100,95,109,97,108,108,111,99,58,32,115,105,122,101,32,116,111,111,32,98,105,103,0,99,114,110,100,95,109,97,108,108,111,99,58,32,111,117,116,32,111,102,32,109,101,109,111,114,121,0,40,40,117,105,110,116,51,50,41,112,95,110,101,119,32,38,32,40,67,82,78,68,95,77,73,78,95,65,76,76,79,67,95,65,76,73,71,78,77,69,78,84,32,45,32,49,41,41,32,61,61,32,48,0,99,114,110,100,95,114,101,97,108,108,111,99,58,32,98,97,100,32,112,116,114,0,99,114,110,100,95,102,114,101,101,58,32,98,97,100,32,112,116,114,0,102,97,108,115,101,0,40,116,111,116,97,108,95,115,121,109,115,32,62,61,32,49,41,32,38,38,32,40,116,111,116,97,108,95,115,121,109,115,32,60,61,32,112,114,101,102,105,120,95,99,111,100,105,110,103,58,58,99,77,97,120,83,117,112,112,111,114,116,101,100,83,121,109,115,41,0,17,18,19,20,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,16,48,0,110,117,109,95,98,105,116,115,32,60,61,32,51,50,85,0,109,95,98,105,116,95,99,111,117,110,116,32,60,61,32,99,66,105,116,66,117,102,83,105,122,101,0,116,32,33,61,32,99,85,73,78,84,51,50,95,77,65,88,0,109,111,100,101,108,46,109,95,99,111,100,101,95,115,105,122,101,115,91,115,121,109,93,32,61,61,32,108,101,110,0,0,2,3,1,0,2,3,4,5,6,7,1,40,108,101,110,32,62,61,32,49,41,32,38,38,32,40,108,101,110,32,60,61,32,99,77,97,120,69,120,112,101,99,116,101,100,67,111,100,101,83,105,122,101,41,0,105,32,60,32,109,95,115,105,122,101,0,110,101,120,116,95,108,101,118,101,108,95,111,102,115,32,62,32,99,117,114,95,108,101,118,101,108,95,111,102,115,0,1,2,2,3,3,3,3,4,0,0,0,0,0,0,1,1,0,1,0,1,0,0,1,2,1,2,0,0,0,1,0,2,1,0,2,0,0,1,2,3,110,117,109,32,38,38,32,40,110,117,109,32,61,61,32,126,110,117,109,95,99,104,101,99,107,41,0,17,0,10,0,17,17,17,0,0,0,0,5,0,0,0,0,0,0,9,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,15,10,17,17,17,3,10,7,0,1,19,9,11,11,0,0,9,6,11,0,0,11,0,6,17,0,0,0,17,17,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,17,0,10,10,17,17,17,0,10,0,0,2,0,9,11,0,0,0,9,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,4,13,0,0,0,0,9,14,0,0,0,0,0,14,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,9,16,0,0,0,0,0,16,0,0,16,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,18,18,18,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,10,0,0,0,0,9,11,0,0,0,0,0,11,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,12,0,0,0,0,9,12,0,0,0,0,0,12,0,0,12,0,0,45,43,32,32,32,48,88,48,120,0,40,110,117,108,108,41,0,45,48,88,43,48,88,32,48,88,45,48,120,43,48,120,32,48,120,0,105,110,102,0,73,78,70,0,110,97,110,0,78,65,78,0,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,46,0,84,33,34,25,13,1,2,3,17,75,28,12,16,4,11,29,18,30,39,104,110,111,112,113,98,32,5,6,15,19,20,21,26,8,22,7,40,36,23,24,9,10,14,27,31,37,35,131,130,125,38,42,43,60,61,62,63,67,71,74,77,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,105,106,107,108,114,115,116,121,122,123,124,0,73,108,108,101,103,97,108,32,98,121,116,101,32,115,101,113,117,101,110,99,101,0,68,111,109,97,105,110,32,101,114,114,111,114,0,82,101,115,117,108,116,32,110,111,116,32,114,101,112,114,101,115,101,110,116,97,98,108,101,0,78,111,116,32,97,32,116,116,121,0,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,0,79,112,101,114,97,116,105,111,110,32,110,111,116,32,112,101,114,109,105,116,116,101,100,0,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,0,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115,0,70,105,108,101,32,101,120,105,115,116,115,0,86,97,108,117,101,32,116,111,111,32,108,97,114,103,101,32,102,111,114,32,100,97,116,97,32,116,121,112,101,0,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101,0,79,117,116,32,111,102,32,109,101,109,111,114,121,0,82,101,115,111,117,114,99,101,32,98,117,115,121,0,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108,0,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101,0,73,110,118,97,108,105,100,32,115,101,101,107,0,67,114,111,115,115,45,100,101,118,105,99,101,32,108,105,110,107,0,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109,0,68,105,114,101,99,116,111,114,121,32,110,111,116,32,101,109,112,116,121,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,112,101,101,114,0,79,112,101,114,97,116,105,111,110,32,116,105,109,101,100,32,111,117,116,0,67,111,110,110,101,99,116,105,111,110,32,114,101,102,117,115,101,100,0,72,111,115,116,32,105,115,32,100,111,119,110,0,72,111,115,116,32,105,115,32,117,110,114,101,97,99,104,97,98,108,101,0,65,100,100,114,101,115,115,32,105,110,32,117,115,101,0,66,114,111,107,101,110,32,112,105,112,101,0,73,47,79,32,101,114,114,111,114,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115,0,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100,0,78,111,32,115,117,99,104,32,100,101,118,105,99,101,0,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121,0,73,115,32,97,32,100,105,114,101,99,116,111,114,121,0,84,101,120,116,32,102,105,108,101,32,98,117,115,121,0,69,120,101,99,32,102,111,114,109,97,116,32,101,114,114,111,114,0,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116,0,65,114,103,117,109,101,110,116,32,108,105,115,116,32,116,111,111,32,108,111,110,103,0,83,121,109,98,111,108,105,99,32,108,105,110,107,32,108,111,111,112,0,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103,0,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115,32,105,110,32,115,121,115,116,101,109,0,78,111,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,97,118,97,105,108,97,98,108,101,0,66,97,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,0,78,111,32,99,104,105,108,100,32,112,114,111,99,101,115,115,0,66,97,100,32,97,100,100,114,101,115,115,0,70,105,108,101,32,116,111,111,32,108,97,114,103,101,0,84,111,111,32,109,97,110,121,32,108,105,110,107,115,0,78,111,32,108,111,99,107,115,32,97,118,97,105,108,97,98,108,101,0,82,101,115,111,117,114,99,101,32,100,101,97,100,108,111,99,107,32,119,111,117,108,100,32,111,99,99,117,114,0,83,116,97,116,101,32,110,111,116,32,114,101,99,111,118,101,114,97,98,108,101,0,80,114,101,118,105,111,117,115,32,111,119,110,101,114,32,100,105,101,100,0,79,112,101,114,97,116,105,111,110,32,99,97,110,99,101,108,101,100,0,70,117,110,99,116,105,111,110,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,0,78,111,32,109,101,115,115,97,103,101,32,111,102,32,100,101,115,105,114,101,100,32,116,121,112,101,0,73,100,101,110,116,105,102,105,101,114,32,114,101,109,111,118,101,100,0,68,101,118,105,99,101,32,110,111,116,32,97,32,115,116,114,101,97,109,0,78,111,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,0,68,101,118,105,99,101,32,116,105,109,101,111,117,116,0,79,117,116,32,111,102,32,115,116,114,101,97,109,115,32,114,101,115,111,117,114,99,101,115,0,76,105,110,107,32,104,97,115,32,98,101,101,110,32,115,101,118,101,114,101,100,0,80,114,111,116,111,99,111,108,32,101,114,114,111,114,0,66,97,100,32,109,101,115,115,97,103,101,0,70,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,105,110,32,98,97,100,32,115,116,97,116,101,0,78,111,116,32,97,32,115,111,99,107,101,116,0,68,101,115,116,105,110,97,116,105,111,110,32,97,100,100,114,101,115,115,32,114,101,113,117,105,114,101,100,0,77,101,115,115,97,103,101,32,116,111,111,32,108,97,114,103,101,0,80,114,111,116,111,99,111,108,32,119,114,111,110,103,32,116,121,112,101,32,102,111,114,32,115,111,99,107,101,116,0,80,114,111,116,111,99,111,108,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,80,114,111,116,111,99,111,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,83,111,99,107,101,116,32,116,121,112,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,78,111,116,32,115,117,112,112,111,114,116,101,100,0,80,114,111,116,111,99,111,108,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,0,65,100,100,114,101,115,115,32,102,97,109,105,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,112,114,111,116,111,99,111,108,0,65,100,100,114,101,115,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,0,78,101,116,119,111,114,107,32,105,115,32,100,111,119,110,0,78,101,116,119,111,114,107,32,117,110,114,101,97,99,104,97,98,108,101,0,67,111,110,110,101,99,116,105,111,110,32,114,101,115,101,116,32,98,121,32,110,101,116,119,111,114,107,0,67,111,110,110,101,99,116,105,111,110,32,97,98,111,114,116,101,100,0,78,111,32,98,117,102,102,101,114,32,115,112,97,99,101,32,97,118,97,105,108,97,98,108,101,0,83,111,99,107,101,116,32,105,115,32,99,111,110,110,101,99,116,101,100,0,83,111,99,107,101,116,32,110,111,116,32,99,111,110,110,101,99,116,101,100,0,67,97,110,110,111,116,32,115,101,110,100,32,97,102,116,101,114,32,115,111,99,107,101,116,32,115,104,117,116,100,111,119,110,0,79,112,101,114,97,116,105,111,110,32,97,108,114,101,97,100,121,32,105,110,32,112,114,111,103,114,101,115,115,0,79,112,101,114,97,116,105,111,110,32,105,110,32,112,114,111,103,114,101,115,115,0,83,116,97,108,101,32,102,105,108,101,32,104,97,110,100,108,101,0,82,101,109,111,116,101,32,73,47,79,32,101,114,114,111,114,0,81,117,111,116,97,32,101,120,99,101,101,100,101,100,0,78,111,32,109,101,100,105,117,109,32,102,111,117,110,100,0,87,114,111,110,103,32,109,101,100,105,117,109,32,116,121,112,101,0,78,111,32,101,114,114,111,114,32,105,110,102,111,114,109,97,116,105,111,110,0,0,116,101,114,109,105,110,97,116,105,110,103,32,119,105,116,104,32,37,115,32,101,120,99,101,112,116,105,111,110,32,111,102,32,116,121,112,101,32,37,115,58,32,37,115,0,116,101,114,109,105,110,97,116,105,110,103,32,119,105,116,104,32,37,115,32,101,120,99,101,112,116,105,111,110,32,111,102,32,116,121,112,101,32,37,115,0,116,101,114,109,105,110,97,116,105,110,103,32,119,105,116,104,32,37,115,32,102,111,114,101,105,103,110,32,101,120,99,101,112,116,105,111,110,0,116,101,114,109,105,110,97,116,105,110,103,0,117,110,99,97,117,103,104,116,0,83,116,57,101,120,99,101,112,116,105,111,110,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,54,95,95,115,104,105,109,95,116,121,112,101,95,105,110,102,111,69,0,83,116,57,116,121,112,101,95,105,110,102,111,0,78,49,48,95,95,99,120,120,97,98,105,118,49,50,48,95,95,115,105,95,99,108,97,115,115,95,116,121,112,101,95,105,110,102,111,69,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,55,95,95,99,108,97,115,115,95,116,121,112,101,95,105,110,102,111,69,0,112,116,104,114,101,97,100,95,111,110,99,101,32,102,97,105,108,117,114,101,32,105,110,32,95,95,99,120,97,95,103,101,116,95,103,108,111,98,97,108,115,95,102,97,115,116,40,41,0,99,97,110,110,111,116,32,99,114,101,97,116,101,32,112,116,104,114,101,97,100,32,107,101,121,32,102,111,114,32,95,95,99,120,97,95,103,101,116,95,103,108,111,98,97,108,115,40,41,0,99,97,110,110,111,116,32,122,101,114,111,32,111,117,116,32,116,104,114,101,97,100,32,118,97,108,117,101,32,102,111,114,32,95,95,99,120,97,95,103,101,116,95,103,108,111,98,97,108,115,40,41,0,116,101,114,109,105,110,97,116,101,95,104,97,110,100,108,101,114,32,117,110,101,120,112,101,99,116,101,100,108,121,32,114,101,116,117,114,110,101,100,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,57,95,95,112,111,105,110,116,101,114,95,116,121,112,101,95,105,110,102,111,69,0,78,49,48,95,95,99,120,120,97,98,105,118,49,49,55,95,95,112,98,97,115,101,95,116,121,112,101,95,105,110,102,111,69,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);var tempDoublePtr=STATICTOP;STATICTOP+=16;function _abort(){Module["abort"]()}function __ZSt18uncaught_exceptionv(){return!!__ZSt18uncaught_exceptionv.uncaught_exception}var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:(function(adjusted){if(!adjusted||EXCEPTIONS.infos[adjusted])return adjusted;for(var ptr in EXCEPTIONS.infos){var info=EXCEPTIONS.infos[ptr];if(info.adjusted===adjusted){return ptr}}return adjusted}),addRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];info.refcount++}),decRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];assert(info.refcount>0);info.refcount--;if(info.refcount===0&&!info.rethrown){if(info.destructor){Module["dynCall_vi"](info.destructor,ptr)}delete EXCEPTIONS.infos[ptr];___cxa_free_exception(ptr)}}),clearRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];info.refcount=0})};function ___cxa_begin_catch(ptr){var info=EXCEPTIONS.infos[ptr];if(info&&!info.caught){info.caught=true;__ZSt18uncaught_exceptionv.uncaught_exception--}if(info)info.rethrown=false;EXCEPTIONS.caught.push(ptr);EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr));return ptr}function _pthread_once(ptr,func){if(!_pthread_once.seen)_pthread_once.seen={};if(ptr in _pthread_once.seen)return;Module["dynCall_v"](func);_pthread_once.seen[ptr]=1}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}var SYSCALLS={varargs:0,get:(function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret}),getStr:(function(){var ret=Pointer_stringify(SYSCALLS.get());return ret}),get64:(function(){var low=SYSCALLS.get(),high=SYSCALLS.get();if(low>=0)assert(high===0);else assert(high===-1);return low}),getZero:(function(){assert(SYSCALLS.get()===0)})};function ___syscall6(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD();FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_STATIC);var PTHREAD_SPECIFIC={};function _pthread_getspecific(key){return PTHREAD_SPECIFIC[key]||0}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}var PTHREAD_SPECIFIC_NEXT_KEY=1;var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _pthread_key_create(key,destructor){if(key==0){return ERRNO_CODES.EINVAL}HEAP32[key>>2]=PTHREAD_SPECIFIC_NEXT_KEY;PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY]=0;PTHREAD_SPECIFIC_NEXT_KEY++;return 0}function ___resumeException(ptr){if(!EXCEPTIONS.last){EXCEPTIONS.last=ptr}throw ptr+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch."}function ___cxa_find_matching_catch(){var thrown=EXCEPTIONS.last;if(!thrown){return(Runtime.setTempRet0(0),0)|0}var info=EXCEPTIONS.infos[thrown];var throwntype=info.type;if(!throwntype){return(Runtime.setTempRet0(0),thrown)|0}var typeArray=Array.prototype.slice.call(arguments);var pointer=Module["___cxa_is_pointer_type"](throwntype);if(!___cxa_find_matching_catch.buffer)___cxa_find_matching_catch.buffer=_malloc(4);HEAP32[___cxa_find_matching_catch.buffer>>2]=thrown;thrown=___cxa_find_matching_catch.buffer;for(var i=0;i>2];info.adjusted=thrown;return(Runtime.setTempRet0(typeArray[i]),thrown)|0}}thrown=HEAP32[thrown>>2];return(Runtime.setTempRet0(throwntype),thrown)|0}function ___gxx_personality_v0(){}function _pthread_setspecific(key,value){if(!(key in PTHREAD_SPECIFIC)){return ERRNO_CODES.EINVAL}PTHREAD_SPECIFIC[key]=value;return 0}function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();var offset=offset_low;FS.llseek(stream,offset,whence);HEAP32[result>>2]=stream.position;if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall146(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.get(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();var ret=0;if(!___syscall146.buffer){___syscall146.buffers=[null,[],[]];___syscall146.printChar=(function(stream,curr){var buffer=___syscall146.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?Module["print"]:Module["printErr"])(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}})}for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=DYNAMIC_BASE;staticSealed=true;function invoke_iiii(index,a1,a2,a3){try{return Module["dynCall_iiii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){try{Module["dynCall_viiiii"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_vi(index,a1){try{Module["dynCall_vi"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_ii(index,a1){try{return Module["dynCall_ii"](index,a1)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viii(index,a1,a2,a3){try{Module["dynCall_viii"](index,a1,a2,a3)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_v(index){try{Module["dynCall_v"](index)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){try{Module["dynCall_viiiiii"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}function invoke_viiii(index,a1,a2,a3,a4){try{Module["dynCall_viiii"](index,a1,a2,a3,a4)}catch(e){if(typeof e!=="number"&&e!=="longjmp")throw e;Module["setThrew"](1,0)}}Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity,"byteLength":byteLength};Module.asmLibraryArg={"abort":abort,"assert":assert,"enlargeMemory":enlargeMemory,"getTotalMemory":getTotalMemory,"abortOnCannotGrowMemory":abortOnCannotGrowMemory,"invoke_iiii":invoke_iiii,"invoke_viiiii":invoke_viiiii,"invoke_vi":invoke_vi,"invoke_ii":invoke_ii,"invoke_viii":invoke_viii,"invoke_v":invoke_v,"invoke_viiiiii":invoke_viiiiii,"invoke_viiii":invoke_viiii,"_pthread_getspecific":_pthread_getspecific,"___syscall54":___syscall54,"_pthread_setspecific":_pthread_setspecific,"___gxx_personality_v0":___gxx_personality_v0,"___syscall6":___syscall6,"___setErrNo":___setErrNo,"_abort":_abort,"___cxa_begin_catch":___cxa_begin_catch,"_pthread_once":_pthread_once,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_pthread_key_create":_pthread_key_create,"___syscall140":___syscall140,"___resumeException":___resumeException,"___cxa_find_matching_catch":___cxa_find_matching_catch,"___syscall146":___syscall146,"__ZSt18uncaught_exceptionv":__ZSt18uncaught_exceptionv,"DYNAMICTOP_PTR":DYNAMICTOP_PTR,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM var asm=(function(global,env,buffer) { "almost asm";var a=global.Int8Array;var b=new a(buffer);var c=global.Int16Array;var d=new c(buffer);var e=global.Int32Array;var f=new e(buffer);var g=global.Uint8Array;var h=new g(buffer);var i=global.Uint16Array;var j=new i(buffer);var k=global.Uint32Array;var l=new k(buffer);var m=global.Float32Array;var n=new m(buffer);var o=global.Float64Array;var p=new o(buffer);var q=global.byteLength;var r=env.DYNAMICTOP_PTR|0;var s=env.tempDoublePtr|0;var t=env.ABORT|0;var u=env.STACKTOP|0;var v=env.STACK_MAX|0;var w=env.cttz_i8|0;var x=0;var y=0;var z=0;var A=0;var B=global.NaN,C=global.Infinity;var D=0,E=0,F=0,G=0,H=0.0;var I=0;var J=global.Math.floor;var K=global.Math.abs;var L=global.Math.sqrt;var M=global.Math.pow;var N=global.Math.cos;var O=global.Math.sin;var P=global.Math.tan;var Q=global.Math.acos;var R=global.Math.asin;var S=global.Math.atan;var T=global.Math.atan2;var U=global.Math.exp;var V=global.Math.log;var W=global.Math.ceil;var X=global.Math.imul;var Y=global.Math.min;var Z=global.Math.max;var _=global.Math.clz32;var $=env.abort;var aa=env.assert;var ba=env.enlargeMemory;var ca=env.getTotalMemory;var da=env.abortOnCannotGrowMemory;var ea=env.invoke_iiii;var fa=env.invoke_viiiii;var ga=env.invoke_vi;var ha=env.invoke_ii;var ia=env.invoke_viii;var ja=env.invoke_v;var ka=env.invoke_viiiiii;var la=env.invoke_viiii;var ma=env._pthread_getspecific;var na=env.___syscall54;var oa=env._pthread_setspecific;var pa=env.___gxx_personality_v0;var qa=env.___syscall6;var ra=env.___setErrNo;var sa=env._abort;var ta=env.___cxa_begin_catch;var ua=env._pthread_once;var va=env._emscripten_memcpy_big;var wa=env._pthread_key_create;var xa=env.___syscall140;var ya=env.___resumeException;var za=env.___cxa_find_matching_catch;var Aa=env.___syscall146;var Ba=env.__ZSt18uncaught_exceptionv;var Ca=0.0;function Da(newBuffer){if(q(newBuffer)&16777215||q(newBuffer)<=16777215||q(newBuffer)>2147483648)return false;b=new a(newBuffer);d=new c(newBuffer);f=new e(newBuffer);h=new g(newBuffer);j=new i(newBuffer);l=new k(newBuffer);n=new m(newBuffer);p=new o(newBuffer);buffer=newBuffer;return true} @@ -42,5 +40,4 @@ var Ea=[gd,mb,Yb,$b,lc,Kb,gd,gd];var Fa=[Zc,Hb,nb,Zc];var Ga=[wd,sd,_c,sd,sd,_c, // EMSCRIPTEN_END_ASM (Module.asmGlobalArg,Module.asmLibraryArg,buffer);var stackSave=Module["stackSave"]=asm["stackSave"];var getTempRet0=Module["getTempRet0"]=asm["getTempRet0"];var _memset=Module["_memset"]=asm["_memset"];var setThrew=Module["setThrew"]=asm["setThrew"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var setTempRet0=Module["setTempRet0"]=asm["setTempRet0"];var _crn_decompress=Module["_crn_decompress"]=asm["_crn_decompress"];var _crn_get_bytes_per_block=Module["_crn_get_bytes_per_block"]=asm["_crn_get_bytes_per_block"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var _crn_get_height=Module["_crn_get_height"]=asm["_crn_get_height"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _crn_get_levels=Module["_crn_get_levels"]=asm["_crn_get_levels"];var _crn_get_uncompressed_size=Module["_crn_get_uncompressed_size"]=asm["_crn_get_uncompressed_size"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=asm["_emscripten_get_global_libc"];var ___udivdi3=Module["___udivdi3"]=asm["___udivdi3"];var _llvm_bswap_i32=Module["_llvm_bswap_i32"]=asm["_llvm_bswap_i32"];var ___cxa_can_catch=Module["___cxa_can_catch"]=asm["___cxa_can_catch"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var ___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=asm["___cxa_is_pointer_type"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var _malloc=Module["_malloc"]=asm["_malloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _crn_get_width=Module["_crn_get_width"]=asm["_crn_get_width"];var _crn_get_dxt_format=Module["_crn_get_dxt_format"]=asm["_crn_get_dxt_format"];var dynCall_iiii=Module["dynCall_iiii"]=asm["dynCall_iiii"];var dynCall_viiiii=Module["dynCall_viiiii"]=asm["dynCall_viiiii"];var dynCall_vi=Module["dynCall_vi"]=asm["dynCall_vi"];var dynCall_ii=Module["dynCall_ii"]=asm["dynCall_ii"];var dynCall_viii=Module["dynCall_viii"]=asm["dynCall_viii"];var dynCall_v=Module["dynCall_v"]=asm["dynCall_v"];var dynCall_viiiiii=Module["dynCall_viiiiii"]=asm["dynCall_viiiiii"];var dynCall_viiii=Module["dynCall_viiii"]=asm["dynCall_viiii"];Runtime.stackAlloc=Module["stackAlloc"];Runtime.stackSave=Module["stackSave"];Runtime.stackRestore=Module["stackRestore"];Runtime.establishStackSpace=Module["establishStackSpace"];Runtime.setTempRet0=Module["setTempRet0"];Runtime.getTempRet0=Module["getTempRet0"];Module["asm"]=asm;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["exit"](status)}Module["quit"](status,new ExitStatus(status))}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"]){shouldRunNow=false}Module["noExitRuntime"]=true;run() - return Module; -}); +export default Module; diff --git a/Source/ThirdParty/earcut-2.1.1.js b/Source/ThirdParty/earcut-2.1.1.js index 3b6d8636a3c..25d406043a0 100644 --- a/Source/ThirdParty/earcut-2.1.1.js +++ b/Source/ThirdParty/earcut-2.1.1.js @@ -1,6 +1,3 @@ -define([], function() { - 'use strict'; - function earcut(data, holeIndices, dim) { dim = dim || 2; @@ -642,5 +639,4 @@ earcut.flatten = function (data) { return result; }; -return earcut; -}); +export default earcut; diff --git a/Source/ThirdParty/jsep.js b/Source/ThirdParty/jsep.js index c7a175a5657..77f989eb957 100644 --- a/Source/ThirdParty/jsep.js +++ b/Source/ThirdParty/jsep.js @@ -2,7 +2,8 @@ // JSEP may be freely distributed under the MIT License // http://jsep.from.so/ -define(function() { +var exports = {}; +var module = { exports: exports }; /*global module: true, exports: true, console: true */ (function (root) { @@ -680,8 +681,4 @@ define(function() { } }(this)); - // `jsep` only exists when running in the browser - if (typeof jsep !== 'undefined') { - return jsep.noConflict(); - } -}); +export default module.exports; diff --git a/Source/ThirdParty/kdbush.js b/Source/ThirdParty/kdbush.js index 91dfa143578..ed89abe0c93 100644 --- a/Source/ThirdParty/kdbush.js +++ b/Source/ThirdParty/kdbush.js @@ -1,6 +1,3 @@ -define([], function() { -'use strict'; - function kdbush(points, getX, getY, nodeSize, ArrayType) { return new KDBush(points, getX, getY, nodeSize, ArrayType); } @@ -191,5 +188,4 @@ function sqDist(ax, ay, bx, by) { return dx * dx + dy * dy; } -return kdbush; -}); +export default kdbush; diff --git a/Source/ThirdParty/knockout-3.5.0.js b/Source/ThirdParty/knockout-3.5.0.js index fccfc186f88..48df2cd8e53 100644 --- a/Source/ThirdParty/knockout-3.5.0.js +++ b/Source/ThirdParty/knockout-3.5.0.js @@ -1,3 +1,6 @@ +var exports = {}; +var module = { exports: exports }; + /*! * Knockout JavaScript library v3.5.0 * (c) The Knockout.js team - http://knockoutjs.com/ @@ -136,3 +139,5 @@ h.beforeRemove?a.na:a.removeNode);var M,O,P;try{P=e.ownerDocument.activeElement} 0;Ea.a.W?0:b.nodes)?b.nodes():null)return a.a.la(c.cloneNode(!0).childNodes);b=b.text();return a.a.ta(b,e)};a.ba.Na=new a.ba;a.ec(a.ba.Na);a.b("nativeTemplateEngine",a.ba);(function(){a.Za=function(){var a=this.Gd=function(){if(!v|| !v.tmpl)return 0;try{if(0<=v.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,f,g){g=g||w;f=f||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=v.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=v.extend({koBindingContext:e},f.templateOptions);e=v.tmpl(h,b,e);e.appendTo(g.createElement("div")); v.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){w.write(" - - - + diff --git a/Specs/karma-main.js b/Specs/karma-main.js index 0b46974e54e..44f130e7b53 100644 --- a/Specs/karma-main.js +++ b/Specs/karma-main.js @@ -1,73 +1,19 @@ -(function() { - /*global __karma__,require*/ - 'use strict'; - - var included = ''; - var excluded = ''; - var webglValidation = false; - var webglStub = false; - var release = false; - - if(__karma__.config.args){ - included = __karma__.config.args[0]; - excluded = __karma__.config.args[1]; - webglValidation = __karma__.config.args[2]; - webglStub = __karma__.config.args[3]; - release = __karma__.config.args[4]; - } - - var toRequire = ['Cesium']; - - if (release) { - require.config({ - baseUrl : '/base/Build/Cesium', - waitSeconds : 0 - }); - toRequire.push('../Stubs/paths'); - } else { - require.config({ - baseUrl : '/base/Source', - waitSeconds : 0 - }); - } - - require(toRequire, function (Cesium, paths) { - if (release) { - paths.Specs = '../../Specs'; - paths.Source = '../../Source'; - paths.Stubs = '../Stubs'; - - require.config({ - paths: paths, - shim: { - 'Cesium': { - exports: 'Cesium' - } - } - }); - } else { - require.config({ - paths: { - 'Specs': '../Specs', - 'Source' : '.' - } - }); - } - - require([ - 'Specs/customizeJasmine' - ], function( - customizeJasmine) { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; - customizeJasmine(jasmine.getEnv(), included, excluded, webglValidation, webglStub, release); - - var specFiles = Object.keys(__karma__.files).filter(function(file) { - return /Spec\.js$/.test(file); - }); - - require(specFiles, function() { - __karma__.start(); - }); - }); - }); -})(); +/*global __karma__*/ +import customizeJasmine from './customizeJasmine.js'; + +var included = ''; +var excluded = ''; +var webglValidation = false; +var webglStub = false; +var release = false; + +if (__karma__.config.args) { + included = __karma__.config.args[0]; + excluded = __karma__.config.args[1]; + webglValidation = __karma__.config.args[2]; + webglStub = __karma__.config.args[3]; + release = __karma__.config.args[4]; +} + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; +customizeJasmine(jasmine.getEnv(), included, excluded, webglValidation, webglStub, release); diff --git a/Specs/karma.conf.js b/Specs/karma.conf.js index f1323de2af6..c4c4a8358b9 100644 --- a/Specs/karma.conf.js +++ b/Specs/karma.conf.js @@ -11,7 +11,7 @@ module.exports = function(config) { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks : ['jasmine', 'requirejs', 'detectBrowsers'], + frameworks : ['jasmine', 'detectBrowsers'], client: { captureConsole: false, @@ -27,9 +27,9 @@ module.exports = function(config) { // list of files / patterns to load in the browser files : [ - 'Specs/karma-main.js', - {pattern : 'Source/**', included : false}, - {pattern : 'Specs/**', included : false} + { pattern: 'Specs/karma-main.js', included: true, type: 'module' }, + { pattern: 'Source/**', included: false, type: 'module' }, + { pattern: 'Specs/**', included: true, type: 'module' } ], proxies : { @@ -37,7 +37,12 @@ module.exports = function(config) { }, // list of files to exclude - exclude : [], + exclude: [ + 'Specs/TestWorkers/**', + 'Specs/SpecList.js', + 'Specs/SpecRunner.js', + 'Specs/spec-main.js' + ], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor diff --git a/Specs/spec-main.js b/Specs/spec-main.js index 84ffc4376e7..db832670337 100644 --- a/Specs/spec-main.js +++ b/Specs/spec-main.js @@ -1,5 +1,5 @@ /** - This is a version of Jasmine's boot.js modified to work with specs defined with AMD. The original comments from boot.js follow. + This is a version of Jasmine's boot.js modified to work with specs defined with ES6. The original comments from boot.js follow. Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. @@ -10,66 +10,25 @@ [jasmine-gem]: http://github.com/pivotal/jasmine-gem */ -/*global require*/ +import * as Cesium from '../Source/Cesium.js'; +import addDefaultMatchers from './addDefaultMatchers.js'; +import equalsMethodEqualityTester from './equalsMethodEqualityTester.js'; -(function() { - 'use strict'; + // set this for uniform test resolution across devices + window.devicePixelRatio = 1; - // set this for uniform test resolution across devices - window.devicePixelRatio = 1; - - function getQueryParameter(name) { - var match = new RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search); - return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); - } - - var built = getQueryParameter('built'); - var release = getQueryParameter('release'); - - var toRequire = ['Cesium']; - - if (built) { - require.config({ - waitSeconds: 30, - baseUrl: getQueryParameter('baseUrl') || '../Build/Cesium', - paths: { - 'Stubs': '../Stubs', - 'Specs': '../../Specs', - 'Source' : '../../Source' - }, - shim: { - 'Cesium': { - exports: 'Cesium' - } - } - }); - - toRequire.push('./Stubs/paths'); - } else { - require.config({ - waitSeconds: 30, - baseUrl: getQueryParameter('baseUrl') || '../Source', - paths: { - 'Specs': '../Specs', - 'Source' : '.' - } - }); - } + function getQueryParameter(name) { + var match = new RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search); + return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); + } - require(toRequire, function( - Cesium, - paths) { + var built = getQueryParameter('built'); + var release = getQueryParameter('release'); /*global jasmineRequire,jasmine,exports,specs*/ var when = Cesium.when; - if (typeof paths !== 'undefined') { - require.config({ - paths : paths - }); - } - /** * ## Require & Instantiate * @@ -346,17 +305,15 @@ * * Load the modules via AMD, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. */ - var modules = ['Specs/addDefaultMatchers', 'Specs/equalsMethodEqualityTester'].concat(specs); - require(modules, function(addDefaultMatchers, equalsMethodEqualityTester) { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; - htmlReporter.initialize(); + jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; - var release = getQueryParameter('release'); - env.beforeEach(function() { addDefaultMatchers(!release).call(env); }); - env.beforeEach(function() { env.addCustomEqualityTester(equalsMethodEqualityTester); }); + htmlReporter.initialize(); + var release = getQueryParameter('release'); + env.beforeEach(function() { addDefaultMatchers(!release).call(env); }); + env.beforeEach(function() { env.addCustomEqualityTester(equalsMethodEqualityTester); }); + + import('./SpecList.js').then(function() { env.execute(); - }); - }); -})(); + }) diff --git a/gulpfile.js b/gulpfile.js index 211b88df79f..1741d66c0ae 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -732,13 +732,16 @@ gulp.task('coverage', function(done) { suppressSkipped: true }, preprocessors: { - 'Source/Core/**/*.js': ['coverage'], - 'Source/DataSources/**/*.js': ['coverage'], - 'Source/Renderer/**/*.js': ['coverage'], - 'Source/Scene/**/*.js': ['coverage'], - 'Source/Shaders/**/*.js': ['coverage'], - 'Source/Widgets/**/*.js': ['coverage'], - 'Source/Workers/**/*.js': ['coverage'] + 'Source/Core/**/*.js': ['karma-coverage-istanbul-instrumenter'], + 'Source/DataSources/**/*.js': ['karma-coverage-istanbul-instrumenter'], + 'Source/Renderer/**/*.js': ['karma-coverage-istanbul-instrumenter'], + 'Source/Scene/**/*.js': ['karma-coverage-istanbul-instrumenter'], + 'Source/Shaders/**/*.js': ['karma-coverage-istanbul-instrumenter'], + 'Source/Widgets/**/*.js': ['karma-coverage-istanbul-instrumenter'], + 'Source/Workers/**/*.js': ['karma-coverage-istanbul-instrumenter'] + }, + coverageIstanbulInstrumenter: { + esModules: true }, reporters: ['spec', 'coverage'], coverageReporter: { @@ -789,9 +792,9 @@ gulp.task('test', function(done) { } var files = [ - 'Specs/karma-main.js', - {pattern : 'Source/**', included : false}, - {pattern : 'Specs/**', included : false} + { pattern: 'Specs/karma-main.js', included: true, type: 'module' }, + { pattern: 'Source/**', included: false, type: 'module' }, + { pattern: 'Specs/**', included: true, type: 'module' } ]; if (release) { @@ -1317,14 +1320,13 @@ function createCesiumJs() { } function createSpecList() { - var specFiles = globby.sync(['Specs/**/*.js', '!Specs/*.js']); - var specs = []; + var specFiles = globby.sync(['Specs/**/*Spec.js']); + var contents = ''; specFiles.forEach(function(file) { - specs.push("'" + filePathToModuleId(file) + "'"); + contents += "import './" + filePathToModuleId(file).replace('Specs/', '') + ".js';\n"; }); - var contents = '/*eslint-disable no-unused-vars*/\n/*eslint-disable no-implicit-globals*/\nvar specs = [' + specs.join(',') + '];\n'; fs.writeFileSync(path.join('Specs', 'SpecList.js'), contents); } diff --git a/package.json b/package.json index afe4395083d..5bcd37ef366 100644 --- a/package.json +++ b/package.json @@ -56,13 +56,13 @@ "karma": "^4.0.0", "karma-chrome-launcher": "^3.1.0", "karma-coverage": "^2.0.1", + "karma-coverage-istanbul-instrumenter": "^1.0.1", "karma-detect-browsers": "^2.2.3", "karma-edge-launcher": "^0.4.2", "karma-firefox-launcher": "^1.0.0", "karma-ie-launcher": "^1.0.0", "karma-jasmine": "^2.0.0", "karma-longest-reporter": "^1.1.0", - "karma-requirejs": "^1.1.0", "karma-safari-launcher": "^1.0.0", "karma-spec-reporter": "^0.0.32", "merge-stream": "^2.0.0", From 8ec945fe196130c83ad68ba5d10be03484a12b67 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Fri, 20 Sep 2019 23:31:36 -0400 Subject: [PATCH 04/20] Remove requirejs and update packaging for ES6 1. Switch to rollup for combining/minifying JS code. 2. Switch to clean-css for combining/minifying CSS code. 3. Get eslint passing 4. Switch to `esm` for Node.JS ES6 support and make Node.js work again, which required re-fixing third-party code shims and upgrading AutoLinker and topojson 5. Remove `generateStubs` which is no longer being used. 6. Fix some merge issues with missing ES6 module imports 7. Deleted unneeded `Source/main.js` 8. Add back VERSION property on Cesium object. --- .eslintignore | 2 + .eslintrc.json | 18 +- .npmignore | 2 - Apps/CesiumViewer/index.html | 2 +- Apps/Sandcastle/.eslintrc.json | 4 + Apps/TimelineDemo/.eslintrc.json | 10 + Source/Core/buildModuleUrl.js | 8 +- Source/DataSources/CzmlDataSource.js | 1 + Source/DataSources/GeoJsonDataSource.js | 1 + Source/DataSources/KmlDataSource.js | 4 +- Source/Scene/Model.js | 1 + Source/ThirdParty/Autolinker.js | 6955 ++++++++++++-------- Source/ThirdParty/LercDecode.js | 21 +- Source/ThirdParty/NoSleep.js | 7 +- Source/ThirdParty/jsep.js | 7 +- Source/ThirdParty/knockout-3.5.0.js | 7 +- Source/ThirdParty/pako_inflate.js | 7 +- Source/ThirdParty/topojson.js | 2117 ++++-- Source/Workers/createGeometry.js | 1 + Source/Workers/decodeDraco.js | 1 + Source/main.js | 18 - Specs/.eslintrc.json | 12 +- Specs/Core/TaskProcessorSpec.js | 1 + Specs/DataSources/CzmlDataSourceSpec.js | 1 + Specs/DataSources/GeoJsonDataSourceSpec.js | 1 + Specs/DataSources/KmlDataSourceSpec.js | 1 + Specs/Scene/ModelSpec.js | 1 + Specs/TestWorkers/.eslintrc.json | 10 + Tools/eslint-config-cesium/browser.js | 7 +- Tools/jsdoc/conf.json | 2 +- gulpfile.js | 418 +- index.js | 14 +- package.json | 8 +- 33 files changed, 6095 insertions(+), 3575 deletions(-) create mode 100644 Apps/TimelineDemo/.eslintrc.json delete mode 100644 Source/main.js create mode 100644 Specs/TestWorkers/.eslintrc.json diff --git a/.eslintignore b/.eslintignore index 66f85f5764a..2e3b462086b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -10,3 +10,5 @@ ThirdParty/** Tools/** Apps/Sandcastle/jsHintOptions.js Apps/Sandcastle/gallery/gallery-index.js +Source/Core/buildModuleUrl.js +Specs/spec-main.js diff --git a/.eslintrc.json b/.eslintrc.json index f3ddd763a13..6c69dcbf3be 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,10 +3,20 @@ "plugins": [ "html" ], - "parserOptions": { - "sourceType": "module" - }, "rules": { "no-unused-vars": ["error", {"vars": "all", "args": "none"}] - } + }, + "overrides": [ + { + "files": [ + "index.js", + "server.js", + "gulpfile.js", + "Source/Workers/transferTypedArrayTest.js" + ], + "parserOptions": { + "sourceType": "script" + } + } + ] } diff --git a/.npmignore b/.npmignore index da787f59d72..4736b2d3208 100644 --- a/.npmignore +++ b/.npmignore @@ -13,7 +13,6 @@ /Apps /Build/Coverage /Build/minifyShaders.state -/Build/Stubs /Build/Documentation /Cesium-*.zip /Documentation @@ -24,7 +23,6 @@ /launches /server.js /Source/copyrightHeader.js -/Source/main.js /Specs /ThirdParty /Tools diff --git a/Apps/CesiumViewer/index.html b/Apps/CesiumViewer/index.html index 99a6b82bcfd..35b67a8902b 100644 --- a/Apps/CesiumViewer/index.html +++ b/Apps/CesiumViewer/index.html @@ -10,10 +10,10 @@ Cesium Viewer -
+ diff --git a/Apps/Sandcastle/.eslintrc.json b/Apps/Sandcastle/.eslintrc.json index 0983ac08d13..28b3b16677e 100644 --- a/Apps/Sandcastle/.eslintrc.json +++ b/Apps/Sandcastle/.eslintrc.json @@ -1,5 +1,8 @@ { "extends": "../../.eslintrc.json", + "env": { + "amd": true + }, "globals": { "JSON": true, "require": true, @@ -8,6 +11,7 @@ "Cesium": true }, "parserOptions": { + "ecmaVersion": 5, "sourceType": "script" }, "rules": { diff --git a/Apps/TimelineDemo/.eslintrc.json b/Apps/TimelineDemo/.eslintrc.json new file mode 100644 index 00000000000..50014f5ec8f --- /dev/null +++ b/Apps/TimelineDemo/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": "../../.eslintrc.json", + "env": { + "amd": true + }, + "parserOptions": { + "ecmaVersion": 5, + "sourceType": "script" + } +} diff --git a/Source/Core/buildModuleUrl.js b/Source/Core/buildModuleUrl.js index 724f3d992e6..401606c6629 100644 --- a/Source/Core/buildModuleUrl.js +++ b/Source/Core/buildModuleUrl.js @@ -46,12 +46,16 @@ import Resource from './Resource.js'; baseUrlString = CESIUM_BASE_URL; } else if (typeof define === 'object' && defined(define.amd) && !define.amd.toUrlUndefined && defined(require.toUrl)) { baseUrlString = getAbsoluteUri('..', buildModuleUrl('Core/buildModuleUrl.js')); - } else if (defined(import.meta.url)){ - baseUrlString = getAbsoluteUri('..', import.meta.url) + } else if (/\/buildModuleUrl\.js$/.test(import.meta.url)) { + baseUrlString = getAbsoluteUri('..', import.meta.url); } else { baseUrlString = getBaseUrlFromCesiumScript(); } + if (baseUrlString === '') { + baseUrlString = '.'; + } + //>>includeStart('debug', pragmas.debug); if (!defined(baseUrlString)) { throw new DeveloperError('Unable to determine Cesium base URL automatically, try defining a global variable called CESIUM_BASE_URL.'); diff --git a/Source/DataSources/CzmlDataSource.js b/Source/DataSources/CzmlDataSource.js index 1ce927e6ccd..4e019a937ae 100644 --- a/Source/DataSources/CzmlDataSource.js +++ b/Source/DataSources/CzmlDataSource.js @@ -7,6 +7,7 @@ import ClockRange from '../Core/ClockRange.js'; import ClockStep from '../Core/ClockStep.js'; import Color from '../Core/Color.js'; import CornerType from '../Core/CornerType.js'; +import Credit from '../Core/Credit.js'; import createGuid from '../Core/createGuid.js'; import defaultValue from '../Core/defaultValue.js'; import defined from '../Core/defined.js'; diff --git a/Source/DataSources/GeoJsonDataSource.js b/Source/DataSources/GeoJsonDataSource.js index 5997d14b895..68273113dd7 100644 --- a/Source/DataSources/GeoJsonDataSource.js +++ b/Source/DataSources/GeoJsonDataSource.js @@ -2,6 +2,7 @@ import ArcType from '../Core/ArcType.js'; import Cartesian3 from '../Core/Cartesian3.js'; import Color from '../Core/Color.js'; import createGuid from '../Core/createGuid.js'; +import Credit from '../Core/Credit.js'; import defaultValue from '../Core/defaultValue.js'; import defined from '../Core/defined.js'; import defineProperties from '../Core/defineProperties.js'; diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 6d2429fbed2..313f3b3990d 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -8,6 +8,7 @@ import ClockRange from '../Core/ClockRange.js'; import ClockStep from '../Core/ClockStep.js'; import Color from '../Core/Color.js'; import createGuid from '../Core/createGuid.js'; +import Credit from '../Core/Credit.js'; import defaultValue from '../Core/defaultValue.js'; import defined from '../Core/defined.js'; import defineProperties from '../Core/defineProperties.js'; @@ -137,9 +138,8 @@ import WallGraphics from './WallGraphics.js'; var autolinker = new Autolinker({ stripPrefix : false, - twitter : false, email : false, - replaceFn : function(linker, match) { + replaceFn : function(match) { if (!match.protocolUrlMatch) { //Prevent matching of non-explicit urls. //i.e. foo.id won't match but http://foo.id will diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index f5d9c238115..3d80935d6f4 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -8,6 +8,7 @@ import clone from '../Core/clone.js'; import Color from '../Core/Color.js'; import combine from '../Core/combine.js'; import createGuid from '../Core/createGuid.js'; +import Credit from '../Core/Credit.js'; import defaultValue from '../Core/defaultValue.js'; import defined from '../Core/defined.js'; import defineProperties from '../Core/defineProperties.js'; diff --git a/Source/ThirdParty/Autolinker.js b/Source/ThirdParty/Autolinker.js index 76d76b6b0ff..e2ca956c056 100644 --- a/Source/ThirdParty/Autolinker.js +++ b/Source/ThirdParty/Autolinker.js @@ -1,2761 +1,4216 @@ -var exports = {}; -var module = { exports: exports }; - -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module unless amdModuleId is set - define([], function () { - return (root['Autolinker'] = factory()); - }); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - root['Autolinker'] = factory(); - } -}(this, function () { +var tmp = {}; /*! * Autolinker.js - * 0.17.1 + * 3.11.0 * - * Copyright(c) 2015 Gregory Jacobs - * MIT Licensed. http://www.opensource.org/licenses/mit-license.php + * Copyright(c) 2019 Gregory Jacobs + * MIT License * * https://github.com/gregjacobs/Autolinker.js */ -/** - * @class Autolinker - * @extends Object - * - * Utility class used to process a given string of text, and wrap the matches in - * the appropriate anchor (<a>) tags to turn them into links. - * - * Any of the configuration options may be provided in an Object (map) provided - * to the Autolinker constructor, which will configure how the {@link #link link()} - * method will process the links. - * - * For example: - * - * var autolinker = new Autolinker( { - * newWindow : false, - * truncate : 30 - * } ); - * - * var html = autolinker.link( "Joe went to www.yahoo.com" ); - * // produces: 'Joe went to yahoo.com' - * - * - * The {@link #static-link static link()} method may also be used to inline options into a single call, which may - * be more convenient for one-off uses. For example: - * - * var html = Autolinker.link( "Joe went to www.yahoo.com", { - * newWindow : false, - * truncate : 30 - * } ); - * // produces: 'Joe went to yahoo.com' - * - * - * ## Custom Replacements of Links - * - * If the configuration options do not provide enough flexibility, a {@link #replaceFn} - * may be provided to fully customize the output of Autolinker. This function is - * called once for each URL/Email/Phone#/Twitter Handle/Hashtag match that is - * encountered. - * - * For example: - * - * var input = "..."; // string with URLs, Email Addresses, Phone #s, Twitter Handles, and Hashtags - * - * var linkedText = Autolinker.link( input, { - * replaceFn : function( autolinker, match ) { - * console.log( "href = ", match.getAnchorHref() ); - * console.log( "text = ", match.getAnchorText() ); - * - * switch( match.getType() ) { - * case 'url' : - * console.log( "url: ", match.getUrl() ); - * - * if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes - * tag.setAttr( 'rel', 'nofollow' ); - * tag.addClass( 'external-link' ); - * - * return tag; - * - * } else { - * return true; // let Autolinker perform its normal anchor tag replacement - * } - * - * case 'email' : - * var email = match.getEmail(); - * console.log( "email: ", email ); - * - * if( email === "my@own.address" ) { - * return false; // don't auto-link this particular email address; leave as-is - * } else { - * return; // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`) - * } - * - * case 'phone' : - * var phoneNumber = match.getPhoneNumber(); - * console.log( phoneNumber ); - * - * return '' + phoneNumber + ''; - * - * case 'twitter' : - * var twitterHandle = match.getTwitterHandle(); - * console.log( twitterHandle ); - * - * return '' + twitterHandle + ''; - * - * case 'hashtag' : - * var hashtag = match.getHashtag(); - * console.log( hashtag ); - * - * return '' + hashtag + ''; - * } - * } - * } ); - * - * - * The function may return the following values: - * - * - `true` (Boolean): Allow Autolinker to replace the match as it normally would. - * - `false` (Boolean): Do not replace the current match at all - leave as-is. - * - Any String: If a string is returned from the function, the string will be used directly as the replacement HTML for - * the match. - * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify an HTML tag before writing out its HTML text. - * - * @constructor - * @param {Object} [config] The configuration options for the Autolinker instance, specified in an Object (map). - */ -var Autolinker = function( cfg ) { - Autolinker.Util.assign( this, cfg ); // assign the properties of `cfg` onto the Autolinker instance. Prototype properties will be used for missing configs. - - // Validate the value of the `hashtag` cfg. - var hashtag = this.hashtag; - if( hashtag !== false && hashtag !== 'twitter' && hashtag !== 'facebook' ) { - throw new Error( "invalid `hashtag` cfg - see docs" ); - } -}; - -Autolinker.prototype = { - constructor : Autolinker, // fix constructor property - - /** - * @cfg {Boolean} urls - * - * `true` if miscellaneous URLs should be automatically linked, `false` if they should not be. - */ - urls : true, - - /** - * @cfg {Boolean} email - * - * `true` if email addresses should be automatically linked, `false` if they should not be. - */ - email : true, - - /** - * @cfg {Boolean} twitter - * - * `true` if Twitter handles ("@example") should be automatically linked, `false` if they should not be. - */ - twitter : true, - - /** - * @cfg {Boolean} phone - * - * `true` if Phone numbers ("(555)555-5555") should be automatically linked, `false` if they should not be. - */ - phone: true, - - /** - * @cfg {Boolean/String} hashtag - * - * A string for the service name to have hashtags (ex: "#myHashtag") - * auto-linked to. The currently-supported values are: - * - * - 'twitter' - * - 'facebook' - * - * Pass `false` to skip auto-linking of hashtags. - */ - hashtag : false, - - /** - * @cfg {Boolean} newWindow - * - * `true` if the links should open in a new window, `false` otherwise. - */ - newWindow : true, - - /** - * @cfg {Boolean} stripPrefix - * - * `true` if 'http://' or 'https://' and/or the 'www.' should be stripped - * from the beginning of URL links' text, `false` otherwise. - */ - stripPrefix : true, - - /** - * @cfg {Number} truncate - * - * A number for how many characters long matched text should be truncated to inside the text of - * a link. If the matched text is over this number of characters, it will be truncated to this length by - * adding a two period ellipsis ('..') to the end of the string. - * - * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters might look - * something like this: 'yahoo.com/some/long/pat..' - */ - truncate : undefined, - - /** - * @cfg {String} className - * - * A CSS class name to add to the generated links. This class will be added to all links, as well as this class - * plus match suffixes for styling url/email/phone/twitter/hashtag links differently. - * - * For example, if this config is provided as "myLink", then: - * - * - URL links will have the CSS classes: "myLink myLink-url" - * - Email links will have the CSS classes: "myLink myLink-email", and - * - Twitter links will have the CSS classes: "myLink myLink-twitter" - * - Phone links will have the CSS classes: "myLink myLink-phone" - * - Hashtag links will have the CSS classes: "myLink myLink-hashtag" - */ - className : "", - - /** - * @cfg {Function} replaceFn - * - * A function to individually process each match found in the input string. - * - * See the class's description for usage. - * - * This function is called with the following parameters: - * - * @cfg {Autolinker} replaceFn.autolinker The Autolinker instance, which may be used to retrieve child objects from (such - * as the instance's {@link #getTagBuilder tag builder}). - * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which can be used to retrieve information about the - * match that the `replaceFn` is currently processing. See {@link Autolinker.match.Match} subclasses for details. - */ - - - /** - * @private - * @property {Autolinker.htmlParser.HtmlParser} htmlParser - * - * The HtmlParser instance used to skip over HTML tags, while finding text nodes to process. This is lazily instantiated - * in the {@link #getHtmlParser} method. - */ - htmlParser : undefined, - - /** - * @private - * @property {Autolinker.matchParser.MatchParser} matchParser - * - * The MatchParser instance used to find matches in the text nodes of an input string passed to - * {@link #link}. This is lazily instantiated in the {@link #getMatchParser} method. - */ - matchParser : undefined, - - /** - * @private - * @property {Autolinker.AnchorTagBuilder} tagBuilder - * - * The AnchorTagBuilder instance used to build match replacement anchor tags. Note: this is lazily instantiated - * in the {@link #getTagBuilder} method. - */ - tagBuilder : undefined, - - /** - * Automatically links URLs, Email addresses, Phone numbers, Twitter - * handles, and Hashtags found in the given chunk of HTML. Does not link - * URLs found within HTML tags. - * - * For instance, if given the text: `You should go to http://www.yahoo.com`, - * then the result will be `You should go to - * <a href="http://www.yahoo.com">http://www.yahoo.com</a>` - * - * This method finds the text around any HTML elements in the input - * `textOrHtml`, which will be the text that is processed. Any original HTML - * elements will be left as-is, as well as the text that is already wrapped - * in anchor (<a>) tags. - * - * @param {String} textOrHtml The HTML or text to autolink matches within - * (depending on if the {@link #urls}, {@link #email}, {@link #phone}, - * {@link #twitter}, and {@link #hashtag} options are enabled). - * @return {String} The HTML, with matches automatically linked. - */ - link : function( textOrHtml ) { - var htmlParser = this.getHtmlParser(), - htmlNodes = htmlParser.parse( textOrHtml ), - anchorTagStackCount = 0, // used to only process text around anchor tags, and any inner text/html they may have - resultHtml = []; - - for( var i = 0, len = htmlNodes.length; i < len; i++ ) { - var node = htmlNodes[ i ], - nodeType = node.getType(), - nodeText = node.getText(); - - if( nodeType === 'element' ) { - // Process HTML nodes in the input `textOrHtml` - if( node.getTagName() === 'a' ) { - if( !node.isClosing() ) { // it's the start tag - anchorTagStackCount++; - } else { // it's the end tag - anchorTagStackCount = Math.max( anchorTagStackCount - 1, 0 ); // attempt to handle extraneous tags by making sure the stack count never goes below 0 - } - } - resultHtml.push( nodeText ); // now add the text of the tag itself verbatim - - } else if( nodeType === 'entity' || nodeType === 'comment' ) { - resultHtml.push( nodeText ); // append HTML entity nodes (such as ' ') or HTML comments (such as '') verbatim - - } else { - // Process text nodes in the input `textOrHtml` - if( anchorTagStackCount === 0 ) { - // If we're not within an tag, process the text node to linkify - var linkifiedStr = this.linkifyStr( nodeText ); - resultHtml.push( linkifiedStr ); - - } else { - // `text` is within an tag, simply append the text - we do not want to autolink anything - // already within an ... tag - resultHtml.push( nodeText ); - } - } - } - - return resultHtml.join( "" ); - }, - - /** - * Process the text that lies in between HTML tags, performing the anchor - * tag replacements for the matches, and returns the string with the - * replacements made. - * - * This method does the actual wrapping of matches with anchor tags. - * - * @private - * @param {String} str The string of text to auto-link. - * @return {String} The text with anchor tags auto-filled. - */ - linkifyStr : function( str ) { - return this.getMatchParser().replace( str, this.createMatchReturnVal, this ); - }, - - - /** - * Creates the return string value for a given match in the input string, - * for the {@link #linkifyStr} method. - * - * This method handles the {@link #replaceFn}, if one was provided. - * - * @private - * @param {Autolinker.match.Match} match The Match object that represents the match. - * @return {String} The string that the `match` should be replaced with. This is usually the anchor tag string, but - * may be the `matchStr` itself if the match is not to be replaced. - */ - createMatchReturnVal : function( match ) { - // Handle a custom `replaceFn` being provided - var replaceFnResult; - if( this.replaceFn ) { - replaceFnResult = this.replaceFn.call( this, this, match ); // Autolinker instance is the context, and the first arg - } - - if( typeof replaceFnResult === 'string' ) { - return replaceFnResult; // `replaceFn` returned a string, use that - - } else if( replaceFnResult === false ) { - return match.getMatchedText(); // no replacement for the match - - } else if( replaceFnResult instanceof Autolinker.HtmlTag ) { - return replaceFnResult.toAnchorString(); - - } else { // replaceFnResult === true, or no/unknown return value from function - // Perform Autolinker's default anchor tag generation - var tagBuilder = this.getTagBuilder(), - anchorTag = tagBuilder.build( match ); // returns an Autolinker.HtmlTag instance - - return anchorTag.toAnchorString(); - } - }, - - - /** - * Lazily instantiates and returns the {@link #htmlParser} instance for this Autolinker instance. - * - * @protected - * @return {Autolinker.htmlParser.HtmlParser} - */ - getHtmlParser : function() { - var htmlParser = this.htmlParser; - - if( !htmlParser ) { - htmlParser = this.htmlParser = new Autolinker.htmlParser.HtmlParser(); - } - - return htmlParser; - }, - - - /** - * Lazily instantiates and returns the {@link #matchParser} instance for this Autolinker instance. - * - * @protected - * @return {Autolinker.matchParser.MatchParser} - */ - getMatchParser : function() { - var matchParser = this.matchParser; - - if( !matchParser ) { - matchParser = this.matchParser = new Autolinker.matchParser.MatchParser( { - urls : this.urls, - email : this.email, - twitter : this.twitter, - phone : this.phone, - hashtag : this.hashtag, - stripPrefix : this.stripPrefix - } ); - } - - return matchParser; - }, - - - /** - * Returns the {@link #tagBuilder} instance for this Autolinker instance, lazily instantiating it - * if it does not yet exist. - * - * This method may be used in a {@link #replaceFn} to generate the {@link Autolinker.HtmlTag HtmlTag} instance that - * Autolinker would normally generate, and then allow for modifications before returning it. For example: - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance - * tag.setAttr( 'rel', 'nofollow' ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test google.com - * - * @return {Autolinker.AnchorTagBuilder} - */ - getTagBuilder : function() { - var tagBuilder = this.tagBuilder; - - if( !tagBuilder ) { - tagBuilder = this.tagBuilder = new Autolinker.AnchorTagBuilder( { - newWindow : this.newWindow, - truncate : this.truncate, - className : this.className - } ); - } - - return tagBuilder; - } - -}; - - -/** - * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles, - * and Hashtags found in the given chunk of HTML. Does not link URLs found - * within HTML tags. - * - * For instance, if given the text: `You should go to http://www.yahoo.com`, - * then the result will be `You should go to <a href="http://www.yahoo.com">http://www.yahoo.com</a>` - * - * Example: - * - * var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } ); - * // Produces: "Go to google.com" - * - * @static - * @param {String} textOrHtml The HTML or text to find matches within (depending - * on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #twitter}, - * and {@link #hashtag} options are enabled). - * @param {Object} [options] Any of the configuration options for the Autolinker - * class, specified in an Object (map). See the class description for an - * example call. - * @return {String} The HTML text, with matches automatically linked. - */ -Autolinker.link = function( textOrHtml, options ) { - var autolinker = new Autolinker( options ); - return autolinker.link( textOrHtml ); -}; - - -// Autolinker Namespaces -Autolinker.match = {}; -Autolinker.htmlParser = {}; -Autolinker.matchParser = {}; - -/*global Autolinker */ -/*jshint eqnull:true, boss:true */ -/** - * @class Autolinker.Util - * @singleton - * - * A few utility methods for Autolinker. - */ -Autolinker.Util = { - - /** - * @property {Function} abstractMethod - * - * A function object which represents an abstract method. - */ - abstractMethod : function() { throw "abstract"; }, - - - /** - * @private - * @property {RegExp} trimRegex - * - * The regular expression used to trim the leading and trailing whitespace - * from a string. - */ - trimRegex : /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - - /** - * Assigns (shallow copies) the properties of `src` onto `dest`. - * - * @param {Object} dest The destination object. - * @param {Object} src The source object. - * @return {Object} The destination object (`dest`) - */ - assign : function( dest, src ) { - for( var prop in src ) { - if( src.hasOwnProperty( prop ) ) { - dest[ prop ] = src[ prop ]; - } - } - - return dest; - }, - - - /** - * Extends `superclass` to create a new subclass, adding the `protoProps` to the new subclass's prototype. - * - * @param {Function} superclass The constructor function for the superclass. - * @param {Object} protoProps The methods/properties to add to the subclass's prototype. This may contain the - * special property `constructor`, which will be used as the new subclass's constructor function. - * @return {Function} The new subclass function. - */ - extend : function( superclass, protoProps ) { - var superclassProto = superclass.prototype; - - var F = function() {}; - F.prototype = superclassProto; - - var subclass; - if( protoProps.hasOwnProperty( 'constructor' ) ) { - subclass = protoProps.constructor; - } else { - subclass = function() { superclassProto.constructor.apply( this, arguments ); }; - } - - var subclassProto = subclass.prototype = new F(); // set up prototype chain - subclassProto.constructor = subclass; // fix constructor property - subclassProto.superclass = superclassProto; - - delete protoProps.constructor; // don't re-assign constructor property to the prototype, since a new function may have been created (`subclass`), which is now already there - Autolinker.Util.assign( subclassProto, protoProps ); - - return subclass; - }, - - - /** - * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the - * end of the string (by default, two periods: '..'). If the `str` length does not exceed - * `len`, the string will be returned unchanged. - * - * @param {String} str The string to truncate and add an ellipsis to. - * @param {Number} truncateLen The length to truncate the string at. - * @param {String} [ellipsisChars=..] The ellipsis character(s) to add to the end of `str` - * when truncated. Defaults to '..' - */ - ellipsis : function( str, truncateLen, ellipsisChars ) { - if( str.length > truncateLen ) { - ellipsisChars = ( ellipsisChars == null ) ? '..' : ellipsisChars; - str = str.substring( 0, truncateLen - ellipsisChars.length ) + ellipsisChars; - } - return str; - }, - - - /** - * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below). - * - * @param {Array} arr The array to find an element of. - * @param {*} element The element to find in the array, and return the index of. - * @return {Number} The index of the `element`, or -1 if it was not found. - */ - indexOf : function( arr, element ) { - if( Array.prototype.indexOf ) { - return arr.indexOf( element ); - - } else { - for( var i = 0, len = arr.length; i < len; i++ ) { - if( arr[ i ] === element ) return i; - } - return -1; - } - }, - - - - /** - * Performs the functionality of what modern browsers do when `String.prototype.split()` is called - * with a regular expression that contains capturing parenthesis. - * - * For example: - * - * // Modern browsers: - * "a,b,c".split( /(,)/ ); // --> [ 'a', ',', 'b', ',', 'c' ] - * - * // Old IE (including IE8): - * "a,b,c".split( /(,)/ ); // --> [ 'a', 'b', 'c' ] - * - * This method emulates the functionality of modern browsers for the old IE case. - * - * @param {String} str The string to split. - * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting - * character(s) will be spliced into the array, as in the "modern browsers" example in the - * description of this method. - * Note #1: the supplied regular expression **must** have the 'g' flag specified. - * Note #2: for simplicity's sake, the regular expression does not need - * to contain capturing parenthesis - it will be assumed that any match has them. - * @return {String[]} The split array of strings, with the splitting character(s) included. - */ - splitAndCapture : function( str, splitRegex ) { - if( !splitRegex.global ) throw new Error( "`splitRegex` must have the 'g' flag set" ); - - var result = [], - lastIdx = 0, - match; - - while( match = splitRegex.exec( str ) ) { - result.push( str.substring( lastIdx, match.index ) ); - result.push( match[ 0 ] ); // push the splitting char(s) - - lastIdx = match.index + match[ 0 ].length; - } - result.push( str.substring( lastIdx ) ); - - return result; - }, - - - /** - * Trims the leading and trailing whitespace from a string. - * - * @param {String} str The string to trim. - * @return {String} - */ - trim : function( str ) { - return str.replace( this.trimRegex, '' ); - } - -}; -/*global Autolinker */ -/*jshint boss:true */ -/** - * @class Autolinker.HtmlTag - * @extends Object - * - * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically. - * - * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use - * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}. - * - * ## Examples - * - * Example instantiation: - * - * var tag = new Autolinker.HtmlTag( { - * tagName : 'a', - * attrs : { 'href': 'http://google.com', 'class': 'external-link' }, - * innerHtml : 'Google' - * } ); - * - * tag.toAnchorString(); // Google - * - * // Individual accessor methods - * tag.getTagName(); // 'a' - * tag.getAttr( 'href' ); // 'http://google.com' - * tag.hasClass( 'external-link' ); // true - * - * - * Using mutator methods (which may be used in combination with instantiation config properties): - * - * var tag = new Autolinker.HtmlTag(); - * tag.setTagName( 'a' ); - * tag.setAttr( 'href', 'http://google.com' ); - * tag.addClass( 'external-link' ); - * tag.setInnerHtml( 'Google' ); - * - * tag.getTagName(); // 'a' - * tag.getAttr( 'href' ); // 'http://google.com' - * tag.hasClass( 'external-link' ); // true - * - * tag.toAnchorString(); // Google - * - * - * ## Example use within a {@link Autolinker#replaceFn replaceFn} - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text - * tag.setAttr( 'rel', 'nofollow' ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test google.com - * - * - * ## Example use with a new tag for the replacement - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = new Autolinker.HtmlTag( { - * tagName : 'button', - * attrs : { 'title': 'Load URL: ' + match.getAnchorHref() }, - * innerHtml : 'Load URL: ' + match.getAnchorText() - * } ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test - */ -Autolinker.HtmlTag = Autolinker.Util.extend( Object, { - - /** - * @cfg {String} tagName - * - * The tag name. Ex: 'a', 'button', etc. - * - * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString} - * is executed. - */ - - /** - * @cfg {Object.} attrs - * - * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the - * values are the attribute values. - */ - - /** - * @cfg {String} innerHtml - * - * The inner HTML for the tag. - * - * Note the camel case name on `innerHtml`. Acronyms are camelCased in this utility (such as not to run into the acronym - * naming inconsistency that the DOM developers created with `XMLHttpRequest`). You may alternatively use {@link #innerHTML} - * if you prefer, but this one is recommended. - */ - - /** - * @cfg {String} innerHTML - * - * Alias of {@link #innerHtml}, accepted for consistency with the browser DOM api, but prefer the camelCased version - * for acronym names. - */ - - - /** - * @protected - * @property {RegExp} whitespaceRegex - * - * Regular expression used to match whitespace in a string of CSS classes. - */ - whitespaceRegex : /\s+/, - - - /** - * @constructor - * @param {Object} [cfg] The configuration properties for this class, in an Object (map) - */ - constructor : function( cfg ) { - Autolinker.Util.assign( this, cfg ); - - this.innerHtml = this.innerHtml || this.innerHTML; // accept either the camelCased form or the fully capitalized acronym - }, - - - /** - * Sets the tag name that will be used to generate the tag with. - * - * @param {String} tagName - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setTagName : function( tagName ) { - this.tagName = tagName; - return this; - }, - - - /** - * Retrieves the tag name. - * - * @return {String} - */ - getTagName : function() { - return this.tagName || ""; - }, - - - /** - * Sets an attribute on the HtmlTag. - * - * @param {String} attrName The attribute name to set. - * @param {String} attrValue The attribute value to set. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setAttr : function( attrName, attrValue ) { - var tagAttrs = this.getAttrs(); - tagAttrs[ attrName ] = attrValue; - - return this; - }, - - - /** - * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`. - * - * @param {String} name The attribute name to retrieve. - * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag. - */ - getAttr : function( attrName ) { - return this.getAttrs()[ attrName ]; - }, - - - /** - * Sets one or more attributes on the HtmlTag. - * - * @param {Object.} attrs A key/value Object (map) of the attributes to set. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setAttrs : function( attrs ) { - var tagAttrs = this.getAttrs(); - Autolinker.Util.assign( tagAttrs, attrs ); - - return this; - }, - - - /** - * Retrieves the attributes Object (map) for the HtmlTag. - * - * @return {Object.} A key/value object of the attributes for the HtmlTag. - */ - getAttrs : function() { - return this.attrs || ( this.attrs = {} ); - }, - - - /** - * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag. - * - * @param {String} cssClass One or more space-separated CSS classes to set (overwrite). - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setClass : function( cssClass ) { - return this.setAttr( 'class', cssClass ); - }, - - - /** - * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes. - * - * @param {String} cssClass One or more space-separated CSS classes to add. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - addClass : function( cssClass ) { - var classAttr = this.getClass(), - whitespaceRegex = this.whitespaceRegex, - indexOf = Autolinker.Util.indexOf, // to support IE8 and below - classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ), - newClasses = cssClass.split( whitespaceRegex ), - newClass; - - while( newClass = newClasses.shift() ) { - if( indexOf( classes, newClass ) === -1 ) { - classes.push( newClass ); - } - } - - this.getAttrs()[ 'class' ] = classes.join( " " ); - return this; - }, - - - /** - * Convenience method to remove one or more CSS classes from the HtmlTag. - * - * @param {String} cssClass One or more space-separated CSS classes to remove. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - removeClass : function( cssClass ) { - var classAttr = this.getClass(), - whitespaceRegex = this.whitespaceRegex, - indexOf = Autolinker.Util.indexOf, // to support IE8 and below - classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ), - removeClasses = cssClass.split( whitespaceRegex ), - removeClass; - - while( classes.length && ( removeClass = removeClasses.shift() ) ) { - var idx = indexOf( classes, removeClass ); - if( idx !== -1 ) { - classes.splice( idx, 1 ); - } - } - - this.getAttrs()[ 'class' ] = classes.join( " " ); - return this; - }, - - - /** - * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when - * there are multiple. - * - * @return {String} - */ - getClass : function() { - return this.getAttrs()[ 'class' ] || ""; - }, - - - /** - * Convenience method to check if the tag has a CSS class or not. - * - * @param {String} cssClass The CSS class to check for. - * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise. - */ - hasClass : function( cssClass ) { - return ( ' ' + this.getClass() + ' ' ).indexOf( ' ' + cssClass + ' ' ) !== -1; - }, - - - /** - * Sets the inner HTML for the tag. - * - * @param {String} html The inner HTML to set. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setInnerHtml : function( html ) { - this.innerHtml = html; - - return this; - }, - - - /** - * Retrieves the inner HTML for the tag. - * - * @return {String} - */ - getInnerHtml : function() { - return this.innerHtml || ""; - }, - - - /** - * Override of superclass method used to generate the HTML string for the tag. - * - * @return {String} - */ - toAnchorString : function() { - var tagName = this.getTagName(), - attrsStr = this.buildAttrsStr(); - - attrsStr = ( attrsStr ) ? ' ' + attrsStr : ''; // prepend a space if there are actually attributes - - return [ '<', tagName, attrsStr, '>', this.getInnerHtml(), '' ].join( "" ); - }, - - - /** - * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate - * the stringified HtmlTag. - * - * @protected - * @return {String} Example return: `attr1="value1" attr2="value2"` - */ - buildAttrsStr : function() { - if( !this.attrs ) return ""; // no `attrs` Object (map) has been set, return empty string - - var attrs = this.getAttrs(), - attrsArr = []; - - for( var prop in attrs ) { - if( attrs.hasOwnProperty( prop ) ) { - attrsArr.push( prop + '="' + attrs[ prop ] + '"' ); - } - } - return attrsArr.join( " " ); - } - -} ); - -/*global Autolinker */ -/*jshint sub:true */ -/** - * @protected - * @class Autolinker.AnchorTagBuilder - * @extends Object - * - * Builds anchor (<a>) tags for the Autolinker utility when a match is found. - * - * Normally this class is instantiated, configured, and used internally by an {@link Autolinker} instance, but may - * actually be retrieved in a {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag} instances - * which may be modified before returning from the {@link Autolinker#replaceFn replaceFn}. For example: - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance - * tag.setAttr( 'rel', 'nofollow' ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test google.com - */ -Autolinker.AnchorTagBuilder = Autolinker.Util.extend( Object, { - - /** - * @cfg {Boolean} newWindow - * @inheritdoc Autolinker#newWindow - */ - - /** - * @cfg {Number} truncate - * @inheritdoc Autolinker#truncate - */ +(function (global, factory) { + global.Autolinker = factory(); +}(tmp, function () { 'use strict'; + + /** + * Assigns (shallow copies) the properties of `src` onto `dest`, if the + * corresponding property on `dest` === `undefined`. + * + * @param {Object} dest The destination object. + * @param {Object} src The source object. + * @return {Object} The destination object (`dest`) + */ + function defaults(dest, src) { + for (var prop in src) { + if (src.hasOwnProperty(prop) && dest[prop] === undefined) { + dest[prop] = src[prop]; + } + } + return dest; + } + /** + * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the + * end of the string (by default, two periods: '..'). If the `str` length does not exceed + * `len`, the string will be returned unchanged. + * + * @param {String} str The string to truncate and add an ellipsis to. + * @param {Number} truncateLen The length to truncate the string at. + * @param {String} [ellipsisChars=...] The ellipsis character(s) to add to the end of `str` + * when truncated. Defaults to '...' + */ + function ellipsis(str, truncateLen, ellipsisChars) { + var ellipsisLength; + if (str.length > truncateLen) { + if (ellipsisChars == null) { + ellipsisChars = '…'; + ellipsisLength = 3; + } + else { + ellipsisLength = ellipsisChars.length; + } + str = str.substring(0, truncateLen - ellipsisLength) + ellipsisChars; + } + return str; + } + /** + * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below). + * + * @param {Array} arr The array to find an element of. + * @param {*} element The element to find in the array, and return the index of. + * @return {Number} The index of the `element`, or -1 if it was not found. + */ + function indexOf(arr, element) { + if (Array.prototype.indexOf) { + return arr.indexOf(element); + } + else { + for (var i = 0, len = arr.length; i < len; i++) { + if (arr[i] === element) + return i; + } + return -1; + } + } + /** + * Removes array elements based on a filtering function. Mutates the input + * array. + * + * Using this instead of the ES5 Array.prototype.filter() function, to allow + * Autolinker compatibility with IE8, and also to prevent creating many new + * arrays in memory for filtering. + * + * @param {Array} arr The array to remove elements from. This array is + * mutated. + * @param {Function} fn A function which should return `true` to + * remove an element. + * @return {Array} The mutated input `arr`. + */ + function remove(arr, fn) { + for (var i = arr.length - 1; i >= 0; i--) { + if (fn(arr[i]) === true) { + arr.splice(i, 1); + } + } + } + /** + * Performs the functionality of what modern browsers do when `String.prototype.split()` is called + * with a regular expression that contains capturing parenthesis. + * + * For example: + * + * // Modern browsers: + * "a,b,c".split( /(,)/ ); // --> [ 'a', ',', 'b', ',', 'c' ] + * + * // Old IE (including IE8): + * "a,b,c".split( /(,)/ ); // --> [ 'a', 'b', 'c' ] + * + * This method emulates the functionality of modern browsers for the old IE case. + * + * @param {String} str The string to split. + * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting + * character(s) will be spliced into the array, as in the "modern browsers" example in the + * description of this method. + * Note #1: the supplied regular expression **must** have the 'g' flag specified. + * Note #2: for simplicity's sake, the regular expression does not need + * to contain capturing parenthesis - it will be assumed that any match has them. + * @return {String[]} The split array of strings, with the splitting character(s) included. + */ + function splitAndCapture(str, splitRegex) { + if (!splitRegex.global) + throw new Error("`splitRegex` must have the 'g' flag set"); + var result = [], lastIdx = 0, match; + while (match = splitRegex.exec(str)) { + result.push(str.substring(lastIdx, match.index)); + result.push(match[0]); // push the splitting char(s) + lastIdx = match.index + match[0].length; + } + result.push(str.substring(lastIdx)); + return result; + } + /** + * Function that should never be called but is used to check that every + * enum value is handled using TypeScript's 'never' type. + */ + function throwUnhandledCaseError(theValue) { + throw new Error("Unhandled case for value: '" + theValue + "'"); + } + + /** + * @class Autolinker.HtmlTag + * @extends Object + * + * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically. + * + * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use + * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}. + * + * ## Examples + * + * Example instantiation: + * + * var tag = new Autolinker.HtmlTag( { + * tagName : 'a', + * attrs : { 'href': 'http://google.com', 'class': 'external-link' }, + * innerHtml : 'Google' + * } ); + * + * tag.toAnchorString(); // Google + * + * // Individual accessor methods + * tag.getTagName(); // 'a' + * tag.getAttr( 'href' ); // 'http://google.com' + * tag.hasClass( 'external-link' ); // true + * + * + * Using mutator methods (which may be used in combination with instantiation config properties): + * + * var tag = new Autolinker.HtmlTag(); + * tag.setTagName( 'a' ); + * tag.setAttr( 'href', 'http://google.com' ); + * tag.addClass( 'external-link' ); + * tag.setInnerHtml( 'Google' ); + * + * tag.getTagName(); // 'a' + * tag.getAttr( 'href' ); // 'http://google.com' + * tag.hasClass( 'external-link' ); // true + * + * tag.toAnchorString(); // Google + * + * + * ## Example use within a {@link Autolinker#replaceFn replaceFn} + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( match ) { + * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text + * tag.setAttr( 'rel', 'nofollow' ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test google.com + * + * + * ## Example use with a new tag for the replacement + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( match ) { + * var tag = new Autolinker.HtmlTag( { + * tagName : 'button', + * attrs : { 'title': 'Load URL: ' + match.getAnchorHref() }, + * innerHtml : 'Load URL: ' + match.getAnchorText() + * } ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test + */ + var HtmlTag = /** @class */ (function () { + /** + * @method constructor + * @param {Object} [cfg] The configuration properties for this class, in an Object (map) + */ + function HtmlTag(cfg) { + if (cfg === void 0) { cfg = {}; } + /** + * @cfg {String} tagName + * + * The tag name. Ex: 'a', 'button', etc. + * + * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString} + * is executed. + */ + this.tagName = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Object.} attrs + * + * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the + * values are the attribute values. + */ + this.attrs = {}; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {String} innerHTML + * + * The inner HTML for the tag. + */ + this.innerHTML = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @protected + * @property {RegExp} whitespaceRegex + * + * Regular expression used to match whitespace in a string of CSS classes. + */ + this.whitespaceRegex = /\s+/; // default value just to get the above doc comment in the ES5 output and documentation generator + this.tagName = cfg.tagName || ''; + this.attrs = cfg.attrs || {}; + this.innerHTML = cfg.innerHtml || cfg.innerHTML || ''; // accept either the camelCased form or the fully capitalized acronym as in the DOM + } + /** + * Sets the tag name that will be used to generate the tag with. + * + * @param {String} tagName + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.setTagName = function (tagName) { + this.tagName = tagName; + return this; + }; + /** + * Retrieves the tag name. + * + * @return {String} + */ + HtmlTag.prototype.getTagName = function () { + return this.tagName || ''; + }; + /** + * Sets an attribute on the HtmlTag. + * + * @param {String} attrName The attribute name to set. + * @param {String} attrValue The attribute value to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.setAttr = function (attrName, attrValue) { + var tagAttrs = this.getAttrs(); + tagAttrs[attrName] = attrValue; + return this; + }; + /** + * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`. + * + * @param {String} attrName The attribute name to retrieve. + * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag. + */ + HtmlTag.prototype.getAttr = function (attrName) { + return this.getAttrs()[attrName]; + }; + /** + * Sets one or more attributes on the HtmlTag. + * + * @param {Object.} attrs A key/value Object (map) of the attributes to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.setAttrs = function (attrs) { + Object.assign(this.getAttrs(), attrs); + return this; + }; + /** + * Retrieves the attributes Object (map) for the HtmlTag. + * + * @return {Object.} A key/value object of the attributes for the HtmlTag. + */ + HtmlTag.prototype.getAttrs = function () { + return this.attrs || (this.attrs = {}); + }; + /** + * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag. + * + * @param {String} cssClass One or more space-separated CSS classes to set (overwrite). + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.setClass = function (cssClass) { + return this.setAttr('class', cssClass); + }; + /** + * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes. + * + * @param {String} cssClass One or more space-separated CSS classes to add. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.addClass = function (cssClass) { + var classAttr = this.getClass(), whitespaceRegex = this.whitespaceRegex, classes = (!classAttr) ? [] : classAttr.split(whitespaceRegex), newClasses = cssClass.split(whitespaceRegex), newClass; + while (newClass = newClasses.shift()) { + if (indexOf(classes, newClass) === -1) { + classes.push(newClass); + } + } + this.getAttrs()['class'] = classes.join(" "); + return this; + }; + /** + * Convenience method to remove one or more CSS classes from the HtmlTag. + * + * @param {String} cssClass One or more space-separated CSS classes to remove. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.removeClass = function (cssClass) { + var classAttr = this.getClass(), whitespaceRegex = this.whitespaceRegex, classes = (!classAttr) ? [] : classAttr.split(whitespaceRegex), removeClasses = cssClass.split(whitespaceRegex), removeClass; + while (classes.length && (removeClass = removeClasses.shift())) { + var idx = indexOf(classes, removeClass); + if (idx !== -1) { + classes.splice(idx, 1); + } + } + this.getAttrs()['class'] = classes.join(" "); + return this; + }; + /** + * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when + * there are multiple. + * + * @return {String} + */ + HtmlTag.prototype.getClass = function () { + return this.getAttrs()['class'] || ""; + }; + /** + * Convenience method to check if the tag has a CSS class or not. + * + * @param {String} cssClass The CSS class to check for. + * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise. + */ + HtmlTag.prototype.hasClass = function (cssClass) { + return (' ' + this.getClass() + ' ').indexOf(' ' + cssClass + ' ') !== -1; + }; + /** + * Sets the inner HTML for the tag. + * + * @param {String} html The inner HTML to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.setInnerHTML = function (html) { + this.innerHTML = html; + return this; + }; + /** + * Backwards compatibility method name. + * + * @param {String} html The inner HTML to set. + * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. + */ + HtmlTag.prototype.setInnerHtml = function (html) { + return this.setInnerHTML(html); + }; + /** + * Retrieves the inner HTML for the tag. + * + * @return {String} + */ + HtmlTag.prototype.getInnerHTML = function () { + return this.innerHTML || ""; + }; + /** + * Backward compatibility method name. + * + * @return {String} + */ + HtmlTag.prototype.getInnerHtml = function () { + return this.getInnerHTML(); + }; + /** + * Override of superclass method used to generate the HTML string for the tag. + * + * @return {String} + */ + HtmlTag.prototype.toAnchorString = function () { + var tagName = this.getTagName(), attrsStr = this.buildAttrsStr(); + attrsStr = (attrsStr) ? ' ' + attrsStr : ''; // prepend a space if there are actually attributes + return ['<', tagName, attrsStr, '>', this.getInnerHtml(), ''].join(""); + }; + /** + * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate + * the stringified HtmlTag. + * + * @protected + * @return {String} Example return: `attr1="value1" attr2="value2"` + */ + HtmlTag.prototype.buildAttrsStr = function () { + if (!this.attrs) + return ""; // no `attrs` Object (map) has been set, return empty string + var attrs = this.getAttrs(), attrsArr = []; + for (var prop in attrs) { + if (attrs.hasOwnProperty(prop)) { + attrsArr.push(prop + '="' + attrs[prop] + '"'); + } + } + return attrsArr.join(" "); + }; + return HtmlTag; + }()); + + /** + * Date: 2015-10-05 + * Author: Kasper Søfren (https://github.com/kafoso) + * + * A truncation feature, where the ellipsis will be placed at a section within + * the URL making it still somewhat human readable. + * + * @param {String} url A URL. + * @param {Number} truncateLen The maximum length of the truncated output URL string. + * @param {String} ellipsisChars The characters to place within the url, e.g. "...". + * @return {String} The truncated URL. + */ + function truncateSmart(url, truncateLen, ellipsisChars) { + var ellipsisLengthBeforeParsing; + var ellipsisLength; + if (ellipsisChars == null) { + ellipsisChars = '…'; + ellipsisLength = 3; + ellipsisLengthBeforeParsing = 8; + } + else { + ellipsisLength = ellipsisChars.length; + ellipsisLengthBeforeParsing = ellipsisChars.length; + } + var parse_url = function (url) { + var urlObj = {}; + var urlSub = url; + var match = urlSub.match(/^([a-z]+):\/\//i); + if (match) { + urlObj.scheme = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^(.*?)(?=(\?|#|\/|$))/i); + if (match) { + urlObj.host = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^\/(.*?)(?=(\?|#|$))/i); + if (match) { + urlObj.path = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^\?(.*?)(?=(#|$))/i); + if (match) { + urlObj.query = match[1]; + urlSub = urlSub.substr(match[0].length); + } + match = urlSub.match(/^#(.*?)$/i); + if (match) { + urlObj.fragment = match[1]; + //urlSub = urlSub.substr(match[0].length); -- not used. Uncomment if adding another block. + } + return urlObj; + }; + var buildUrl = function (urlObj) { + var url = ""; + if (urlObj.scheme && urlObj.host) { + url += urlObj.scheme + "://"; + } + if (urlObj.host) { + url += urlObj.host; + } + if (urlObj.path) { + url += "/" + urlObj.path; + } + if (urlObj.query) { + url += "?" + urlObj.query; + } + if (urlObj.fragment) { + url += "#" + urlObj.fragment; + } + return url; + }; + var buildSegment = function (segment, remainingAvailableLength) { + var remainingAvailableLengthHalf = remainingAvailableLength / 2, startOffset = Math.ceil(remainingAvailableLengthHalf), endOffset = (-1) * Math.floor(remainingAvailableLengthHalf), end = ""; + if (endOffset < 0) { + end = segment.substr(endOffset); + } + return segment.substr(0, startOffset) + ellipsisChars + end; + }; + if (url.length <= truncateLen) { + return url; + } + var availableLength = truncateLen - ellipsisLength; + var urlObj = parse_url(url); + // Clean up the URL + if (urlObj.query) { + var matchQuery = urlObj.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i); + if (matchQuery) { + // Malformed URL; two or more "?". Removed any content behind the 2nd. + urlObj.query = urlObj.query.substr(0, matchQuery[1].length); + url = buildUrl(urlObj); + } + } + if (url.length <= truncateLen) { + return url; + } + if (urlObj.host) { + urlObj.host = urlObj.host.replace(/^www\./, ""); + url = buildUrl(urlObj); + } + if (url.length <= truncateLen) { + return url; + } + // Process and build the URL + var str = ""; + if (urlObj.host) { + str += urlObj.host; + } + if (str.length >= availableLength) { + if (urlObj.host.length == truncateLen) { + return (urlObj.host.substr(0, (truncateLen - ellipsisLength)) + ellipsisChars).substr(0, availableLength + ellipsisLengthBeforeParsing); + } + return buildSegment(str, availableLength).substr(0, availableLength + ellipsisLengthBeforeParsing); + } + var pathAndQuery = ""; + if (urlObj.path) { + pathAndQuery += "/" + urlObj.path; + } + if (urlObj.query) { + pathAndQuery += "?" + urlObj.query; + } + if (pathAndQuery) { + if ((str + pathAndQuery).length >= availableLength) { + if ((str + pathAndQuery).length == truncateLen) { + return (str + pathAndQuery).substr(0, truncateLen); + } + var remainingAvailableLength = availableLength - str.length; + return (str + buildSegment(pathAndQuery, remainingAvailableLength)).substr(0, availableLength + ellipsisLengthBeforeParsing); + } + else { + str += pathAndQuery; + } + } + if (urlObj.fragment) { + var fragment = "#" + urlObj.fragment; + if ((str + fragment).length >= availableLength) { + if ((str + fragment).length == truncateLen) { + return (str + fragment).substr(0, truncateLen); + } + var remainingAvailableLength2 = availableLength - str.length; + return (str + buildSegment(fragment, remainingAvailableLength2)).substr(0, availableLength + ellipsisLengthBeforeParsing); + } + else { + str += fragment; + } + } + if (urlObj.scheme && urlObj.host) { + var scheme = urlObj.scheme + "://"; + if ((str + scheme).length < availableLength) { + return (scheme + str).substr(0, truncateLen); + } + } + if (str.length <= truncateLen) { + return str; + } + var end = ""; + if (availableLength > 0) { + end = str.substr((-1) * Math.floor(availableLength / 2)); + } + return (str.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing); + } + + /** + * Date: 2015-10-05 + * Author: Kasper Søfren (https://github.com/kafoso) + * + * A truncation feature, where the ellipsis will be placed in the dead-center of the URL. + * + * @param {String} url A URL. + * @param {Number} truncateLen The maximum length of the truncated output URL string. + * @param {String} ellipsisChars The characters to place within the url, e.g. "..". + * @return {String} The truncated URL. + */ + function truncateMiddle(url, truncateLen, ellipsisChars) { + if (url.length <= truncateLen) { + return url; + } + var ellipsisLengthBeforeParsing; + var ellipsisLength; + if (ellipsisChars == null) { + ellipsisChars = '…'; + ellipsisLengthBeforeParsing = 8; + ellipsisLength = 3; + } + else { + ellipsisLengthBeforeParsing = ellipsisChars.length; + ellipsisLength = ellipsisChars.length; + } + var availableLength = truncateLen - ellipsisLength; + var end = ""; + if (availableLength > 0) { + end = url.substr((-1) * Math.floor(availableLength / 2)); + } + return (url.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing); + } + + /** + * A truncation feature where the ellipsis will be placed at the end of the URL. + * + * @param {String} anchorText + * @param {Number} truncateLen The maximum length of the truncated output URL string. + * @param {String} ellipsisChars The characters to place within the url, e.g. "..". + * @return {String} The truncated URL. + */ + function truncateEnd(anchorText, truncateLen, ellipsisChars) { + return ellipsis(anchorText, truncateLen, ellipsisChars); + } + + /** + * @protected + * @class Autolinker.AnchorTagBuilder + * @extends Object + * + * Builds anchor (<a>) tags for the Autolinker utility when a match is + * found. + * + * Normally this class is instantiated, configured, and used internally by an + * {@link Autolinker} instance, but may actually be used indirectly in a + * {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag} + * instances which may be modified before returning from the + * {@link Autolinker#replaceFn replaceFn}. For example: + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( match ) { + * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance + * tag.setAttr( 'rel', 'nofollow' ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test google.com + */ + var AnchorTagBuilder = /** @class */ (function () { + /** + * @method constructor + * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map). + */ + function AnchorTagBuilder(cfg) { + if (cfg === void 0) { cfg = {}; } + /** + * @cfg {Boolean} newWindow + * @inheritdoc Autolinker#newWindow + */ + this.newWindow = false; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Object} truncate + * @inheritdoc Autolinker#truncate + */ + this.truncate = {}; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {String} className + * @inheritdoc Autolinker#className + */ + this.className = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + this.newWindow = cfg.newWindow || false; + this.truncate = cfg.truncate || {}; + this.className = cfg.className || ''; + } + /** + * Generates the actual anchor (<a>) tag to use in place of the + * matched text, via its `match` object. + * + * @param {Autolinker.match.Match} match The Match instance to generate an + * anchor tag from. + * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag. + */ + AnchorTagBuilder.prototype.build = function (match) { + return new HtmlTag({ + tagName: 'a', + attrs: this.createAttrs(match), + innerHtml: this.processAnchorText(match.getAnchorText()) + }); + }; + /** + * Creates the Object (map) of the HTML attributes for the anchor (<a>) + * tag being generated. + * + * @protected + * @param {Autolinker.match.Match} match The Match instance to generate an + * anchor tag from. + * @return {Object} A key/value Object (map) of the anchor tag's attributes. + */ + AnchorTagBuilder.prototype.createAttrs = function (match) { + var attrs = { + 'href': match.getAnchorHref() // we'll always have the `href` attribute + }; + var cssClass = this.createCssClass(match); + if (cssClass) { + attrs['class'] = cssClass; + } + if (this.newWindow) { + attrs['target'] = "_blank"; + attrs['rel'] = "noopener noreferrer"; // Issue #149. See https://mathiasbynens.github.io/rel-noopener/ + } + if (this.truncate) { + if (this.truncate.length && this.truncate.length < match.getAnchorText().length) { + attrs['title'] = match.getAnchorHref(); + } + } + return attrs; + }; + /** + * Creates the CSS class that will be used for a given anchor tag, based on + * the `matchType` and the {@link #className} config. + * + * Example returns: + * + * - "" // no {@link #className} + * - "myLink myLink-url" // url match + * - "myLink myLink-email" // email match + * - "myLink myLink-phone" // phone match + * - "myLink myLink-hashtag" // hashtag match + * - "myLink myLink-mention myLink-twitter" // mention match with Twitter service + * + * @protected + * @param {Autolinker.match.Match} match The Match instance to generate an + * anchor tag from. + * @return {String} The CSS class string for the link. Example return: + * "myLink myLink-url". If no {@link #className} was configured, returns + * an empty string. + */ + AnchorTagBuilder.prototype.createCssClass = function (match) { + var className = this.className; + if (!className) { + return ""; + } + else { + var returnClasses = [className], cssClassSuffixes = match.getCssClassSuffixes(); + for (var i = 0, len = cssClassSuffixes.length; i < len; i++) { + returnClasses.push(className + '-' + cssClassSuffixes[i]); + } + return returnClasses.join(' '); + } + }; + /** + * Processes the `anchorText` by truncating the text according to the + * {@link #truncate} config. + * + * @private + * @param {String} anchorText The anchor tag's text (i.e. what will be + * displayed). + * @return {String} The processed `anchorText`. + */ + AnchorTagBuilder.prototype.processAnchorText = function (anchorText) { + anchorText = this.doTruncate(anchorText); + return anchorText; + }; + /** + * Performs the truncation of the `anchorText` based on the {@link #truncate} + * option. If the `anchorText` is longer than the length specified by the + * {@link #truncate} option, the truncation is performed based on the + * `location` property. See {@link #truncate} for details. + * + * @private + * @param {String} anchorText The anchor tag's text (i.e. what will be + * displayed). + * @return {String} The truncated anchor text. + */ + AnchorTagBuilder.prototype.doTruncate = function (anchorText) { + var truncate = this.truncate; + if (!truncate || !truncate.length) + return anchorText; + var truncateLength = truncate.length, truncateLocation = truncate.location; + if (truncateLocation === 'smart') { + return truncateSmart(anchorText, truncateLength); + } + else if (truncateLocation === 'middle') { + return truncateMiddle(anchorText, truncateLength); + } + else { + return truncateEnd(anchorText, truncateLength); + } + }; + return AnchorTagBuilder; + }()); + + /** + * @abstract + * @class Autolinker.match.Match + * + * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a + * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match. + * + * For example: + * + * var input = "..."; // string with URLs, Email Addresses, and Mentions (Twitter, Instagram, Soundcloud) + * + * var linkedText = Autolinker.link( input, { + * replaceFn : function( match ) { + * console.log( "href = ", match.getAnchorHref() ); + * console.log( "text = ", match.getAnchorText() ); + * + * switch( match.getType() ) { + * case 'url' : + * console.log( "url: ", match.getUrl() ); + * + * case 'email' : + * console.log( "email: ", match.getEmail() ); + * + * case 'mention' : + * console.log( "mention: ", match.getMention() ); + * } + * } + * } ); + * + * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}. + */ + var Match = /** @class */ (function () { + /** + * @member Autolinker.match.Match + * @method constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + function Match(cfg) { + /** + * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) + * + * Reference to the AnchorTagBuilder instance to use to generate an anchor + * tag for the Match. + */ + this.__jsduckDummyDocProp = null; // property used just to get the above doc comment into the ES5 output and documentation generator + /** + * @cfg {String} matchedText (required) + * + * The original text that was matched by the {@link Autolinker.matcher.Matcher}. + */ + this.matchedText = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Number} offset (required) + * + * The offset of where the match was made in the input string. + */ + this.offset = 0; // default value just to get the above doc comment in the ES5 output and documentation generator + this.tagBuilder = cfg.tagBuilder; + this.matchedText = cfg.matchedText; + this.offset = cfg.offset; + } + /** + * Returns the original text that was matched. + * + * @return {String} + */ + Match.prototype.getMatchedText = function () { + return this.matchedText; + }; + /** + * Sets the {@link #offset} of where the match was made in the input string. + * + * A {@link Autolinker.matcher.Matcher} will be fed only HTML text nodes, + * and will therefore set an original offset that is relative to the HTML + * text node itself. However, we want this offset to be relative to the full + * HTML input string, and thus if using {@link Autolinker#parse} (rather + * than calling a {@link Autolinker.matcher.Matcher} directly), then this + * offset is corrected after the Matcher itself has done its job. + * + * @param {Number} offset + */ + Match.prototype.setOffset = function (offset) { + this.offset = offset; + }; + /** + * Returns the offset of where the match was made in the input string. This + * is the 0-based index of the match. + * + * @return {Number} + */ + Match.prototype.getOffset = function () { + return this.offset; + }; + /** + * Returns the CSS class suffix(es) for this match. + * + * A CSS class suffix is appended to the {@link Autolinker#className} in + * the {@link Autolinker.AnchorTagBuilder} when a match is translated into + * an anchor tag. + * + * For example, if {@link Autolinker#className} was configured as 'myLink', + * and this method returns `[ 'url' ]`, the final class name of the element + * will become: 'myLink myLink-url'. + * + * The match may provide multiple CSS class suffixes to be appended to the + * {@link Autolinker#className} in order to facilitate better styling + * options for different match criteria. See {@link Autolinker.match.Mention} + * for an example. + * + * By default, this method returns a single array with the match's + * {@link #getType type} name, but may be overridden by subclasses. + * + * @return {String[]} + */ + Match.prototype.getCssClassSuffixes = function () { + return [this.getType()]; + }; + /** + * Builds and returns an {@link Autolinker.HtmlTag} instance based on the + * Match. + * + * This can be used to easily generate anchor tags from matches, and either + * return their HTML string, or modify them before doing so. + * + * Example Usage: + * + * var tag = match.buildTag(); + * tag.addClass( 'cordova-link' ); + * tag.setAttr( 'target', '_system' ); + * + * tag.toAnchorString(); // Google + * + * Example Usage in {@link Autolinker#replaceFn}: + * + * var html = Autolinker.link( "Test google.com", { + * replaceFn : function( match ) { + * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance + * tag.setAttr( 'rel', 'nofollow' ); + * + * return tag; + * } + * } ); + * + * // generated html: + * // Test google.com + */ + Match.prototype.buildTag = function () { + return this.tagBuilder.build(this); + }; + return Match; + }()); + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + /** + * @class Autolinker.match.Email + * @extends Autolinker.match.Match + * + * Represents a Email match found in an input string which should be Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more details. + */ + var EmailMatch = /** @class */ (function (_super) { + __extends(EmailMatch, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + function EmailMatch(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {String} email (required) + * + * The email address that was matched. + */ + _this.email = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + _this.email = cfg.email; + return _this; + } + /** + * Returns a string name for the type of match that this class represents. + * For the case of EmailMatch, returns 'email'. + * + * @return {String} + */ + EmailMatch.prototype.getType = function () { + return 'email'; + }; + /** + * Returns the email address that was matched. + * + * @return {String} + */ + EmailMatch.prototype.getEmail = function () { + return this.email; + }; + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + EmailMatch.prototype.getAnchorHref = function () { + return 'mailto:' + this.email; + }; + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + EmailMatch.prototype.getAnchorText = function () { + return this.email; + }; + return EmailMatch; + }(Match)); + + /** + * @class Autolinker.match.Hashtag + * @extends Autolinker.match.Match + * + * Represents a Hashtag match found in an input string which should be + * Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more + * details. + */ + var HashtagMatch = /** @class */ (function (_super) { + __extends(HashtagMatch, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + function HashtagMatch(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {String} serviceName + * + * The service to point hashtag matches to. See {@link Autolinker#hashtag} + * for available values. + */ + _this.serviceName = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {String} hashtag (required) + * + * The HashtagMatch that was matched, without the '#'. + */ + _this.hashtag = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + _this.serviceName = cfg.serviceName; + _this.hashtag = cfg.hashtag; + return _this; + } + /** + * Returns a string name for the type of match that this class represents. + * For the case of HashtagMatch, returns 'hashtag'. + * + * @return {String} + */ + HashtagMatch.prototype.getType = function () { + return 'hashtag'; + }; + /** + * Returns the configured {@link #serviceName} to point the HashtagMatch to. + * Ex: 'facebook', 'twitter'. + * + * @return {String} + */ + HashtagMatch.prototype.getServiceName = function () { + return this.serviceName; + }; + /** + * Returns the matched hashtag, without the '#' character. + * + * @return {String} + */ + HashtagMatch.prototype.getHashtag = function () { + return this.hashtag; + }; + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + HashtagMatch.prototype.getAnchorHref = function () { + var serviceName = this.serviceName, hashtag = this.hashtag; + switch (serviceName) { + case 'twitter': + return 'https://twitter.com/hashtag/' + hashtag; + case 'facebook': + return 'https://www.facebook.com/hashtag/' + hashtag; + case 'instagram': + return 'https://instagram.com/explore/tags/' + hashtag; + default: // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case. + throw new Error('Unknown service name to point hashtag to: ' + serviceName); + } + }; + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + HashtagMatch.prototype.getAnchorText = function () { + return '#' + this.hashtag; + }; + return HashtagMatch; + }(Match)); + + /** + * @class Autolinker.match.Mention + * @extends Autolinker.match.Match + * + * Represents a Mention match found in an input string which should be Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more details. + */ + var MentionMatch = /** @class */ (function (_super) { + __extends(MentionMatch, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + function MentionMatch(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {String} serviceName + * + * The service to point mention matches to. See {@link Autolinker#mention} + * for available values. + */ + _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {String} mention (required) + * + * The Mention that was matched, without the '@' character. + */ + _this.mention = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + _this.mention = cfg.mention; + _this.serviceName = cfg.serviceName; + return _this; + } + /** + * Returns a string name for the type of match that this class represents. + * For the case of MentionMatch, returns 'mention'. + * + * @return {String} + */ + MentionMatch.prototype.getType = function () { + return 'mention'; + }; + /** + * Returns the mention, without the '@' character. + * + * @return {String} + */ + MentionMatch.prototype.getMention = function () { + return this.mention; + }; + /** + * Returns the configured {@link #serviceName} to point the mention to. + * Ex: 'instagram', 'twitter', 'soundcloud'. + * + * @return {String} + */ + MentionMatch.prototype.getServiceName = function () { + return this.serviceName; + }; + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + MentionMatch.prototype.getAnchorHref = function () { + switch (this.serviceName) { + case 'twitter': + return 'https://twitter.com/' + this.mention; + case 'instagram': + return 'https://instagram.com/' + this.mention; + case 'soundcloud': + return 'https://soundcloud.com/' + this.mention; + default: // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case. + throw new Error('Unknown service name to point mention to: ' + this.serviceName); + } + }; + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + MentionMatch.prototype.getAnchorText = function () { + return '@' + this.mention; + }; + /** + * Returns the CSS class suffixes that should be used on a tag built with + * the match. See {@link Autolinker.match.Match#getCssClassSuffixes} for + * details. + * + * @return {String[]} + */ + MentionMatch.prototype.getCssClassSuffixes = function () { + var cssClassSuffixes = _super.prototype.getCssClassSuffixes.call(this), serviceName = this.getServiceName(); + if (serviceName) { + cssClassSuffixes.push(serviceName); + } + return cssClassSuffixes; + }; + return MentionMatch; + }(Match)); + + /** + * @class Autolinker.match.Phone + * @extends Autolinker.match.Match + * + * Represents a Phone number match found in an input string which should be + * Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more + * details. + */ + var PhoneMatch = /** @class */ (function (_super) { + __extends(PhoneMatch, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + function PhoneMatch(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @protected + * @property {String} number (required) + * + * The phone number that was matched, without any delimiter characters. + * + * Note: This is a string to allow for prefixed 0's. + */ + _this.number = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @protected + * @property {Boolean} plusSign (required) + * + * `true` if the matched phone number started with a '+' sign. We'll include + * it in the `tel:` URL if so, as this is needed for international numbers. + * + * Ex: '+1 (123) 456 7879' + */ + _this.plusSign = false; // default value just to get the above doc comment in the ES5 output and documentation generator + _this.number = cfg.number; + _this.plusSign = cfg.plusSign; + return _this; + } + /** + * Returns a string name for the type of match that this class represents. + * For the case of PhoneMatch, returns 'phone'. + * + * @return {String} + */ + PhoneMatch.prototype.getType = function () { + return 'phone'; + }; + /** + * Returns the phone number that was matched as a string, without any + * delimiter characters. + * + * Note: This is a string to allow for prefixed 0's. + * + * @return {String} + */ + PhoneMatch.prototype.getPhoneNumber = function () { + return this.number; + }; + /** + * Alias of {@link #getPhoneNumber}, returns the phone number that was + * matched as a string, without any delimiter characters. + * + * Note: This is a string to allow for prefixed 0's. + * + * @return {String} + */ + PhoneMatch.prototype.getNumber = function () { + return this.getPhoneNumber(); + }; + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + PhoneMatch.prototype.getAnchorHref = function () { + return 'tel:' + (this.plusSign ? '+' : '') + this.number; + }; + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + PhoneMatch.prototype.getAnchorText = function () { + return this.matchedText; + }; + return PhoneMatch; + }(Match)); + + /** + * @class Autolinker.match.Url + * @extends Autolinker.match.Match + * + * Represents a Url match found in an input string which should be Autolinked. + * + * See this class's superclass ({@link Autolinker.match.Match}) for more details. + */ + var UrlMatch = /** @class */ (function (_super) { + __extends(UrlMatch, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match + * instance, specified in an Object (map). + */ + function UrlMatch(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {String} url (required) + * + * The url that was matched. + */ + _this.url = ''; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {"scheme"/"www"/"tld"} urlMatchType (required) + * + * The type of URL match that this class represents. This helps to determine + * if the match was made in the original text with a prefixed scheme (ex: + * 'http://www.google.com'), a prefixed 'www' (ex: 'www.google.com'), or + * was matched by a known top-level domain (ex: 'google.com'). + */ + _this.urlMatchType = 'scheme'; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Boolean} protocolUrlMatch (required) + * + * `true` if the URL is a match which already has a protocol (i.e. + * 'http://'), `false` if the match was from a 'www' or known TLD match. + */ + _this.protocolUrlMatch = false; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Boolean} protocolRelativeMatch (required) + * + * `true` if the URL is a protocol-relative match. A protocol-relative match + * is a URL that starts with '//', and will be either http:// or https:// + * based on the protocol that the site is loaded under. + */ + _this.protocolRelativeMatch = false; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Object} stripPrefix (required) + * + * The Object form of {@link Autolinker#cfg-stripPrefix}. + */ + _this.stripPrefix = { scheme: true, www: true }; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Boolean} stripTrailingSlash (required) + * @inheritdoc Autolinker#cfg-stripTrailingSlash + */ + _this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Boolean} decodePercentEncoding (required) + * @inheritdoc Autolinker#cfg-decodePercentEncoding + */ + _this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @private + * @property {RegExp} schemePrefixRegex + * + * A regular expression used to remove the 'http://' or 'https://' from + * URLs. + */ + _this.schemePrefixRegex = /^(https?:\/\/)?/i; + /** + * @private + * @property {RegExp} wwwPrefixRegex + * + * A regular expression used to remove the 'www.' from URLs. + */ + _this.wwwPrefixRegex = /^(https?:\/\/)?(www\.)?/i; + /** + * @private + * @property {RegExp} protocolRelativeRegex + * + * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes + * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com" + */ + _this.protocolRelativeRegex = /^\/\//; + /** + * @private + * @property {Boolean} protocolPrepended + * + * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the + * {@link #url} did not have a protocol) + */ + _this.protocolPrepended = false; + _this.urlMatchType = cfg.urlMatchType; + _this.url = cfg.url; + _this.protocolUrlMatch = cfg.protocolUrlMatch; + _this.protocolRelativeMatch = cfg.protocolRelativeMatch; + _this.stripPrefix = cfg.stripPrefix; + _this.stripTrailingSlash = cfg.stripTrailingSlash; + _this.decodePercentEncoding = cfg.decodePercentEncoding; + return _this; + } + /** + * Returns a string name for the type of match that this class represents. + * For the case of UrlMatch, returns 'url'. + * + * @return {String} + */ + UrlMatch.prototype.getType = function () { + return 'url'; + }; + /** + * Returns a string name for the type of URL match that this class + * represents. + * + * This helps to determine if the match was made in the original text with a + * prefixed scheme (ex: 'http://www.google.com'), a prefixed 'www' (ex: + * 'www.google.com'), or was matched by a known top-level domain (ex: + * 'google.com'). + * + * @return {"scheme"/"www"/"tld"} + */ + UrlMatch.prototype.getUrlMatchType = function () { + return this.urlMatchType; + }; + /** + * Returns the url that was matched, assuming the protocol to be 'http://' if the original + * match was missing a protocol. + * + * @return {String} + */ + UrlMatch.prototype.getUrl = function () { + var url = this.url; + // if the url string doesn't begin with a protocol, assume 'http://' + if (!this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended) { + url = this.url = 'http://' + url; + this.protocolPrepended = true; + } + return url; + }; + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + UrlMatch.prototype.getAnchorHref = function () { + var url = this.getUrl(); + return url.replace(/&/g, '&'); // any &'s in the URL should be converted back to '&' if they were displayed as & in the source html + }; + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + UrlMatch.prototype.getAnchorText = function () { + var anchorText = this.getMatchedText(); + if (this.protocolRelativeMatch) { + // Strip off any protocol-relative '//' from the anchor text + anchorText = this.stripProtocolRelativePrefix(anchorText); + } + if (this.stripPrefix.scheme) { + anchorText = this.stripSchemePrefix(anchorText); + } + if (this.stripPrefix.www) { + anchorText = this.stripWwwPrefix(anchorText); + } + if (this.stripTrailingSlash) { + anchorText = this.removeTrailingSlash(anchorText); // remove trailing slash, if there is one + } + if (this.decodePercentEncoding) { + anchorText = this.removePercentEncoding(anchorText); + } + return anchorText; + }; + // --------------------------------------- + // Utility Functionality + /** + * Strips the scheme prefix (such as "http://" or "https://") from the given + * `url`. + * + * @private + * @param {String} url The text of the anchor that is being generated, for + * which to strip off the url scheme. + * @return {String} The `url`, with the scheme stripped. + */ + UrlMatch.prototype.stripSchemePrefix = function (url) { + return url.replace(this.schemePrefixRegex, ''); + }; + /** + * Strips the 'www' prefix from the given `url`. + * + * @private + * @param {String} url The text of the anchor that is being generated, for + * which to strip off the 'www' if it exists. + * @return {String} The `url`, with the 'www' stripped. + */ + UrlMatch.prototype.stripWwwPrefix = function (url) { + return url.replace(this.wwwPrefixRegex, '$1'); // leave any scheme ($1), it one exists + }; + /** + * Strips any protocol-relative '//' from the anchor text. + * + * @private + * @param {String} text The text of the anchor that is being generated, for which to strip off the + * protocol-relative prefix (such as stripping off "//") + * @return {String} The `anchorText`, with the protocol-relative prefix stripped. + */ + UrlMatch.prototype.stripProtocolRelativePrefix = function (text) { + return text.replace(this.protocolRelativeRegex, ''); + }; + /** + * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed. + * + * @private + * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing + * slash ('/') that may exist. + * @return {String} The `anchorText`, with the trailing slash removed. + */ + UrlMatch.prototype.removeTrailingSlash = function (anchorText) { + if (anchorText.charAt(anchorText.length - 1) === '/') { + anchorText = anchorText.slice(0, -1); + } + return anchorText; + }; + /** + * Decodes percent-encoded characters from the given `anchorText`, in + * preparation for the text to be displayed. + * + * @private + * @param {String} anchorText The text of the anchor that is being + * generated, for which to decode any percent-encoded characters. + * @return {String} The `anchorText`, with the percent-encoded characters + * decoded. + */ + UrlMatch.prototype.removePercentEncoding = function (anchorText) { + // First, convert a few of the known % encodings to the corresponding + // HTML entities that could accidentally be interpretted as special + // HTML characters + var preProcessedEntityAnchorText = anchorText + .replace(/%22/gi, '"') // " char + .replace(/%26/gi, '&') // & char + .replace(/%27/gi, ''') // ' char + .replace(/%3C/gi, '<') // < char + .replace(/%3E/gi, '>'); // > char + try { + // Now attempt to decode the rest of the anchor text + return decodeURIComponent(preProcessedEntityAnchorText); + } + catch (e) { // Invalid % escape sequence in the anchor text + return preProcessedEntityAnchorText; + } + }; + return UrlMatch; + }(Match)); + + /** + * @abstract + * @class Autolinker.matcher.Matcher + * + * An abstract class and interface for individual matchers to find matches in + * an input string with linkified versions of them. + * + * Note that Matchers do not take HTML into account - they must be fed the text + * nodes of any HTML string, which is handled by {@link Autolinker#parse}. + */ + var Matcher = /** @class */ (function () { + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Matcher + * instance, specified in an Object (map). + */ + function Matcher(cfg) { + /** + * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) + * + * Reference to the AnchorTagBuilder instance to use to generate HTML tags + * for {@link Autolinker.match.Match Matches}. + */ + this.__jsduckDummyDocProp = null; // property used just to get the above doc comment into the ES5 output and documentation generator + this.tagBuilder = cfg.tagBuilder; + } + return Matcher; + }()); + + /* + * This file builds and stores a library of the common regular expressions used + * by the Autolinker utility. + * + * Other regular expressions may exist ad-hoc, but these are generally the + * regular expressions that are shared between source files. + */ + /** + * Regular expression to match upper and lowercase ASCII letters + */ + var letterRe = /[A-Za-z]/; + /** + * Regular expression to match ASCII digits + */ + var digitRe = /[0-9]/; + /** + * Regular expression to match whitespace + */ + var whitespaceRe = /\s/; + /** + * Regular expression to match quote characters + */ + var quoteRe = /['"]/; + /** + * Regular expression to match the range of ASCII control characters (0-31), and + * the backspace char (127) + */ + var controlCharsRe = /[\x00-\x1F\x7F]/; + /** + * The string form of a regular expression that would match all of the + * alphabetic ("letter") chars in the unicode character set when placed in a + * RegExp character class (`[]`). This includes all international alphabetic + * characters. + * + * These would be the characters matched by unicode regex engines `\p{L}` + * escape ("all letters"). + * + * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) + * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Letter' + * regex's bmp + * + * VERY IMPORTANT: This set of characters is defined inside of a Regular + * Expression literal rather than a string literal to prevent UglifyJS from + * compressing the unicode escape sequences into their actual unicode + * characters. If Uglify compresses these into the unicode characters + * themselves, this results in the error "Range out of order in character + * class" when these characters are used inside of a Regular Expression + * character class (`[]`). See usages of this const. Alternatively, we can set + * the UglifyJS option `ascii_only` to true for the build, but that doesn't + * help others who are pulling in Autolinker into their own build and running + * UglifyJS themselves. + */ + var alphaCharsStr = /A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC/ + .source; // see note in above variable description + /** + * The string form of a regular expression that would match all emoji characters + * Source: https://www.regextester.com/106421 + */ + var emojiStr = /\u00a9\u00ae\u2000-\u3300\ud83c\ud000-\udfff\ud83d\ud000-\udfff\ud83e\ud000-\udfff/ + .source; + /** + * The string form of a regular expression that would match all of the + * combining mark characters in the unicode character set when placed in a + * RegExp character class (`[]`). + * + * These would be the characters matched by unicode regex engines `\p{M}` + * escape ("all marks"). + * + * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) + * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Mark' + * regex's bmp + * + * VERY IMPORTANT: This set of characters is defined inside of a Regular + * Expression literal rather than a string literal to prevent UglifyJS from + * compressing the unicode escape sequences into their actual unicode + * characters. If Uglify compresses these into the unicode characters + * themselves, this results in the error "Range out of order in character + * class" when these characters are used inside of a Regular Expression + * character class (`[]`). See usages of this const. Alternatively, we can set + * the UglifyJS option `ascii_only` to true for the build, but that doesn't + * help others who are pulling in Autolinker into their own build and running + * UglifyJS themselves. + */ + var marksStr = /\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F/ + .source; // see note in above variable description + /** + * The string form of a regular expression that would match all of the + * alphabetic ("letter") chars, emoji, and combining marks in the unicode character set + * when placed in a RegExp character class (`[]`). This includes all + * international alphabetic characters. + * + * These would be the characters matched by unicode regex engines `\p{L}\p{M}` + * escapes and emoji characters. + */ + var alphaCharsAndMarksStr = alphaCharsStr + emojiStr + marksStr; + /** + * The string form of a regular expression that would match all of the + * decimal number chars in the unicode character set when placed in a RegExp + * character class (`[]`). + * + * These would be the characters matched by unicode regex engines `\p{Nd}` + * escape ("all decimal numbers") + * + * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) + * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Decimal_Number' + * regex's bmp + * + * VERY IMPORTANT: This set of characters is defined inside of a Regular + * Expression literal rather than a string literal to prevent UglifyJS from + * compressing the unicode escape sequences into their actual unicode + * characters. If Uglify compresses these into the unicode characters + * themselves, this results in the error "Range out of order in character + * class" when these characters are used inside of a Regular Expression + * character class (`[]`). See usages of this const. Alternatively, we can set + * the UglifyJS option `ascii_only` to true for the build, but that doesn't + * help others who are pulling in Autolinker into their own build and running + * UglifyJS themselves. + */ + var decimalNumbersStr = /0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19/ + .source; // see note in above variable description + /** + * The string form of a regular expression that would match all of the + * letters and decimal number chars in the unicode character set when placed in + * a RegExp character class (`[]`). + * + * These would be the characters matched by unicode regex engines + * `[\p{L}\p{Nd}]` escape ("all letters and decimal numbers") + */ + var alphaNumericCharsStr = alphaCharsAndMarksStr + decimalNumbersStr; + /** + * The string form of a regular expression that would match all of the + * letters, combining marks, and decimal number chars in the unicode character + * set when placed in a RegExp character class (`[]`). + * + * These would be the characters matched by unicode regex engines + * `[\p{L}\p{M}\p{Nd}]` escape ("all letters, combining marks, and decimal + * numbers") + */ + var alphaNumericAndMarksCharsStr = alphaCharsAndMarksStr + decimalNumbersStr; + // Simplified IP regular expression + var ipStr = '(?:[' + decimalNumbersStr + ']{1,3}\\.){3}[' + decimalNumbersStr + ']{1,3}'; + // Protected domain label which do not allow "-" character on the beginning and the end of a single label + var domainLabelStr = '[' + alphaNumericAndMarksCharsStr + '](?:[' + alphaNumericAndMarksCharsStr + '\\-]{0,61}[' + alphaNumericAndMarksCharsStr + '])?'; + var getDomainLabelStr = function (group) { + return '(?=(' + domainLabelStr + '))\\' + group; + }; + /** + * A function to match domain names of a URL or email address. + * Ex: 'google', 'yahoo', 'some-other-company', etc. + */ + var getDomainNameStr = function (group) { + return '(?:' + getDomainLabelStr(group) + '(?:\\.' + getDomainLabelStr(group + 1) + '){0,126}|' + ipStr + ')'; + }; + /** + * A regular expression that is simply the character class of the characters + * that may be used in a domain name, minus the '-' or '.' + */ + var domainNameCharRegex = new RegExp("[" + alphaNumericAndMarksCharsStr + "]"); + + // NOTE: THIS IS A GENERATED FILE + // To update with the latest TLD list, run `npm run update-tld-regex` or `yarn update-tld-regex` (depending on which you have installed) + var tldRegex = /(?:xn--vermgensberatung-pwb|xn--vermgensberater-ctb|xn--clchc0ea0b2g2a9gcd|xn--w4r85el8fhu5dnra|northwesternmutual|travelersinsurance|vermögensberatung|xn--3oq18vl8pn36a|xn--5su34j936bgsg|xn--bck1b9a5dre4c|xn--mgbai9azgqp6j|xn--mgberp4a5d4ar|xn--xkc2dl3a5ee0h|vermögensberater|xn--fzys8d69uvgm|xn--mgba7c0bbn0a|xn--xkc2al3hye2a|americanexpress|kerryproperties|sandvikcoromant|xn--i1b6b1a6a2e|xn--kcrx77d1x4a|xn--lgbbat1ad8j|xn--mgba3a4f16a|xn--mgbaakc7dvf|xn--mgbc0a9azcg|xn--nqv7fs00ema|afamilycompany|americanfamily|bananarepublic|cancerresearch|cookingchannel|kerrylogistics|weatherchannel|xn--54b7fta0cc|xn--6qq986b3xl|xn--80aqecdr1a|xn--b4w605ferd|xn--fiq228c5hs|xn--h2breg3eve|xn--jlq61u9w7b|xn--mgba3a3ejt|xn--mgbaam7a8h|xn--mgbayh7gpa|xn--mgbb9fbpob|xn--mgbbh1a71e|xn--mgbca7dzdo|xn--mgbi4ecexp|xn--mgbx4cd0ab|xn--rvc1e0am3e|international|lifeinsurance|spreadbetting|travelchannel|wolterskluwer|xn--eckvdtc9d|xn--fpcrj9c3d|xn--fzc2c9e2c|xn--h2brj9c8c|xn--tiq49xqyj|xn--yfro4i67o|xn--ygbi2ammx|construction|lplfinancial|scholarships|versicherung|xn--3e0b707e|xn--45br5cyl|xn--80adxhks|xn--80asehdb|xn--8y0a063a|xn--gckr3f0f|xn--mgb9awbf|xn--mgbab2bd|xn--mgbgu82a|xn--mgbpl2fh|xn--mgbt3dhd|xn--mk1bu44c|xn--ngbc5azd|xn--ngbe9e0a|xn--ogbpf8fl|xn--qcka1pmc|accountants|barclaycard|blackfriday|blockbuster|bridgestone|calvinklein|contractors|creditunion|engineering|enterprises|foodnetwork|investments|kerryhotels|lamborghini|motorcycles|olayangroup|photography|playstation|productions|progressive|redumbrella|rightathome|williamhill|xn--11b4c3d|xn--1ck2e1b|xn--1qqw23a|xn--2scrj9c|xn--3bst00m|xn--3ds443g|xn--3hcrj9c|xn--42c2d9a|xn--45brj9c|xn--55qw42g|xn--6frz82g|xn--80ao21a|xn--9krt00a|xn--cck2b3b|xn--czr694b|xn--d1acj3b|xn--efvy88h|xn--estv75g|xn--fct429k|xn--fjq720a|xn--flw351e|xn--g2xx48c|xn--gecrj9c|xn--gk3at1e|xn--h2brj9c|xn--hxt814e|xn--imr513n|xn--j6w193g|xn--jvr189m|xn--kprw13d|xn--kpry57d|xn--kpu716f|xn--mgbbh1a|xn--mgbtx2b|xn--mix891f|xn--nyqy26a|xn--otu796d|xn--pbt977c|xn--pgbs0dh|xn--q9jyb4c|xn--rhqv96g|xn--rovu88b|xn--s9brj9c|xn--ses554g|xn--t60b56a|xn--vuq861b|xn--w4rs40l|xn--xhq521b|xn--zfr164b|சிங்கப்பூர்|accountant|apartments|associates|basketball|bnpparibas|boehringer|capitalone|consulting|creditcard|cuisinella|eurovision|extraspace|foundation|healthcare|immobilien|industries|management|mitsubishi|nationwide|newholland|nextdirect|onyourside|properties|protection|prudential|realestate|republican|restaurant|schaeffler|swiftcover|tatamotors|technology|telefonica|university|vistaprint|vlaanderen|volkswagen|xn--30rr7y|xn--3pxu8k|xn--45q11c|xn--4gbrim|xn--55qx5d|xn--5tzm5g|xn--80aswg|xn--90a3ac|xn--9dbq2a|xn--9et52u|xn--c2br7g|xn--cg4bki|xn--czrs0t|xn--czru2d|xn--fiq64b|xn--fiqs8s|xn--fiqz9s|xn--io0a7i|xn--kput3i|xn--mxtq1m|xn--o3cw4h|xn--pssy2u|xn--unup4y|xn--wgbh1c|xn--wgbl6a|xn--y9a3aq|accenture|alfaromeo|allfinanz|amsterdam|analytics|aquarelle|barcelona|bloomberg|christmas|community|directory|education|equipment|fairwinds|financial|firestone|fresenius|frontdoor|fujixerox|furniture|goldpoint|hisamitsu|homedepot|homegoods|homesense|honeywell|institute|insurance|kuokgroup|ladbrokes|lancaster|landrover|lifestyle|marketing|marshalls|melbourne|microsoft|panasonic|passagens|pramerica|richardli|scjohnson|shangrila|solutions|statebank|statefarm|stockholm|travelers|vacations|xn--90ais|xn--c1avg|xn--d1alf|xn--e1a4c|xn--fhbei|xn--j1aef|xn--j1amh|xn--l1acc|xn--ngbrx|xn--nqv7f|xn--p1acf|xn--tckwe|xn--vhquv|yodobashi|abudhabi|airforce|allstate|attorney|barclays|barefoot|bargains|baseball|boutique|bradesco|broadway|brussels|budapest|builders|business|capetown|catering|catholic|chrysler|cipriani|cityeats|cleaning|clinique|clothing|commbank|computer|delivery|deloitte|democrat|diamonds|discount|discover|download|engineer|ericsson|esurance|etisalat|everbank|exchange|feedback|fidelity|firmdale|football|frontier|goodyear|grainger|graphics|guardian|hdfcbank|helsinki|holdings|hospital|infiniti|ipiranga|istanbul|jpmorgan|lighting|lundbeck|marriott|maserati|mckinsey|memorial|merckmsd|mortgage|movistar|observer|partners|pharmacy|pictures|plumbing|property|redstone|reliance|saarland|samsclub|security|services|shopping|showtime|softbank|software|stcgroup|supplies|symantec|training|uconnect|vanguard|ventures|verisign|woodside|xn--90ae|xn--node|xn--p1ai|xn--qxam|yokohama|السعودية|abogado|academy|agakhan|alibaba|android|athleta|auction|audible|auspost|avianca|banamex|bauhaus|bentley|bestbuy|booking|brother|bugatti|capital|caravan|careers|cartier|channel|charity|chintai|citadel|clubmed|college|cologne|comcast|company|compare|contact|cooking|corsica|country|coupons|courses|cricket|cruises|dentist|digital|domains|exposed|express|farmers|fashion|ferrari|ferrero|finance|fishing|fitness|flights|florist|flowers|forsale|frogans|fujitsu|gallery|genting|godaddy|grocery|guitars|hamburg|hangout|hitachi|holiday|hosting|hoteles|hotmail|hyundai|iselect|ismaili|jewelry|juniper|kitchen|komatsu|lacaixa|lancome|lanxess|lasalle|latrobe|leclerc|liaison|limited|lincoln|markets|metlife|monster|netbank|netflix|network|neustar|okinawa|oldnavy|organic|origins|philips|pioneer|politie|realtor|recipes|rentals|reviews|rexroth|samsung|sandvik|schmidt|schwarz|science|shiksha|shriram|singles|staples|starhub|storage|support|surgery|systems|temasek|theater|theatre|tickets|tiffany|toshiba|trading|walmart|wanggou|watches|weather|website|wedding|whoswho|windows|winners|xfinity|yamaxun|youtube|zuerich|католик|اتصالات|الجزائر|العليان|پاکستان|كاثوليك|موبايلي|இந்தியா|abarth|abbott|abbvie|active|africa|agency|airbus|airtel|alipay|alsace|alstom|anquan|aramco|author|bayern|beauty|berlin|bharti|blanco|bostik|boston|broker|camera|career|caseih|casino|center|chanel|chrome|church|circle|claims|clinic|coffee|comsec|condos|coupon|credit|cruise|dating|datsun|dealer|degree|dental|design|direct|doctor|dunlop|dupont|durban|emerck|energy|estate|events|expert|family|flickr|futbol|gallup|garden|george|giving|global|google|gratis|health|hermes|hiphop|hockey|hotels|hughes|imamat|insure|intuit|jaguar|joburg|juegos|kaufen|kinder|kindle|kosher|lancia|latino|lawyer|lefrak|living|locker|london|luxury|madrid|maison|makeup|market|mattel|mobile|mobily|monash|mormon|moscow|museum|mutual|nagoya|natura|nissan|nissay|norton|nowruz|office|olayan|online|oracle|orange|otsuka|pfizer|photos|physio|piaget|pictet|quebec|racing|realty|reisen|repair|report|review|rocher|rogers|ryukyu|safety|sakura|sanofi|school|schule|search|secure|select|shouji|soccer|social|stream|studio|supply|suzuki|swatch|sydney|taipei|taobao|target|tattoo|tennis|tienda|tjmaxx|tkmaxx|toyota|travel|unicom|viajes|viking|villas|virgin|vision|voting|voyage|vuelos|walter|warman|webcam|xihuan|yachts|yandex|zappos|москва|онлайн|ابوظبي|ارامكو|الاردن|المغرب|امارات|فلسطين|مليسيا|भारतम्|இலங்கை|ファッション|actor|adult|aetna|amfam|amica|apple|archi|audio|autos|azure|baidu|beats|bible|bingo|black|boats|bosch|build|canon|cards|chase|cheap|cisco|citic|click|cloud|coach|codes|crown|cymru|dabur|dance|deals|delta|dodge|drive|dubai|earth|edeka|email|epost|epson|faith|fedex|final|forex|forum|gallo|games|gifts|gives|glade|glass|globo|gmail|green|gripe|group|gucci|guide|homes|honda|horse|house|hyatt|ikano|intel|irish|iveco|jetzt|koeln|kyoto|lamer|lease|legal|lexus|lilly|linde|lipsy|lixil|loans|locus|lotte|lotto|lupin|macys|mango|media|miami|money|mopar|movie|nadex|nexus|nikon|ninja|nokia|nowtv|omega|osaka|paris|parts|party|phone|photo|pizza|place|poker|praxi|press|prime|promo|quest|radio|rehab|reise|ricoh|rocks|rodeo|rugby|salon|sener|seven|sharp|shell|shoes|skype|sling|smart|smile|solar|space|sport|stada|store|study|style|sucks|swiss|tatar|tires|tirol|tmall|today|tokyo|tools|toray|total|tours|trade|trust|tunes|tushu|ubank|vegas|video|vodka|volvo|wales|watch|weber|weibo|works|world|xerox|yahoo|zippo|ایران|بازار|بھارت|سودان|سورية|همراه|भारोत|संगठन|বাংলা|భారత్|ഭാരതം|嘉里大酒店|aarp|able|adac|aero|aigo|akdn|ally|amex|arab|army|arpa|arte|asda|asia|audi|auto|baby|band|bank|bbva|beer|best|bike|bing|blog|blue|bofa|bond|book|buzz|cafe|call|camp|care|cars|casa|case|cash|cbre|cern|chat|citi|city|club|cool|coop|cyou|data|date|dclk|deal|dell|desi|diet|dish|docs|doha|duck|duns|dvag|erni|fage|fail|fans|farm|fast|fiat|fido|film|fire|fish|flir|food|ford|free|fund|game|gbiz|gent|ggee|gift|gmbh|gold|golf|goog|guge|guru|hair|haus|hdfc|help|here|hgtv|host|hsbc|icbc|ieee|imdb|immo|info|itau|java|jeep|jobs|jprs|kddi|kiwi|kpmg|kred|land|lego|lgbt|lidl|life|like|limo|link|live|loan|loft|love|ltda|luxe|maif|meet|meme|menu|mini|mint|mobi|moda|moto|name|navy|news|next|nico|nike|ollo|open|page|pars|pccw|pics|ping|pink|play|plus|pohl|porn|post|prod|prof|qpon|raid|read|reit|rent|rest|rich|rmit|room|rsvp|ruhr|safe|sale|sarl|save|saxo|scor|scot|seat|seek|sexy|shaw|shia|shop|show|silk|sina|site|skin|sncf|sohu|song|sony|spot|star|surf|talk|taxi|team|tech|teva|tiaa|tips|town|toys|tube|vana|visa|viva|vivo|vote|voto|wang|weir|wien|wiki|wine|work|xbox|yoga|zara|zero|zone|дети|сайт|بارت|بيتك|ڀارت|تونس|شبكة|عراق|عمان|موقع|भारत|ভারত|ভাৰত|ਭਾਰਤ|ભારત|ଭାରତ|ಭಾರತ|ලංකා|グーグル|クラウド|ポイント|大众汽车|组织机构|電訊盈科|香格里拉|aaa|abb|abc|aco|ads|aeg|afl|aig|anz|aol|app|art|aws|axa|bar|bbc|bbt|bcg|bcn|bet|bid|bio|biz|bms|bmw|bnl|bom|boo|bot|box|buy|bzh|cab|cal|cam|car|cat|cba|cbn|cbs|ceb|ceo|cfa|cfd|com|crs|csc|dad|day|dds|dev|dhl|diy|dnp|dog|dot|dtv|dvr|eat|eco|edu|esq|eus|fan|fit|fly|foo|fox|frl|ftr|fun|fyi|gal|gap|gdn|gea|gle|gmo|gmx|goo|gop|got|gov|hbo|hiv|hkt|hot|how|ibm|ice|icu|ifm|inc|ing|ink|int|ist|itv|jcb|jcp|jio|jll|jmp|jnj|jot|joy|kfh|kia|kim|kpn|krd|lat|law|lds|llc|lol|lpl|ltd|man|map|mba|med|men|mil|mit|mlb|mls|mma|moe|moi|mom|mov|msd|mtn|mtr|nab|nba|nec|net|new|nfl|ngo|nhk|now|nra|nrw|ntt|nyc|obi|off|one|ong|onl|ooo|org|ott|ovh|pay|pet|phd|pid|pin|pnc|pro|pru|pub|pwc|qvc|red|ren|ril|rio|rip|run|rwe|sap|sas|sbi|sbs|sca|scb|ses|sew|sex|sfr|ski|sky|soy|srl|srt|stc|tab|tax|tci|tdk|tel|thd|tjx|top|trv|tui|tvs|ubs|uno|uol|ups|vet|vig|vin|vip|wed|win|wme|wow|wtc|wtf|xin|xxx|xyz|you|yun|zip|бел|ком|қаз|мкд|мон|орг|рус|срб|укр|հայ|קום|عرب|قطر|كوم|مصر|कॉम|नेट|คอม|ไทย|ストア|セール|みんな|中文网|天主教|我爱你|新加坡|淡马锡|诺基亚|飞利浦|ac|ad|ae|af|ag|ai|al|am|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|ελ|бг|ею|рф|გე|닷넷|닷컴|삼성|한국|コム|世界|中信|中国|中國|企业|佛山|信息|健康|八卦|公司|公益|台湾|台灣|商城|商店|商标|嘉里|在线|大拿|娱乐|家電|工行|广东|微博|慈善|手机|手表|招聘|政务|政府|新闻|时尚|書籍|机构|游戏|澳門|点看|珠宝|移动|网址|网店|网站|网络|联通|谷歌|购物|通販|集团|食品|餐厅|香港)/; + + // For debugging: search for other "For debugging" lines + // import CliTable from 'cli-table'; + /** + * @class Autolinker.matcher.Email + * @extends Autolinker.matcher.Matcher + * + * Matcher to find email matches in an input string. + * + * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. + */ + var EmailMatcher = /** @class */ (function (_super) { + __extends(EmailMatcher, _super); + function EmailMatcher() { + var _this = _super !== null && _super.apply(this, arguments) || this; + /** + * Valid characters that can be used in the "local" part of an email address, + * i.e. the "name" part of "name@site.com" + */ + _this.localPartCharRegex = new RegExp("[" + alphaNumericAndMarksCharsStr + "!#$%&'*+/=?^_`{|}~-]"); + /** + * Stricter TLD regex which adds a beginning and end check to ensure + * the string is a valid TLD + */ + _this.strictTldRegex = new RegExp("^" + tldRegex.source + "$"); + return _this; + } + /** + * @inheritdoc + */ + EmailMatcher.prototype.parseMatches = function (text) { + var tagBuilder = this.tagBuilder, localPartCharRegex = this.localPartCharRegex, strictTldRegex = this.strictTldRegex, matches = [], len = text.length, noCurrentEmailMatch = new CurrentEmailMatch(); + // for matching a 'mailto:' prefix + var mailtoTransitions = { + 'm': 'a', + 'a': 'i', + 'i': 'l', + 'l': 't', + 't': 'o', + 'o': ':', + }; + var charIdx = 0, state = 0 /* NonEmailMatch */, currentEmailMatch = noCurrentEmailMatch; + // For debugging: search for other "For debugging" lines + // const table = new CliTable( { + // head: [ 'charIdx', 'char', 'state', 'charIdx', 'currentEmailAddress.idx', 'hasDomainDot' ] + // } ); + while (charIdx < len) { + var char = text.charAt(charIdx); + // For debugging: search for other "For debugging" lines + // table.push( + // [ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ] + // ); + switch (state) { + case 0 /* NonEmailMatch */: + stateNonEmailAddress(char); + break; + case 1 /* Mailto */: + stateMailTo(text.charAt(charIdx - 1), char); + break; + case 2 /* LocalPart */: + stateLocalPart(char); + break; + case 3 /* LocalPartDot */: + stateLocalPartDot(char); + break; + case 4 /* AtSign */: + stateAtSign(char); + break; + case 5 /* DomainChar */: + stateDomainChar(char); + break; + case 6 /* DomainHyphen */: + stateDomainHyphen(char); + break; + case 7 /* DomainDot */: + stateDomainDot(char); + break; + default: + throwUnhandledCaseError(state); + } + // For debugging: search for other "For debugging" lines + // table.push( + // [ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ] + // ); + charIdx++; + } + // Capture any valid match at the end of the string + captureMatchIfValidAndReset(); + // For debugging: search for other "For debugging" lines + //console.log( '\n' + table.toString() ); + return matches; + // Handles the state when we're not in an email address + function stateNonEmailAddress(char) { + if (char === 'm') { + beginEmailMatch(1 /* Mailto */); + } + else if (localPartCharRegex.test(char)) { + beginEmailMatch(); + } + } + // Handles if we're reading a 'mailto:' prefix on the string + function stateMailTo(prevChar, char) { + if (prevChar === ':') { + // We've reached the end of the 'mailto:' prefix + if (localPartCharRegex.test(char)) { + state = 2 /* LocalPart */; + currentEmailMatch = new CurrentEmailMatch(__assign({}, currentEmailMatch, { hasMailtoPrefix: true })); + } + else { + // we've matched 'mailto:' but didn't get anything meaningful + // immediately afterwards (for example, we encountered a + // space character, or an '@' character which formed 'mailto:@' + resetToNonEmailMatchState(); + } + } + else if (mailtoTransitions[prevChar] === char) ; + else if (localPartCharRegex.test(char)) { + // We we're reading a prefix of 'mailto:', but encountered a + // different character that didn't continue the prefix + state = 2 /* LocalPart */; + } + else if (char === '.') { + // We we're reading a prefix of 'mailto:', but encountered a + // dot character + state = 3 /* LocalPartDot */; + } + else if (char === '@') { + // We we're reading a prefix of 'mailto:', but encountered a + // an @ character + state = 4 /* AtSign */; + } + else { + // not an email address character, return to "NonEmailAddress" state + resetToNonEmailMatchState(); + } + } + // Handles the state when we're currently in the "local part" of an + // email address (as opposed to the "domain part") + function stateLocalPart(char) { + if (char === '.') { + state = 3 /* LocalPartDot */; + } + else if (char === '@') { + state = 4 /* AtSign */; + } + else if (localPartCharRegex.test(char)) ; + else { + // not an email address character, return to "NonEmailAddress" state + resetToNonEmailMatchState(); + } + } + // Handles the state where we've read + function stateLocalPartDot(char) { + if (char === '.') { + // We read a second '.' in a row, not a valid email address + // local part + resetToNonEmailMatchState(); + } + else if (char === '@') { + // We read the '@' character immediately after a dot ('.'), not + // an email address + resetToNonEmailMatchState(); + } + else if (localPartCharRegex.test(char)) { + state = 2 /* LocalPart */; + } + else { + // Anything else, not an email address + resetToNonEmailMatchState(); + } + } + function stateAtSign(char) { + if (domainNameCharRegex.test(char)) { + state = 5 /* DomainChar */; + } + else { + // Anything else, not an email address + resetToNonEmailMatchState(); + } + } + function stateDomainChar(char) { + if (char === '.') { + state = 7 /* DomainDot */; + } + else if (char === '-') { + state = 6 /* DomainHyphen */; + } + else if (domainNameCharRegex.test(char)) ; + else { + // Anything else, we potentially matched if the criteria has + // been met + captureMatchIfValidAndReset(); + } + } + function stateDomainHyphen(char) { + if (char === '-' || char === '.') { + // Not valid to have two hyphens ("--") or hypen+dot ("-.") + captureMatchIfValidAndReset(); + } + else if (domainNameCharRegex.test(char)) { + state = 5 /* DomainChar */; + } + else { + // Anything else + captureMatchIfValidAndReset(); + } + } + function stateDomainDot(char) { + if (char === '.' || char === '-') { + // not valid to have two dots ("..") or dot+hypen (".-") + captureMatchIfValidAndReset(); + } + else if (domainNameCharRegex.test(char)) { + state = 5 /* DomainChar */; + // After having read a '.' and then a valid domain character, + // we now know that the domain part of the email is valid, and + // we have found at least a partial EmailMatch (however, the + // email address may have additional characters from this point) + currentEmailMatch = new CurrentEmailMatch(__assign({}, currentEmailMatch, { hasDomainDot: true })); + } + else { + // Anything else + captureMatchIfValidAndReset(); + } + } + function beginEmailMatch(newState) { + if (newState === void 0) { newState = 2 /* LocalPart */; } + state = newState; + currentEmailMatch = new CurrentEmailMatch({ idx: charIdx }); + } + function resetToNonEmailMatchState() { + state = 0 /* NonEmailMatch */; + currentEmailMatch = noCurrentEmailMatch; + } + /* + * Captures the current email address as an EmailMatch if it's valid, + * and resets the state to read another email address. + */ + function captureMatchIfValidAndReset() { + if (currentEmailMatch.hasDomainDot) { // we need at least one dot in the domain to be considered a valid email address + var matchedText = text.slice(currentEmailMatch.idx, charIdx); + // If we read a '.' or '-' char that ended the email address + // (valid domain name characters, but only valid email address + // characters if they are followed by something else), strip + // it off now + if (/[-.]$/.test(matchedText)) { + matchedText = matchedText.slice(0, -1); + } + var emailAddress = currentEmailMatch.hasMailtoPrefix + ? matchedText.slice('mailto:'.length) + : matchedText; + // if the email address has a valid TLD, add it to the list of matches + if (doesEmailHaveValidTld(emailAddress)) { + matches.push(new EmailMatch({ + tagBuilder: tagBuilder, + matchedText: matchedText, + offset: currentEmailMatch.idx, + email: emailAddress + })); + } + } + resetToNonEmailMatchState(); + /** + * Determines if the given email address has a valid TLD or not + * @param {string} emailAddress - email address + * @return {Boolean} - true is email have valid TLD, false otherwise + */ + function doesEmailHaveValidTld(emailAddress) { + var emailAddressTld = emailAddress.split('.').pop() || ''; + var emailAddressNormalized = emailAddressTld.toLowerCase(); + var isValidTld = strictTldRegex.test(emailAddressNormalized); + return isValidTld; + } + } + }; + return EmailMatcher; + }(Matcher)); + var CurrentEmailMatch = /** @class */ (function () { + function CurrentEmailMatch(cfg) { + if (cfg === void 0) { cfg = {}; } + this.idx = cfg.idx !== undefined ? cfg.idx : -1; + this.hasMailtoPrefix = !!cfg.hasMailtoPrefix; + this.hasDomainDot = !!cfg.hasDomainDot; + } + return CurrentEmailMatch; + }()); + + /** + * @private + * @class Autolinker.matcher.UrlMatchValidator + * @singleton + * + * Used by Autolinker to filter out false URL positives from the + * {@link Autolinker.matcher.Url UrlMatcher}. + * + * Due to the limitations of regular expressions (including the missing feature + * of look-behinds in JS regular expressions), we cannot always determine the + * validity of a given match. This class applies a bit of additional logic to + * filter out any false positives that have been matched by the + * {@link Autolinker.matcher.Url UrlMatcher}. + */ + var UrlMatchValidator = /** @class */ (function () { + function UrlMatchValidator() { + } + /** + * Determines if a given URL match found by the {@link Autolinker.matcher.Url UrlMatcher} + * is valid. Will return `false` for: + * + * 1) URL matches which do not have at least have one period ('.') in the + * domain name (effectively skipping over matches like "abc:def"). + * However, URL matches with a protocol will be allowed (ex: 'http://localhost') + * 2) URL matches which do not have at least one word character in the + * domain name (effectively skipping over matches like "git:1.0"). + * 3) A protocol-relative url match (a URL beginning with '//') whose + * previous character is a word character (effectively skipping over + * strings like "abc//google.com") + * + * Otherwise, returns `true`. + * + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} protocolUrlMatch The match URL string for a protocol + * match. Ex: 'http://yahoo.com'. This is used to match something like + * 'http://localhost', where we won't double check that the domain name + * has at least one '.' in it. + * @return {Boolean} `true` if the match given is valid and should be + * processed, or `false` if the match is invalid and/or should just not be + * processed. + */ + UrlMatchValidator.isValid = function (urlMatch, protocolUrlMatch) { + if ((protocolUrlMatch && !this.isValidUriScheme(protocolUrlMatch)) || + this.urlMatchDoesNotHaveProtocolOrDot(urlMatch, protocolUrlMatch) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost') + (this.urlMatchDoesNotHaveAtLeastOneWordChar(urlMatch, protocolUrlMatch) && // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" + !this.isValidIpAddress(urlMatch)) || // Except if it's an IP address + this.containsMultipleDots(urlMatch)) { + return false; + } + return true; + }; + UrlMatchValidator.isValidIpAddress = function (uriSchemeMatch) { + var newRegex = new RegExp(this.hasFullProtocolRegex.source + this.ipRegex.source); + var uriScheme = uriSchemeMatch.match(newRegex); + return uriScheme !== null; + }; + UrlMatchValidator.containsMultipleDots = function (urlMatch) { + var stringBeforeSlash = urlMatch; + if (this.hasFullProtocolRegex.test(urlMatch)) { + stringBeforeSlash = urlMatch.split('://')[1]; + } + return stringBeforeSlash.split('/')[0].indexOf("..") > -1; + }; + /** + * Determines if the URI scheme is a valid scheme to be autolinked. Returns + * `false` if the scheme is 'javascript:' or 'vbscript:' + * + * @private + * @param {String} uriSchemeMatch The match URL string for a full URI scheme + * match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'. + * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise. + */ + UrlMatchValidator.isValidUriScheme = function (uriSchemeMatch) { + var uriSchemeMatchArr = uriSchemeMatch.match(this.uriSchemeRegex), uriScheme = uriSchemeMatchArr && uriSchemeMatchArr[0].toLowerCase(); + return (uriScheme !== 'javascript:' && uriScheme !== 'vbscript:'); + }; + /** + * Determines if a URL match does not have either: + * + * a) a full protocol (i.e. 'http://'), or + * b) at least one dot ('.') in the domain name (for a non-full-protocol + * match). + * + * Either situation is considered an invalid URL (ex: 'git:d' does not have + * either the '://' part, or at least one dot in the domain name. If the + * match was 'git:abc.com', we would consider this valid.) + * + * @private + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} protocolUrlMatch The match URL string for a protocol + * match. Ex: 'http://yahoo.com'. This is used to match something like + * 'http://localhost', where we won't double check that the domain name + * has at least one '.' in it. + * @return {Boolean} `true` if the URL match does not have a full protocol, + * or at least one dot ('.') in a non-full-protocol match. + */ + UrlMatchValidator.urlMatchDoesNotHaveProtocolOrDot = function (urlMatch, protocolUrlMatch) { + return (!!urlMatch && (!protocolUrlMatch || !this.hasFullProtocolRegex.test(protocolUrlMatch)) && urlMatch.indexOf('.') === -1); + }; + /** + * Determines if a URL match does not have at least one word character after + * the protocol (i.e. in the domain name). + * + * At least one letter character must exist in the domain name after a + * protocol match. Ex: skip over something like "git:1.0" + * + * @private + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} protocolUrlMatch The match URL string for a protocol + * match. Ex: 'http://yahoo.com'. This is used to know whether or not we + * have a protocol in the URL string, in order to check for a word + * character after the protocol separator (':'). + * @return {Boolean} `true` if the URL match does not have at least one word + * character in it after the protocol, `false` otherwise. + */ + UrlMatchValidator.urlMatchDoesNotHaveAtLeastOneWordChar = function (urlMatch, protocolUrlMatch) { + if (urlMatch && protocolUrlMatch) { + return !this.hasWordCharAfterProtocolRegex.test(urlMatch); + } + else { + return false; + } + }; + /** + * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://' + * + * @private + * @property {RegExp} hasFullProtocolRegex + */ + UrlMatchValidator.hasFullProtocolRegex = /^[A-Za-z][-.+A-Za-z0-9]*:\/\//; + /** + * Regex to find the URI scheme, such as 'mailto:'. + * + * This is used to filter out 'javascript:' and 'vbscript:' schemes. + * + * @private + * @property {RegExp} uriSchemeRegex + */ + UrlMatchValidator.uriSchemeRegex = /^[A-Za-z][-.+A-Za-z0-9]*:/; + /** + * Regex to determine if at least one word char exists after the protocol (i.e. after the ':') + * + * @private + * @property {RegExp} hasWordCharAfterProtocolRegex + */ + UrlMatchValidator.hasWordCharAfterProtocolRegex = new RegExp(":[^\\s]*?[" + alphaCharsStr + "]"); + /** + * Regex to determine if the string is a valid IP address + * + * @private + * @property {RegExp} ipRegex + */ + UrlMatchValidator.ipRegex = /[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/; + return UrlMatchValidator; + }()); + + /** + * @class Autolinker.matcher.Url + * @extends Autolinker.matcher.Matcher + * + * Matcher to find URL matches in an input string. + * + * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. + */ + var UrlMatcher = /** @class */ (function (_super) { + __extends(UrlMatcher, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match instance, + * specified in an Object (map). + */ + function UrlMatcher(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {Object} stripPrefix (required) + * + * The Object form of {@link Autolinker#cfg-stripPrefix}. + */ + _this.stripPrefix = { scheme: true, www: true }; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Boolean} stripTrailingSlash (required) + * @inheritdoc Autolinker#stripTrailingSlash + */ + _this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @cfg {Boolean} decodePercentEncoding (required) + * @inheritdoc Autolinker#decodePercentEncoding + */ + _this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * @protected + * @property {RegExp} matcherRegex + * + * The regular expression to match URLs with an optional scheme, port + * number, path, query string, and hash anchor. + * + * Example matches: + * + * http://google.com + * www.google.com + * google.com/path/to/file?q1=1&q2=2#myAnchor + * + * + * This regular expression will have the following capturing groups: + * + * 1. Group that matches a scheme-prefixed URL (i.e. 'http://google.com'). + * This is used to match scheme URLs with just a single word, such as + * 'http://localhost', where we won't double check that the domain name + * has at least one dot ('.') in it. + * 2. Group that matches a 'www.' prefixed URL. This is only matched if the + * 'www.' text was not prefixed by a scheme (i.e.: not prefixed by + * 'http://', 'ftp:', etc.) + * 3. A protocol-relative ('//') match for the case of a 'www.' prefixed + * URL. Will be an empty string if it is not a protocol-relative match. + * We need to know the character before the '//' in order to determine + * if it is a valid match or the // was in a string we don't want to + * auto-link. + * 4. Group that matches a known TLD (top level domain), when a scheme + * or 'www.'-prefixed domain is not matched. + * 5. A protocol-relative ('//') match for the case of a known TLD prefixed + * URL. Will be an empty string if it is not a protocol-relative match. + * See #3 for more info. + */ + _this.matcherRegex = (function () { + var schemeRegex = /(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\/\/)(?!\d+\/?)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex) + wwwRegex = /(?:www\.)/, // starting with 'www.' + // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;" + // http://blog.codinghorror.com/the-problem-with-urls/ + urlSuffixRegex = new RegExp('[/?#](?:[' + alphaNumericAndMarksCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]?!:,.;\u2713]*[' + alphaNumericAndMarksCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]\u2713])?'); + return new RegExp([ + '(?:', + '(', + schemeRegex.source, + getDomainNameStr(2), + ')', + '|', + '(', + '(//)?', + wwwRegex.source, + getDomainNameStr(6), + ')', + '|', + '(', + '(//)?', + getDomainNameStr(10) + '\\.', + tldRegex.source, + '(?![-' + alphaNumericCharsStr + '])', + ')', + ')', + '(?::[0-9]+)?', + '(?:' + urlSuffixRegex.source + ')?' // match for path, query string, and/or hash anchor - optional + ].join(""), 'gi'); + })(); + /** + * A regular expression to use to check the character before a protocol-relative + * URL match. We don't want to match a protocol-relative URL if it is part + * of another word. + * + * For example, we want to match something like "Go to: //google.com", + * but we don't want to match something like "abc//google.com" + * + * This regular expression is used to test the character before the '//'. + * + * @protected + * @type {RegExp} wordCharRegExp + */ + _this.wordCharRegExp = new RegExp('[' + alphaNumericAndMarksCharsStr + ']'); + _this.stripPrefix = cfg.stripPrefix; + _this.stripTrailingSlash = cfg.stripTrailingSlash; + _this.decodePercentEncoding = cfg.decodePercentEncoding; + return _this; + } + /** + * @inheritdoc + */ + UrlMatcher.prototype.parseMatches = function (text) { + var matcherRegex = this.matcherRegex, stripPrefix = this.stripPrefix, stripTrailingSlash = this.stripTrailingSlash, decodePercentEncoding = this.decodePercentEncoding, tagBuilder = this.tagBuilder, matches = [], match; + var _loop_1 = function () { + var matchStr = match[0], schemeUrlMatch = match[1], wwwUrlMatch = match[4], wwwProtocolRelativeMatch = match[5], + //tldUrlMatch = match[ 8 ], -- not needed at the moment + tldProtocolRelativeMatch = match[9], offset = match.index, protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch, prevChar = text.charAt(offset - 1); + if (!UrlMatchValidator.isValid(matchStr, schemeUrlMatch)) { + return "continue"; + } + // If the match is preceded by an '@' character, then it is either + // an email address or a username. Skip these types of matches. + if (offset > 0 && prevChar === '@') { + return "continue"; + } + // If it's a protocol-relative '//' match, but the character before the '//' + // was a word character (i.e. a letter/number), then we found the '//' in the + // middle of another word (such as "asdf//asdf.com"). In this case, skip the + // match. + if (offset > 0 && protocolRelativeMatch && this_1.wordCharRegExp.test(prevChar)) { + return "continue"; + } + // If the URL ends with a question mark, don't include the question + // mark as part of the URL. We'll assume the question mark was the + // end of a sentence, such as: "Going to google.com?" + if (/\?$/.test(matchStr)) { + matchStr = matchStr.substr(0, matchStr.length - 1); + } + // Handle a closing parenthesis or square bracket at the end of the + // match, and exclude it if there is not a matching open parenthesis + // or square bracket in the match itself. + if (this_1.matchHasUnbalancedClosingParen(matchStr)) { + matchStr = matchStr.substr(0, matchStr.length - 1); // remove the trailing ")" + } + else { + // Handle an invalid character after the TLD + var pos = this_1.matchHasInvalidCharAfterTld(matchStr, schemeUrlMatch); + if (pos > -1) { + matchStr = matchStr.substr(0, pos); // remove the trailing invalid chars + } + } + // The autolinker accepts many characters in a url's scheme (like `fake://test.com`). + // However, in cases where a URL is missing whitespace before an obvious link, + // (for example: `nowhitespacehttp://www.test.com`), we only want the match to start + // at the http:// part. We will check if the match contains a common scheme and then + // shift the match to start from there. + var foundCommonScheme = ['http://', 'https://'].find(function (commonScheme) { return !!schemeUrlMatch && schemeUrlMatch.indexOf(commonScheme) !== -1; }); + if (foundCommonScheme) { + // If we found an overmatched URL, we want to find the index + // of where the match should start and shift the match to + // start from the beginning of the common scheme + var indexOfSchemeStart = matchStr.indexOf(foundCommonScheme); + matchStr = matchStr.substr(indexOfSchemeStart); + schemeUrlMatch = schemeUrlMatch.substr(indexOfSchemeStart); + offset = offset + indexOfSchemeStart; + } + var urlMatchType = schemeUrlMatch ? 'scheme' : (wwwUrlMatch ? 'www' : 'tld'), protocolUrlMatch = !!schemeUrlMatch; + matches.push(new UrlMatch({ + tagBuilder: tagBuilder, + matchedText: matchStr, + offset: offset, + urlMatchType: urlMatchType, + url: matchStr, + protocolUrlMatch: protocolUrlMatch, + protocolRelativeMatch: !!protocolRelativeMatch, + stripPrefix: stripPrefix, + stripTrailingSlash: stripTrailingSlash, + decodePercentEncoding: decodePercentEncoding, + })); + }; + var this_1 = this; + while ((match = matcherRegex.exec(text)) !== null) { + _loop_1(); + } + return matches; + }; + /** + * Determines if a match found has an unmatched closing parenthesis or + * square bracket. If so, the parenthesis or square bracket will be removed + * from the match itself, and appended after the generated anchor tag. + * + * A match may have an extra closing parenthesis at the end of the match + * because the regular expression must include parenthesis for URLs such as + * "wikipedia.com/something_(disambiguation)", which should be auto-linked. + * + * However, an extra parenthesis *will* be included when the URL itself is + * wrapped in parenthesis, such as in the case of: + * "(wikipedia.com/something_(disambiguation))" + * In this case, the last closing parenthesis should *not* be part of the + * URL itself, and this method will return `true`. + * + * For square brackets in URLs such as in PHP arrays, the same behavior as + * parenthesis discussed above should happen: + * "[http://www.example.com/foo.php?bar[]=1&bar[]=2&bar[]=3]" + * The closing square bracket should not be part of the URL itself, and this + * method will return `true`. + * + * @protected + * @param {String} matchStr The full match string from the {@link #matcherRegex}. + * @return {Boolean} `true` if there is an unbalanced closing parenthesis or + * square bracket at the end of the `matchStr`, `false` otherwise. + */ + UrlMatcher.prototype.matchHasUnbalancedClosingParen = function (matchStr) { + var endChar = matchStr.charAt(matchStr.length - 1); + var startChar; + if (endChar === ')') { + startChar = '('; + } + else if (endChar === ']') { + startChar = '['; + } + else { + return false; // not a close parenthesis or square bracket + } + // Find if there are the same number of open braces as close braces in + // the URL string, minus the last character (which we have already + // determined to be either ')' or ']' + var numOpenBraces = 0; + for (var i = 0, len = matchStr.length - 1; i < len; i++) { + var char = matchStr.charAt(i); + if (char === startChar) { + numOpenBraces++; + } + else if (char === endChar) { + numOpenBraces = Math.max(numOpenBraces - 1, 0); + } + } + // If the number of open braces matches the number of close braces in + // the URL minus the last character, then the match has *unbalanced* + // braces because of the last character. Example of unbalanced braces + // from the regex match: + // "http://example.com?a[]=1]" + if (numOpenBraces === 0) { + return true; + } + return false; + }; + /** + * Determine if there's an invalid character after the TLD in a URL. Valid + * characters after TLD are ':/?#'. Exclude scheme matched URLs from this + * check. + * + * @protected + * @param {String} urlMatch The matched URL, if there was one. Will be an + * empty string if the match is not a URL match. + * @param {String} schemeUrlMatch The match URL string for a scheme + * match. Ex: 'http://yahoo.com'. This is used to match something like + * 'http://localhost', where we won't double check that the domain name + * has at least one '.' in it. + * @return {Number} the position where the invalid character was found. If + * no such character was found, returns -1 + */ + UrlMatcher.prototype.matchHasInvalidCharAfterTld = function (urlMatch, schemeUrlMatch) { + if (!urlMatch) { + return -1; + } + var offset = 0; + if (schemeUrlMatch) { + offset = urlMatch.indexOf(':'); + urlMatch = urlMatch.slice(offset); + } + var re = new RegExp("^((.?\/\/)?[-." + alphaNumericAndMarksCharsStr + "]*[-" + alphaNumericAndMarksCharsStr + "]\\.[-" + alphaNumericAndMarksCharsStr + "]+)"); + var res = re.exec(urlMatch); + if (res === null) { + return -1; + } + offset += res[1].length; + urlMatch = urlMatch.slice(res[1].length); + if (/^[^-.A-Za-z0-9:\/?#]/.test(urlMatch)) { + return offset; + } + return -1; + }; + return UrlMatcher; + }(Matcher)); + + /** + * @class Autolinker.matcher.Hashtag + * @extends Autolinker.matcher.Matcher + * + * Matcher to find HashtagMatch matches in an input string. + */ + var HashtagMatcher = /** @class */ (function (_super) { + __extends(HashtagMatcher, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match instance, + * specified in an Object (map). + */ + function HashtagMatcher(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {String} serviceName + * + * The service to point hashtag matches to. See {@link Autolinker#hashtag} + * for available values. + */ + _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * The regular expression to match Hashtags. Example match: + * + * #asdf + * + * @protected + * @property {RegExp} matcherRegex + */ + _this.matcherRegex = new RegExp("#[_" + alphaNumericAndMarksCharsStr + "]{1,139}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'); // lookahead used to make sure we don't match something above 139 characters + /** + * The regular expression to use to check the character before a username match to + * make sure we didn't accidentally match an email address. + * + * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. + * + * @protected + * @property {RegExp} nonWordCharRegex + */ + _this.nonWordCharRegex = new RegExp('[^' + alphaNumericAndMarksCharsStr + ']'); + _this.serviceName = cfg.serviceName; + return _this; + } + /** + * @inheritdoc + */ + HashtagMatcher.prototype.parseMatches = function (text) { + var matcherRegex = this.matcherRegex, nonWordCharRegex = this.nonWordCharRegex, serviceName = this.serviceName, tagBuilder = this.tagBuilder, matches = [], match; + while ((match = matcherRegex.exec(text)) !== null) { + var offset = match.index, prevChar = text.charAt(offset - 1); + // If we found the match at the beginning of the string, or we found the match + // and there is a whitespace char in front of it (meaning it is not a '#' char + // in the middle of a word), then it is a hashtag match. + if (offset === 0 || nonWordCharRegex.test(prevChar)) { + var matchedText = match[0], hashtag = match[0].slice(1); // strip off the '#' character at the beginning + matches.push(new HashtagMatch({ + tagBuilder: tagBuilder, + matchedText: matchedText, + offset: offset, + serviceName: serviceName, + hashtag: hashtag + })); + } + } + return matches; + }; + return HashtagMatcher; + }(Matcher)); + + /** + * @class Autolinker.matcher.Phone + * @extends Autolinker.matcher.Matcher + * + * Matcher to find Phone number matches in an input string. + * + * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more + * details. + */ + var PhoneMatcher = /** @class */ (function (_super) { + __extends(PhoneMatcher, _super); + function PhoneMatcher() { + var _this = _super !== null && _super.apply(this, arguments) || this; + /** + * The regular expression to match Phone numbers. Example match: + * + * (123) 456-7890 + * + * This regular expression has the following capturing groups: + * + * 1 or 2. The prefixed '+' sign, if there is one. + * + * @protected + * @property {RegExp} matcherRegex + */ + _this.matcherRegex = /(?:(?:(?:(\+)?\d{1,3}[-\040.]?)?\(?\d{3}\)?[-\040.]?\d{3}[-\040.]?\d{4})|(?:(\+)(?:9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)[-\040.]?(?:\d[-\040.]?){6,12}\d+))([,;]+[0-9]+#?)*/g; + return _this; + } + // ex: (123) 456-7890, 123 456 7890, 123-456-7890, +18004441234,,;,10226420346#, + // +1 (800) 444 1234, 10226420346#, 1-800-444-1234,1022,64,20346# + /** + * @inheritdoc + */ + PhoneMatcher.prototype.parseMatches = function (text) { + var matcherRegex = this.matcherRegex, tagBuilder = this.tagBuilder, matches = [], match; + while ((match = matcherRegex.exec(text)) !== null) { + // Remove non-numeric values from phone number string + var matchedText = match[0], cleanNumber = matchedText.replace(/[^0-9,;#]/g, ''), // strip out non-digit characters exclude comma semicolon and # + plusSign = !!(match[1] || match[2]), // match[ 1 ] or match[ 2 ] is the prefixed plus sign, if there is one + before = match.index == 0 ? '' : text.substr(match.index - 1, 1), after = text.substr(match.index + matchedText.length, 1), contextClear = !before.match(/\d/) && !after.match(/\d/); + if (this.testMatch(match[3]) && this.testMatch(matchedText) && contextClear) { + matches.push(new PhoneMatch({ + tagBuilder: tagBuilder, + matchedText: matchedText, + offset: match.index, + number: cleanNumber, + plusSign: plusSign + })); + } + } + return matches; + }; + PhoneMatcher.prototype.testMatch = function (text) { + return /\D/.test(text); + }; + return PhoneMatcher; + }(Matcher)); + + /** + * @class Autolinker.matcher.Mention + * @extends Autolinker.matcher.Matcher + * + * Matcher to find/replace username matches in an input string. + */ + var MentionMatcher = /** @class */ (function (_super) { + __extends(MentionMatcher, _super); + /** + * @method constructor + * @param {Object} cfg The configuration properties for the Match instance, + * specified in an Object (map). + */ + function MentionMatcher(cfg) { + var _this = _super.call(this, cfg) || this; + /** + * @cfg {'twitter'/'instagram'/'soundcloud'} protected + * + * The name of service to link @mentions to. + * + * Valid values are: 'twitter', 'instagram', or 'soundcloud' + */ + _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator + /** + * Hash of regular expression to match username handles. Example match: + * + * @asdf + * + * @private + * @property {Object} matcherRegexes + */ + _this.matcherRegexes = { + 'twitter': new RegExp("@[_" + alphaNumericAndMarksCharsStr + "]{1,50}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'), + 'instagram': new RegExp("@[_." + alphaNumericAndMarksCharsStr + "]{1,30}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'), + 'soundcloud': new RegExp("@[-_." + alphaNumericAndMarksCharsStr + "]{1,50}(?![-_" + alphaNumericAndMarksCharsStr + "])", 'g') // lookahead used to make sure we don't match something above 50 characters + }; + /** + * The regular expression to use to check the character before a username match to + * make sure we didn't accidentally match an email address. + * + * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. + * + * @private + * @property {RegExp} nonWordCharRegex + */ + _this.nonWordCharRegex = new RegExp('[^' + alphaNumericAndMarksCharsStr + ']'); + _this.serviceName = cfg.serviceName; + return _this; + } + /** + * @inheritdoc + */ + MentionMatcher.prototype.parseMatches = function (text) { + var serviceName = this.serviceName, matcherRegex = this.matcherRegexes[this.serviceName], nonWordCharRegex = this.nonWordCharRegex, tagBuilder = this.tagBuilder, matches = [], match; + if (!matcherRegex) { + return matches; + } + while ((match = matcherRegex.exec(text)) !== null) { + var offset = match.index, prevChar = text.charAt(offset - 1); + // If we found the match at the beginning of the string, or we found the match + // and there is a whitespace char in front of it (meaning it is not an email + // address), then it is a username match. + if (offset === 0 || nonWordCharRegex.test(prevChar)) { + var matchedText = match[0].replace(/\.+$/g, ''), // strip off trailing . + mention = matchedText.slice(1); // strip off the '@' character at the beginning + matches.push(new MentionMatch({ + tagBuilder: tagBuilder, + matchedText: matchedText, + offset: offset, + serviceName: serviceName, + mention: mention + })); + } + } + return matches; + }; + return MentionMatcher; + }(Matcher)); + + // For debugging: search for other "For debugging" lines + // import CliTable from 'cli-table'; + /** + * Parses an HTML string, calling the callbacks to notify of tags and text. + * + * ## History + * + * This file previously used a regular expression to find html tags in the input + * text. Unfortunately, we ran into a bunch of catastrophic backtracking issues + * with certain input text, causing Autolinker to either hang or just take a + * really long time to parse the string. + * + * The current code is intended to be a O(n) algorithm that walks through + * the string in one pass, and tries to be as cheap as possible. We don't need + * to implement the full HTML spec, but rather simply determine where the string + * looks like an HTML tag, and where it looks like text (so that we can autolink + * that). + * + * This state machine parser is intended just to be a simple but performant + * parser of HTML for the subset of requirements we have. We simply need to: + * + * 1. Determine where HTML tags are + * 2. Determine the tag name (Autolinker specifically only cares about , + * - + + + From 332fc06c302e610a7261d545b46d6833bb0cc3a3 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Tue, 24 Sep 2019 12:44:58 -0400 Subject: [PATCH 08/20] Fixes after merge. --- Apps/TimelineDemo/TimelineDemo.js | 1 + Source/DataSources/KmlDataSource.js | 2 + Source/Renderer/Context.js | 3 +- Source/Renderer/checkFloatTexturePrecision.js | 14 ++--- Source/Scene/Picking.js | 56 +++++++++---------- Source/Scene/Scene.js | 10 +--- 6 files changed, 41 insertions(+), 45 deletions(-) diff --git a/Apps/TimelineDemo/TimelineDemo.js b/Apps/TimelineDemo/TimelineDemo.js index a0610253fcc..750928fe1da 100644 --- a/Apps/TimelineDemo/TimelineDemo.js +++ b/Apps/TimelineDemo/TimelineDemo.js @@ -5,6 +5,7 @@ define([ dijit, dojo) { 'use strict'; + /* global Cesium */ var defined = Cesium.defined; var Clock = Cesium.Clock; diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 2d64c62d80b..84263f47470 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -6,6 +6,7 @@ import Cartesian3 from '../Core/Cartesian3.js'; import Cartographic from '../Core/Cartographic.js'; import ClockRange from '../Core/ClockRange.js'; import ClockStep from '../Core/ClockStep.js'; +import clone from '../Core/clone.js'; import Color from '../Core/Color.js'; import createGuid from '../Core/createGuid.js'; import Credit from '../Core/Credit.js'; @@ -17,6 +18,7 @@ import Ellipsoid from '../Core/Ellipsoid.js'; import Event from '../Core/Event.js'; import getExtensionFromUri from '../Core/getExtensionFromUri.js'; import getFilenameFromUri from '../Core/getFilenameFromUri.js'; +import getTimestamp from '../Core/getTimestamp.js'; import HeadingPitchRange from '../Core/HeadingPitchRange.js'; import HeadingPitchRoll from '../Core/HeadingPitchRoll.js'; import Iso8601 from '../Core/Iso8601.js'; diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js index 6051fa87d9e..eac1afd472d 100644 --- a/Source/Renderer/Context.js +++ b/Source/Renderer/Context.js @@ -1,4 +1,4 @@ -t Check from '../Core/Check.js'; +import Check from '../Core/Check.js'; import clone from '../Core/clone.js'; import Color from '../Core/Color.js'; import ComponentDatatype from '../Core/ComponentDatatype.js'; @@ -17,6 +17,7 @@ import RuntimeError from '../Core/RuntimeError.js'; import WebGLConstants from '../Core/WebGLConstants.js'; import ViewportQuadVS from '../Shaders/ViewportQuadVS.js'; import BufferUsage from './BufferUsage.js'; +import checkFloatTexturePrecision from './checkFloatTexturePrecision.js'; import ClearCommand from './ClearCommand.js'; import ContextLimits from './ContextLimits.js'; import CubeMap from './CubeMap.js'; diff --git a/Source/Renderer/checkFloatTexturePrecision.js b/Source/Renderer/checkFloatTexturePrecision.js index 06ea977f9b1..5af8b83e1a0 100644 --- a/Source/Renderer/checkFloatTexturePrecision.js +++ b/Source/Renderer/checkFloatTexturePrecision.js @@ -1,10 +1,10 @@ -import { PixelFormat } from '../Core/PixelFormat.js'; -import { CheckFloatTexturePrecisionFS } from '../Shaders/CheckFloatTexturePrecisionFS.js'; -import { ComputeCommand } from './ComputeCommand.js'; -import { ComputeEngine } from './ComputeEngine.js'; -import { Framebuffer } from './Framebuffer.js'; -import { PixelDatatype } from './PixelDatatype.js'; -import { Texture } from './Texture.js'; +import PixelFormat from '../Core/PixelFormat.js'; +import CheckFloatTexturePrecisionFS from '../Shaders/CheckFloatTexturePrecisionFS.js'; +import ComputeCommand from './ComputeCommand.js'; +import ComputeEngine from './ComputeEngine.js'; +import Framebuffer from './Framebuffer.js'; +import PixelDatatype from './PixelDatatype.js'; +import Texture from './Texture.js'; /** * Checks if the context's floating point textures support 6 decimal places of precision. diff --git a/Source/Scene/Picking.js b/Source/Scene/Picking.js index 1a201535a3f..529a1f66820 100644 --- a/Source/Scene/Picking.js +++ b/Source/Scene/Picking.js @@ -1,31 +1,31 @@ -import { ApproximateTerrainHeights } from '../Core/ApproximateTerrainHeights.js'; -import { BoundingRectangle } from '../Core/BoundingRectangle.js'; -import { Cartesian2 } from '../Core/Cartesian2.js'; -import { Cartesian3 } from '../Core/Cartesian3.js'; -import { Cartographic } from '../Core/Cartographic.js'; -import { Check } from '../Core/Check.js'; -import { Color } from '../Core/Color.js'; -import { defaultValue } from '../Core/defaultValue.js'; -import { defined } from '../Core/defined.js'; -import { DeveloperError } from '../Core/DeveloperError.js'; -import { Matrix4 } from '../Core/Matrix4.js'; -import { OrthographicFrustum } from '../Core/OrthographicFrustum.js'; -import { OrthographicOffCenterFrustum } from '../Core/OrthographicOffCenterFrustum.js'; -import { PerspectiveFrustum } from '../Core/PerspectiveFrustum.js'; -import { PerspectiveOffCenterFrustum } from '../Core/PerspectiveOffCenterFrustum.js'; -import { Ray } from '../Core/Ray.js'; -import { ShowGeometryInstanceAttribute } from '../Core/ShowGeometryInstanceAttribute.js'; -import { when } from '../ThirdParty/when.js'; -import { Camera } from './Camera.js'; -import { Cesium3DTileFeature } from './Cesium3DTileFeature.js'; -import { Cesium3DTilePass } from './Cesium3DTilePass.js'; -import { Cesium3DTilePassState } from './Cesium3DTilePassState.js'; -import { Cesium3DTileset } from './Cesium3DTileset.js'; -import { PickDepth } from './PickDepth.js'; -import { PrimitiveCollection } from './PrimitiveCollection.js'; -import { SceneMode } from './SceneMode.js'; -import { SceneTransforms } from './SceneTransforms.js'; -import { View } from './View.js'; +import ApproximateTerrainHeights from '../Core/ApproximateTerrainHeights.js'; +import BoundingRectangle from '../Core/BoundingRectangle.js'; +import Cartesian2 from '../Core/Cartesian2.js'; +import Cartesian3 from '../Core/Cartesian3.js'; +import Cartographic from '../Core/Cartographic.js'; +import Check from '../Core/Check.js'; +import Color from '../Core/Color.js'; +import defaultValue from '../Core/defaultValue.js'; +import defined from '../Core/defined.js'; +import DeveloperError from '../Core/DeveloperError.js'; +import Matrix4 from '../Core/Matrix4.js'; +import OrthographicFrustum from '../Core/OrthographicFrustum.js'; +import OrthographicOffCenterFrustum from '../Core/OrthographicOffCenterFrustum.js'; +import PerspectiveFrustum from '../Core/PerspectiveFrustum.js'; +import PerspectiveOffCenterFrustum from '../Core/PerspectiveOffCenterFrustum.js'; +import Ray from '../Core/Ray.js'; +import ShowGeometryInstanceAttribute from '../Core/ShowGeometryInstanceAttribute.js'; +import when from '../ThirdParty/when.js'; +import Camera from './Camera.js'; +import Cesium3DTileFeature from './Cesium3DTileFeature.js'; +import Cesium3DTilePass from './Cesium3DTilePass.js'; +import Cesium3DTilePassState from './Cesium3DTilePassState.js'; +import Cesium3DTileset from './Cesium3DTileset.js'; +import PickDepth from './PickDepth.js'; +import PrimitiveCollection from './PrimitiveCollection.js'; +import SceneMode from './SceneMode.js'; +import SceneTransforms from './SceneTransforms.js'; +import View from './View.js'; var offscreenDefaultWidth = 0.1; diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 2817b934478..81464766957 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -1,11 +1,8 @@ -import ApproximateTerrainHeights from '../Core/ApproximateTerrainHeights.js'; import BoundingRectangle from '../Core/BoundingRectangle.js'; import BoundingSphere from '../Core/BoundingSphere.js'; import BoxGeometry from '../Core/BoxGeometry.js'; -import Cartesian2 from '../Core/Cartesian2.js'; import Cartesian3 from '../Core/Cartesian3.js'; import Cartographic from '../Core/Cartographic.js'; -import Check from '../Core/Check.js'; import Color from '../Core/Color.js'; import ColorGeometryInstanceAttribute from '../Core/ColorGeometryInstanceAttribute.js'; import createGuid from '../Core/createGuid.js'; @@ -30,9 +27,7 @@ import OrthographicFrustum from '../Core/OrthographicFrustum.js'; import OrthographicOffCenterFrustum from '../Core/OrthographicOffCenterFrustum.js'; import PerspectiveFrustum from '../Core/PerspectiveFrustum.js'; import PerspectiveOffCenterFrustum from '../Core/PerspectiveOffCenterFrustum.js'; -import Ray from '../Core/Ray.js'; import RequestScheduler from '../Core/RequestScheduler.js'; -import ShowGeometryInstanceAttribute from '../Core/ShowGeometryInstanceAttribute.js'; import TaskProcessor from '../Core/TaskProcessor.js'; import Transforms from '../Core/Transforms.js'; import ClearCommand from '../Renderer/ClearCommand.js'; @@ -44,13 +39,10 @@ import Pass from '../Renderer/Pass.js'; import RenderState from '../Renderer/RenderState.js'; import ShaderProgram from '../Renderer/ShaderProgram.js'; import ShaderSource from '../Renderer/ShaderSource.js'; -import when from '../ThirdParty/when.js'; import BrdfLutGenerator from './BrdfLutGenerator.js'; import Camera from './Camera.js'; -import Cesium3DTileFeature from './Cesium3DTileFeature.js'; import Cesium3DTilePass from './Cesium3DTilePass.js'; import Cesium3DTilePassState from './Cesium3DTilePassState.js'; -import Cesium3DTileset from './Cesium3DTileset.js'; import CreditDisplay from './CreditDisplay.js'; import DebugCameraPrimitive from './DebugCameraPrimitive.js'; import DepthPlane from './DepthPlane.js'; @@ -65,7 +57,7 @@ import MapMode2D from './MapMode2D.js'; import OctahedralProjectedCubeMap from './OctahedralProjectedCubeMap.js'; import PerformanceDisplay from './PerformanceDisplay.js'; import PerInstanceColorAppearance from './PerInstanceColorAppearance.js'; -import PickDepth from './PickDepth.js'; +import Picking from './Picking.js'; import PostProcessStageCollection from './PostProcessStageCollection.js'; import Primitive from './Primitive.js'; import PrimitiveCollection from './PrimitiveCollection.js'; From 4d1706503a56f0f2d0d7711cd395ccbeb6829849 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Tue, 24 Sep 2019 13:31:27 -0400 Subject: [PATCH 09/20] Minor clean-up --- Apps/Sandcastle/Sandcastle-helpers.js | 2 +- Apps/Sandcastle/load-cesium-es6.js | 2 +- Apps/Sandcastle/standalone.html | 23 +++++++++++++---------- package.json | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Apps/Sandcastle/Sandcastle-helpers.js b/Apps/Sandcastle/Sandcastle-helpers.js index feda23c2d6a..079610424c7 100644 --- a/Apps/Sandcastle/Sandcastle-helpers.js +++ b/Apps/Sandcastle/Sandcastle-helpers.js @@ -11,7 +11,7 @@ ' Sandcastle.finishedLoading();\n' + '}\n' + 'if (typeof Cesium !== \'undefined\') {\n' + - ' startupCalled = true;\n' + + ' window.startupCalled = true;\n' + ' startup(Cesium);\n' + '}\n'; }; diff --git a/Apps/Sandcastle/load-cesium-es6.js b/Apps/Sandcastle/load-cesium-es6.js index f4c74f5845d..dc7a14da374 100644 --- a/Apps/Sandcastle/load-cesium-es6.js +++ b/Apps/Sandcastle/load-cesium-es6.js @@ -4,7 +4,7 @@ import * as Cesium from "../../../Source/Cesium.js"; window.Cesium = Cesium; // Since ES6 modues have no gauranteed load order, -// onlycall startup if it's already defined but hasn't been called yet +// only call startup if it's already defined but hasn't been called yet if (!window.startupCalled && typeof window.startup === 'function') { window.startup(Cesium); } diff --git a/Apps/Sandcastle/standalone.html b/Apps/Sandcastle/standalone.html index 9f95abcd471..60ece3a66d5 100644 --- a/Apps/Sandcastle/standalone.html +++ b/Apps/Sandcastle/standalone.html @@ -24,19 +24,22 @@ - -   + + diff --git a/Specs/spec-main.js b/Specs/spec-main.js index db832670337..caffe5e7835 100644 --- a/Specs/spec-main.js +++ b/Specs/spec-main.js @@ -10,7 +10,12 @@ [jasmine-gem]: http://github.com/pivotal/jasmine-gem */ +// Use a pragma so we can remove this code when building specs for running in ES5 + +//>>includeStart('debug', pragmas.debug); import * as Cesium from '../Source/Cesium.js'; +//>>includeEnd('debug'); + import addDefaultMatchers from './addDefaultMatchers.js'; import equalsMethodEqualityTester from './equalsMethodEqualityTester.js'; @@ -22,7 +27,6 @@ import equalsMethodEqualityTester from './equalsMethodEqualityTester.js'; return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); } - var built = getQueryParameter('built'); var release = getQueryParameter('release'); /*global jasmineRequire,jasmine,exports,specs*/ @@ -314,6 +318,8 @@ import equalsMethodEqualityTester from './equalsMethodEqualityTester.js'; env.beforeEach(function() { addDefaultMatchers(!release).call(env); }); env.beforeEach(function() { env.addCustomEqualityTester(equalsMethodEqualityTester); }); + //>>includeStart('debug', pragmas.debug); import('./SpecList.js').then(function() { env.execute(); }) + //>>includeEnd('debug'); diff --git a/gulpfile.js b/gulpfile.js index 2987af9e969..0fe0b72db26 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -31,10 +31,10 @@ var yargs = require('yargs'); var AWS = require('aws-sdk'); var mime = require('mime'); var rollup = require('rollup'); -var cleanCSS = require('gulp-clean-css'); - -var rollupStripPragma = require('./Tools/rollup-plugin-strip-pragma'); +var rollupPluginStripPragma = require('./Tools/rollup-plugin-strip-pragma'); +var rollupPluginExternalGlobals = require('rollup-plugin-external-globals'); var rollupPluginUglify = require('rollup-plugin-uglify'); +var cleanCSS = require('gulp-clean-css'); var packageJson = require('./package.json'); var version = packageJson.version; @@ -151,6 +151,73 @@ gulp.task('buildApps', function() { ); }); +gulp.task('build-specs', function buildSpecs() { + var cesiumViewerOutputDirectory = 'Build/Apps/CesiumViewer'; + mkdirp.sync(cesiumViewerOutputDirectory); + + var promise = Promise.join( + rollup.rollup({ + input: 'Specs/SpecList.js', + plugins: [ + rollupPluginExternalGlobals({ + '../Source/Cesium.js': 'Cesium', + '../../Source/Cesium.js': 'Cesium', + '../../../Source/Cesium.js': 'Cesium', + '../../../../Source/Cesium.js': 'Cesium' + }) + ] + }).then(function(bundle) { + return bundle.write({ + file: 'Build/Specs/Specs.js', + format: 'iife' + }); + }).then(function(){ + return rollup.rollup({ + input: 'Specs/spec-main.js', + plugins: [ + rollupPluginStripPragma({ + pragmas: ['debug'] + }), + rollupPluginExternalGlobals({ + '../Source/Cesium.js': 'Cesium', + '../../Source/Cesium.js': 'Cesium', + '../../../Source/Cesium.js': 'Cesium', + '../../../../Source/Cesium.js': 'Cesium' + }) + ] + }).then(function(bundle) { + return bundle.write({ + file: 'Build/Specs/spec-main.js', + format: 'iife' + }); + }); + }).then(function(){ + return rollup.rollup({ + input: 'Specs/karma-main.js', + plugins: [ + rollupPluginStripPragma({ + pragmas: ['debug'] + }), + rollupPluginExternalGlobals({ + '../Source/Cesium.js': 'Cesium', + '../../Source/Cesium.js': 'Cesium', + '../../../Source/Cesium.js': 'Cesium', + '../../../../Source/Cesium.js': 'Cesium' + }) + ] + }).then(function(bundle) { + return bundle.write({ + file: 'Build/Specs/karma-main.js', + name: 'karmaMain', + format: 'iife' + }); + }); + }) + ); + + return promise; +}); + gulp.task('clean', function(done) { rimraf.sync('Build'); globby.sync(filesToClean).forEach(function(file) { @@ -281,7 +348,6 @@ gulp.task('makeZipFile', gulp.series('release', function() { glslToJavaScript(false, 'Build/minifyShaders.state'); var builtSrc = gulp.src([ - 'Build/Apps/**', 'Build/Cesium/**', 'Build/CesiumUnminified/**', 'Build/Documentation/**' @@ -766,7 +832,15 @@ gulp.task('test', function(done) { ]; if (release) { - files.push({pattern : 'Build/**', included : false}); + files = [ + { pattern: 'Specs/Data/**', included: false }, + { pattern: 'Specs/ThirdParty/**', included: true, type: 'module' }, + { pattern: 'Specs/TestWorkers/**', included: false }, + { pattern: 'Build/Cesium/Cesium.js', included: true }, + { pattern: 'Build/Cesium/**', included: false }, + { pattern: 'Build/Specs/karma-main.js', included: true }, + { pattern: 'Build/Specs/Specs.js', included: true } + ]; } var karma = new Karma.Server({ @@ -928,7 +1002,7 @@ function combineCesium(debug, optimizer, combineOutput) { var plugins = []; if (!debug) { - plugins.push(rollupStripPragma({ + plugins.push(rollupPluginStripPragma({ pragmas: ['debug'] })); } @@ -978,7 +1052,7 @@ function combineWorkers(debug, optimizer, combineOutput) { var plugins = []; if (!debug) { - plugins.push(rollupStripPragma({ + plugins.push(rollupPluginStripPragma({ pragmas: ['debug'] })); } @@ -1320,7 +1394,7 @@ function buildCesiumViewer() { moduleSideEffects: false }, plugins: [ - rollupStripPragma({ + rollupPluginStripPragma({ pragmas: ['debug'] }), rollupPluginUglify.uglify() diff --git a/package.json b/package.json index 5768077c6b5..7a357258ee4 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "request": "^2.79.0", "rimraf": "^3.0.0", "rollup": "^1.21.4", + "rollup-plugin-external-globals": "^0.4.0", "rollup-plugin-strip-pragma": "^1.0.0", "rollup-plugin-uglify": "^6.0.3", "stream-to-promise": "^2.2.0", @@ -98,6 +99,7 @@ "minifyRelease": "gulp minifyRelease", "optimizeApproximateTerrainHeights": "gulp optimizeApproximateTerrainHeights -p 2", "release": "gulp release", + "build-specs": "gulp build-specs", "test": "gulp test", "test-all": "gulp test --all", "test-webgl": "gulp test --include WebGL", From 5f2bc5b1a9a865a6086492233e04960f0057ae9f Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 25 Sep 2019 19:40:24 -0400 Subject: [PATCH 15/20] Remove almond. --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 7a357258ee4..963d77cd6e1 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "esm": "^3.2.25" }, "devDependencies": { - "almond": "^0.3.3", "aws-sdk": "^2.531.0", "bluebird": "^3.4.6", "cloc": "^2.3.3", From 728f85bc2a9215d7c87976be358a35d38271ff3c Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 25 Sep 2019 20:54:53 -0400 Subject: [PATCH 16/20] Fix cloc, use built version for windows appveyor. --- .appveyor.yml | 5 +++-- gulpfile.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 9e426110418..db631d033b5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -13,8 +13,9 @@ install: - npm install test_script: - - npm --silent run build - - npm --silent run test -- --browsers IE --webgl-stub --suppressPassed + - npm --silent run minifyRelease + - npm --silent run build-specs + - npm --silent run test -- --browsers IE --webgl-stub --release --suppressPassed # Don't actually build. build: off diff --git a/gulpfile.js b/gulpfile.js index 0fe0b72db26..245a56ad127 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -254,7 +254,7 @@ function cloc() { //Run cloc on primary Source files only var source = new Promise(function(resolve, reject) { cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' + - ' Source/ --exclude-dir=Assets,ThirdParty --not-match-f=copyrightHeader.js'; + ' Source/ --exclude-dir=Assets,ThirdParty,Workers --not-match-f=copyrightHeader.js'; child_process.exec(cmdLine, function(error, stdout, stderr) { if (error) { From eb168515976784ad83ee7a9fb1d5b0ae9553c93f Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 26 Sep 2019 11:17:56 -0400 Subject: [PATCH 17/20] Avoid polluting global namespace in Node.js. --- Source/ThirdParty/knockout-3.5.0.js | 25 +++++++++++++++++-------- Source/ThirdParty/protobuf-minimal.js | 21 +++++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Source/ThirdParty/knockout-3.5.0.js b/Source/ThirdParty/knockout-3.5.0.js index c23d0a1b6fa..fa768c7d783 100644 --- a/Source/ThirdParty/knockout-3.5.0.js +++ b/Source/ThirdParty/knockout-3.5.0.js @@ -1,17 +1,16 @@ var oldValue; -if (typeof window !== 'undefined') { - oldValue = window.ko; +if (typeof ko !== 'undefined') { + oldValue = ko; } (function(){ - /*! * Knockout JavaScript library v3.5.0 * (c) The Knockout.js team - http://knockoutjs.com/ * License: MIT (http://www.opensource.org/licenses/mit-license.php) */ -(function() {(function(p){var z=this||(0,eval)("this"),w=z.document,R=z.navigator,v=z.jQuery,H=z.JSON;v||"undefined"===typeof jQuery||(v=jQuery);(function(p){"function"===typeof define&&define.amd?define(["exports","require"],p):"object"===typeof exports&&"object"===typeof module?p(module.exports||exports):p(z.ko={})})(function(S,T){function K(a,c){return null===a||typeof a in W?a===c:!1}function X(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=p;b()},c))}}function Y(b,c){var d;return function(){clearTimeout(d); +(function() {(function(p){var z=this||(0,eval)("this"),w=z.document,R=z.navigator,v=z.jQuery,H=z.JSON;v||"undefined"===typeof jQuery||(v=jQuery);(function(p){"function"===typeof define&&define.amd?define(["exports","require"],p):p(z.ko={})})(function(S,T){function K(a,c){return null===a||typeof a in W?a===c:!1}function X(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=p;b()},c))}}function Y(b,c){var d;return function(){clearTimeout(d); d=a.a.setTimeout(b,c)}}function Z(a,c){c&&"change"!==c?"beforeChange"===c?this.oc(a):this.bb(a,c):this.pc(a)}function aa(a,c){null!==c&&c.s&&c.s()}function ba(a,c){var d=this.pd,e=d[t];e.qa||(this.Pb&&this.kb[c]?(d.tc(c,a,this.kb[c]),this.kb[c]=null,--this.Pb):e.F[c]||d.tc(c,a,e.G?{da:a}:d.Zc(a)),a.Ka&&a.fd())}var a="undefined"!==typeof S?S:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;f Date: Fri, 27 Sep 2019 20:04:20 -0400 Subject: [PATCH 18/20] Fix convertToModules --- gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 245a56ad127..ab3daebc047 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -970,7 +970,7 @@ gulp.task('convertToModules', function() { } } } else { - contents += 'import { ' + sortedIdentifiers[q] + ' } from ' + modulePath + ';' + os.EOL; + contents += 'import ' + sortedIdentifiers[q] + ' from ' + modulePath + ';' + os.EOL; } } } From 0fd94864de4a3d817053e9ad6daf0f89136c6d2e Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 3 Oct 2019 09:23:05 -0400 Subject: [PATCH 19/20] Changes after review. --- .eslintignore | 1 + .gitignore | 2 +- Apps/Sandcastle/load-cesium-es6.js | 4 +- ThirdParty/requirejs-2.1.20/MIT.LICENSE | 19 - ThirdParty/requirejs-2.1.20/domReady.js | 129 -- ThirdParty/requirejs-2.1.20/require.js | 2103 -------------------- ThirdParty/requirejs-2.1.20/require.min.js | 36 - gulpfile.js | 51 +- package.json | 1 + 9 files changed, 22 insertions(+), 2324 deletions(-) delete mode 100644 ThirdParty/requirejs-2.1.20/MIT.LICENSE delete mode 100644 ThirdParty/requirejs-2.1.20/domReady.js delete mode 100644 ThirdParty/requirejs-2.1.20/require.js delete mode 100644 ThirdParty/requirejs-2.1.20/require.min.js diff --git a/.eslintignore b/.eslintignore index bb3ab8d0775..f6d729a5154 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,6 +5,7 @@ Documentation/** Source/Shaders/** Source/ThirdParty/** Source/Workers/** +!Source/Workers/transferTypedArrayTest.js ThirdParty/** Tools/** Apps/Sandcastle/jsHintOptions.js diff --git a/.gitignore b/.gitignore index 3ed92865bf4..0a6c57a54ee 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ Thumbs.db /Specs/SpecList.js /Source/Shaders/**/*.js /Source/ThirdParty/Shaders/**/*.js -/Source/Workers +/Source/Workers/** !/Source/Workers/cesiumWorkerBootstrapper.js !/Source/Workers/transferTypedArrayTest.js diff --git a/Apps/Sandcastle/load-cesium-es6.js b/Apps/Sandcastle/load-cesium-es6.js index dc7a14da374..35ab6dfca53 100644 --- a/Apps/Sandcastle/load-cesium-es6.js +++ b/Apps/Sandcastle/load-cesium-es6.js @@ -1,9 +1,9 @@ -// This file load the ES6 unbuilt version of Cesium +// This file loads the unbuilt ES6 version of Cesium // into the global scope during local developmnet import * as Cesium from "../../../Source/Cesium.js"; window.Cesium = Cesium; -// Since ES6 modues have no gauranteed load order, +// Since ES6 modules have no guaranteed load order, // only call startup if it's already defined but hasn't been called yet if (!window.startupCalled && typeof window.startup === 'function') { window.startup(Cesium); diff --git a/ThirdParty/requirejs-2.1.20/MIT.LICENSE b/ThirdParty/requirejs-2.1.20/MIT.LICENSE deleted file mode 100644 index edc8ca84dca..00000000000 --- a/ThirdParty/requirejs-2.1.20/MIT.LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010-2015, The Dojo Foundation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/ThirdParty/requirejs-2.1.20/domReady.js b/ThirdParty/requirejs-2.1.20/domReady.js deleted file mode 100644 index 2b541220981..00000000000 --- a/ThirdParty/requirejs-2.1.20/domReady.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * @license RequireJS domReady 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/requirejs/domReady for details - */ -/*jslint */ -/*global require: false, define: false, requirejs: false, - window: false, clearInterval: false, document: false, - self: false, setInterval: false */ - - -define(function () { - 'use strict'; - - var isTop, testDiv, scrollIntervalId, - isBrowser = typeof window !== "undefined" && window.document, - isPageLoaded = !isBrowser, - doc = isBrowser ? document : null, - readyCalls = []; - - function runCallbacks(callbacks) { - var i; - for (i = 0; i < callbacks.length; i += 1) { - callbacks[i](doc); - } - } - - function callReady() { - var callbacks = readyCalls; - - if (isPageLoaded) { - //Call the DOM ready callbacks - if (callbacks.length) { - readyCalls = []; - runCallbacks(callbacks); - } - } - } - - /** - * Sets the page as loaded. - */ - function pageLoaded() { - if (!isPageLoaded) { - isPageLoaded = true; - if (scrollIntervalId) { - clearInterval(scrollIntervalId); - } - - callReady(); - } - } - - if (isBrowser) { - if (document.addEventListener) { - //Standards. Hooray! Assumption here that if standards based, - //it knows about DOMContentLoaded. - document.addEventListener("DOMContentLoaded", pageLoaded, false); - window.addEventListener("load", pageLoaded, false); - } else if (window.attachEvent) { - window.attachEvent("onload", pageLoaded); - - testDiv = document.createElement('div'); - try { - isTop = window.frameElement === null; - } catch (e) {} - - //DOMContentLoaded approximation that uses a doScroll, as found by - //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/, - //but modified by other contributors, including jdalton - if (testDiv.doScroll && isTop && window.external) { - scrollIntervalId = setInterval(function () { - try { - testDiv.doScroll(); - pageLoaded(); - } catch (e) {} - }, 30); - } - } - - //Check if document already complete, and if so, just trigger page load - //listeners. Latest webkit browsers also use "interactive", and - //will fire the onDOMContentLoaded before "interactive" but not after - //entering "interactive" or "complete". More details: - //http://dev.w3.org/html5/spec/the-end.html#the-end - //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded - //Hmm, this is more complicated on further use, see "firing too early" - //bug: https://github.com/requirejs/domReady/issues/1 - //so removing the || document.readyState === "interactive" test. - //There is still a window.onload binding that should get fired if - //DOMContentLoaded is missed. - if (document.readyState === "complete") { - pageLoaded(); - } - } - - /** START OF PUBLIC API **/ - - /** - * Registers a callback for DOM ready. If DOM is already ready, the - * callback is called immediately. - * @param {Function} callback - */ - function domReady(callback) { - if (isPageLoaded) { - callback(doc); - } else { - readyCalls.push(callback); - } - return domReady; - } - - domReady.version = '2.0.1'; - - /** - * Loader Plugin API method - */ - domReady.load = function (name, req, onLoad, config) { - if (config.isBuild) { - onLoad(null); - } else { - domReady(onLoad); - } - }; - - /** END OF PUBLIC API **/ - - return domReady; -}); diff --git a/ThirdParty/requirejs-2.1.20/require.js b/ThirdParty/requirejs-2.1.20/require.js deleted file mode 100644 index 5237640495b..00000000000 --- a/ThirdParty/requirejs-2.1.20/require.js +++ /dev/null @@ -1,2103 +0,0 @@ -/** vim: et:ts=4:sw=4:sts=4 - * @license RequireJS 2.1.20 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/requirejs for details - */ -//Not using strict: uneven strict support in browsers, #392, and causes -//problems with requirejs.exec()/transpiler plugins that may not be strict. -/*jslint regexp: true, nomen: true, sloppy: true */ -/*global window, navigator, document, importScripts, setTimeout, opera */ - -var requirejs, require, define; -(function (global) { - var req, s, head, baseElement, dataMain, src, - interactiveScript, currentlyAddingScript, mainScript, subPath, - version = '2.1.20', - commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, - cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, - jsSuffixRegExp = /\.js$/, - currDirRegExp = /^\.\//, - op = Object.prototype, - ostring = op.toString, - hasOwn = op.hasOwnProperty, - ap = Array.prototype, - isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document), - isWebWorker = !isBrowser && typeof importScripts !== 'undefined', - //PS3 indicates loaded and complete, but need to wait for complete - //specifically. Sequence is 'loading', 'loaded', execution, - // then 'complete'. The UA check is unfortunate, but not sure how - //to feature test w/o causing perf issues. - readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? - /^complete$/ : /^(complete|loaded)$/, - defContextName = '_', - //Oh the tragedy, detecting opera. See the usage of isOpera for reason. - isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]', - contexts = {}, - cfg = {}, - globalDefQueue = [], - useInteractive = false; - - function isFunction(it) { - return ostring.call(it) === '[object Function]'; - } - - function isArray(it) { - return ostring.call(it) === '[object Array]'; - } - - /** - * Helper function for iterating over an array. If the func returns - * a true value, it will break out of the loop. - */ - function each(ary, func) { - if (ary) { - var i; - for (i = 0; i < ary.length; i += 1) { - if (ary[i] && func(ary[i], i, ary)) { - break; - } - } - } - } - - /** - * Helper function for iterating over an array backwards. If the func - * returns a true value, it will break out of the loop. - */ - function eachReverse(ary, func) { - if (ary) { - var i; - for (i = ary.length - 1; i > -1; i -= 1) { - if (ary[i] && func(ary[i], i, ary)) { - break; - } - } - } - } - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop); - } - - function getOwn(obj, prop) { - return hasProp(obj, prop) && obj[prop]; - } - - /** - * Cycles over properties in an object and calls a function for each - * property value. If the function returns a truthy value, then the - * iteration is stopped. - */ - function eachProp(obj, func) { - var prop; - for (prop in obj) { - if (hasProp(obj, prop)) { - if (func(obj[prop], prop)) { - break; - } - } - } - } - - /** - * Simple function to mix in properties from source into target, - * but only if target does not already have a property of the same name. - */ - function mixin(target, source, force, deepStringMixin) { - if (source) { - eachProp(source, function (value, prop) { - if (force || !hasProp(target, prop)) { - if (deepStringMixin && typeof value === 'object' && value && - !isArray(value) && !isFunction(value) && - !(value instanceof RegExp)) { - - if (!target[prop]) { - target[prop] = {}; - } - mixin(target[prop], value, force, deepStringMixin); - } else { - target[prop] = value; - } - } - }); - } - return target; - } - - //Similar to Function.prototype.bind, but the 'this' object is specified - //first, since it is easier to read/figure out what 'this' will be. - function bind(obj, fn) { - return function () { - return fn.apply(obj, arguments); - }; - } - - function scripts() { - return document.getElementsByTagName('script'); - } - - function defaultOnError(err) { - throw err; - } - - //Allow getting a global that is expressed in - //dot notation, like 'a.b.c'. - function getGlobal(value) { - if (!value) { - return value; - } - var g = global; - each(value.split('.'), function (part) { - g = g[part]; - }); - return g; - } - - /** - * Constructs an error with a pointer to an URL with more information. - * @param {String} id the error ID that maps to an ID on a web page. - * @param {String} message human readable error. - * @param {Error} [err] the original error, if there is one. - * - * @returns {Error} - */ - function makeError(id, msg, err, requireModules) { - var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); - e.requireType = id; - e.requireModules = requireModules; - if (err) { - e.originalError = err; - } - return e; - } - - if (typeof define !== 'undefined') { - //If a define is already in play via another AMD loader, - //do not overwrite. - return; - } - - if (typeof requirejs !== 'undefined') { - if (isFunction(requirejs)) { - //Do not overwrite an existing requirejs instance. - return; - } - cfg = requirejs; - requirejs = undefined; - } - - //Allow for a require config object - if (typeof require !== 'undefined' && !isFunction(require)) { - //assume it is a config object. - cfg = require; - require = undefined; - } - - function newContext(contextName) { - var inCheckLoaded, Module, context, handlers, - checkLoadedTimeoutId, - config = { - //Defaults. Do not set a default for map - //config to speed up normalize(), which - //will run faster if there is no default. - waitSeconds: 7, - baseUrl: './', - paths: {}, - bundles: {}, - pkgs: {}, - shim: {}, - config: {} - }, - registry = {}, - //registry of just enabled modules, to speed - //cycle breaking code when lots of modules - //are registered, but not activated. - enabledRegistry = {}, - undefEvents = {}, - defQueue = [], - defined = {}, - urlFetched = {}, - bundlesMap = {}, - requireCounter = 1, - unnormalizedCounter = 1; - - /** - * Trims the . and .. from an array of path segments. - * It will keep a leading path segment if a .. will become - * the first path segment, to help with module name lookups, - * which act like paths, but can be remapped. But the end result, - * all paths that use this function should look normalized. - * NOTE: this method MODIFIES the input array. - * @param {Array} ary the array of path segments. - */ - function trimDots(ary) { - var i, part; - for (i = 0; i < ary.length; i++) { - part = ary[i]; - if (part === '.') { - ary.splice(i, 1); - i -= 1; - } else if (part === '..') { - // If at the start, or previous value is still .., - // keep them so that when converted to a path it may - // still work when converted to a path, even though - // as an ID it is less than ideal. In larger point - // releases, may be better to just kick out an error. - if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') { - continue; - } else if (i > 0) { - ary.splice(i - 1, 2); - i -= 2; - } - } - } - } - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @param {Boolean} applyMap apply the map config to the value. Should - * only be done if this normalization is for a dependency ID. - * @returns {String} normalized name - */ - function normalize(name, baseName, applyMap) { - var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex, - foundMap, foundI, foundStarMap, starI, normalizedBaseParts, - baseParts = (baseName && baseName.split('/')), - map = config.map, - starMap = map && map['*']; - - //Adjust any relative paths. - if (name) { - name = name.split('/'); - lastIndex = name.length - 1; - - // If wanting node ID compatibility, strip .js from end - // of IDs. Have to do this here, and not in nameToUrl - // because node allows either .js or non .js to map - // to same file. - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - - // Starts with a '.' so need the baseName - if (name[0].charAt(0) === '.' && baseParts) { - //Convert baseName to array, and lop off the last part, - //so that . matches that 'directory' and not name of the baseName's - //module. For instance, baseName of 'one/two/three', maps to - //'one/two/three.js', but we want the directory, 'one/two' for - //this normalization. - normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); - name = normalizedBaseParts.concat(name); - } - - trimDots(name); - name = name.join('/'); - } - - //Apply map config if available. - if (applyMap && map && (baseParts || starMap)) { - nameParts = name.split('/'); - - outerLoop: for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join('/'); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = getOwn(map, baseParts.slice(0, j).join('/')); - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = getOwn(mapValue, nameSegment); - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break outerLoop; - } - } - } - } - - //Check for a star map match, but just hold on to it, - //if there is a shorter segment match later in a matching - //config, then favor over this star map. - if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) { - foundStarMap = getOwn(starMap, nameSegment); - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } - } - - // If the name points to a package's name, use - // the package main instead. - pkgMain = getOwn(config.pkgs, name); - - return pkgMain ? pkgMain : name; - } - - function removeScript(name) { - if (isBrowser) { - each(scripts(), function (scriptNode) { - if (scriptNode.getAttribute('data-requiremodule') === name && - scriptNode.getAttribute('data-requirecontext') === context.contextName) { - scriptNode.parentNode.removeChild(scriptNode); - return true; - } - }); - } - } - - function hasPathFallback(id) { - var pathConfig = getOwn(config.paths, id); - if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { - //Pop off the first array value, since it failed, and - //retry - pathConfig.shift(); - context.require.undef(id); - - //Custom require that does not do map translation, since - //ID is "absolute", already mapped/resolved. - context.makeRequire(null, { - skipMap: true - })([id]); - - return true; - } - } - - //Turns a plugin!resource to [plugin, resource] - //with the plugin being undefined if the name - //did not have a plugin prefix. - function splitPrefix(name) { - var prefix, - index = name ? name.indexOf('!') : -1; - if (index > -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); - } - return [prefix, name]; - } - - /** - * Creates a module mapping that includes plugin prefix, module - * name, and path. If parentModuleMap is provided it will - * also normalize the name via require.normalize() - * - * @param {String} name the module name - * @param {String} [parentModuleMap] parent module map - * for the module name, used to resolve relative names. - * @param {Boolean} isNormalized: is the ID already normalized. - * This is true if this call is done for a define() module ID. - * @param {Boolean} applyMap: apply the map config to the ID. - * Should only be true if this map is for a dependency. - * - * @returns {Object} - */ - function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) { - var url, pluginModule, suffix, nameParts, - prefix = null, - parentName = parentModuleMap ? parentModuleMap.name : null, - originalName = name, - isDefine = true, - normalizedName = ''; - - //If no name, then it means it is a require call, generate an - //internal name. - if (!name) { - isDefine = false; - name = '_@r' + (requireCounter += 1); - } - - nameParts = splitPrefix(name); - prefix = nameParts[0]; - name = nameParts[1]; - - if (prefix) { - prefix = normalize(prefix, parentName, applyMap); - pluginModule = getOwn(defined, prefix); - } - - //Account for relative paths if there is a base name. - if (name) { - if (prefix) { - if (pluginModule && pluginModule.normalize) { - //Plugin is loaded, use its normalize method. - normalizedName = pluginModule.normalize(name, function (name) { - return normalize(name, parentName, applyMap); - }); - } else { - // If nested plugin references, then do not try to - // normalize, as it will not normalize correctly. This - // places a restriction on resourceIds, and the longer - // term solution is not to normalize until plugins are - // loaded and all normalizations to allow for async - // loading of a loader plugin. But for now, fixes the - // common uses. Details in #1131 - normalizedName = name.indexOf('!') === -1 ? - normalize(name, parentName, applyMap) : - name; - } - } else { - //A regular module. - normalizedName = normalize(name, parentName, applyMap); - - //Normalized name may be a plugin ID due to map config - //application in normalize. The map config values must - //already be normalized, so do not need to redo that part. - nameParts = splitPrefix(normalizedName); - prefix = nameParts[0]; - normalizedName = nameParts[1]; - isNormalized = true; - - url = context.nameToUrl(normalizedName); - } - } - - //If the id is a plugin id that cannot be determined if it needs - //normalization, stamp it with a unique ID so two matching relative - //ids that may conflict can be separate. - suffix = prefix && !pluginModule && !isNormalized ? - '_unnormalized' + (unnormalizedCounter += 1) : - ''; - - return { - prefix: prefix, - name: normalizedName, - parentMap: parentModuleMap, - unnormalized: !!suffix, - url: url, - originalName: originalName, - isDefine: isDefine, - id: (prefix ? - prefix + '!' + normalizedName : - normalizedName) + suffix - }; - } - - function getModule(depMap) { - var id = depMap.id, - mod = getOwn(registry, id); - - if (!mod) { - mod = registry[id] = new context.Module(depMap); - } - - return mod; - } - - function on(depMap, name, fn) { - var id = depMap.id, - mod = getOwn(registry, id); - - if (hasProp(defined, id) && - (!mod || mod.defineEmitComplete)) { - if (name === 'defined') { - fn(defined[id]); - } - } else { - mod = getModule(depMap); - if (mod.error && name === 'error') { - fn(mod.error); - } else { - mod.on(name, fn); - } - } - } - - function onError(err, errback) { - var ids = err.requireModules, - notified = false; - - if (errback) { - errback(err); - } else { - each(ids, function (id) { - var mod = getOwn(registry, id); - if (mod) { - //Set error on module, so it skips timeout checks. - mod.error = err; - if (mod.events.error) { - notified = true; - mod.emit('error', err); - } - } - }); - - if (!notified) { - req.onError(err); - } - } - } - - /** - * Internal method to transfer globalQueue items to this context's - * defQueue. - */ - function takeGlobalQueue() { - //Push all the globalDefQueue items into the context's defQueue - if (globalDefQueue.length) { - each(globalDefQueue, function(queueItem) { - var id = queueItem[0]; - if (typeof id === 'string') { - context.defQueueMap[id] = true; - } - defQueue.push(queueItem); - }); - globalDefQueue = []; - } - } - - handlers = { - 'require': function (mod) { - if (mod.require) { - return mod.require; - } else { - return (mod.require = context.makeRequire(mod.map)); - } - }, - 'exports': function (mod) { - mod.usingExports = true; - if (mod.map.isDefine) { - if (mod.exports) { - return (defined[mod.map.id] = mod.exports); - } else { - return (mod.exports = defined[mod.map.id] = {}); - } - } - }, - 'module': function (mod) { - if (mod.module) { - return mod.module; - } else { - return (mod.module = { - id: mod.map.id, - uri: mod.map.url, - config: function () { - return getOwn(config.config, mod.map.id) || {}; - }, - exports: mod.exports || (mod.exports = {}) - }); - } - } - }; - - function cleanRegistry(id) { - //Clean up machinery used for waiting modules. - delete registry[id]; - delete enabledRegistry[id]; - } - - function breakCycle(mod, traced, processed) { - var id = mod.map.id; - - if (mod.error) { - mod.emit('error', mod.error); - } else { - traced[id] = true; - each(mod.depMaps, function (depMap, i) { - var depId = depMap.id, - dep = getOwn(registry, depId); - - //Only force things that have not completed - //being defined, so still in the registry, - //and only if it has not been matched up - //in the module already. - if (dep && !mod.depMatched[i] && !processed[depId]) { - if (getOwn(traced, depId)) { - mod.defineDep(i, defined[depId]); - mod.check(); //pass false? - } else { - breakCycle(dep, traced, processed); - } - } - }); - processed[id] = true; - } - } - - function checkLoaded() { - var err, usingPathFallback, - waitInterval = config.waitSeconds * 1000, - //It is possible to disable the wait interval by using waitSeconds of 0. - expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), - noLoads = [], - reqCalls = [], - stillLoading = false, - needCycleCheck = true; - - //Do not bother if this call was a result of a cycle break. - if (inCheckLoaded) { - return; - } - - inCheckLoaded = true; - - //Figure out the state of all the modules. - eachProp(enabledRegistry, function (mod) { - var map = mod.map, - modId = map.id; - - //Skip things that are not enabled or in error state. - if (!mod.enabled) { - return; - } - - if (!map.isDefine) { - reqCalls.push(mod); - } - - if (!mod.error) { - //If the module should be executed, and it has not - //been inited and time is up, remember it. - if (!mod.inited && expired) { - if (hasPathFallback(modId)) { - usingPathFallback = true; - stillLoading = true; - } else { - noLoads.push(modId); - removeScript(modId); - } - } else if (!mod.inited && mod.fetched && map.isDefine) { - stillLoading = true; - if (!map.prefix) { - //No reason to keep looking for unfinished - //loading. If the only stillLoading is a - //plugin resource though, keep going, - //because it may be that a plugin resource - //is waiting on a non-plugin cycle. - return (needCycleCheck = false); - } - } - } - }); - - if (expired && noLoads.length) { - //If wait time expired, throw error of unloaded modules. - err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads); - err.contextName = context.contextName; - return onError(err); - } - - //Not expired, check for a cycle. - if (needCycleCheck) { - each(reqCalls, function (mod) { - breakCycle(mod, {}, {}); - }); - } - - //If still waiting on loads, and the waiting load is something - //other than a plugin resource, or there are still outstanding - //scripts, then just try back later. - if ((!expired || usingPathFallback) && stillLoading) { - //Something is still waiting to load. Wait for it, but only - //if a timeout is not already in effect. - if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { - checkLoadedTimeoutId = setTimeout(function () { - checkLoadedTimeoutId = 0; - checkLoaded(); - }, 50); - } - } - - inCheckLoaded = false; - } - - Module = function (map) { - this.events = getOwn(undefEvents, map.id) || {}; - this.map = map; - this.shim = getOwn(config.shim, map.id); - this.depExports = []; - this.depMaps = []; - this.depMatched = []; - this.pluginMaps = {}; - this.depCount = 0; - - /* this.exports this.factory - this.depMaps = [], - this.enabled, this.fetched - */ - }; - - Module.prototype = { - init: function (depMaps, factory, errback, options) { - options = options || {}; - - //Do not do more inits if already done. Can happen if there - //are multiple define calls for the same module. That is not - //a normal, common case, but it is also not unexpected. - if (this.inited) { - return; - } - - this.factory = factory; - - if (errback) { - //Register for errors on this module. - this.on('error', errback); - } else if (this.events.error) { - //If no errback already, but there are error listeners - //on this module, set up an errback to pass to the deps. - errback = bind(this, function (err) { - this.emit('error', err); - }); - } - - //Do a copy of the dependency array, so that - //source inputs are not modified. For example - //"shim" deps are passed in here directly, and - //doing a direct modification of the depMaps array - //would affect that config. - this.depMaps = depMaps && depMaps.slice(0); - - this.errback = errback; - - //Indicate this module has be initialized - this.inited = true; - - this.ignore = options.ignore; - - //Could have option to init this module in enabled mode, - //or could have been previously marked as enabled. However, - //the dependencies are not known until init is called. So - //if enabled previously, now trigger dependencies as enabled. - if (options.enabled || this.enabled) { - //Enable this module and dependencies. - //Will call this.check() - this.enable(); - } else { - this.check(); - } - }, - - defineDep: function (i, depExports) { - //Because of cycles, defined callback for a given - //export can be called more than once. - if (!this.depMatched[i]) { - this.depMatched[i] = true; - this.depCount -= 1; - this.depExports[i] = depExports; - } - }, - - fetch: function () { - if (this.fetched) { - return; - } - this.fetched = true; - - context.startTime = (new Date()).getTime(); - - var map = this.map; - - //If the manager is for a plugin managed resource, - //ask the plugin to load it now. - if (this.shim) { - context.makeRequire(this.map, { - enableBuildCallback: true - })(this.shim.deps || [], bind(this, function () { - return map.prefix ? this.callPlugin() : this.load(); - })); - } else { - //Regular dependency. - return map.prefix ? this.callPlugin() : this.load(); - } - }, - - load: function () { - var url = this.map.url; - - //Regular dependency. - if (!urlFetched[url]) { - urlFetched[url] = true; - context.load(this.map.id, url); - } - }, - - /** - * Checks if the module is ready to define itself, and if so, - * define it. - */ - check: function () { - if (!this.enabled || this.enabling) { - return; - } - - var err, cjsModule, - id = this.map.id, - depExports = this.depExports, - exports = this.exports, - factory = this.factory; - - if (!this.inited) { - // Only fetch if not already in the defQueue. - if (!hasProp(context.defQueueMap, id)) { - this.fetch(); - } - } else if (this.error) { - this.emit('error', this.error); - } else if (!this.defining) { - //The factory could trigger another require call - //that would result in checking this module to - //define itself again. If already in the process - //of doing that, skip this work. - this.defining = true; - - if (this.depCount < 1 && !this.defined) { - if (isFunction(factory)) { - //If there is an error listener, favor passing - //to that instead of throwing an error. However, - //only do it for define()'d modules. require - //errbacks should not be called for failures in - //their callbacks (#699). However if a global - //onError is set, use that. - if ((this.events.error && this.map.isDefine) || - req.onError !== defaultOnError) { - try { - exports = context.execCb(id, factory, depExports, exports); - } catch (e) { - err = e; - } - } else { - exports = context.execCb(id, factory, depExports, exports); - } - - // Favor return value over exports. If node/cjs in play, - // then will not have a return value anyway. Favor - // module.exports assignment over exports object. - if (this.map.isDefine && exports === undefined) { - cjsModule = this.module; - if (cjsModule) { - exports = cjsModule.exports; - } else if (this.usingExports) { - //exports already set the defined value. - exports = this.exports; - } - } - - if (err) { - err.requireMap = this.map; - err.requireModules = this.map.isDefine ? [this.map.id] : null; - err.requireType = this.map.isDefine ? 'define' : 'require'; - return onError((this.error = err)); - } - - } else { - //Just a literal value - exports = factory; - } - - this.exports = exports; - - if (this.map.isDefine && !this.ignore) { - defined[id] = exports; - - if (req.onResourceLoad) { - req.onResourceLoad(context, this.map, this.depMaps); - } - } - - //Clean up - cleanRegistry(id); - - this.defined = true; - } - - //Finished the define stage. Allow calling check again - //to allow define notifications below in the case of a - //cycle. - this.defining = false; - - if (this.defined && !this.defineEmitted) { - this.defineEmitted = true; - this.emit('defined', this.exports); - this.defineEmitComplete = true; - } - - } - }, - - callPlugin: function () { - var map = this.map, - id = map.id, - //Map already normalized the prefix. - pluginMap = makeModuleMap(map.prefix); - - //Mark this as a dependency for this plugin, so it - //can be traced for cycles. - this.depMaps.push(pluginMap); - - on(pluginMap, 'defined', bind(this, function (plugin) { - var load, normalizedMap, normalizedMod, - bundleId = getOwn(bundlesMap, this.map.id), - name = this.map.name, - parentName = this.map.parentMap ? this.map.parentMap.name : null, - localRequire = context.makeRequire(map.parentMap, { - enableBuildCallback: true - }); - - //If current map is not normalized, wait for that - //normalized name to load instead of continuing. - if (this.map.unnormalized) { - //Normalize the ID if the plugin allows it. - if (plugin.normalize) { - name = plugin.normalize(name, function (name) { - return normalize(name, parentName, true); - }) || ''; - } - - //prefix and name should already be normalized, no need - //for applying map config again either. - normalizedMap = makeModuleMap(map.prefix + '!' + name, - this.map.parentMap); - on(normalizedMap, - 'defined', bind(this, function (value) { - this.init([], function () { return value; }, null, { - enabled: true, - ignore: true - }); - })); - - normalizedMod = getOwn(registry, normalizedMap.id); - if (normalizedMod) { - //Mark this as a dependency for this plugin, so it - //can be traced for cycles. - this.depMaps.push(normalizedMap); - - if (this.events.error) { - normalizedMod.on('error', bind(this, function (err) { - this.emit('error', err); - })); - } - normalizedMod.enable(); - } - - return; - } - - //If a paths config, then just load that file instead to - //resolve the plugin, as it is built into that paths layer. - if (bundleId) { - this.map.url = context.nameToUrl(bundleId); - this.load(); - return; - } - - load = bind(this, function (value) { - this.init([], function () { return value; }, null, { - enabled: true - }); - }); - - load.error = bind(this, function (err) { - this.inited = true; - this.error = err; - err.requireModules = [id]; - - //Remove temp unnormalized modules for this module, - //since they will never be resolved otherwise now. - eachProp(registry, function (mod) { - if (mod.map.id.indexOf(id + '_unnormalized') === 0) { - cleanRegistry(mod.map.id); - } - }); - - onError(err); - }); - - //Allow plugins to load other code without having to know the - //context or how to 'complete' the load. - load.fromText = bind(this, function (text, textAlt) { - /*jslint evil: true */ - var moduleName = map.name, - moduleMap = makeModuleMap(moduleName), - hasInteractive = useInteractive; - - //As of 2.1.0, support just passing the text, to reinforce - //fromText only being called once per resource. Still - //support old style of passing moduleName but discard - //that moduleName in favor of the internal ref. - if (textAlt) { - text = textAlt; - } - - //Turn off interactive script matching for IE for any define - //calls in the text, then turn it back on at the end. - if (hasInteractive) { - useInteractive = false; - } - - //Prime the system by creating a module instance for - //it. - getModule(moduleMap); - - //Transfer any config to this other module. - if (hasProp(config.config, id)) { - config.config[moduleName] = config.config[id]; - } - - try { - req.exec(text); - } catch (e) { - return onError(makeError('fromtexteval', - 'fromText eval for ' + id + - ' failed: ' + e, - e, - [id])); - } - - if (hasInteractive) { - useInteractive = true; - } - - //Mark this as a dependency for the plugin - //resource - this.depMaps.push(moduleMap); - - //Support anonymous modules. - context.completeLoad(moduleName); - - //Bind the value of that module to the value for this - //resource ID. - localRequire([moduleName], load); - }); - - //Use parentName here since the plugin's name is not reliable, - //could be some weird string with no path that actually wants to - //reference the parentName's path. - plugin.load(map.name, localRequire, load, config); - })); - - context.enable(pluginMap, this); - this.pluginMaps[pluginMap.id] = pluginMap; - }, - - enable: function () { - enabledRegistry[this.map.id] = this; - this.enabled = true; - - //Set flag mentioning that the module is enabling, - //so that immediate calls to the defined callbacks - //for dependencies do not trigger inadvertent load - //with the depCount still being zero. - this.enabling = true; - - //Enable each dependency - each(this.depMaps, bind(this, function (depMap, i) { - var id, mod, handler; - - if (typeof depMap === 'string') { - //Dependency needs to be converted to a depMap - //and wired up to this module. - depMap = makeModuleMap(depMap, - (this.map.isDefine ? this.map : this.map.parentMap), - false, - !this.skipMap); - this.depMaps[i] = depMap; - - handler = getOwn(handlers, depMap.id); - - if (handler) { - this.depExports[i] = handler(this); - return; - } - - this.depCount += 1; - - on(depMap, 'defined', bind(this, function (depExports) { - if (this.undefed) { - return; - } - this.defineDep(i, depExports); - this.check(); - })); - - if (this.errback) { - on(depMap, 'error', bind(this, this.errback)); - } else if (this.events.error) { - // No direct errback on this module, but something - // else is listening for errors, so be sure to - // propagate the error correctly. - on(depMap, 'error', bind(this, function(err) { - this.emit('error', err); - })); - } - } - - id = depMap.id; - mod = registry[id]; - - //Skip special modules like 'require', 'exports', 'module' - //Also, don't call enable if it is already enabled, - //important in circular dependency cases. - if (!hasProp(handlers, id) && mod && !mod.enabled) { - context.enable(depMap, this); - } - })); - - //Enable each plugin that is used in - //a dependency - eachProp(this.pluginMaps, bind(this, function (pluginMap) { - var mod = getOwn(registry, pluginMap.id); - if (mod && !mod.enabled) { - context.enable(pluginMap, this); - } - })); - - this.enabling = false; - - this.check(); - }, - - on: function (name, cb) { - var cbs = this.events[name]; - if (!cbs) { - cbs = this.events[name] = []; - } - cbs.push(cb); - }, - - emit: function (name, evt) { - each(this.events[name], function (cb) { - cb(evt); - }); - if (name === 'error') { - //Now that the error handler was triggered, remove - //the listeners, since this broken Module instance - //can stay around for a while in the registry. - delete this.events[name]; - } - } - }; - - function callGetModule(args) { - //Skip modules already defined. - if (!hasProp(defined, args[0])) { - getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); - } - } - - function removeListener(node, func, name, ieName) { - //Favor detachEvent because of IE9 - //issue, see attachEvent/addEventListener comment elsewhere - //in this file. - if (node.detachEvent && !isOpera) { - //Probably IE. If not it will throw an error, which will be - //useful to know. - if (ieName) { - node.detachEvent(ieName, func); - } - } else { - node.removeEventListener(name, func, false); - } - } - - /** - * Given an event from a script node, get the requirejs info from it, - * and then removes the event listeners on the node. - * @param {Event} evt - * @returns {Object} - */ - function getScriptData(evt) { - //Using currentTarget instead of target for Firefox 2.0's sake. Not - //all old browsers will be supported, but this one was easy enough - //to support and still makes sense. - var node = evt.currentTarget || evt.srcElement; - - //Remove the listeners once here. - removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange'); - removeListener(node, context.onScriptError, 'error'); - - return { - node: node, - id: node && node.getAttribute('data-requiremodule') - }; - } - - function intakeDefines() { - var args; - - //Any defined modules in the global queue, intake them now. - takeGlobalQueue(); - - //Make sure any remaining defQueue items get properly processed. - while (defQueue.length) { - args = defQueue.shift(); - if (args[0] === null) { - return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + - args[args.length - 1])); - } else { - //args are id, deps, factory. Should be normalized by the - //define() function. - callGetModule(args); - } - } - context.defQueueMap = {}; - } - - context = { - config: config, - contextName: contextName, - registry: registry, - defined: defined, - urlFetched: urlFetched, - defQueue: defQueue, - defQueueMap: {}, - Module: Module, - makeModuleMap: makeModuleMap, - nextTick: req.nextTick, - onError: onError, - - /** - * Set a configuration for the context. - * @param {Object} cfg config object to integrate. - */ - configure: function (cfg) { - //Make sure the baseUrl ends in a slash. - if (cfg.baseUrl) { - if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') { - cfg.baseUrl += '/'; - } - } - - //Save off the paths since they require special processing, - //they are additive. - var shim = config.shim, - objs = { - paths: true, - bundles: true, - config: true, - map: true - }; - - eachProp(cfg, function (value, prop) { - if (objs[prop]) { - if (!config[prop]) { - config[prop] = {}; - } - mixin(config[prop], value, true, true); - } else { - config[prop] = value; - } - }); - - //Reverse map the bundles - if (cfg.bundles) { - eachProp(cfg.bundles, function (value, prop) { - each(value, function (v) { - if (v !== prop) { - bundlesMap[v] = prop; - } - }); - }); - } - - //Merge shim - if (cfg.shim) { - eachProp(cfg.shim, function (value, id) { - //Normalize the structure - if (isArray(value)) { - value = { - deps: value - }; - } - if ((value.exports || value.init) && !value.exportsFn) { - value.exportsFn = context.makeShimExports(value); - } - shim[id] = value; - }); - config.shim = shim; - } - - //Adjust packages if necessary. - if (cfg.packages) { - each(cfg.packages, function (pkgObj) { - var location, name; - - pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj; - - name = pkgObj.name; - location = pkgObj.location; - if (location) { - config.paths[name] = pkgObj.location; - } - - //Save pointer to main module ID for pkg name. - //Remove leading dot in main, so main paths are normalized, - //and remove any trailing .js, since different package - //envs have different conventions: some use a module name, - //some use a file name. - config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main') - .replace(currDirRegExp, '') - .replace(jsSuffixRegExp, ''); - }); - } - - //If there are any "waiting to execute" modules in the registry, - //update the maps for them, since their info, like URLs to load, - //may have changed. - eachProp(registry, function (mod, id) { - //If module already has init called, since it is too - //late to modify them, and ignore unnormalized ones - //since they are transient. - if (!mod.inited && !mod.map.unnormalized) { - mod.map = makeModuleMap(id, null, true); - } - }); - - //If a deps array or a config callback is specified, then call - //require with those args. This is useful when require is defined as a - //config object before require.js is loaded. - if (cfg.deps || cfg.callback) { - context.require(cfg.deps || [], cfg.callback); - } - }, - - makeShimExports: function (value) { - function fn() { - var ret; - if (value.init) { - ret = value.init.apply(global, arguments); - } - return ret || (value.exports && getGlobal(value.exports)); - } - return fn; - }, - - makeRequire: function (relMap, options) { - options = options || {}; - - function localRequire(deps, callback, errback) { - var id, map, requireMod; - - if (options.enableBuildCallback && callback && isFunction(callback)) { - callback.__requireJsBuild = true; - } - - if (typeof deps === 'string') { - if (isFunction(callback)) { - //Invalid call - return onError(makeError('requireargs', 'Invalid require call'), errback); - } - - //If require|exports|module are requested, get the - //value for them from the special handlers. Caveat: - //this only works while module is being defined. - if (relMap && hasProp(handlers, deps)) { - return handlers[deps](registry[relMap.id]); - } - - //Synchronous access to one module. If require.get is - //available (as in the Node adapter), prefer that. - if (req.get) { - return req.get(context, deps, relMap, localRequire); - } - - //Normalize module name, if it contains . or .. - map = makeModuleMap(deps, relMap, false, true); - id = map.id; - - if (!hasProp(defined, id)) { - return onError(makeError('notloaded', 'Module name "' + - id + - '" has not been loaded yet for context: ' + - contextName + - (relMap ? '' : '. Use require([])'))); - } - return defined[id]; - } - - //Grab defines waiting in the global queue. - intakeDefines(); - - //Mark all the dependencies as needing to be loaded. - context.nextTick(function () { - //Some defines could have been added since the - //require call, collect them. - intakeDefines(); - - requireMod = getModule(makeModuleMap(null, relMap)); - - //Store if map config should be applied to this require - //call for dependencies. - requireMod.skipMap = options.skipMap; - - requireMod.init(deps, callback, errback, { - enabled: true - }); - - checkLoaded(); - }); - - return localRequire; - } - - mixin(localRequire, { - isBrowser: isBrowser, - - /** - * Converts a module name + .extension into an URL path. - * *Requires* the use of a module name. It does not support using - * plain URLs like nameToUrl. - */ - toUrl: function (moduleNamePlusExt) { - var ext, - index = moduleNamePlusExt.lastIndexOf('.'), - segment = moduleNamePlusExt.split('/')[0], - isRelative = segment === '.' || segment === '..'; - - //Have a file extension alias, and it is not the - //dots from a relative path. - if (index !== -1 && (!isRelative || index > 1)) { - ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); - moduleNamePlusExt = moduleNamePlusExt.substring(0, index); - } - - return context.nameToUrl(normalize(moduleNamePlusExt, - relMap && relMap.id, true), ext, true); - }, - - defined: function (id) { - return hasProp(defined, makeModuleMap(id, relMap, false, true).id); - }, - - specified: function (id) { - id = makeModuleMap(id, relMap, false, true).id; - return hasProp(defined, id) || hasProp(registry, id); - } - }); - - //Only allow undef on top level require calls - if (!relMap) { - localRequire.undef = function (id) { - //Bind any waiting define() calls to this context, - //fix for #408 - takeGlobalQueue(); - - var map = makeModuleMap(id, relMap, true), - mod = getOwn(registry, id); - - mod.undefed = true; - removeScript(id); - - delete defined[id]; - delete urlFetched[map.url]; - delete undefEvents[id]; - - //Clean queued defines too. Go backwards - //in array so that the splices do not - //mess up the iteration. - eachReverse(defQueue, function(args, i) { - if (args[0] === id) { - defQueue.splice(i, 1); - } - }); - delete context.defQueueMap[id]; - - if (mod) { - //Hold on to listeners in case the - //module will be attempted to be reloaded - //using a different config. - if (mod.events.defined) { - undefEvents[id] = mod.events; - } - - cleanRegistry(id); - } - }; - } - - return localRequire; - }, - - /** - * Called to enable a module if it is still in the registry - * awaiting enablement. A second arg, parent, the parent module, - * is passed in for context, when this method is overridden by - * the optimizer. Not shown here to keep code compact. - */ - enable: function (depMap) { - var mod = getOwn(registry, depMap.id); - if (mod) { - getModule(depMap).enable(); - } - }, - - /** - * Internal method used by environment adapters to complete a load event. - * A load event could be a script load or just a load pass from a synchronous - * load call. - * @param {String} moduleName the name of the module to potentially complete. - */ - completeLoad: function (moduleName) { - var found, args, mod, - shim = getOwn(config.shim, moduleName) || {}, - shExports = shim.exports; - - takeGlobalQueue(); - - while (defQueue.length) { - args = defQueue.shift(); - if (args[0] === null) { - args[0] = moduleName; - //If already found an anonymous module and bound it - //to this name, then this is some other anon module - //waiting for its completeLoad to fire. - if (found) { - break; - } - found = true; - } else if (args[0] === moduleName) { - //Found matching define call for this script! - found = true; - } - - callGetModule(args); - } - context.defQueueMap = {}; - - //Do this after the cycle of callGetModule in case the result - //of those calls/init calls changes the registry. - mod = getOwn(registry, moduleName); - - if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) { - if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { - if (hasPathFallback(moduleName)) { - return; - } else { - return onError(makeError('nodefine', - 'No define call for ' + moduleName, - null, - [moduleName])); - } - } else { - //A script that does not call define(), so just simulate - //the call for it. - callGetModule([moduleName, (shim.deps || []), shim.exportsFn]); - } - } - - checkLoaded(); - }, - - /** - * Converts a module name to a file path. Supports cases where - * moduleName may actually be just an URL. - * Note that it **does not** call normalize on the moduleName, - * it is assumed to have already been normalized. This is an - * internal API, not a public one. Use toUrl for the public API. - */ - nameToUrl: function (moduleName, ext, skipExt) { - var paths, syms, i, parentModule, url, - parentPath, bundleId, - pkgMain = getOwn(config.pkgs, moduleName); - - if (pkgMain) { - moduleName = pkgMain; - } - - bundleId = getOwn(bundlesMap, moduleName); - - if (bundleId) { - return context.nameToUrl(bundleId, ext, skipExt); - } - - //If a colon is in the URL, it indicates a protocol is used and it is just - //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?) - //or ends with .js, then assume the user meant to use an url and not a module id. - //The slash is important for protocol-less URLs as well as full paths. - if (req.jsExtRegExp.test(moduleName)) { - //Just a plain path, not module name lookup, so just return it. - //Add extension if it is included. This is a bit wonky, only non-.js things pass - //an extension, this method probably needs to be reworked. - url = moduleName + (ext || ''); - } else { - //A module that needs to be converted to a path. - paths = config.paths; - - syms = moduleName.split('/'); - //For each module name segment, see if there is a path - //registered for it. Start with most specific name - //and work up from it. - for (i = syms.length; i > 0; i -= 1) { - parentModule = syms.slice(0, i).join('/'); - - parentPath = getOwn(paths, parentModule); - if (parentPath) { - //If an array, it means there are a few choices, - //Choose the one that is desired - if (isArray(parentPath)) { - parentPath = parentPath[0]; - } - syms.splice(0, i, parentPath); - break; - } - } - - //Join the path parts together, then figure out if baseUrl is needed. - url = syms.join('/'); - url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js')); - url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; - } - - return config.urlArgs ? url + - ((url.indexOf('?') === -1 ? '?' : '&') + - config.urlArgs) : url; - }, - - //Delegates to req.load. Broken out as a separate function to - //allow overriding in the optimizer. - load: function (id, url) { - req.load(context, id, url); - }, - - /** - * Executes a module callback function. Broken out as a separate function - * solely to allow the build system to sequence the files in the built - * layer in the right sequence. - * - * @private - */ - execCb: function (name, callback, args, exports) { - return callback.apply(exports, args); - }, - - /** - * callback for script loads, used to check status of loading. - * - * @param {Event} evt the event from the browser for the script - * that was loaded. - */ - onScriptLoad: function (evt) { - //Using currentTarget instead of target for Firefox 2.0's sake. Not - //all old browsers will be supported, but this one was easy enough - //to support and still makes sense. - if (evt.type === 'load' || - (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) { - //Reset interactive script so a script node is not held onto for - //to long. - interactiveScript = null; - - //Pull out the name of the module and the context. - var data = getScriptData(evt); - context.completeLoad(data.id); - } - }, - - /** - * Callback for script errors. - */ - onScriptError: function (evt) { - var data = getScriptData(evt); - if (!hasPathFallback(data.id)) { - return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id])); - } - } - }; - - context.require = context.makeRequire(); - return context; - } - - /** - * Main entry point. - * - * If the only argument to require is a string, then the module that - * is represented by that string is fetched for the appropriate context. - * - * If the first argument is an array, then it will be treated as an array - * of dependency string names to fetch. An optional function callback can - * be specified to execute when all of those dependencies are available. - * - * Make a local req variable to help Caja compliance (it assumes things - * on a require that are not standardized), and to give a short - * name for minification/local scope use. - */ - req = requirejs = function (deps, callback, errback, optional) { - - //Find the right context, use default - var context, config, - contextName = defContextName; - - // Determine if have config object in the call. - if (!isArray(deps) && typeof deps !== 'string') { - // deps is a config object - config = deps; - if (isArray(callback)) { - // Adjust args if there are dependencies - deps = callback; - callback = errback; - errback = optional; - } else { - deps = []; - } - } - - if (config && config.context) { - contextName = config.context; - } - - context = getOwn(contexts, contextName); - if (!context) { - context = contexts[contextName] = req.s.newContext(contextName); - } - - if (config) { - context.configure(config); - } - - return context.require(deps, callback, errback); - }; - - /** - * Support require.config() to make it easier to cooperate with other - * AMD loaders on globally agreed names. - */ - req.config = function (config) { - return req(config); - }; - - /** - * Execute something after the current tick - * of the event loop. Override for other envs - * that have a better solution than setTimeout. - * @param {Function} fn function to execute later. - */ - req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) { - setTimeout(fn, 4); - } : function (fn) { fn(); }; - - /** - * Export require as a global, but only if it does not already exist. - */ - if (!require) { - require = req; - } - - req.version = version; - - //Used to filter out dependencies that are already paths. - req.jsExtRegExp = /^\/|:|\?|\.js$/; - req.isBrowser = isBrowser; - s = req.s = { - contexts: contexts, - newContext: newContext - }; - - //Create default context. - req({}); - - //Exports some context-sensitive methods on global require. - each([ - 'toUrl', - 'undef', - 'defined', - 'specified' - ], function (prop) { - //Reference from contexts instead of early binding to default context, - //so that during builds, the latest instance of the default context - //with its config gets used. - req[prop] = function () { - var ctx = contexts[defContextName]; - return ctx.require[prop].apply(ctx, arguments); - }; - }); - - if (isBrowser) { - head = s.head = document.getElementsByTagName('head')[0]; - //If BASE tag is in play, using appendChild is a problem for IE6. - //When that browser dies, this can be removed. Details in this jQuery bug: - //http://dev.jquery.com/ticket/2709 - baseElement = document.getElementsByTagName('base')[0]; - if (baseElement) { - head = s.head = baseElement.parentNode; - } - } - - /** - * Any errors that require explicitly generates will be passed to this - * function. Intercept/override it if you want custom error handling. - * @param {Error} err the error object. - */ - req.onError = defaultOnError; - - /** - * Creates the node for the load command. Only used in browser envs. - */ - req.createNode = function (config, moduleName, url) { - var node = config.xhtml ? - document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') : - document.createElement('script'); - node.type = config.scriptType || 'text/javascript'; - node.charset = 'utf-8'; - node.async = true; - return node; - }; - - /** - * Does the request to load a module for the browser case. - * Make this a separate function to allow other environments - * to override it. - * - * @param {Object} context the require context to find state. - * @param {String} moduleName the name of the module. - * @param {Object} url the URL to the module. - */ - req.load = function (context, moduleName, url) { - var config = (context && context.config) || {}, - node; - if (isBrowser) { - //In the browser so use a script tag - node = req.createNode(config, moduleName, url); - if (config.onNodeCreated) { - config.onNodeCreated(node, config, moduleName, url); - } - - node.setAttribute('data-requirecontext', context.contextName); - node.setAttribute('data-requiremodule', moduleName); - - //Set up load listener. Test attachEvent first because IE9 has - //a subtle issue in its addEventListener and script onload firings - //that do not match the behavior of all other browsers with - //addEventListener support, which fire the onload event for a - //script right after the script execution. See: - //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution - //UNFORTUNATELY Opera implements attachEvent but does not follow the script - //script execution mode. - if (node.attachEvent && - //Check if node.attachEvent is artificially added by custom script or - //natively supported by browser - //read https://github.com/jrburke/requirejs/issues/187 - //if we can NOT find [native code] then it must NOT natively supported. - //in IE8, node.attachEvent does not have toString() - //Note the test for "[native code" with no closing brace, see: - //https://github.com/jrburke/requirejs/issues/273 - !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) && - !isOpera) { - //Probably IE. IE (at least 6-8) do not fire - //script onload right after executing the script, so - //we cannot tie the anonymous define call to a name. - //However, IE reports the script as being in 'interactive' - //readyState at the time of the define call. - useInteractive = true; - - node.attachEvent('onreadystatechange', context.onScriptLoad); - //It would be great to add an error handler here to catch - //404s in IE9+. However, onreadystatechange will fire before - //the error handler, so that does not help. If addEventListener - //is used, then IE will fire error before load, but we cannot - //use that pathway given the connect.microsoft.com issue - //mentioned above about not doing the 'script execute, - //then fire the script load event listener before execute - //next script' that other browsers do. - //Best hope: IE10 fixes the issues, - //and then destroys all installs of IE 6-9. - //node.attachEvent('onerror', context.onScriptError); - } else { - node.addEventListener('load', context.onScriptLoad, false); - node.addEventListener('error', context.onScriptError, false); - } - node.src = url; - - //For some cache cases in IE 6-8, the script executes before the end - //of the appendChild execution, so to tie an anonymous define - //call to the module name (which is stored on the node), hold on - //to a reference to this node, but clear after the DOM insertion. - currentlyAddingScript = node; - if (baseElement) { - head.insertBefore(node, baseElement); - } else { - head.appendChild(node); - } - currentlyAddingScript = null; - - return node; - } else if (isWebWorker) { - try { - //In a web worker, use importScripts. This is not a very - //efficient use of importScripts, importScripts will block until - //its script is downloaded and evaluated. However, if web workers - //are in play, the expectation that a build has been done so that - //only one script needs to be loaded anyway. This may need to be - //reevaluated if other use cases become common. - importScripts(url); - - //Account for anonymous modules - context.completeLoad(moduleName); - } catch (e) { - context.onError(makeError('importscripts', - 'importScripts failed for ' + - moduleName + ' at ' + url, - e, - [moduleName])); - } - } - }; - - function getInteractiveScript() { - if (interactiveScript && interactiveScript.readyState === 'interactive') { - return interactiveScript; - } - - eachReverse(scripts(), function (script) { - if (script.readyState === 'interactive') { - return (interactiveScript = script); - } - }); - return interactiveScript; - } - - //Look for a data-main script attribute, which could also adjust the baseUrl. - if (isBrowser && !cfg.skipDataMain) { - //Figure out baseUrl. Get it from the script tag with require.js in it. - eachReverse(scripts(), function (script) { - //Set the 'head' where we can append children by - //using the script's parent. - if (!head) { - head = script.parentNode; - } - - //Look for a data-main attribute to set main script for the page - //to load. If it is there, the path to data main becomes the - //baseUrl, if it is not already set. - dataMain = script.getAttribute('data-main'); - if (dataMain) { - //Preserve dataMain in case it is a path (i.e. contains '?') - mainScript = dataMain; - - //Set final baseUrl if there is not already an explicit one. - if (!cfg.baseUrl) { - //Pull off the directory of data-main for use as the - //baseUrl. - src = mainScript.split('/'); - mainScript = src.pop(); - subPath = src.length ? src.join('/') + '/' : './'; - - cfg.baseUrl = subPath; - } - - //Strip off any trailing .js since mainScript is now - //like a module name. - mainScript = mainScript.replace(jsSuffixRegExp, ''); - - //If mainScript is still a path, fall back to dataMain - if (req.jsExtRegExp.test(mainScript)) { - mainScript = dataMain; - } - - //Put the data-main script in the files to load. - cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; - - return true; - } - }); - } - - /** - * The function that handles definitions of modules. Differs from - * require() in that a string for the module should be the first argument, - * and the function to execute after dependencies are loaded should - * return a value to define the module corresponding to the first argument's - * name. - */ - define = function (name, deps, callback) { - var node, context; - - //Allow for anonymous modules - if (typeof name !== 'string') { - //Adjust args appropriately - callback = deps; - deps = name; - name = null; - } - - //This module may not have dependencies - if (!isArray(deps)) { - callback = deps; - deps = null; - } - - //If no name, and callback is a function, then figure out if it a - //CommonJS thing with dependencies. - if (!deps && isFunction(callback)) { - deps = []; - //Remove comments from the callback string, - //look for require calls, and pull them into the dependencies, - //but only if there are function args. - if (callback.length) { - callback - .toString() - .replace(commentRegExp, '') - .replace(cjsRequireRegExp, function (match, dep) { - deps.push(dep); - }); - - //May be a CommonJS thing even without require calls, but still - //could use exports, and module. Avoid doing exports and module - //work though if it just needs require. - //REQUIRES the function to expect the CommonJS variables in the - //order listed below. - deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps); - } - } - - //If in IE 6-8 and hit an anonymous define() call, do the interactive - //work. - if (useInteractive) { - node = currentlyAddingScript || getInteractiveScript(); - if (node) { - if (!name) { - name = node.getAttribute('data-requiremodule'); - } - context = contexts[node.getAttribute('data-requirecontext')]; - } - } - - //Always save off evaluating the def call until the script onload handler. - //This allows multiple modules to be in a file without prematurely - //tracing dependencies, and allows for anonymous module support, - //where the module name is not known until the script onload event - //occurs. If no context, use the global queue, and get it processed - //in the onscript load callback. - if (context) { - context.defQueue.push([name, deps, callback]); - context.defQueueMap[name] = true; - } else { - globalDefQueue.push([name, deps, callback]); - } - }; - - define.amd = { - jQuery: true - }; - - /** - * Executes the text. Normally just uses eval, but can be modified - * to use a better, environment-specific call. Only used for transpiling - * loader plugins, not for plain JS modules. - * @param {String} text the text to execute/evaluate. - */ - req.exec = function (text) { - /*jslint evil: true */ - return eval(text); - }; - - //Set up with config info. - req(cfg); -}(this)); diff --git a/ThirdParty/requirejs-2.1.20/require.min.js b/ThirdParty/requirejs-2.1.20/require.min.js deleted file mode 100644 index 693164afc8d..00000000000 --- a/ThirdParty/requirejs-2.1.20/require.min.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - RequireJS 2.1.20 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved. - Available via the MIT or new BSD license. - see: http://github.com/jrburke/requirejs for details -*/ -var requirejs,require,define; -(function(ba){function G(b){return"[object Function]"===K.call(b)}function H(b){return"[object Array]"===K.call(b)}function v(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(G(l)){if(this.events.error&&this.map.isDefine||e.onError!==ca)try{f=h.execCb(c,l,b,f)}catch(d){a=d}else f=h.execCb(c,l,b,f);this.map.isDefine&& -void 0===f&&((b=this.module)?f=b.exports:this.usingExports&&(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=l;this.exports=f;if(this.map.isDefine&&!this.ignore&&(q[c]=f,e.onResourceLoad))e.onResourceLoad(h,this.map,this.depMaps);y(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete= -!0)}}else t(h.defQueueMap,c)||this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=i(a.prefix);this.depMaps.push(d);s(d,"defined",u(this,function(f){var l,d;d=n(aa,this.map.id);var g=this.map.name,P=this.map.parentMap?this.map.parentMap.name:null,p=h.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(g=f.normalize(g,function(a){return c(a,P,!0)})||""),f=i(a.prefix+"!"+g,this.map.parentMap),s(f,"defined",u(this,function(a){this.init([],function(){return a}, -null,{enabled:!0,ignore:!0})})),d=n(m,f.id)){this.depMaps.push(f);if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else d?(this.map.url=h.nameToUrl(d),this.load()):(l=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),l.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];A(m,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),l.fromText=u(this,function(f,c){var d=a.name,g=i(d),P=M;c&&(f=c);P&& -(M=!1);r(g);t(k.config,b)&&(k.config[d]=k.config[b]);try{e.exec(f)}catch(m){return w(B("fromtexteval","fromText eval for "+b+" failed: "+m,m,[b]))}P&&(M=!0);this.depMaps.push(g);h.completeLoad(d);p([d],l)}),f.load(a.name,p,l,k))}));h.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,u(this,function(a,b){var c,f;if("string"===typeof a){a=i(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c= -n(L,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",u(this,function(a){this.undefed||(this.defineDep(b,a),this.check())}));this.errback?s(a,"error",u(this,this.errback)):this.events.error&&s(a,"error",u(this,function(a){this.emit("error",a)}))}c=a.id;f=m[c];!t(L,c)&&(f&&!f.enabled)&&h.enable(a,this)}));A(this.pluginMaps,u(this,function(a){var b=n(m,a.id);b&&!b.enabled&&h.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]= -[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};h={config:k,contextName:b,registry:m,defined:q,urlFetched:S,defQueue:C,defQueueMap:{},Module:Z,makeModuleMap:i,nextTick:e.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=k.shim,c={paths:!0,bundles:!0,config:!0,map:!0};A(a,function(a,b){c[b]?(k[b]||(k[b]={}),U(k[b],a,!0,!0)):k[b]=a});a.bundles&&A(a.bundles,function(a,b){v(a, -function(a){a!==b&&(aa[a]=b)})});a.shim&&(A(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=h.makeShimExports(a);b[c]=a}),k.shim=b);a.packages&&v(a.packages,function(a){var b,a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(k.paths[b]=a.location);k.pkgs[b]=a.name+"/"+(a.main||"main").replace(ha,"").replace(Q,"")});A(m,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=i(b,null,!0))});if(a.deps||a.callback)h.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b; -a.init&&(b=a.init.apply(ba,arguments));return b||a.exports&&da(a.exports)}},makeRequire:function(a,j){function g(c,d,p){var k,n;j.enableBuildCallback&&(d&&G(d))&&(d.__requireJsBuild=!0);if("string"===typeof c){if(G(d))return w(B("requireargs","Invalid require call"),p);if(a&&t(L,c))return L[c](m[a.id]);if(e.get)return e.get(h,c,a,g);k=i(c,a,!1,!0);k=k.id;return!t(q,k)?w(B("notloaded",'Module name "'+k+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):q[k]}J();h.nextTick(function(){J(); -n=r(i(null,a));n.skipMap=j.skipMap;n.init(c,d,p,{enabled:!0});D()});return g}j=j||{};U(g,{isBrowser:z,toUrl:function(b){var d,e=b.lastIndexOf("."),j=b.split("/")[0];if(-1!==e&&(!("."===j||".."===j)||1g.attachEvent.toString().indexOf("[native code"))&&!Y?(M=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1));g.src=d;J=g;D?y.insertBefore(g,D):y.appendChild(g);J=null;return g}if(ea)try{importScripts(d),b.completeLoad(c)}catch(i){b.onError(B("importscripts", -"importScripts failed for "+c+" at "+d,i,[c]))}};z&&!s.skipDataMain&&T(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(I=b.getAttribute("data-main"))return r=I,s.baseUrl||(E=r.split("/"),r=E.pop(),O=E.length?E.join("/")+"/":"./",s.baseUrl=O),r=r.replace(Q,""),e.jsExtRegExp.test(r)&&(r=I),s.deps=s.deps?s.deps.concat(r):[r],!0});define=function(b,c,d){var e,g;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(ja,"").replace(ka, -function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(M){if(!(e=J))N&&"interactive"===N.readyState||T(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b}),e=N;e&&(b||(b=e.getAttribute("data-requiremodule")),g=F[e.getAttribute("data-requirecontext")])}g?(g.defQueue.push([b,c,d]),g.defQueueMap[b]=!0):R.push([b,c,d])};define.amd={jQuery:!0};e.exec=function(b){return eval(b)};e(s)}})(this); diff --git a/gulpfile.js b/gulpfile.js index ab3daebc047..cafa90b76c1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -31,7 +31,8 @@ var yargs = require('yargs'); var AWS = require('aws-sdk'); var mime = require('mime'); var rollup = require('rollup'); -var rollupPluginStripPragma = require('./Tools/rollup-plugin-strip-pragma'); +var rollupPluginBanner = require('rollup-plugin-banner'); +var rollupPluginStripPragma = require('rollup-plugin-strip-pragma'); var rollupPluginExternalGlobals = require('rollup-plugin-external-globals'); var rollupPluginUglify = require('rollup-plugin-uglify'); var cleanCSS = require('gulp-clean-css'); @@ -116,7 +117,8 @@ function createWorkers() { ]); return rollup.rollup({ - input: workers + input: workers, + plugins: [rollupPluginBanner.default('This file is automatically rebuilt by the Cesium build process.')] }).then(function(bundle) { return bundle.write({ dir: 'Build/createWorkers', @@ -152,20 +154,21 @@ gulp.task('buildApps', function() { }); gulp.task('build-specs', function buildSpecs() { - var cesiumViewerOutputDirectory = 'Build/Apps/CesiumViewer'; - mkdirp.sync(cesiumViewerOutputDirectory); + var externalCesium = rollupPluginExternalGlobals({ + '../Source/Cesium.js': 'Cesium', + '../../Source/Cesium.js': 'Cesium', + '../../../Source/Cesium.js': 'Cesium', + '../../../../Source/Cesium.js': 'Cesium' + }); + + var removePragmas = rollupPluginStripPragma({ + pragmas: ['debug'] + }); var promise = Promise.join( rollup.rollup({ input: 'Specs/SpecList.js', - plugins: [ - rollupPluginExternalGlobals({ - '../Source/Cesium.js': 'Cesium', - '../../Source/Cesium.js': 'Cesium', - '../../../Source/Cesium.js': 'Cesium', - '../../../../Source/Cesium.js': 'Cesium' - }) - ] + plugins: [externalCesium] }).then(function(bundle) { return bundle.write({ file: 'Build/Specs/Specs.js', @@ -174,17 +177,7 @@ gulp.task('build-specs', function buildSpecs() { }).then(function(){ return rollup.rollup({ input: 'Specs/spec-main.js', - plugins: [ - rollupPluginStripPragma({ - pragmas: ['debug'] - }), - rollupPluginExternalGlobals({ - '../Source/Cesium.js': 'Cesium', - '../../Source/Cesium.js': 'Cesium', - '../../../Source/Cesium.js': 'Cesium', - '../../../../Source/Cesium.js': 'Cesium' - }) - ] + plugins: [removePragmas, externalCesium] }).then(function(bundle) { return bundle.write({ file: 'Build/Specs/spec-main.js', @@ -194,17 +187,7 @@ gulp.task('build-specs', function buildSpecs() { }).then(function(){ return rollup.rollup({ input: 'Specs/karma-main.js', - plugins: [ - rollupPluginStripPragma({ - pragmas: ['debug'] - }), - rollupPluginExternalGlobals({ - '../Source/Cesium.js': 'Cesium', - '../../Source/Cesium.js': 'Cesium', - '../../../Source/Cesium.js': 'Cesium', - '../../../../Source/Cesium.js': 'Cesium' - }) - ] + plugins: [removePragmas, externalCesium] }).then(function(bundle) { return bundle.write({ file: 'Build/Specs/karma-main.js', diff --git a/package.json b/package.json index bbba5a6a196..3bbd6391c61 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "request": "^2.79.0", "rimraf": "^3.0.0", "rollup": "^1.21.4", + "rollup-plugin-banner": "^0.2.1", "rollup-plugin-external-globals": "^0.4.0", "rollup-plugin-strip-pragma": "^1.0.0", "rollup-plugin-uglify": "^6.0.3", From b03d680ef7787e98bb21336b70d22adee25aad30 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Thu, 3 Oct 2019 09:53:33 -0400 Subject: [PATCH 20/20] Fix built Sandcastle open in standalone. --- Apps/Sandcastle/standalone.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Apps/Sandcastle/standalone.html b/Apps/Sandcastle/standalone.html index 60ece3a66d5..4a4dbb26a80 100644 --- a/Apps/Sandcastle/standalone.html +++ b/Apps/Sandcastle/standalone.html @@ -27,6 +27,14 @@ var base64String; var data; + // Since we are setting the HTML base href below, we need to get the getCesiumBaseUrl + // upfront so that the value is correct. It gets cached for future calls. + // This is only a problem when using combined Cesium, which is the only time Cesium + // will be defined below. + if (typeof Cesium !== 'undefined') { + Cesium.buildModuleUrl.getCesiumBaseUrl(); + } + if (window.location.hash.indexOf('#c=') === 0) { base64String = window.location.hash.substr(3); data = window.decodeBase64Data(base64String, pako);