├── .gitignore ├── .travis.yml ├── .vscode └── launch.json ├── CONFIGURATION.md ├── INTRODUCTION.md ├── README.md ├── configs ├── jsdoc.bad.json ├── jsdoc.cesium.json ├── jsdoc.json ├── jsdoc.misc.json └── jsdoc.ol.json ├── content ├── cesium_footer.ts ├── cesium_header.ts ├── ol_footer.ts └── ol_header.ts ├── examples ├── jsdoc3-examples │ ├── Book.js │ ├── BookMore.js │ ├── Empty.js │ ├── Namespace1.js │ ├── Simple1.js │ ├── Simple2.js │ ├── Simple3.js │ ├── alias1.js │ ├── alias2.js │ ├── alias3.js │ ├── borrows1.js │ ├── define1.js │ ├── define2.js │ ├── define3.js │ ├── define4.js │ ├── exports1.js │ ├── exports2.js │ ├── exports3.js │ ├── exports4.js │ ├── exports5.js │ ├── foo.js │ ├── html │ │ └── utils.js │ ├── jacket.js │ ├── lends1.js │ ├── lends2.js │ ├── lends3.js │ ├── lends4.js │ ├── mixes1.js │ ├── mixes2.js │ ├── module1.js │ ├── module2.js │ ├── module3.js │ ├── my │ │ └── shirt.js │ ├── namepaths1.js │ ├── namepaths2.js │ ├── namepaths3.js │ └── requires1.js └── misc │ ├── callback.js │ ├── generics.js │ ├── optionargs.js │ ├── optionproperty.js │ ├── parameters.js │ ├── record.js │ ├── reserved.js │ └── typedef.js ├── package.json ├── plugins ├── cesiumTags.js └── falcorFix.js ├── src ├── config.ts ├── entrypoint.ts ├── functypedefrewriter.ts ├── generics.pegjs ├── io.ts ├── jsdoc.d.ts ├── kinds.ts ├── moduleutils.ts ├── parser.ts ├── tsdgenerator.ts └── tsoutput.ts ├── test ├── cesium-tests.ts ├── ol-tests.ts └── openlayers-tests.ts ├── tools └── ol-postprocess.js ├── tsconfig.json ├── tsd.json ├── typings ├── cesium.baseline.d.ts ├── misc.baseline.d.ts ├── node │ └── node.d.ts ├── openlayers.baseline.d.ts └── tsd.d.ts └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /docs 3 | /build 4 | .vscode 5 | /test/*.js -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: yarn 3 | node_js: 4 | - "4.2" 5 | script: 6 | - yarn run test -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch", 6 | "type": "node", 7 | "request": "launch", 8 | "program": "${workspaceRoot}/node_modules/jsdoc/jsdoc.js", 9 | "stopOnEntry": false, 10 | "args": [ 11 | "-c", 12 | "${workspaceRoot}/jsdoc.misc.json", 13 | "-d", 14 | "${workspaceRoot}/docs/misc" 15 | ], 16 | "cwd": "${workspaceRoot}", 17 | "preLaunchTask": null, 18 | "runtimeExecutable": null, 19 | "runtimeArgs": [ 20 | "--nolazy" 21 | ], 22 | "env": { 23 | "NODE_ENV": "development" 24 | }, 25 | "externalConsole": false, 26 | "sourceMaps": true, 27 | "outDir": null 28 | }, 29 | { 30 | "name": "Attach", 31 | "type": "node", 32 | "request": "attach", 33 | "port": 5858, 34 | "address": "localhost", 35 | "restart": false, 36 | "sourceMaps": false, 37 | "outDir": null, 38 | "localRoot": "${workspaceRoot}", 39 | "remoteRoot": null 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /CONFIGURATION.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jumpinjackie/jsdoc-typescript-plugin/7ac5e8b4b32d549fafe9b3c8fbbc02da59882014/CONFIGURATION.md -------------------------------------------------------------------------------- /INTRODUCTION.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The behavior of the jsdoc-typescript-plugin can be configured via a `typescript` configuration section in your JSDoc configuration file 4 | 5 | For full configuration reference see [TBD] 6 | 7 | # Customization features 8 | 9 | In a perfect world, your meticulously written JSDoc should cleanly translate to TypeScript. 10 | 11 | In fact, should an invalid TypeScript definition be generated from your source by this plugin, it may reveal semantic and syntactic inconsistencies in your API documentation, so in a roundabout way this tool can also double as a validation tool for your JSDoc API documentation. 12 | 13 | So with that being said, these customization features should be considered as a *last resort*, where possible you should try to fix the API documentation in the original source first before falling back to using any of these features. 14 | 15 | ## Type replacement 16 | 17 | In the event that a reference to a type is emitted that actually has no definition due to spelling/typos, you can use the `typeReplacements` configuration property to specify a series of key/value pairs where the `key` is the type symbol to search for and the `value` is the type symbol to replace with. 18 | 19 | For example consider the following code fragment 20 | 21 | declare class Foo { 22 | /** 23 | * Returns the HTML image element for this instance 24 | */ 25 | getSource(): Image; // <====== Error: Cannot find name 'Image' 26 | } 27 | 28 | Let's say that the type `Image` could not be found by the plugin (because what you really meant was `HTMLImageElement`). Let's also say you cannot fix this particular signature due to not having commit 29 | access to the original canonical source repository to make this documentation/code fix. In such cases you can define a type replacement like so: 30 | 31 | "typescript": { 32 | "typeReplacements": { 33 | "Image": "HTMLImageElement" 34 | } 35 | } 36 | 37 | That will cause the emitted TypeScript signature for this function to become this: 38 | 39 | declare class Foo { 40 | /** 41 | * Returns the HTML image element for this instance 42 | */ 43 | getSource(): HTMLImageElement; 44 | } 45 | 46 | ## User-defined type injection 47 | 48 | Your library may inadvertently make references to external third party types that that library uses. Or similarly, your API documentation may make references to function/callback types that may not have the appropriate `@callback` or `@typedef` annotations 49 | 50 | If you generate a TypeScript definition from such a library, you will most likely get errors due to the plugin not being able to find a reference to this type to generate a type definition for it. 51 | 52 | declare class Foo { 53 | process(cb: CallbackFunc): void; // <====== Error: Cannot find name 'CallbackFunc' 54 | } 55 | 56 | In such cases you can use type injection to inject the missing types into the final TypeScript definition. There are two kinds of types you can inject: 57 | 58 | 1. Type aliases 59 | 2. Interfaces 60 | 61 | To fix the above example, you could add `CallbackFunc` as a user-defined type alias 62 | 63 | "typescript": { 64 | "aliases": { 65 | "global": { 66 | "CallbackFunc": "(args: string) => void" 67 | } 68 | } 69 | } 70 | 71 | Which will instruct the plugin to emit this declaration to resolve the unknown type: 72 | 73 | declare type CallbackFunc = (args: string) => void; 74 | 75 | ## User-defined type injection as a replacement mechanism 76 | 77 | If we take the above example again, but this time the `CallbackFunc` type exists, but is actually not defined to something we're expecting `(args: string) => void` 78 | 79 | In this case, we add the same user-defined type alias as before, but also you have to make sure to also add your user-defined 80 | type to the `ignore` list to ensure the plugin will skip over this type (giving your user-injected type precedence) when 81 | processing to avoid accidental double-ups of emitted types. 82 | 83 | "typescript": { 84 | "ignore": [ 85 | "CallbackFunc" 86 | ] 87 | } 88 | 89 | ## User-defined member overrides 90 | 91 | Sometimes, the erroneous TypeScript fragment is not at the type level, but at the type member level. 92 | 93 | For example, introducing class inheritance may reveal semantic inconsitencies in the generated output: 94 | 95 | ... 96 | 97 | declare class Foo { 98 | getSource(): FooSource; 99 | } 100 | declare class Bar extends Foo { 101 | getSource(): BarSource; // <====== Example error: 102 | } // Class 'Bar' incorrectly extends base class 103 | // 'Foo'. Types of property 'getSource' are 104 | // incompatible. 105 | 106 | 107 | In this case, you can avoid replacing the type entirely via the `memberReplacements` property and just replace the erroneous member with your own 108 | 109 | "typescript": { 110 | "memberReplacements": { 111 | "Bar#getSource": { 112 | "description": "Return the associated source (NOTE: TypeScript currently prevents us from returning the intended type of BarSource, you will have to manually cast the returned value to this type)", 113 | "declaration": "getSource(): any;" 114 | } 115 | } 116 | } 117 | 118 | This will "patch" the `getSource` method of `Bar` to be like this 119 | 120 | declare class Bar extends Foo { 121 | /** 122 | * Return the associated source (NOTE: TypeScript currently prevents us from returning the intended type of BarSource, you will have to manually cast the returned value to this type) 123 | */ 124 | getSource(): any; 125 | } 126 | 127 | ## Custom header/footer 128 | 129 | From the plugin's perspective, the anatomy of a TypeScript definition file that is generated is structured like so: 130 | 131 | mymodule.d.ts 132 | |-------------------------------------------| 133 | | Custom header content (if specified) | 134 | |-------------------------------------------| 135 | | Auto-generated TypeScript Definition body | 136 | |-------------------------------------------| 137 | | Custom footer content (if specified) | 138 | |-------------------------------------------| 139 | 140 | The header and footer sections can contain whatever arbitrary content you choose, as long as the final merged definition is a syntactically valid TypeScript definition file. 141 | 142 | You can can use this feature to provide fine-grained augmentations should the user-defined type injection prove unwieldy. Due to TypeScript supporting declaration merging, you do not have to worry about declaring the same module many times over. 143 | 144 | Note that the plugin currently has no way to determine the type of module we are trying to generate a d.ts for, nor does it know exactly what types are exportable (a question this author poses to you is: Is there a way?) 145 | 146 | You can use this feature to specify what parts of the generated TypeScript definition are to be exported onto the public API surface. 147 | 148 | # Closure library annotations 149 | 150 | If you use annotations provided by the [Closure Compiler](https://developers.google.com/closure/compiler/), the plugin can light up support for extra features that are not available through standard JSDoc annotations 151 | 152 | ## Generics 153 | 154 | If `@template` is found, the plugin will do the following: 155 | 156 | * If applied to a class, it will append the placeholder as part of the class name 157 | * If applied to a class member function, it will append the placeholder as part of the method signature 158 | 159 | For example, the following JS fragment: 160 | 161 | /** 162 | * @constructor 163 | * @classdesc 164 | * A generic class 165 | * @template T 166 | */ 167 | Foo = function() { }; 168 | 169 | /** 170 | * @description Another generic method 171 | * @template TArg 172 | * @param {T} arg The class generic type 173 | * @param {TArg} arg2 An argument of a generic type 174 | * @return {string} A string value 175 | */ 176 | Foo.prototype.setBar = function(arg, arg2) { }; 177 | 178 | Will emit the following TypeScript: 179 | 180 | /** 181 | * A generic class 182 | */ 183 | declare class Foo { 184 | /** 185 | * Another generic method 186 | * @param arg (Required) The class generic type 187 | * @param arg2 (Required) An argument of a generic type 188 | */ 189 | setBar(arg: T, arg2: TArg): string; 190 | } 191 | 192 | ## Function typedef rewriting 193 | 194 | Function types are normally defined using `@callback`. Such function types will properly translate to their TypeScript counterparts: 195 | 196 | //JavaScript 197 | /** 198 | * This callback is displayed as part of the Requester class. 199 | * @callback CallbackFunc 200 | * @param {number} responseCode 201 | * @param {string} responseMessage 202 | * @return {boolean} 203 | */ 204 | 205 | //TypeScript 206 | /** 207 | * This callback is displayed as part of the Requester class. 208 | */ 209 | declare type CallbackFunc = (responseCode: number, responseMessage: string) => boolean; 210 | 211 | However, the use of `@callback` is not recognised by the Closure compiler, which expects such function types to be annotated with `@typedef` like so: 212 | 213 | /** 214 | * A function that takes a string and returns a number 215 | * @typedef {function(string): number} 216 | */ 217 | var FooFunction; 218 | 219 | By default, such typedefs will be aliased to plain `Function` 220 | 221 | /** 222 | * A function that takes a string and returns a number 223 | */ 224 | declare type FooFunction = Function; 225 | 226 | Setting the `rewriteFunctionTypedefs` property to `true` will activate function typedef rewriting, which will add an extra processor in the 227 | JSDoc pipeline to rewrite function typedef doclets into a callback form, that allows the plugin to emit function typedefs like this: 228 | 229 | /** 230 | * A function that takes a string and returns a number 231 | */ 232 | declare type FooFunction = (arg0: string) => number; 233 | 234 | Notice the `arg0` name. Because function typedefs do not carry argument descriptions we use a generic `arg0..n` naming format for any arguments encountered. So 235 | where possible, `@callback` is strongly preferred over `@typedef` for documenting function types. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # No longer maintained 2 | 3 | When I started this project, I had the lofty goal of a generic `d.ts` typings generator that works off of JSDoc annotations for *any* plain JS project. 4 | 5 | In reality, this project had a singular purpose: To generate a 100% coverage TypeScript definition file for the [OpenLayers](https://openlayers.org/) library. This project had fulfilled this singular purpose very well up to the latest 4.x release (4.6.5). 6 | 7 | OpenLayers afterwards had changed their module structure to the point that this plugin no longer was able to generate a suitable TypeScript definition. Given there are competing efforts that have made better inroads than I have in this regard, I am no longer maintaining this project and have archived this repository. 8 | 9 | If you are after TypeScript support for OpenLayers 5.x and newer, see: 10 | 11 | * [https://github.com/hanreev/types-ol](https://github.com/hanreev/types-ol) 12 | * [The tracking issue for official TypeScript support](https://github.com/openlayers/openlayers/issues/8120) 13 | 14 | Otherwise, feel free to fork this repo and see what you can do with the code. Good luck! 15 | 16 | # jsdoc-typescript-plugin 17 | 18 | [![Build Status](https://travis-ci.org/jumpinjackie/jsdoc-typescript-plugin.svg)](https://travis-ci.org/jumpinjackie/jsdoc-typescript-plugin) 19 | 20 | JSDoc plugin to automatically generate TypeScript Definitions from annotated source 21 | 22 | # Building 23 | 24 | npm install 25 | npm run-script tsc 26 | 27 | The compiled plugin will reside under `plugins/typescript.js` 28 | 29 | # Using the plugin 30 | 31 | Add the following snippet to your JSDoc configuration 32 | 33 | ```json 34 | { "plugins": [ "plugins/typescript" ] } 35 | ``` 36 | 37 | Refer to configuration for plugin configuration options 38 | 39 | # Configuration 40 | 41 | TBD 42 | -------------------------------------------------------------------------------- /configs/jsdoc.bad.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "includePattern": ".+\\.js(doc)?$", 4 | "excludePattern": "(^|\\/|\\\\)_", 5 | "include": [ 6 | "examples/bad" 7 | ] 8 | }, 9 | "plugins": ["plugins/typescript"], 10 | "typescript": { 11 | "rootModuleName": "bad", 12 | "outDir": "./typings", 13 | "rewriteFunctionTypedefs": true 14 | }, 15 | "templates": { 16 | "default": { 17 | "outputSourceFiles": true, 18 | "outputSourceReference": true 19 | } 20 | }, 21 | "opts": { 22 | "recurse": true, 23 | "explain": false 24 | } 25 | } -------------------------------------------------------------------------------- /configs/jsdoc.cesium.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "includePattern": ".+\\.js(doc)?$", 4 | "excludePattern": "(^|\\/|\\\\)_", 5 | "include": [ 6 | "node_modules/cesium/Source" 7 | ], 8 | "exclude": [ 9 | "node_modules/cesium/Source/ThirdParty", 10 | "node_modules/cesium/Source/Workers/cesiumWorkerBootstrapper.js" 11 | ] 12 | }, 13 | "plugins": [ 14 | "plugins/cesiumTags", 15 | "plugins/typescript" 16 | ], 17 | "typescript": { 18 | "rootModuleName": "cesium", 19 | "outDir": "./typings", 20 | "outputDocletDefs": false, 21 | "fillUndocumentedDoclets": true, 22 | "defaultReturnType": "void", 23 | "rewriteFunctionTypedefs": true, 24 | "headerFile": "./content/cesium_header.ts", 25 | "footerFile": "./content/cesium_footer.ts", 26 | "declareTopLevelElements": false, 27 | "initialIndentation": 1, 28 | "processAsEnums": { 29 | "classes": { 30 | "BingMapsStyle": "string", 31 | "BlendEquation": "number", 32 | "BlendFunction": "number", 33 | "CameraEventType": "number", 34 | "ClockRange": "number", 35 | "ClockStep": "number", 36 | "Color": "Color", 37 | "ComponentDatatype": "number", 38 | "CornerType": "number", 39 | "CullFace": "number", 40 | "DepthFunction": "number", 41 | "EasingFunction": "EasingFunction.Callback", 42 | "ExtrapolationType": "number", 43 | "HeightReference": "number", 44 | "HorizontalOrigin": "number", 45 | "IndexDatatype": "number", 46 | "InterpolationAlgorithm": "number", 47 | "Intersect": "number", 48 | "KeyboardEventModifier": "number", 49 | "LabelStyle": "number", 50 | "MapMode2D": "number", 51 | "MaterialAppearance.MaterialSupport": "number", 52 | "ModelAnimationLoop": "number", 53 | "PixelFormat": "number", 54 | "PrimitiveType": "number", 55 | "ReferenceFrame": "number", 56 | "RenderState": "number", 57 | "SceneMode": "number", 58 | "ScreenSpaceEventType": "number", 59 | "ShadowMode": "number", 60 | "StencilFunction": "number", 61 | "StencilOperation": "number", 62 | "TimeStandard": "number", 63 | "VerticalOrigin": "number", 64 | "Visibility": "number", 65 | "WindingOrder": "number" 66 | } 67 | }, 68 | "ignoreTypes": [ 69 | "TextureAtlas~CreateImageCallback" 70 | ], 71 | "memberReplacements": { 72 | "RectangleGeometryUpdater#createDynamicUpdater": { 73 | "_reason": "Documentation Error. Duplicate parameter names in source", 74 | "description": "Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.", 75 | "declaration": "createDynamicUpdater(primitives: PrimitiveCollection, groundPrimitives: PrimitiveCollection): DynamicGeometryUpdater;" 76 | }, 77 | "GroundPrimitive.initializeTerrainHeights": { 78 | "_reason": "Documentation Error. Promise is generic and promised type is not specified", 79 | "description": "Initializes the minimum and maximum terrain heights. This only needs to be called if you are creating the GroundPrimitive asynchronously.", 80 | "declaration": "static initializeTerrainHeights(): Promise;" 81 | } 82 | }, 83 | "ignoreModules": [ 84 | "" 85 | ], 86 | "globalModuleAliases": [ 87 | "" 88 | ], 89 | "typeReplacements": { 90 | "Cartesian": "(Cartesian2|Cartesian3|Cartesian4)", 91 | "Image": "HTMLImageElement", 92 | "Canvas": "HTMLCanvasElement", 93 | "String": "string", 94 | "Number": "number", 95 | "Any": "any" 96 | }, 97 | "classTypeAugmentations": { 98 | "GeoJsonDataSource": { 99 | "extends": "DataSource" 100 | }, 101 | "KmlDataSource": { 102 | "extends": "DataSource" 103 | }, 104 | "CzmlDataSource": { 105 | "extends": "DataSource" 106 | }, 107 | "CustomDataSource": { 108 | "extends": "DataSource" 109 | } 110 | } 111 | }, 112 | "templates": { 113 | "default": { 114 | "outputSourceFiles": true, 115 | "outputSourceReference": true 116 | } 117 | }, 118 | "opts": { 119 | "recurse": true, 120 | "explain": false 121 | } 122 | } -------------------------------------------------------------------------------- /configs/jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "includePattern": ".+\\.js(doc)?$", 4 | "excludePattern": "(^|\\/|\\\\)_" 5 | }, 6 | "plugins": ["plugins/typescript"], 7 | "typescript": { 8 | "rootModuleName": "jsdoc3-examples", 9 | "outDir": "./typings" 10 | }, 11 | "templates": { 12 | "default": { 13 | "outputSourceFiles": true, 14 | "outputSourceReference": true 15 | } 16 | }, 17 | "opts": { 18 | "recurse": true, 19 | "explain": false 20 | } 21 | } -------------------------------------------------------------------------------- /configs/jsdoc.misc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "includePattern": ".+\\.js(doc)?$", 4 | "excludePattern": "(^|\\/|\\\\)_", 5 | "include": [ 6 | "examples/misc" 7 | ] 8 | }, 9 | "plugins": ["plugins/typescript"], 10 | "typescript": { 11 | "rootModuleName": "misc", 12 | "outDir": "./typings", 13 | "outputDocletDefs": false, 14 | "rewriteFunctionTypedefs": true, 15 | "useUnionTypeForStringEnum": true 16 | }, 17 | "templates": { 18 | "default": { 19 | "outputSourceFiles": true, 20 | "outputSourceReference": true 21 | } 22 | }, 23 | "opts": { 24 | "recurse": true, 25 | "explain": false 26 | } 27 | } -------------------------------------------------------------------------------- /configs/jsdoc.ol.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "includePattern": ".+\\.js(doc)?$", 4 | "excludePattern": "(^|\\/|\\\\)_", 5 | "include": [ 6 | "node_modules/openlayers/src", 7 | "node_modules/openlayers/externs/oli.js", 8 | "node_modules/openlayers/externs/olx.js" 9 | ] 10 | }, 11 | "plugins": [ 12 | "plugins/typescript", 13 | "node_modules/openlayers/config/jsdoc/api/plugins/inheritdoc", 14 | "node_modules/openlayers/config/jsdoc/api/plugins/typedefs", 15 | "node_modules/openlayers/config/jsdoc/api/plugins/events", 16 | "node_modules/openlayers/config/jsdoc/api/plugins/observable" 17 | ], 18 | "typescript": { 19 | "rootModuleName": "openlayers", 20 | "outDir": "./typings", 21 | "outputDocletDefs": false, 22 | "fillUndocumentedDoclets": true, 23 | "rewriteFunctionTypedefs": true, 24 | "ignoreTypes": [ 25 | "ol.Color", 26 | "ol.Size", 27 | "ol.Pixel", 28 | "ol.Coordinate", 29 | "ol.TileCoord", 30 | "ol.Extent" 31 | ], 32 | "makePublic": [], 33 | "aliases": { 34 | "global": { 35 | "Proj4": "any", 36 | "EsriJSONGeometry": "any", 37 | "GeoJSONFeature": "any", 38 | "GeoJSONFeatureCollection": "any", 39 | "GeoJSONGeometry": "any", 40 | "GeoJSONGeometryCollection": "any", 41 | "TileJSON": "any" 42 | }, 43 | "module": {} 44 | }, 45 | "interfaces": {}, 46 | "typeReplacements": { 47 | "Image": "HTMLImageElement" 48 | }, 49 | "publicAnnotation": "api", 50 | "defaultReturnType": "void", 51 | "headerFile": "./content/ol_header.ts", 52 | "footerFile": "./content/ol_footer.ts", 53 | "skipUndocumentedDoclets": false, 54 | "useUnionTypeForStringEnum": false, 55 | "dumpPublicTypesTo": "./typings/ol-public.json", 56 | "memberReplacements": { 57 | "ol.layer.VectorTile#getSource": { 58 | "description": "Return the associated source of the layer (NOTE: TypeScript currently prevents us from returning the intended type of ol.source.VectorTile, you will have to manually cast the returned value to this type)", 59 | "declaration": "getSource(): any;" 60 | } 61 | } 62 | }, 63 | "templates": { 64 | "default": { 65 | "outputSourceFiles": true, 66 | "outputSourceReference": true 67 | } 68 | }, 69 | "opts": { 70 | "recurse": true, 71 | "explain": false 72 | } 73 | } -------------------------------------------------------------------------------- /content/cesium_footer.ts: -------------------------------------------------------------------------------- 1 | 2 | } 3 | 4 | declare module "cesium" { 5 | export = Cesium; 6 | } -------------------------------------------------------------------------------- /content/cesium_header.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Cesium v1.27 2 | // Project: https://cesiumjs.org 3 | // Definitions by: Jackie Ng 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | // 7 | // This file is automatically generated by jsdoc-typescript-plugin (https://github.com/jumpinjackie/jsdoc-typescript-plugin). 8 | // 9 | // Do not edit this file unless you know what you're doing. Where possible, consult the plugin documentation for options to 10 | // augment and customize the content of this generated file 11 | // 12 | 13 | declare module Cesium { 14 | 15 | type CanvasPixelArray = any[]; 16 | 17 | /** 18 | * Cesium's internal copy of knockout.js 19 | */ 20 | const knockout: any; //TODO: Should probably link to knockout d.ts 21 | /** 22 | * Cesium's internal copy of when.js 23 | */ 24 | const when: any; //TODO: If there's a typings for this, we should be linking against it 25 | 26 | /** 27 | * Type alias for a promise 28 | */ 29 | type Promise = PromiseLike; 30 | 31 | type TypedArray = any[]; 32 | 33 | type Packable = any; 34 | 35 | type Proxy = any; 36 | 37 | type Context = any; 38 | 39 | type Frustum = any; 40 | 41 | type DrawCommand = any; 42 | 43 | // ========== These types are not supposed to be public, but the plugin is leaking them out at the moment ========== // 44 | 45 | type BufferUsage = any; 46 | 47 | type VertexBuffer = any; 48 | 49 | type IndexBuffer = any; 50 | 51 | type ShaderProgram = any; 52 | 53 | type ShaderSource = any; 54 | 55 | type IauOrientationParameters = any; 56 | 57 | type HMDVRDevice = any; 58 | 59 | type Rotation = any; 60 | 61 | type Framebuffer = any; 62 | 63 | type ClearCommand = any; 64 | 65 | type VertexArray = any; 66 | 67 | type Texture = any; 68 | 69 | type Pass = any; 70 | 71 | type CubeMap = any; 72 | 73 | type MipmapHint = any; 74 | 75 | type PassState = any; 76 | 77 | type Tile = any; 78 | 79 | type TileReplacementQueue = any; -------------------------------------------------------------------------------- /content/ol_footer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Monolithic module export 3 | */ 4 | declare module "openlayers" { 5 | export = ol; 6 | } -------------------------------------------------------------------------------- /content/ol_header.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for OpenLayers v4.6.2 2 | // Project: http://openlayers.org/ 3 | // Definitions by: Jackie Ng 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | // 7 | // This file is automatically generated by jsdoc-typescript-plugin (https://github.com/jumpinjackie/jsdoc-typescript-plugin). 8 | // 9 | // Do not edit this file unless you know what you're doing. Where possible, consult the plugin documentation for options to 10 | // augment and customize the content of this generated file 11 | // 12 | 13 | /** 14 | * This is an alias for the HTML5 geolocation position options 15 | */ 16 | type GeolocationPositionOptions = PositionOptions; 17 | 18 | // These types normally resolve to number[] by the plugin, which is fine, but TypeScript lets us define 19 | // tuple types (ie. Arrays of specific size and item types) which is much more expressive 20 | // and clearer than what the plugin generates 21 | // 22 | // For example, instead of number[] for ol.Coordinate, we can express this as [number, number], ie. A 23 | // 2-item array of numbers, which is more clearer as it communicates the maximum number of allowed elements 24 | // that number[] does not 25 | // 26 | // We have to define these types manually, as there is no JSDoc analogue for this plugin to translate from 27 | 28 | declare module ol { 29 | /** 30 | * A color represented as a short array [red, green, blue, alpha]. 31 | * red, green, and blue should be integers in the range 0..255 inclusive. 32 | * alpha should be a float in the range 0..1 inclusive. If no alpha value is 33 | * given then `1` will be used. 34 | */ 35 | type Color = [number, number, number, number]; 36 | /** 37 | * An array of numbers representing an xy coordinate. Example: `[16, 48]`. 38 | */ 39 | type Coordinate = [number, number]; 40 | /** 41 | * An array of numbers representing an extent: `[minx, miny, maxx, maxy]`. 42 | */ 43 | type Extent = [number, number, number, number]; 44 | /** 45 | * An array with two elements, representing a pixel. The first element is the 46 | * x-coordinate, the second the y-coordinate of the pixel. 47 | */ 48 | type Pixel = [number, number]; 49 | /** 50 | * An array of numbers representing a size: `[width, height]`. 51 | */ 52 | type Size = [number, number]; 53 | /** 54 | * An array of three numbers representing the location of a tile in a tile 55 | * grid. The order is `z`, `x`, and `y`. `z` is the zoom level. 56 | */ 57 | type TileCoord = [number, number, number]; 58 | } -------------------------------------------------------------------------------- /examples/jsdoc3-examples/Book.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/about-getting-started.html 2 | //Use a documentation tag to describe your code. 3 | /** 4 | * Represents a book. 5 | * @constructor 6 | */ 7 | function Book(title, author) { 8 | } 9 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/BookMore.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/about-getting-started.html 2 | //Adding more information with tags. 3 | /** 4 | * Represents a book. 5 | * @constructor 6 | * @param {string} title - The title of the book. 7 | * @param {string} author - The author of the book. 8 | */ 9 | function BookMore(title, author) { 10 | } 11 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/Empty.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jumpinjackie/jsdoc-typescript-plugin/7ac5e8b4b32d549fafe9b3c8fbbc02da59882014/examples/jsdoc3-examples/Empty.js -------------------------------------------------------------------------------- /examples/jsdoc3-examples/Namespace1.js: -------------------------------------------------------------------------------- 1 | /** @namespace */ 2 | var Namespace1; 3 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/Simple1.js: -------------------------------------------------------------------------------- 1 | var Simple1; 2 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/Simple2.js: -------------------------------------------------------------------------------- 1 | /***/ 2 | var Simple2; 3 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/Simple3.js: -------------------------------------------------------------------------------- 1 | /** Simple3 */ 2 | var Simple3; 3 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/alias1.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/tags-alias.html 2 | //Using @alias with an anonymous constructor function 3 | 4 | Klass('trackr.CookieManager', 5 | 6 | /** 7 | * @class 8 | * @alias trackr.CookieManager 9 | * @param {Object} kv 10 | */ 11 | function(kv) { 12 | /** The value. */ 13 | this.value = kv; 14 | } 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/alias2.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/tags-alias.html 2 | //Using @alias for static members of a namespace 3 | 4 | /** @namespace */ 5 | var Alias2Apple = {}; 6 | 7 | (function(ns) { 8 | /** 9 | * @namespace 10 | * @alias Alias2Apple.Core 11 | */ 12 | var core = {}; 13 | 14 | /** Documented as Alias2Apple.Core.seed */ 15 | core.seed = function() {}; 16 | 17 | ns.Core = core; 18 | })(Alias2Apple); 19 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/alias3.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/tags-alias.html 2 | //Using @alias for an object literal 3 | 4 | // Documenting Alias3objectA with @alias 5 | 6 | var Alias3objectA = (function() { 7 | 8 | /** 9 | * Documented as Alias3objectA 10 | * @alias Alias3objectA 11 | * @namespace 12 | */ 13 | var x = { 14 | /** 15 | * Documented as Alias3objectA.myProperty 16 | * @member 17 | */ 18 | myProperty: 'foo' 19 | }; 20 | 21 | return x; 22 | })(); 23 | 24 | // Documenting Alias3objectB with @lends 25 | 26 | /** 27 | * Documented as Alias3objectB 28 | * @namespace 29 | */ 30 | var Alias3objectB = (function() { 31 | 32 | /** @lends Alias3objectB */ 33 | var x = { 34 | /** 35 | * Documented as Alias3objectB.myProperty 36 | * @member 37 | */ 38 | myProperty: 'bar' 39 | }; 40 | 41 | return x; 42 | })(); 43 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/borrows1.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-borrows.html 2 | //Duplicate the documentation for trstr as util.trim 3 | 4 | /** 5 | * @namespace 6 | * @borrows trstr as trim 7 | */ 8 | var borrows1util = { 9 | trim: trstr 10 | }; 11 | 12 | /** 13 | * Remove whitespace from around a string. 14 | * @param {string} str 15 | */ 16 | function trstr(str) { 17 | } 18 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/define1.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | }); -------------------------------------------------------------------------------- /examples/jsdoc3-examples/define2.js: -------------------------------------------------------------------------------- 1 | /** @exports define2 */ 2 | define(function () { 3 | }); -------------------------------------------------------------------------------- /examples/jsdoc3-examples/define3.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | /** @exports define3 */ 3 | }); -------------------------------------------------------------------------------- /examples/jsdoc3-examples/define4.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | /** @exports define4 */ 3 | var define4; 4 | }); -------------------------------------------------------------------------------- /examples/jsdoc3-examples/exports1.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-exports.html 2 | //CommonJS module 3 | /** 4 | * A module that says hello! 5 | * @module hello/world 6 | */ 7 | 8 | /** Say hello. */ 9 | exports.sayHello = function() { 10 | return 'Hello world'; 11 | }; 12 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/exports2.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-exports.html 2 | //Node.js module 3 | /** 4 | * A module that shouts hello! 5 | * @module hello/world2 6 | */ 7 | 8 | /** SAY HELLO. */ 9 | module.exports = function() { 10 | return "HELLO WORLD"; 11 | }; 12 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/exports3.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-exports.html 2 | //AMD module that exports an object literal 3 | define(function() { 4 | 5 | /** 6 | * A module that whispers hello! 7 | * @module hello/world3 8 | */ 9 | var exports = {}; 10 | 11 | /** say hello. */ 12 | exports.sayHello = function() { 13 | return 'hello world'; 14 | }; 15 | 16 | return exports; 17 | }); 18 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/exports4.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-exports.html 2 | //AMD module that exports a constructor 3 | define(function() { 4 | /** 5 | * A module that creates greeters. 6 | * @module greeter 7 | */ 8 | 9 | /** 10 | * @constructor 11 | * @param {string} subject - The subject to greet. 12 | */ 13 | var exports = function(subject) { 14 | this.subject = subject || 'world'; 15 | }; 16 | 17 | /** Say hello to the subject. */ 18 | exports.prototype.sayHello = function() { 19 | return 'Hello ' + this.subject; 20 | }; 21 | 22 | return exports; 23 | }); 24 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/exports5.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-exports.html 2 | //AMD module that exports an object 3 | define(function () { 4 | 5 | /** 6 | * A module that says hello! 7 | * @exports hello/world5 8 | */ 9 | var ns = {}; 10 | 11 | /** Say hello. */ 12 | ns.sayHello = function() { 13 | return 'Hello world'; 14 | }; 15 | 16 | return ns; 17 | }); 18 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/foo.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/about-getting-started.html 2 | //The simplest documentation is just a description. 3 | /** This is a description of the foo function. */ 4 | function foo() { 5 | } 6 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/html/utils.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/howto-commonjs-modules.html 2 | //Document Multiple RequireJS Modules Defined in a Single File 3 | //If you have multiple calls to define in a single file use the @exports tag to document each function that returns module code. Name the exported objects "exports" and JSDoc 3 will automatically document any of their members as members of their module. 4 | //The getStyleProperty and isInHead methods are documented as members of the "html/utils" module. The Tag class is documented as a member of the "tag" module. 5 | // one module 6 | define('html/utils', 7 | /** 8 | * Utility functions to ease working with DOM elements. 9 | * @exports html/utils 10 | */ 11 | function() { 12 | var exports = { 13 | /** Get the value of a property on an element. */ 14 | getStyleProperty: function(element, propertyName) { } 15 | }; 16 | 17 | /** Determine if an element is in the document head. */ 18 | exports.isInHead = function(element) { } 19 | 20 | return exports; 21 | } 22 | ); 23 | 24 | // another module 25 | define('tag', 26 | /** @exports tag */ 27 | function() { 28 | var exports = { 29 | /** @class */ 30 | Tag: function(tagName) { } 31 | }; 32 | 33 | return exports; 34 | } 35 | ); 36 | 37 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/jacket.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/howto-commonjs-modules.html 2 | //Document a Module as a Constructor 3 | //The following examples illustrate patterns for documenting modules that are constructors. 4 | //Use the @alias tag simplify documenting a constructor-module in RequireJS. 5 | /** 6 | * A module representing a jacket. 7 | * @module jacket 8 | */ 9 | define('jacket', function () { 10 | /** 11 | * @constructor 12 | * @alias module:jacket 13 | */ 14 | var exports = function() { 15 | } 16 | 17 | /** Open and close your Jacket. */ 18 | exports.prototype.zip = function() { 19 | } 20 | 21 | return exports; 22 | }); 23 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/lends1.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-lends.html 2 | //Example class 3 | 4 | // We want to document this as being a class 5 | var Lends1Person = makeClass( 6 | // We want to document these as being methods 7 | { 8 | initialize: function(name) { 9 | this.name = name; 10 | }, 11 | say: function(message) { 12 | return this.name + " says: " + message; 13 | } 14 | } 15 | ); 16 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/lends2.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-lends.html 2 | //Documented as static methods 3 | 4 | /** @class */ 5 | var Lends2Person = makeClass( 6 | /** @lends Lends2Person */ 7 | { 8 | initialize: function(name) { 9 | this.name = name; 10 | }, 11 | say: function(message) { 12 | return this.name + " says: " + message; 13 | } 14 | } 15 | ); 16 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/lends3.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-lends.html 2 | //Documented as instance methods 3 | 4 | /** @class */ 5 | var Lends3Person = makeClass( 6 | /** @lends Lends3Person.prototype */ 7 | { 8 | initialize: function(name) { 9 | this.name = name; 10 | }, 11 | say: function(message) { 12 | return this.name + " says: " + message; 13 | } 14 | } 15 | ); 16 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/lends4.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-lends.html 2 | //Documented with a constructor 3 | 4 | var Lends4Person = makeClass( 5 | /** @lends Lends4Person.prototype */ 6 | { 7 | /** @constructs */ 8 | initialize: function(name) { 9 | this.name = name; 10 | }, 11 | say: function(message) { 12 | return this.name + " says: " + message; 13 | } 14 | } 15 | ); 16 | 17 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/mixes1.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-mixes.html 2 | //Example of a @mixin 3 | 4 | /** 5 | * This provides methods used for event handling. It's not meant to 6 | * be used directly. 7 | * 8 | * @mixin 9 | */ 10 | var Mixes1Eventful = { 11 | /** 12 | * Register a handler function to be called whenever this event is fired. 13 | * @param {string} eventName - Name of the event. 14 | * @param {function(Object)} handler - The handler to call. 15 | */ 16 | on: function(eventName, handler) { 17 | // code... 18 | }, 19 | 20 | /** 21 | * Fire an event, causing all handlers for that event name to run. 22 | * @param {string} eventName - Name of the event. 23 | * @param {Object} eventData - The data provided to each handler. 24 | */ 25 | fire: function(eventName, eventData) { 26 | // code... 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/mixes2.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-mixes.html 2 | //Using the @mixes tag 3 | 4 | /** 5 | * @constructor Mixes2FormButton 6 | * @mixes Mixes1Eventful 7 | */ 8 | var Mixes2FormButton = function() { 9 | // code... 10 | }; 11 | Mixes2FormButton.prototype.press = function() { 12 | this.fire('press', {}); 13 | } 14 | mix(Mixes1Eventful).into(Mixes2FormButton.prototype); 15 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/module1.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-module.html 2 | //Basic @module use 3 | 4 | /** @module myModule */ 5 | 6 | /** will be module:myModule~foo */ 7 | var foo = 1; 8 | 9 | /** will be module:myModule.bar */ 10 | var bar = function() {}; 11 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/module2.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-module.html 2 | //Defining exported symbols as a member of 'this' 3 | 4 | /** @module bookshelf */ 5 | /** @class */ 6 | this.Book = function (title) { 7 | /** The title. */ 8 | this.title = title; 9 | }; 10 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/module3.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-module.html 2 | //Defining exported symbols as a member of 'module.exports' or 'exports' 3 | 4 | /** @module color/mixer */ 5 | module.exports = { 6 | /** Blend two colours together. */ 7 | blend: function (color1, color2) {} 8 | }; 9 | /** Darkens a color. */ 10 | exports.darken = function (color, shade) {}; 11 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/my/shirt.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/howto-commonjs-modules.html 2 | //Document a Function that returns a RequireJS Module 3 | //The RequireJS library provides a define method that allows you to write a function to return a module object. Use the @exports tag to document that all the members of an object literal should be documented as members of a module. 4 | //The color property and the Turtleneck class are documented as members of the "my/shirt" module. 5 | define('my/shirt', function () { 6 | /** 7 | * A module representing a shirt. 8 | * @exports my/shirt 9 | * @version 1.0 10 | */ 11 | var shirt = { 12 | 13 | /** A property of the module. */ 14 | color: "black", 15 | 16 | /** @constructor */ 17 | Turtleneck: function(size) { 18 | /** A property of the class. */ 19 | this.size = size; 20 | } 21 | }; 22 | 23 | return shirt; 24 | }); 25 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/namepaths1.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/about-namepaths.html 2 | //Use a documentation tag to describe your code. 3 | /** @constructor */ 4 | namepath1Person = function() { 5 | this.say = function() { 6 | return "I'm an instance."; 7 | } 8 | 9 | function say() { 10 | return "I'm inner."; 11 | } 12 | } 13 | namepath1Person.say = function() { 14 | return "I'm static."; 15 | } 16 | 17 | var p = new namepath1Person(); 18 | p.say(); // I'm an instance. 19 | namepath1Person.say(); // I'm static. 20 | // there is no way to directly access the inner function from here 21 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/namepaths2.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/about-namepaths.html 2 | //Use a documentation tag to describe your code. 3 | /** @constructor */ 4 | namepath2Person = function() { 5 | /** @constructor */ 6 | this.Idea = function() { 7 | this.consider = function(){ 8 | return "hmmm"; 9 | } 10 | } 11 | } 12 | 13 | var p = new namepath2Person(); 14 | var i = new p.Idea(); 15 | i.consider(); 16 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/namepaths3.js: -------------------------------------------------------------------------------- 1 | //http://usejsdoc.org/about-namepaths.html 2 | //Namepaths of objects with special characters in the name. 3 | /** @namespace */ 4 | var namepath3chat = { 5 | /** 6 | * Refer to this by {@link namepath3."#channel"}. 7 | * @namespace 8 | */ 9 | "#channel": { 10 | /** 11 | * Refer to this by {@link namepath3."#channel".open}. 12 | * @type {boolean} 13 | * @defaultvalue 14 | */ 15 | open: true, 16 | /** 17 | * Internal quotes have to be escaped by backslash. This is 18 | * {@link namepath3."#channel"."say-\"hello\""}. 19 | */ 20 | 'say-"hello"': function (msg) {} 21 | } 22 | }; 23 | 24 | /** 25 | * Now we define an event in our {@link namepath3."#channel"} namespace. 26 | * @event namepath3."#channel"."op:announce-motd" 27 | */ 28 | -------------------------------------------------------------------------------- /examples/jsdoc3-examples/requires1.js: -------------------------------------------------------------------------------- 1 | // http://usejsdoc.org/tags-requires.html 2 | //Using the @requires tag 3 | 4 | /** 5 | * This class requires the modules {@link module:xyzcorp/helper} and 6 | * {@link module:xyzcorp/helper.ShinyWidget#polish}. 7 | * @class 8 | * @requires module:xyzcorp/helper 9 | * @requires xyzcorp/helper.ShinyWidget#polish 10 | */ 11 | function Requires1Widgetizer() {} 12 | -------------------------------------------------------------------------------- /examples/misc/callback.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This callback is displayed as part of the Requester class. 3 | * @callback CallbackFunc 4 | * @param {number} responseCode 5 | * @param {string} responseMessage 6 | * @return {boolean} 7 | */ 8 | 9 | /** 10 | * A callback that takes no arguments returns a boolean 11 | * @callback NoArgBooleanFunc 12 | * @return {boolean} 13 | */ -------------------------------------------------------------------------------- /examples/misc/generics.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | */ 4 | SomeType = function() { }; 5 | 6 | /** 7 | * @constructor 8 | */ 9 | SomeOtherType = function() { }; 10 | 11 | /** 12 | * @constructor 13 | * @classdesc 14 | * A generic class 15 | * @template T 16 | */ 17 | Foo = function() { }; 18 | 19 | /** 20 | * @description A generic method 21 | * @template TArg 22 | * @param {TArg} arg An argument of a generic type 23 | * @return {string} A string value 24 | */ 25 | Foo.prototype.bar = function(arg) { return "foo"; }; 26 | 27 | /** 28 | * @description Another generic method 29 | * @template TArg 30 | * @param {T} arg The class generic type 31 | * @param {TArg} arg2 An argument of a generic type 32 | * @return {string} A string value 33 | */ 34 | Foo.prototype.setBar = function(arg, arg2) { }; 35 | 36 | /** 37 | * @description Yet another generic method 38 | * @return {T} THe class generic type 39 | */ 40 | Foo.prototype.getBar = function() { return null; }; 41 | 42 | /** 43 | * @return {Foo.} 44 | */ 45 | function returnFoo() { 46 | return null; 47 | } 48 | 49 | /** 50 | * @return {Foo.} 51 | */ 52 | function returnFoo2() { 53 | return null; 54 | } -------------------------------------------------------------------------------- /examples/misc/optionargs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | * @classdesc 4 | * A class that takes an options argument 5 | * @param {Object} options Object with the following properties: 6 | * @param {String} options.url The URL of the service. 7 | * @param {String} [options.token] The authorization token to use to connect to the service. 8 | * @param {Object} [options.proxy] A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed. 9 | * @param {String=} options.arg An optional string argument 10 | */ 11 | Optionable = function(options) { }; 12 | 13 | /** 14 | * @constructor 15 | * @classdesc 16 | * A class that takes an options argument 17 | * @param {String} options.url The URL of the service. 18 | * @param {String} [options.token] The authorization token to use to connect to the service. 19 | * @param {Object} [options.proxy] A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed. 20 | * @param {String=} options.arg An optional string argument 21 | */ 22 | ImproperlyDocumentedOptionable = function(options) { }; 23 | 24 | /** 25 | * @constructor 26 | * @classdesc 27 | * A class that takes an options array argument 28 | * @param {Object[]} employees - The employees who are responsible for the project. 29 | * @param {string} employees[].name - The name of an employee. 30 | * @param {string} employees[].department - The employee's department. 31 | */ 32 | ArrayOptionable = function(employees) { 33 | // ... 34 | }; 35 | 36 | /** 37 | * Lorem ipsum 38 | * @func 39 | * @name doFoo 40 | * @memberof coolmodule 41 | * @param {Object} params - Blub 42 | * @param {string} params.id - The ID 43 | */ 44 | function doFoo(params) { } -------------------------------------------------------------------------------- /examples/misc/optionproperty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | */ 4 | function ClassWithOptionProperty() { 5 | /** 6 | * Name 7 | * @type {String} 8 | */ 9 | this.name = "Foobar"; 10 | /** 11 | * Foo 12 | * @type {Object} 13 | */ 14 | this.foo = { 15 | /** 16 | * Bar of Foo 17 | * @memberof! ClassWithOptionProperty# 18 | * @type {string} 19 | * @property foo.bar 20 | */ 21 | bar: "Whatever", 22 | /** 23 | * Foo of Foo 24 | * @memberof! ClassWithOptionProperty# 25 | * @type {number} 26 | * @property foo.foo 27 | */ 28 | foo: 1234 29 | }; 30 | } -------------------------------------------------------------------------------- /examples/misc/parameters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} [value] - Somebody's name 3 | */ 4 | function optionalFunc(value) { 5 | 6 | } 7 | 8 | /** 9 | * @param {string=} value - Somebody's name 10 | */ 11 | function optionalFunc2(value) { 12 | 13 | } 14 | 15 | /** 16 | * @param {string} [value=Foobar] - Somebody's name 17 | */ 18 | function defaultArgFunc(value) { 19 | 20 | } 21 | 22 | /** 23 | * @param {...number} value - A series of numbers 24 | */ 25 | function varArgsFunc(value) { 26 | 27 | } -------------------------------------------------------------------------------- /examples/misc/record.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @record 3 | */ 4 | olx.foo.Bar; 5 | 6 | /** 7 | * @type {string} 8 | */ 9 | olx.foo.Bar.prototype.a; 10 | 11 | /** 12 | * @type {number} 13 | */ 14 | olx.foo.Bar.prototype.b; -------------------------------------------------------------------------------- /examples/misc/reserved.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A class that contains reserved member names 3 | * 4 | * @constructor 5 | */ 6 | ReservedType = function() { } 7 | 8 | /** 9 | * Deletes an object by name 10 | * 11 | * @param {string} name description 12 | * @returns {boolean} Whether any entry with this name was deleted. 13 | */ 14 | ReservedType.prototype["delete"] = function(name) { 15 | 16 | } -------------------------------------------------------------------------------- /examples/misc/typedef.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A function that takes a string and number and returns void 3 | * @typedef {function(string, number)} 4 | */ 5 | var VoidFunction; 6 | 7 | /** 8 | * A function that takes a string and returns a number 9 | * @typedef {function(string): number} 10 | */ 11 | var FooFunction; 12 | 13 | /** 14 | * A function that takes an optional string parameter and returns a string 15 | * @typedef {function(string=): string} 16 | */ 17 | var OptionalStringParamFunc; 18 | 19 | /** 20 | * A function that takes an optional string parameter and returns a number 21 | * @typedef {function(?string): string} 22 | */ 23 | var OptionalStringParamFunc2; 24 | 25 | /** 26 | * A function that returns an object 27 | * @typedef {function(): *} 28 | */ 29 | var AnyFunc; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsdoc-typescript-plugin", 3 | "version": "0.0.1", 4 | "description": "A JSDoc plugin to generate a TypeScript definition file (.d.ts) from annotated JSDoc sources", 5 | "scripts": { 6 | "build": "tsc", 7 | "example-doc": "jsdoc ./examples/jsdoc3-examples -r -c ./configs/jsdoc.json -d ./docs/example", 8 | "ol-doc": "jsdoc -c ./configs/jsdoc.ol.json -d ./docs/ol && node tools/ol-postprocess.js ./typings/ol-public.json ./typings/openlayers.d.ts", 9 | "cesium-doc": "jsdoc -c ./configs/jsdoc.cesium.json -d ./docs/cesium", 10 | "misc-doc": "jsdoc -c ./configs/jsdoc.misc.json -d ./docs/misc", 11 | "bad-doc": "jsdoc -c ./configs/jsdoc.bad.json -d ./docs/bad", 12 | "test:misc": "yarn run misc-doc && tsc ./typings/misc.d.ts", 13 | "test:cesium": "yarn run cesium-doc && tsc ./typings/cesium.d.ts && tsc test/cesium-tests.ts", 14 | "test:ol": "yarn run ol-doc && tsc ./typings/openlayers.d.ts && tsc test/openlayers-tests.ts && tsc test/ol-tests.ts", 15 | "test": "yarn run build && yarn run test:misc && yarn run test:ol" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/jumpinjackie/jsdoc-typescript-plugin.git" 20 | }, 21 | "keywords": [ 22 | "jsdoc", 23 | "typescript" 24 | ], 25 | "author": "Jackie Ng", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/jumpinjackie/jsdoc-typescript-plugin/issues" 29 | }, 30 | "homepage": "https://github.com/jumpinjackie/jsdoc-typescript-plugin#readme", 31 | "devDependencies": { 32 | "@types/node": "^8.0.56", 33 | "@types/pegjs": "^0.10.0", 34 | "cesium": "1.27.0", 35 | "jsdoc": "^3.5.5", 36 | "jsonfile": "^4.0.0", 37 | "openlayers": "4.6.2", 38 | "pegjs": "^0.10.0", 39 | "typescript": "2.6.2" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /plugins/cesiumTags.js: -------------------------------------------------------------------------------- 1 | exports.defineTags = function(dictionary) { 2 | dictionary.lookUp('class').synonym('internalConstructor'); 3 | 4 | dictionary.defineTag('glsl', { 5 | onTagged : function(doclet, tag) { 6 | doclet.addTag('kind', 'glsl'); 7 | doclet.filename = doclet.name; 8 | } 9 | }).synonym('glslStruct').synonym('glslUniform').synonym('glslConstant').synonym('glslFunction'); 10 | 11 | dictionary.defineTag('performance', { 12 | mustHaveValue : true, 13 | onTagged : function(doclet, tag) { 14 | if (!doclet.performance) { 15 | doclet.performance = []; 16 | } 17 | doclet.performance.push(tag.value); 18 | } 19 | }); 20 | 21 | dictionary.defineTag('demo', { 22 | mustHaveValue : true, 23 | onTagged : function(doclet, tag) { 24 | if (!doclet.demo) { 25 | doclet.demo = []; 26 | } 27 | doclet.demo.push(tag.value); 28 | } 29 | }); 30 | }; -------------------------------------------------------------------------------- /plugins/falcorFix.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var os = require("os"); 3 | var env = require("jsdoc/env"); 4 | var logger = require("jsdoc/util/logger"); 5 | 6 | // "Patch" the Observable and ModelResponse docs to declare the required template placeholder 7 | exports.handlers = { 8 | beforeParse: function(e) { 9 | if (e.filename.indexOf("Observable.js") >= 0) { 10 | e.source = e.source.replace("@constructor Observable", "@constructor Observable\n * @template T"); 11 | } else if (e.filename.indexOf("ModelResponse.js") >= 0) { 12 | e.source = e.source 13 | .replace("@constructor ModelResponse", "@constructor ModelResponse\n * @template T") 14 | .replace("@augments Observable", "@augments Observable.") 15 | } 16 | } 17 | }; -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | module TsdPlugin { 2 | /** 3 | * Alias for a dictionary keyed on strings 4 | */ 5 | export type Dictionary = { [key: string]: TValue; }; 6 | 7 | /** 8 | * Allows a user to inject additional TS code elements at the global or module levels. Code element injection allows one to "plug the holes" 9 | * in a generated typescript definition if unknown/unresolved types appear in the typescript definition. 10 | * 11 | * Code element injection should only be the last resort. The first port of call should be to fix the API visibility of the affected types 12 | * in the original documented source. 13 | */ 14 | export interface IUserOverride { 15 | 16 | /** 17 | * Overrides for the global namespace. Keys are the actual type 18 | * names for which the configuration applies to 19 | */ 20 | global: Dictionary; 21 | 22 | /** 23 | * Overrides for specific modules. 1st level keys are module names. 24 | * 2nd level keys are the actual type names for which the configuration 25 | * applies to 26 | */ 27 | module: Dictionary>; 28 | } 29 | 30 | export interface IMemberDeclaration { 31 | 32 | /** 33 | * Documentation to attach to the declaration 34 | */ 35 | description?: string; 36 | 37 | /** 38 | * The actual declaration 39 | */ 40 | declaration: string; 41 | } 42 | 43 | export type PrimitiveType = "string" | "number"; 44 | 45 | export interface IEnumConfiguration { 46 | 47 | /** 48 | * The list of identifiers in their original JSDoc format to process as class-like enums. Such 49 | * enums are basically classes with static constant members. Any references to this enum class 50 | * will be replaced with its underlying integral type (generally number|string) 51 | */ 52 | classes: Dictionary; 53 | 54 | /** 55 | * The list of identifiers to process as native enums. 56 | */ 57 | //native: string[]; 58 | } 59 | 60 | /** 61 | * Describes a class type augmentation. You can have a class extend another class or implement extra interfaces 62 | * 63 | * @export 64 | * @interface IClassTypeAugmentation 65 | */ 66 | export interface IClassTypeAugmentation { 67 | /** 68 | * The class this generated class should be extending. Only applies if when generating, the class has been 69 | * determined to not be inheriting from any other class 70 | * 71 | * @type {string} 72 | * @memberOf IClassTypeAugmentation 73 | */ 74 | extends?: string; 75 | /** 76 | * An array of interfaces that this generated class should be implementing 77 | * 78 | * @type {string[]} 79 | * @memberOf IClassTypeAugmentation 80 | */ 81 | implements?: string[]; 82 | } 83 | 84 | /** 85 | * Defines the root plugin configuration section of the JSDoc configuration 86 | */ 87 | export interface IPluginConfig { 88 | 89 | /** 90 | * The name of the TypeScript definition file 91 | */ 92 | rootModuleName: string; 93 | 94 | /** 95 | * The directory where the TypeScript definition file will be saved to 96 | */ 97 | outDir: string; 98 | 99 | /** 100 | * A list of key/value pairs indicating JSDoc types and their TypeScript replacements 101 | */ 102 | typeReplacements: Dictionary; 103 | 104 | /** 105 | * Default constructor description to generate for each emited class constructor when 106 | * description does not exist. Include the %TYPENAME% special token to have it be replaced 107 | * with the name of the emitted class 108 | */ 109 | defaultCtorDesc: string; 110 | 111 | /** 112 | * If set to true, emitted types that have no documentation will have TODO boilerplate 113 | * documentation in their place, as a friendly reminder to the library author to probably 114 | * document this particular API 115 | */ 116 | fillUndocumentedDoclets: boolean; 117 | 118 | /** 119 | * If set to true, raw JSDoc doclets are emitted (in comments) along with each emitted type 120 | * for debugging purposes. 121 | */ 122 | outputDocletDefs: boolean; 123 | 124 | /** 125 | * User-defined type aliases 126 | */ 127 | aliases: Readonly>; 128 | 129 | /** 130 | * User-defined interface definitions 131 | */ 132 | interfaces: Readonly>; 133 | 134 | /** 135 | * An annotation that if found in a parsed doclet, will consider said doclet to be 136 | * part of the public API, and any resulting emitted type to be made public as well 137 | * 138 | * Otherwise, a doclet is considered public if its access is not private 139 | */ 140 | publicAnnotation: string; 141 | 142 | /** 143 | * For methods where the return type is not specified, the configured value will be 144 | * used instead. By default, methods without a return type will default to 'any' 145 | */ 146 | defaultReturnType: string; 147 | 148 | /** 149 | * If you have provided custom interfaces and type aliases, the types may double 150 | * up in the TSD file if public doclets for types of the same name are encountered. 151 | * 152 | * You can avoid double-ups by specifying types to ignore in this list. Such doclets 153 | * will be ignored, giving precedence to your user-defined aliases and interfaces. 154 | */ 155 | ignoreTypes: string[]; 156 | 157 | /** 158 | * A list of types to always make public. Add types here if you are manually defining types in a 159 | * custom header or footer and those types reference types that may not be public when the 160 | * source is processed by the plugin 161 | */ 162 | makePublic: string[]; 163 | 164 | /** 165 | * Path to custom header content file to add to the top of the generated TypeScript definition file 166 | */ 167 | headerFile: string; 168 | 169 | /** 170 | * Path to custom footer content file to add to the bottom of the generated TypeScript definition file 171 | */ 172 | footerFile: string; 173 | 174 | /** 175 | * Member overrides to replace any generated members. Key is the JsDoc longname (ie. qualifiedClassName#memberName) 176 | * Value is the replacement for it 177 | */ 178 | memberReplacements: Dictionary>; 179 | 180 | /** 181 | * Indicates if top-level elements (ie: doclets without parents) should be declared. Default is false, set to true 182 | * if you wrap the emitted types around a custom top-level module through the custom header/footer feature 183 | */ 184 | declareTopLevelElements: boolean; 185 | 186 | /** 187 | * A list of modules to ignore (without the module: prefix), any member under this module will be ignored 188 | */ 189 | ignoreModules: string[]; 190 | 191 | /** 192 | * Indicates if doclets with undocumented = true should be skipped or not. Default is false. 193 | */ 194 | skipUndocumentedDoclets: boolean; 195 | 196 | /** 197 | * Sets the initial indentation level. Each level starts indentation by one "tab" (4 spaces) 198 | */ 199 | initialIndentation: number; 200 | 201 | /** 202 | * Any module on this list, for any types found under it, will be added to the global namespace instead 203 | */ 204 | globalModuleAliases?: string[]; 205 | 206 | /** 207 | * Controls whether to use TS 1.8 string union types for any string enums 208 | */ 209 | useUnionTypeForStringEnum?: boolean; 210 | 211 | /** 212 | * Used to instruct the plugin to configure the given types as enums regardless of what the processed doclet may suggest it is 213 | */ 214 | processAsEnums?: Readonly; 215 | /** 216 | * Used to add type augmentations for any generated classes. 217 | * 218 | * @type {Dictionary} 219 | * @memberOf IPluginConfig 220 | */ 221 | classTypeAugmentations?: Dictionary>; 222 | 223 | rewriteFunctionTypedefs?: boolean; 224 | 225 | /** 226 | * A path (if specified) to a file where all parsed and emitted public types are written to 227 | */ 228 | dumpPublicTypesTo?: string; 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /src/entrypoint.ts: -------------------------------------------------------------------------------- 1 | let fs: typeof nodeModules.fs = require("fs"); 2 | let os: typeof nodeModules.os = require("os"); 3 | let peg: typeof PEG = require("pegjs"); 4 | let env: any = require("jsdoc/env"); 5 | let logger:TsdPlugin.ILogger = require("jsdoc/util/logger"); 6 | let tsConf:TsdPlugin.IPluginConfig = env.conf.typescript || {}; 7 | 8 | exports.handlers = { 9 | newDoclet(e: jsdoc.INewDocletEvent): void { 10 | if (tsConf.rewriteFunctionTypedefs === true) { 11 | TsdPlugin.FunctionTypedefRewriter.rewrite(e.doclet); 12 | } 13 | }, 14 | processingComplete(e: jsdoc.IProcessingCompleteEvent): void { 15 | let proc = new TsdPlugin.TsdGenerator(tsConf); 16 | let sf = { 17 | createStream: (fileName) => fs.createWriteStream(fileName), 18 | readText: (fileName) => fs.readFileSync(fileName, "utf8"), 19 | endl: os.EOL 20 | }; 21 | proc.process(e.doclets, sf, logger); 22 | //proc.dumpDoclets(e.doclets, sf); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/functypedefrewriter.ts: -------------------------------------------------------------------------------- 1 | 2 | module TsdPlugin { 3 | /** 4 | * A helper class to rewrite @typedef based function annotations into the @callback form 5 | */ 6 | export class FunctionTypedefRewriter { 7 | public static getDocletKind(doclet: Readonly): string { 8 | //Not a function or constructor eh? 9 | if (doclet.kind != DocletKind.Function && doclet.kind != DocletKind.Class) { 10 | if (doclet.params && doclet.params.length > 0) { 11 | return DocletKind.Function; //LIAR 12 | } 13 | if (doclet.returns && doclet.returns.length > 0) { 14 | return DocletKind.Function; //LIAR 15 | } 16 | } 17 | return doclet.kind; 18 | } 19 | 20 | private static isFunctionTypedef(doclet: Readonly): boolean { 21 | return doclet.kind == DocletKind.Typedef && 22 | doclet.type != null && 23 | doclet.type.names != null && 24 | doclet.type.names.length == 1 && 25 | doclet.type.names.indexOf("function") >= 0 && 26 | doclet.comment.indexOf("@callback") < 0; 27 | } 28 | 29 | static cleanArg(str: string): string { 30 | let clean = str; 31 | 32 | if (clean.indexOf("function") < 0) 33 | clean = clean.replace("(", "").replace(")", ""); 34 | 35 | if (clean.indexOf("!") == 0) 36 | clean = clean.substr(1); 37 | 38 | return clean; 39 | } 40 | 41 | static isContextualParameter(str: string): boolean { 42 | return str.indexOf(":") >= 0; 43 | } 44 | 45 | public static rewrite(doclet: jsdoc.IDoclet): void { 46 | 47 | if (FunctionTypedefRewriter.isFunctionTypedef(doclet)) { 48 | // The meat that makes this possible is the @typedef annotation in the comments 49 | // Use regex to test for common patterns 50 | 51 | // Clean the comment of newlines and *, so it doesn't trip the regex 52 | 53 | let comment = doclet.comment.split("\n *").join(""); 54 | 55 | // A function that returns a value 56 | let matches = comment.match(/@typedef \{function\((.*?)\)\s*:\s*(.*?)\}/); 57 | if (matches && matches.length == 3) { 58 | let argPart = matches[1]; 59 | let retPart = matches[2]; 60 | let args = argPart.split(",") 61 | .filter(a => !FunctionTypedefRewriter.isContextualParameter(a)) 62 | .map(a => FunctionTypedefRewriter.cleanArg(a).trim()) 63 | .filter(a => a != null && a != ""); 64 | let params = []; 65 | //NOTE: As the typedef does not carry parameter name information, we have to fall back 66 | //to the not very useful argN parameter name format. Also there will be no parameter information 67 | let argNo = 0; 68 | for (let arg of args) { 69 | let typeNames = arg.split("|").map(a => FunctionTypedefRewriter.cleanArg(a).trim()); 70 | let param: any = { 71 | type: { 72 | names: typeNames 73 | }, 74 | name: `arg${argNo}` 75 | }; 76 | if (typeNames.length == 1) { 77 | //Check for optional parameter formats 78 | if (typeNames[0].indexOf("?") == 0) { //1st optional variant: ?typename 79 | typeNames[0] = typeNames[0].substr(1); 80 | param.optional = true; 81 | } else if (typeNames[0].indexOf("=") == typeNames[0].length - 1) { //2nd optional variant: typename= 82 | typeNames[0] = typeNames[0].substr(0, typeNames[0].length - 1); 83 | param.optional = true; 84 | } 85 | } else { 86 | let anyOptional = typeNames.filter(tn => tn.indexOf("?") >= 0 || tn.indexOf("=") == tn.length - 1); 87 | if (anyOptional.length > 0) { 88 | //Clean the type names 89 | param.type.names = typeNames.map(tn => { 90 | if (tn.indexOf("?") == 0) { 91 | return tn.substr(1); 92 | } else if (tn.indexOf("=") == tn.length - 1) { 93 | return tn.substr(0, tn.length - 1); 94 | } else { 95 | return tn; 96 | } 97 | }); 98 | param.optional = true; 99 | } 100 | } 101 | params.push(param); 102 | argNo++; 103 | } 104 | doclet.params = params; 105 | doclet.returns = [ 106 | { 107 | type: { 108 | names: retPart.split("|").map(a => FunctionTypedefRewriter.cleanArg(a).trim()) 109 | } 110 | } 111 | ] 112 | console.log(`Rewrote doclet for (${doclet.longname}) with extra callback metadata`); 113 | //Inject the @callback annotation into the comments (as the main processor checks for the presence) 114 | //of this annotation 115 | doclet.comment = doclet.comment.replace("/**", `/**\n * @callback ${doclet.longname}\n *`); 116 | return; 117 | } 118 | // No return types 119 | matches = comment.match(/@typedef \{function\((.*?)\)\}/); 120 | if (matches && matches.length == 2) { 121 | let argPart = matches[1]; 122 | let args = argPart.split(",") 123 | .filter(a => !FunctionTypedefRewriter.isContextualParameter(a)) 124 | .map(a => FunctionTypedefRewriter.cleanArg(a).trim()) 125 | .filter(a => a != null && a != ""); 126 | let params = []; 127 | //NOTE: As the typedef does not carry parameter name information, we have to fall back 128 | //to the not very useful argN parameter name format. Also there will be no parameter information 129 | let argNo = 0; 130 | for (let arg of args) { 131 | let typeNames = arg.split("|").map(a => FunctionTypedefRewriter.cleanArg(a).trim()); 132 | let param: any = { 133 | type: { 134 | names: typeNames 135 | }, 136 | name: `arg${argNo}` 137 | }; 138 | if (typeNames.length == 1) { 139 | //Check for optional parameter formats 140 | if (typeNames[0].indexOf("?") == 0) { //1st variant: ?typename 141 | typeNames[0] = typeNames[0].substr(1); 142 | param.optional = true; 143 | } else if (typeNames[0].indexOf("=") == typeNames[0].length - 1) { //2nd variant: typename= 144 | typeNames[0] = typeNames[0].substr(0, typeNames[0].length - 1); 145 | param.optional = true; 146 | } 147 | } 148 | params.push(param); 149 | argNo++; 150 | } 151 | doclet.params = params; 152 | console.log(`Rewrote doclet for (${doclet.longname}) with extra callback metadata`); 153 | //Inject the @callback annotation into the comments (as the main processor checks for the presence) 154 | //of this annotation 155 | doclet.comment = doclet.comment.replace("/**", `/**\n * @callback ${doclet.longname}\n *`); 156 | return; 157 | } 158 | 159 | console.log(`Skipped rewriting ${doclet.longname} as it does not match any known function type patterns`); 160 | } 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/generics.pegjs: -------------------------------------------------------------------------------- 1 | Type 2 | = GenericType 3 | / UnionType 4 | / ArrayType 5 | / SimpleType 6 | 7 | NonUnionType 8 | = GenericType 9 | / ArrayType 10 | / SimpleType 11 | 12 | NonArrayType 13 | = GenericType 14 | / "(" _ type:UnionType ")" { 15 | return type; 16 | } 17 | / SimpleType 18 | 19 | UnionType 20 | = "("? first:NonUnionType _ rest:UnionTypeRest+ ")"? { 21 | return { 22 | kind: "union", 23 | types: [first].concat(rest) 24 | }; 25 | } 26 | 27 | UnionTypeRest 28 | = "|" _ type:NonUnionType { 29 | return type; 30 | } 31 | 32 | GenericType 33 | = name:Ident "."? "<" _ params:GenericTypeParams _ ">" { 34 | if (name === "Array") { 35 | return { 36 | kind: "array", 37 | type: params[0] 38 | } 39 | } else { 40 | return { 41 | kind: "generic", 42 | name: name, 43 | types: params 44 | } 45 | } 46 | } 47 | 48 | GenericTypeParams 49 | = first:Type? _ rest:GenericTypeParamsRest* { 50 | return first ? [first].concat(rest) : rest; 51 | } 52 | 53 | GenericTypeParamsRest 54 | = "," _ type:Type { 55 | return type; 56 | } 57 | 58 | SimpleType 59 | = name:Ident { 60 | if (name === "Array") { 61 | return { 62 | kind: "array", 63 | type: {kind: "simple", name:"*"} 64 | } 65 | } else { 66 | return { 67 | kind: "simple", 68 | name: name 69 | }; 70 | } 71 | } 72 | 73 | ArrayType 74 | = type:NonArrayType arr:"[]"+ { 75 | return arr.reduce((previousValue) => { 76 | let obj = { 77 | kind: "array", 78 | type: previousValue !== null ? previousValue : type 79 | }; 80 | return obj; 81 | }, null); 82 | } 83 | 84 | Ident 85 | = "*" 86 | / [\\.a-zA-Z0-9$_-]* { 87 | let txt = text(); 88 | if (txt.endsWith(".")) {return txt.slice(0,-1);} 89 | return txt; 90 | } 91 | 92 | _ "whitespace" 93 | = [ \t\n\r]* -------------------------------------------------------------------------------- /src/io.ts: -------------------------------------------------------------------------------- 1 | module TsdPlugin { 2 | export interface ILogger { 3 | warn(msg: string): void; 4 | error(msg: string): void; 5 | fatal(msg: string): void; 6 | } 7 | 8 | export interface IFileStreamFactory { 9 | createStream(fileName: string): any; /* fs.WriteStream */ 10 | readText(fileName: string): string; 11 | endl: string; 12 | } 13 | 14 | export class IndentedOutputStream { 15 | private indentLevel: number; 16 | private output: any; 17 | private endl: string; 18 | 19 | constructor(output: any /* fs.WriteStream */, endl: string) { 20 | this.indentLevel = 0; 21 | this.output = output; 22 | this.endl = endl; 23 | } 24 | 25 | indent(): void { 26 | this.indentLevel++; 27 | } 28 | 29 | unindent(): void { 30 | this.indentLevel--; 31 | } 32 | 33 | private indentedText(): string { 34 | let pattern = " "; 35 | let count = this.indentLevel * 4; 36 | if (count < 1) return ''; 37 | let result = ''; 38 | while (count > 1) { 39 | if (count & 1) result += pattern; 40 | count >>= 1, pattern += pattern; 41 | } 42 | return result + pattern; 43 | } 44 | 45 | writeln(str: string) { 46 | this.output.write(`${this.indentedText()}${str}${this.endl}`); 47 | } 48 | 49 | close(callback: () => void) { 50 | this.output.on("finish", callback); 51 | this.output.end(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/jsdoc.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare module "jsdoc/env" { 3 | class Environment { 4 | public static conf: any; 5 | } 6 | export = Environment; 7 | } 8 | 9 | declare module "jsdoc/util/logger" { 10 | class Logger { 11 | public warn(msg: string); 12 | public error(msg: string); 13 | public fatal(msg: string); 14 | } 15 | export = Logger; 16 | } 17 | 18 | declare module jsdoc { 19 | /** 20 | * The event passed on a JsDoc newDoclet event 21 | */ 22 | export interface INewDocletEvent { 23 | 24 | /** 25 | * The processed doclet 26 | */ 27 | doclet: IDoclet; 28 | } 29 | 30 | /** 31 | * The event passed on a JsDoc processingComplete event 32 | */ 33 | export interface IProcessingCompleteEvent { 34 | 35 | /** 36 | * The processed doclets 37 | */ 38 | doclets: IDoclet[]; 39 | } 40 | 41 | /** 42 | * Represents a JsDoc doclet, a parsed piece of documentation for a type, function 43 | * or member 44 | */ 45 | export interface IDoclet { 46 | 47 | /** 48 | * The full raw comment of the doclet 49 | */ 50 | comment?: string; 51 | 52 | /** 53 | * Declared access 54 | */ 55 | access?: string; 56 | 57 | /** 58 | * The description of the doclet (extracted from raw comments) 59 | */ 60 | description: string; 61 | 62 | /** 63 | * The description of the class doclet (extracted from raw comments) 64 | */ 65 | classdesc?: string; 66 | 67 | /** 68 | * Parameter information 69 | */ 70 | params?: IParameter[]; 71 | 72 | /** 73 | * Return type information 74 | */ 75 | returns?: ITypeInfo[]; 76 | 77 | /** 78 | * Data about custom annotations applied on this doclet 79 | */ 80 | tags?: ITag[]; 81 | 82 | /** 83 | * The name of this identifier 84 | */ 85 | name: string; 86 | 87 | /** 88 | * The full name of this identifier 89 | */ 90 | longname: string; 91 | 92 | /** 93 | * The kind of doclet 94 | */ 95 | kind: string; 96 | 97 | /** 98 | * Denotes the full name of the parent identifier that this doclet is a child of 99 | */ 100 | memberof: string; 101 | 102 | /** 103 | * The scope of the doclet 104 | */ 105 | scope: string; 106 | 107 | /** 108 | * Indicates of any documentation was found while parsing the doclet for this identifier 109 | */ 110 | undocumented?: boolean; 111 | 112 | /** 113 | * The type of this identifier. Not applicable for functions 114 | */ 115 | type?: IType; 116 | 117 | /** 118 | * If this is a class doclet, denotes the types that this class inherits from 119 | */ 120 | augments?: string[]; 121 | 122 | /** 123 | * Indicates of this identifier is nullable. Applicable for properties and module/global-scoped vars 124 | */ 125 | nullable?: boolean; 126 | 127 | /** 128 | * Indicates if this doclet inherits documentation from a parent type member of the same name 129 | */ 130 | inheritdoc?: boolean; 131 | 132 | /** 133 | * Arbitrary JSDoc metadata 134 | */ 135 | meta?: any; 136 | 137 | /** 138 | * Indicates if this doclet is an enum 139 | */ 140 | isEnum?: boolean; 141 | 142 | /** 143 | * If isEnum == true, contains the members of this enum. Note that other libraries may define enums differently (eg. A typedef with members) 144 | */ 145 | properties?: IDoclet[]; 146 | } 147 | 148 | /** 149 | * Type name 150 | */ 151 | export interface IType { 152 | names: string[]; 153 | } 154 | 155 | /** 156 | * Type information 157 | */ 158 | export interface ITypeInfo { 159 | type: IType; 160 | description?: string; 161 | } 162 | 163 | /** 164 | * Describes a method parameter 165 | */ 166 | export interface IParameter extends ITypeInfo { 167 | 168 | /** 169 | * The name of this parameter 170 | */ 171 | name: string; 172 | 173 | /** 174 | * Indicates of this parameter is optional. Alias for optional 175 | */ 176 | nullable?: boolean; 177 | 178 | /** 179 | * Indicates of this parameter is optional. Alias for nullable 180 | */ 181 | optional?: boolean; 182 | 183 | /** 184 | * Indicates if this parameter is a variable argument list 185 | */ 186 | variable?: boolean; 187 | } 188 | 189 | /** 190 | * Describes a tag (annotation) 191 | */ 192 | export interface ITag { 193 | originalTitle: string; 194 | title: string; 195 | text: string; 196 | value?: string; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/kinds.ts: -------------------------------------------------------------------------------- 1 | module TsdPlugin { 2 | 3 | /** 4 | * Constants for different kinds of doclets 5 | */ 6 | export class DocletKind { 7 | 8 | /** 9 | * Doclet for a function 10 | */ 11 | static Function = "function"; 12 | 13 | /** 14 | * Doclet for a typedef 15 | */ 16 | static Typedef = "typedef"; 17 | 18 | /** 19 | * Doclet for a class 20 | */ 21 | static Class = "class"; 22 | 23 | /** 24 | * Doclet for a member 25 | */ 26 | static Member = "member"; 27 | 28 | /** 29 | * Doclet for a property 30 | */ 31 | static Value = "value"; 32 | 33 | /** 34 | * Doclet for a module 35 | */ 36 | static Module = "module"; 37 | 38 | /** 39 | * Doclet for a constant 40 | */ 41 | static Constant = "constant"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/moduleutils.ts: -------------------------------------------------------------------------------- 1 | module TsdPlugin { 2 | /** 3 | * Module helper utility 4 | */ 5 | export class ModuleUtils { 6 | /** 7 | * Gets whether this module name is an AMD one 8 | */ 9 | public static isAMD(name: string): boolean { 10 | return name.indexOf("/") >= 0; 11 | } 12 | 13 | public static cleanModuleName(moduleName: string): string { 14 | let modName: string = moduleName; 15 | if (modName.indexOf("module:") == 0) { 16 | modName = modName.substring(7); 17 | } 18 | if (modName.indexOf("~") >= 0) { 19 | modName = modName.substring(modName.indexOf("~") + 1); 20 | } 21 | return modName; 22 | } 23 | 24 | /** 25 | * Writes the TS module tree out to the specified output stream 26 | */ 27 | public static outputTsd( 28 | module: Readonly, 29 | stream: IndentedOutputStream, 30 | conf: Readonly, 31 | logger: ILogger, 32 | publicTypes: Map, 33 | publicApi: Map, 34 | isTopLevel: boolean = true 35 | ): void { 36 | for (let type of module.types) { 37 | //console.log(`Outputting type: ${type.getFullName()}`); 38 | type.output(stream, conf, logger, publicTypes); 39 | publicApi.set(type.getFullName(), type); 40 | } 41 | let childModules = module.children; 42 | if (isTopLevel && conf.globalModuleAliases.length > 0) { 43 | //For any modules declared as global aliases, output them 44 | //without the module declaration 45 | for (const modName of conf.globalModuleAliases) { 46 | if (childModules.has(modName)) { 47 | const mod = childModules.get(modName); 48 | ModuleUtils.outputTsd(mod, stream, conf, logger, publicTypes, publicApi, false); 49 | } 50 | } 51 | } 52 | childModules.forEach((child, moduleName) => { 53 | //Skip over any modules declared as global aliases 54 | if (isTopLevel) { 55 | const matches = conf.globalModuleAliases.filter(gm => gm === moduleName); 56 | if (matches.length > 0) { 57 | return; 58 | } 59 | } 60 | //Root modules have to be declared 61 | let decl = ((child.isRoot === true && conf.declareTopLevelElements) ? "declare " : ""); 62 | //Write module decl 63 | 64 | //Strip module: prefix if found 65 | let modName: string = ModuleUtils.cleanModuleName(moduleName); 66 | if (ModuleUtils.isAMD(modName)) { 67 | stream.writeln(`${decl}module "${modName}" {`) 68 | } else { 69 | stream.writeln(`${decl}module ${modName} {`); 70 | } 71 | stream.indent(); 72 | ModuleUtils.outputTsd(child, stream, conf, logger, publicTypes, publicApi, false); 73 | stream.unindent(); 74 | stream.writeln("}"); 75 | }); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/parser.ts: -------------------------------------------------------------------------------- 1 | module TsdPlugin { 2 | export module Generics { 3 | let grammer = fs.readFileSync("./src/generics.pegjs", 'utf8'); 4 | 5 | type IType = IArrayType | IUnionType | ISimpleType | IGenericType; 6 | 7 | interface IArrayType { 8 | kind: "array"; 9 | type: IType; 10 | } 11 | 12 | interface INamedType { 13 | name: string; 14 | } 15 | 16 | export interface IUnionType { 17 | kind: "union"; 18 | types: IType[]; 19 | } 20 | 21 | export interface ISimpleType { 22 | kind: "simple"; 23 | name: string; 24 | } 25 | 26 | export interface IGenericType { 27 | kind: "generic"; 28 | name: string; 29 | types: IType[]; 30 | } 31 | 32 | class GenericsResult { 33 | public constructor(private type: IType, private replacer?: (typeName) => string) { 34 | this.remapType(type); 35 | }; 36 | 37 | public toString(): string { 38 | let {type} = this; 39 | if (!type) return null; 40 | 41 | return this.typeString(type); 42 | } 43 | 44 | private typeString(type: IType): string { 45 | switch(type.kind) { 46 | case "array": 47 | return this.stringArray(type); 48 | case "generic": 49 | return this.stringGeneric(type); 50 | case "simple": 51 | return this.stringSimple(type); 52 | case "union": 53 | return this.stringUnion(type); 54 | } 55 | console.error("Invalid Type:", type); 56 | } 57 | 58 | private stringSimple(tn: INamedType): string { 59 | return tn.name; 60 | } 61 | 62 | private stringUnion(tn: IUnionType): string { 63 | return tn.types.map(v => this.typeString(v)).join("|"); 64 | } 65 | 66 | private stringArray(tn: IArrayType): string { 67 | let innerTypeString = this.typeString(tn.type); 68 | if (tn.type.kind === "union") { 69 | return "(" + innerTypeString + ")[]"; 70 | } else { 71 | return innerTypeString + "[]"; 72 | } 73 | } 74 | 75 | private stringGeneric(tn: IGenericType): string { 76 | let innerTypeString = tn.types.map(v => this.typeString(v)).join(","); 77 | return tn.name + "<" + innerTypeString + ">"; 78 | } 79 | 80 | private remapType(tn: IType) { 81 | let {replacer} = this; 82 | if (!replacer || !tn) return; 83 | 84 | switch(tn.kind) { 85 | case "array": 86 | this.remapArray(tn); 87 | break; 88 | case "generic": 89 | this.remapGeneric(tn); 90 | break; 91 | case "simple": 92 | this.remapSimple(tn); 93 | break; 94 | case "union": 95 | this.remapUnion(tn); 96 | break; 97 | } 98 | } 99 | 100 | private remapSimple(tn: INamedType) { 101 | tn.name = this.replacer(tn.name); 102 | } 103 | 104 | private remapUnion(tn: IUnionType) { 105 | tn.types.forEach(value => this.remapType(value)); 106 | } 107 | 108 | private remapArray(tn: IArrayType) { 109 | this.remapType(tn.type); 110 | } 111 | 112 | private remapGeneric(tn: IGenericType) { 113 | this.remapSimple(tn); 114 | tn.types.forEach(value => this.remapType(value)); 115 | } 116 | } 117 | 118 | export function parse(input: string, replacer?: (typeName: string) => string): string { 119 | try { 120 | return new GenericsResult(_parse(input), replacer).toString(); 121 | } catch(e) { 122 | return null; 123 | } 124 | } 125 | 126 | const _parse: (input: string, options?:PEG.ParserOptions) => IType = peg.generate(grammer).parse; 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /src/tsdgenerator.ts: -------------------------------------------------------------------------------- 1 | module TsdPlugin { 2 | const CLS_DESC_PLACEHOLDER = "%TYPENAME%"; 3 | 4 | interface IGeneratorStats { 5 | typedefs: { 6 | user: number; 7 | gen: number; 8 | }, 9 | moduleMembers: number; 10 | ifaces: number; 11 | classes: number; 12 | } 13 | 14 | /** 15 | * The class that does all the grunt work 16 | */ 17 | export class TsdGenerator implements ITypeRegistrar { 18 | private moduleMembers = new Map(); 19 | private globalMembers = new Array(); 20 | private moduleDoclets = new Map>(); 21 | private classes = new Map(); 22 | private typedefs = new Map(); 23 | private trackedDoclets = new Map>(); 24 | private userTypeAliases = new Array(); 25 | private userInterfaces = new Array(); 26 | private ignoreTypes = new Set(); 27 | 28 | private stats: IGeneratorStats = { 29 | typedefs: { 30 | user: 0, 31 | gen: 0 32 | }, 33 | moduleMembers: 0, 34 | ifaces: 0, 35 | classes: 0 36 | }; 37 | 38 | private config: IPluginConfig; 39 | 40 | constructor(config: IPluginConfig) { 41 | 42 | const defaults: IPluginConfig = { 43 | rootModuleName: "generated", 44 | outDir: ".", 45 | typeReplacements: { 46 | "*": "any", 47 | "?": "any", 48 | "Object": "any", 49 | "function": "Function" 50 | }, 51 | defaultCtorDesc: `Constructor for ${CLS_DESC_PLACEHOLDER}`, 52 | fillUndocumentedDoclets: false, 53 | outputDocletDefs: false, 54 | publicAnnotation: null, 55 | defaultReturnType: "any", 56 | aliases: { 57 | global: {}, 58 | module: {} 59 | }, 60 | interfaces: { 61 | global: {}, 62 | module: {} 63 | }, 64 | ignoreTypes: [], 65 | makePublic: [], 66 | headerFile: undefined, 67 | footerFile: undefined, 68 | memberReplacements: {}, 69 | dumpPublicTypesTo: undefined, 70 | declareTopLevelElements: true, 71 | ignoreModules: [], 72 | skipUndocumentedDoclets: true, 73 | initialIndentation: 0, 74 | globalModuleAliases: [], 75 | useUnionTypeForStringEnum: false, 76 | processAsEnums: { 77 | //native: [], 78 | classes: {} 79 | }, 80 | classTypeAugmentations: {} 81 | }; 82 | 83 | this.config = Object.assign(defaults, config, { 84 | aliases: Object.assign(defaults.aliases, config.aliases), 85 | interfaces: Object.assign(defaults.interfaces, config.interfaces), 86 | processAsEnums: Object.assign(defaults.processAsEnums, config.processAsEnums), 87 | typeReplacements: Object.assign(defaults.typeReplacements, config.typeReplacements) 88 | }); 89 | 90 | for (let ignoreType of this.config.ignoreTypes) { 91 | this.ignoreTypes.add(ignoreType); 92 | } 93 | } 94 | 95 | private shouldIgnoreType(fullname: string): boolean { 96 | return this.ignoreTypes.has(fullname); 97 | } 98 | 99 | private ensureClassDef(name: string, factory?: () => TSClass): TSClass { 100 | if (!this.classes.has(name)) { 101 | if (factory != null) { 102 | let cls = factory(); 103 | this.classes.set(name, cls); 104 | return cls; 105 | } else { 106 | return null; 107 | } 108 | } else { 109 | return this.classes.get(name); 110 | } 111 | } 112 | 113 | private ensureTypedef(name: string, factory?: () => TSTypedef): TSTypedef { 114 | if (!this.typedefs.has(name)) { 115 | if (factory != null) { 116 | let tdf = factory(); 117 | this.typedefs.set(name, tdf); 118 | return tdf; 119 | } else { 120 | return null; 121 | } 122 | } else { 123 | return this.typedefs.get(name); 124 | } 125 | } 126 | 127 | public registerTypedef(name: string, typedef: TSTypedef): boolean { 128 | if (!this.typedefs.has(name)) { 129 | this.typedefs.set(name, typedef); 130 | return true; 131 | } 132 | return false; 133 | } 134 | 135 | private isTSInterfaceCandidate(doclet: Readonly): boolean { 136 | return !TsdGenerator.isCallbackType(doclet) && //Because callback types could also be through typedefs 137 | (doclet.kind == DocletKind.Typedef || 138 | (doclet.comment || "").indexOf("@record") >= 0); 139 | } 140 | 141 | private parseClassesAndTypedefs(doclets: Readonly[]): void { 142 | for (let doclet of doclets) { 143 | //On ignore list 144 | if (this.shouldIgnoreType(doclet.longname)) 145 | continue; 146 | //Undocumented and we're ignoring them 147 | if (doclet.undocumented && this.config.skipUndocumentedDoclets) 148 | continue; 149 | 150 | //TypeScript definition covers a module's *public* API surface, so 151 | //skip private classes 152 | let isPublic = !(TypeUtil.isPrivateDoclet(doclet, this.config)); 153 | let parentModName = null; 154 | if (doclet.longname.indexOf("module:") >= 0) { 155 | //Assuming that anything annotated "module:" will have a "." to denote end of module and start of class name 156 | let modLen = "module:".length; 157 | let dotIdx = doclet.longname.indexOf("."); 158 | if (dotIdx < 0) 159 | dotIdx = doclet.longname.length; 160 | parentModName = doclet.longname.substring(modLen, dotIdx); 161 | } else if (doclet.memberof) { 162 | parentModName = doclet.memberof; 163 | } 164 | let makeGlobal = this.config.globalModuleAliases.indexOf(parentModName) >= 0; 165 | if (doclet.kind == DocletKind.Class) { 166 | //Key class definition on longname 167 | let cls = this.ensureClassDef(doclet.longname, () => new TSClass(doclet)); 168 | cls.setIsPublic(isPublic); 169 | if (parentModName != null) 170 | cls.setParentModule(parentModName); 171 | if (doclet.params != null) 172 | cls.ctor = new TSConstructor(doclet); 173 | this.trackedDoclets.set(doclet.longname, doclet); 174 | } else if (TsdGenerator.isCallbackType(doclet)) { 175 | if (parentModName != null && !this.moduleMembers.has(parentModName)) 176 | this.moduleMembers.set(parentModName, []); 177 | let method = new TSMethod(doclet) 178 | method.setIsModule(true); 179 | method.setIsTypedef(true); 180 | if (parentModName != null && !makeGlobal) 181 | this.moduleMembers.get(parentModName).push(method); 182 | else if (makeGlobal) 183 | this.globalMembers.push(method); 184 | this.trackedDoclets.set(doclet.longname, doclet); 185 | } else if (this.isTSInterfaceCandidate(doclet)) { 186 | let tdf = null; 187 | if (makeGlobal) 188 | tdf = new TSTypedef(doclet); 189 | else 190 | tdf = this.ensureTypedef(doclet.longname, () => new TSTypedef(doclet)); 191 | tdf.setIsPublic(isPublic); 192 | if (parentModName != null && !makeGlobal) 193 | tdf.setParentModule(parentModName); 194 | else if (makeGlobal) 195 | this.globalMembers.push(tdf); 196 | this.trackedDoclets.set(doclet.longname, doclet); 197 | } else if (TsdPlugin.FunctionTypedefRewriter.getDocletKind(doclet) == DocletKind.Function) { 198 | let parentModule = doclet.memberof; 199 | if (parentModule == null) { 200 | let method = new TSMethod(doclet); 201 | method.setIsModule(true); 202 | method.setIsPublic(isPublic); 203 | method.setIsTypedef(false); 204 | this.globalMembers.push(method); 205 | this.trackedDoclets.set(doclet.longname, doclet); 206 | } 207 | } else if (TypeUtil.isEnumDoclet(doclet)) { 208 | let tdf = null; 209 | if (makeGlobal) 210 | tdf = new TSTypedef(doclet); 211 | else 212 | tdf = this.ensureTypedef(doclet.longname, () => new TSTypedef(doclet)); 213 | tdf.setIsPublic(isPublic); 214 | if (parentModName != null && !makeGlobal) 215 | tdf.setParentModule(parentModName); 216 | else if (makeGlobal) 217 | this.globalMembers.push(tdf); 218 | this.trackedDoclets.set(doclet.longname, doclet); 219 | } 220 | } 221 | } 222 | 223 | private parseModules(doclets: Readonly[]): void { 224 | for (let doclet of doclets) { 225 | //Already covered in 1st pass 226 | if (this.trackedDoclets.has(doclet.longname)) 227 | continue; 228 | //On ignore list 229 | if (this.shouldIgnoreType(doclet.longname)) 230 | continue; 231 | //Undocumented and we're ignoring them 232 | if (doclet.undocumented && this.config.skipUndocumentedDoclets) 233 | continue; 234 | 235 | if (doclet.kind == DocletKind.Module) { 236 | this.moduleDoclets.set(doclet.name, doclet); 237 | this.trackedDoclets.set(doclet.longname, doclet); 238 | } 239 | } 240 | } 241 | 242 | private static isCallbackType(doclet: Readonly): boolean { 243 | return doclet.kind == DocletKind.Typedef && 244 | doclet.type != null && 245 | doclet.type.names != null && 246 | doclet.type.names.indexOf("function") >= 0 && 247 | //This is to check that the function type was documented using @callback instead of @typedef 248 | (doclet.comment || "").indexOf("@callback") >= 0; 249 | } 250 | 251 | private processTypeMembers(doclets: Readonly[], logger: ILogger): void { 252 | for (let doclet of doclets) { 253 | //Already covered in 1st pass 254 | if (this.trackedDoclets.has(doclet.longname)) 255 | continue; 256 | //On the ignore list 257 | if (this.shouldIgnoreType(doclet.longname)) 258 | continue; 259 | //Undocumented and we're ignoring them 260 | if (doclet.undocumented && this.config.skipUndocumentedDoclets) 261 | continue; 262 | 263 | let isPublic = !TypeUtil.isPrivateDoclet(doclet, this.config); 264 | 265 | //We've keyed class definition on longname, so memberof should 266 | //point to it 267 | let cls: TSComposable = this.ensureClassDef(doclet.memberof); 268 | let isTypedef = false; 269 | let isClass = true; 270 | 271 | if (!cls) { 272 | isClass = false; 273 | //Failing that it would've been registered as a typedef 274 | cls = this.ensureTypedef(doclet.memberof); 275 | if (!cls) { 276 | //Bail on this iteration here if not public 277 | if (!isPublic) 278 | continue; 279 | 280 | //Before we bail, let's assume this is a module level member and 281 | //see if it's the right doclet kind 282 | let parentModule = doclet.memberof; 283 | if (parentModule == null) 284 | continue; 285 | 286 | parentModule = ModuleUtils.cleanModuleName(parentModule); 287 | 288 | //HACK-ish: If we found an enum, that this is a member of, skip it if it already exists 289 | let parentDoclet = this.trackedDoclets.get(doclet.memberof); 290 | if (parentDoclet != null && TypeUtil.isEnumDoclet(parentDoclet)) { 291 | 292 | let matches = (parentDoclet.properties || []).filter(prop => prop.name == doclet.name); 293 | if (matches.length > 0) 294 | continue; 295 | } 296 | 297 | if (doclet.kind == DocletKind.Function) { 298 | if (!this.moduleMembers.has(parentModule)) 299 | this.moduleMembers.set(parentModule, []); 300 | let method = new TSMethod(doclet) 301 | method.setIsModule(true); 302 | this.moduleMembers.get(parentModule).push(method); 303 | } else if (doclet.kind == DocletKind.Constant || doclet.kind == DocletKind.Value || (doclet.kind == DocletKind.Member && doclet.params == null)) { 304 | if (!this.moduleMembers.has(parentModule)) 305 | this.moduleMembers.set(parentModule, []); 306 | let prop = new TSProperty(doclet, false); 307 | prop.setIsModule(true); 308 | 309 | this.moduleMembers.get(parentModule).push(prop); 310 | } 311 | continue; 312 | } else { 313 | isTypedef = true; 314 | } 315 | } 316 | 317 | if (doclet.kind == DocletKind.Function) { 318 | let method = new TSMethod(doclet); 319 | method.setIsPublic(isPublic); 320 | cls.addMember(method, logger); 321 | } else if (doclet.kind == DocletKind.Constant || doclet.kind == DocletKind.Value || (doclet.kind == DocletKind.Member && doclet.params == null)) { 322 | let prop = new TSProperty(doclet, isTypedef); 323 | prop.setIsPublic(isPublic); 324 | cls.addMember(prop, logger); 325 | } 326 | } 327 | } 328 | 329 | private processUserDefinedTypes(): void { 330 | //Output user-injected type aliases 331 | //global 332 | for (let typeAlias in this.config.aliases.global) { 333 | let typeName = this.config.aliases.global[typeAlias]; 334 | this.userTypeAliases.push( 335 | new TSUserTypeAlias(null, typeAlias, typeName)); 336 | } 337 | //module 338 | for (let moduleName in this.config.aliases.module) { 339 | for (let typeAlias in this.config.aliases.module[moduleName]) { 340 | let typeName = this.config.aliases.module[moduleName][typeAlias]; 341 | this.userTypeAliases.push( 342 | new TSUserTypeAlias(moduleName, typeAlias, typeName)); 343 | } 344 | } 345 | //Output user-injected interfaces 346 | //global 347 | for (let typeName in this.config.interfaces.global) { 348 | let iface = this.config.interfaces.global[typeName]; 349 | this.userInterfaces.push( 350 | new TSUserInterface(null, typeName, iface)); 351 | } 352 | //module 353 | for (let moduleName in this.config.interfaces.module) { 354 | for (let typeName in this.config.interfaces.module[moduleName]) { 355 | let iface = this.config.interfaces.module[moduleName][typeName]; 356 | this.userInterfaces.push( 357 | new TSUserInterface(moduleName, typeName, iface)); 358 | } 359 | } 360 | } 361 | 362 | private hoistPubliclyReferencedTypesToPublic(logger: ILogger): Map { 363 | let publicTypes = new Map(); 364 | let context = new TypeVisibilityContext(this); 365 | 366 | //First, visit all known public types and collect referenced types 367 | for (let typedef of this.userTypeAliases) { 368 | typedef.visit(context, this.config, logger); 369 | } 370 | for (let iface of this.userInterfaces) { 371 | iface.visit(context, this.config, logger); 372 | } 373 | this.moduleMembers.forEach((members, moduleName) => { 374 | for (let member of members) { 375 | member.visit(context, this.config, logger); 376 | } 377 | }); 378 | this.globalMembers.forEach((member, moduleName) => { 379 | member.visit(context, this.config, logger); 380 | }); 381 | this.classes.forEach((cls, typeName) => { 382 | if (cls.getIsPublic()) 383 | cls.visit(context, this.config, logger); 384 | }); 385 | this.typedefs.forEach((tdf, typeName) => { 386 | if (tdf.getIsPublic()) 387 | tdf.visit(context, this.config, logger); 388 | }); 389 | 390 | let userTypes = {}; 391 | for (let typedef of this.userTypeAliases) { 392 | userTypes[typedef.getQualifiedName()] = typedef; 393 | } 394 | for (let iface of this.userInterfaces) { 395 | userTypes[iface.getQualifiedName()] = iface; 396 | } 397 | 398 | //Now that we've collected all referenced types, see what isn't public and 399 | //make them public 400 | // 401 | //Each type that is encountered is checked if it is public, if it is not 402 | //public then the type is "promoted" to public and its referenced types are 403 | //added to the context. At the same time, each type that has been checked 404 | //is removed from the context 405 | // 406 | //We repeat this process until the context is empty 407 | // 408 | //But before we start, auto-hoist any type in the "makePublic" list 409 | for (let typeName of this.config.makePublic) { 410 | console.log(`Checking if (${typeName}) needs to be hoisted`); 411 | if (this.classes.has(typeName)) { 412 | let cls = this.classes.get(typeName); 413 | if (!cls.getIsPublic()) { 414 | //logger.warn(`class (${typeName}) is referenced in one or more public APIs, but itself is not public. Making this public`); 415 | cls.setIsPublic(true); 416 | console.log(`Hoisting (${typeName}) to public API`); 417 | //Have to visit to we know what extra types to check for 418 | cls.visit(context, this.config, logger); 419 | } 420 | } else if (this.typedefs.has(typeName)) { 421 | let tdf = this.typedefs.get(typeName); 422 | if (!tdf.getIsPublic()) { 423 | //logger.warn(`typedef (${typeName}) is referenced in one or more public APIs, but itself is not public. Making this public`); 424 | tdf.setIsPublic(true); 425 | console.log(`Hoisting (${typeName}) to public API`); 426 | //Have to visit so we know what extra types to check for 427 | tdf.visit(context, this.config, logger); 428 | } 429 | } 430 | } 431 | 432 | let pass = 1; 433 | while (!context.isEmpty()) { 434 | //NOTE: This is an array copy. Any new types added in this 435 | //pass should not affect the iterated array 436 | let allTypes = context.getTypes(); 437 | //console.log(`Pass ${pass}: ${allTypes.length} types remaining to check`); 438 | for (let typeName of allTypes) { 439 | //console.log(`Checking type: ${typeName}`); 440 | if (this.classes.has(typeName)) { 441 | let cls = this.classes.get(typeName); 442 | if (!cls.getIsPublic()) { 443 | logger.warn(`class (${typeName}) is referenced in one or more public APIs, but itself is not public. Making this public`); 444 | cls.setIsPublic(true); 445 | //Have to visit to we know what extra types to check for 446 | cls.visit(context, this.config, logger); 447 | } else { 448 | publicTypes.set(cls.getFullName(), cls); 449 | } 450 | } else if (this.typedefs.has(typeName)) { 451 | let tdf = this.typedefs.get(typeName); 452 | if (!tdf.getIsPublic()) { 453 | logger.warn(`typedef (${typeName}) is referenced in one or more public APIs, but itself is not public. Making this public`); 454 | tdf.setIsPublic(true); 455 | //Have to visit so we know what extra types to check for 456 | tdf.visit(context, this.config, logger); 457 | } else { 458 | publicTypes.set(tdf.getFullName(), tdf); 459 | } 460 | } else if (userTypes[typeName]) { 461 | //If the user defines a type, it means they want said type on 462 | //the public API surface already. Nothing to do here. 463 | publicTypes.set(userTypes[typeName], userTypes[typeName]); 464 | } else { 465 | //TODO: Generate "any" type alias 466 | //TODO: But only if it is not a built-in type (eg. A DOM class) 467 | logger.warn(`Type (${typeName}) is referenced in one or more public APIs, but no definition for this type found`); 468 | } 469 | //Type has been checked, remove from context 470 | context.removeType(typeName); 471 | } 472 | pass++; 473 | } 474 | 475 | return publicTypes; 476 | } 477 | 478 | private ensureModuleTree(root: ITSModule, moduleNameParts: string[]): ITSModule { 479 | let tree: ITSModule = root; 480 | for (let i = 0; i < moduleNameParts.length; i++) { 481 | let name = moduleNameParts[i]; 482 | //Doesn't exist at this level, make it 483 | if (!tree.children.has(name)) { 484 | tree.children.set(name, { 485 | isRoot: (i == 0), 486 | children: new Map(), 487 | types: [] 488 | }); 489 | } 490 | tree = tree.children.get(name); 491 | } 492 | return tree; 493 | } 494 | 495 | private resolveType(tree: ITSModule, typeNameParts: string[]): TSComposable|ITSModule { 496 | if (typeNameParts.length == 0) { 497 | return null; 498 | } 499 | if (typeNameParts.length == 1) { 500 | let matches = tree.types.filter(t => t.getDoclet().name == typeNameParts[0]); 501 | if (matches.length == 0) { 502 | if (tree.children.has(typeNameParts[0])) { 503 | return tree.children.get(typeNameParts[0]); 504 | } 505 | } 506 | 507 | if (matches.length == 1) { 508 | const match = matches[0]; 509 | const kind = match.getKind(); 510 | if (match instanceof TSComposable) { 511 | return match; 512 | } 513 | } 514 | } else { 515 | if (tree.children.has(typeNameParts[0])) { 516 | const childTree = tree.children.get(typeNameParts[0]); 517 | return this.resolveType(childTree, typeNameParts.slice(1)); 518 | } 519 | } 520 | return null; 521 | } 522 | 523 | private putDefinitionInTree(type: IOutputtable, moduleName: string, root: ITSModule, logger: ILogger): boolean { 524 | if (moduleName == null) { 525 | if (TypeUtil.isTsElementNotPublic(type)) { 526 | return false; 527 | } 528 | root.types.push(type); 529 | return true; 530 | } else { 531 | let moduleNameClean = ModuleUtils.cleanModuleName(moduleName); 532 | if (moduleNameClean.indexOf("#") >= 0) { 533 | //This is an illegal module name and most likely the result of parsing an inner object property 534 | //from within an AMD module (or it could be bad JSDoc documentation) 535 | // 536 | //NOTE: This ultimately doesn't actually do anyting at the moment. All returns will be false and 537 | //this type won't be added, but it should at least log something useful along the way 538 | const parts = moduleNameClean.split("#"); 539 | const parentName = parts[0]; 540 | const memberName = parts[1]; 541 | const resolvedType = this.resolveType(root, parentName.split(".")); 542 | if (resolvedType == null) { 543 | return false; 544 | } 545 | if (resolvedType instanceof TSComposable) { 546 | const resolvedMember = resolvedType.findMember(memberName, false /* # implies instance member */); 547 | if (resolvedMember == null) { 548 | logger.warn(`Type or member (${type.getFullName()}) has a parent of (${moduleNameClean}) which doesn't resolve to any processed type. Skipping this type`); 549 | return false; 550 | } else { 551 | logger.warn(`Type or member (${type.getFullName()}) has a parent of (${moduleNameClean}) which resolves to a known member, but this plugin doesn't know how to process this type yet. Skipping`); 552 | return false; 553 | } 554 | } else { //module 555 | const matchingMembers = resolvedType.types.filter(t => t.getDoclet().name == memberName);; 556 | if (matchingMembers.length == 1) { 557 | logger.warn(`Type or member (${type.getFullName()}) has a parent of (${moduleNameClean}) which doesn't resolve to any processed type. Skipping this type`); 558 | return false; 559 | } else { 560 | logger.warn(`Type or member (${type.getFullName()}) has a parent of (${moduleNameClean}) which resolves to a known module member, but this plugin doesn't know how to process this type yet. Skipping`); 561 | return false; 562 | } 563 | } 564 | } else { 565 | //Before we put the definition in, if it is a function or constant and its parent module is private or 566 | //configured to be ignored, skip it. 567 | let bIgnoreThisType = (type.getKind() == TSOutputtableKind.Method || type.getKind() == TSOutputtableKind.Property) && 568 | ( 569 | (this.moduleDoclets.has(moduleNameClean) && TypeUtil.isPrivateDoclet(this.moduleDoclets.get(moduleNameClean), this.config)) || 570 | (this.config.ignoreModules.indexOf(moduleNameClean) >= 0) 571 | ); 572 | if (bIgnoreThisType) { 573 | return false; 574 | } 575 | 576 | if (TypeUtil.isTsElementNotPublic(type)) { 577 | return false; 578 | } 579 | 580 | if (ModuleUtils.isAMD(moduleNameClean)) { 581 | //No nesting required for AMD modules 582 | if (!root.children.has(moduleNameClean)) { 583 | root.children.set(moduleNameClean, { 584 | isRoot: true, 585 | children: new Map(), 586 | types: [] 587 | }); 588 | } 589 | root.children.get(moduleNameClean).types.push(type); 590 | return true; 591 | } else { 592 | //Explode this module name and see how many levels we need to go 593 | let moduleNameParts = moduleNameClean.split("."); 594 | let tree = this.ensureModuleTree(root, moduleNameParts); 595 | tree.types.push(type); 596 | return true; 597 | } 598 | } 599 | } 600 | } 601 | 602 | /** 603 | * This method groups all of our collected TS types according to their parent module 604 | */ 605 | private assembleModuleTree(logger: ILogger): ITSModule { 606 | let root: ITSModule = { 607 | isRoot: null, 608 | children: new Map(), 609 | types: [] 610 | }; 611 | for (let typedef of this.userTypeAliases) { 612 | let moduleName = typedef.getParentModule(); 613 | if (this.putDefinitionInTree(typedef, moduleName, root, logger)) 614 | this.stats.typedefs.user++; 615 | } 616 | for (let iface of this.userInterfaces) { 617 | let moduleName = iface.getParentModule(); 618 | if (this.putDefinitionInTree(iface, moduleName, root, logger)) 619 | this.stats.ifaces++; 620 | } 621 | for (let oType of this.globalMembers) { 622 | //console.log(`Adding ${oType.getFullName()} to global namespace`); 623 | if (oType instanceof TSMember && !oType.getIsPublic()) 624 | continue; 625 | if (oType instanceof TSComposable && !oType.getIsPublic()) 626 | continue; 627 | root.types.push(oType); 628 | } 629 | this.classes.forEach((cls, typeName) => { 630 | if (!cls.getIsPublic()) 631 | return; 632 | console.log(`Processing class: ${typeName}`); 633 | let moduleName = cls.getParentModule(); 634 | if (this.putDefinitionInTree(cls, moduleName, root, logger)) 635 | this.stats.classes++; 636 | }); 637 | this.typedefs.forEach((tdf, typeName) => { 638 | if (!tdf.getIsPublic()) 639 | return; 640 | console.log(`Processing typedef: ${typeName}`); 641 | let moduleName = tdf.getParentModule(); 642 | if (this.putDefinitionInTree(tdf, moduleName, root, logger)) 643 | this.stats.typedefs.gen++; 644 | }); 645 | this.moduleMembers.forEach((members, modName) => { 646 | for (let member of members) { 647 | if (this.putDefinitionInTree(member, modName, root, logger)) 648 | this.stats.moduleMembers++; 649 | } 650 | }); 651 | return root; 652 | } 653 | 654 | public dumpDoclets(doclets: Readonly[], streamFactory: IFileStreamFactory) { 655 | let fileName = `${this.config.outDir}/${this.config.rootModuleName}.doclets.txt`; 656 | let output = new IndentedOutputStream(streamFactory.createStream(fileName), streamFactory.endl); 657 | 658 | for (let doc of doclets) { 659 | output.writeln(DumpDoclet(doc)); 660 | } 661 | 662 | output.close(() => { 663 | console.log(`Saved dumped doclets to: ${fileName}`); 664 | }); 665 | } 666 | 667 | public process(doclets: Readonly[], streamFactory: IFileStreamFactory, logger: ILogger): void { 668 | let fileName = `${this.config.outDir}/${this.config.rootModuleName}.d.ts`; 669 | let output = new IndentedOutputStream(streamFactory.createStream(fileName), streamFactory.endl); 670 | 671 | //1st pass 672 | this.parseClassesAndTypedefs(doclets); 673 | //2nd pass. We process modules in this pass instead of the 1st so that enums do not get double-registered as modules as well 674 | this.parseModules(doclets); 675 | //3rd pass 676 | this.processTypeMembers(doclets, logger); 677 | //Process user-defined types 678 | this.processUserDefinedTypes(); 679 | //Raise any non-public types referenced from public types to public 680 | let publicTypes = this.hoistPubliclyReferencedTypesToPublic(logger); 681 | 682 | //Write custom header if specified 683 | if (this.config.headerFile != null) { 684 | let header = streamFactory.readText(this.config.headerFile); 685 | output.writeln(header); 686 | } 687 | 688 | const publicApi = new Map(); 689 | 690 | //Write the main d.ts body 691 | let tree = this.assembleModuleTree(logger); 692 | for (let i = 0; i < this.config.initialIndentation; i++) { 693 | output.indent(); 694 | } 695 | ModuleUtils.outputTsd(tree, output, this.config, logger, publicTypes, publicApi); 696 | for (let i = 0; i < this.config.initialIndentation; i++) { 697 | output.unindent(); 698 | } 699 | 700 | //Write custom footer if specified 701 | if (this.config.headerFile != null) { 702 | let footer = streamFactory.readText(this.config.footerFile); 703 | output.writeln(footer); 704 | } 705 | 706 | //Dump public types if required 707 | if (this.config.dumpPublicTypesTo) { 708 | const endl = streamFactory.endl; 709 | const fs = streamFactory.createStream(this.config.dumpPublicTypesTo); 710 | fs.write(`[${endl}`); 711 | let bFirst = true; 712 | publicApi.forEach((value, key) => { 713 | if (!bFirst) { 714 | fs.write(`,${endl}`); 715 | } 716 | const meta = { 717 | fullName: value.getFullName(), 718 | kind: TSOutputtableKind[value.getKind()] 719 | }; 720 | fs.write(JSON.stringify(meta)); 721 | bFirst = false; 722 | }); 723 | fs.write(`]`); 724 | fs.on("finish", () => { 725 | console.log(`Dumped public types to: ${this.config.dumpPublicTypesTo}`); 726 | }); 727 | fs.end(); 728 | } 729 | 730 | output.close(() => { 731 | console.log("Wrote:"); 732 | console.log(` ${this.stats.typedefs.user} user-specified typedefs`); 733 | console.log(` ${this.stats.ifaces} user-specified interfaces`); 734 | console.log(` ${this.stats.moduleMembers} module members`); 735 | console.log(` ${this.stats.typedefs.gen} scanned typedefs`); 736 | console.log(` ${this.stats.classes} scanned classes`); 737 | console.log(`Saved TypeScript definition file to: ${fileName}`); 738 | }); 739 | } 740 | } 741 | } 742 | -------------------------------------------------------------------------------- /test/cesium-tests.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Current baseline: Cesium 1.25 4 | 5 | import Cesium = require("cesium"); 6 | 7 | var viewer = new Cesium.Viewer('cesiumContainer'); 8 | var source = new Cesium.GeoJsonDataSource("name123"); 9 | viewer.dataSources.add(source); 10 | 11 | source.load({ 12 | type: "FeatureCollection", 13 | crs: { 14 | type: "name", 15 | properties: { 16 | name: "urn:ogc:def:crs:OGC:1.3:CRS84" 17 | } 18 | }, 19 | features: [{ 20 | type: "Feature", 21 | properties: { 22 | foo: 123, 23 | }, 24 | geometry: { 25 | type: "Point", 26 | coordinates: [0.1275, 51.5072] // London 27 | }, 28 | id: "123" 29 | }] 30 | }); 31 | 32 | // source.entities.removeAll(); 33 | 34 | // sometime later... 35 | source.load({ 36 | type: "FeatureCollection", 37 | crs: { 38 | type: "name", 39 | properties: { 40 | name: "urn:ogc:def:crs:OGC:1.3:CRS84" 41 | } 42 | }, 43 | features: [{ 44 | type: "Feature", 45 | properties: { 46 | foo: 456, 47 | }, 48 | geometry: { 49 | type: "Point", 50 | coordinates: [-75.1890, 42.3482] // New York 51 | }, 52 | id: "123" 53 | }] 54 | }); -------------------------------------------------------------------------------- /test/ol-tests.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // This tests the ES2015 module definitions in openlayers.d.ts 4 | 5 | // Current baseline: OpenLayers 4.0.1 6 | 7 | // Based on sample from: https://www.npmjs.com/package/ol/ 8 | import Map from 'ol/map'; 9 | import View from 'ol/view'; 10 | import Feature from 'ol/feature'; 11 | 12 | import TileLayer from 'ol/layer/tile'; 13 | import LayerBase from 'ol/layer/base'; 14 | import VectorLayer from 'ol/layer/vector'; 15 | import VectorTileLayer from 'ol/layer/vectortile'; 16 | import ImageLayer from 'ol/layer/image'; 17 | import HeatmapLayer from 'ol/layer/heatmap'; 18 | 19 | import Control from 'ol/control/control'; 20 | import AttributionControl from 'ol/control/attribution'; 21 | import FullScreenControl from 'ol/control/fullscreen'; 22 | import MousePositionControl from 'ol/control/mouseposition'; 23 | import OverviewMapControl from 'ol/control/overviewmap'; 24 | import RotateControl from 'ol/control/rotate'; 25 | import ScaleLineControl from 'ol/control/scaleline'; 26 | import ZoomControl from 'ol/control/zoom'; 27 | import ZoomSliderControl from 'ol/control/zoomslider'; 28 | import ZoomExtentControl from 'ol/control/zoomtoextent'; 29 | 30 | import Geometry from 'ol/geom/geometry'; 31 | import SimpleGeometry from 'ol/geom/simplegeometry'; 32 | import Circle from 'ol/geom/circle'; 33 | import GeometryCollection from 'ol/geom/geometrycollection'; 34 | import MultiLineString from 'ol/geom/multilinestring'; 35 | import MultiPoint from 'ol/geom/multipoint'; 36 | import Point from 'ol/geom/point'; 37 | import MultiPolygon from 'ol/geom/multipolygon'; 38 | import Polygon from 'ol/geom/polygon'; 39 | 40 | import Interaction from 'ol/interaction/interaction'; 41 | import DoubleClickZoom from 'ol/interaction/doubleclickzoom'; 42 | import DragAndDrop from 'ol/interaction/draganddrop'; 43 | import DragBox from 'ol/interaction/dragbox'; 44 | import Pointer from 'ol/interaction/pointer'; 45 | import DragPan from 'ol/interaction/dragpan'; 46 | import DragRotate from 'ol/interaction/dragrotate'; 47 | import DragRotateAndZoom from 'ol/interaction/dragrotateandzoom'; 48 | import DragZoom from 'ol/interaction/dragzoom'; 49 | import Draw from 'ol/interaction/draw'; 50 | import Extent from 'ol/interaction/extent'; 51 | import KeyboardPan from 'ol/interaction/keyboardpan'; 52 | import KeyboardZoom from 'ol/interaction/keyboardzoom'; 53 | import Modify from 'ol/interaction/modify'; 54 | import MouseWheelZoom from 'ol/interaction/mousewheelzoom'; 55 | import PinchRotate from 'ol/interaction/pinchrotate'; 56 | import PinchZoom from 'ol/interaction/pinchzoom'; 57 | import Select from 'ol/interaction/select'; 58 | 59 | import Source from 'ol/source/source'; 60 | import BingMaps from 'ol/source/bingmaps'; 61 | import CartoDB from 'ol/source/cartodb'; 62 | import Cluster from 'ol/source/cluster'; 63 | import ImageArcGISRest from 'ol/source/imagearcgisrest'; 64 | import ImageCanvas from 'ol/source/imagecanvas'; 65 | import ImageMapGuide from 'ol/source/imagemapguide'; 66 | import ImageStatic from 'ol/source/imagestatic'; 67 | import ImageVector from 'ol/source/imagevector'; 68 | import ImageWMS from 'ol/source/imagewms'; 69 | import OSM from 'ol/source/osm'; 70 | import Raster from 'ol/source/raster'; 71 | import Stamen from 'ol/source/stamen'; 72 | import TileImage from 'ol/source/tileimage'; 73 | import TileArcGISRest from 'ol/source/tilearcgisrest'; 74 | import TileDebug from 'ol/source/tiledebug'; 75 | import TileJSON from 'ol/source/tilejson'; 76 | import TileUTFGrid from 'ol/source/tileutfgrid'; 77 | import TileWMS from 'ol/source/tilewms'; 78 | import Vector from 'ol/source/vector'; 79 | import VectorTile from 'ol/source/vectortile'; 80 | import WMTS from 'ol/source/wmts'; 81 | import Zoomify from 'ol/source/zoomify'; 82 | import XYZ from 'ol/source/xyz'; 83 | 84 | import TileGrid from 'ol/tilegrid/tilegrid'; 85 | import WMTSTileGrid from 'ol/tilegrid/wmts'; 86 | 87 | import Collection from 'ol/collection'; 88 | 89 | import olXml from 'ol/xml'; 90 | import olProj from 'ol/proj'; 91 | import olExtent from 'ol/extent'; 92 | 93 | const map = new Map({ 94 | target: 'map', 95 | layers: [ 96 | new TileLayer({ 97 | source: new XYZ({ 98 | url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png' 99 | }) 100 | }) 101 | ], 102 | view: new View({ 103 | center: [0, 0], 104 | zoom: 2 105 | }) 106 | }); 107 | 108 | const view = map.getView(); 109 | view.fit([-180.0, -90.0, 180.0, 90.0]); 110 | 111 | const layers = new Collection(); 112 | layers.push(new ImageLayer()); 113 | layers.push(new TileLayer()); 114 | layers.push(new VectorLayer()); 115 | layers.push(new VectorTileLayer()); 116 | layers.push(new HeatmapLayer()); 117 | 118 | layers.forEach((layer) => { 119 | map.addLayer(layer); 120 | }); 121 | 122 | const geometries = new Collection(); 123 | geometries.push(new SimpleGeometry()); 124 | geometries.push(new Circle([1, 1], 2)); 125 | geometries.push(new GeometryCollection()); 126 | geometries.push(new MultiLineString([])); 127 | geometries.push(new MultiPoint([])); 128 | geometries.push(new Point([1, 1])); 129 | geometries.push(new MultiPolygon([])); 130 | geometries.push(new Polygon([])); 131 | 132 | const controls = new Collection(); 133 | controls.push(new AttributionControl()); 134 | controls.push(new FullScreenControl()); 135 | controls.push(new MousePositionControl()); 136 | controls.push(new OverviewMapControl()); 137 | controls.push(new RotateControl()); 138 | controls.push(new ScaleLineControl()); 139 | controls.push(new ZoomControl()); 140 | controls.push(new ZoomSliderControl()); 141 | controls.push(new ZoomExtentControl()); 142 | 143 | controls.forEach((ctrl) => { 144 | map.addControl(ctrl); 145 | }); 146 | 147 | const features = new Collection(); 148 | 149 | const inter = new Collection(); 150 | inter.push(new DoubleClickZoom()); 151 | inter.push(new DragAndDrop()); 152 | inter.push(new DragBox()); 153 | inter.push(new Pointer()); 154 | inter.push(new DragPan()); 155 | inter.push(new DragRotate()); 156 | inter.push(new DragRotateAndZoom()); 157 | inter.push(new DragZoom()); 158 | inter.push(new Draw({ 159 | type: "Point" 160 | })); 161 | inter.push(new Extent()); 162 | inter.push(new KeyboardPan()); 163 | inter.push(new KeyboardZoom()); 164 | inter.push(new Modify({ 165 | features: features 166 | })); 167 | inter.push(new MouseWheelZoom()); 168 | inter.push(new PinchRotate()); 169 | inter.push(new PinchZoom()); 170 | inter.push(new Select()); 171 | 172 | const sources = new Collection(); 173 | sources.push(new BingMaps({ 174 | key: "abcd1234", 175 | imagerySet: "satellite" 176 | })); 177 | sources.push(new TileImage({})); 178 | sources.push(new CartoDB({ 179 | account: "test" 180 | })); 181 | sources.push(new XYZ()); 182 | sources.push(new Cluster({ 183 | source: new Vector() 184 | })); 185 | sources.push(new ImageArcGISRest()); 186 | sources.push(new ImageCanvas({ 187 | canvasFunction: () => null 188 | })); 189 | sources.push(new ImageMapGuide({})); 190 | sources.push(new ImageStatic({ 191 | imageExtent: [-180.0, -90.0, 180.0, 90.0], 192 | projection: "EPSG:4326", 193 | url: "adsjfdsf" 194 | })); 195 | sources.push(new ImageVector({ 196 | source: new Vector() 197 | })); 198 | sources.push(new ImageWMS()); 199 | sources.push(new OSM()); 200 | sources.push(new Raster({ 201 | sources: sources.getArray() 202 | })); 203 | sources.push(new Stamen({ 204 | layer: "toner" 205 | })); 206 | sources.push(new TileArcGISRest()); 207 | sources.push(new TileDebug({})); 208 | sources.push(new TileJSON({ 209 | url: "asdjkdf" 210 | })); 211 | sources.push(new TileUTFGrid({})); 212 | sources.push(new TileWMS()); 213 | sources.push(new VectorTile({})); 214 | sources.push(new WMTS({ 215 | tileGrid: new WMTSTileGrid({ 216 | resolutions: [], 217 | matrixIds: [] 218 | }), 219 | projection: "EPSG:4326", 220 | layer: "blah", 221 | style: "default", 222 | matrixSet: "thereisnospoon" 223 | })); 224 | sources.push(new Zoomify()); 225 | 226 | olXml.parse("Bar"); 227 | const tx = olProj.fromLonLat([0, 0]); 228 | const center = olExtent.getCenter([1, 2, 3, 4]); -------------------------------------------------------------------------------- /test/openlayers-tests.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Current baseline: OpenLayers 4.0.1 4 | 5 | // Basic type variables for test functions 6 | var voidValue: void; 7 | var numberValue: number; 8 | var booleanValue: boolean; 9 | var stringValue: string; 10 | var jsonValue: JSON; 11 | 12 | // Callback predefinitions for OpenLayers 13 | var preRenderFunction: ol.PreRenderFunction; 14 | var transformFunction: ol.TransformFunction; 15 | var coordinateFormatType: ol.CoordinateFormatType; 16 | var featureStyleFunction: ol.FeatureStyleFunction; 17 | var featureLoader: ol.FeatureLoader; 18 | var easingFunction: (t: number) => number; 19 | 20 | // Type variables for OpenLayers 21 | var circle: ol.geom.Circle; 22 | var color: ol.Color; 23 | var coordinate: ol.Coordinate; 24 | var coordinatesArray: Array; 25 | var coordinatesArrayDim2: Array>; 26 | var extent: ol.Extent; 27 | var boundingCoordinates: Array; 28 | var size: ol.Size; 29 | var style: ol.style.Style; 30 | var styleArray: Array; 31 | var feature: ol.Feature; 32 | var featureArray: Array; 33 | var graticule: ol.Graticule 34 | var geometry: ol.geom.Geometry; 35 | var geometriesArray: Array; 36 | var feature: ol.Feature; 37 | var featureArray: Array; 38 | var featureFormat: ol.format.Feature; 39 | var geometry: ol.geom.Geometry; 40 | var geometryCollection: ol.geom.GeometryCollection; 41 | var geometryLayout: ol.geom.GeometryLayout; 42 | var geometryType: ol.geom.GeometryType; 43 | var linearRing: ol.geom.LinearRing; 44 | var lineString: ol.geom.LineString; 45 | var loadingstrategy: ol.LoadingStrategy; 46 | var multiLineString: ol.geom.MultiLineString; 47 | var multiPoint: ol.geom.MultiPoint; 48 | var multiPolygon: ol.geom.MultiPolygon; 49 | var point: ol.geom.Point; 50 | var polygon: ol.geom.Polygon; 51 | var simpleGeometry: ol.geom.SimpleGeometry; 52 | var tilegrid: ol.tilegrid.TileGrid; 53 | var vector: ol.source.Vector; 54 | var projection: ol.proj.Projection; 55 | var projectionLike: ol.ProjectionLike; 56 | var transformFn: ol.TransformFunction; 57 | 58 | // 59 | // ol.Attribution 60 | // 61 | 62 | var attribution: ol.Attribution = new ol.Attribution({ 63 | html: stringValue, 64 | }); 65 | 66 | // 67 | // ol.color 68 | // 69 | color = ol.color.asArray(color); 70 | color = ol.color.asArray(stringValue); 71 | stringValue = ol.color.asString(color); 72 | stringValue = ol.color.asString(stringValue); 73 | 74 | // 75 | // ol.extent 76 | // 77 | transformFunction = function (input: number[]) { 78 | var returnData: number[]; 79 | return returnData; 80 | }; 81 | transformFunction = function (input: number[], output: number[]) { 82 | var returnData: number[]; 83 | return returnData; 84 | }; 85 | transformFunction = function (input: number[], output: number[], dimension: number) { 86 | var returnData: number[]; 87 | return returnData; 88 | } 89 | extent = ol.extent.applyTransform(extent, transformFunction); 90 | ol.extent.applyTransform(extent, transformFunction, extent); 91 | extent = ol.extent.boundingExtent(boundingCoordinates) 92 | extent = ol.extent.buffer(extent, numberValue); 93 | ol.extent.buffer(extent, numberValue, extent); 94 | booleanValue = ol.extent.containsCoordinate(extent, coordinate); 95 | booleanValue = ol.extent.containsExtent(extent, extent); 96 | booleanValue = ol.extent.containsXY(extent, numberValue, numberValue); 97 | extent = ol.extent.createEmpty(); 98 | booleanValue = ol.extent.equals(extent, extent); 99 | extent = ol.extent.extend(extent, extent); 100 | coordinate = ol.extent.getBottomLeft(extent); 101 | coordinate = ol.extent.getBottomRight(extent); 102 | coordinate = ol.extent.getCenter(extent); 103 | numberValue = ol.extent.getHeight(extent); 104 | extent = ol.extent.getIntersection(extent, extent); 105 | ol.extent.getIntersection(extent, extent, extent); 106 | size = ol.extent.getSize(extent); 107 | coordinate = ol.extent.getTopLeft(extent); 108 | coordinate = ol.extent.getTopRight(extent); 109 | numberValue = ol.extent.getWidth(extent); 110 | booleanValue = ol.extent.intersects(extent, extent); 111 | booleanValue = ol.extent.isEmpty(extent); 112 | 113 | // 114 | // ol.featureloader 115 | // 116 | featureLoader = ol.featureloader.xhr(stringValue, featureFormat); 117 | 118 | // 119 | // ol.loadingstrategy 120 | // 121 | loadingstrategy = ol.loadingstrategy.all; 122 | loadingstrategy = ol.loadingstrategy.bbox; 123 | loadingstrategy = ol.loadingstrategy.tile(tilegrid); 124 | 125 | // 126 | // 127 | // ol.geom.Circle 128 | // 129 | booleanValue = circle.intersectsExtent(extent); 130 | circle = circle.transform(projectionLike, projectionLike); 131 | 132 | // 133 | // 134 | // ol.geom.Geometry 135 | // 136 | var geometryResult: ol.geom.Geometry; 137 | coordinate = geometryResult.getClosestPoint(coordinate); 138 | geometryResult.getClosestPoint(coordinate, coordinate); 139 | extent = geometryResult.getExtent(); 140 | geometryResult.getExtent(extent); 141 | 142 | // 143 | // 144 | // ol.geom.GeometryCollection 145 | // 146 | geometryCollection = new ol.geom.GeometryCollection(geometriesArray) 147 | geometryCollection = new ol.geom.GeometryCollection(); 148 | voidValue = geometryCollection.applyTransform(transformFn); 149 | geometryCollection = geometryCollection.clone(); 150 | geometriesArray = geometryCollection.getGeometries(); 151 | geometryType = geometryCollection.getType(); 152 | booleanValue = geometryCollection.intersectsExtent(extent); 153 | voidValue = geometryCollection.setGeometries(geometriesArray); 154 | 155 | // 156 | // 157 | // ol.geom.LinearRing 158 | // 159 | linearRing = new ol.geom.LinearRing(coordinatesArray); 160 | linearRing = new ol.geom.LinearRing(coordinatesArray, ol.geom.GeometryLayout.XY); 161 | linearRing = new ol.geom.LinearRing(coordinatesArray, ol.geom.GeometryLayout.XYM); 162 | linearRing = new ol.geom.LinearRing(coordinatesArray, ol.geom.GeometryLayout.XYZ); 163 | linearRing = new ol.geom.LinearRing(coordinatesArray, ol.geom.GeometryLayout.XYZM); 164 | linearRing = linearRing.clone(); 165 | numberValue = linearRing.getArea(); 166 | coordinatesArray = linearRing.getCoordinates(); 167 | geometryType = linearRing.getType(); 168 | voidValue = linearRing.setCoordinates(coordinatesArray); 169 | voidValue = linearRing.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XY); 170 | voidValue = linearRing.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYM); 171 | voidValue = linearRing.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYZ); 172 | voidValue = linearRing.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYZM); 173 | 174 | // 175 | // 176 | // ol.geom.LineString 177 | // 178 | lineString = new ol.geom.LineString(coordinatesArray); 179 | lineString = new ol.geom.LineString(coordinatesArray, ol.geom.GeometryLayout.XY); 180 | lineString = new ol.geom.LineString(coordinatesArray, ol.geom.GeometryLayout.XYM); 181 | lineString = new ol.geom.LineString(coordinatesArray, ol.geom.GeometryLayout.XYZ); 182 | lineString = new ol.geom.LineString(coordinatesArray, ol.geom.GeometryLayout.XYZM); 183 | voidValue = lineString.appendCoordinate(coordinate); 184 | lineString = lineString.clone(); 185 | coordinate = lineString.getCoordinateAtM(numberValue); 186 | coordinate = lineString.getCoordinateAtM(numberValue, booleanValue); 187 | coordinatesArray = lineString.getCoordinates(); 188 | numberValue = lineString.getLength(); 189 | geometryType = lineString.getType(); 190 | booleanValue = lineString.intersectsExtent(extent); 191 | voidValue = lineString.setCoordinates(coordinatesArray); 192 | voidValue = lineString.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XY); 193 | voidValue = lineString.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYM); 194 | voidValue = lineString.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYZ); 195 | voidValue = lineString.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYZM); 196 | 197 | // 198 | // 199 | // ol.geom.MultiLineString 200 | // 201 | var lineStringsArray: Array; 202 | 203 | multiLineString = new ol.geom.MultiLineString(coordinatesArrayDim2); 204 | multiLineString = new ol.geom.MultiLineString(coordinatesArrayDim2, ol.geom.GeometryLayout.XY); 205 | multiLineString = new ol.geom.MultiLineString(coordinatesArrayDim2, ol.geom.GeometryLayout.XYM); 206 | multiLineString = new ol.geom.MultiLineString(coordinatesArrayDim2, ol.geom.GeometryLayout.XYZ); 207 | multiLineString = new ol.geom.MultiLineString(coordinatesArrayDim2, ol.geom.GeometryLayout.XYZM); 208 | voidValue = multiLineString.appendLineString(lineString); 209 | multiLineString = multiLineString.clone(); 210 | coordinate = multiLineString.getCoordinateAtM(numberValue); 211 | coordinate = multiLineString.getCoordinateAtM(numberValue, booleanValue); 212 | coordinate = multiLineString.getCoordinateAtM(numberValue, booleanValue, booleanValue); 213 | coordinatesArrayDim2 = multiLineString.getCoordinates(); 214 | lineString = multiLineString.getLineString(numberValue); 215 | lineStringsArray = multiLineString.getLineStrings(); 216 | geometryType = multiLineString.getType(); 217 | booleanValue = multiLineString.intersectsExtent(extent); 218 | voidValue = multiLineString.setCoordinates(coordinatesArrayDim2); 219 | voidValue = multiLineString.setCoordinates(coordinatesArrayDim2, ol.geom.GeometryLayout.XY); 220 | voidValue = multiLineString.setCoordinates(coordinatesArrayDim2, ol.geom.GeometryLayout.XYM); 221 | voidValue = multiLineString.setCoordinates(coordinatesArrayDim2, ol.geom.GeometryLayout.XYZ); 222 | voidValue = multiLineString.setCoordinates(coordinatesArrayDim2, ol.geom.GeometryLayout.XYZM); 223 | 224 | // 225 | // 226 | // ol.geom.MultiPoint 227 | // 228 | var pointsArray: Array; 229 | 230 | multiPoint = new ol.geom.MultiPoint(coordinatesArray); 231 | multiPoint = new ol.geom.MultiPoint(coordinatesArray, ol.geom.GeometryLayout.XY); 232 | multiPoint = new ol.geom.MultiPoint(coordinatesArray, ol.geom.GeometryLayout.XYM); 233 | multiPoint = new ol.geom.MultiPoint(coordinatesArray, ol.geom.GeometryLayout.XYZ); 234 | multiPoint = new ol.geom.MultiPoint(coordinatesArray, ol.geom.GeometryLayout.XYZM); 235 | voidValue = multiPoint.appendPoint(point); 236 | multiPoint = multiPoint.clone(); 237 | coordinatesArray = multiPoint.getCoordinates(); 238 | point = multiPoint.getPoint(numberValue); 239 | pointsArray = multiPoint.getPoints(); 240 | geometryType = multiPoint.getType(); 241 | booleanValue = multiPoint.intersectsExtent(extent); 242 | voidValue = multiPoint.setCoordinates(coordinatesArray); 243 | voidValue = multiPoint.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XY); 244 | voidValue = multiPoint.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYM); 245 | voidValue = multiPoint.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYZ); 246 | voidValue = multiPoint.setCoordinates(coordinatesArray, ol.geom.GeometryLayout.XYZM); 247 | 248 | // 249 | // 250 | // ol.geom.MultiPolygon 251 | // 252 | var coordinatesArrayDim3: Array>>; 253 | var polygonsArray: Array; 254 | 255 | multiPolygon = new ol.geom.MultiPolygon(coordinatesArrayDim3); 256 | multiPolygon = new ol.geom.MultiPolygon(coordinatesArrayDim3, ol.geom.GeometryLayout.XY); 257 | multiPolygon = new ol.geom.MultiPolygon(coordinatesArrayDim3, ol.geom.GeometryLayout.XYM); 258 | multiPolygon = new ol.geom.MultiPolygon(coordinatesArrayDim3, ol.geom.GeometryLayout.XYZ); 259 | multiPolygon = new ol.geom.MultiPolygon(coordinatesArrayDim3, ol.geom.GeometryLayout.XYZM); 260 | voidValue = multiPolygon.appendPolygon(polygon); 261 | multiPolygon = multiPolygon.clone(); 262 | numberValue = multiPolygon.getArea(); 263 | coordinatesArrayDim3 = multiPolygon.getCoordinates(); 264 | coordinatesArrayDim3 = multiPolygon.getCoordinates(booleanValue); 265 | multiPoint = multiPolygon.getInteriorPoints(); 266 | polygon = multiPolygon.getPolygon(numberValue); 267 | polygonsArray = multiPolygon.getPolygons(); 268 | geometryType = multiPolygon.getType(); 269 | booleanValue = multiPolygon.intersectsExtent(extent); 270 | voidValue = multiPolygon.setCoordinates(coordinatesArrayDim3); 271 | voidValue = multiPolygon.setCoordinates(coordinatesArrayDim3, ol.geom.GeometryLayout.XY); 272 | voidValue = multiPolygon.setCoordinates(coordinatesArrayDim3, ol.geom.GeometryLayout.XYM); 273 | voidValue = multiPolygon.setCoordinates(coordinatesArrayDim3, ol.geom.GeometryLayout.XYZ); 274 | voidValue = multiPolygon.setCoordinates(coordinatesArrayDim3, ol.geom.GeometryLayout.XYZM); 275 | 276 | // 277 | // 278 | // ol.geom.Point 279 | // 280 | point = new ol.geom.Point(coordinate); 281 | point = new ol.geom.Point(coordinate, ol.geom.GeometryLayout.XY); 282 | point = new ol.geom.Point(coordinate, ol.geom.GeometryLayout.XYM); 283 | point = new ol.geom.Point(coordinate, ol.geom.GeometryLayout.XYZ); 284 | point = new ol.geom.Point(coordinate, ol.geom.GeometryLayout.XYZM); 285 | point = point.clone(); 286 | coordinate = point.getCoordinates(); 287 | geometryType = point.getType(); 288 | booleanValue = point.intersectsExtent(extent); 289 | voidValue = point.setCoordinates(coordinate); 290 | voidValue = point.setCoordinates(coordinate, ol.geom.GeometryLayout.XY); 291 | voidValue = point.setCoordinates(coordinate, ol.geom.GeometryLayout.XYM); 292 | voidValue = point.setCoordinates(coordinate, ol.geom.GeometryLayout.XYZ); 293 | voidValue = point.setCoordinates(coordinate, ol.geom.GeometryLayout.XYZM); 294 | 295 | // 296 | // 297 | // ol.geom.Polygon 298 | // 299 | var localSphere: ol.Sphere; 300 | var linearRingsArray: Array; 301 | 302 | polygon = new ol.geom.Polygon(coordinatesArrayDim2); 303 | polygon = new ol.geom.Polygon(coordinatesArrayDim2, ol.geom.GeometryLayout.XY); 304 | polygon = new ol.geom.Polygon(coordinatesArrayDim2, ol.geom.GeometryLayout.XYM); 305 | polygon = new ol.geom.Polygon(coordinatesArrayDim2, ol.geom.GeometryLayout.XYZ); 306 | polygon = new ol.geom.Polygon(coordinatesArrayDim2, ol.geom.GeometryLayout.XYZM); 307 | polygon = ol.geom.Polygon.circular(localSphere, coordinate, numberValue); 308 | polygon = ol.geom.Polygon.circular(localSphere, coordinate, numberValue, numberValue); 309 | voidValue = polygon.appendLinearRing(linearRing); 310 | polygon = polygon.clone(); 311 | numberValue = polygon.getArea(); 312 | coordinatesArrayDim2 = polygon.getCoordinates(); 313 | coordinatesArrayDim2 = polygon.getCoordinates(booleanValue); 314 | point = polygon.getInteriorPoint(); 315 | linearRing = polygon.getLinearRing(numberValue); 316 | linearRingsArray = polygon.getLinearRings(); 317 | geometryType = polygon.getType(); 318 | booleanValue = polygon.intersectsExtent(extent); 319 | 320 | // 321 | // 322 | // ol.geom.SimpleGeometry 323 | // 324 | simpleGeometry.applyTransform(transformFn); 325 | coordinate = simpleGeometry.getFirstCoordinate(); 326 | coordinate = simpleGeometry.getLastCoordinate(); 327 | geometryLayout = simpleGeometry.getLayout(); 328 | voidValue = simpleGeometry.translate(numberValue, numberValue); 329 | 330 | // 331 | // ol.source 332 | // 333 | vector = new ol.source.Vector({ 334 | features: [feature] 335 | }); 336 | 337 | // 338 | // ol.Feature 339 | // 340 | feature = new ol.Feature(); 341 | feature = new ol.Feature(geometry); 342 | feature = new ol.Feature({ 343 | geometry: geometry 344 | }); 345 | feature = feature.clone(); 346 | geometry = feature.getGeometry(); 347 | stringValue = feature.getGeometryName(); 348 | var featureGetId: string | number = feature.getId(); 349 | var featureGetStyle: ol.style.Style | Array | ol.FeatureStyleFunction | ol.StyleFunction = feature.getStyle(); 350 | featureStyleFunction = feature.getStyleFunction(); 351 | voidValue = feature.setGeometry(geometry); 352 | voidValue = feature.setGeometryName(stringValue); 353 | voidValue = feature.setId(stringValue); 354 | voidValue = feature.setId(numberValue); 355 | voidValue = feature.setStyle(style); 356 | voidValue = feature.setStyle(styleArray); 357 | voidValue = feature.setStyle(featureStyleFunction); 358 | 359 | // 360 | // ol.View 361 | // 362 | 363 | var view: ol.View = new ol.View({ 364 | center: [0, 0], 365 | zoom: numberValue, 366 | }); 367 | 368 | // 369 | // ol.layer.Tile 370 | // 371 | var tileLayer: ol.layer.Tile = new ol.layer.Tile({ 372 | source: new ol.source.OSM() 373 | }); 374 | 375 | // 376 | // ol.proj 377 | // 378 | projection = new ol.proj.Projection({ 379 | code:stringValue, 380 | }); 381 | 382 | // 383 | // ol.Map 384 | // 385 | 386 | var map: ol.Map = new ol.Map({ 387 | view: view, 388 | layers: [tileLayer], 389 | target: stringValue 390 | }); 391 | 392 | map.getView().animate(preRenderFunction); 393 | 394 | // 395 | // ol.source.ImageWMS 396 | // 397 | var imageWMS: ol.source.ImageWMS = new ol.source.ImageWMS({ 398 | serverType: stringValue, 399 | url:stringValue, 400 | params: {} 401 | }); 402 | // 403 | // ol.source.TileWMS 404 | // 405 | var tileWMS: ol.source.TileWMS = new ol.source.TileWMS({ 406 | params: {}, 407 | serverType: stringValue, 408 | url:stringValue 409 | }); 410 | 411 | // 412 | // ol.source.WMTS 413 | // 414 | var wmts: ol.source.WMTS = new ol.source.WMTS({ 415 | tileGrid: new ol.tilegrid.WMTS({ 416 | resolutions: [], 417 | matrixIds: [] 418 | }), 419 | layer: "", 420 | style: "", 421 | matrixSet: "", 422 | wrapX: true 423 | }); 424 | 425 | // 426 | // ol.coordinate 427 | // 428 | coordinate = ol.coordinate.add(coordinate, coordinate); 429 | coordinateFormatType = ol.coordinate.createStringXY(); 430 | coordinateFormatType = ol.coordinate.createStringXY(numberValue); 431 | stringValue = ol.coordinate.format(coordinate, stringValue); 432 | stringValue = ol.coordinate.format(coordinate, stringValue, numberValue); 433 | coordinate = ol.coordinate.rotate(coordinate, numberValue); 434 | stringValue = ol.coordinate.toStringHDMS(); 435 | stringValue = ol.coordinate.toStringHDMS(coordinate); 436 | stringValue = ol.coordinate.toStringXY(); 437 | stringValue = ol.coordinate.toStringXY(coordinate); 438 | stringValue = ol.coordinate.toStringXY(coordinate, numberValue); 439 | 440 | // 441 | // ol.easing 442 | // 443 | easingFunction = ol.easing.easeIn; 444 | easingFunction = ol.easing.easeOut; 445 | easingFunction = ol.easing.inAndOut; 446 | easingFunction = ol.easing.linear; 447 | easingFunction = ol.easing.upAndDown; 448 | 449 | // 450 | // ol.Geolocation 451 | // 452 | var geolocation: ol.Geolocation = new ol.Geolocation({ 453 | projection: projection 454 | }); 455 | geolocation.on('change', function (evt) { 456 | window.console.log(geolocation.getPosition()); 457 | }); 458 | 459 | // 460 | // ol.Graticule 461 | // 462 | 463 | graticule = new ol.Graticule(); 464 | graticule = new ol.Graticule({ 465 | map: map, 466 | }); 467 | var graticuleMap: ol.Map = graticule.getMap(); 468 | var graticuleMeridians: Array = graticule.getMeridians(); 469 | var graticuleParallels: Array = graticule.getParallels(); 470 | graticule.setMap(graticuleMap); 471 | 472 | // 473 | // ol.DeviceOrientation 474 | // 475 | 476 | var deviceOrientation: ol.DeviceOrientation = new ol.DeviceOrientation({ 477 | tracking: true, 478 | }); 479 | deviceOrientation.on('change', function (evt) { 480 | window.console.log(deviceOrientation.getHeading()); 481 | }); 482 | 483 | // 484 | // ol.Overlay 485 | // 486 | 487 | var popup: ol.Overlay = new ol.Overlay({ 488 | element: document.getElementById('popup') 489 | }); 490 | map.addOverlay(popup); 491 | var popupElement: Element = popup.getElement(); 492 | var popupMap: ol.Map = popup.getMap(); 493 | var popupOffset: Array = popup.getOffset(); 494 | coordinate = popup.getPosition(); 495 | var popupPositioning = popup.getPositioning(); 496 | popup.setElement(popupElement); 497 | popup.setMap(popupMap); 498 | popup.setOffset(popupOffset); 499 | popup.setPosition(coordinate); 500 | popup.setPositioning(popupPositioning); 501 | popup.setPositioning(ol.OverlayPositioning.BOTTOM_CENTER); 502 | popup.setPositioning(ol.OverlayPositioning.BOTTOM_LEFT); 503 | popup.setPositioning(ol.OverlayPositioning.BOTTOM_RIGHT); 504 | popup.setPositioning(ol.OverlayPositioning.CENTER_CENTER); 505 | popup.setPositioning(ol.OverlayPositioning.CENTER_LEFT); 506 | popup.setPositioning(ol.OverlayPositioning.CENTER_RIGHT); 507 | popup.setPositioning(ol.OverlayPositioning.TOP_CENTER); 508 | popup.setPositioning(ol.OverlayPositioning.TOP_LEFT); 509 | popup.setPositioning(ol.OverlayPositioning.TOP_RIGHT); 510 | 511 | // 512 | // ol.format.GeoJSON 513 | // 514 | 515 | var geojsonOptions: olx.format.GeoJSONOptions; 516 | geojsonOptions.defaultDataProjection = "EPSG"; 517 | geojsonOptions.defaultDataProjection = projection; 518 | geojsonOptions.geometryName = "geom"; 519 | 520 | var geojsonFormat: ol.format.GeoJSON; 521 | geojsonFormat = new ol.format.GeoJSON(); 522 | geojsonFormat = new ol.format.GeoJSON(geojsonOptions); 523 | 524 | // Test options 525 | var readOptions: olx.format.ReadOptions; 526 | readOptions.dataProjection = "EPSG"; 527 | readOptions.dataProjection = projection; 528 | readOptions.featureProjection = "EPSG"; 529 | readOptions.featureProjection = projection; 530 | 531 | var writeOptions: olx.format.WriteOptions; 532 | writeOptions.dataProjection = "EPSG"; 533 | writeOptions.dataProjection = projection; 534 | writeOptions.featureProjection = "EPSG"; 535 | writeOptions.featureProjection = projection; 536 | writeOptions.rightHanded = false; 537 | 538 | // Test functions 539 | feature = geojsonFormat.readFeature("json"); 540 | feature = geojsonFormat.readFeature("json", readOptions); 541 | featureArray = geojsonFormat.readFeatures("json"); 542 | featureArray = geojsonFormat.readFeatures("json", readOptions); 543 | geometry = geojsonFormat.readGeometry("geometry"); 544 | geometry = geojsonFormat.readGeometry("geometry", readOptions); 545 | stringValue = geojsonFormat.writeFeature(feature); 546 | stringValue = geojsonFormat.writeFeature(feature, writeOptions); 547 | stringValue = geojsonFormat.writeFeatures(featureArray); 548 | stringValue = geojsonFormat.writeFeatures(featureArray, writeOptions); 549 | stringValue = geojsonFormat.writeGeometry(geometry); 550 | stringValue = geojsonFormat.writeGeometry(geometry, writeOptions); 551 | jsonValue = geojsonFormat.writeFeatureObject(feature); 552 | jsonValue = geojsonFormat.writeFeatureObject(feature, writeOptions); 553 | jsonValue = geojsonFormat.writeFeaturesObject(featureArray); 554 | jsonValue = geojsonFormat.writeFeaturesObject(featureArray, writeOptions); 555 | jsonValue = geojsonFormat.writeGeometryObject(geometry); 556 | jsonValue = geojsonFormat.writeGeometryObject(geometry, writeOptions); 557 | 558 | // 559 | // ol.interactions 560 | // 561 | var modify: ol.interaction.Modify = new ol.interaction.Modify({ 562 | features: new ol.Collection(featureArray) 563 | }); 564 | 565 | var draw: ol.interaction.Draw = new ol.interaction.Draw({ 566 | type: "Point" 567 | }) -------------------------------------------------------------------------------- /tools/ol-postprocess.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ol-postprocess.js 3 | * 4 | * This script generates TypeScript ES2015 module declarations from a JSON file containing public types 5 | * dumped by the jsdoc-typescript-plugin and appends them to a openlayers.d.ts file 6 | */ 7 | const os = require("os"); 8 | const fs = require("fs"); 9 | const path = require("path"); 10 | const jsonfile = require("jsonfile"); 11 | 12 | if (process.argv.length != 4) { 13 | console.log("Usage: node ol-postprocess.js [path/to/public.json] [path/to/openlayers.d.ts]") 14 | process.exit(1); 15 | } 16 | 17 | const publicJsonPath = path.resolve(process.argv[2]); 18 | const dtsPath = path.resolve(process.argv[3]); 19 | 20 | if (!fs.existsSync(dtsPath)) { 21 | console.error("File not found: " + dtsPath); 22 | process.exit(1); 23 | } 24 | 25 | console.log("public types path: " + publicJsonPath); 26 | console.log("openlayers.d.ts path: " + dtsPath); 27 | 28 | jsonfile.readFile(publicJsonPath, function(err, obj) { 29 | if (err) { 30 | console.error(err); 31 | process.exit(1); 32 | } 33 | 34 | // OL ES2015 modules follow a very simple convention which makes this easy to implement. 35 | // 36 | // For a fully dotted class, replace the dots with '/' and lowercase all identifiers between 37 | // That name is your ES2015 module name and we just re-export said identifier as a default export 38 | // 39 | // For example, the ES2015 for ol.Map would look like this: 40 | // 41 | // declare module "ol/map" { 42 | // export default ol.Map; 43 | // } 44 | // 45 | 46 | var esClasses = obj.filter(function(val) { 47 | return val.kind == "Class"; 48 | }).map(function(val, index) { 49 | return { 50 | module: val.fullName.split(".").map(function(t) { return t.toLowerCase() }).join("/"), 51 | export: val.fullName 52 | }; 53 | }); 54 | 55 | esClasses.forEach(function(cls) { 56 | var def = "/*" + os.EOL; 57 | def += " * ES2015 module declaration for " + cls.export + os.EOL; 58 | def += " */" + os.EOL; 59 | def += 'declare module "' + cls.module + '" {' + os.EOL; 60 | def += " export default " + cls.export + ";" + os.EOL; 61 | def += "}" + os.EOL; 62 | fs.appendFileSync(dtsPath, def); 63 | console.log("Wrote ES2015 module for: " + cls.export); 64 | }); 65 | 66 | var esModules = new Map(); 67 | obj.filter(function(val) { 68 | return val.kind == "Method" 69 | }).forEach(function(meth) { 70 | const tokens = meth.fullName.split("."); 71 | const parent = tokens.slice(0, tokens.length - 1); 72 | const dotted = parent.join("."); 73 | if (dotted != "" && dotted != "ol") { //HACK: Typedefs mis-classified as functions are being emitted by the plugin, so skip them for now 74 | if (!esModules.has(dotted)) { 75 | esModules.set(dotted, { 76 | module: parent.join("/"), 77 | exportMembers: [] 78 | }); 79 | } 80 | esModules.get(dotted).exportMembers.push({ name: tokens[tokens.length - 1], fullName: meth.fullName }); 81 | } 82 | }); 83 | 84 | esModules.forEach(function(mod) { 85 | var def = "/*" + os.EOL; 86 | def += " * ES2015 module declaration for " + mod.module.split("/").join(".") + os.EOL; 87 | def += " */" + os.EOL; 88 | def += 'declare module "' + mod.module + '" {' + os.EOL; 89 | //This method no longer works for TS 2.6 90 | /* 91 | def += " declare const _default: {" + os.EOL; 92 | for (var i = 0; i < mod.exportMembers.length; i++) { 93 | def += " " + mod.exportMembers[i].name + ": " + mod.exportMembers[i].fullName; 94 | if (i < mod.exportMembers.length - 1) { 95 | def += ","; 96 | } 97 | def += os.EOL; 98 | } 99 | def += " };" + os.EOL; 100 | def += " export default _default;" + os.EOL; 101 | */ 102 | def += " const _default: typeof " + mod.module.split("/").join(".") + ";" + os.EOL; 103 | def += " export default _default;" + os.EOL; 104 | def += "}" + os.EOL; 105 | fs.appendFileSync(dtsPath, def); 106 | console.log("Wrote ES2015 module for: " + mod.module.split("/").join(".")); 107 | }); 108 | }); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "none", 4 | "target": "es5", 5 | "noImplicitAny": false, 6 | "outFile": "plugins/typescript.js", 7 | "sourceMap": true, 8 | "lib": ["es6", "dom"] 9 | }, 10 | "include": [ 11 | "src/**/*.ts" 12 | ], 13 | "files": [ 14 | "typings/tsd.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "node/node.d.ts": { 9 | "commit": "717a5fdb079f8dd7c19f1b22f7f656dd990f0ccf" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /typings/misc.baseline.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | */ 3 | declare function returnFoo(): Foo; 4 | /** 5 | */ 6 | declare function returnFoo2(): Foo>; 7 | /** 8 | * @param value (Optional) Somebody's name 9 | */ 10 | declare function optionalFunc(value?: string): any; 11 | /** 12 | * @param value (Optional) Somebody's name 13 | */ 14 | declare function optionalFunc2(value?: string): any; 15 | /** 16 | * @param value (Optional) Somebody's name 17 | */ 18 | declare function defaultArgFunc(value?: string): any; 19 | /** 20 | * @param value (Required) A series of numbers 21 | */ 22 | declare function varArgsFunc(...value: number[]): any; 23 | declare class SomeType { 24 | } 25 | declare class SomeOtherType { 26 | } 27 | /** 28 | * A generic class 29 | */ 30 | declare class Foo { 31 | /** 32 | * A generic method 33 | * @param arg (Required) An argument of a generic type 34 | */ 35 | bar(arg: TArg): string; 36 | /** 37 | * Another generic method 38 | * @param arg (Required) The class generic type 39 | * @param arg2 (Required) An argument of a generic type 40 | */ 41 | setBar(arg: T, arg2: TArg): string; 42 | /** 43 | * Yet another generic method 44 | */ 45 | getBar(): T; 46 | } 47 | /** 48 | * A class that takes an options argument 49 | */ 50 | declare class Optionable { 51 | /** 52 | * @param options (Required) Object with the following properties: 53 | */ 54 | constructor(options: IOptionableOptions); 55 | } 56 | /** 57 | * A class that takes an options argument 58 | */ 59 | declare class ImproperlyDocumentedOptionable { 60 | /** 61 | * @param options (Required) An object with the following properties 62 | */ 63 | constructor(options: IImproperlyDocumentedOptionableOptions); 64 | } 65 | /** 66 | * A class that takes an options array argument 67 | */ 68 | declare class ArrayOptionable { 69 | /** 70 | * @param employees (Required) The employees who are responsible for the project. 71 | */ 72 | constructor(employees: IArrayOptionableOptions[]); 73 | } 74 | declare class ClassWithOptionProperty { 75 | /** 76 | */ 77 | constructor(); 78 | /** 79 | * Name 80 | */ 81 | name: String; 82 | /** 83 | * Foo 84 | */ 85 | foo: IClassWithOptionPropertyOptions; 86 | } 87 | interface IOptionableOptions { 88 | /** 89 | * The URL of the service. 90 | */ 91 | url: String; 92 | /** 93 | * The authorization token to use to connect to the service. 94 | */ 95 | token?: String; 96 | /** 97 | * A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed. 98 | */ 99 | proxy?: any; 100 | /** 101 | * An optional string argument 102 | */ 103 | arg?: String; 104 | } 105 | interface IImproperlyDocumentedOptionableOptions { 106 | /** 107 | * The URL of the service. 108 | */ 109 | url: String; 110 | /** 111 | * The authorization token to use to connect to the service. 112 | */ 113 | token?: String; 114 | /** 115 | * A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed. 116 | */ 117 | proxy?: any; 118 | /** 119 | * An optional string argument 120 | */ 121 | arg?: String; 122 | } 123 | interface IArrayOptionableOptions { 124 | /** 125 | * The name of an employee. 126 | */ 127 | name: string; 128 | /** 129 | * The employee's department. 130 | */ 131 | department: string; 132 | } 133 | interface IClassWithOptionPropertyOptions { 134 | /** 135 | * Bar of Foo 136 | */ 137 | bar: string; 138 | /** 139 | * Foo of Foo 140 | */ 141 | foo: number; 142 | } 143 | declare module olx { 144 | module foo { 145 | interface Bar { 146 | /** 147 | */ 148 | a: string; 149 | /** 150 | */ 151 | b: number; 152 | } 153 | } 154 | } 155 | declare module coolmodule { 156 | interface ICoolmoduleDoFooOptions { 157 | /** 158 | * The ID 159 | */ 160 | id: string; 161 | } 162 | /** 163 | * Lorem ipsum 164 | * @param params (Required) Blub 165 | */ 166 | function doFoo(params: coolmodule.ICoolmoduleDoFooOptions): any; 167 | } 168 | -------------------------------------------------------------------------------- /typings/node/node.d.ts: -------------------------------------------------------------------------------- 1 | export import fs = require("fs"); 2 | export import os = require("os"); 3 | export as namespace nodeModules; -------------------------------------------------------------------------------- /typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | 2 | /// 3 | --------------------------------------------------------------------------------