From c0c5c520470aa386392cba2c7032c26116c53bb9 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Fri, 29 May 2020 17:52:31 -0400 Subject: [PATCH] Re-add changes from #8884 --- Source/Core/Event.js | 5 +- Source/Core/Resource.js | 34 +++++++++---- Source/DataSources/DataSource.js | 4 +- Source/DataSources/EntityCluster.js | 5 +- Source/DataSources/PropertyBag.js | 7 +-- Source/DataSources/exportKml.js | 76 +++++++++++++++++++---------- gulpfile.cjs | 28 ++++++++--- 7 files changed, 105 insertions(+), 54 deletions(-) diff --git a/Source/Core/Event.js b/Source/Core/Event.js index 99001dc5fce5..8becdbdbb9eb 100644 --- a/Source/Core/Event.js +++ b/Source/Core/Event.js @@ -7,6 +7,7 @@ import defined from "./defined.js"; * exposed as a property for others to subscribe to. * * @alias Event + * @template Listener the function call signature for this event's listeners * @constructor * @example * MyObject.prototype.myListener = function(arg1, arg2) { @@ -46,7 +47,7 @@ Object.defineProperties(Event.prototype, { * An optional scope can be provided to serve as the this pointer * in which the function will execute. * - * @param {Function} listener The function to be executed when the event is raised. + * @param {Listener} listener The function to be executed when the event is raised. * @param {Object} [scope] An optional object scope to serve as the this * pointer in which the listener function will execute. * @returns {Event.RemoveCallback} A function that will remove this event listener when invoked. @@ -71,7 +72,7 @@ Event.prototype.addEventListener = function (listener, scope) { /** * Unregisters a previously registered callback. * - * @param {Function} listener The function to be unregistered. + * @param {Listener} listener The function to be unregistered. * @param {Object} [scope] The scope that was originally passed to addEventListener. * @returns {Boolean} true if the listener was removed; false if the listener and scope are not registered with the event. * diff --git a/Source/Core/Resource.js b/Source/Core/Resource.js index c3fea4c508a6..1afe7f7ab6b4 100644 --- a/Source/Core/Resource.js +++ b/Source/Core/Resource.js @@ -212,21 +212,35 @@ function combineQueryParameters(q1, q2, preserveQueryParameters) { return result; } +/** @typedef {string | number | boolean} QueryValue */ +/** + * @typedef {Object.} Resource.QueryParameters + * QueryParameters must be an object whose keys are parameter names and whose + * values are a primitive (string, number, boolean) or an array thereof. + * */ + +/** + * @typedef {Object} Resource.ConstructorOptions + * + * Initialization options for the Resource constructor + * + * @property {String} url The url of the resource. + * @property {Resource.QueryParameters} [queryParameters] An object containing query parameters that will be sent when retrieving the resource. + * @property {Object} [templateValues] Key/Value pairs that are used to replace template values (eg. {x}). + * @property {Object} [headers={}] Additional HTTP headers that will be sent. + * @property {Proxy} [proxy] A proxy to be used when loading the resource. + * @property {Resource.RetryCallback} [retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried. + * @property {Number} [retryAttempts=0] The number of times the retryCallback should be called before giving up. + * @property {Request} [request] A Request object that will be used. Intended for internal use only. + */ + /** * A resource that includes the location and any other parameters we need to retrieve it or create derived resources. It also provides the ability to retry requests. * * @alias Resource * @constructor * - * @param {String|Object} options A url or an object with the following properties - * @param {String} options.url The url of the resource. - * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource. - * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}). - * @param {Object} [options.headers={}] Additional HTTP headers that will be sent. - * @param {Proxy} [options.proxy] A proxy to be used when loading the resource. - * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried. - * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up. - * @param {Request} [options.request] A Request object that will be used. Intended for internal use only. + * @param {String|Resource.ConstructorOptions} options A url or an object describing initialization options * * @example * function refreshTokenRetryCallback(resource, error) { @@ -564,7 +578,7 @@ Resource.prototype.getUrlComponent = function (query, proxy) { * Combines the specified object and the existing query parameters. This allows you to add many parameters at once, * as opposed to adding them one at a time to the queryParameters property. If a value is already set, it will be replaced with the new value. * - * @param {Object} params The query parameters + * @param {Resource.QueryParameters} params The query parameters * @param {Boolean} [useAsDefault=false] If true the params will be used as the default values, so they will only be set if they are undefined. */ Resource.prototype.setQueryParameters = function (params, useAsDefault) { diff --git a/Source/DataSources/DataSource.js b/Source/DataSources/DataSource.js index 182dac7602bf..4ac760371721 100644 --- a/Source/DataSources/DataSource.js +++ b/Source/DataSources/DataSource.js @@ -58,7 +58,7 @@ Object.defineProperties(DataSource.prototype, { /** * Gets an event that will be raised if an error is encountered during processing. * @memberof DataSource.prototype - * @type {Event} + * @type {Event} */ errorEvent: { get: DeveloperError.throwInstantiationError, @@ -66,7 +66,7 @@ Object.defineProperties(DataSource.prototype, { /** * Gets an event that will be raised when the value of isLoading changes. * @memberof DataSource.prototype - * @type {Event} + * @type {Event} */ loadingEvent: { get: DeveloperError.throwInstantiationError, diff --git a/Source/DataSources/EntityCluster.js b/Source/DataSources/EntityCluster.js index 2779deb12142..cee9319edec1 100644 --- a/Source/DataSources/EntityCluster.js +++ b/Source/DataSources/EntityCluster.js @@ -549,7 +549,7 @@ Object.defineProperties(EntityCluster.prototype, { /** * Gets the event that will be raised when a new cluster will be displayed. The signature of the event listener is {@link EntityCluster.newClusterCallback}. * @memberof EntityCluster.prototype - * @type {Event} + * @type {Event} */ clusterEvent: { get: function () { @@ -963,7 +963,8 @@ EntityCluster.prototype.destroy = function () { * @callback EntityCluster.newClusterCallback * * @param {Entity[]} clusteredEntities An array of the entities contained in the cluster. - * @param {Object} cluster An object containing billboard, label, and point properties. The values are the same as + * @param {{billboard: Billboard, label: Label, point: PointPrimitive}} cluster An object + * containing billboard, label, and point properties. The values are the same as * billboard, label and point entities, but must be the values of the ConstantProperty. * * @example diff --git a/Source/DataSources/PropertyBag.js b/Source/DataSources/PropertyBag.js index 688053f4c7ae..24f95598a6be 100644 --- a/Source/DataSources/PropertyBag.js +++ b/Source/DataSources/PropertyBag.js @@ -9,12 +9,7 @@ import Property from "./Property.js"; /** * A {@link Property} whose value is a key-value mapping of property names to the computed value of other properties. * - * @alias PropertyBag - * @constructor - * @implements {DictionaryLike} - * - * @param {Object} [value] An object, containing key-value mapping of property names to properties. - * @param {Function} [createPropertyCallback] A function that will be called when the value of any of the properties in value are not a Property. + * @typedef {PropertyBagType} */ function PropertyBag(value, createPropertyCallback) { this._propertyNames = []; diff --git a/Source/DataSources/exportKml.js b/Source/DataSources/exportKml.js index 46c1fa16de9e..0d8a17d4b3c2 100644 --- a/Source/DataSources/exportKml.js +++ b/Source/DataSources/exportKml.js @@ -221,6 +221,33 @@ IdManager.prototype.get = function (id) { return id.toString() + "-" + ++ids[id]; }; +/** + * @variation 2 KML return + * @param {Object} options An object with the following properties: + * @param {EntityCollection} options.entities The EntityCollection to export as KML. + * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for the output file. + * @param {exportKmlModelCallback} [options.modelCallback] A callback that will be called with a {@link ModelGraphics} instance and should return the URI to use in the KML. Required if a model exists in the entity collection. + * @param {JulianDate} [options.time=entities.computeAvailability().start] The time value to use to get properties that are not time varying in KML. + * @param {TimeInterval} [options.defaultAvailability=entities.computeAvailability()] The interval that will be sampled if an entity doesn't have an availability. + * @param {Number} [options.sampleDuration=60] The number of seconds to sample properties that are varying in KML. + * @param {false} [options.kmz=false] If false or unset, returns the KML file and referenced resources individually + * + * @returns {Promise} A promise that resolved to an object containing the KML string and a dictionary of external file Blobs + * + * @example + * Cesium.exportKml({ + * entities: entityCollection + * }) + * .then(function(result) { + * // The XML string is in result.kml + * + * var externalFiles = result.externalFiles + * for(var file in externalFiles) { + * // file is the name of the file used in the KML document as the href + * // externalFiles[file] is a Blob with the contents of the file + * } + * }); + */ /** * @typedef exportKmlResultKml @@ -236,17 +263,22 @@ IdManager.prototype.get = function (id) { */ /** - * Exports an EntityCollection as a KML document. Only Point, Billboard, Model, Path, Polygon, Polyline geometries - * will be exported. Note that there is not a 1 to 1 mapping of Entity properties to KML Feature properties. For - * example, entity properties that are time dynamic but cannot be dynamic in KML are exported with their values at - * options.time or the beginning of the EntityCollection's time interval if not specified. For time-dynamic properties - * that are supported in KML, we use the samples if it is a {@link SampledProperty} otherwise we sample the value using - * the options.sampleDuration. Point, Billboard, Model and Path geometries with time-dynamic positions will be exported - * as gx:Track Features. Not all Materials are representable in KML, so for more advanced Materials just the primary - * color is used. Canvas objects are exported as PNG images. + * Exports an EntityCollection as a KML document or KMZ archive. + * + * Only Point, Billboard, Model, Path, Polygon, Polyline geometries will be exported. + * Note that there is not a 1 to 1 mapping of Entity properties to KML Feature + * properties. For example, entity properties that are time dynamic but cannot + * be dynamic in KML are exported with their values at `options.time` or the + * beginning of the EntityCollection's time interval if not specified. For + * time-dynamic properties that are supported in KML, we use the samples if it + * is a {@link SampledProperty}, otherwise we sample the value using the + * `options.sampleDuration`. Point, Billboard, Model and Path geometries with + * time-dynamic positions will be exported as gx:Track Features. * - * @function exportKml + * Not all Materials are representable in KML, so for more advanced Materials + * just the primary color is used. Canvas objects are exported as PNG images. * + * @variation 1 KMZ return * @param {Object} options An object with the following properties: * @param {EntityCollection} options.entities The EntityCollection to export as KML. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for the output file. @@ -254,26 +286,20 @@ IdManager.prototype.get = function (id) { * @param {JulianDate} [options.time=entities.computeAvailability().start] The time value to use to get properties that are not time varying in KML. * @param {TimeInterval} [options.defaultAvailability=entities.computeAvailability()] The interval that will be sampled if an entity doesn't have an availability. * @param {Number} [options.sampleDuration=60] The number of seconds to sample properties that are varying in KML. - * @param {Boolean} [options.kmz=false] If true KML and external files will be compressed into a kmz file. + * @param {true} options.kmz If true, KML and external files will be compressed into a single KMZ file. + * + * @returns {Promise} A promise that resolves to a KMZ file as a Blob. * - * @returns {Promise} A promise that resolved to an object containing the KML string and a dictionary of external file blobs, or a kmz file as a blob if options.kmz is true. * @demo {@link https://sandcastle.cesium.com/index.html?src=Export%20KML.html|Cesium Sandcastle KML Export Demo} * @example * Cesium.exportKml({ - * entities: entityCollection - * }) - * .then(function(result) { - * // The XML string is in result.kml - * - * var externalFiles = result.externalFiles - * for(var file in externalFiles) { - * // file is the name of the file used in the KML document as the href - * // externalFiles[file] is a blob with the contents of the file - * } - * }); - * - */ -function exportKml(options) { + * entities: entityCollection, + * options: { kmz: true } + * }) + * .then(function(result) { + * downloadFile(result.kmz); + * }); + */ function exportKml(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); var entities = options.entities; var kmz = defaultValue(options.kmz, false); diff --git a/gulpfile.cjs b/gulpfile.cjs index 680f91e245aa..6ae2826018a3 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -1481,10 +1481,9 @@ function createCesiumJs() { function createTypeScriptDefinitions() { // Run jsdoc with tsd-jsdoc to generate an initial Cesium.d.ts file. - child_process.execSync( - "node_modules/.bin/jsdoc --configure Tools/jsdoc/ts-conf.json", - { stdio: "inherit" } - ); + child_process.execSync("npx jsdoc --configure Tools/jsdoc/ts-conf.json", { + stdio: "inherit", + }); var source = fs.readFileSync("Source/Cesium.d.ts").toString(); @@ -1568,6 +1567,11 @@ function createTypeScriptDefinitions() { .replace(//gm, "") .replace(//gm, "") .replace(//gm, "") + // This is an ugly hack but @template doesn't actually seem to work + .replace( + /export class Event {/gm, + "export class Event {" + ) .replace( /= "WebGLConstants\.(.+)"/gm, (match, p1) => `= WebGLConstants.${p1}` @@ -1580,9 +1584,19 @@ function createTypeScriptDefinitions() { /** * Private interfaces to support PropertyBag being a dictionary-like object. */ -interface DictionaryLike { - [index: string]: any; +interface PropertyDictionary { + [key: string]: Property | undefined; +} +class PropertyBagBase { + readonly propertyNames: string[]; + constructor(value?: object, createPropertyCallback?: Function); + addProperty(propertyName: string, value?: any, createPropertyCallback?: Function): void; + hasProperty(propertyName: string): boolean; + merge(source: Object, createPropertyCallback?: Function): void; + removeProperty(propertyName: string): void; } +/** This has to be in the workaround section because JSDoc doesn't support Intersection Types */ +type PropertyBagType = PropertyDictionary & Property & PropertyBagBase; ${source} } @@ -1608,7 +1622,7 @@ ${source} fs.writeFileSync("Source/Cesium.d.ts", source); // Use tsc to compile it and make sure it is valid - child_process.execSync("node_modules/.bin/tsc -p Tools/jsdoc/tsconfig.json", { + child_process.execSync("npx tsc -p Tools/jsdoc/tsconfig.json", { stdio: "inherit", });