diff --git a/.gitignore b/.gitignore index c6533aa..cffd7e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ +# NPM node_modules npm-debug.log + +# WebStorm user-specific .idea/workspace.xml .idea/tasks.xml -.DS_Store -Thumbs.db + +# Generate data +test diff --git a/.idea/OBJ2GLTF.iml b/.idea/OBJ2GLTF.iml index e14bba9..eb519c4 100644 --- a/.idea/OBJ2GLTF.iml +++ b/.idea/OBJ2GLTF.iml @@ -1,9 +1,14 @@ - + + + + - + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..eff7139 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml index 2d8ad44..09c4a54 100644 --- a/.idea/jsLibraryMappings.xml +++ b/.idea/jsLibraryMappings.xml @@ -1,7 +1,9 @@ - + + + \ No newline at end of file diff --git a/.idea/jsLinters/jshint.xml b/.idea/jsLinters/jshint.xml new file mode 100644 index 0000000..aed467c --- /dev/null +++ b/.idea/jsLinters/jshint.xml @@ -0,0 +1,83 @@ + + + + + \ No newline at end of file diff --git a/.idea/libraries/TypeScriptDefinitions.xml b/.idea/libraries/TypeScriptDefinitions.xml new file mode 100644 index 0000000..2a75ac2 --- /dev/null +++ b/.idea/libraries/TypeScriptDefinitions.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/OBJ2GLTF_node_modules.xml b/.idea/libraries/node_modules.xml similarity index 57% rename from .idea/libraries/OBJ2GLTF_node_modules.xml rename to .idea/libraries/node_modules.xml index 7737ba8..c4a1e51 100644 --- a/.idea/libraries/OBJ2GLTF_node_modules.xml +++ b/.idea/libraries/node_modules.xml @@ -1,12 +1,10 @@ - + + diff --git a/.idea/misc.xml b/.idea/misc.xml index 72abef0..fa7d715 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + diff --git a/.idea/modules.xml b/.idea/modules.xml index eb8cfab..662b990 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.jshintrc b/.jshintrc index 6edd987..bdff25a 100644 --- a/.jshintrc +++ b/.jshintrc @@ -7,6 +7,7 @@ "freeze": true, "immed": true, "latedef": "nofunc", + "newcap": true, "noarg": true, "nonbsp": true, "nonew": true, diff --git a/.npmignore b/.npmignore index 42dd344..c9ba582 100644 --- a/.npmignore +++ b/.npmignore @@ -1,8 +1,8 @@ -node_modules -npm-debug.log .idea -.DS_Store -Thumbs.db -.npmignore -gulpfile.js .jshintrc +.npmignore +.travis.yml +gulpfile.js +test +specs +TypeScriptDefinitions diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a73b51f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - 4 +script: + - npm run jsHint -- --failTaskOnError + - npm run test -- --failTaskOnError --suppressPassed diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..b24bcec --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,6 @@ +Change Log +========== + +### 0.1.0 - 2016-07-08 + +Initial release. diff --git a/LICENSE.md b/LICENSE.md index 6cb7cfd..8938747 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,135 @@ -Copyright 2015 Analytical Graphics, Inc. +Copyright 2016 Analytical Graphics, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +Third-Party Code +================ + +obj2gltf includes the following third-party code. + +### async + +https://www.npmjs.com/package/async + +> Copyright (c) 2010-2016 Caolan McMahon +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +### byline + +https://www.npmjs.com/package/byline + +> node-byline (C) 2011-2015 John Hewson +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +### Cesium + +http://cesiumjs.org/ + +> Copyright 2011-2016 Cesium Contributors +> +> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +> +> http://www.apache.org/licenses/LICENSE-2.0 +> +> Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +See https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md + +### fs-extra + +https://www.npmjs.com/package/fs-extra + +> (The MIT License) +> +> Copyright (c) 2011-2016 JP Richardson +> +> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +> merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +### gltf-pipeline + +https://www.npmjs.com/package/gltf-pipeline + +> Copyright 2015-2016 Richard Lee, Analytical Graphics, Inc., and Contributors +> +> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +> +> http://www.apache.org/licenses/LICENSE-2.0 +> +> Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +### yargs + +https://www.npmjs.com/package/yargs + +The command-line tool uses yargs. + +> Copyright 2010 James Halliday (mail@substack.net) +Modified work Copyright 2014 Contributors (ben@npmjs.com) +> +> This project is free software released under the MIT/X11 license: +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/TypeScriptDefinitions/async.d.ts b/TypeScriptDefinitions/async.d.ts new file mode 100644 index 0000000..6288a26 --- /dev/null +++ b/TypeScriptDefinitions/async.d.ts @@ -0,0 +1,165 @@ +// Type definitions for Async 1.4.2 +// Project: https://github.com/caolan/async +// Definitions by: Boris Yankov , Arseniy Maximov , Joe Herman +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +interface Dictionary { [key: string]: T; } + +interface ErrorCallback { (err?: Error): void; } +interface AsyncResultCallback { (err: Error, result: T): void; } +interface AsyncResultArrayCallback { (err: Error, results: T[]): void; } +interface AsyncResultObjectCallback { (err: Error, results: Dictionary): void; } + +interface AsyncFunction { (callback: (err?: Error, result?: T) => void): void; } +interface AsyncIterator { (item: T, callback: ErrorCallback): void; } +interface AsyncForEachOfIterator { (item: T, key: number|string, callback: ErrorCallback): void; } +interface AsyncResultIterator { (item: T, callback: AsyncResultCallback): void; } +interface AsyncMemoIterator { (memo: R, item: T, callback: AsyncResultCallback): void; } +interface AsyncBooleanIterator { (item: T, callback: (err: string, truthValue: boolean) => void): void; } + +interface AsyncWorker { (task: T, callback: ErrorCallback): void; } +interface AsyncVoidFunction { (callback: ErrorCallback): void; } + +interface AsyncQueue { + length(): number; + started: boolean; + running(): number; + idle(): boolean; + concurrency: number; + push(task: T, callback?: ErrorCallback): void; + push(task: T[], callback?: ErrorCallback): void; + unshift(task: T, callback?: ErrorCallback): void; + unshift(task: T[], callback?: ErrorCallback): void; + saturated: () => any; + empty: () => any; + drain: () => any; + paused: boolean; + pause(): void + resume(): void; + kill(): void; +} + +interface AsyncPriorityQueue { + length(): number; + concurrency: number; + started: boolean; + paused: boolean; + push(task: T, priority: number, callback?: AsyncResultArrayCallback): void; + push(task: T[], priority: number, callback?: AsyncResultArrayCallback): void; + saturated: () => any; + empty: () => any; + drain: () => any; + running(): number; + idle(): boolean; + pause(): void; + resume(): void; + kill(): void; +} + +interface AsyncCargo { + length(): number; + payload: number; + push(task: any, callback? : Function): void; + push(task: any[], callback? : Function): void; + saturated(): void; + empty(): void; + drain(): void; + idle(): boolean; + pause(): void; + resume(): void; + kill(): void; +} + +interface Async { + + // Collections + each(arr: T[], iterator: AsyncIterator, callback?: ErrorCallback): void; + eachSeries(arr: T[], iterator: AsyncIterator, callback?: ErrorCallback): void; + eachLimit(arr: T[], limit: number, iterator: AsyncIterator, callback?: ErrorCallback): void; + forEachOf(obj: any, iterator: (item: any, key: string|number, callback?: ErrorCallback) => void, callback: ErrorCallback): void; + forEachOf(obj: T[], iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; + forEachOfSeries(obj: any, iterator: (item: any, key: string|number, callback?: ErrorCallback) => void, callback: ErrorCallback): void; + forEachOfSeries(obj: T[], iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; + forEachOfLimit(obj: any, limit: number, iterator: (item: any, key: string|number, callback?: ErrorCallback) => void, callback: ErrorCallback): void; + forEachOfLimit(obj: T[], limit: number, iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; + map(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + mapSeries(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + mapLimit(arr: T[], limit: number, iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + filter(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + select(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + filterSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + selectSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + filterLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + selectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + reject(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + rejectSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + rejectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; + reduce(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): any; + inject(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): any; + foldl(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): any; + reduceRight(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncResultCallback): any; + foldr(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncResultCallback): any; + detect(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; + detectSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; + detectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; + sortBy(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + some(arr: T[], iterator: AsyncBooleanIterator, callback?: (result: boolean) => void): any; + someLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: (result: boolean) => void): any; + any(arr: T[], iterator: AsyncBooleanIterator, callback?: (result: boolean) => void): any; + every(arr: T[], iterator: AsyncBooleanIterator, callback?: (result: boolean) => any): any; + everyLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: (result: boolean) => any): any; + all(arr: T[], iterator: AsyncBooleanIterator, callback?: (result: boolean) => any): any; + concat(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + concatSeries(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + + // Control Flow + series(tasks: AsyncFunction[], callback?: AsyncResultArrayCallback): void; + series(tasks: Dictionary>, callback?: AsyncResultObjectCallback): void; + parallel(tasks: Array>, callback?: AsyncResultArrayCallback): void; + parallel(tasks: Dictionary>, callback?: AsyncResultObjectCallback): void; + parallelLimit(tasks: Array>, limit: number, callback?: AsyncResultArrayCallback): void; + parallelLimit(tasks: Dictionary>, limit: number, callback?: AsyncResultObjectCallback): void; + whilst(test: () => boolean, fn: AsyncVoidFunction, callback: (err: any) => void): void; + doWhilst(fn: AsyncVoidFunction, test: () => boolean, callback: (err: any) => void): void; + until(test: () => boolean, fn: AsyncVoidFunction, callback: (err: any) => void): void; + doUntil(fn: AsyncVoidFunction, test: () => boolean, callback: (err: any) => void): void; + during(test: (testCallback : (error: Error, truth: boolean) => void) => void, fn: AsyncVoidFunction, callback: (err: any) => void): void; + doDuring(fn: AsyncVoidFunction, test: (testCallback: (error: Error, truth: boolean) => void) => void, callback: (err: any) => void): void; + forever(next: (errCallback : (err: Error) => void) => void, errBack: (err: Error) => void) : void; + waterfall(tasks: Function[], callback?: (err: Error, results?: any) => void): void; + compose(...fns: Function[]): Function; + seq(...fns: Function[]): Function; + applyEach(fns: Function[], argsAndCallback: any[]): void; // applyEach(fns, args..., callback). TS does not support ... for a middle argument. Callback is optional. + applyEachSeries(fns: Function[], argsAndCallback: any[]): void; // applyEachSeries(fns, args..., callback). TS does not support ... for a middle argument. Callback is optional. + queue(worker: AsyncWorker, concurrency?: number): AsyncQueue; + priorityQueue(worker: AsyncWorker, concurrency: number): AsyncPriorityQueue; + cargo(worker : (tasks: any[], callback : ErrorCallback) => void, payload? : number) : AsyncCargo; + auto(tasks: any, callback?: (error: Error, results: any) => void): void; + retry(opts: number, task: (callback : AsyncResultCallback, results: any) => void, callback: (error: Error, results: any) => void): void; + retry(opts: { times: number, interval: number|((retryCount: number) => number) }, task: (callback: AsyncResultCallback, results : any) => void, callback: (error: Error, results: any) => void): void; + iterator(tasks: Function[]): Function; + apply(fn: Function, ...arguments: any[]): AsyncFunction; + nextTick(callback: Function): void; + setImmediate(callback: Function): void; + + times (n: number, iterator: AsyncResultIterator, callback: AsyncResultArrayCallback): void; + timesSeries(n: number, iterator: AsyncResultIterator, callback: AsyncResultArrayCallback): void; + timesLimit(n: number, limit: number, iterator: AsyncResultIterator, callback: AsyncResultArrayCallback): void; + + // Utils + memoize(fn: Function, hasher?: Function): Function; + unmemoize(fn: Function): Function; + ensureAsync(fn: (... argsAndCallback: any[]) => void): Function; + constant(...values: any[]): Function; + asyncify(fn: Function): Function; + wrapSync(fn: Function): Function; + log(fn: Function, ...arguments: any[]): void; + dir(fn: Function, ...arguments: any[]): void; + noConflict(): Async; +} + +declare var async: Async; + +declare module "async" { + export = async; +} diff --git a/TypeScriptDefinitions/byline.d.ts b/TypeScriptDefinitions/byline.d.ts new file mode 100644 index 0000000..48ddd2d --- /dev/null +++ b/TypeScriptDefinitions/byline.d.ts @@ -0,0 +1,38 @@ +// Type definitions for byline 4.2.1 +// Project: https://github.com/jahewson/node-byline +// Definitions by: Stefan Steinhart +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare module "byline" { + import stream = require("stream"); + + export interface LineStreamOptions extends stream.TransformOptions { + keepEmptyLines?: boolean; + } + + export interface LineStream extends stream.Transform { + } + + export interface LineStreamCreatable extends LineStream { + new (options?:LineStreamOptions):LineStream + } + + //TODO is it possible to declare static factory functions without name (directly on the module) + // + // JS: + // // convinience API + // module.exports = function(readStream, options) { + // return module.exports.createStream(readStream, options); + // }; + // + // TS: + // ():LineStream; // same as createStream():LineStream + // (stream:stream.Stream, options?:LineStreamOptions):LineStream; // same as createStream(stream, options?):LineStream + + export function createStream():LineStream; + export function createStream(stream:NodeJS.ReadableStream, options?:LineStreamOptions):LineStream; + + export var LineStream:LineStreamCreatable; +} diff --git a/TypeScriptDefinitions/fs-extra.d.ts b/TypeScriptDefinitions/fs-extra.d.ts new file mode 100644 index 0000000..39656ce --- /dev/null +++ b/TypeScriptDefinitions/fs-extra.d.ts @@ -0,0 +1,95 @@ +// Type definitions for fs-extra +// Project: https://github.com/jprichardson/node-fs-extra +// Definitions by: midknight41 +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +// Imported from: https://github.com/soywiz/typescript-node-definitions/fs-extra.d.ts + +/// + +declare module "fs-extra" { + export * from "fs"; + + export function copy(src: string, dest: string, callback?: (err: Error) => void): void; + export function copy(src: string, dest: string, filter: CopyFilter, callback?: (err: Error) => void): void; + export function copy(src: string, dest: string, options: CopyOptions, callback?: (err: Error) => void): void; + + export function copySync(src: string, dest: string): void; + export function copySync(src: string, dest: string, filter: CopyFilter): void; + export function copySync(src: string, dest: string, options: CopyOptions): void; + + export function createFile(file: string, callback?: (err: Error) => void): void; + export function createFileSync(file: string): void; + + export function mkdirs(dir: string, callback?: (err: Error) => void): void; + export function mkdirp(dir: string, callback?: (err: Error) => void): void; + export function mkdirs(dir: string, options?: MkdirOptions, callback?: (err: Error) => void): void; + export function mkdirp(dir: string, options?: MkdirOptions, callback?: (err: Error) => void): void; + export function mkdirsSync(dir: string, options?: MkdirOptions): void; + export function mkdirpSync(dir: string, options?: MkdirOptions): void; + + export function outputFile(file: string, data: any, callback?: (err: Error) => void): void; + export function outputFileSync(file: string, data: any): void; + + export function outputJson(file: string, data: any, callback?: (err: Error) => void): void; + export function outputJSON(file: string, data: any, callback?: (err: Error) => void): void; + export function outputJsonSync(file: string, data: any): void; + export function outputJSONSync(file: string, data: any): void; + + export function readJson(file: string, callback: (err: Error, jsonObject: any) => void): void; + export function readJson(file: string, options: OpenOptions, callback: (err: Error, jsonObject: any) => void): void; + export function readJSON(file: string, callback: (err: Error, jsonObject: any) => void): void; + export function readJSON(file: string, options: OpenOptions, callback: (err: Error, jsonObject: any) => void): void; + + export function readJsonSync(file: string, options?: OpenOptions): any; + export function readJSONSync(file: string, options?: OpenOptions): any; + + export function remove(dir: string, callback?: (err: Error) => void): void; + export function removeSync(dir: string): void; + + export function writeJson(file: string, object: any, callback?: (err: Error) => void): void; + export function writeJson(file: string, object: any, options?: OpenOptions, callback?: (err: Error) => void): void; + export function writeJSON(file: string, object: any, callback?: (err: Error) => void): void; + export function writeJSON(file: string, object: any, options?: OpenOptions, callback?: (err: Error) => void): void; + + export function writeJsonSync(file: string, object: any, options?: OpenOptions): void; + export function writeJSONSync(file: string, object: any, options?: OpenOptions): void; + + export function ensureDir(path: string, cb: (err: Error) => void): void; + export function ensureDirSync(path: string): void; + + export function ensureFile(path: string, cb: (err: Error) => void): void; + export function ensureFileSync(path: string): void; + + export function ensureLink(path: string, cb: (err: Error) => void): void; + export function ensureLinkSync(path: string): void; + + export function ensureSymlink(path: string, cb: (err: Error) => void): void; + export function ensureSymlinkSync(path: string): void; + + export function emptyDir(path: string, callback?: (err: Error) => void): void; + export function emptyDirSync(path: string): boolean; + + export interface CopyFilterFunction { + (src: string): boolean + } + + export type CopyFilter = CopyFilterFunction | RegExp; + + export interface CopyOptions { + clobber?: boolean + preserveTimestamps?: boolean + dereference?: boolean + filter?: CopyFilter + } + + export interface OpenOptions { + encoding?: string; + flag?: string; + } + + export interface MkdirOptions { + fs?: any; + mode?: number; + } +} diff --git a/TypeScriptDefinitions/gulp.d.ts b/TypeScriptDefinitions/gulp.d.ts new file mode 100644 index 0000000..43bb5aa --- /dev/null +++ b/TypeScriptDefinitions/gulp.d.ts @@ -0,0 +1,290 @@ +// Type definitions for Gulp v3.8.x +// Project: http://gulpjs.com +// Definitions by: Drew Noakes +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// +/// + +declare module "gulp" { + import Orchestrator = require("orchestrator"); + + namespace gulp { + interface Gulp extends Orchestrator { + /** + * Define a task + * @param name The name of the task. + * @param deps An array of task names to be executed and completed before your task will run. + * @param fn The function that performs the task's operations. For asynchronous tasks, you need to provide a hint when the task is complete: + *
    + *
  • Take in a callback
  • + *
  • Return a stream or a promise
  • + *
+ */ + task: Orchestrator.AddMethod; + /** + * Emits files matching provided glob or an array of globs. Returns a stream of Vinyl files that can be piped to plugins. + * @param glob Glob or array of globs to read. + * @param opt Options to pass to node-glob through glob-stream. + */ + src: SrcMethod; + /** + * Can be piped to and it will write files. Re-emits all data passed to it so you can pipe to multiple folders. + * Folders that don't exist will be created. + * + * @param outFolder The path (output folder) to write files to. Or a function that returns it, the function will be provided a vinyl File instance. + * @param opt + */ + dest: DestMethod; + /** + * Watch files and do something when a file changes. This always returns an EventEmitter that emits change events. + * + * @param glob a single glob or array of globs that indicate which files to watch for changes. + * @param opt options, that are passed to the gaze library. + * @param fn a callback or array of callbacks to be called on each change, or names of task(s) to run when a file changes, added with task(). + */ + watch: WatchMethod; + } + + interface GulpPlugin { + (...args: any[]): NodeJS.ReadWriteStream; + } + + interface WatchMethod { + /** + * Watch files and do something when a file changes. This always returns an EventEmitter that emits change events. + * + * @param glob a single glob or array of globs that indicate which files to watch for changes. + * @param fn a callback or array of callbacks to be called on each change, or names of task(s) to run when a file changes, added with task(). + */ + (glob: string|string[], fn: (WatchCallback|string)): NodeJS.EventEmitter; + /** + * Watch files and do something when a file changes. This always returns an EventEmitter that emits change events. + * + * @param glob a single glob or array of globs that indicate which files to watch for changes. + * @param fn a callback or array of callbacks to be called on each change, or names of task(s) to run when a file changes, added with task(). + */ + (glob: string|string[], fn: (WatchCallback|string)[]): NodeJS.EventEmitter; + /** + * Watch files and do something when a file changes. This always returns an EventEmitter that emits change events. + * + * @param glob a single glob or array of globs that indicate which files to watch for changes. + * @param opt options, that are passed to the gaze library. + * @param fn a callback or array of callbacks to be called on each change, or names of task(s) to run when a file changes, added with task(). + */ + (glob: string|string[], opt: WatchOptions, fn: (WatchCallback|string)): NodeJS.EventEmitter; + /** + * Watch files and do something when a file changes. This always returns an EventEmitter that emits change events. + * + * @param glob a single glob or array of globs that indicate which files to watch for changes. + * @param opt options, that are passed to the gaze library. + * @param fn a callback or array of callbacks to be called on each change, or names of task(s) to run when a file changes, added with task(). + */ + (glob: string|string[], opt: WatchOptions, fn: (WatchCallback|string)[]): NodeJS.EventEmitter; + + } + + interface DestMethod { + /** + * Can be piped to and it will write files. Re-emits all data passed to it so you can pipe to multiple folders. + * Folders that don't exist will be created. + * + * @param outFolder The path (output folder) to write files to. Or a function that returns it, the function will be provided a vinyl File instance. + * @param opt + */ + (outFolder: string|((file: string) => string), opt?: DestOptions): NodeJS.ReadWriteStream; + } + + interface SrcMethod { + /** + * Emits files matching provided glob or an array of globs. Returns a stream of Vinyl files that can be piped to plugins. + * @param glob Glob or array of globs to read. + * @param opt Options to pass to node-glob through glob-stream. + */ + (glob: string|string[], opt?: SrcOptions): NodeJS.ReadWriteStream; + } + + /** + * Options to pass to node-glob through glob-stream. + * Specifies two options in addition to those used by node-glob: + * https://github.com/isaacs/node-glob#options + */ + interface SrcOptions { + /** + * Setting this to false will return file.contents as null + * and not read the file at all. + * Default: true. + */ + read?: boolean; + + /** + * Setting this to false will return file.contents as a stream and not buffer files. + * This is useful when working with large files. + * Note: Plugins might not implement support for streams. + * Default: true. + */ + buffer?: boolean; + + /** + * The base path of a glob. + * + * Default is everything before a glob starts. + */ + base?: string; + + /** + * The current working directory in which to search. + * Defaults to process.cwd(). + */ + cwd?: string; + + /** + * The place where patterns starting with / will be mounted onto. + * Defaults to path.resolve(options.cwd, "/") (/ on Unix systems, and C:\ or some such on Windows.) + */ + root?: string; + + /** + * Include .dot files in normal matches and globstar matches. + * Note that an explicit dot in a portion of the pattern will always match dot files. + */ + dot?: boolean; + + /** + * By default, a pattern starting with a forward-slash will be "mounted" onto the root setting, so that a valid + * filesystem path is returned. Set this flag to disable that behavior. + */ + nomount?: boolean; + + /** + * Add a / character to directory matches. Note that this requires additional stat calls. + */ + mark?: boolean; + + /** + * Don't sort the results. + */ + nosort?: boolean; + + /** + * Set to true to stat all results. This reduces performance somewhat, and is completely unnecessary, unless + * readdir is presumed to be an untrustworthy indicator of file existence. It will cause ELOOP to be triggered one + * level sooner in the case of cyclical symbolic links. + */ + stat?: boolean; + + /** + * When an unusual error is encountered when attempting to read a directory, a warning will be printed to stderr. + * Set the silent option to true to suppress these warnings. + */ + silent?: boolean; + + /** + * When an unusual error is encountered when attempting to read a directory, the process will just continue on in + * search of other matches. Set the strict option to raise an error in these cases. + */ + strict?: boolean; + + /** + * See cache property above. Pass in a previously generated cache object to save some fs calls. + */ + cache?: boolean; + + /** + * A cache of results of filesystem information, to prevent unnecessary stat calls. + * While it should not normally be necessary to set this, you may pass the statCache from one glob() call to the + * options object of another, if you know that the filesystem will not change between calls. + */ + statCache?: boolean; + + /** + * Perform a synchronous glob search. + */ + sync?: boolean; + + /** + * In some cases, brace-expanded patterns can result in the same file showing up multiple times in the result set. + * By default, this implementation prevents duplicates in the result set. Set this flag to disable that behavior. + */ + nounique?: boolean; + + /** + * Set to never return an empty set, instead returning a set containing the pattern itself. + * This is the default in glob(3). + */ + nonull?: boolean; + + /** + * Perform a case-insensitive match. Note that case-insensitive filesystems will sometimes result in glob returning + * results that are case-insensitively matched anyway, since readdir and stat will not raise an error. + */ + nocase?: boolean; + + /** + * Set to enable debug logging in minimatch and glob. + */ + debug?: boolean; + + /** + * Set to enable debug logging in glob, but not minimatch. + */ + globDebug?: boolean; + } + + interface DestOptions { + /** + * The output folder. Only has an effect if provided output folder is relative. + * Default: process.cwd() + */ + cwd?: string; + + /** + * Octal permission string specifying mode for any folders that need to be created for output folder. + * Default: 0777. + */ + mode?: string; + } + + /** + * Options that are passed to gaze. + * https://github.com/shama/gaze + */ + interface WatchOptions { + /** Interval to pass to fs.watchFile. */ + interval?: number; + /** Delay for events called in succession for the same file/event. */ + debounceDelay?: number; + /** Force the watch mode. Either 'auto' (default), 'watch' (force native events), or 'poll' (force stat polling). */ + mode?: string; + /** The current working directory to base file patterns from. Default is process.cwd().. */ + cwd?: string; + } + + interface WatchEvent { + /** The type of change that occurred, either added, changed or deleted. */ + type: string; + /** The path to the file that triggered the event. */ + path: string; + } + + /** + * Callback to be called on each watched file change. + */ + interface WatchCallback { + (event: WatchEvent): void; + } + + interface TaskCallback { + /** + * Defines a task. + * Tasks may be made asynchronous if they are passing a callback or return a promise or a stream. + * @param cb callback used to signal asynchronous completion. Caller includes err in case of error. + */ + (cb?: (err?: any) => void): any; + } + } + + var gulp: gulp.Gulp; + + export = gulp; +} diff --git a/TypeScriptDefinitions/istanbul.d.ts b/TypeScriptDefinitions/istanbul.d.ts new file mode 100644 index 0000000..1ccbd14 --- /dev/null +++ b/TypeScriptDefinitions/istanbul.d.ts @@ -0,0 +1,73 @@ +// Type definitions for Istanbul v0.4.0 +// Project: https://github.com/gotwarlost/istanbul +// Definitions by: Tanguy Krotoff +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module 'istanbul' { + namespace istanbul { + interface Istanbul { + new (options?: any): Istanbul; + Collector: Collector; + config: Config; + ContentWriter: ContentWriter; + FileWriter: FileWriter; + hook: Hook; + Instrumenter: Instrumenter; + Report: Report; + Reporter: Reporter; + Store: Store; + utils: ObjectUtils; + VERSION: string; + Writer: Writer; + } + + interface Collector { + new (options?: any): Collector; + add(coverage: any, testName?: string): void; + } + + interface Config { + } + + interface ContentWriter { + } + + interface FileWriter { + } + + interface Hook { + } + + interface Instrumenter { + new (options?: any): Instrumenter; + instrumentSync(code: string, filename: string): string; + } + + interface Report { + } + + interface Configuration { + new (obj: any, overrides: any): Configuration; + } + + interface Reporter { + new (cfg?: Configuration, dir?: string): Reporter; + add(fmt: string): void; + addAll(fmts: Array): void; + write(collector: Collector, sync: boolean, callback: Function): void; + } + + interface Store { + } + + interface ObjectUtils { + } + + interface Writer { + } + } + + var istanbul: istanbul.Istanbul; + + export = istanbul; +} diff --git a/TypeScriptDefinitions/jasmine.d.ts b/TypeScriptDefinitions/jasmine.d.ts new file mode 100644 index 0000000..538aca3 --- /dev/null +++ b/TypeScriptDefinitions/jasmine.d.ts @@ -0,0 +1,508 @@ +// Type definitions for Jasmine 2.2 +// Project: http://jasmine.github.io/ +// Definitions by: Boris Yankov , Theodore Brown , David Pärsson +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + + +// For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts + +declare function describe(description: string, specDefinitions: () => void): void; +declare function fdescribe(description: string, specDefinitions: () => void): void; +declare function xdescribe(description: string, specDefinitions: () => void): void; + +declare function it(expectation: string, assertion?: () => void, timeout?: number): void; +declare function it(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; +declare function fit(expectation: string, assertion?: () => void, timeout?: number): void; +declare function fit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; +declare function xit(expectation: string, assertion?: () => void, timeout?: number): void; +declare function xit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; + +/** If you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. */ +declare function pending(reason?: string): void; + +declare function beforeEach(action: () => void, timeout?: number): void; +declare function beforeEach(action: (done: DoneFn) => void, timeout?: number): void; +declare function afterEach(action: () => void, timeout?: number): void; +declare function afterEach(action: (done: DoneFn) => void, timeout?: number): void; + +declare function beforeAll(action: () => void, timeout?: number): void; +declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void; +declare function afterAll(action: () => void, timeout?: number): void; +declare function afterAll(action: (done: DoneFn) => void, timeout?: number): void; + +declare function expect(spy: Function): jasmine.Matchers; +declare function expect(actual: any): jasmine.Matchers; + +declare function fail(e?: any): void; +/** Action method that should be called when the async work is complete */ +interface DoneFn extends Function { + (): void; + + /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */ + fail: (message?: Error|string) => void; +} + +declare function spyOn(object: any, method: string): jasmine.Spy; + +declare function runs(asyncMethod: Function): void; +declare function waitsFor(latchMethod: () => boolean, failureMessage?: string, timeout?: number): void; +declare function waits(timeout?: number): void; + +declare namespace jasmine { + + var clock: () => Clock; + + function any(aclass: any): Any; + function anything(): Any; + function arrayContaining(sample: any[]): ArrayContaining; + function objectContaining(sample: any): ObjectContaining; + function createSpy(name: string, originalFn?: Function): Spy; + function createSpyObj(baseName: string, methodNames: any[]): any; + function createSpyObj(baseName: string, methodNames: any[]): T; + function pp(value: any): string; + function getEnv(): Env; + function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + function addMatchers(matchers: CustomMatcherFactories): void; + function stringMatching(str: string): Any; + function stringMatching(str: RegExp): Any; + + interface Any { + + new (expectedClass: any): any; + + jasmineMatches(other: any): boolean; + jasmineToString(): string; + } + + // taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains() + interface ArrayLike { + length: number; + [n: number]: T; + } + + interface ArrayContaining { + new (sample: any[]): any; + + asymmetricMatch(other: any): boolean; + jasmineToString(): string; + } + + interface ObjectContaining { + new (sample: any): any; + + jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; + jasmineToString(): string; + } + + interface Block { + + new (env: Env, func: SpecFunction, spec: Spec): any; + + execute(onComplete: () => void): void; + } + + interface WaitsBlock extends Block { + new (env: Env, timeout: number, spec: Spec): any; + } + + interface WaitsForBlock extends Block { + new (env: Env, timeout: number, latchFunction: SpecFunction, message: string, spec: Spec): any; + } + + interface Clock { + install(): void; + uninstall(): void; + /** Calls to any registered callback are triggered when the clock is ticked forward via the jasmine.clock().tick function, which takes a number of milliseconds. */ + tick(ms: number): void; + mockDate(date?: Date): void; + } + + interface CustomEqualityTester { + (first: any, second: any): boolean; + } + + interface CustomMatcher { + compare(actual: T, expected: T): CustomMatcherResult; + compare(actual: any, expected: any): CustomMatcherResult; + } + + interface CustomMatcherFactory { + (util: MatchersUtil, customEqualityTesters: Array): CustomMatcher; + } + + interface CustomMatcherFactories { + [index: string]: CustomMatcherFactory; + } + + interface CustomMatcherResult { + pass: boolean; + message?: string; + } + + interface MatchersUtil { + equals(a: any, b: any, customTesters?: Array): boolean; + contains(haystack: ArrayLike | string, needle: any, customTesters?: Array): boolean; + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: Array): string; + } + + interface Env { + setTimeout: any; + clearTimeout: void; + setInterval: any; + clearInterval: void; + updateInterval: number; + + currentSpec: Spec; + + matchersClass: Matchers; + + version(): any; + versionString(): string; + nextSpecId(): number; + addReporter(reporter: Reporter): void; + execute(): void; + describe(description: string, specDefinitions: () => void): Suite; + // ddescribe(description: string, specDefinitions: () => void): Suite; Not a part of jasmine. Angular team adds these + beforeEach(beforeEachFunction: () => void): void; + beforeAll(beforeAllFunction: () => void): void; + currentRunner(): Runner; + afterEach(afterEachFunction: () => void): void; + afterAll(afterAllFunction: () => void): void; + xdescribe(desc: string, specDefinitions: () => void): XSuite; + it(description: string, func: () => void): Spec; + // iit(description: string, func: () => void): Spec; Not a part of jasmine. Angular team adds these + xit(desc: string, func: () => void): XSpec; + compareRegExps_(a: RegExp, b: RegExp, mismatchKeys: string[], mismatchValues: string[]): boolean; + compareObjects_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; + equals_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; + contains_(haystack: any, needle: any): boolean; + addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + addMatchers(matchers: CustomMatcherFactories): void; + specFilter(spec: Spec): boolean; + throwOnExpectationFailure(value: boolean): void; + } + + interface FakeTimer { + + new (): any; + + reset(): void; + tick(millis: number): void; + runFunctionsWithinRange(oldMillis: number, nowMillis: number): void; + scheduleFunction(timeoutKey: any, funcToCall: () => void, millis: number, recurring: boolean): void; + } + + interface HtmlReporter { + new (): any; + } + + interface HtmlSpecFilter { + new (): any; + } + + interface Result { + type: string; + } + + interface NestedResults extends Result { + description: string; + + totalCount: number; + passedCount: number; + failedCount: number; + + skipped: boolean; + + rollupCounts(result: NestedResults): void; + log(values: any): void; + getItems(): Result[]; + addResult(result: Result): void; + passed(): boolean; + } + + interface MessageResult extends Result { + values: any; + trace: Trace; + } + + interface ExpectationResult extends Result { + matcherName: string; + passed(): boolean; + expected: any; + actual: any; + message: string; + trace: Trace; + } + + interface Trace { + name: string; + message: string; + stack: any; + } + + interface PrettyPrinter { + + new (): any; + + format(value: any): void; + iterateObject(obj: any, fn: (property: string, isGetter: boolean) => void): void; + emitScalar(value: any): void; + emitString(value: string): void; + emitArray(array: any[]): void; + emitObject(obj: any): void; + append(value: any): void; + } + + interface StringPrettyPrinter extends PrettyPrinter { + } + + interface Queue { + + new (env: any): any; + + env: Env; + ensured: boolean[]; + blocks: Block[]; + running: boolean; + index: number; + offset: number; + abort: boolean; + + addBefore(block: Block, ensure?: boolean): void; + add(block: any, ensure?: boolean): void; + insertNext(block: any, ensure?: boolean): void; + start(onComplete?: () => void): void; + isRunning(): boolean; + next_(): void; + results(): NestedResults; + } + + interface Matchers { + + new (env: Env, actual: any, spec: Env, isNot?: boolean): any; + + env: Env; + actual: any; + spec: Env; + isNot?: boolean; + message(): any; + + toBe(expected: any, expectationFailOutput?: any): boolean; + toEqual(expected: any, expectationFailOutput?: any): boolean; + toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean; + toBeDefined(expectationFailOutput?: any): boolean; + toBeUndefined(expectationFailOutput?: any): boolean; + toBeNull(expectationFailOutput?: any): boolean; + toBeNaN(): boolean; + toBeTruthy(expectationFailOutput?: any): boolean; + toBeFalsy(expectationFailOutput?: any): boolean; + toHaveBeenCalled(): boolean; + toHaveBeenCalledWith(...params: any[]): boolean; + toHaveBeenCalledTimes(expected: number): boolean; + toContain(expected: any, expectationFailOutput?: any): boolean; + toBeLessThan(expected: number, expectationFailOutput?: any): boolean; + toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean; + toBeCloseTo(expected: number, precision?: any, expectationFailOutput?: any): boolean; + toThrow(expected?: any): boolean; + toThrowError(message?: string | RegExp): boolean; + toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean; + not: Matchers; + + Any: Any; + } + + interface Reporter { + reportRunnerStarting(runner: Runner): void; + reportRunnerResults(runner: Runner): void; + reportSuiteResults(suite: Suite): void; + reportSpecStarting(spec: Spec): void; + reportSpecResults(spec: Spec): void; + log(str: string): void; + } + + interface MultiReporter extends Reporter { + addReporter(reporter: Reporter): void; + } + + interface Runner { + + new (env: Env): any; + + execute(): void; + beforeEach(beforeEachFunction: SpecFunction): void; + afterEach(afterEachFunction: SpecFunction): void; + beforeAll(beforeAllFunction: SpecFunction): void; + afterAll(afterAllFunction: SpecFunction): void; + finishCallback(): void; + addSuite(suite: Suite): void; + add(block: Block): void; + specs(): Spec[]; + suites(): Suite[]; + topLevelSuites(): Suite[]; + results(): NestedResults; + } + + interface SpecFunction { + (spec?: Spec): void; + } + + interface SuiteOrSpec { + id: number; + env: Env; + description: string; + queue: Queue; + } + + interface Spec extends SuiteOrSpec { + + new (env: Env, suite: Suite, description: string): any; + + suite: Suite; + + afterCallbacks: SpecFunction[]; + spies_: Spy[]; + + results_: NestedResults; + matchersClass: Matchers; + + getFullName(): string; + results(): NestedResults; + log(arguments: any): any; + runs(func: SpecFunction): Spec; + addToQueue(block: Block): void; + addMatcherResult(result: Result): void; + expect(actual: any): any; + waits(timeout: number): Spec; + waitsFor(latchFunction: SpecFunction, timeoutMessage?: string, timeout?: number): Spec; + fail(e?: any): void; + getMatchersClass_(): Matchers; + addMatchers(matchersPrototype: CustomMatcherFactories): void; + finishCallback(): void; + finish(onComplete?: () => void): void; + after(doAfter: SpecFunction): void; + execute(onComplete?: () => void): any; + addBeforesAndAftersToQueue(): void; + explodes(): void; + spyOn(obj: any, methodName: string, ignoreMethodDoesntExist: boolean): Spy; + removeAllSpies(): void; + } + + interface XSpec { + id: number; + runs(): void; + } + + interface Suite extends SuiteOrSpec { + + new (env: Env, description: string, specDefinitions: () => void, parentSuite: Suite): any; + + parentSuite: Suite; + + getFullName(): string; + finish(onComplete?: () => void): void; + beforeEach(beforeEachFunction: SpecFunction): void; + afterEach(afterEachFunction: SpecFunction): void; + beforeAll(beforeAllFunction: SpecFunction): void; + afterAll(afterAllFunction: SpecFunction): void; + results(): NestedResults; + add(suiteOrSpec: SuiteOrSpec): void; + specs(): Spec[]; + suites(): Suite[]; + children(): any[]; + execute(onComplete?: () => void): void; + } + + interface XSuite { + execute(): void; + } + + interface Spy { + (...params: any[]): any; + + identity: string; + and: SpyAnd; + calls: Calls; + mostRecentCall: { args: any[]; }; + argsForCall: any[]; + wasCalled: boolean; + } + + interface SpyAnd { + /** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */ + callThrough(): Spy; + /** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */ + returnValue(val: any): Spy; + /** By chaining the spy with and.returnValues, all calls to the function will return specific values in order until it reaches the end of the return values list. */ + returnValues(...values: any[]): Spy; + /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */ + callFake(fn: Function): Spy; + /** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */ + throwError(msg: string): Spy; + /** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */ + stub(): Spy; + } + + interface Calls { + /** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. **/ + any(): boolean; + /** By chaining the spy with calls.count(), will return the number of times the spy was called **/ + count(): number; + /** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index **/ + argsFor(index: number): any[]; + /** By chaining the spy with calls.allArgs(), will return the arguments to all calls **/ + allArgs(): any[]; + /** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls **/ + all(): CallInfo[]; + /** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call **/ + mostRecent(): CallInfo; + /** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call **/ + first(): CallInfo; + /** By chaining the spy with calls.reset(), will clears all tracking for a spy **/ + reset(): void; + } + + interface CallInfo { + /** The context (the this) for the call */ + object: any; + /** All arguments passed to the call */ + args: any[]; + /** The return value of the call */ + returnValue: any; + } + + interface Util { + inherit(childClass: Function, parentClass: Function): any; + formatException(e: any): any; + htmlEscape(str: string): string; + argsToArray(args: any): any; + extend(destination: any, source: any): any; + } + + interface JsApiReporter extends Reporter { + + started: boolean; + finished: boolean; + result: any; + messages: any; + + new (): any; + + suites(): Suite[]; + summarize_(suiteOrSpec: SuiteOrSpec): any; + results(): any; + resultsForSpec(specId: any): any; + log(str: any): any; + resultsForSpecs(specIds: any): any; + summarizeResult_(result: any): any; + } + + interface Jasmine { + Spec: Spec; + clock: Clock; + util: Util; + } + + export var HtmlReporter: HtmlReporter; + export var HtmlSpecFilter: HtmlSpecFilter; + export var DEFAULT_TIMEOUT_INTERVAL: number; +} diff --git a/TypeScriptDefinitions/open.d.ts b/TypeScriptDefinitions/open.d.ts new file mode 100644 index 0000000..bca02e5 --- /dev/null +++ b/TypeScriptDefinitions/open.d.ts @@ -0,0 +1,9 @@ +// Type definitions for open 0.0.3 +// Project: https://github.com/jjrdn/node-open +// Definitions by: Bart van der Schoor +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module 'open' { + function open(target: string, app?: string): void; + export = open; +} diff --git a/TypeScriptDefinitions/request.d.ts b/TypeScriptDefinitions/request.d.ts new file mode 100644 index 0000000..547ee62 --- /dev/null +++ b/TypeScriptDefinitions/request.d.ts @@ -0,0 +1,262 @@ +// Type definitions for request +// Project: https://github.com/mikeal/request +// Definitions by: Carlos Ballesteros Velasco , bonnici , Bart van der Schoor , Joe Skeen , Christopher Currens +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +// Imported from: https://github.com/soywiz/typescript-node-definitions/d.ts + +/// +/// + +declare module 'request' { + import stream = require('stream'); + import http = require('http'); + import https = require('https'); + import FormData = require('form-data'); + import url = require('url'); + import fs = require('fs'); + + namespace request { + export interface RequestAPI { + + defaults(options: TOptions): RequestAPI; + defaults(options: RequiredUriUrl & TOptions): DefaultUriUrlRequestApi; + + (uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + (uri: string, callback?: RequestCallback): TRequest; + (options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + get(uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + get(uri: string, callback?: RequestCallback): TRequest; + get(options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + post(uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + post(uri: string, callback?: RequestCallback): TRequest; + post(options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + put(uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + put(uri: string, callback?: RequestCallback): TRequest; + put(options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + head(uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + head(uri: string, callback?: RequestCallback): TRequest; + head(options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + patch(uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + patch(uri: string, callback?: RequestCallback): TRequest; + patch(options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + del(uri: string, options?: TOptions, callback?: RequestCallback): TRequest; + del(uri: string, callback?: RequestCallback): TRequest; + del(options: TUriUrlOptions & TOptions, callback?: RequestCallback): TRequest; + + forever(agentOptions: any, optionsArg: any): TRequest; + jar(): CookieJar; + cookie(str: string): Cookie; + + initParams: any; + debug: boolean; + } + + interface DefaultUriUrlRequestApi extends RequestAPI { + + defaults(options: TOptions): DefaultUriUrlRequestApi; + (): TRequest; + get(): TRequest; + post(): TRequest; + put(): TRequest; + head(): TRequest; + patch(): TRequest; + del(): TRequest; + } + + interface CoreOptions { + baseUrl?: string; + callback?: (error: any, response: http.IncomingMessage, body: any) => void; + jar?: any; // CookieJar + formData?: any; // Object + form?: any; // Object or string + auth?: AuthOptions; + oauth?: OAuthOptions; + aws?: AWSOptions; + hawk?: HawkOptions; + qs?: any; + json?: any; + multipart?: RequestPart[] | Multipart; + agent?: http.Agent | https.Agent; + agentOptions?: any; + agentClass?: any; + forever?: any; + host?: string; + port?: number; + method?: string; + headers?: Headers; + body?: any; + followRedirect?: boolean | ((response: http.IncomingMessage) => boolean); + followAllRedirects?: boolean; + maxRedirects?: number; + encoding?: string; + pool?: any; + timeout?: number; + proxy?: any; + strictSSL?: boolean; + gzip?: boolean; + preambleCRLF?: boolean; + postambleCRLF?: boolean; + key?: Buffer; + cert?: Buffer; + passphrase?: string; + ca?: string | Buffer | string[] | Buffer[]; + har?: HttpArchiveRequest; + useQuerystring?: boolean; + } + + interface UriOptions { + uri: string; + } + interface UrlOptions { + url: string; + } + export type RequiredUriUrl = UriOptions | UrlOptions; + + interface OptionalUriUrl { + uri?: string; + url?: string; + } + + export type OptionsWithUri = UriOptions & CoreOptions; + export type OptionsWithUrl = UrlOptions & CoreOptions; + export type Options = OptionsWithUri | OptionsWithUrl; + + export interface RequestCallback { + (error: any, response: http.IncomingMessage, body: any): void; + } + + export interface HttpArchiveRequest { + url?: string; + method?: string; + headers?: NameValuePair[]; + postData?: { + mimeType?: string; + params?: NameValuePair[]; + } + } + + export interface NameValuePair { + name: string; + value: string; + } + + export interface Multipart { + chunked?: boolean; + data?: { + 'content-type'?: string, + body: string + }[]; + } + + export interface RequestPart { + headers?: Headers; + body: any; + } + + export interface Request extends stream.Stream { + readable: boolean; + writable: boolean; + + getAgent(): http.Agent; + //start(): void; + //abort(): void; + pipeDest(dest: any): void; + setHeader(name: string, value: string, clobber?: boolean): Request; + setHeaders(headers: Headers): Request; + qs(q: Object, clobber?: boolean): Request; + form(): FormData.FormData; + form(form: any): Request; + multipart(multipart: RequestPart[]): Request; + json(val: any): Request; + aws(opts: AWSOptions, now?: boolean): Request; + auth(username: string, password: string, sendInmediately?: boolean, bearer?: string): Request; + oauth(oauth: OAuthOptions): Request; + jar(jar: CookieJar): Request; + + on(event: string, listener: Function): this; + on(event: 'request', listener: (req: http.ClientRequest) => void): this; + on(event: 'response', listener: (resp: http.IncomingMessage) => void): this; + on(event: 'data', listener: (data: Buffer | string) => void): this; + on(event: 'error', listener: (e: Error) => void): this; + on(event: 'complete', listener: (resp: http.IncomingMessage, body?: string | Buffer) => void): this; + + write(buffer: Buffer, cb?: Function): boolean; + write(str: string, cb?: Function): boolean; + write(str: string, encoding: string, cb?: Function): boolean; + write(str: string, encoding?: string, fd?: string): boolean; + end(): void; + end(chunk: Buffer, cb?: Function): void; + end(chunk: string, cb?: Function): void; + end(chunk: string, encoding: string, cb?: Function): void; + pause(): void; + resume(): void; + abort(): void; + destroy(): void; + toJSON(): Object; + } + + export interface Headers { + [key: string]: any; + } + + export interface AuthOptions { + user?: string; + username?: string; + pass?: string; + password?: string; + sendImmediately?: boolean; + bearer?: string; + } + + export interface OAuthOptions { + callback?: string; + consumer_key?: string; + consumer_secret?: string; + token?: string; + token_secret?: string; + verifier?: string; + } + + export interface HawkOptions { + credentials: any; + } + + export interface AWSOptions { + secret: string; + bucket?: string; + } + + export interface CookieJar { + setCookie(cookie: Cookie, uri: string | url.Url, options?: any): void + getCookieString(uri: string | url.Url): string + getCookies(uri: string | url.Url): Cookie[] + } + + export interface CookieValue { + name: string; + value: any; + httpOnly: boolean; + } + + export interface Cookie extends Array { + constructor(name: string, req: Request): void; + str: string; + expires: Date; + path: string; + toString(): string; + } + } + var request: request.RequestAPI; + export = request; +} diff --git a/TypeScriptDefinitions/yargs.d.ts b/TypeScriptDefinitions/yargs.d.ts new file mode 100644 index 0000000..7dc1ef2 --- /dev/null +++ b/TypeScriptDefinitions/yargs.d.ts @@ -0,0 +1,170 @@ +// Type definitions for yargs +// Project: https://github.com/chevex/yargs +// Definitions by: Martin Poelstra +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module "yargs" { + + namespace yargs { + interface Argv { + argv: any; + (...args: any[]): any; + parse(...args: any[]): any; + + reset(): Argv; + + locale(): string; + locale(loc:string): Argv; + + detectLocale(detect:boolean): Argv; + + alias(shortName: string, longName: string): Argv; + alias(aliases: { [shortName: string]: string }): Argv; + alias(aliases: { [shortName: string]: string[] }): Argv; + + array(key: string): Argv; + array(keys: string[]): Argv; + + default(key: string, value: any): Argv; + default(defaults: { [key: string]: any}): Argv; + + demand(key: string, msg: string): Argv; + demand(key: string, required?: boolean): Argv; + demand(keys: string[], msg: string): Argv; + demand(keys: string[], required?: boolean): Argv; + demand(positionals: number, required?: boolean): Argv; + demand(positionals: number, msg: string): Argv; + + require(key: string, msg: string): Argv; + require(key: string, required: boolean): Argv; + require(keys: number[], msg: string): Argv; + require(keys: number[], required: boolean): Argv; + require(positionals: number, required: boolean): Argv; + require(positionals: number, msg: string): Argv; + + required(key: string, msg: string): Argv; + required(key: string, required: boolean): Argv; + required(keys: number[], msg: string): Argv; + required(keys: number[], required: boolean): Argv; + required(positionals: number, required: boolean): Argv; + required(positionals: number, msg: string): Argv; + + requiresArg(key: string): Argv; + requiresArg(keys: string[]): Argv; + + describe(key: string, description: string): Argv; + describe(descriptions: { [key: string]: string }): Argv; + + option(key: string, options: Options): Argv; + option(options: { [key: string]: Options }): Argv; + options(key: string, options: Options): Argv; + options(options: { [key: string]: Options }): Argv; + + usage(message: string, options?: { [key: string]: Options }): Argv; + usage(options?: { [key: string]: Options }): Argv; + + command(command: string, description: string): Argv; + command(command: string, description: string, handler: (args: Argv) => void): Argv; + command(command: string, description: string, builder: (args: Argv) => Options): Argv; + command(command: string, description: string, builder: { [optionName: string]: Options }): Argv; + command(command: string, description: string, builder: { [optionName: string]: Options }, handler: (args: Argv) => void): Argv; + command(command: string, description: string, builder: (args: Argv) => Options, handler: (args: Argv) => void): Argv; + + completion(cmd: string, fn?: SyncCompletionFunction): Argv; + completion(cmd: string, description?: string, fn?: SyncCompletionFunction): Argv; + completion(cmd: string, fn?: AsyncCompletionFunction): Argv; + completion(cmd: string, description?: string, fn?: AsyncCompletionFunction): Argv; + + example(command: string, description: string): Argv; + + check(func: (argv: any, aliases: { [alias: string]: string }) => any): Argv; + + boolean(key: string): Argv; + boolean(keys: string[]): Argv; + + string(key: string): Argv; + string(keys: string[]): Argv; + + choices(choices: Object): Argv; + choices(key: string, values:any[]): Argv; + + config(key: string): Argv; + config(keys: string[]): Argv; + + wrap(columns: number): Argv; + + strict(): Argv; + + help(): string; + help(option: string, description?: string): Argv; + + env(prefix?: string): Argv; + env(enable: boolean): Argv; + + epilog(msg: string): Argv; + epilogue(msg: string): Argv; + + version(version: string, option?: string, description?: string): Argv; + version(version: () => string, option?: string, description?: string): Argv; + + showHelpOnFail(enable: boolean, message?: string): Argv; + + showHelp(func?: (message: string) => any): Argv; + + exitProcess(enabled:boolean): Argv; + + global(key: string): Argv; + global(keys: string[]): Argv; + + group(key: string, groupName: string): Argv; + group(keys: string[], groupName: string): Argv; + + nargs(key: string, count: number): Argv; + nargs(nargs: { [key: string]: number }): Argv; + + /* Undocumented */ + + normalize(key: string): Argv; + normalize(keys: string[]): Argv; + + implies(key: string, value: string): Argv; + implies(implies: { [key: string]: string }): Argv; + + count(key: string): Argv; + count(keys: string[]): Argv; + + fail(func: (msg: string) => any): void; + } + + interface Options { + type?: string; + group?: string; + alias?: any; + demand?: any; + required?: any; + require?: any; + default?: any; + defaultDescription?: string; + boolean?: boolean; + string?: boolean; + count?: boolean; + describe?: any; + description?: any; + desc?: any; + requiresArg?: any; + choices?:string[]; + global?: boolean; + array?: boolean; + config?: boolean; + number?: boolean; + normalize?: boolean; + nargs?: number; + } + + type SyncCompletionFunction = (current: string, argv: any) => string[]; + type AsyncCompletionFunction = (current: string, argv: any, done: (completion: string[]) => void) => void; + } + + var yargs: yargs.Argv; + export = yargs; +} diff --git a/gulpfile.js b/gulpfile.js index efb6f69..313aa31 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,25 +1,106 @@ 'use strict'; -var jshint = require('gulp-jshint'); +var Cesium = require('cesium'); +var child_process = require('child_process'); +var fsExtra = require('fs-extra'); var gulp = require('gulp'); +var gulpJshint = require('gulp-jshint'); +var Jasmine = require('jasmine'); +var JasmineSpecReporter = require('jasmine-spec-reporter'); +var open = require('open'); +var path = require('path'); +var request = require('request'); +var yargs = require('yargs'); -var jsHintFiles = ['index.js', 'bin/*.js', 'lib/*.js']; +var defined = Cesium.defined; +var argv = yargs.argv; -gulp.task('default', ['jsHint']); +// Add third-party node module binaries to the system path +// since some tasks need to call them directly. +var environmentSeparator = process.platform === 'win32' ? ';' : ':'; +var nodeBinaries = path.join(__dirname, 'node_modules', '.bin'); +process.env.PATH += environmentSeparator + nodeBinaries; -gulp.task('jsHint', function() { - return gulp.src(jsHintFiles) - .pipe(jshint.extract('auto')) - .pipe(jshint()) - .pipe(jshint.reporter('jshint-stylish')) - .pipe(jshint.reporter('fail')); +var jsHintFiles = ['**/*.js', '!node_modules/**', '!coverage/**']; +var specFiles = ['**/*.js', '!node_modules/**', '!coverage/**']; + +gulp.task('jsHint', function () { + var stream = gulp.src(jsHintFiles) + .pipe(gulpJshint()) + .pipe(gulpJshint.reporter('jshint-stylish')); + + if (argv.failTaskOnError) { + stream = stream.pipe(gulpJshint.reporter('fail')); + } + + return stream; }); -gulp.task('jsHint-watch', function() { - gulp.watch(jsHintFiles).on('change', function(event) { - gulp.src(event.path) - .pipe(jshint.extract('auto')) - .pipe(jshint()) - .pipe(jshint.reporter('jshint-stylish')); +gulp.task('jsHint-watch', function () { + gulp.watch(jsHintFiles, ['jsHint']); +}); + +gulp.task('test', function (done) { + var jasmine = new Jasmine(); + jasmine.loadConfigFile('specs/jasmine.json'); + jasmine.addReporter(new JasmineSpecReporter({ + displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed + })); + jasmine.execute(); + jasmine.onComplete(function (passed) { + done(argv.failTaskOnError && !passed ? 1 : 0); }); }); + +gulp.task('test-watch', function () { + gulp.watch(specFiles).on('change', function () { + //We can't simply depend on the test task because Jasmine + //does not like being run multiple times in the same process. + try { + child_process.execSync('jasmine JASMINE_CONFIG_PATH=specs/jasmine.json', { + stdio: [process.stdin, process.stdout, process.stderr] + }); + } catch (exception) { + console.log('Tests failed to execute.'); + } + }); +}); + +gulp.task('coverage', function () { + fsExtra.removeSync('coverage/server'); + child_process.execSync('istanbul' + + ' cover' + + ' --include-all-sources' + + ' --dir coverage' + + ' -x "specs/** coverage/** index.js gulpfile.js"' + + ' node_modules/jasmine/bin/jasmine.js' + + ' JASMINE_CONFIG_PATH=specs/jasmine.json', { + stdio: [process.stdin, process.stdout, process.stderr] + }); + open('coverage/lcov-report/index.html'); +}); + +function copyModule(module) { + var tsName = module + '.d.ts'; + var srcUrl = 'https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/' + module + '/' + tsName; + var desPath = path.join('TypeScriptDefinitions', tsName); + + request.get({ + url: srcUrl + }, function (error, response) { + if (error) { + console.log(error); + return; + } + if (response.statusCode >= 200 && response.statusCode < 300) { + fsExtra.outputFileSync(desPath, response.body); + } + }); +} + +gulp.task('update-ts-definitions', function () { + fsExtra.removeSync('TypeScriptDefinitions'); + var packageJson = require('./package.json'); + Object.keys(packageJson.dependencies).forEach(copyModule); + Object.keys(packageJson.devDependencies).forEach(copyModule); +}); diff --git a/package.json b/package.json index 4c12f5c..e9fcc6d 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "obj2gltf", - "version": "0.0.1", + "version": "0.1.0", "description": "Convert OBJ model format to glTF", "license": "Apache-2.0", - "author": { - "name": "Sean Lilley", - "email": "slilley@agi.com" - }, + "contributors": [ + { + "name": "Analytical Graphics, Inc., and Contributors", + "url": "https://github.com/AnalyticalGraphicsInc/OBJ2GLTF/graphs/contributors" + } + ], "keywords": [ "obj", "gltf" @@ -19,26 +21,39 @@ "bugs": { "url": "https://github.com/AnalyticalGraphicsInc/OBJ2GLTF/issues" }, + "main": "index.js", "engines": { "node": ">=4.0.0" }, - "scripts": { - "jsHint": "gulp jsHint", - "jsHint-watch": "gulp jsHint-watch" - }, "dependencies": { - "async": "^1.4.2", - "byline": "^4.2.1", - "cesium": "^1.22.0", - "fs-extra": "^0.30.0", - "gltf-pipeline": "git://github.com/AnalyticalGraphicsInc/gltf-pipeline.git", - "path": "^0.12.7", - "yargs": "^4.7.1" + "async": "2.0.0-rc.6", + "byline": "4.2.1", + "cesium": "1.23.0", + "fs-extra": "0.30.0", + "gltf-pipeline": "0.1.0", + "yargs": "4.7.1" }, "devDependencies": { - "gulp": "^3.9.1", - "gulp-jshint": "^2.0.1", - "jshint": "^2.6.0", - "jshint-stylish": "^2.2.0" + "gulp": "3.9.1", + "gulp-jshint": "2.0.1", + "istanbul": "0.4.4", + "jasmine": "2.4.1", + "jasmine-spec-reporter": "2.5.0", + "jshint": "2.9.2", + "jshint-stylish": "2.2.0", + "open": "0.0.5", + "request": "2.72.0", + "requirejs": "2.2.0" + }, + "scripts": { + "jsHint": "gulp jsHint", + "jsHint-watch": "gulp jsHint-watch", + "test": "gulp test", + "test-watch": "gulp test-watch", + "coverage": "gulp coverage", + "update-ts-definitions": "gulp update-ts-definitions" + }, + "bin": { + "obj2gltf": "./bin/obj2gltf.js" } } diff --git a/specs/.jshintrc b/specs/.jshintrc new file mode 100644 index 0000000..d921aae --- /dev/null +++ b/specs/.jshintrc @@ -0,0 +1,5 @@ +{ + "extends": "../.jshintrc", + "jasmine": true, + "unused": false +} diff --git a/specs/jasmine.json b/specs/jasmine.json new file mode 100644 index 0000000..daab2c1 --- /dev/null +++ b/specs/jasmine.json @@ -0,0 +1,9 @@ +{ + "spec_dir": "specs", + "spec_files": [ + "**/*Spec.js" + ], + "helpers": [ + "matchers/nodeHelper.js" + ] +} diff --git a/specs/matchers/addDefaultMatchers.js b/specs/matchers/addDefaultMatchers.js new file mode 100644 index 0000000..a1c6410 --- /dev/null +++ b/specs/matchers/addDefaultMatchers.js @@ -0,0 +1,215 @@ +//This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/addDefaultMatchers.js +/*global define*/ +/*jshint unused:false*/ +define([ + './equals', + 'Cesium/Core/defined', + 'Cesium/Core/DeveloperError', + 'Cesium/Core/RuntimeError' + ], function( + equals, + defined, + DeveloperError, + RuntimeError) { + 'use strict'; + + function createMissingFunctionMessageFunction(item, actualPrototype, expectedInterfacePrototype) { + return function() { + return 'Expected function \'' + item + '\' to exist on ' + actualPrototype.constructor.name + ' because it should implement interface ' + expectedInterfacePrototype.constructor.name + '.'; + }; + } + + function makeThrowFunction(debug, Type, name) { + if (debug) { + return function(util, customEqualityTesters) { + return { + compare : function(actual, expected) { + // based on the built-in Jasmine toThrow matcher + var result = false; + var exception; + + if (typeof actual !== 'function') { + throw new Error('Actual is not a function'); + } + + try { + actual(); + } catch (e) { + exception = e; + } + + if (exception) { + result = exception instanceof Type; + } + + var message; + if (result) { + message = ['Expected function not to throw ' + name + ' , but it threw', exception.message || exception].join(' '); + if (defined(expected)) { + expect(expected).toEqual(exception.message); + } + } else { + message = 'Expected function to throw ' + name + '.'; + } + + return { + pass : result, + message : message + }; + } + }; + }; + } + + return function() { + return { + compare : function(actual, expected) { + return { pass : true }; + }, + negativeCompare : function(actual, expected) { + return { pass : true }; + } + }; + }; + } + + function createDefaultMatchers(debug) { + return { + toBeGreaterThanOrEqualTo : function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { pass : actual >= expected }; + } + }; + }, + + toBeLessThanOrEqualTo : function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { pass : actual <= expected }; + } + }; + }, + + toBeBetween : function(util, customEqualityTesters) { + return { + compare: function(actual, lower, upper) { + if (lower > upper) { + var tmp = upper; + upper = lower; + lower = tmp; + } + return { pass : actual >= lower && actual <= upper }; + } + }; + }, + + toStartWith : function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { pass : actual.slice(0, expected.length) === expected }; + } + }; + }, + + toEndWith : function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { pass : actual.slice(-expected.length) === expected }; + } + }; + }, + + toEqual : function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { pass : equals(util, customEqualityTesters, actual, expected) }; + } + }; + }, + + toEqualEpsilon : function(util, customEqualityTesters) { + return { + compare: function(actual, expected, epsilon) { + function equalityTester(a, b) { + var to_run; + if (defined(a)) { + if (typeof a.equalsEpsilon === 'function') { + return a.equalsEpsilon(b, epsilon); + } else if (a instanceof Object) { + // Check if the current object has a static function named 'equalsEpsilon' + to_run = Object.getPrototypeOf(a).constructor.equalsEpsilon; + if (typeof to_run === 'function') { + return to_run(a, b, epsilon); + } + } + } + + if (defined(b)) { + if (typeof b.equalsEpsilon === 'function') { + return b.equalsEpsilon(a, epsilon); + } else if (b instanceof Object) { + // Check if the current object has a static function named 'equalsEpsilon' + to_run = Object.getPrototypeOf(b).constructor.equalsEpsilon; + if (typeof to_run === 'function') { + return to_run(b, a, epsilon); + } + } + } + + if (typeof a === 'number' || typeof b === 'number') { + return Math.abs(a - b) <= epsilon; + } + + return undefined; + } + + var result = equals(util, [equalityTester], actual, expected); + + return { pass : result }; + } + }; + }, + + toConformToInterface : function(util, customEqualityTesters) { + return { + compare : function(actual, expectedInterface) { + // All function properties on the prototype should also exist on the actual's prototype. + var actualPrototype = actual.prototype; + var expectedInterfacePrototype = expectedInterface.prototype; + + for ( var item in expectedInterfacePrototype) { + if (expectedInterfacePrototype.hasOwnProperty(item) && typeof expectedInterfacePrototype[item] === 'function' && !actualPrototype.hasOwnProperty(item)) { + return { pass : false, message : createMissingFunctionMessageFunction(item, actualPrototype, expectedInterfacePrototype) }; + } + } + + return { pass : true }; + } + }; + }, + + toBeInstanceOf : function(util, customEqualityTesters) { + return { + compare : function(actual, expectedConstructor) { + return { pass : actual instanceof expectedConstructor }; + } + }; + }, + + toThrow : function(expectedConstructor) { + throw new Error('Do not use toThrow. Use toThrowDeveloperError or toThrowRuntimeError instead.'); + }, + + toThrowDeveloperError : makeThrowFunction(debug, DeveloperError, 'DeveloperError'), + + toThrowRuntimeError : makeThrowFunction(true, RuntimeError, 'RuntimeError') + }; + } + + return function(debug) { + return function() { + this.addMatchers(createDefaultMatchers(debug)); + }; + }; +}); diff --git a/specs/matchers/customizeJasmine.js b/specs/matchers/customizeJasmine.js new file mode 100644 index 0000000..8630965 --- /dev/null +++ b/specs/matchers/customizeJasmine.js @@ -0,0 +1,15 @@ +/*global define*/ +define([ + './addDefaultMatchers', + './equalsMethodEqualityTester' +], function (addDefaultMatchers, + equalsMethodEqualityTester) { + 'use strict'; + + return function (env) { + env.beforeEach(function () { + addDefaultMatchers(true).call(env); + env.addCustomEqualityTester(equalsMethodEqualityTester); + }); + }; +}); diff --git a/specs/matchers/equals.js b/specs/matchers/equals.js new file mode 100644 index 0000000..99203d0 --- /dev/null +++ b/specs/matchers/equals.js @@ -0,0 +1,45 @@ +//This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equals.js +/*global define*/ +define([ + 'Cesium/Core/FeatureDetection' + ], function( + FeatureDetection) { + 'use strict'; + /*global CanvasPixelArray*/ + + var typedArrayTypes = []; + + // Earlier versions of IE do not support typed arrays + if (FeatureDetection.supportsTypedArrays()) { + typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array); + + if (typeof Uint8ClampedArray !== 'undefined') { + typedArrayTypes.push(Uint8ClampedArray); + } + + if (typeof CanvasPixelArray !== 'undefined') { + typedArrayTypes.push(CanvasPixelArray); + } + } + + function isTypedArray(o) { + return typedArrayTypes.some(function(type) { + return o instanceof type; + }); + } + + function typedArrayToArray(array) { + if (array !== null && typeof array === 'object' && isTypedArray(array)) { + return Array.prototype.slice.call(array, 0); + } + return array; + } + + function equals(util, customEqualiyTesters, a, b) { + a = typedArrayToArray(a); + b = typedArrayToArray(b); + return util.equals(a, b, customEqualiyTesters); + } + + return equals; +}); diff --git a/specs/matchers/equalsMethodEqualityTester.js b/specs/matchers/equalsMethodEqualityTester.js new file mode 100644 index 0000000..b9fd40e --- /dev/null +++ b/specs/matchers/equalsMethodEqualityTester.js @@ -0,0 +1,39 @@ +//This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equalsMethodEqualityTester.js +/*global define*/ +define([ + 'Cesium/Core/defined' + ], function( + defined) { + 'use strict'; + + return function(a, b) { + var to_run; + // if either a or b have an equals method, call it. + if (a !== null && defined(a)) { + if (typeof a.equals === 'function') { + return a.equals(b); + } else if(a instanceof Object) { + // Check if the current object has a static function named 'equals' + to_run = Object.getPrototypeOf(a).constructor.equals; + if( typeof to_run === 'function') { + return to_run(a, b); + } + } + } + + if (b !== null && defined(b)) { + if (typeof b.equals === 'function') { + return b.equals(a); + } else if(b instanceof Object) { + // Check if the current object has a static function named 'equals' + to_run = Object.getPrototypeOf(b).constructor.equals; + if( typeof to_run === 'function') { + return to_run(b, a); + } + } + } + + // fall back to default equality checks. + return undefined; + }; +}); diff --git a/specs/matchers/expectPromise.js b/specs/matchers/expectPromise.js new file mode 100644 index 0000000..8b73ee4 --- /dev/null +++ b/specs/matchers/expectPromise.js @@ -0,0 +1,47 @@ +'use strict'; + +var Cesium = require('cesium'); + +var defined = Cesium.defined; +var defaultValue = Cesium.defaultValue; + +module.exports = function expectPrommise(promise, done) { + return { + toResolve: function toResolve() { + return promise + .then(done) + .catch(function(err){ + done.fail('Expected promise to resolve' + err); + }); + }, + toResolveWith: function toResolveWith(expectedValue) { + return promise + .then(function (result) { + expect(result).toEqual(expectedValue); + done(); + }) + .catch(function(err){ + done.fail('Expected promise to resolve' + err); + }); + }, + toRejectWith: function toRejectWith(ErrorType, errorMessage) { + var typeName = defaultValue(ErrorType.displayName, ErrorType.name); + + promise + .then(function () { + done.fail('expected promise to reject with ' + typeName); + }) + .catch(function (error) { + if (!(error instanceof ErrorType)) { + done.fail(defaultValue(defaultValue(error.displayName, error.name), ErrorType) + ' to be instance of ' + typeName); + console.log(error); + } + + if (defined(errorMessage)) { + expect(error.message).toEqual(errorMessage); + } + done(); + }); + } + }; +}; diff --git a/specs/matchers/nodeHelper.js b/specs/matchers/nodeHelper.js new file mode 100644 index 0000000..2787699 --- /dev/null +++ b/specs/matchers/nodeHelper.js @@ -0,0 +1,33 @@ +'use strict'; + +var path = require('path'); +var requirejs = require('requirejs'); + +var expectPromise = require('./expectPromise'); + +//Since Jasmine matchers are shared between client and server code +//We need to use requirejs to bring them into node. +requirejs.config({ + baseUrl: path.join(__dirname, '../..'), + paths: { + 'Cesium': 'node_modules/cesium/source' + }, + nodeRequire: require +}); + +var customizeJasmine = requirejs('./specs/matchers/customizeJasmine'); + +var env = jasmine.getEnv(); +customizeJasmine(env); + +var oldExpect = global.expect; +global.expect = function (promise, done) { + //We can't use instanceof Promise here because promise + //may not be a bluebird-defined Promise + if (promise && promise.then && done) { + return expectPromise(promise, done); + } + + //If it wasn't a promise, call original implementation + return oldExpect.apply(global, arguments); +};