178 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| $(document).ready(function() {
 | |
|   const common = window.common;
 | |
|   const { Observable } = window.Rx;
 | |
|   const {
 | |
|     addLoopProtect,
 | |
|     challengeName,
 | |
|     challengeType,
 | |
|     challengeTypes
 | |
|   } = common;
 | |
| 
 | |
|   common.init.forEach(function(init) {
 | |
|     init($);
 | |
|   });
 | |
| 
 | |
|   // only run if editor present
 | |
|   if (common.editor.getValue) {
 | |
|     const code$ = common.editorKeyUp$
 | |
|       .debounce(750)
 | |
|       .map(() => common.editor.getValue())
 | |
|       .distinctUntilChanged()
 | |
|       .shareReplay();
 | |
| 
 | |
|     // update storage
 | |
|     code$.subscribe(
 | |
|         code => {
 | |
|           common.codeStorage.updateStorage(common.challengeName, code);
 | |
|           common.codeUri.querify(code);
 | |
|         },
 | |
|         err => console.error(err)
 | |
|       );
 | |
| 
 | |
|     code$
 | |
|       // only run for HTML
 | |
|       .filter(() => common.challengeType === challengeTypes.HTML)
 | |
|       .flatMap(code => {
 | |
|         return common.detectUnsafeCode$(code)
 | |
|           .map(() => {
 | |
|             const combinedCode = common.head + code + common.tail;
 | |
| 
 | |
|             return addLoopProtect(combinedCode);
 | |
|           })
 | |
|           .flatMap(code => common.updatePreview$(code))
 | |
|           .flatMap(() => common.checkPreview$({ code }))
 | |
|           .catch(err => Observable.just({ err }));
 | |
|       })
 | |
|       .subscribe(
 | |
|         ({ err }) => {
 | |
|           if (err) {
 | |
|             console.error(err);
 | |
|             return common.updatePreview$(`
 | |
|               <h1>${err}</h1>
 | |
|             `).subscribe(() => {});
 | |
|           }
 | |
|           return null;
 | |
|         },
 | |
|         err => console.error(err)
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   common.resetBtn$
 | |
|     .doOnNext(() => {
 | |
|       common.editor.setValue(common.replaceSafeTags(common.seed));
 | |
|     })
 | |
|     .flatMap(() => {
 | |
|       return common.executeChallenge$()
 | |
|         .catch(err => Observable.just({ err }));
 | |
|     })
 | |
|     .subscribe(
 | |
|       ({ err, output, originalCode, tests }) => {
 | |
|         if (err) {
 | |
|           console.error(err);
 | |
|           return common.updateOutputDisplay('' + err);
 | |
|         }
 | |
|         common.codeStorage.updateStorage(challengeName, originalCode);
 | |
|         common.codeUri.querify(originalCode);
 | |
|         common.displayTestResults(tests, true);
 | |
|         common.updateOutputDisplay(output);
 | |
|         return null;
 | |
|       },
 | |
|       (err) => {
 | |
|         if (err) {
 | |
|           console.error(err);
 | |
|         }
 | |
|         common.updateOutputDisplay('' + err);
 | |
|       }
 | |
|     );
 | |
| 
 | |
|   Observable.merge(
 | |
|     common.editorExecute$,
 | |
|     common.submitBtn$
 | |
|   )
 | |
|     .flatMap(() => {
 | |
|       common.appendToOutputDisplay('\n// testing challenge...');
 | |
|       return common.executeChallenge$()
 | |
|         .map(({ tests, ...rest }) => {
 | |
|           const solved = tests.every(test => !test.err);
 | |
|           return { ...rest, tests, solved };
 | |
|         })
 | |
|         .catch(err => Observable.just({ err }));
 | |
|     })
 | |
|     .subscribe(
 | |
|       ({ err, solved, output, tests }) => {
 | |
|         if (err) {
 | |
|           console.error(err);
 | |
|           if (common.challengeType === common.challengeTypes.HTML) {
 | |
|             return common.updatePreview$(`
 | |
|               <h1>${err}</h1>
 | |
|             `).first().subscribe(() => {});
 | |
|           }
 | |
|           return common.updateOutputDisplay('' + err);
 | |
|         }
 | |
|         common.updateOutputDisplay(output);
 | |
|         common.displayTestResults(tests, true);
 | |
|         if (solved) {
 | |
|           common.showCompletion();
 | |
|         }
 | |
|         return null;
 | |
|       },
 | |
|       ({ err }) => {
 | |
|         console.error(err);
 | |
|         common.updateOutputDisplay('' + err);
 | |
|       }
 | |
|     );
 | |
| 
 | |
|   // initial challenge run to populate tests
 | |
|   if (challengeType === challengeTypes.HTML) {
 | |
|     var $preview = $('#preview');
 | |
|     return Observable.fromCallback($preview.ready, $preview)()
 | |
|       .delay(500)
 | |
|       .flatMap(() => common.executeChallenge$())
 | |
|       .catch(err => Observable.just({ err }))
 | |
|       .subscribe(
 | |
|         ({ err, tests }) => {
 | |
|           if (err) {
 | |
|             console.error(err);
 | |
|             if (common.challengeType === common.challengeTypes.HTML) {
 | |
|               return common.updatePreview$(`
 | |
|                 <h1>${err}</h1>
 | |
|               `).subscribe(() => {});
 | |
|             }
 | |
|             return common.updateOutputDisplay('' + err);
 | |
|           }
 | |
|           common.displayTestResults(tests, false);
 | |
|           return null;
 | |
|         },
 | |
|         ({ err }) => {
 | |
|           console.error(err);
 | |
|         }
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if (
 | |
|     challengeType === challengeTypes.BONFIRE ||
 | |
|     challengeType === challengeTypes.JS
 | |
|   ) {
 | |
|     return Observable.just({})
 | |
|       .delay(500)
 | |
|       .flatMap(() => common.executeChallenge$())
 | |
|       .catch(err => Observable.just({ err }))
 | |
|       .subscribe(
 | |
|         ({ err, originalCode, tests }) => {
 | |
|           if (err) {
 | |
|             console.error(err);
 | |
|             return common.updateOutputDisplay('' + err);
 | |
|           }
 | |
|           common.codeStorage.updateStorage(challengeName, originalCode);
 | |
|           common.displayTestResults(tests, false);
 | |
|           return null;
 | |
|         },
 | |
|         (err) => {
 | |
|           console.error(err);
 | |
|           common.updateOutputDisplay('' + err);
 | |
|         }
 | |
|       );
 | |
|   }
 | |
|   return null;
 | |
| });
 |