diff --git a/CHANGES.md b/CHANGES.md index c0f2c80ef5ce..397b924b117c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,9 @@ Change Log ##### Deprecated :hourglass_flowing_sand: * `ClippingPlaneCollection` is now supported in Internet Explorer, so `ClippingPlaneCollection.isSupported` has been deprecated and will be removed in Cesium 1.45. * `ClippingPlaneCollection` should now be used with `ClippingPlane` objects instead of `Plane`. Use of `Plane` objects has been deprecated and will be removed in Cesium 1.45. +* `Credit` now takes an `html` and `showOnScreen` parameters instead of an `options` object. Use of the `options` parameter is deprecated and will be removed in Cesium 1.46. +* `Credit.text`, `Credit.imageUrl` and `Credit.link` properties have all been deprecated and will be removed in Cesium 1.46. Use `Credit.html` to retrieve the credit content. +* `Credit.hasImage` and `Credit.hasLink` functions have been deprecated and will be removed in Cesium 1.46. ##### Additions :tada: * Added support for glTF models with [Draco geometry compression](https://github.com/fanzhanggoogle/glTF/blob/KHR_mesh_compression/extensions/Khronos/KHR_draco_mesh_compression/README.md). @@ -20,6 +23,7 @@ Change Log * sourceType specifies the type of data source if the URL doesn't have a known file extension. * flyTo=false optionally disables the automatic flyTo after loading the data source. * Added a multi-part CZML example to Sandcastle. [#6320](https://github.com/AnalyticalGraphicsInc/cesium/pull/6320) +* `Credit` has been modified to take an HTML string as the credit content [#6331](https://github.com/AnalyticalGraphicsInc/cesium/pull/6331) ##### Fixes :wrench: * Fixed support of glTF-supplied tangent vectors. [#6302](https://github.com/AnalyticalGraphicsInc/cesium/pull/6302) diff --git a/LICENSE.md b/LICENSE.md index 31245d76d8e4..4c062b3fc734 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -686,6 +686,34 @@ https://github.com/google/draco >License for the specific language governing permissions and limitations under >the License. +### JSXSS + +https://github.com/leizongmin/js-xss + +> Copyright (c) 2012-2017 Zongmin Lei(雷宗民) +> http://ucdok.com +> +> The MIT License +> +> 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. + Tests ===== diff --git a/Source/Assets/Images/bing_maps_credit.png b/Source/Assets/Images/bing_maps_credit.png new file mode 100644 index 000000000000..15109db3cd49 Binary files /dev/null and b/Source/Assets/Images/bing_maps_credit.png differ diff --git a/Source/Assets/Images/cesium_credit.png b/Source/Assets/Images/cesium_credit.png new file mode 100644 index 000000000000..4d1722b6ba90 Binary files /dev/null and b/Source/Assets/Images/cesium_credit.png differ diff --git a/Source/Assets/Images/google_earth_credit.png b/Source/Assets/Images/google_earth_credit.png new file mode 100644 index 000000000000..a7622d822d38 Binary files /dev/null and b/Source/Assets/Images/google_earth_credit.png differ diff --git a/Source/Core/BingMapsApi.js b/Source/Core/BingMapsApi.js index fbca04299f50..6d6032d28297 100644 --- a/Source/Core/BingMapsApi.js +++ b/Source/Core/BingMapsApi.js @@ -52,10 +52,7 @@ define([ } if (!defined(errorCredit)) { - errorCredit = new Credit({ - text : errorString, - showOnScreen : true - }); + errorCredit = new Credit(errorString, true); } return errorCredit; diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index cdd7644fe905..97760891cde1 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -131,7 +131,7 @@ define([ var credit = options.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } this._credit = credit; @@ -163,12 +163,11 @@ define([ var uri = new Uri(metadataResource.url); if (uri.authority === 'assets.agi.com') { - var deprecationText = 'The STK World Terrain tileset is deprecated and will be available until September 1, 2018'; + var deprecationText = 'The STK World Terrain tileset is deprecated and will be available until September 1, 2018.'; var deprecationLinkText = 'Check out the new high-resolution Cesium World Terrain'; var deprecationLink = 'https://cesium.com/blog/2018/03/01/introducing-cesium-world-terrain/'; that._tileCredits = [ - new Credit({ text: deprecationText, showOnScreen: true }), - new Credit({ text: deprecationLinkText, link: deprecationLink, showOnScreen: true }) + new Credit('' + deprecationText + ' ' + deprecationLinkText + '', true) ]; deprecationWarning('assets.agi.com', deprecationText + ' ' + deprecationLinkText + ' ' + deprecationLink); } else { @@ -327,7 +326,7 @@ define([ } } - var layerJsonCredit = new Credit({ text: attribution }); + var layerJsonCredit = new Credit(attribution); if (defined(that._tileCredits)) { that._tileCredits.push(layerJsonCredit); diff --git a/Source/Core/Credit.js b/Source/Core/Credit.js index 596339ef4d70..5e4bff76dc4b 100644 --- a/Source/Core/Credit.js +++ b/Source/Core/Credit.js @@ -1,62 +1,39 @@ define([ - './defaultValue', - './defined', - './defineProperties', - './DeveloperError' - ], function( - defaultValue, - defined, - defineProperties, - DeveloperError) { + './defaultValue', + './defined', + './defineProperties', + './deprecationWarning', + './DeveloperError', + '../ThirdParty/xss' +], function( + defaultValue, + defined, + defineProperties, + deprecationWarning, + DeveloperError, + xss) { 'use strict'; var nextCreditId = 0; var creditToId = {}; + function createDomNode(html) { + var span = document.createElement('span'); + span.innerHTML = html; + + return span; + } + function getElement(credit) { - var element = document.createElement('span'); - var text = credit.text; - var link = credit.link; - var a; - if (credit._hasImage) { - var content = document.createElement('img'); - content.src = credit.imageUrl; - if (defined(text)) { - content.alt = text; - content.title = text; - } - if (credit._hasLink) { - a = document.createElement('a'); - a.appendChild(content); - a.href = link; - a.target = '_blank'; - element.appendChild(a); - } else { - element.appendChild(content); - } - element.className = 'cesium-credit-image'; - } else { - if (credit._hasLink) { - a = document.createElement('a'); - a.textContent = text; - a.href = link; - a.target = '_blank'; - element.appendChild(a); - } else { - element.textContent = text; - } - element.className = 'cesium-credit-text'; - } - return element; + var html = credit.html; + html = xss(html); + return createDomNode(html); } /** * A credit contains data pertaining to how to display attributions/credits for certain content on the screen. - * @param {Object} [options] An object with the following properties - * @param {String} [options.text] The text to be displayed on the screen if no imageUrl is specified. - * @param {String} [options.imageUrl] The source location for an image - * @param {String} [options.link] A URL location for which the credit will be hyperlinked - * @param {Boolean} [options.showOnScreen=false] If true, the credit will be visible in the main credit container. Otherwise, it will appear in a popover + * @param {String} html An string representing an html code snippet (can be text only) + * @param {Boolean} [showOnScreen=false] If true, the credit will be visible in the main credit container. Otherwise, it will appear in a popover * * @alias Credit * @constructor @@ -71,38 +48,74 @@ define([ * link : 'https://cesiumjs.org/' * }); */ - function Credit(options) { - options = defaultValue(options, defaultValue.EMPTY_OBJECT); + function Credit(html, showOnScreen) { + var id; + var key; + if (typeof html !== 'string') { + var options = defaultValue(html, defaultValue.EMPTY_OBJECT); + deprecationWarning('Credit options', 'The options parameter has been deprecated and will be removed in Cesium 1.46. Instead, pass in an HTML string (or a string of text)'); + showOnScreen = defaultValue(options.showOnScreen, showOnScreen); + var text = options.text; + var imageUrl = options.imageUrl; + var link = options.link; - var text = options.text; - var imageUrl = options.imageUrl; - var link = options.link; - var showOnScreen = defaultValue(options.showOnScreen, false); + var hasLink = (defined(link)); + var hasImage = (defined(imageUrl)); + var hasText = (defined(text)); - var hasLink = (defined(link)); - var hasImage = (defined(imageUrl)); - var hasText = (defined(text)); + //>>includeStart('debug', pragmas.debug); + if (!hasText && !hasImage && !hasLink) { + throw new DeveloperError('options.text, options.imageUrl, or options.link is required.'); + } + //>>includeEnd('debug'); - //>>includeStart('debug', pragmas.debug); - if (!hasText && !hasImage && !hasLink) { - throw new DeveloperError('options.text, options.imageUrl, or options.link is required.'); - } - //>>includeEnd('debug'); + if (!hasText && !hasImage) { + text = link; + } - if (!hasText && !hasImage) { - text = link; - } + this._text = text; + this._imageUrl = imageUrl; + this._link = link; + this._hasLink = hasLink; + this._hasImage = hasImage; - this._text = text; - this._imageUrl = imageUrl; - this._link = link; - this._hasLink = hasLink; - this._hasImage = hasImage; - this._showOnScreen = showOnScreen; + var element = document.createElement('span'); + var a; + if (hasImage) { + var content = document.createElement('img'); + content.src = imageUrl; + if (defined(text)) { + content.alt = text; + content.title = text; + } + if (hasLink) { + a = document.createElement('a'); + a.appendChild(content); + a.href = link; + a.target = '_blank'; + element.appendChild(a); + } else { + element.appendChild(content); + } + element.className = 'cesium-credit-image'; + } else { + if (hasLink) { + a = document.createElement('a'); + a.textContent = text; + a.href = link; + a.target = '_blank'; + element.appendChild(a); + } else { + element.textContent = text; + } + element.className = 'cesium-credit-text'; + } - // Credits are immutable so generate an id to use to optimize equal() - var id; - var key = JSON.stringify([text, imageUrl, link]); + html = '' + element.innerHTML + ''; + key = JSON.stringify([text, imageUrl, link]); + } else { + key = html; + } if (defined(creditToId[key])) { id = creditToId[key]; @@ -111,12 +124,27 @@ define([ creditToId[key] = id; } - this._id = id; + showOnScreen = defaultValue(showOnScreen, false); + // Credits are immutable so generate an id to use to optimize equal() + this._id = id; + this._html = html; + this._showOnScreen = showOnScreen; this._element = undefined; } defineProperties(Credit.prototype, { + /** + * The credit content + * @memberof Credit.prototype + * @type {String} + * @readonly + */ + html : { + get : function() { + return this._html; + } + }, /** * The credit text * @memberof Credit.prototype @@ -125,6 +153,7 @@ define([ */ text : { get : function() { + deprecationWarning('Credit.text', 'Credit.text is deprecated and will be removed in Cesium 1.46. Instead, use Credit.html to get the credit content.'); return this._text; } }, @@ -137,6 +166,7 @@ define([ */ imageUrl : { get : function() { + deprecationWarning('Credit.imageUrl', 'Credit.imageUrl is deprecated and will be removed in Cesium 1.46. Instead, use Credit.html to get the credit content.'); return this._imageUrl; } }, @@ -149,6 +179,7 @@ define([ */ link : { get : function() { + deprecationWarning('Credit.link', 'Credit.link is deprecated and will be removed in Cesium 1.46. Instead, use Credit.html to get the credit content.'); return this._link; } }, @@ -200,6 +231,7 @@ define([ * @returns {Boolean} */ Credit.prototype.hasImage = function() { + deprecationWarning('Credit.hasImage', 'Credit.hasImage is deprecated and will be removed in Cesium 1.46.'); return this._hasImage; }; @@ -209,6 +241,7 @@ define([ * @returns {Boolean} */ Credit.prototype.hasLink = function() { + deprecationWarning('Credit.hasLink', 'Credit.hasLink is deprecated and will be removed in Cesium 1.46.'); return this._hasLink; }; @@ -236,5 +269,26 @@ define([ return Credit.equals(this, credit); }; + /** + * @private + * @param attribution + * @return {Credit} + */ + Credit.getIonCredit = function(attribution) { + var credit; + var showOnScreen = defined(attribution.collapsible) && !attribution.collapsible; + if (defined(attribution.html)) { + credit = new Credit(attribution.html, showOnScreen); + } else { + credit = new Credit({ + text: attribution.text, + link: attribution.url, + imageUrl: attribution.image + }, showOnScreen); + } + credit._isIon = true; + return credit; + }; + return Credit; }); diff --git a/Source/Core/GoogleEarthEnterpriseMetadata.js b/Source/Core/GoogleEarthEnterpriseMetadata.js index 1ad3392796f7..2d6b5e7fd66b 100644 --- a/Source/Core/GoogleEarthEnterpriseMetadata.js +++ b/Source/Core/GoogleEarthEnterpriseMetadata.js @@ -546,7 +546,7 @@ define([ var provider = providerInfo[i]; var copyrightString = provider.copyrightString; if (defined(copyrightString)) { - providers[provider.providerId] = new Credit({text: copyrightString.value}); + providers[provider.providerId] = new Credit(copyrightString.value); } } }) diff --git a/Source/Core/GoogleEarthEnterpriseTerrainProvider.js b/Source/Core/GoogleEarthEnterpriseTerrainProvider.js index bb0cc9f0e299..40fcffa7e54a 100644 --- a/Source/Core/GoogleEarthEnterpriseTerrainProvider.js +++ b/Source/Core/GoogleEarthEnterpriseTerrainProvider.js @@ -150,7 +150,7 @@ define([ var credit = options.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } this._credit = credit; diff --git a/Source/Core/IonResource.js b/Source/Core/IonResource.js index 329ddba62b3a..d814869f6131 100644 --- a/Source/Core/IonResource.js +++ b/Source/Core/IonResource.js @@ -130,14 +130,7 @@ define([ return this._credits; } - this._credits = this._ionEndpoint.attributions.map(function(attribution) { - return new Credit({ - text: attribution.text, - link: attribution.url, - imageUrl: attribution.image, - showOnScreen: defined(attribution.collapsible) && !attribution.collapsible - }); - }); + this._credits = this._ionEndpoint.attributions.map(Credit.getIonCredit); return this._credits; } diff --git a/Source/Core/MapboxApi.js b/Source/Core/MapboxApi.js index 1ca3b34368ba..59b600f021ff 100644 --- a/Source/Core/MapboxApi.js +++ b/Source/Core/MapboxApi.js @@ -47,10 +47,7 @@ define([ } if (!defined(errorCredit)) { - errorCredit = new Credit({ - text : errorString, - showOnScreen : true - }); + errorCredit = new Credit(errorString, true); } return errorCredit; diff --git a/Source/Core/VRTheWorldTerrainProvider.js b/Source/Core/VRTheWorldTerrainProvider.js index 21570b0b5961..a416dae9ead4 100644 --- a/Source/Core/VRTheWorldTerrainProvider.js +++ b/Source/Core/VRTheWorldTerrainProvider.js @@ -98,7 +98,7 @@ define([ var credit = options.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } this._credit = credit; diff --git a/Source/Scene/ArcGisMapServerImageryProvider.js b/Source/Scene/ArcGisMapServerImageryProvider.js index d5123ec76a33..7644ed4fe608 100644 --- a/Source/Scene/ArcGisMapServerImageryProvider.js +++ b/Source/Scene/ArcGisMapServerImageryProvider.js @@ -216,7 +216,7 @@ define([ } if (defined(data.copyrightText) && data.copyrightText.length > 0) { - that._credit = new Credit({text: data.copyrightText}); + that._credit = new Credit(data.copyrightText); } that._ready = true; diff --git a/Source/Scene/BingMapsImageryProvider.js b/Source/Scene/BingMapsImageryProvider.js index 7588ffcd01e3..ef450efe5d6c 100644 --- a/Source/Scene/BingMapsImageryProvider.js +++ b/Source/Scene/BingMapsImageryProvider.js @@ -1,5 +1,6 @@ define([ '../Core/BingMapsApi', + '../Core/buildModuleUrl', '../Core/Cartesian2', '../Core/Credit', '../Core/defaultValue', @@ -20,6 +21,7 @@ define([ './ImageryProvider' ], function( BingMapsApi, + buildModuleUrl, Cartesian2, Credit, defaultValue, @@ -118,11 +120,7 @@ define([ this._culture = defaultValue(options.culture, ''); this._tileDiscardPolicy = options.tileDiscardPolicy; this._proxy = options.proxy; - this._credit = new Credit({ - text: 'Bing Imagery', - imageUrl: BingMapsImageryProvider._logoData, - link: 'http://www.bing.com' - }); + this._credit = new Credit(''); /** * The default {@link ImageryLayer#gamma} to use for imagery layers created for this provider. @@ -200,9 +198,7 @@ define([ for (var attributionIndex = 0, attributionLength = attributionList.length; attributionIndex < attributionLength; ++attributionIndex) { var attribution = attributionList[attributionIndex]; - attribution.credit = new Credit({ - text: attribution.attribution - }); + attribution.credit = new Credit(attribution.attribution); var coverageAreas = attribution.coverageAreas; @@ -574,7 +570,7 @@ define([ return undefined; }; - BingMapsImageryProvider._logoData = 'data:image/png;base64,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'; + BingMapsImageryProvider._logoData = buildModuleUrl('Assets/Images/bing_maps_credit.png'); /** * Converts a tiles (x, y, level) position into a quadkey used to request an image diff --git a/Source/Scene/CreditDisplay.js b/Source/Scene/CreditDisplay.js index 9eb709c98c11..d513f937f8c6 100644 --- a/Source/Scene/CreditDisplay.js +++ b/Source/Scene/CreditDisplay.js @@ -1,10 +1,12 @@ define([ + '../Core/buildModuleUrl', '../Core/Check', '../Core/Credit', '../Core/defaultValue', '../Core/defined', '../Core/destroyObject' ], function( + buildModuleUrl, Check, Credit, defaultValue, @@ -28,16 +30,36 @@ define([ return false; } - function displayTextCredits(creditDisplay, textCredits) { + function swapCesiumCredit(creditDisplay) { + // We don't want to clutter the screen with the Cesium logo and the Cesium ion + // logo at the same time. Since the ion logo is required, we just replace the + // Cesium logo or add the logo if the Cesium one was removed. + var previousCredit = creditDisplay._previousCesiumCredit; + var currentCredit = creditDisplay._currentCesiumCredit; + if (Credit.equals(currentCredit, previousCredit)) { + return; + } + + if (defined(previousCredit)) { + creditDisplay._cesiumCreditContainer.removeChild(previousCredit.element); + } + if (defined(currentCredit)) { + creditDisplay._cesiumCreditContainer.appendChild(currentCredit.element); + } + + creditDisplay._previousCesiumCredit = currentCredit; + } + + function displayCredits(creditDisplay, credits) { var i; var index; var credit; - var displayedTextCredits = creditDisplay._displayedCredits.textCredits; - var container = creditDisplay._textContainer; - for (i = 0; i < textCredits.length; i++) { - credit = textCredits[i]; + var displayedCredits = creditDisplay._displayedCredits.screenCredits; + var container = creditDisplay._screenContainer; + for (i = 0; i < credits.length; i++) { + credit = credits[i]; if (defined(credit)) { - index = displayedTextCredits.indexOf(credit); + index = displayedCredits.indexOf(credit); if (index === -1) { var element = credit.element; if (container.hasChildNodes()) { @@ -48,26 +70,7 @@ define([ } container.appendChild(element); } else { - displayedTextCredits.splice(index, 1); - } - } - } - } - - function displayImageCredits(creditDisplay, imageCredits) { - var i; - var index; - var credit; - var displayedImageCredits = creditDisplay._displayedCredits.imageCredits; - var container = creditDisplay._imageContainer; - for (i = 0; i < imageCredits.length; i++) { - credit = imageCredits[i]; - if (defined(credit)) { - index = displayedImageCredits.indexOf(credit); - if (index === -1) { - container.appendChild(credit.element); - } else { - displayedImageCredits.splice(index, 1); + displayedCredits.splice(index, 1); } } } @@ -100,12 +103,8 @@ define([ var container = credit.showOnScreen ? element.parentNode : element.parentNode.parentNode; - if (credit.hasImage() || !credit.showOnScreen) { - if (credit.showOnScreen) { - container.removeChild(element); - } else { - container.removeChild(element.parentNode); - } + if (!credit.showOnScreen) { + container.removeChild(element.parentNode); return; } @@ -122,20 +121,13 @@ define([ function removeUnusedCredits(creditDisplay) { var i; var credit; - var displayedTextCredits = creditDisplay._displayedCredits.textCredits; + var displayedTextCredits = creditDisplay._displayedCredits.screenCredits; for (i = 0; i < displayedTextCredits.length; i++) { credit = displayedTextCredits[i]; if (defined(credit)) { removeCreditDomElement(credit); } } - var displayedImageCredits = creditDisplay._displayedCredits.imageCredits; - for (i = 0; i < displayedImageCredits.length; i++) { - credit = displayedImageCredits[i]; - if (defined(credit)) { - removeCreditDomElement(credit); - } - } } function removeUnusedLightboxCredits(creditDisplay) { @@ -205,11 +197,11 @@ define([ margin : 'auto' }); - style += addStyle('.cesium-credit-lightbox > ul > li > span > a, .cesium-credit-lightbox > ul > li > span > a:visited', { + style += addStyle('.cesium-credit-lightbox > ul > li > span a, .cesium-credit-lightbox > ul > li > span a:visited', { color: textColor }); - style += addStyle('.cesium-credit-lightbox > ul > li > span > a:hover', { + style += addStyle('.cesium-credit-lightbox > ul > li > span a:hover', { color: highlightColor }); @@ -270,12 +262,8 @@ define([ head.insertBefore(css, head.firstChild); } - var cesiumCredit = new Credit({ - text: 'CesiumJS', - imageUrl: 'data:image/png;base64,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', - link: 'https://cesiumjs.org/', - showOnScreen: true - }); + var cesiumLogo = buildModuleUrl('Assets/Images/cesium_credit.png'); + var cesiumCredit = new Credit('', true); /** * The credit display is responsible for displaying credits on screen. @@ -328,13 +316,12 @@ define([ var creditList = document.createElement('ul'); lightboxCredits.appendChild(creditList); - var imageContainer = document.createElement('span'); - imageContainer.className = 'cesium-credit-imageContainer'; - container.appendChild(imageContainer); + var cesiumCreditContainer = document.createElement('span'); + container.appendChild(cesiumCreditContainer); - var textContainer = document.createElement('span'); - textContainer.className = 'cesium-credit-textContainer'; - container.appendChild(textContainer); + var screenContainer = document.createElement('span'); + screenContainer.className = 'cesium-credit-textContainer'; + container.appendChild(screenContainer); var expandLink = document.createElement('a'); expandLink.className = 'cesium-credit-expand-link'; @@ -345,8 +332,8 @@ define([ appendCss(); this._delimiter = defaultValue(delimiter, ' • '); - this._textContainer = textContainer; - this._imageContainer = imageContainer; + this._screenContainer = screenContainer; + this._cesiumCreditContainer = cesiumCreditContainer; this._lastViewportHeight = undefined; this._lastViewportWidth = undefined; this._lightboxCredits = lightboxCredits; @@ -355,17 +342,16 @@ define([ this._hideLightbox = hideLightbox; this._expandLink = expandLink; this._expanded = false; - this._defaultImageCredits = []; - this._defaultTextCredits = []; + this._defaultCredits = []; + this._previousCesiumCredit = undefined; + this._currentCesiumCredit = CreditDisplay.cesiumCredit; this._displayedCredits = { - imageCredits : [], - textCredits : [], + screenCredits : [], lightboxCredits : [] }; this._currentFrameCredits = { - imageCredits : [], - textCredits : [], + screenCredits : [], lightboxCredits : [] }; @@ -388,23 +374,14 @@ define([ Check.defined('credit', credit); //>>includeEnd('debug'); - var imageCredits = this._currentFrameCredits.imageCredits; + var screenCredits = this._currentFrameCredits.screenCredits; - if (credit.text === 'Cesium ion') { - // We don't want to clutter the screen with the Cesium logo and the Cesium ion - // logo at the same time. Since the ion logo is required, we just replace the - // Cesium logo or add the logo if the Cesium one was removed. - if (defined(imageCredits[cesiumCredit.id])) { - imageCredits[cesiumCredit.id] = credit; - } else { - imageCredits[credit.id] = credit; - } + if (credit._isIon) { + this._currentCesiumCredit = credit; } else if (!credit.showOnScreen) { this._currentFrameCredits.lightboxCredits[credit.id] = credit; - } else if (credit.hasImage()) { - imageCredits[credit.id] = credit; } else { - this._currentFrameCredits.textCredits[credit.id] = credit; + screenCredits[credit.id] = credit; } }; @@ -418,16 +395,9 @@ define([ Check.defined('credit', credit); //>>includeEnd('debug'); - if (credit.hasImage()) { - var imageCredits = this._defaultImageCredits; - if (!contains(imageCredits, credit)) { - imageCredits.push(credit); - } - } else { - var textCredits = this._defaultTextCredits; - if (!contains(textCredits, credit)) { - textCredits.push(credit); - } + var credits = this._defaultCredits; + if (!contains(credits, credit)) { + credits.push(credit); } }; @@ -441,17 +411,9 @@ define([ Check.defined('credit', credit); //>>includeEnd('debug'); - var index; - if (credit.hasImage()) { - index = this._defaultImageCredits.indexOf(credit); - if (index !== -1) { - this._defaultImageCredits.splice(index, 1); - } - } else { - index = this._defaultTextCredits.indexOf(credit); - if (index !== -1) { - this._defaultTextCredits.splice(index, 1); - } + var index = this._defaultCredits.indexOf(credit); + if (index !== -1) { + this._defaultCredits.splice(index, 1); } }; @@ -486,36 +448,27 @@ define([ * Resets the credit display to a beginning of frame state, clearing out current credits. */ CreditDisplay.prototype.beginFrame = function() { - this._currentFrameCredits.imageCredits.length = 0; - this._currentFrameCredits.textCredits.length = 0; + this._currentFrameCredits.screenCredits.length = 0; this._currentFrameCredits.lightboxCredits.length = 0; - - var cesiumCredit = CreditDisplay.cesiumCredit; - if (defined(cesiumCredit)) { - this._currentFrameCredits.imageCredits[cesiumCredit.id] = cesiumCredit; - } + this._currentCesiumCredit = CreditDisplay.cesiumCredit; }; /** * Sets the credit display to the end of frame state, displaying credits from the last frame in the credit container. */ CreditDisplay.prototype.endFrame = function() { - displayImageCredits(this, this._defaultImageCredits); - displayTextCredits(this, this._defaultTextCredits); - - displayImageCredits(this, this._currentFrameCredits.imageCredits); - displayTextCredits(this, this._currentFrameCredits.textCredits); + displayCredits(this, this._defaultCredits); + displayCredits(this, this._currentFrameCredits.screenCredits); - var displayedTextCredits = this._defaultTextCredits.concat(this._currentFrameCredits.textCredits); - var displayedImageCredits = this._defaultImageCredits.concat(this._currentFrameCredits.imageCredits); + var displayedScreenCredits = this._defaultCredits.concat(this._currentFrameCredits.screenCredits); var showLightboxLink = this._currentFrameCredits.lightboxCredits.length > 0; this._expandLink.style.display = showLightboxLink ? 'inline' : 'none'; removeUnusedCredits(this); + swapCesiumCredit(this); - this._displayedCredits.textCredits = displayedTextCredits; - this._displayedCredits.imageCredits = displayedImageCredits; + this._displayedCredits.screenCredits = displayedScreenCredits; this._creditsToUpdate = this._currentFrameCredits.lightboxCredits.slice(); }; @@ -533,8 +486,8 @@ define([ CreditDisplay.prototype.destroy = function() { this._lightbox.removeEventListener('click', this._hideLightbox, false); - this.container.removeChild(this._textContainer); - this.container.removeChild(this._imageContainer); + this.container.removeChild(this._cesiumCreditContainer); + this.container.removeChild(this._screenContainer); this.container.removeChild(this._expandLink); this.viewport.removeChild(this._lightbox); diff --git a/Source/Scene/GoogleEarthEnterpriseImageryProvider.js b/Source/Scene/GoogleEarthEnterpriseImageryProvider.js index e3602588038d..25e99b644153 100644 --- a/Source/Scene/GoogleEarthEnterpriseImageryProvider.js +++ b/Source/Scene/GoogleEarthEnterpriseImageryProvider.js @@ -133,7 +133,7 @@ define([ var credit = options.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } this._credit = credit; diff --git a/Source/Scene/GoogleEarthEnterpriseMapsProvider.js b/Source/Scene/GoogleEarthEnterpriseMapsProvider.js index 7e48643fae7b..3a961721987a 100644 --- a/Source/Scene/GoogleEarthEnterpriseMapsProvider.js +++ b/Source/Scene/GoogleEarthEnterpriseMapsProvider.js @@ -1,4 +1,5 @@ define([ + '../Core/buildModuleUrl', '../Core/Credit', '../Core/defaultValue', '../Core/defined', @@ -15,6 +16,7 @@ define([ '../ThirdParty/when', './ImageryProvider' ], function( + buildModuleUrl, Credit, defaultValue, defined, @@ -134,11 +136,7 @@ define([ this._tileDiscardPolicy = options.tileDiscardPolicy; this._channel = options.channel; this._requestType = 'ImageryMaps'; - this._credit = new Credit({ - text: 'Google Imagery', - imageUrl: GoogleEarthEnterpriseMapsProvider._logoData, - link: 'http://www.google.com/enterprise/mapsearth/products/earthenterprise.html' - }); + this._credit = new Credit(''); /** * The default {@link ImageryLayer#gamma} to use for imagery layers created for this provider. @@ -607,7 +605,7 @@ define([ return undefined; }; - GoogleEarthEnterpriseMapsProvider._logoData = 'data:image/png;base64,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'; + GoogleEarthEnterpriseMapsProvider._logoData = buildModuleUrl('Assets/Images/google_earth_credit.png'); return GoogleEarthEnterpriseMapsProvider; }); diff --git a/Source/Scene/IonImageryProvider.js b/Source/Scene/IonImageryProvider.js index 1dca249c0ca5..48205d1dea2d 100644 --- a/Source/Scene/IonImageryProvider.js +++ b/Source/Scene/IonImageryProvider.js @@ -185,14 +185,7 @@ define([ imageryProvider = factory(endpoint.options); } - that._tileCredits = endpoint.attributions.map(function(attribution) { - return new Credit({ - text: attribution.text, - link: attribution.url, - imageUrl: attribution.image, - showOnScreen: defined(attribution.collapsible) && !attribution.collapsible - }); - }); + that._tileCredits = endpoint.attributions.map(Credit.getIonCredit); return imageryProvider; }) diff --git a/Source/Scene/MapboxImageryProvider.js b/Source/Scene/MapboxImageryProvider.js index ac46c2693cd6..a6826f7e9728 100644 --- a/Source/Scene/MapboxImageryProvider.js +++ b/Source/Scene/MapboxImageryProvider.js @@ -21,14 +21,7 @@ define([ 'use strict'; var trailingSlashRegex = /\/$/; - var defaultCredit1 = new Credit({ - text:'© Mapbox © OpenStreetMap', - link: 'https://www.mapbox.com/about/maps/' - }); - var defaultCredit2 = [new Credit({ - text: 'Improve this map', - link: 'https://www.mapbox.com/map-feedback/' - })]; + var defaultCredit = new Credit('© Mapbox © OpenStreetMap Improve this map'); /** * Provides tiled imagery hosted by Mapbox. @@ -104,19 +97,20 @@ define([ access_token: accessToken }); + var credit; if (defined(options.credit)) { - var credit = options.credit; + credit = options.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } - defaultCredit1 = credit; - defaultCredit2.length = 0; + } else { + credit = defaultCredit; } this._resource = resource; this._imageryProvider = new UrlTemplateImageryProvider({ url: resource, - credit: defaultCredit1, + credit: credit, ellipsoid: options.ellipsoid, minimumLevel: options.minimumLevel, maximumLevel: options.maximumLevel, @@ -326,11 +320,9 @@ define([ * @exception {DeveloperError} getTileCredits must not be called before the imagery provider is ready. */ MapboxImageryProvider.prototype.getTileCredits = function(x, y, level) { - var credits = defaultCredit2.slice(); if (defined(this._accessTokenErrorCredit)) { - credits.push(this._accessTokenErrorCredit); + return [this._accessTokenErrorCredit]; } - return credits; }; /** @@ -374,5 +366,8 @@ define([ return this._imageryProvider.pickFeatures(x, y, level, longitude, latitude); }; + // Exposed for tests + MapboxImageryProvider._defaultCredit = defaultCredit; + return MapboxImageryProvider; }); diff --git a/Source/Scene/SingleTileImageryProvider.js b/Source/Scene/SingleTileImageryProvider.js index 2a2e676e9201..1ad86c008ebf 100644 --- a/Source/Scene/SingleTileImageryProvider.js +++ b/Source/Scene/SingleTileImageryProvider.js @@ -87,7 +87,7 @@ define([ var credit = options.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } this._credit = credit; diff --git a/Source/Scene/UrlTemplateImageryProvider.js b/Source/Scene/UrlTemplateImageryProvider.js index 029a097934d3..f325eade8085 100644 --- a/Source/Scene/UrlTemplateImageryProvider.js +++ b/Source/Scene/UrlTemplateImageryProvider.js @@ -620,7 +620,7 @@ define([ var credit = properties.credit; if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } that._credit = credit; diff --git a/Source/Scene/WebMapTileServiceImageryProvider.js b/Source/Scene/WebMapTileServiceImageryProvider.js index 0ec60896e918..6378d84595f6 100644 --- a/Source/Scene/WebMapTileServiceImageryProvider.js +++ b/Source/Scene/WebMapTileServiceImageryProvider.js @@ -87,7 +87,7 @@ define([ * tileMatrixSetID : 'default028mm', * // tileMatrixLabels : ['default028mm:0', 'default028mm:1', 'default028mm:2' ...], * maximumLevel: 19, - * credit : new Cesium.Credit({ text : 'U. S. Geological Survey' }) + * credit : new Cesium.Credit('U. S. Geological Survey') * }); * viewer.imageryLayers.addImageryProvider(shadedRelief1); * @@ -100,7 +100,7 @@ define([ * format : 'image/jpeg', * tileMatrixSetID : 'default028mm', * maximumLevel: 19, - * credit : new Cesium.Credit({ text : 'U. S. Geological Survey' }) + * credit : new Cesium.Credit('U. S. Geological Survey') * }); * viewer.imageryLayers.addImageryProvider(shadedRelief2); * @@ -123,7 +123,7 @@ define([ * format : 'image/png', * clock: clock, * times: times, - * credit : new Cesium.Credit({ text : 'NASA Global Imagery Browse Services for EOSDIS' }) + * credit : new Cesium.Credit('NASA Global Imagery Browse Services for EOSDIS') * }); * viewer.imageryLayers.addImageryProvider(weather); * @@ -234,7 +234,7 @@ define([ this._errorEvent = new Event(); var credit = options.credit; - this._credit = typeof credit === 'string' ? new Credit({text: credit}) : credit; + this._credit = typeof credit === 'string' ? new Credit(credit) : credit; this._subdomains = options.subdomains; if (isArray(this._subdomains)) { diff --git a/Source/Scene/createOpenStreetMapImageryProvider.js b/Source/Scene/createOpenStreetMapImageryProvider.js index 62ca813375e0..da0a604ad770 100644 --- a/Source/Scene/createOpenStreetMapImageryProvider.js +++ b/Source/Scene/createOpenStreetMapImageryProvider.js @@ -22,7 +22,7 @@ define([ UrlTemplateImageryProvider) { 'use strict'; - var defaultCredit = new Credit({text: 'MapQuest, Open Street Map and contributors, CC-BY-SA'}); + var defaultCredit = new Credit('MapQuest, Open Street Map and contributors, CC-BY-SA'); /** * Creates a {@link UrlTemplateImageryProvider} instance that provides tiled imagery hosted by OpenStreetMap @@ -101,7 +101,7 @@ define([ var credit = defaultValue(options.credit, defaultCredit); if (typeof credit === 'string') { - credit = new Credit({text: credit}); + credit = new Credit(credit); } return new UrlTemplateImageryProvider({ diff --git a/Source/ThirdParty/xss.js b/Source/ThirdParty/xss.js new file mode 100644 index 000000000000..24871d6276b4 --- /dev/null +++ b/Source/ThirdParty/xss.js @@ -0,0 +1,1613 @@ +/** +* @license +* Copyright (c) 2012-2017 Zongmin Lei(雷宗民) +* http://ucdok.com +* The MIT License +*/ + +// Built using: browserify lib/index.js --standalone xss > xss.js +// From: git@github.com:leizongmin/js-xss.git tag: v0.3.5 + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.xss = f()}})(function(){var define,module,exports;return (function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + */ + +var FilterCSS = require('cssfilter').FilterCSS; +var getDefaultCSSWhiteList = require('cssfilter').getDefaultWhiteList; +var _ = require('./util'); + +// 默认白名单 +function getDefaultWhiteList () { + return { + a: ['target', 'href', 'title'], + abbr: ['title'], + address: [], + area: ['shape', 'coords', 'href', 'alt'], + article: [], + aside: [], + audio: ['autoplay', 'controls', 'loop', 'preload', 'src'], + b: [], + bdi: ['dir'], + bdo: ['dir'], + big: [], + blockquote: ['cite'], + br: [], + caption: [], + center: [], + cite: [], + code: [], + col: ['align', 'valign', 'span', 'width'], + colgroup: ['align', 'valign', 'span', 'width'], + dd: [], + del: ['datetime'], + details: ['open'], + div: [], + dl: [], + dt: [], + em: [], + font: ['color', 'size', 'face'], + footer: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + header: [], + hr: [], + i: [], + img: ['src', 'alt', 'title', 'width', 'height'], + ins: ['datetime'], + li: [], + mark: [], + nav: [], + ol: [], + p: [], + pre: [], + s: [], + section:[], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + table: ['width', 'border', 'align', 'valign'], + tbody: ['align', 'valign'], + td: ['width', 'rowspan', 'colspan', 'align', 'valign'], + tfoot: ['align', 'valign'], + th: ['width', 'rowspan', 'colspan', 'align', 'valign'], + thead: ['align', 'valign'], + tr: ['rowspan', 'align', 'valign'], + tt: [], + u: [], + ul: [], + video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width'] + }; +} + +// 默认CSS Filter +var defaultCSSFilter = new FilterCSS(); + +/** + * 匹配到标签时的处理方法 + * + * @param {String} tag + * @param {String} html + * @param {Object} options + * @return {String} + */ +function onTag (tag, html, options) { + // do nothing +} + +/** + * 匹配到不在白名单上的标签时的处理方法 + * + * @param {String} tag + * @param {String} html + * @param {Object} options + * @return {String} + */ +function onIgnoreTag (tag, html, options) { + // do nothing +} + +/** + * 匹配到标签属性时的处理方法 + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @return {String} + */ +function onTagAttr (tag, name, value) { + // do nothing +} + +/** + * 匹配到不在白名单上的标签属性时的处理方法 + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @return {String} + */ +function onIgnoreTagAttr (tag, name, value) { + // do nothing +} + +/** + * HTML转义 + * + * @param {String} html + */ +function escapeHtml (html) { + return html.replace(REGEXP_LT, '<').replace(REGEXP_GT, '>'); +} + +/** + * 安全的标签属性值 + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @param {Object} cssFilter + * @return {String} + */ +function safeAttrValue (tag, name, value, cssFilter) { + // 转换为友好的属性值,再做判断 + value = friendlyAttrValue(value); + + if (name === 'href' || name === 'src') { + // 过滤 href 和 src 属性 + // 仅允许 http:// | https:// | mailto: | / | # 开头的地址 + value = _.trim(value); + if (value === '#') return '#'; + if (!(value.substr(0, 7) === 'http://' || + value.substr(0, 8) === 'https://' || + value.substr(0, 7) === 'mailto:' || + value.substr(0, 4) === 'tel:' || + value[0] === '#' || + value[0] === '/')) { + return ''; + } + } else if (name === 'background') { + // 过滤 background 属性 (这个xss漏洞较老了,可能已经不适用) + // javascript: + REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0; + if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) { + return ''; + } + } else if (name === 'style') { + // /*注释*/ + /*REGEXP_DEFAULT_ON_TAG_ATTR_3.lastIndex = 0; + if (REGEXP_DEFAULT_ON_TAG_ATTR_3.test(value)) { + return ''; + }*/ + // expression() + REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0; + if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) { + return ''; + } + // url() + REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0; + if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) { + REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0; + if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) { + return ''; + } + } + if (cssFilter !== false) { + cssFilter = cssFilter || defaultCSSFilter; + value = cssFilter.process(value); + } + } + + // 输出时需要转义<>" + value = escapeAttrValue(value); + return value; +} + +// 正则表达式 +var REGEXP_LT = //g; +var REGEXP_QUOTE = /"/g; +var REGEXP_QUOTE_2 = /"/g; +var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/img; +var REGEXP_ATTR_VALUE_COLON = /:?/img; +var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/img; +var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//mg; +var REGEXP_DEFAULT_ON_TAG_ATTR_4 = /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/ig; +var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/ig; +var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//ig; +var REGEXP_DEFAULT_ON_TAG_ATTR_7 = /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/ig; +var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/ig; + +/** + * 对双引号进行转义 + * + * @param {String} str + * @return {String} str + */ +function escapeQuote (str) { + return str.replace(REGEXP_QUOTE, '"'); +} + +/** + * 对双引号进行转义 + * + * @param {String} str + * @return {String} str + */ +function unescapeQuote (str) { + return str.replace(REGEXP_QUOTE_2, '"'); +} + +/** + * 对html实体编码进行转义 + * + * @param {String} str + * @return {String} + */ +function escapeHtmlEntities (str) { + return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode (str, code) { + return (code[0] === 'x' || code[0] === 'X') + ? String.fromCharCode(parseInt(code.substr(1), 16)) + : String.fromCharCode(parseInt(code, 10)); + }); +} + +/** + * 对html5新增的危险实体编码进行转义 + * + * @param {String} str + * @return {String} + */ +function escapeDangerHtml5Entities (str) { + return str.replace(REGEXP_ATTR_VALUE_COLON, ':') + .replace(REGEXP_ATTR_VALUE_NEWLINE, ' '); +} + +/** + * 清除不可见字符 + * + * @param {String} str + * @return {String} + */ +function clearNonPrintableCharacter (str) { + var str2 = ''; + for (var i = 0, len = str.length; i < len; i++) { + str2 += str.charCodeAt(i) < 32 ? ' ' : str.charAt(i); + } + return _.trim(str2); +} + +/** + * 将标签的属性值转换成一般字符,便于分析 + * + * @param {String} str + * @return {String} + */ +function friendlyAttrValue (str) { + str = unescapeQuote(str); // 双引号 + str = escapeHtmlEntities(str); // 转换HTML实体编码 + str = escapeDangerHtml5Entities(str); // 转换危险的HTML5新增实体编码 + str = clearNonPrintableCharacter(str); // 清除不可见字符 + return str; +} + +/** + * 转义用于输出的标签属性值 + * + * @param {String} str + * @return {String} + */ +function escapeAttrValue (str) { + str = escapeQuote(str); + str = escapeHtml(str); + return str; +} + +/** + * 去掉不在白名单中的标签onIgnoreTag处理方法 + */ +function onIgnoreTagStripAll () { + return ''; +} + +/** + * 删除标签体 + * + * @param {array} tags 要删除的标签列表 + * @param {function} next 对不在列表中的标签的处理函数,可选 + */ +function StripTagBody (tags, next) { + if (typeof(next) !== 'function') { + next = function () {}; + } + + var isRemoveAllTag = !Array.isArray(tags); + function isRemoveTag (tag) { + if (isRemoveAllTag) return true; + return (_.indexOf(tags, tag) !== -1); + } + + var removeList = []; // 要删除的位置范围列表 + var posStart = false; // 当前标签开始位置 + + return { + onIgnoreTag: function (tag, html, options) { + if (isRemoveTag(tag)) { + if (options.isClosing) { + var ret = '[/removed]'; + var end = options.position + ret.length; + removeList.push([posStart !== false ? posStart : options.position, end]); + posStart = false; + return ret; + } else { + if (!posStart) { + posStart = options.position; + } + return '[removed]'; + } + } else { + return next(tag, html, options); + } + }, + remove: function (html) { + var rethtml = ''; + var lastPos = 0; + _.forEach(removeList, function (pos) { + rethtml += html.slice(lastPos, pos[0]); + lastPos = pos[1]; + }); + rethtml += html.slice(lastPos); + return rethtml; + } + }; +} + +/** + * 去除备注标签 + * + * @param {String} html + * @return {String} + */ +function stripCommentTag (html) { + return html.replace(STRIP_COMMENT_TAG_REGEXP, ''); +} +var STRIP_COMMENT_TAG_REGEXP = //g; + +/** + * 去除不可见字符 + * + * @param {String} html + * @return {String} + */ +function stripBlankChar (html) { + var chars = html.split(''); + chars = chars.filter(function (char) { + var c = char.charCodeAt(0); + if (c === 127) return false; + if (c <= 31) { + if (c === 10 || c === 13) return true; + return false; + } + return true; + }); + return chars.join(''); +} + + +exports.whiteList = getDefaultWhiteList(); +exports.getDefaultWhiteList = getDefaultWhiteList; +exports.onTag = onTag; +exports.onIgnoreTag = onIgnoreTag; +exports.onTagAttr = onTagAttr; +exports.onIgnoreTagAttr = onIgnoreTagAttr; +exports.safeAttrValue = safeAttrValue; +exports.escapeHtml = escapeHtml; +exports.escapeQuote = escapeQuote; +exports.unescapeQuote = unescapeQuote; +exports.escapeHtmlEntities = escapeHtmlEntities; +exports.escapeDangerHtml5Entities = escapeDangerHtml5Entities; +exports.clearNonPrintableCharacter = clearNonPrintableCharacter; +exports.friendlyAttrValue = friendlyAttrValue; +exports.escapeAttrValue = escapeAttrValue; +exports.onIgnoreTagStripAll = onIgnoreTagStripAll; +exports.StripTagBody = StripTagBody; +exports.stripCommentTag = stripCommentTag; +exports.stripBlankChar = stripBlankChar; +exports.cssFilter = defaultCSSFilter; +exports.getDefaultCSSWhiteList = getDefaultCSSWhiteList; + +},{"./util":4,"cssfilter":8}],2:[function(require,module,exports){ +/** + * 模块入口 + * + * @author 老雷 + */ + +var DEFAULT = require('./default'); +var parser = require('./parser'); +var FilterXSS = require('./xss'); + + +/** + * XSS过滤 + * + * @param {String} html 要过滤的HTML代码 + * @param {Object} options 选项:whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml + * @return {String} + */ +function filterXSS (html, options) { + var xss = new FilterXSS(options); + return xss.process(html); +} + + +// 输出 +exports = module.exports = filterXSS; +exports.FilterXSS = FilterXSS; +for (var i in DEFAULT) exports[i] = DEFAULT[i]; +for (var i in parser) exports[i] = parser[i]; + + +// 在浏览器端使用 +if (typeof window !== 'undefined') { + window.filterXSS = module.exports; +} + +},{"./default":1,"./parser":3,"./xss":5}],3:[function(require,module,exports){ +/** + * 简单 HTML Parser + * + * @author 老雷 + */ + +var _ = require('./util'); + +/** + * 获取标签的名称 + * + * @param {String} html 如:'' + * @return {String} + */ +function getTagName (html) { + var i = _.spaceIndex(html); + if (i === -1) { + var tagName = html.slice(1, -1); + } else { + var tagName = html.slice(1, i + 1); + } + tagName = _.trim(tagName).toLowerCase(); + if (tagName.slice(0, 1) === '/') tagName = tagName.slice(1); + if (tagName.slice(-1) === '/') tagName = tagName.slice(0, -1); + return tagName; +} + +/** + * 是否为闭合标签 + * + * @param {String} html 如:'' + * @return {Boolean} + */ +function isClosing (html) { + return (html.slice(0, 2) === '') { + rethtml += escapeHtml(html.slice(lastPos, tagStart)); + currentHtml = html.slice(tagStart, currentPos + 1); + currentTagName = getTagName(currentHtml); + rethtml += onTag(tagStart, + rethtml.length, + currentTagName, + currentHtml, + isClosing(currentHtml)); + lastPos = currentPos + 1; + tagStart = false; + continue; + } + // HTML标签内的引号仅当前一个字符是等于号时才有效 + if ((c === '"' || c === "'") && html.charAt(currentPos - 1) === '=') { + quoteStart = c; + continue; + } + } else { + if (c === quoteStart) { + quoteStart = false; + continue; + } + } + } + } + if (lastPos < html.length) { + rethtml += escapeHtml(html.substr(lastPos)); + } + + return rethtml; +} + +// 不符合属性名称规则的正则表达式 +var REGEXP_ATTR_NAME = /[^a-zA-Z0-9_:\.\-]/img; + +/** + * 分析标签HTML代码,调用相应的函数处理,返回HTML + * + * @param {String} html 如标签'' 则为 'href="#" target="_blank"' + * @param {Function} onAttr 处理属性值的函数 + * 函数格式: function (name, value) + * @return {String} + */ +function parseAttr (html, onAttr) { + 'user strict'; + + var lastPos = 0; // 当前位置 + var retAttrs = []; // 待返回的属性列表 + var tmpName = false; // 临时属性名称 + var len = html.length; // HTML代码长度 + + function addAttr (name, value) { + name = _.trim(name); + name = name.replace(REGEXP_ATTR_NAME, '').toLowerCase(); + if (name.length < 1) return; + var ret = onAttr(name, value || ''); + if (ret) retAttrs.push(ret); + }; + + // 逐个分析字符 + for (var i = 0; i < len; i++) { + var c = html.charAt(i); + var v, j; + if (tmpName === false && c === '=') { + tmpName = html.slice(lastPos, i); + lastPos = i + 1; + continue; + } + if (tmpName !== false) { + // HTML标签内的引号仅当前一个字符是等于号时才有效 + if (i === lastPos && (c === '"' || c === "'") && html.charAt(i - 1) === '=') { + j = html.indexOf(c, i + 1); + if (j === -1) { + break; + } else { + v = _.trim(html.slice(lastPos + 1, j)); + addAttr(tmpName, v); + tmpName = false; + i = j; + lastPos = i + 1; + continue; + } + } + } + if (/\s|\n|\t/.test(c)) { + html = html.replace(/\s|\n|\t/g, ' '); + if (tmpName === false) { + j = findNextEqual(html, i); + if (j === -1) { + v = _.trim(html.slice(lastPos, i)); + addAttr(v); + tmpName = false; + lastPos = i + 1; + continue; + } else { + i = j - 1; + continue; + } + } else { + j = findBeforeEqual(html, i - 1); + if (j === -1) { + v = _.trim(html.slice(lastPos, i)); + v = stripQuoteWrap(v); + addAttr(tmpName, v); + tmpName = false; + lastPos = i + 1; + continue; + } else { + continue; + } + } + } + } + + if (lastPos < html.length) { + if (tmpName === false) { + addAttr(html.slice(lastPos)); + } else { + addAttr(tmpName, stripQuoteWrap(_.trim(html.slice(lastPos)))); + } + } + + return _.trim(retAttrs.join(' ')); +} + +function findNextEqual (str, i) { + for (; i < str.length; i++) { + var c = str[i]; + if (c === ' ') continue; + if (c === '=') return i; + return -1; + } +} + +function findBeforeEqual (str, i) { + for (; i > 0; i--) { + var c = str[i]; + if (c === ' ') continue; + if (c === '=') return i; + return -1; + } +} + +function isQuoteWrapString (text) { + if ((text[0] === '"' && text[text.length - 1] === '"') || + (text[0] === '\'' && text[text.length - 1] === '\'')) { + return true; + } else { + return false; + } +}; + +function stripQuoteWrap (text) { + if (isQuoteWrapString(text)) { + return text.substr(1, text.length - 2); + } else { + return text; + } +}; + + +exports.parseTag = parseTag; +exports.parseAttr = parseAttr; + +},{"./util":4}],4:[function(require,module,exports){ +module.exports = { + indexOf: function (arr, item) { + var i, j; + if (Array.prototype.indexOf) { + return arr.indexOf(item); + } + for (i = 0, j = arr.length; i < j; i++) { + if (arr[i] === item) { + return i; + } + } + return -1; + }, + forEach: function (arr, fn, scope) { + var i, j; + if (Array.prototype.forEach) { + return arr.forEach(fn, scope); + } + for (i = 0, j = arr.length; i < j; i++) { + fn.call(scope, arr[i], i, arr); + } + }, + trim: function (str) { + if (String.prototype.trim) { + return str.trim(); + } + return str.replace(/(^\s*)|(\s*$)/g, ''); + }, + spaceIndex: function (str) { + var reg = /\s|\n|\t/; + var match = reg.exec(str); + return match ? match.index : -1; + } +}; + +},{}],5:[function(require,module,exports){ +/** + * 过滤XSS + * + * @author 老雷 + */ + +var FilterCSS = require('cssfilter').FilterCSS; +var DEFAULT = require('./default'); +var parser = require('./parser'); +var parseTag = parser.parseTag; +var parseAttr = parser.parseAttr; +var _ = require('./util'); + + +/** + * 返回值是否为空 + * + * @param {Object} obj + * @return {Boolean} + */ +function isNull (obj) { + return (obj === undefined || obj === null); +} + +/** + * 取标签内的属性列表字符串 + * + * @param {String} html + * @return {Object} + * - {String} html + * - {Boolean} closing + */ +function getAttrs (html) { + var i = _.spaceIndex(html); + if (i === -1) { + return { + html: '', + closing: (html[html.length - 2] === '/') + }; + } + html = _.trim(html.slice(i + 1, -1)); + var isClosing = (html[html.length - 1] === '/'); + if (isClosing) html = _.trim(html.slice(0, -1)); + return { + html: html, + closing: isClosing + }; +} + +/** + * 浅拷贝对象 + * + * @param {Object} obj + * @return {Object} + */ +function shallowCopyObject (obj) { + var ret = {}; + for (var i in obj) { + ret[i] = obj[i]; + } + return ret; +} + +/** + * XSS过滤对象 + * + * @param {Object} options + * 选项:whiteList, onTag, onTagAttr, onIgnoreTag, + * onIgnoreTagAttr, safeAttrValue, escapeHtml + * stripIgnoreTagBody, allowCommentTag, stripBlankChar + * css{whiteList, onAttr, onIgnoreAttr} css=false表示禁用cssfilter + */ +function FilterXSS (options) { + options = shallowCopyObject(options || {}); + + if (options.stripIgnoreTag) { + if (options.onIgnoreTag) { + console.error('Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time'); + } + options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll; + } + + options.whiteList = options.whiteList || DEFAULT.whiteList; + options.onTag = options.onTag || DEFAULT.onTag; + options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr; + options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag; + options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr; + options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue; + options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml; + this.options = options; + + if (options.css === false) { + this.cssFilter = false; + } else { + options.css = options.css || {}; + this.cssFilter = new FilterCSS(options.css); + } +} + +/** + * 开始处理 + * + * @param {String} html + * @return {String} + */ +FilterXSS.prototype.process = function (html) { + // 兼容各种奇葩输入 + html = html || ''; + html = html.toString(); + if (!html) return ''; + + var me = this; + var options = me.options; + var whiteList = options.whiteList; + var onTag = options.onTag; + var onIgnoreTag = options.onIgnoreTag; + var onTagAttr = options.onTagAttr; + var onIgnoreTagAttr = options.onIgnoreTagAttr; + var safeAttrValue = options.safeAttrValue; + var escapeHtml = options.escapeHtml; + var cssFilter = me.cssFilter; + + // 是否清除不可见字符 + if (options.stripBlankChar) { + html = DEFAULT.stripBlankChar(html); + } + + // 是否禁止备注标签 + if (!options.allowCommentTag) { + html = DEFAULT.stripCommentTag(html); + } + + // 如果开启了stripIgnoreTagBody + var stripIgnoreTagBody = false; + if (options.stripIgnoreTagBody) { + var stripIgnoreTagBody = DEFAULT.StripTagBody(options.stripIgnoreTagBody, onIgnoreTag); + onIgnoreTag = stripIgnoreTagBody.onIgnoreTag; + } + + var retHtml = parseTag(html, function (sourcePosition, position, tag, html, isClosing) { + var info = { + sourcePosition: sourcePosition, + position: position, + isClosing: isClosing, + isWhite: (tag in whiteList) + }; + + // 调用onTag处理 + var ret = onTag(tag, html, info); + if (!isNull(ret)) return ret; + + // 默认标签处理方法 + if (info.isWhite) { + // 白名单标签,解析标签属性 + // 如果是闭合标签,则不需要解析属性 + if (info.isClosing) { + return ''; + } + + var attrs = getAttrs(html); + var whiteAttrList = whiteList[tag]; + var attrsHtml = parseAttr(attrs.html, function (name, value) { + + // 调用onTagAttr处理 + var isWhiteAttr = (_.indexOf(whiteAttrList, name) !== -1); + var ret = onTagAttr(tag, name, value, isWhiteAttr); + if (!isNull(ret)) return ret; + + // 默认的属性处理方法 + if (isWhiteAttr) { + // 白名单属性,调用safeAttrValue过滤属性值 + value = safeAttrValue(tag, name, value, cssFilter); + if (value) { + return name + '="' + value + '"'; + } else { + return name; + } + } else { + // 非白名单属性,调用onIgnoreTagAttr处理 + var ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr); + if (!isNull(ret)) return ret; + return; + } + }); + + // 构造新的标签代码 + var html = '<' + tag; + if (attrsHtml) html += ' ' + attrsHtml; + if (attrs.closing) html += ' /'; + html += '>'; + return html; + + } else { + // 非白名单标签,调用onIgnoreTag处理 + var ret = onIgnoreTag(tag, html, info); + if (!isNull(ret)) return ret; + return escapeHtml(html); + } + + }, escapeHtml); + + // 如果开启了stripIgnoreTagBody,需要对结果再进行处理 + if (stripIgnoreTagBody) { + retHtml = stripIgnoreTagBody.remove(retHtml); + } + + return retHtml; +}; + + +module.exports = FilterXSS; + +},{"./default":1,"./parser":3,"./util":4,"cssfilter":8}],6:[function(require,module,exports){ +/** + * cssfilter + * + * @author 老雷 + */ + +var DEFAULT = require('./default'); +var parseStyle = require('./parser'); +var _ = require('./util'); + + +/** + * 返回值是否为空 + * + * @param {Object} obj + * @return {Boolean} + */ +function isNull (obj) { + return (obj === undefined || obj === null); +} + +/** + * 浅拷贝对象 + * + * @param {Object} obj + * @return {Object} + */ +function shallowCopyObject (obj) { + var ret = {}; + for (var i in obj) { + ret[i] = obj[i]; + } + return ret; +} + +/** + * 创建CSS过滤器 + * + * @param {Object} options + * - {Object} whiteList + * - {Function} onAttr + * - {Function} onIgnoreAttr + * - {Function} safeAttrValue + */ +function FilterCSS (options) { + options = shallowCopyObject(options || {}); + options.whiteList = options.whiteList || DEFAULT.whiteList; + options.onAttr = options.onAttr || DEFAULT.onAttr; + options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT.onIgnoreAttr; + options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue; + this.options = options; +} + +FilterCSS.prototype.process = function (css) { + // 兼容各种奇葩输入 + css = css || ''; + css = css.toString(); + if (!css) return ''; + + var me = this; + var options = me.options; + var whiteList = options.whiteList; + var onAttr = options.onAttr; + var onIgnoreAttr = options.onIgnoreAttr; + var safeAttrValue = options.safeAttrValue; + + var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) { + + var check = whiteList[name]; + var isWhite = false; + if (check === true) isWhite = check; + else if (typeof check === 'function') isWhite = check(value); + else if (check instanceof RegExp) isWhite = check.test(value); + if (isWhite !== true) isWhite = false; + + // 如果过滤后 value 为空则直接忽略 + value = safeAttrValue(name, value); + if (!value) return; + + var opts = { + position: position, + sourcePosition: sourcePosition, + source: source, + isWhite: isWhite + }; + + if (isWhite) { + + var ret = onAttr(name, value, opts); + if (isNull(ret)) { + return name + ':' + value; + } else { + return ret; + } + + } else { + + var ret = onIgnoreAttr(name, value, opts); + if (!isNull(ret)) { + return ret; + } + + } + }); + + return retCSS; +}; + + +module.exports = FilterCSS; + +},{"./default":7,"./parser":9,"./util":10}],7:[function(require,module,exports){ +/** + * cssfilter + * + * @author 老雷 + */ + +function getDefaultWhiteList () { + // 白名单值说明: + // true: 允许该属性 + // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许 + // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许 + // 除上面列出的值外均表示不允许 + var whiteList = {}; + + whiteList['align-content'] = false; // default: auto + whiteList['align-items'] = false; // default: auto + whiteList['align-self'] = false; // default: auto + whiteList['alignment-adjust'] = false; // default: auto + whiteList['alignment-baseline'] = false; // default: baseline + whiteList['all'] = false; // default: depending on individual properties + whiteList['anchor-point'] = false; // default: none + whiteList['animation'] = false; // default: depending on individual properties + whiteList['animation-delay'] = false; // default: 0 + whiteList['animation-direction'] = false; // default: normal + whiteList['animation-duration'] = false; // default: 0 + whiteList['animation-fill-mode'] = false; // default: none + whiteList['animation-iteration-count'] = false; // default: 1 + whiteList['animation-name'] = false; // default: none + whiteList['animation-play-state'] = false; // default: running + whiteList['animation-timing-function'] = false; // default: ease + whiteList['azimuth'] = false; // default: center + whiteList['backface-visibility'] = false; // default: visible + whiteList['background'] = true; // default: depending on individual properties + whiteList['background-attachment'] = true; // default: scroll + whiteList['background-clip'] = true; // default: border-box + whiteList['background-color'] = true; // default: transparent + whiteList['background-image'] = true; // default: none + whiteList['background-origin'] = true; // default: padding-box + whiteList['background-position'] = true; // default: 0% 0% + whiteList['background-repeat'] = true; // default: repeat + whiteList['background-size'] = true; // default: auto + whiteList['baseline-shift'] = false; // default: baseline + whiteList['binding'] = false; // default: none + whiteList['bleed'] = false; // default: 6pt + whiteList['bookmark-label'] = false; // default: content() + whiteList['bookmark-level'] = false; // default: none + whiteList['bookmark-state'] = false; // default: open + whiteList['border'] = true; // default: depending on individual properties + whiteList['border-bottom'] = true; // default: depending on individual properties + whiteList['border-bottom-color'] = true; // default: current color + whiteList['border-bottom-left-radius'] = true; // default: 0 + whiteList['border-bottom-right-radius'] = true; // default: 0 + whiteList['border-bottom-style'] = true; // default: none + whiteList['border-bottom-width'] = true; // default: medium + whiteList['border-collapse'] = true; // default: separate + whiteList['border-color'] = true; // default: depending on individual properties + whiteList['border-image'] = true; // default: none + whiteList['border-image-outset'] = true; // default: 0 + whiteList['border-image-repeat'] = true; // default: stretch + whiteList['border-image-slice'] = true; // default: 100% + whiteList['border-image-source'] = true; // default: none + whiteList['border-image-width'] = true; // default: 1 + whiteList['border-left'] = true; // default: depending on individual properties + whiteList['border-left-color'] = true; // default: current color + whiteList['border-left-style'] = true; // default: none + whiteList['border-left-width'] = true; // default: medium + whiteList['border-radius'] = true; // default: 0 + whiteList['border-right'] = true; // default: depending on individual properties + whiteList['border-right-color'] = true; // default: current color + whiteList['border-right-style'] = true; // default: none + whiteList['border-right-width'] = true; // default: medium + whiteList['border-spacing'] = true; // default: 0 + whiteList['border-style'] = true; // default: depending on individual properties + whiteList['border-top'] = true; // default: depending on individual properties + whiteList['border-top-color'] = true; // default: current color + whiteList['border-top-left-radius'] = true; // default: 0 + whiteList['border-top-right-radius'] = true; // default: 0 + whiteList['border-top-style'] = true; // default: none + whiteList['border-top-width'] = true; // default: medium + whiteList['border-width'] = true; // default: depending on individual properties + whiteList['bottom'] = false; // default: auto + whiteList['box-decoration-break'] = true; // default: slice + whiteList['box-shadow'] = true; // default: none + whiteList['box-sizing'] = true; // default: content-box + whiteList['box-snap'] = true; // default: none + whiteList['box-suppress'] = true; // default: show + whiteList['break-after'] = true; // default: auto + whiteList['break-before'] = true; // default: auto + whiteList['break-inside'] = true; // default: auto + whiteList['caption-side'] = false; // default: top + whiteList['chains'] = false; // default: none + whiteList['clear'] = true; // default: none + whiteList['clip'] = false; // default: auto + whiteList['clip-path'] = false; // default: none + whiteList['clip-rule'] = false; // default: nonzero + whiteList['color'] = true; // default: implementation dependent + whiteList['color-interpolation-filters'] = true; // default: auto + whiteList['column-count'] = false; // default: auto + whiteList['column-fill'] = false; // default: balance + whiteList['column-gap'] = false; // default: normal + whiteList['column-rule'] = false; // default: depending on individual properties + whiteList['column-rule-color'] = false; // default: current color + whiteList['column-rule-style'] = false; // default: medium + whiteList['column-rule-width'] = false; // default: medium + whiteList['column-span'] = false; // default: none + whiteList['column-width'] = false; // default: auto + whiteList['columns'] = false; // default: depending on individual properties + whiteList['contain'] = false; // default: none + whiteList['content'] = false; // default: normal + whiteList['counter-increment'] = false; // default: none + whiteList['counter-reset'] = false; // default: none + whiteList['counter-set'] = false; // default: none + whiteList['crop'] = false; // default: auto + whiteList['cue'] = false; // default: depending on individual properties + whiteList['cue-after'] = false; // default: none + whiteList['cue-before'] = false; // default: none + whiteList['cursor'] = false; // default: auto + whiteList['direction'] = false; // default: ltr + whiteList['display'] = true; // default: depending on individual properties + whiteList['display-inside'] = true; // default: auto + whiteList['display-list'] = true; // default: none + whiteList['display-outside'] = true; // default: inline-level + whiteList['dominant-baseline'] = false; // default: auto + whiteList['elevation'] = false; // default: level + whiteList['empty-cells'] = false; // default: show + whiteList['filter'] = false; // default: none + whiteList['flex'] = false; // default: depending on individual properties + whiteList['flex-basis'] = false; // default: auto + whiteList['flex-direction'] = false; // default: row + whiteList['flex-flow'] = false; // default: depending on individual properties + whiteList['flex-grow'] = false; // default: 0 + whiteList['flex-shrink'] = false; // default: 1 + whiteList['flex-wrap'] = false; // default: nowrap + whiteList['float'] = false; // default: none + whiteList['float-offset'] = false; // default: 0 0 + whiteList['flood-color'] = false; // default: black + whiteList['flood-opacity'] = false; // default: 1 + whiteList['flow-from'] = false; // default: none + whiteList['flow-into'] = false; // default: none + whiteList['font'] = true; // default: depending on individual properties + whiteList['font-family'] = true; // default: implementation dependent + whiteList['font-feature-settings'] = true; // default: normal + whiteList['font-kerning'] = true; // default: auto + whiteList['font-language-override'] = true; // default: normal + whiteList['font-size'] = true; // default: medium + whiteList['font-size-adjust'] = true; // default: none + whiteList['font-stretch'] = true; // default: normal + whiteList['font-style'] = true; // default: normal + whiteList['font-synthesis'] = true; // default: weight style + whiteList['font-variant'] = true; // default: normal + whiteList['font-variant-alternates'] = true; // default: normal + whiteList['font-variant-caps'] = true; // default: normal + whiteList['font-variant-east-asian'] = true; // default: normal + whiteList['font-variant-ligatures'] = true; // default: normal + whiteList['font-variant-numeric'] = true; // default: normal + whiteList['font-variant-position'] = true; // default: normal + whiteList['font-weight'] = true; // default: normal + whiteList['grid'] = false; // default: depending on individual properties + whiteList['grid-area'] = false; // default: depending on individual properties + whiteList['grid-auto-columns'] = false; // default: auto + whiteList['grid-auto-flow'] = false; // default: none + whiteList['grid-auto-rows'] = false; // default: auto + whiteList['grid-column'] = false; // default: depending on individual properties + whiteList['grid-column-end'] = false; // default: auto + whiteList['grid-column-start'] = false; // default: auto + whiteList['grid-row'] = false; // default: depending on individual properties + whiteList['grid-row-end'] = false; // default: auto + whiteList['grid-row-start'] = false; // default: auto + whiteList['grid-template'] = false; // default: depending on individual properties + whiteList['grid-template-areas'] = false; // default: none + whiteList['grid-template-columns'] = false; // default: none + whiteList['grid-template-rows'] = false; // default: none + whiteList['hanging-punctuation'] = false; // default: none + whiteList['height'] = true; // default: auto + whiteList['hyphens'] = false; // default: manual + whiteList['icon'] = false; // default: auto + whiteList['image-orientation'] = false; // default: auto + whiteList['image-resolution'] = false; // default: normal + whiteList['ime-mode'] = false; // default: auto + whiteList['initial-letters'] = false; // default: normal + whiteList['inline-box-align'] = false; // default: last + whiteList['justify-content'] = false; // default: auto + whiteList['justify-items'] = false; // default: auto + whiteList['justify-self'] = false; // default: auto + whiteList['left'] = false; // default: auto + whiteList['letter-spacing'] = true; // default: normal + whiteList['lighting-color'] = true; // default: white + whiteList['line-box-contain'] = false; // default: block inline replaced + whiteList['line-break'] = false; // default: auto + whiteList['line-grid'] = false; // default: match-parent + whiteList['line-height'] = false; // default: normal + whiteList['line-snap'] = false; // default: none + whiteList['line-stacking'] = false; // default: depending on individual properties + whiteList['line-stacking-ruby'] = false; // default: exclude-ruby + whiteList['line-stacking-shift'] = false; // default: consider-shifts + whiteList['line-stacking-strategy'] = false; // default: inline-line-height + whiteList['list-style'] = true; // default: depending on individual properties + whiteList['list-style-image'] = true; // default: none + whiteList['list-style-position'] = true; // default: outside + whiteList['list-style-type'] = true; // default: disc + whiteList['margin'] = true; // default: depending on individual properties + whiteList['margin-bottom'] = true; // default: 0 + whiteList['margin-left'] = true; // default: 0 + whiteList['margin-right'] = true; // default: 0 + whiteList['margin-top'] = true; // default: 0 + whiteList['marker-offset'] = false; // default: auto + whiteList['marker-side'] = false; // default: list-item + whiteList['marks'] = false; // default: none + whiteList['mask'] = false; // default: border-box + whiteList['mask-box'] = false; // default: see individual properties + whiteList['mask-box-outset'] = false; // default: 0 + whiteList['mask-box-repeat'] = false; // default: stretch + whiteList['mask-box-slice'] = false; // default: 0 fill + whiteList['mask-box-source'] = false; // default: none + whiteList['mask-box-width'] = false; // default: auto + whiteList['mask-clip'] = false; // default: border-box + whiteList['mask-image'] = false; // default: none + whiteList['mask-origin'] = false; // default: border-box + whiteList['mask-position'] = false; // default: center + whiteList['mask-repeat'] = false; // default: no-repeat + whiteList['mask-size'] = false; // default: border-box + whiteList['mask-source-type'] = false; // default: auto + whiteList['mask-type'] = false; // default: luminance + whiteList['max-height'] = true; // default: none + whiteList['max-lines'] = false; // default: none + whiteList['max-width'] = true; // default: none + whiteList['min-height'] = true; // default: 0 + whiteList['min-width'] = true; // default: 0 + whiteList['move-to'] = false; // default: normal + whiteList['nav-down'] = false; // default: auto + whiteList['nav-index'] = false; // default: auto + whiteList['nav-left'] = false; // default: auto + whiteList['nav-right'] = false; // default: auto + whiteList['nav-up'] = false; // default: auto + whiteList['object-fit'] = false; // default: fill + whiteList['object-position'] = false; // default: 50% 50% + whiteList['opacity'] = false; // default: 1 + whiteList['order'] = false; // default: 0 + whiteList['orphans'] = false; // default: 2 + whiteList['outline'] = false; // default: depending on individual properties + whiteList['outline-color'] = false; // default: invert + whiteList['outline-offset'] = false; // default: 0 + whiteList['outline-style'] = false; // default: none + whiteList['outline-width'] = false; // default: medium + whiteList['overflow'] = false; // default: depending on individual properties + whiteList['overflow-wrap'] = false; // default: normal + whiteList['overflow-x'] = false; // default: visible + whiteList['overflow-y'] = false; // default: visible + whiteList['padding'] = true; // default: depending on individual properties + whiteList['padding-bottom'] = true; // default: 0 + whiteList['padding-left'] = true; // default: 0 + whiteList['padding-right'] = true; // default: 0 + whiteList['padding-top'] = true; // default: 0 + whiteList['page'] = false; // default: auto + whiteList['page-break-after'] = false; // default: auto + whiteList['page-break-before'] = false; // default: auto + whiteList['page-break-inside'] = false; // default: auto + whiteList['page-policy'] = false; // default: start + whiteList['pause'] = false; // default: implementation dependent + whiteList['pause-after'] = false; // default: implementation dependent + whiteList['pause-before'] = false; // default: implementation dependent + whiteList['perspective'] = false; // default: none + whiteList['perspective-origin'] = false; // default: 50% 50% + whiteList['pitch'] = false; // default: medium + whiteList['pitch-range'] = false; // default: 50 + whiteList['play-during'] = false; // default: auto + whiteList['position'] = false; // default: static + whiteList['presentation-level'] = false; // default: 0 + whiteList['quotes'] = false; // default: text + whiteList['region-fragment'] = false; // default: auto + whiteList['resize'] = false; // default: none + whiteList['rest'] = false; // default: depending on individual properties + whiteList['rest-after'] = false; // default: none + whiteList['rest-before'] = false; // default: none + whiteList['richness'] = false; // default: 50 + whiteList['right'] = false; // default: auto + whiteList['rotation'] = false; // default: 0 + whiteList['rotation-point'] = false; // default: 50% 50% + whiteList['ruby-align'] = false; // default: auto + whiteList['ruby-merge'] = false; // default: separate + whiteList['ruby-position'] = false; // default: before + whiteList['shape-image-threshold'] = false; // default: 0.0 + whiteList['shape-outside'] = false; // default: none + whiteList['shape-margin'] = false; // default: 0 + whiteList['size'] = false; // default: auto + whiteList['speak'] = false; // default: auto + whiteList['speak-as'] = false; // default: normal + whiteList['speak-header'] = false; // default: once + whiteList['speak-numeral'] = false; // default: continuous + whiteList['speak-punctuation'] = false; // default: none + whiteList['speech-rate'] = false; // default: medium + whiteList['stress'] = false; // default: 50 + whiteList['string-set'] = false; // default: none + whiteList['tab-size'] = false; // default: 8 + whiteList['table-layout'] = false; // default: auto + whiteList['text-align'] = true; // default: start + whiteList['text-align-last'] = true; // default: auto + whiteList['text-combine-upright'] = true; // default: none + whiteList['text-decoration'] = true; // default: none + whiteList['text-decoration-color'] = true; // default: currentColor + whiteList['text-decoration-line'] = true; // default: none + whiteList['text-decoration-skip'] = true; // default: objects + whiteList['text-decoration-style'] = true; // default: solid + whiteList['text-emphasis'] = true; // default: depending on individual properties + whiteList['text-emphasis-color'] = true; // default: currentColor + whiteList['text-emphasis-position'] = true; // default: over right + whiteList['text-emphasis-style'] = true; // default: none + whiteList['text-height'] = true; // default: auto + whiteList['text-indent'] = true; // default: 0 + whiteList['text-justify'] = true; // default: auto + whiteList['text-orientation'] = true; // default: mixed + whiteList['text-overflow'] = true; // default: clip + whiteList['text-shadow'] = true; // default: none + whiteList['text-space-collapse'] = true; // default: collapse + whiteList['text-transform'] = true; // default: none + whiteList['text-underline-position'] = true; // default: auto + whiteList['text-wrap'] = true; // default: normal + whiteList['top'] = false; // default: auto + whiteList['transform'] = false; // default: none + whiteList['transform-origin'] = false; // default: 50% 50% 0 + whiteList['transform-style'] = false; // default: flat + whiteList['transition'] = false; // default: depending on individual properties + whiteList['transition-delay'] = false; // default: 0s + whiteList['transition-duration'] = false; // default: 0s + whiteList['transition-property'] = false; // default: all + whiteList['transition-timing-function'] = false; // default: ease + whiteList['unicode-bidi'] = false; // default: normal + whiteList['vertical-align'] = false; // default: baseline + whiteList['visibility'] = false; // default: visible + whiteList['voice-balance'] = false; // default: center + whiteList['voice-duration'] = false; // default: auto + whiteList['voice-family'] = false; // default: implementation dependent + whiteList['voice-pitch'] = false; // default: medium + whiteList['voice-range'] = false; // default: medium + whiteList['voice-rate'] = false; // default: normal + whiteList['voice-stress'] = false; // default: normal + whiteList['voice-volume'] = false; // default: medium + whiteList['volume'] = false; // default: medium + whiteList['white-space'] = false; // default: normal + whiteList['widows'] = false; // default: 2 + whiteList['width'] = true; // default: auto + whiteList['will-change'] = false; // default: auto + whiteList['word-break'] = true; // default: normal + whiteList['word-spacing'] = true; // default: normal + whiteList['word-wrap'] = true; // default: normal + whiteList['wrap-flow'] = false; // default: auto + whiteList['wrap-through'] = false; // default: wrap + whiteList['writing-mode'] = false; // default: horizontal-tb + whiteList['z-index'] = false; // default: auto + + return whiteList; +} + + +/** + * 匹配到白名单上的一个属性时 + * + * @param {String} name + * @param {String} value + * @param {Object} options + * @return {String} + */ +function onAttr (name, value, options) { + // do nothing +} + +/** + * 匹配到不在白名单上的一个属性时 + * + * @param {String} name + * @param {String} value + * @param {Object} options + * @return {String} + */ +function onIgnoreAttr (name, value, options) { + // do nothing +} + +var REGEXP_URL_JAVASCRIPT = /javascript\s*\:/img; + +/** + * 过滤属性值 + * + * @param {String} name + * @param {String} value + * @return {String} + */ +function safeAttrValue(name, value) { + if (REGEXP_URL_JAVASCRIPT.test(value)) return ''; + return value; +} + + +exports.whiteList = getDefaultWhiteList(); +exports.getDefaultWhiteList = getDefaultWhiteList; +exports.onAttr = onAttr; +exports.onIgnoreAttr = onIgnoreAttr; +exports.safeAttrValue = safeAttrValue; + +},{}],8:[function(require,module,exports){ +/** + * cssfilter + * + * @author 老雷 + */ + +var DEFAULT = require('./default'); +var FilterCSS = require('./css'); + + +/** + * XSS过滤 + * + * @param {String} css 要过滤的CSS代码 + * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr + * @return {String} + */ +function filterCSS (html, options) { + var xss = new FilterCSS(options); + return xss.process(html); +} + + +// 输出 +exports = module.exports = filterCSS; +exports.FilterCSS = FilterCSS; +for (var i in DEFAULT) exports[i] = DEFAULT[i]; + +// 在浏览器端使用 +if (typeof window !== 'undefined') { + window.filterCSS = module.exports; +} + +},{"./css":6,"./default":7}],9:[function(require,module,exports){ +/** + * cssfilter + * + * @author 老雷 + */ + +var _ = require('./util'); + + +/** + * 解析style + * + * @param {String} css + * @param {Function} onAttr 处理属性的函数 + * 参数格式: function (sourcePosition, position, name, value, source) + * @return {String} + */ +function parseStyle (css, onAttr) { + css = _.trimRight(css); + if (css[css.length - 1] !== ';') css += ';'; + var cssLength = css.length; + var isParenthesisOpen = false; + var lastPos = 0; + var i = 0; + var retCSS = ''; + + function addNewAttr () { + // 如果没有正常的闭合圆括号,则直接忽略当前属性 + if (!isParenthesisOpen) { + var source = _.trim(css.slice(lastPos, i)); + var j = source.indexOf(':'); + if (j !== -1) { + var name = _.trim(source.slice(0, j)); + var value = _.trim(source.slice(j + 1)); + // 必须有属性名称 + if (name) { + var ret = onAttr(lastPos, retCSS.length, name, value, source); + if (ret) retCSS += ret + '; '; + } + } + } + lastPos = i + 1; + } + + for (; i < cssLength; i++) { + var c = css[i]; + if (c === '/' && css[i + 1] === '*') { + // 备注开始 + var j = css.indexOf('*/', i + 2); + // 如果没有正常的备注结束,则后面的部分全部跳过 + if (j === -1) break; + // 直接将当前位置调到备注结尾,并且初始化状态 + i = j + 1; + lastPos = i + 1; + isParenthesisOpen = false; + } else if (c === '(') { + isParenthesisOpen = true; + } else if (c === ')') { + isParenthesisOpen = false; + } else if (c === ';') { + if (isParenthesisOpen) { + // 在圆括号里面,忽略 + } else { + addNewAttr(); + } + } else if (c === '\n') { + addNewAttr(); + } + } + + return _.trim(retCSS); +} + +module.exports = parseStyle; + +},{"./util":10}],10:[function(require,module,exports){ +module.exports = { + indexOf: function (arr, item) { + var i, j; + if (Array.prototype.indexOf) { + return arr.indexOf(item); + } + for (i = 0, j = arr.length; i < j; i++) { + if (arr[i] === item) { + return i; + } + } + return -1; + }, + forEach: function (arr, fn, scope) { + var i, j; + if (Array.prototype.forEach) { + return arr.forEach(fn, scope); + } + for (i = 0, j = arr.length; i < j; i++) { + fn.call(scope, arr[i], i, arr); + } + }, + trim: function (str) { + if (String.prototype.trim) { + return str.trim(); + } + return str.replace(/(^\s*)|(\s*$)/g, ''); + }, + trimRight: function (str) { + if (String.prototype.trimRight) { + return str.trimRight(); + } + return str.replace(/(\s*$)/g, ''); + } +}; + +},{}]},{},[2])(2) +}); diff --git a/Source/Widgets/CesiumWidget/CesiumWidget.js b/Source/Widgets/CesiumWidget/CesiumWidget.js index 5039775c771a..4439fc514b5a 100644 --- a/Source/Widgets/CesiumWidget/CesiumWidget.js +++ b/Source/Widgets/CesiumWidget/CesiumWidget.js @@ -2,7 +2,6 @@ define([ '../../Core/buildModuleUrl', '../../Core/Cartesian3', '../../Core/Clock', - '../../Core/Credit', '../../Core/defaultValue', '../../Core/defined', '../../Core/defineProperties', @@ -27,7 +26,6 @@ define([ buildModuleUrl, Cartesian3, Clock, - Credit, defaultValue, defined, defineProperties, diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index 73a52c045821..009cb3508b59 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -314,7 +314,7 @@ defineSuite([ return pollToPromise(function() { return provider.ready; }).then(function() { - expect(provider._tileCredits[0].text).toBe('This is a child tileset! This amazing data is courtesy The Amazing Data Source!'); + expect(provider._tileCredits[0].html).toBe('This is a child tileset! This amazing data is courtesy The Amazing Data Source!'); expect(provider.requestVertexNormals).toBe(true); expect(provider.requestWaterMask).toBe(true); expect(provider.hasVertexNormals).toBe(false); // Neither tileset has them @@ -455,7 +455,7 @@ defineSuite([ return pollToPromise(function() { return provider.ready; }).then(function() { - expect(provider._tileCredits[0].text).toBe('This amazing data is courtesy The Amazing Data Source!'); + expect(provider._tileCredits[0].html).toBe('This amazing data is courtesy The Amazing Data Source!'); }); }); diff --git a/Specs/Scene/CreditDisplaySpec.js b/Specs/Scene/CreditDisplaySpec.js index 6ab00dfc6f6e..4893462db55e 100644 --- a/Specs/Scene/CreditDisplaySpec.js +++ b/Specs/Scene/CreditDisplaySpec.js @@ -9,12 +9,6 @@ defineSuite([ 'use strict'; var container; - var imageContainer = 'cesium-credit-imageContainer'; - var textContainer = 'cesium-credit-textContainer'; - var text = 'cesium-credit-text'; - var image = 'cesium-credit-image'; - var imgSrc = 'imagesrc'; - var delimiter = 'cesium-credit-delimiter'; var creditDisplay; var defaultCredit; @@ -36,7 +30,6 @@ defineSuite([ // credit at the beginning of every frame function beginFrame(creditDisplay) { creditDisplay.beginFrame(); - creditDisplay._currentFrameCredits.imageCredits.length = 0; } it('credit display throws with no container', function() { @@ -67,125 +60,47 @@ defineSuite([ }); it('credits have unique ids', function() { - var credit1 = new Credit({ - text: 'credit1', - imageUrl: imgSrc, - link: 'http://cesiumjs.org/' - }); - var credit2 = new Credit({ - text: 'credit2', - imageUrl: imgSrc, - link: 'http://cesiumjs.org/' - }); + var credit1 = new Credit('credit1'); + var credit2 = new Credit('credit2'); expect(credit1.id).not.toEqual(credit2.id); - var credit1a = new Credit({ - text: 'credit1', - imageUrl: imgSrc, - link: 'http://cesiumjs.org/' - }); - expect(credit1.id).toEqual(credit1a.id); - }); - - it('credit display displays text credit', function() { - creditDisplay = new CreditDisplay(container); - var credit = new Credit({ - text: 'credit1', - showOnScreen: true - }); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit); - creditDisplay.endFrame(); - expect(container.childNodes.length).toEqual(3); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(1); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('credit1'); - }); - - it('credit display displays image credit', function() { - creditDisplay = new CreditDisplay(container); - var credit = new Credit({ - imageUrl: imgSrc, - showOnScreen: true - }); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit); - creditDisplay.endFrame(); - - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(1); - expect(child1.childNodes.length).toEqual(0); - var child00 = child0.childNodes[0]; - expect(child00.className).toEqual(image); - expect(child00.childNodes.length).toEqual(1); - expect(child00.childNodes[0].src).toContain(imgSrc); + var credit3 = new Credit('credit1'); + expect(credit1.id).toEqual(credit3.id); }); - it('credit display displays hyperlink credit', function() { + it('credit display displays a credit', function() { creditDisplay = new CreditDisplay(container); - var link = 'http://cesiumjs.org/'; - var credit = new Credit({ - link: link, - showOnScreen: true - }); + var credit = new Credit('CesiumJS.org', true); beginFrame(creditDisplay); creditDisplay.addCredit(credit); creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(1); - var child10 = child1.childNodes[0]; - expect(child10.className).toEqual(text); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(1); + var child10 = creditContainer.childNodes[0]; expect(child10.childNodes.length).toEqual(1); - expect(child10.childNodes[0].href).toEqual(link); - expect(child10.childNodes[0].innerHTML).toEqual(link); }); it('credit display updates html when credits change', function() { - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - var credit2 = new Credit({ - imageUrl: imgSrc, - showOnScreen: true - }); + var credit1 = new Credit('credit1', true); + var credit2 = new Credit('credit2', true); creditDisplay = new CreditDisplay(container); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); creditDisplay.endFrame(); var innerHTML = container.innerHTML; - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(1); - expect(child1.childNodes[0].innerHTML).toEqual('credit1'); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(1); + expect(creditContainer.childNodes[0].innerHTML).toEqual('credit1'); beginFrame(creditDisplay); creditDisplay.addCredit(credit2); creditDisplay.endFrame(); expect(container.innerHTML).not.toEqual(innerHTML); innerHTML = container.innerHTML; - child0 = container.childNodes[0]; - child1 = container.childNodes[1]; - expect(child0.childNodes.length).toEqual(1); - expect(child1.childNodes.length).toEqual(0); - var child00 = child0.childNodes[0]; - expect(child00.childNodes.length).toEqual(1); - expect(child00.childNodes[0].src).toContain(imgSrc); + expect(creditContainer.childNodes.length).toEqual(1); + expect(creditContainer.childNodes[0].innerHTML).toEqual('credit2'); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); @@ -193,162 +108,78 @@ defineSuite([ creditDisplay.endFrame(); expect(container.innerHTML).not.toEqual(innerHTML); innerHTML = container.innerHTML; - expect(container.childNodes[0].childNodes.length).toEqual(1); - expect(container.childNodes[1].childNodes.length).toEqual(1); + expect(creditContainer.childNodes.length).toEqual(3); beginFrame(creditDisplay); creditDisplay.endFrame(); expect(container.innerHTML).not.toEqual(innerHTML); - expect(container.childNodes[0].childNodes.length).toEqual(0); - expect(container.childNodes[1].childNodes.length).toEqual(0); + expect(creditContainer.childNodes.length).toEqual(0); }); - it('credit display uses delimeter for text credits', function() { - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - var credit2 = new Credit({ - text: 'credit2', - showOnScreen: true - }); + it('credit display uses delimeter', function() { + var credit1 = new Credit('credit1', true); + var credit2 = new Credit('credit2', true); + var delimiter = ', '; creditDisplay = new CreditDisplay(container, ', '); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); creditDisplay.addCredit(credit2); creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(3); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('credit1'); - expect(child1.childNodes[1].className).toEqual(delimiter); - expect(child1.childNodes[1].innerHTML).toEqual(', '); - expect(child1.childNodes[2].className).toEqual(text); - expect(child1.childNodes[2].innerHTML).toEqual('credit2'); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(3); + expect(creditContainer.childNodes[0].innerHTML).toEqual('credit1'); + expect(creditContainer.childNodes[1].innerHTML).toEqual(delimiter); + expect(creditContainer.childNodes[2].innerHTML).toEqual('credit2'); }); it('credit display manages delimeters correctly for text credits', function() { - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - var credit2 = new Credit({ - text: 'credit2', - showOnScreen: true - }); - var credit3 = new Credit({ - text: 'credit3', - showOnScreen: true - }); - - creditDisplay = new CreditDisplay(container, ', '); + var credit1 = new Credit('credit1', true); + var credit2 = new Credit('credit2', true); + var credit3 = new Credit('credit3', true); + var delimiter = ', '; + creditDisplay = new CreditDisplay(container, delimiter); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); creditDisplay.addCredit(credit2); creditDisplay.addCredit(credit3); creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(5); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[1].className).toEqual(delimiter); - expect(child1.childNodes[2].className).toEqual(text); - expect(child1.childNodes[3].className).toEqual(delimiter); - expect(child1.childNodes[4].className).toEqual(text); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(5); + expect(creditContainer.childNodes[0]).toEqual(credit1.element); + expect(creditContainer.childNodes[1].innerHTML).toEqual(delimiter); + expect(creditContainer.childNodes[2]).toEqual(credit2.element); + expect(creditContainer.childNodes[3].innerHTML).toEqual(delimiter); + expect(creditContainer.childNodes[4]).toEqual(credit3.element); beginFrame(creditDisplay); creditDisplay.addCredit(credit2); creditDisplay.addCredit(credit3); creditDisplay.endFrame(); - child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(3); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[1].className).toEqual(delimiter); - expect(child1.childNodes[2].className).toEqual(text); + expect(creditContainer.childNodes.length).toEqual(3); + expect(creditContainer.childNodes[0]).toEqual(credit2.element); + expect(creditContainer.childNodes[1].innerHTML).toEqual(delimiter); + expect(creditContainer.childNodes[2]).toEqual(credit3.element); beginFrame(creditDisplay); creditDisplay.addCredit(credit2); creditDisplay.endFrame(); - child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(1); - expect(child1.childNodes[0].className).toEqual(text); + expect(creditContainer.childNodes.length).toEqual(1); + expect(creditContainer.childNodes[0]).toEqual(credit2.element); beginFrame(creditDisplay); creditDisplay.addCredit(credit2); creditDisplay.addCredit(credit3); creditDisplay.endFrame(); - child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(3); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[1].className).toEqual(delimiter); - expect(child1.childNodes[2].className).toEqual(text); - }); - - it('credit display uses text as title for image credit', function() { - var credit1 = new Credit({ - text: 'credit text', - imageUrl: imgSrc, - showOnScreen: true - }); - creditDisplay = new CreditDisplay(container); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit1); - creditDisplay.endFrame(); - - var child0 = container.childNodes[0]; - expect(child0.className).toEqual(imageContainer); - expect(child0.childNodes.length).toEqual(1); - var child00 = child0.childNodes[0]; - expect(child00.className).toEqual(image); - expect(child00.childNodes.length).toEqual(1); - expect(child00.childNodes[0].src).toContain(imgSrc); - expect(child00.childNodes[0].alt).toEqual('credit text'); - expect(child00.childNodes[0].title).toEqual('credit text'); - }); - - it('credit display creates image credit with hyperlink', function() { - var credit1 = new Credit({ - imageUrl: imgSrc, - link: 'link.com', - showOnScreen: true - }); - creditDisplay = new CreditDisplay(container); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit1); - creditDisplay.endFrame(); - - var child0 = container.childNodes[0]; - expect(child0.className).toEqual(imageContainer); - expect(child0.childNodes.length).toEqual(1); - var child00 = child0.childNodes[0]; - expect(child00.className).toEqual(image); - expect(child00.childNodes.length).toEqual(1); - var child000 = child00.childNodes[0]; - expect(child000.href).toContain('link.com'); - expect(child000.childNodes.length).toEqual(1); - expect(child000.childNodes[0].src).toContain(imgSrc); + expect(creditContainer.childNodes.length).toEqual(3); + expect(creditContainer.childNodes[0]).toEqual(credit2.element); + expect(creditContainer.childNodes[1].innerHTML).toEqual(delimiter); + expect(creditContainer.childNodes[2]).toEqual(credit3.element); }); it('credit display displays default credit', function() { - var defaultCredit = new Credit({ - text: 'default credit', - showOnScreen: true - }); - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); + var defaultCredit = new Credit('default credit', true); + var credit1 = new Credit('credit1', true); creditDisplay = new CreditDisplay(container, ', '); creditDisplay.addDefaultCredit(defaultCredit); @@ -356,180 +187,57 @@ defineSuite([ creditDisplay.addCredit(credit1); creditDisplay.endFrame(); - var child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(3); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('default credit'); - expect(child1.childNodes[1].className).toEqual(delimiter); - expect(child1.childNodes[1].innerHTML).toEqual(', '); - expect(child1.childNodes[2].className).toEqual(text); - expect(child1.childNodes[2].innerHTML).toEqual('credit1'); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(3); + expect(creditContainer.childNodes[0]).toEqual(defaultCredit.element); + expect(creditContainer.childNodes[1].innerHTML).toEqual(', '); + expect(creditContainer.childNodes[2]).toEqual(credit1.element); beginFrame(creditDisplay); creditDisplay.endFrame(); - child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(1); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('default credit'); + expect(creditContainer.childNodes.length).toEqual(1); + expect(creditContainer.childNodes[0]).toEqual(defaultCredit.element); }); it('credit display displays credits when default is removed', function() { - var defaultCredit = new Credit({ - text: 'defaultCredit', - showOnScreen: true - }); - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); + var defaultCredit = new Credit('default credit', true); + var credit1 = new Credit('credit1', true); creditDisplay = new CreditDisplay(container, ', '); creditDisplay.addDefaultCredit(defaultCredit); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); creditDisplay.endFrame(); - var child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(3); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('defaultCredit'); - expect(child1.childNodes[1].className).toEqual(delimiter); - expect(child1.childNodes[1].innerHTML).toEqual(', '); - expect(child1.childNodes[2].className).toEqual(text); - expect(child1.childNodes[2].innerHTML).toEqual('credit1'); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(3); + expect(creditContainer.childNodes[0]).toEqual(defaultCredit.element); + expect(creditContainer.childNodes[1].innerHTML).toEqual(', '); + expect(creditContainer.childNodes[2]).toEqual(credit1.element); creditDisplay.removeDefaultCredit(defaultCredit); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); creditDisplay.endFrame(); - child1 = container.childNodes[1]; - expect(child1.className).toEqual(textContainer); - expect(child1.childNodes.length).toEqual(1); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('credit1'); + expect(creditContainer.childNodes.length).toEqual(1); + expect(creditContainer.childNodes[0]).toEqual(credit1.element); }); - it('credit display displays default image credit', function() { - var defaultCredit = new Credit({ - imageUrl: imgSrc, - showOnScreen: true - }); - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - creditDisplay = new CreditDisplay(container, ', '); - creditDisplay.addDefaultCredit(defaultCredit); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit1); - creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(1); - expect(child1.childNodes.length).toEqual(1); - - beginFrame(creditDisplay); - creditDisplay.endFrame(); - child0 = container.childNodes[0]; - child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(1); - expect(child1.childNodes.length).toEqual(0); - }); - - it('credit display displays credits when default image is removed', function() { - var defaultCredit = new Credit({ - imageUrl: imgSrc, - showOnScreen: true - }); - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - - creditDisplay = new CreditDisplay(container, ', '); - creditDisplay.addDefaultCredit(defaultCredit); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit1); - creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(1); - expect(child1.childNodes.length).toEqual(1); - - creditDisplay.removeDefaultCredit(defaultCredit); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit1); - creditDisplay.endFrame(); - child0 = container.childNodes[0]; - child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(1); - }); - - it('credit display only displays one if two image credits are equal', function() { - var credit1 = new Credit({ - imageUrl: imgSrc, - showOnScreen: true - }); - var credit2 = new Credit({ - imageUrl: imgSrc, - showOnScreen: true - }); + it('credit display only displays one if two credits are equal', function() { + var credit1 = new Credit('credit1', true); + var credit2 = new Credit('credit1', true); creditDisplay = new CreditDisplay(container); beginFrame(creditDisplay); creditDisplay.addCredit(credit1); creditDisplay.addCredit(credit2); creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(1); - expect(child1.childNodes.length).toEqual(0); - var child00 = child0.childNodes[0]; - expect(child00.className).toEqual(image); - expect(child00.childNodes.length).toEqual(1); - expect(child00.childNodes[0].src).toContain(imgSrc); - - }); - - it('credit display only displays one if two text credits are equal', function() { - var credit1 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - var credit2 = new Credit({ - text: 'credit1', - showOnScreen: true - }); - creditDisplay = new CreditDisplay(container); - beginFrame(creditDisplay); - creditDisplay.addCredit(credit1); - creditDisplay.addCredit(credit2); - creditDisplay.endFrame(); - var child0 = container.childNodes[0]; - var child1 = container.childNodes[1]; - expect(child0.className).toEqual(imageContainer); - expect(child1.className).toEqual(textContainer); - expect(child0.childNodes.length).toEqual(0); - expect(child1.childNodes.length).toEqual(1); - expect(child1.childNodes[0].className).toEqual(text); - expect(child1.childNodes[0].innerHTML).toEqual('credit1'); + var creditContainer = container.childNodes[1]; + expect(creditContainer.childNodes.length).toEqual(1); + expect(creditContainer.childNodes[0].innerHTML).toEqual('credit1'); }); it('displays credits in a lightbox', function() { - var credit1 = new Credit({text: 'credit1'}); - var credit2 = new Credit({imageUrl: imgSrc}); + var credit1 = new Credit('credit1'); + var credit2 = new Credit(''); creditDisplay = new CreditDisplay(container); var creditList = creditDisplay._creditList; @@ -576,8 +284,8 @@ defineSuite([ }); it('only renders lightbox credits when lightbox is visible', function() { - var credit1 = new Credit({text: 'credit1'}); - var credit2 = new Credit({imageUrl: imgSrc}); + var credit1 = new Credit('credit1'); + var credit2 = new Credit(''); creditDisplay = new CreditDisplay(container); var creditList = creditDisplay._creditList; @@ -604,8 +312,8 @@ defineSuite([ }); it('updates lightbox when a new frames are not rendered', function() { - var credit1 = new Credit({text: 'credit1'}); - var credit2 = new Credit({imageUrl: imgSrc}); + var credit1 = new Credit('credit1'); + var credit2 = new Credit(''); creditDisplay = new CreditDisplay(container); var creditList = creditDisplay._creditList; @@ -637,43 +345,28 @@ defineSuite([ it('works if Cesium credit removed', function() { creditDisplay = new CreditDisplay(container); + var cesiumCredit = CreditDisplay.cesiumCredit; CreditDisplay.cesiumCredit = undefined; creditDisplay.beginFrame(); - expect(creditDisplay._currentFrameCredits.imageCredits.length).toEqual(0); creditDisplay.endFrame(); + expect(creditDisplay._cesiumCreditContainer.childNodes.length).toBe(0); + CreditDisplay.cesiumCredit = cesiumCredit; }); it('works if Cesium credit replaced', function() { - var credit = new Credit({ text: '' }); - CreditDisplay.cesiumCredit = credit; - creditDisplay = new CreditDisplay(container); - creditDisplay.beginFrame(); - expect(creditDisplay._currentFrameCredits.imageCredits[credit.id]).toBe(credit); - creditDisplay.endFrame(); - }); - - it('replaces Cesium credit if ion asset detected', function() { - var ionCredit = new Credit({ text: 'Cesium ion' }); + var ionCredit = Credit.getIonCredit({ + html: 'Cesium ion', + collapsible: false + }); creditDisplay = new CreditDisplay(container); creditDisplay.beginFrame(); - - expect(creditDisplay._currentFrameCredits.imageCredits[CreditDisplay.cesiumCredit.id]).toBe(CreditDisplay.cesiumCredit); creditDisplay.addCredit(ionCredit); - expect(creditDisplay._currentFrameCredits.imageCredits[CreditDisplay.cesiumCredit.id]).toBe(ionCredit); creditDisplay.endFrame(); - }); - - it('adds ion credit detected if Cesium credit replaced', function() { - var ionCredit = new Credit({ text: 'Cesium ion' }); - CreditDisplay.cesiumCredit = new Credit({ text: 'not Cesium' }); - creditDisplay = new CreditDisplay(container); + expect(creditDisplay._cesiumCreditContainer.childNodes.length).toBe(1); + expect(creditDisplay._cesiumCreditContainer.childNodes[0]).toBe(ionCredit._element); creditDisplay.beginFrame(); - - expect(creditDisplay._currentFrameCredits.imageCredits[CreditDisplay.cesiumCredit.id]).toBe(CreditDisplay.cesiumCredit); - - creditDisplay.addCredit(ionCredit); - - expect(creditDisplay._currentFrameCredits.imageCredits[ionCredit.id]).toBe(ionCredit); creditDisplay.endFrame(); + expect(creditDisplay._cesiumCreditContainer.childNodes.length).toBe(1); + expect(creditDisplay._cesiumCreditContainer.childNodes[0]).toBe(CreditDisplay.cesiumCredit.element); }); }); diff --git a/Specs/Scene/MapboxImageryProviderSpec.js b/Specs/Scene/MapboxImageryProviderSpec.js index 4270f8d2d957..504ab5eec00a 100644 --- a/Specs/Scene/MapboxImageryProviderSpec.js +++ b/Specs/Scene/MapboxImageryProviderSpec.js @@ -242,7 +242,7 @@ defineSuite([ url : 'made/up/mapbox/server/', mapId: 'test-id' }); - expect(provider.credit.text).toEqual('© Mapbox © OpenStreetMap'); + expect(provider.credit.html).toBe(MapboxImageryProvider._defaultCredit); }); it('turns the supplied credit into a logo', function() { @@ -252,7 +252,7 @@ defineSuite([ mapId: 'test-id', credit: creditText }); - expect(providerWithCredit.credit.text).toEqual(creditText); + expect(providerWithCredit.credit.html).toEqual(creditText); }); it('raises error event when image cannot be loaded', function() {