* Feat: Initial backend view * Feat: Refactor frame runner * Feat: backend challenge submit runs tests * Feat: Backend challenge request * Feat: Whitelist hyperdev in csp * Fix: Use app tests instead of challenge tests * Feat: Allow hyperdev subdomains * Fix(csp): allow hypderdev.space subdomains * feat(challenge): submit backend * feat: Add timeout to test runner (5 sec) * chore(seed): Add more to test backend * fix(csp): s/hyperdev/gomix/g * fix(app): fix code mirror skeleton filepath * fix(app): remove Gitter saga import * fix(app): codemirrorskeleton does not need it's own folder fix(app): cmk needs to work with Null types * fix: No longer restart the browser when challenges change * fix(app): Update jquery for challenges * fix(seed): Remove to promise jquery call * fix(lint): Undo merge error undefined is no allowed * fix(app): linting errors due to bad merge * fix(seed): Remove old seed file
		
			
				
	
	
		
			91 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import omit from 'lodash/omit';
 | |
| import normalizeUrl from 'normalize-url';
 | |
| import { isURL } from 'validator';
 | |
| 
 | |
| const normalizeOptions = {
 | |
|   stripWWW: false
 | |
| };
 | |
| 
 | |
| // callIfDefined(fn: (Any) => Any) => (value: Any) => Any
 | |
| export function callIfDefined(fn) {
 | |
|   return value => value ? fn(value) : value;
 | |
| }
 | |
| 
 | |
| // formatUrl(url: String) => String
 | |
| export function formatUrl(url) {
 | |
|   if (
 | |
|     typeof url === 'string' &&
 | |
|     url.length > 4 &&
 | |
|     url.indexOf('.') !== -1
 | |
|   ) {
 | |
|     // prevent trailing / from being stripped during typing
 | |
|     let lastChar = '';
 | |
|     if (url.substring(url.length - 1) === '/') {
 | |
|       lastChar = '/';
 | |
|     }
 | |
|     // prevent normalize-url from stripping last dot during typing
 | |
|     if (url.substring(url.length - 1) === '.') {
 | |
|       lastChar = '.';
 | |
|     }
 | |
|     return normalizeUrl(url, normalizeOptions) + lastChar;
 | |
|   }
 | |
|   return url;
 | |
| }
 | |
| 
 | |
| export function isValidURL(data) {
 | |
|   /* eslint-disable quote-props */
 | |
|   return isURL(data, { 'require_protocol': true });
 | |
|   /* eslint-enable quote-props */
 | |
| }
 | |
| 
 | |
| export function makeOptional(validator) {
 | |
|   return val => val ? validator(val) : true;
 | |
| }
 | |
| 
 | |
| export function makeRequired(validator) {
 | |
|   return (val) => val ? validator(val) : false;
 | |
| }
 | |
| 
 | |
| export function createFormValidator(fieldValidators) {
 | |
|   const fieldKeys = Object.keys(fieldValidators);
 | |
|   return values => fieldKeys
 | |
|     .map(field => {
 | |
|       if (fieldValidators[field](values[field])) {
 | |
|         return null;
 | |
|       }
 | |
|       return { [field]: !fieldValidators[field](values[field]) };
 | |
|     })
 | |
|     .filter(Boolean)
 | |
|     .reduce((errors, error) => ({ ...errors, ...error }), {});
 | |
| }
 | |
| 
 | |
| 
 | |
| export function getValidationState(field) {
 | |
|   if (field.pristine) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   return field.error ?
 | |
|     'error' :
 | |
|     'success';
 | |
| }
 | |
| 
 | |
| // this should filter out none-dom props to silence React warnings
 | |
| export function DOMOnlyProps(field) {
 | |
|   return omit(field, [
 | |
|     'initialValue',
 | |
|     'autofill',
 | |
|     'autocompleted',
 | |
|     'onUpdate',
 | |
|     'valid',
 | |
|     'invalid',
 | |
|     'dirty',
 | |
|     'pristine',
 | |
|     'active',
 | |
|     'touched',
 | |
|     'visited',
 | |
|     'autofilled',
 | |
|     'error'
 | |
|   ]);
 | |
| }
 |