diff --git a/package.json b/package.json index 8213e9ac72..4863f4d47a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "express-session": "~1.9.2", "express-validator": "~2.8.0", "font-awesome": "~4.3.0", - "forcedomain": "~0.4.0", "forever": "~0.14.1", "frameguard": "^0.2.2", "github-api": "~0.7.0", diff --git a/pm2Start.js b/pm2Start.js new file mode 100644 index 0000000000..052f3bdbfa --- /dev/null +++ b/pm2Start.js @@ -0,0 +1,12 @@ +var pm2 = require('pm2'); +pm2.connect(function() { + pm2.start({ + name: 'server', + script: 'server/server.js', + exec_mode: 'cluster', + instances: '2', + max_memory_restart: '900M' + }, function(err, apps) { + pm2.disconnect(); + }); +}); diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js index f11f202086..53204220f6 100644 --- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js +++ b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js @@ -18,7 +18,7 @@ editor.setSize("100%", "auto"); // Hijack tab key to enter two spaces intead editor.setOption("extraKeys", { Tab: function(cm) { - if (cm.somethingSelected()){ + if (cm.somethingSelected()) { cm.indentSelection("add"); } else { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); @@ -26,7 +26,7 @@ editor.setOption("extraKeys", { } }, "Shift-Tab": function(cm) { - if (cm.somethingSelected()){ + if (cm.somethingSelected()) { cm.indentSelection("subtract"); } else { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); @@ -121,7 +121,10 @@ codeOutput.setValue('/**\n' + ' */'); codeOutput.setSize("100%", "100%"); var info = editor.getScrollInfo(); -var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top; +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); @@ -143,8 +146,8 @@ editorValue = (localBonfire.isAlive())? localBonfire.getEditorValue() : allSeeds myCodeMirror.setValue(editorValue); -function doLinting () { - editor.operation(function () { +function doLinting() { + editor.operation(function() { for (var i = 0; i < widgets.length; ++i) editor.removeLineWidget(widgets[i]); widgets.length = 0; @@ -166,14 +169,14 @@ function doLinting () { }); }; -$('#submitButton').on('click', function () { +$('#submitButton').on('click', function() { bonfireExecute(); }); function bonfireExecute() { attempts++; - ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); - userTests= null; + ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); + userTests = null; $('#codeOutput').empty(); var userJavaScript = myCodeMirror.getValue(); userJavaScript = removeComments(userJavaScript); @@ -205,16 +208,23 @@ var scrapeTests = function(userJavaScript) { } var counter = 0; - var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/); + var regex = new RegExp( + /(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/ + ); var match = regex.exec(userJavaScript); while (match != null) { var replacement = '//' + counter + testSalt; - userJavaScript = userJavaScript.substring(0, match.index) + replacement + userJavaScript.substring(match.index + match[0].length); + userJavaScript = userJavaScript.substring(0, match.index) + replacement + + userJavaScript.substring(match.index + match[0].length); if (!userTests) { - userTests= []; + userTests = []; } - userTests.push({"text": match[0], "line": counter, "err": null}); + userTests.push({ + "text": match[0], + "line": counter, + "err": null + }); counter++; match = regex.exec(userJavaScript); } @@ -236,17 +246,22 @@ var createTestDisplay = function() { if (pushed) { userTests.pop(); } - for (var i = 0; i < userTests.length;i++) { + for (var i = 0; i < userTests.length; i++) { var test = userTests[i]; var testDoc = document.createElement("div"); if (test.err != null) { console.log('Should be displaying bad tests'); $(testDoc) - .html("
" + test.text + "
" + test.err + "
") + .html( + "
" + + test.text + "
" + + test.err + "
") .appendTo($('#testSuite')); } else { $(testDoc) - .html("
" + test.text + "
") + .html( + "
" + + test.text + "
") .appendTo($('#testSuite')); } }; @@ -268,18 +283,21 @@ var runTests = function(err, data) { pushed = false; $('#testSuite').children().remove(); if (err && userTests.length > 0) { - userTests= [{text:"Program Execution Failure", err: "No user tests were run."}]; + userTests = [{ + text: "Program Execution Failure", + err: "No user tests were run." + }]; createTestDisplay(); } else if (userTests) { userTests.push(false); pushed = true; - userTests.forEach(function(chaiTestFromJSON, indexOfTestArray, __testArray){ + userTests.forEach(function(chaiTestFromJSON, indexOfTestArray, + __testArray) { try { if (chaiTestFromJSON) { var output = eval(reassembleTest(chaiTestFromJSON, data)); - debugger; } - } catch(error) { + } catch (error) { allTestsPassed = false; __testArray[indexOfTestArray].err = error.message; } finally { @@ -299,12 +317,12 @@ var runTests = function(err, data) { function showCompletion() { var time = Math.floor(Date.now()) - started; - ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time +', Attempts: ' + attempts); + ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time + + ', Attempts: ' + attempts); var bonfireSolution = myCodeMirror.getValue(); var didCompleteWith = $('#completed-with').val() || null; $.post( - '/completed-bonfire/', - { + '/completed-bonfire/', { challengeInfo: { challengeId: challenge_Id, challengeName: challenge_Name, @@ -312,10 +330,11 @@ function showCompletion() { challengeType: challengeType, solution: bonfireSolution } - }, function(res) { + }, + function(res) { if (res) { $('#complete-courseware-dialog').modal('show'); - $('#complete-courseware-dialog').keydown(function (e) { + $('#complete-courseware-dialog').keydown(function(e) { if (e.ctrlKey && e.keyCode == 13) { $('#next-courseware-button').click(); } diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 08c797f58c..49600d63ba 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -180,7 +180,8 @@ "assert.deepEqual(palindrome(\"not a palindrome\"), false);", "assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);", "assert.deepEqual(palindrome(\"never odd or even\"), true);", - "assert.deepEqual(palindrome(\"nope\"), false);" + "assert.deepEqual(palindrome(\"nope\"), false);", + "assert.deepEqual(palindrome(\"almostomla\"), false);" ], "challengeSeed": [ "function palindrome(str) {", @@ -754,8 +755,8 @@ }, { "id": "a5de63ebea8dbee56860f4f2", - "name": "bonfire-diff-two-arrays", - "dashedName": "Bonfire: Diff Two Arrays", + "name": "Bonfire: Diff Two Arrays", + "dashedName": "bonfire-diff-two-arrays", "difficulty": "2.01", "description": [ "Compare two arrays and return a new array with any items not found in both of the original arrays.", @@ -1105,6 +1106,10 @@ ], "tests": [ "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", + "assert.strictEqual(convert('Hamburgers < Pizza < Tacos'), 'Hamburgers < Pizza < Tacos', 'should escape characters');", + "assert.strictEqual(convert('Sixty > twelve'), 'Sixty > twelve', 'should escape characters');", + "assert.strictEqual(convert('Stuff in \"quotation marks\"'), 'Stuff in "quotation marks"', 'should escape characters');", + "assert.strictEqual(convert(\"Shindler's List\"), 'Shindler's List', 'should escape characters');", "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" ], "MDNlinks": [ diff --git a/seed/challenges/basic-html5-and-css.json b/seed/challenges/basic-html5-and-css.json index 4a8df44a71..ccd2fdaa5f 100644 --- a/seed/challenges/basic-html5-and-css.json +++ b/seed/challenges/basic-html5-and-css.json @@ -1005,7 +1005,7 @@ ], "tests": [ "assert((/cat photos/gi).test($('a').text()), 'Your a element should have the anchor text of \"cat photos\"')", - "assert($('a').filter(function(index) { return /com/gi.test($('a').attr('href')); }).length > 0, 'You need an a element that links to http://catphotoapp.com.')", + "assert(/http:\\/\\/catphotoapp\\.com/gi.test($('a').attr('href')), 'You need an a element that links to http://catphotoapp.com.')", "assert(editor.match(/<\\/a>/g) && editor.match(/<\\/a>/g).length === editor.match(/a element has a closing tag.')" ], "challengeSeed": [ diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index eeac669f73..9f2b704153 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -626,7 +626,7 @@ "The \"row\" class is applied to a div, and the buttons themselves can be wrapped within it." ], "tests": [ - "assert($('div.row:has(button)'), 'Your buttons should all be wrapped within the same div element with the class \"row\".')", + "assert($('div.row:has(button)').length > 0, 'Your buttons should all be wrapped within the same div element with the class \"row\".')", "assert($('div.col-xs-4:has(button)').length > 2, 'Each of your Bootstrap buttons should be wrapped within its own a div element with the class \"col-xs-4\".')", "assert(editor.match(/<\\/button>/g) && editor.match(/