diff --git a/client/commonFramework/add-loop-protect.js b/client/commonFramework/add-loop-protect.js deleted file mode 100644 index 56ad7389b2..0000000000 --- a/client/commonFramework/add-loop-protect.js +++ /dev/null @@ -1,21 +0,0 @@ -window.common = (function(global) { - const { - loopProtect, - common = { init: [] } - } = global; - - loopProtect.hit = function hit(line) { - var err = 'Error: Exiting potential infinite loop at line ' + - line + - '. To disable loop protection, write: \n\\/\\/ noprotect\nas the first' + - 'line. Beware that if you do have an infinite loop in your code' + - 'this will crash your browser.'; - console.error(err); - }; - - common.addLoopProtect = function addLoopProtect(code = '') { - return loopProtect(code); - }; - - return common; -})(window); diff --git a/client/commonFramework/bindings.js b/client/commonFramework/bindings.js deleted file mode 100644 index e2165848bc..0000000000 --- a/client/commonFramework/bindings.js +++ /dev/null @@ -1,217 +0,0 @@ -window.common = (function(global) { - const { - $, - Rx: { Observable }, - common = { init: [] }, - Mousetrap - } = global; - - common.ctrlEnterClickHandler = function ctrlEnterClickHandler(e) { - // ctrl + enter or cmd + enter - if ( - e.keyCode === 13 && - (e.metaKey || e.ctrlKey) - ) { - $('#complete-courseware-dialog').off('keydown', ctrlEnterClickHandler); - if ($('#submit-challenge').length > 0) { - $('#submit-challenge').click(); - } else { - window.location = '/challenges/next-challenge?id=' + common.challengeId; - } - } - }; - - common.init.push(function($) { - - var $marginFix = $('.innerMarginFix'); - $marginFix.css('min-height', $marginFix.height()); - - common.submitBtn$ = Observable.fromEvent($('#submitButton'), 'click'); - - common.resetBtn$ = Observable.fromEvent($('#reset-button'), 'click'); - - // init modal keybindings on open - $('#complete-courseware-dialog').on('shown.bs.modal', function() { - $('#complete-courseware-dialog').keydown(common.ctrlEnterClickHandler); - }); - - // remove modal keybinds on close - $('#complete-courseware-dialog').on('hidden.bs.modal', function() { - $('#complete-courseware-dialog').off( - 'keydown', - common.ctrlEnterClickHandler - ); - }); - - // set focus keybind - Mousetrap.bind(['command+shift+e', 'ctrl+shift+e'], () => { - common.editor.focus(); - }); - - // video checklist binding - $('.challenge-list-checkbox').on('change', function() { - var checkboxId = $(this).parent().parent().attr('id'); - if ($(this).is(':checked')) { - $(this).parent().siblings().children().addClass('faded'); - if (!localStorage || !localStorage[checkboxId]) { - localStorage[checkboxId] = true; - } - } - - if (!$(this).is(':checked')) { - $(this).parent().siblings().children().removeClass('faded'); - if (localStorage[checkboxId]) { - localStorage.removeItem(checkboxId); - } - } - }); - - $('.checklist-element').each(function() { - var checklistElementId = $(this).attr('id'); - if (localStorage[checklistElementId]) { - $(this).children().children('li').addClass('faded'); - $(this).children().children('input').trigger('click'); - } - }); - - - // video challenge submit - $('#next-courseware-button').on('click', function() { - $('#next-courseware-button').unbind('click'); - if ($('.signup-btn-nav').length < 1) { - var data; - var solution = $('#public-url').val() || null; - var githubLink = $('#github-url').val() || null; - switch (common.challengeType) { - case common.challengeTypes.VIDEO: - data = { - id: common.challengeId, - name: common.challengeName, - challengeType: +common.challengeType - }; - $.ajax({ - url: '/completed-challenge/', - type: 'POST', - data: JSON.stringify(data), - contentType: 'application/json', - dataType: 'json' - }) - .success(function(res) { - if (!res) { - return; - } - window.location.href = '/challenges/next-challenge?id=' + - common.challengeId; - }) - .fail(function() { - window.location.replace(window.location.href); - }); - - break; - case common.challengeTypes.BASEJUMP: - case common.challengeTypes.ZIPLINE: - data = { - id: common.challengeId, - name: common.challengeName, - challengeType: +common.challengeType, - solution, - githubLink - }; - - $.ajax({ - url: '/completed-zipline-or-basejump/', - type: 'POST', - data: JSON.stringify(data), - contentType: 'application/json', - dataType: 'json' - }) - .success(function() { - window.location.href = '/challenges/next-challenge?id=' + - common.challengeId; - }) - .fail(function() { - window.location.replace(window.location.href); - }); - break; - - case common.challengeTypes.BONFIRE: - window.location.href = '/challenges/next-challenge?id=' + - common.challengeId; - break; - - default: - console.log('Happy Coding!'); - break; - } - } - }); - - if (common.challengeName) { - window.ga('send', 'event', 'Challenge', 'loaded', common.gaName); - } - - $('.modal').on('show.bs.modal', function() { - $('.gitter-chat-embed, .map-aside') - .addClass('is-collapsed'); - }); - - $('#complete-courseware-dialog').on('hidden.bs.modal', function() { - if (common.editor.focus) { - common.editor.focus(); - } - }); - - $('#trigger-issue-modal').on('click', function() { - $('#issue-modal').modal('show'); - }); - - $('#trigger-help-modal').on('click', function() { - $('#help-modal').modal('show'); - }); - - $('#trigger-reset-modal').on('click', function() { - $('#reset-modal').modal('show'); - }); - - $('#trigger-pair-modal').on('click', function() { - $('#pair-modal').modal('show'); - }); - - $('#completed-courseware').on('click', function() { - $('#complete-courseware-dialog').modal('show'); - }); - - $('#show-solution').on('click', function() { - $('#complete-courseware-dialog').modal('hide'); - }); - - $('#challenge-help-btn').on('click', function() { - $('.map-aside, #chat-embed-main').addClass('is-collapsed'); - }); - - $('#help-ive-found-a-bug-wiki-article').on('click', function() { - window.open( - 'http://forum.freecodecamp.com/t/how-to-report-a-bug/19543', - '_blank' - ); - }); - - $('#search-issue').on('click', function() { - var queryIssue = window.location.href - .toString() - .split('?')[0] - .replace(/(#*)$/, ''); - window.open( - 'https://github.com/FreeCodeCamp/FreeCodeCamp/issues?q=' + - 'is:issue is:all ' + - (common.challengeName) + - ' OR ' + - queryIssue - .substr(queryIssue.lastIndexOf('challenges/') + 11) - .replace('/', ''), '_blank'); - }); - - }); - - return common; -}(window)); diff --git a/client/commonFramework/code-storage.js b/client/commonFramework/code-storage.js deleted file mode 100644 index 4eca143dad..0000000000 --- a/client/commonFramework/code-storage.js +++ /dev/null @@ -1,69 +0,0 @@ -// depends on: codeUri -window.common = (function(global) { - const { - localStorage, - common = { init: [] } - } = global; - - const { - replaceNoprotect - } = common; - - var challengePrefix = [ - 'Bonfire: ', - 'Waypoint: ', - 'Zipline: ', - 'Basejump: ', - 'Checkpoint: '], - item; - - var codeStorage = { - getStoredValue(key) { - if ( - !localStorage || - typeof localStorage.getItem !== 'function' || - !key || - typeof key !== 'string' - ) { - console.log('unable to read from storage'); - return ''; - } - if (localStorage.getItem(key + 'Val')) { - return '' + localStorage.getItem(key + 'Val'); - } else { - for (var i = 0; i <= challengePrefix.length; i++) { - item = localStorage.getItem(challengePrefix[i] + key + 'Val'); - if (item) { - return '' + item; - } - } - } - return null; - }, - - isAlive: function(key) { - var val = this.getStoredValue(key); - return val !== 'null' && - val !== 'undefined' && - (val && val.length > 0); - }, - - updateStorage(key, code) { - if ( - !localStorage || - typeof localStorage.setItem !== 'function' || - !key || - typeof key !== 'string' - ) { - console.log('unable to save to storage'); - return code; - } - localStorage.setItem(key + 'Val', replaceNoprotect(code)); - return code; - } - }; - - common.codeStorage = codeStorage; - - return common; -}(window, window.common)); diff --git a/client/commonFramework/code-uri.js b/client/commonFramework/code-uri.js deleted file mode 100644 index c2642aa264..0000000000 --- a/client/commonFramework/code-uri.js +++ /dev/null @@ -1,148 +0,0 @@ -// store code in the URL -window.common = (function(global) { - const { - encodeURIComponent: encode, - decodeURIComponent: decode, - location, - history, - common = { init: [] } - } = global; - - const { - replaceScriptTags, - replaceSafeTags, - replaceFormActionAttr, - replaceFccfaaAttr, - replaceNoprotect - } = common; - - const queryRegex = /^(\?|#\?)/; - function encodeFcc(val) { - return replaceScriptTags(replaceFormActionAttr(replaceNoprotect(val))); - } - - function decodeFcc(val) { - return replaceSafeTags(replaceFccfaaAttr(val)); - } - - var codeUri = { - encode: function(code) { - return encode(code); - }, - decode: function(code) { - try { - return decode(code); - } catch (ignore) { - return null; - } - }, - isInQuery: function(query) { - var decoded = codeUri.decode(query); - if (!decoded || typeof decoded.split !== 'function') { - return false; - } - return decoded - .replace(queryRegex, '') - .split('&') - .reduce(function(found, param) { - var key = param.split('=')[0]; - if (key === 'solution') { - return true; - } - return found; - }, false); - }, - isAlive: function() { - return codeUri.enabled && - codeUri.isInQuery(location.search) || - codeUri.isInQuery(location.hash); - }, - getKeyInQuery(query, keyToFind = '') { - return query - .split('&') - .reduce(function(oldValue, param) { - var key = param.split('=')[0]; - var value = param - .split('=') - .slice(1) - .join('='); - - if (key === keyToFind) { - return value; - } - return oldValue; - }, null); - }, - getSolutionFromQuery(query = '') { - return decodeFcc( - codeUri.decode(codeUri.getKeyInQuery(query, 'solution')) - ); - }, - parse: function() { - if (!codeUri.enabled) { - return null; - } - var query; - if (location.search && codeUri.isInQuery(location.search)) { - query = location.search.replace(/^\?/, ''); - - if (history && typeof history.replaceState === 'function') { - history.replaceState( - history.state, - null, - location.href.split('?')[0] - ); - location.hash = '#?' + encodeFcc(query); - } - } else { - query = location.hash.replace(/^\#\?/, ''); - } - - if (!query) { - return null; - } - - return this.getSolutionFromQuery(query); - }, - querify: function(solution) { - if (!codeUri.enabled) { - return null; - } - if (history && typeof history.replaceState === 'function') { - // grab the url up to the query - // destroy any hash symbols still clinging to life - const url = (location.href.split('?')[0]).replace(/(#*)$/, ''); - history.replaceState( - history.state, - null, - url + - '#?' + - (codeUri.shouldRun() ? '' : 'run=disabled&') + - 'solution=' + - codeUri.encode(encodeFcc(solution)) - ); - } else { - location.hash = '?solution=' + - codeUri.encode(encodeFcc(solution)); - } - - return solution; - }, - enabled: true, - shouldRun() { - return !this.getKeyInQuery( - (location.search || location.hash).replace(queryRegex, ''), - 'run' - ); - } - }; - - common.init.push(function() { - codeUri.parse(); - }); - - common.codeUri = codeUri; - common.shouldRun = () => codeUri.shouldRun(); - - return common; -}(window)); diff --git a/client/commonFramework/create-editor.js b/client/commonFramework/create-editor.js deleted file mode 100644 index 09efed144b..0000000000 --- a/client/commonFramework/create-editor.js +++ /dev/null @@ -1,119 +0,0 @@ -window.common = (function(global) { - const { - Rx: { Subject, Observable }, - CodeMirror, - emmetCodeMirror, - common = { init: [] } - } = global; - - const { challengeType = '0', challengeTypes } = common; - - if ( - !CodeMirror || - challengeType === challengeTypes.BASEJUMP || - challengeType === challengeTypes.ZIPLINE || - challengeType === challengeTypes.VIDEO || - challengeType === challengeTypes.STEP || - challengeType === challengeTypes.HIKES - ) { - common.editor = {}; - return common; - } - - var editor = CodeMirror.fromTextArea( - document.getElementById('codeEditor'), - { - lint: true, - lineNumbers: true, - mode: 'javascript', - theme: 'monokai', - runnable: true, - matchBrackets: true, - autoCloseBrackets: true, - scrollbarStyle: 'null', - lineWrapping: true, - gutters: ['CodeMirror-lint-markers'] - } - ); - - editor.setSize('100%', 'auto'); - - common.editorExecute$ = new Subject(); - common.editorKeyUp$ = Observable.fromEventPattern( - (handler) => editor.on('keyup', handler), - (handler) => editor.off('keyup', handler) - ); - - editor.setOption('extraKeys', { - Tab: function(cm) { - if (cm.somethingSelected()) { - cm.indentSelection('add'); - } else { - var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); - cm.replaceSelection(spaces); - } - }, - 'Shift-Tab': function(cm) { - if (cm.somethingSelected()) { - cm.indentSelection('subtract'); - } else { - var spaces = Array(cm.getOption('indentUnit') + 1).join(' '); - cm.replaceSelection(spaces); - } - }, - 'Ctrl-Enter': function() { - common.editorExecute$.onNext(); - return false; - }, - 'Cmd-Enter': function() { - common.editorExecute$.onNext(); - return false; - }, - 'Ctrl-/': function(cm) { - cm.toggleComment(); - }, - 'Cmd-/': function(cm) { - cm.toggleComment(); - } - }); - - - var info = editor.getScrollInfo(); - - var after = editor.charCoords({ - line: editor.getCursor().line + 1, - ch: 0 - }, 'local').top; - - if (info.top + info.clientHeight < after) { - editor.scrollTo(null, after - info.clientHeight + 3); - } - - if (emmetCodeMirror) { - emmetCodeMirror( - editor, - { - 'Cmd-E': 'emmet.expand_abbreviation', - Tab: 'emmet.expand_abbreviation_with_tab', - Enter: 'emmet.insert_formatted_line_break_only' - } - ); - } - common.init.push(function() { - let editorValue; - if (common.codeUri.isAlive()) { - editorValue = common.codeUri.parse(); - } else { - editorValue = common.codeStorage.isAlive(common.challengeName) ? - common.codeStorage.getStoredValue(common.challengeName) : - common.seed; - } - - editor.setValue(common.replaceSafeTags(editorValue)); - editor.refresh(); - }); - - common.editor = editor; - - return common; -}(window)); diff --git a/client/commonFramework/detect-unsafe-code-stream.js b/client/commonFramework/detect-unsafe-code-stream.js deleted file mode 100644 index 8cf7116622..0000000000 --- a/client/commonFramework/detect-unsafe-code-stream.js +++ /dev/null @@ -1,59 +0,0 @@ -window.common = (function(global) { - const { - Rx: { Observable }, - common = { init: [] } - } = global; - - const detectFunctionCall = /function\s*?\(|function\s+\w+\s*?\(/gi; - const detectUnsafeJQ = /\$\s*?\(\s*?\$\s*?\)/gi; - const detectUnsafeConsoleCall = /if\s\(null\)\sconsole\.log\(1\);/gi; - const detectInComments = new RegExp(['\\/\\/.*?function.*?|', - '\\/\\*[\\s\\w\\W]*?function', - '[\\s\\w\\W]*?\\*\\/'].join(''), 'gi'); - - common.detectUnsafeCode$ = function detectUnsafeCode$(code) { - const openingComments = code.match(/\/\*/gi); - const closingComments = code.match(/\*\//gi); - - // checks if the number of opening comments(/*) matches the number of - // closing comments(*/) - if ( - openingComments && - ( - !closingComments || - openingComments.length > closingComments.length - ) - ) { - - return Observable.throw( - new Error('SyntaxError: Unfinished multi-line comment') - ); - } - - if (code.match(detectUnsafeJQ)) { - return Observable.throw( - new Error('Unsafe $($)') - ); - } - - if ( - code.match(/function/g) && - !code.match(detectFunctionCall) && - !code.match(detectInComments) - ) { - return Observable.throw( - new Error('SyntaxError: Unsafe or unfinished function declaration') - ); - } - - if (code.match(detectUnsafeConsoleCall)) { - return Observable.throw( - new Error('Invalid if (null) console.log(1); detected') - ); - } - - return Observable.just(code); - }; - - return common; -}(window)); diff --git a/client/commonFramework/display-test-results.js b/client/commonFramework/display-test-results.js deleted file mode 100644 index df09d26734..0000000000 --- a/client/commonFramework/display-test-results.js +++ /dev/null @@ -1,32 +0,0 @@ -window.common = (function({ $, common = { init: [] }}) { - - common.displayTestResults = function displayTestResults(data = [], down) { - $('#testSuite').children().remove(); - data.forEach(({ err = false, text = '' }) => { - var iconClass = err ? - '"ion-close-circled big-error-icon"' : - '"ion-checkmark-circled big-success-icon"'; - - $('
').html(` -