├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── src └── index.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | docs 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2017 Endel Dreyer 2 | Copyright © 2008 Philip Hutchison 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @gamestdio/scorm Donate on Patreon 2 | 3 | > SCORM 1.2/2004 Wrapper for JavaScript/TypeScript 4 | 5 | Integrate your e-learning course with SCORM 1.2/2004 LMS. 6 | 7 | This implementation is highly based on a battle tested version from 8 | [pipwerks/scorm-api-wrapper](https://github.com/pipwerks/scorm-api-wrapper). 9 | 10 | ## Why? 11 | 12 | No SCORM wrapper had support for modern JavaScript/TypeScript. 13 | 14 | ## Usage 15 | 16 | ```typescript 17 | import { scorm } from "@gamestdio/scorm"; 18 | 19 | // set configuration options 20 | scorm.configure({ 21 | debug: true 22 | }); 23 | 24 | // initialize connection with parent/opener windows 25 | scorm.initialize(); 26 | 27 | scorm.set('cmi.core.lesson_status', 'Not Attempted'); 28 | scorm.commit(); 29 | 30 | // finish e-learning session 31 | scorm.terminate(); 32 | ``` 33 | 34 | ## Testing 35 | 36 | 1. Create a free account on [SCORM Cloud](https://cloud.scorm.com) 37 | 2. Download and include one of the [XML Schema Definition files](https://scorm.com/scorm-explained/technical-scorm/content-packaging/xml-schema-definition-files/) into your package. 38 | 3. Edit the `imsmanifest.xml` to meet your needs. 39 | 4. Upload your e-learning course to SCORM Cloud. 40 | 41 | ## References 42 | 43 | - [SCORM 1.2 Run-Time Environment](http://xml.coverpages.org/SCORM-12-RunTimeEnv.pdf) 44 | - [SCORM 2004 Guide for Programmers](https://www.adlnet.gov/public/uploads/SCORM_Users_Guide_for_Programmers.pdf) 45 | - [Wikipedia: Sharable_Content_Object_Reference_Model](https://en.wikipedia.org/wiki/Sharable_Content_Object_Reference_Model) 46 | 47 | ## License 48 | 49 | MIT 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gamestdio/scorm", 3 | "version": "0.1.3", 4 | "description": "SCORM 1.2/2004 Wrapper for JavaScript/TypeScript", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "docs": "typedoc --excludePrivate --excludeNotExported --out docs --mode file --entryPoint index", 8 | "prepublish": "tsc", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "author": "Endel Dreyer", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "typedoc": "^0.8.0", 15 | "typescript": "^2.4.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Based on pipwerks SCORM Wrapper for JavaScript 3 | * Created by Philip Hutchison, January 2008-2016 4 | */ 5 | 6 | let apiHandle: any = null; 7 | let isAPIFound = false; 8 | 9 | /* ------------------------------------------------------------------------- 10 | api.find(window) 11 | Looks for an object named API in parent and opener windows 12 | Parameters: window (the browser window object). 13 | Returns: Object if API is found, null if no API found 14 | ---------------------------------------------------------------------------- */ 15 | 16 | function find (win) { 17 | let API = null, 18 | findAttempts = 0, 19 | findAttemptLimit = 500, 20 | traceMsgPrefix = 'SCORM.API.find'; 21 | 22 | while ( 23 | !win.API && 24 | !win.API_1484_11 && 25 | win.parent && 26 | win.parent != win && 27 | findAttempts <= findAttemptLimit 28 | ) { 29 | findAttempts++; 30 | win = win.parent; 31 | } 32 | 33 | //If SCORM version is specified by user, look for specific API 34 | if (scorm.version) { 35 | switch (scorm.version) { 36 | case '2004': 37 | if (win.API_1484_11) { 38 | API = win.API_1484_11; 39 | } else { 40 | debug( 41 | traceMsgPrefix + 42 | ': SCORM version 2004 was specified by user, but API_1484_11 cannot be found.', 43 | ); 44 | } 45 | 46 | break; 47 | 48 | case '1.2': 49 | if (win.API) { 50 | API = win.API; 51 | } else { 52 | debug( 53 | traceMsgPrefix + 54 | ': SCORM version 1.2 was specified by user, but API cannot be found.', 55 | ); 56 | } 57 | 58 | break; 59 | } 60 | } else { 61 | //If SCORM version not specified by user, look for APIs 62 | 63 | if (win.API_1484_11) { 64 | //SCORM 2004-specific API. 65 | 66 | scorm.version = '2004'; //Set version 67 | API = win.API_1484_11; 68 | } else if (win.API) { 69 | //SCORM 1.2-specific API 70 | 71 | scorm.version = '1.2'; //Set version 72 | API = win.API; 73 | } 74 | } 75 | 76 | if (API) { 77 | debug(traceMsgPrefix + ': API found. Version: ' + scorm.version); 78 | debug('API: ' + API); 79 | } else { 80 | debug( 81 | traceMsgPrefix + 82 | ': Error finding API. \nFind attempts: ' + 83 | findAttempts + 84 | '. \nFind attempt limit: ' + 85 | findAttemptLimit, 86 | ); 87 | } 88 | 89 | return API; 90 | }; 91 | 92 | /* ------------------------------------------------------------------------- 93 | api.get() 94 | Looks for an object named API, first in the current window's frame 95 | hierarchy and then, if necessary, in the current window's opener window 96 | hierarchy (if there is an opener window). 97 | Parameters: None. 98 | Returns: Object if API found, null if no API found 99 | ---------------------------------------------------------------------------- */ 100 | 101 | function getAPI () { 102 | let API = null, 103 | win = window; 104 | 105 | API = find(win); 106 | 107 | if (!API && win.parent && win.parent != win) { 108 | API = find(win.parent); 109 | } 110 | 111 | if (!API && win.top && win.top.opener) { 112 | API = find(win.top.opener); 113 | } 114 | 115 | //Special handling for Plateau 116 | //Thanks to Joseph Venditti for the patch 117 | if (!API && win.top && win.top.opener && win.top.opener.document) { 118 | API = find(win.top.opener.document); 119 | } 120 | 121 | if (API) { 122 | isAPIFound = true; 123 | } else { 124 | debug("getAPI failed: Can't find the API!"); 125 | } 126 | 127 | return API; 128 | }; 129 | 130 | /* ------------------------------------------------------------------------- 131 | api.getHandle() 132 | Returns the handle to API object if it was previously set 133 | Parameters: None. 134 | Returns: Object (the api.handle variable). 135 | ---------------------------------------------------------------------------- */ 136 | 137 | function getHandle () { 138 | if (!apiHandle && !isAPIFound) { 139 | apiHandle = getAPI(); 140 | } 141 | 142 | return apiHandle; 143 | }; 144 | 145 | // Public API 146 | 147 | export class Scorm { 148 | version: string; 149 | handleExitMode: boolean = true; 150 | handleCompletionStatus: boolean = true; 151 | isDebugActive: boolean = true; 152 | exitStatus: any; 153 | 154 | isActive = false; 155 | completionStatus: any; 156 | 157 | configure (config: { 158 | version?: string; // SCORM version. 159 | debug?: boolean; 160 | handleExitMode?: boolean; // Whether or not the wrapper should automatically handle the exit mode 161 | handleCompletionStatus?: boolean; // Whether or not the wrapper should automatically handle the initial completion status 162 | } = {}) { 163 | this.version = config.version; 164 | 165 | this.handleExitMode = (config.handleExitMode === undefined) 166 | ? !!config.handleExitMode 167 | : true; 168 | 169 | this.handleCompletionStatus = (config.handleCompletionStatus === undefined) 170 | ? !!config.handleCompletionStatus 171 | : true; 172 | 173 | this.isDebugActive = (config.debug === undefined) 174 | ? !!config.debug 175 | : true; 176 | } 177 | 178 | initialize () { 179 | let success = false, 180 | traceMsgPrefix = 'scorm.initialize '; 181 | 182 | debug('connection.initialize called.'); 183 | 184 | if (!this.isActive) { 185 | let API = getHandle(), 186 | errorCode = 0; 187 | 188 | if (API) { 189 | switch (this.version) { 190 | case '1.2': 191 | success = toBoolean(API.LMSInitialize('')); 192 | break; 193 | case '2004': 194 | success = toBoolean(API.Initialize('')); 195 | break; 196 | } 197 | 198 | if (success) { 199 | //Double-check that connection is active and working before returning 'true' boolean 200 | errorCode = this.getLastError(); 201 | 202 | if (errorCode !== null && errorCode === 0) { 203 | this.isActive = true; 204 | 205 | if (this.handleCompletionStatus) { 206 | //Automatically set new launches to incomplete 207 | this.completionStatus = this.status(); 208 | 209 | if (this.completionStatus) { 210 | switch (this.completionStatus) { 211 | //Both SCORM 1.2 and 2004 212 | case 'not attempted': 213 | this.status('incomplete'); 214 | break; 215 | 216 | //SCORM 2004 only 217 | case 'unknown': 218 | this.status('incomplete'); 219 | break; 220 | 221 | //Additional options, presented here in case you'd like to use them 222 | //case "completed" : break; 223 | //case "incomplete" : break; 224 | //case "passed" : break; //SCORM 1.2 only 225 | //case "failed" : break; //SCORM 1.2 only 226 | //case "browsed" : break; //SCORM 1.2 only 227 | } 228 | 229 | //Commit changes 230 | scorm.commit(); 231 | } 232 | } 233 | } else { 234 | success = false; 235 | debug( 236 | traceMsgPrefix + 237 | 'failed. \nError code: ' + 238 | errorCode + 239 | ' \nError info: ' + 240 | this.getErrorString(errorCode), 241 | ); 242 | } 243 | } else { 244 | errorCode = this.getLastError(); 245 | 246 | if (errorCode !== null && errorCode !== 0) { 247 | debug( 248 | traceMsgPrefix + 249 | 'failed. \nError code: ' + 250 | errorCode + 251 | ' \nError info: ' + 252 | this.getErrorString(errorCode), 253 | ); 254 | } else { 255 | debug(traceMsgPrefix + 'failed: No response from server.'); 256 | } 257 | } 258 | } else { 259 | debug(traceMsgPrefix + 'failed: API is null.'); 260 | } 261 | } else { 262 | debug(traceMsgPrefix + 'aborted: Connection already active.'); 263 | } 264 | 265 | return success; 266 | } 267 | 268 | terminate () { 269 | let success = false, 270 | traceMsgPrefix = 'scorm.terminate '; 271 | 272 | if (this.isActive) { 273 | let API = getHandle(), 274 | errorCode = 0; 275 | 276 | if (API) { 277 | if (scorm.handleExitMode && !this.exitStatus) { 278 | if (this.completionStatus !== 'completed' && this.completionStatus !== 'passed') { 279 | switch (scorm.version) { 280 | case '1.2': 281 | success = scorm.set('cmi.core.exit', 'suspend'); 282 | break; 283 | case '2004': 284 | success = scorm.set('cmi.exit', 'suspend'); 285 | break; 286 | } 287 | } else { 288 | switch (scorm.version) { 289 | case '1.2': 290 | success = scorm.set('cmi.core.exit', 'logout'); 291 | break; 292 | case '2004': 293 | success = scorm.set('cmi.exit', 'normal'); 294 | break; 295 | } 296 | } 297 | } 298 | 299 | //Ensure we persist the data 300 | success = scorm.commit(); 301 | 302 | if (success) { 303 | switch (scorm.version) { 304 | case '1.2': 305 | success = toBoolean(API.LMSFinish('')); 306 | break; 307 | case '2004': 308 | success = toBoolean(API.Terminate('')); 309 | break; 310 | } 311 | 312 | if (success) { 313 | this.isActive = false; 314 | } else { 315 | errorCode = this.getLastError(); 316 | debug( 317 | traceMsgPrefix + 318 | 'failed. \nError code: ' + 319 | errorCode + 320 | ' \nError info: ' + 321 | this.getErrorString(errorCode), 322 | ); 323 | } 324 | } 325 | } else { 326 | debug(traceMsgPrefix + 'failed: API is null.'); 327 | } 328 | } else { 329 | debug(traceMsgPrefix + 'aborted: Connection already terminated.'); 330 | } 331 | 332 | return success; 333 | } 334 | 335 | get (parameter) { 336 | let value = null, 337 | traceMsgPrefix = "scorm.get('" + parameter + "') "; 338 | 339 | if (this.isActive) { 340 | let API = getHandle(), 341 | errorCode = 0; 342 | 343 | if (API) { 344 | switch (scorm.version) { 345 | case '1.2': 346 | value = API.LMSGetValue(parameter); 347 | break; 348 | case '2004': 349 | value = API.GetValue(parameter); 350 | break; 351 | } 352 | 353 | errorCode = this.getLastError(); 354 | 355 | //GetValue returns an empty string on errors 356 | //If value is an empty string, check errorCode to make sure there are no errors 357 | if (value !== '' || errorCode === 0) { 358 | //GetValue is successful. 359 | //If parameter is lesson_status/completion_status or exit status, let's 360 | //grab the value and cache it so we can check it during connection.terminate() 361 | switch (parameter) { 362 | case 'cmi.core.lesson_status': 363 | case 'cmi.completion_status': 364 | this.completionStatus = value; 365 | break; 366 | 367 | case 'cmi.core.exit': 368 | case 'cmi.exit': 369 | this.exitStatus = value; 370 | break; 371 | } 372 | } else { 373 | debug( 374 | traceMsgPrefix + 375 | 'failed. \nError code: ' + 376 | errorCode + 377 | '\nError info: ' + 378 | this.getErrorString(errorCode), 379 | ); 380 | } 381 | } else { 382 | debug(traceMsgPrefix + 'failed: API is null.'); 383 | } 384 | } else { 385 | debug(traceMsgPrefix + 'failed: API connection is inactive.'); 386 | } 387 | 388 | debug(traceMsgPrefix + ' value: ' + value); 389 | 390 | return String(value); 391 | } 392 | 393 | set (parameter, value) { 394 | let success = false, 395 | traceMsgPrefix = "scorm.set('" + parameter + "') "; 396 | 397 | if (this.isActive) { 398 | let API = getHandle(), 399 | errorCode = 0; 400 | 401 | if (API) { 402 | switch (scorm.version) { 403 | case '1.2': 404 | success = toBoolean(API.LMSSetValue(parameter, value)); 405 | break; 406 | case '2004': 407 | success = toBoolean(API.SetValue(parameter, value)); 408 | break; 409 | } 410 | 411 | if (success) { 412 | if ( 413 | parameter === 'cmi.core.lesson_status' || 414 | parameter === 'cmi.completion_status' 415 | ) { 416 | this.completionStatus = value; 417 | } 418 | } else { 419 | errorCode = this.getLastError(); 420 | 421 | debug( 422 | traceMsgPrefix + 423 | 'failed. \nError code: ' + 424 | errorCode + 425 | '. \nError info: ' + 426 | this.getErrorString(errorCode), 427 | ); 428 | } 429 | } else { 430 | debug(traceMsgPrefix + 'failed: API is null.'); 431 | } 432 | } else { 433 | debug(traceMsgPrefix + 'failed: API connection is inactive.'); 434 | } 435 | 436 | debug(traceMsgPrefix + ' value: ' + value); 437 | 438 | return success; 439 | } 440 | 441 | commit () { 442 | let success = false, 443 | traceMsgPrefix = 'scorm.commit failed'; 444 | 445 | if (this.isActive) { 446 | let API = getHandle(); 447 | 448 | if (API) { 449 | switch (scorm.version) { 450 | case '1.2': 451 | success = toBoolean(API.LMSCommit('')); 452 | break; 453 | case '2004': 454 | success = toBoolean(API.Commit('')); 455 | break; 456 | } 457 | } else { 458 | debug(traceMsgPrefix + ': API is null.'); 459 | } 460 | } else { 461 | debug(traceMsgPrefix + ': API connection is inactive.'); 462 | } 463 | 464 | return success; 465 | } 466 | 467 | status (status?: string) { 468 | let success: any = false, 469 | traceMsgPrefix = 'scorm.status failed', 470 | cmi = '', 471 | action = (arguments.length === 0) ? 'get' : 'set'; 472 | 473 | switch (scorm.version) { 474 | case '1.2': 475 | cmi = 'cmi.core.lesson_status'; 476 | break; 477 | case '2004': 478 | cmi = 'cmi.completion_status'; 479 | break; 480 | } 481 | 482 | switch (action) { 483 | case 'get': 484 | success = this.get(cmi); 485 | break; 486 | 487 | case 'set': 488 | if (status !== null) { 489 | success = this.set(cmi, status); 490 | } else { 491 | success = false; 492 | debug(traceMsgPrefix + ': status was not specified.'); 493 | } 494 | 495 | break; 496 | 497 | default: 498 | success = false; 499 | debug(traceMsgPrefix + ': no valid action was specified.'); 500 | } 501 | 502 | return success; 503 | } 504 | 505 | getLastError () { 506 | let API = getHandle(), 507 | code = 0; 508 | 509 | if (API) { 510 | switch (this.version) { 511 | case '1.2': 512 | code = parseInt(API.LMSGetLastError(), 10); 513 | break; 514 | case '2004': 515 | code = parseInt(API.GetLastError(), 10); 516 | break; 517 | } 518 | } else { 519 | debug('scorm.getLastError failed: API is null.'); 520 | } 521 | 522 | return code; 523 | } 524 | 525 | getErrorString (errorCode) { 526 | let API = getHandle(), 527 | result = ''; 528 | 529 | if (API) { 530 | switch (this.version) { 531 | case '1.2': 532 | result = API.LMSGetErrorString(errorCode.toString()); 533 | break; 534 | case '2004': 535 | result = API.GetErrorString(errorCode.toString()); 536 | break; 537 | } 538 | } else { 539 | debug('scorm.getErrorString failed: API is null.'); 540 | } 541 | 542 | return String(result); 543 | } 544 | 545 | getDiagnostic (errorCode) { 546 | let API = getHandle(), 547 | result = ''; 548 | 549 | if (API) { 550 | switch (this.version) { 551 | case '1.2': 552 | result = API.LMSGetDiagnostic(errorCode); 553 | break; 554 | case '2004': 555 | result = API.GetDiagnostic(errorCode); 556 | break; 557 | } 558 | } else { 559 | debug('scorm.getDiagnostic failed: API is null.'); 560 | } 561 | 562 | return String(result); 563 | } 564 | } 565 | 566 | function toBoolean (value) { 567 | switch (typeof(value)) { 568 | case 'object': 569 | case 'string': 570 | return /(true|1)/i.test(value); 571 | case 'number': 572 | return !!value; 573 | case 'boolean': 574 | return value; 575 | case 'undefined': 576 | return null; 577 | default: 578 | return false; 579 | } 580 | }; 581 | 582 | function debug (msg) { 583 | if (scorm.isDebugActive) { 584 | window.console.log(msg); 585 | } 586 | }; 587 | 588 | export let scorm = new Scorm(); 589 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "lib", 4 | "target": "es5", 5 | "module": "commonjs", 6 | "declaration": true 7 | }, 8 | "include": [ 9 | "src/*.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/fs-extra@^4.0.0": 6 | version "4.0.0" 7 | resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.0.tgz#1dd742ad5c9bce308f7a52d02ebc01421bc9102f" 8 | dependencies: 9 | "@types/node" "*" 10 | 11 | "@types/glob@*": 12 | version "5.0.30" 13 | resolved "https://registry.npmjs.org/@types/glob/-/glob-5.0.30.tgz#1026409c5625a8689074602808d082b2867b8a51" 14 | dependencies: 15 | "@types/minimatch" "*" 16 | "@types/node" "*" 17 | 18 | "@types/handlebars@^4.0.31": 19 | version "4.0.35" 20 | resolved "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.35.tgz#409eb97a3ad6970daba4d586cb6afe3f5e082c01" 21 | 22 | "@types/highlight.js@^9.1.8": 23 | version "9.1.9" 24 | resolved "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.1.9.tgz#ed6336955eaf233b75eb7923b9b1f373d045ef01" 25 | 26 | "@types/lodash@^4.14.37": 27 | version "4.14.72" 28 | resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.72.tgz#f090cf6eb1fee1647a0efa1ebe18b0b78ed551c6" 29 | 30 | "@types/marked@0.0.28": 31 | version "0.0.28" 32 | resolved "https://registry.npmjs.org/@types/marked/-/marked-0.0.28.tgz#44ba754e9fa51432583e8eb30a7c4dd249b52faa" 33 | 34 | "@types/minimatch@*", "@types/minimatch@^2.0.29": 35 | version "2.0.29" 36 | resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" 37 | 38 | "@types/node@*": 39 | version "8.0.20" 40 | resolved "https://registry.npmjs.org/@types/node/-/node-8.0.20.tgz#65c7375255c24b184c215a5d0b63247c32f01c91" 41 | 42 | "@types/shelljs@^0.7.0": 43 | version "0.7.4" 44 | resolved "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.4.tgz#137b5f31306eaff4de120ffe5b9d74b297809cfc" 45 | dependencies: 46 | "@types/glob" "*" 47 | "@types/node" "*" 48 | 49 | align-text@^0.1.1, align-text@^0.1.3: 50 | version "0.1.4" 51 | resolved "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" 52 | dependencies: 53 | kind-of "^3.0.2" 54 | longest "^1.0.1" 55 | repeat-string "^1.5.2" 56 | 57 | amdefine@>=0.0.4: 58 | version "1.0.1" 59 | resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" 60 | 61 | async@^1.4.0: 62 | version "1.5.2" 63 | resolved "https://registry.npmjs.org/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 64 | 65 | balanced-match@^1.0.0: 66 | version "1.0.0" 67 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 68 | 69 | brace-expansion@^1.1.7: 70 | version "1.1.8" 71 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 72 | dependencies: 73 | balanced-match "^1.0.0" 74 | concat-map "0.0.1" 75 | 76 | camelcase@^1.0.2: 77 | version "1.2.1" 78 | resolved "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" 79 | 80 | center-align@^0.1.1: 81 | version "0.1.3" 82 | resolved "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" 83 | dependencies: 84 | align-text "^0.1.3" 85 | lazy-cache "^1.0.3" 86 | 87 | cliui@^2.1.0: 88 | version "2.1.0" 89 | resolved "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" 90 | dependencies: 91 | center-align "^0.1.1" 92 | right-align "^0.1.1" 93 | wordwrap "0.0.2" 94 | 95 | concat-map@0.0.1: 96 | version "0.0.1" 97 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 98 | 99 | decamelize@^1.0.0: 100 | version "1.2.0" 101 | resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 102 | 103 | fs-extra@^4.0.0: 104 | version "4.0.1" 105 | resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" 106 | dependencies: 107 | graceful-fs "^4.1.2" 108 | jsonfile "^3.0.0" 109 | universalify "^0.1.0" 110 | 111 | fs.realpath@^1.0.0: 112 | version "1.0.0" 113 | resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 114 | 115 | glob@^7.0.0: 116 | version "7.1.2" 117 | resolved "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 118 | dependencies: 119 | fs.realpath "^1.0.0" 120 | inflight "^1.0.4" 121 | inherits "2" 122 | minimatch "^3.0.4" 123 | once "^1.3.0" 124 | path-is-absolute "^1.0.0" 125 | 126 | graceful-fs@^4.1.2, graceful-fs@^4.1.6: 127 | version "4.1.11" 128 | resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 129 | 130 | handlebars@^4.0.6: 131 | version "4.0.10" 132 | resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" 133 | dependencies: 134 | async "^1.4.0" 135 | optimist "^0.6.1" 136 | source-map "^0.4.4" 137 | optionalDependencies: 138 | uglify-js "^2.6" 139 | 140 | highlight.js@^9.0.0: 141 | version "9.12.0" 142 | resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" 143 | 144 | inflight@^1.0.4: 145 | version "1.0.6" 146 | resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 147 | dependencies: 148 | once "^1.3.0" 149 | wrappy "1" 150 | 151 | inherits@2: 152 | version "2.0.3" 153 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 154 | 155 | interpret@^1.0.0: 156 | version "1.0.3" 157 | resolved "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" 158 | 159 | is-buffer@^1.1.5: 160 | version "1.1.5" 161 | resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" 162 | 163 | jsonfile@^3.0.0: 164 | version "3.0.1" 165 | resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" 166 | optionalDependencies: 167 | graceful-fs "^4.1.6" 168 | 169 | kind-of@^3.0.2: 170 | version "3.2.2" 171 | resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 172 | dependencies: 173 | is-buffer "^1.1.5" 174 | 175 | lazy-cache@^1.0.3: 176 | version "1.0.4" 177 | resolved "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" 178 | 179 | lodash@^4.13.1: 180 | version "4.17.4" 181 | resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 182 | 183 | longest@^1.0.1: 184 | version "1.0.1" 185 | resolved "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" 186 | 187 | marked@^0.3.5: 188 | version "0.3.6" 189 | resolved "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" 190 | 191 | minimatch@^3.0.0, minimatch@^3.0.4: 192 | version "3.0.4" 193 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 194 | dependencies: 195 | brace-expansion "^1.1.7" 196 | 197 | minimist@~0.0.1: 198 | version "0.0.10" 199 | resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" 200 | 201 | once@^1.3.0: 202 | version "1.4.0" 203 | resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 204 | dependencies: 205 | wrappy "1" 206 | 207 | optimist@^0.6.1: 208 | version "0.6.1" 209 | resolved "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" 210 | dependencies: 211 | minimist "~0.0.1" 212 | wordwrap "~0.0.2" 213 | 214 | path-is-absolute@^1.0.0: 215 | version "1.0.1" 216 | resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 217 | 218 | path-parse@^1.0.5: 219 | version "1.0.5" 220 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" 221 | 222 | progress@^2.0.0: 223 | version "2.0.0" 224 | resolved "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" 225 | 226 | rechoir@^0.6.2: 227 | version "0.6.2" 228 | resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" 229 | dependencies: 230 | resolve "^1.1.6" 231 | 232 | repeat-string@^1.5.2: 233 | version "1.6.1" 234 | resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 235 | 236 | resolve@^1.1.6: 237 | version "1.4.0" 238 | resolved "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" 239 | dependencies: 240 | path-parse "^1.0.5" 241 | 242 | right-align@^0.1.1: 243 | version "0.1.3" 244 | resolved "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" 245 | dependencies: 246 | align-text "^0.1.1" 247 | 248 | shelljs@^0.7.0: 249 | version "0.7.8" 250 | resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" 251 | dependencies: 252 | glob "^7.0.0" 253 | interpret "^1.0.0" 254 | rechoir "^0.6.2" 255 | 256 | source-map@^0.4.4: 257 | version "0.4.4" 258 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" 259 | dependencies: 260 | amdefine ">=0.0.4" 261 | 262 | source-map@~0.5.1: 263 | version "0.5.6" 264 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" 265 | 266 | typedoc-default-themes@^0.5.0: 267 | version "0.5.0" 268 | resolved "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz#6dc2433e78ed8bea8e887a3acde2f31785bd6227" 269 | 270 | typedoc@^0.8.0: 271 | version "0.8.0" 272 | resolved "https://registry.npmjs.org/typedoc/-/typedoc-0.8.0.tgz#d7172bc6a29964f451b7609c005beadadefe2361" 273 | dependencies: 274 | "@types/fs-extra" "^4.0.0" 275 | "@types/handlebars" "^4.0.31" 276 | "@types/highlight.js" "^9.1.8" 277 | "@types/lodash" "^4.14.37" 278 | "@types/marked" "0.0.28" 279 | "@types/minimatch" "^2.0.29" 280 | "@types/shelljs" "^0.7.0" 281 | fs-extra "^4.0.0" 282 | handlebars "^4.0.6" 283 | highlight.js "^9.0.0" 284 | lodash "^4.13.1" 285 | marked "^0.3.5" 286 | minimatch "^3.0.0" 287 | progress "^2.0.0" 288 | shelljs "^0.7.0" 289 | typedoc-default-themes "^0.5.0" 290 | typescript "2.4.1" 291 | 292 | typescript@2.4.1: 293 | version "2.4.1" 294 | resolved "https://registry.npmjs.org/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc" 295 | 296 | typescript@^2.4.2: 297 | version "2.4.2" 298 | resolved "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz#f8395f85d459276067c988aa41837a8f82870844" 299 | 300 | uglify-js@^2.6: 301 | version "2.8.29" 302 | resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" 303 | dependencies: 304 | source-map "~0.5.1" 305 | yargs "~3.10.0" 306 | optionalDependencies: 307 | uglify-to-browserify "~1.0.0" 308 | 309 | uglify-to-browserify@~1.0.0: 310 | version "1.0.2" 311 | resolved "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" 312 | 313 | universalify@^0.1.0: 314 | version "0.1.1" 315 | resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" 316 | 317 | window-size@0.1.0: 318 | version "0.1.0" 319 | resolved "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" 320 | 321 | wordwrap@0.0.2: 322 | version "0.0.2" 323 | resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" 324 | 325 | wordwrap@~0.0.2: 326 | version "0.0.3" 327 | resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" 328 | 329 | wrappy@1: 330 | version "1.0.2" 331 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 332 | 333 | yargs@~3.10.0: 334 | version "3.10.0" 335 | resolved "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" 336 | dependencies: 337 | camelcase "^1.0.2" 338 | cliui "^2.1.0" 339 | decamelize "^1.0.0" 340 | window-size "0.1.0" 341 | --------------------------------------------------------------------------------