From 2843bd804a9d31a41d2980ed33c87e0888828570 Mon Sep 17 00:00:00 2001 From: Pavel Tsurbeleu Date: Tue, 15 Sep 2015 00:52:15 -0700 Subject: [PATCH 001/592] add an assertion to ensure well-formed img elements in waypoint-make-images-mobile-responsive challenge, closes #1021 --- seed/challenges/bootstrap.json | 1 + 1 file changed, 1 insertion(+) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index fb4f864474..35b7a02321 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -97,6 +97,7 @@ ], "tests": [ "assert($(\"img\").length > 1, 'You should have a total of two images.')", + "assert(editor.match(//g).length === 2 && editor.match(/img element has a closing angle bracket.')", "assert($(\"img\").hasClass(\"img-responsive\"), 'Your new image should have the class img-responsive.')", "assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Add a second image with the src of http://bit.ly/fcc-running-cats.')" ], From 165cb41080443f0f061185c6fb5a87f22c16bcd1 Mon Sep 17 00:00:00 2001 From: Pavel Tsurbeleu Date: Wed, 16 Sep 2015 18:04:37 -0700 Subject: [PATCH 002/592] fix count img elements assertion in waypoint-make-images-mobile-responsive challenge to be strict --- seed/challenges/bootstrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index 35b7a02321..f953d8e58a 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -96,7 +96,7 @@ "Fortunately, with Bootstrap, all we need to do is add the img-responsive class to your image. Do this, and the image should perfectly fit the width of your page." ], "tests": [ - "assert($(\"img\").length > 1, 'You should have a total of two images.')", + "assert($(\"img\").length === 2, 'You should have a total of two images.')", "assert(editor.match(//g).length === 2 && editor.match(/img element has a closing angle bracket.')", "assert($(\"img\").hasClass(\"img-responsive\"), 'Your new image should have the class img-responsive.')", "assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Add a second image with the src of http://bit.ly/fcc-running-cats.')" From be373787831a45bfce00b92ab70e35dc4f5cd676 Mon Sep 17 00:00:00 2001 From: Pavel Tsurbeleu Date: Wed, 16 Sep 2015 18:10:16 -0700 Subject: [PATCH 003/592] fix wording of src attribute assertion's message to be consistent with other messages in waypoint-make-images-mobile-responsive challenge --- seed/challenges/bootstrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index f953d8e58a..bfc812b897 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -99,7 +99,7 @@ "assert($(\"img\").length === 2, 'You should have a total of two images.')", "assert(editor.match(//g).length === 2 && editor.match(/img element has a closing angle bracket.')", "assert($(\"img\").hasClass(\"img-responsive\"), 'Your new image should have the class img-responsive.')", - "assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Add a second image with the src of http://bit.ly/fcc-running-cats.')" + "assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Your new image should have a src attribute of http://bit.ly/fcc-running-cats.')" ], "challengeSeed": [ "", From 8424fef76f62b65b8e8a71bd49561ed9160ccb85 Mon Sep 17 00:00:00 2001 From: Arsen Melikyan Date: Sat, 19 Sep 2015 15:58:58 +0400 Subject: [PATCH 004/592] adds a switch case to highlight bonfires' code in GitHub issues --- client/main.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/main.js b/client/main.js index 36aa44fe8c..7e56054143 100644 --- a/client/main.js +++ b/client/main.js @@ -130,6 +130,7 @@ $(document).ready(function() { type = 'html'; break; case challengeTypes.JAVASCRIPT: + case challengeTypes.BONFIRE: type = 'javascript'; break; default: From 4c48547b0d160b90531a9fa1e2f6bc17723a67fc Mon Sep 17 00:00:00 2001 From: Joel Bentley Date: Sat, 19 Sep 2015 14:50:54 -0400 Subject: [PATCH 005/592] Fix test on Waypoint Create Unordered List --- seed/challenges/html5-and-css.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/html5-and-css.json b/seed/challenges/html5-and-css.json index 8f5f48cbec..fcfe7314b7 100644 --- a/seed/challenges/html5-and-css.json +++ b/seed/challenges/html5-and-css.json @@ -1434,7 +1434,7 @@ "assert($(\"ul\").length > 0, 'Create a ul element.')", "assert($(\"ul li\").length > 2, 'You should have three li elements within your ul element.')", "assert(editor.match(/<\\/ul>/g) && editor.match(/
    /g).length === editor.match(/
      ul element has a closing tag.')", - "assert(editor.match(/<\\/li>/g) && editor.match(/
    • /g) && editor.match(/<\\/li>/g).length === editor.match(/
    • /g).length, 'Make sure your li element has a closing tag.')" + "assert(editor.match(/<\\/li>/g) && editor.match(/]/g) && editor.match(/<\\/li>/g).length === editor.match(/]/g).length, 'Make sure your li elements have closing tags.')" ], "challengeSeed": [ "", From 12ef390288288670374a2219dbaf338a85165b5d Mon Sep 17 00:00:00 2001 From: Arsen Melikyan Date: Sun, 20 Sep 2015 00:42:01 +0400 Subject: [PATCH 006/592] new test checks if all elements are nested in container-fluid --- seed/challenges/bootstrap.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index fb4f864474..2e83b66f8d 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -14,8 +14,9 @@ "To get started, we should nest all of our HTML in a div element with the class container-fluid." ], "tests": [ - "assert($(\"div\").hasClass(\"container-fluid\"), 'Your div element should have the class container-fluid')", - "assert(editor.match(/<\\/div>/g) && editor.match(/
      /g).length === editor.match(/
      div elements has a closing tag.')" + "assert($(\"div\").hasClass(\"container-fluid\"), 'Your div element should have the class container-fluid.')", + "assert(editor.match(/<\\/div>/g) && editor.match(/
      /g).length === editor.match(/
      div elements has a closing tag.')", + "assert($(\".container-fluid\").children().length >= 8, 'Make sure you have nested all HTML elements in .container-fluid.')" ], "challengeSeed": [ "", From 0a455fcd9231d2a13374380be6722d71a1f53d6b Mon Sep 17 00:00:00 2001 From: Aniruddh Agarwal Date: Fri, 18 Sep 2015 15:31:25 +0800 Subject: [PATCH 007/592] Fixes basic bonfire's permissive test --- seed/challenges/basic-bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index cbcdbd1b83..a5df1ea9ec 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -313,7 +313,7 @@ "tests": [ "assert(end(\"Bastian\", \"n\") === true, '\"Bastian\", \"n\" should return true.');", "assert(end(\"Connor\", \"n\") === false, '\"Connor\", \"n\" should return false.');", - "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") === false, '\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") should return false.');", + "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") === false, '\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") should return false.');", "assert(end(\"He has to give me a new name\", \"name\") === true, '\"He has to give me a new name\", \"name\" should return true.');", "assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, '\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\" should return false.');" ], From 182960af04cd8b65ff47aafe735a3c27b1120cfc Mon Sep 17 00:00:00 2001 From: Joel Bentley Date: Sun, 20 Sep 2015 15:52:54 -0400 Subject: [PATCH 008/592] Fix tests on Waypoint Mobile Responsive Images --- seed/challenges/bootstrap.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index fb4f864474..d56663a44d 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -97,8 +97,8 @@ ], "tests": [ "assert($(\"img\").length > 1, 'You should have a total of two images.')", - "assert($(\"img\").hasClass(\"img-responsive\"), 'Your new image should have the class img-responsive.')", - "assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Add a second image with the src of http://bit.ly/fcc-running-cats.')" + "assert($(\"img:eq(1)\").attr(\"src\") === \"http://bit.ly/fcc-running-cats\", 'Your new image should have an src of http://bit.ly/fcc-running-cats.')", + "assert($(\"img:eq(1)\").hasClass(\"img-responsive\"), 'Your new image should have the class img-responsive.')" ], "challengeSeed": [ "", From e0df3171f42d67c5648f1274cb212ec6d8cad350 Mon Sep 17 00:00:00 2001 From: Rich Churcher Date: Mon, 21 Sep 2015 08:34:22 +1200 Subject: [PATCH 009/592] Make plain that the array is not already sorted. --- seed/challenges/basic-bonfires.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index cbcdbd1b83..e537eda1e6 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -613,8 +613,9 @@ "title": "Where do I belong", "difficulty": "1.61", "description": [ - "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", - "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (0th index), but less than 2 (1st index).", + "Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted.", + "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (index 0), but less than 2 (index 1).", + "Likewise, where([20,3,5], 19) should return 2 because it is less than 20 (index 2) and greater than 5 (index 1).", "Remember to use Read-Search-Ask if you get stuck. Write your own code." ], "challengeSeed": [ From 82605bbcb06f7a76be2596acd7c2da7ea6c41a8b Mon Sep 17 00:00:00 2001 From: Joel Bentley Date: Sun, 20 Sep 2015 16:48:09 -0400 Subject: [PATCH 010/592] Fix test on Waypoint Use Comments to Clarify Code --- seed/challenges/bootstrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index fb4f864474..9c6d924f41 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -2141,7 +2141,7 @@ "tests": [ "assert(editor.match(//g) && editor.match(/-->/g).length > 0, 'Be sure to close your comment with -->.')" + "assert(editor.match(/-->.*\\n.+/g), 'Be sure to close your comment with -->.')" ], "challengeSeed": [ "
      ", From d9d558a8a9c2b03f01882d60cc646c3d1b57e61d Mon Sep 17 00:00:00 2001 From: ahstro Date: Mon, 21 Sep 2015 23:10:13 +0200 Subject: [PATCH 011/592] Slot Machine false positives The 'Add your JavaScript Slot Machine Slots' waypoint would throw false positives if all slot numbers were the same, effectively allowing the campers to pass the test without having written any code. --- seed/challenges/basic-javascript.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index e3542ee41d..53cc76410b 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -1302,7 +1302,7 @@ "}" ], "tests":[ - "assert((function(){var data = runSlots();if(data === null){return true}else{if(data[0] === data[1] && data[1] === data[2]){return true;}else{return false;}}})(), 'If all three of our random numbers are the same we should return that number. Otherwise we should return null.')" + "assert((function(){var data = runSlots();return data === null || data.toString().length === 1;})(), 'If all three of our random numbers are the same we should return that number. Otherwise we should return null.')" ], "challengeSeed":[ "fccss", @@ -1485,9 +1485,10 @@ " ", " // Only change code above this line.", " ", - " if(slotOne !== slotTwo || slotTwo !== slotThree){", - " return null;", + " if(slotOne === slotTwo && slotTwo === slotThree){", + " return slotOne;", " }", + " return null;", " ", " if(slotOne !== undefined && slotTwo !== undefined && slotThree !== undefined){", " $(\".logger\").html(slotOne);", @@ -1655,9 +1656,10 @@ " ", " // Only change code above this line.", " ", - " if(slotOne !== slotTwo || slotTwo !== slotThree){", - " return null;", + " if(slotOne === slotTwo && slotTwo === slotThree){", + " return slotOne;", " }", + " return null;", " ", " if(slotOne !== undefined && slotTwo !== undefined && slotThree !== undefined){", " $('.logger').html(slotOne);", From a75db9c7f2f9490424de7d92e6a93f711a34c35f Mon Sep 17 00:00:00 2001 From: Joel Bentley Date: Wed, 23 Sep 2015 18:21:16 -0400 Subject: [PATCH 012/592] Modify test to allow for blank line after comment --- seed/challenges/bootstrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index 9c6d924f41..927f17a6fa 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -2141,7 +2141,7 @@ "tests": [ "assert(editor.match(/.*\\n.+/g), 'Be sure to close your comment with -->.')" + "assert(editor.match(/-->.*\\n+.+/g), 'Be sure to close your comment with -->.')" ], "challengeSeed": [ "
      ", From e2459fa869f3c05cf659b2cb41d0f7bdd1aadec6 Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Mon, 28 Sep 2015 23:24:42 +0100 Subject: [PATCH 013/592] Foundation fo AJAX stuff is done. Going to move on to process fetched data and creating a UI generating function for each individual object --- seed/challenges/json-apis-and-ajax.json | 116 ++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 seed/challenges/json-apis-and-ajax.json diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json new file mode 100644 index 0000000000..8ece73714b --- /dev/null +++ b/seed/challenges/json-apis-and-ajax.json @@ -0,0 +1,116 @@ +{ + "name": "JSON APIs and Ajax", + "order": 0.0065, + "challenges": [ + { + "id": "bad87fed1348bd9aeca08826", + "title": "Trigger on click Events with jQuery", + "difficulty": 3.19, + "description": [ + "With jQuery we are able to get data from APIs via Ajax", + "This data normally comes in the form of JSON", + "Let's get the Get Message button to set the text of a div", + "We will later use this to display the result of out API request", + "$(\"#getMessage\").on(\"click\", function(){", + "  $(\".message\").html(\"Here is the message\");", + "});" + ], + "tests": [ + "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\#getMessage(?:'|\")\\s*?\\)\\s*?\\.on\\s*?\\(\\s*?(?:'|\")click(?:'|\")\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have bound the click event to the getMessage button')", + "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\.message(?:'|\")\\s*?\\)\\s*?\\.html\\s*?\\(\\s*?(?:'|\")Here\\sis\\sthe\\smessage(?:'|\")\\s*?\\);/gi), 'You should set te value of the #message box to be the message given in the description')", + "assert(editor.match(/\\n*?\\s*?\\}\\n*?\\s*?\\);/gi) && editor.match(/\\n*?\\s*?\\}\\);/gi).length >= 2, 'Make sure that you close off all of your functions')" + ], + "challengeSeed": [ + "fccss", + " $(document).ready(function() {", + " ", + " });", + "fcces", + "", + "", + "", + "
      ", + "
      ", + "

      Cat Photo Finder

      ", + "
      ", + "
      ", + "
      ", + "
      ", + " The message will go here", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      " + ], + "challengeType": 0, + "type": "waypoint" + }, + { + "id": "bad87fee1348bd9aebc08826", + "title": "Get Data from an URL Using jQuery", + "dashedName": "waypoint-get-data-from-a-url-using-jquery", + "difficulty": 3.21, + "description": [ + "", + "We are now going to request data from an external source. (a file on FCC for the purposes of this exercise) The request will load in the data an run the code in the function we provide the data to which is known as the callback.", + "$(\"#getMessage\").on(\"click\", function() {", + "  $.getJSON(\"/json/cats.json?callback=?\", function( json ) {", + "    //Code to run when request is complete", + "    $(\".message\").html(JSON.stringify(json))", + "  });", + "});", + "Let's make it so that the data sent from the request is appended to the .message div", + "" + ], + "tests": [ + "assert(editor.match(/\\$\\s*?\\(\\s*?(\\\"|\\')\\#getMessage(\\\"|\\')\\s*?\\)\\s*?\\.\\s*?on\\s*?\\(\\s*?(\\\"|\\')click(\\\"|\\')\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have a click handler on the getMessage button to trigger the AJAX request')", + "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi), 'You should have at least on closing set of brackets and parenthesis')", + "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi) && editor.match(/\\,\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi) && editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi).length === editor.match(/\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi).length, 'Each callback function should have a closing set of brackets and parenthesis')", + "assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?\"\\\/json\\\/cats\\.json\\?callback\\=\\?\"\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file')", + "assert(editor.match(/\\$\\s*?\\(\\s*?\\\"\\.message\\\"\\s*?\\)\\s*?\\.\\s*?html\\s*?\\(\\s*?JSON\\s*?\\.\\s*?stringify\\s*?\\(\\s*?json\\s*?\\)\\s*?\\)/gi), 'Don\\'t forget to make the .html change the contents of the message box so that it contains the result of the getJSON')" + ], + "challengeSeed": [ + "fccss", + " $(document).ready(function() {", + " ", + " $(\"#getMessage\").on(\"click\", function(){", + " $(\".message\").html(\"Make the result of the getJSON request appear here\")", + " });", + " ", + " });", + "fcces", + "", + "", + "", + "
      ", + "
      ", + "

      Cat Photo Finder

      ", + "
      ", + "
      ", + "
      ", + "
      ", + " The message will go here", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      " + ], + "challengeType": 0, + "type": "waypoint" + } + ] +} From 963856b278f98948feef9a0d8c1af95036aca934 Mon Sep 17 00:00:00 2001 From: Ricky Ng-Adam Date: Tue, 29 Sep 2015 19:00:50 +0800 Subject: [PATCH 014/592] Additional tweaks to doc to get it working --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b0c87d631..90e6cd40cd 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ touch .env npm install -g gulp ``` -Edit your `.env` file with the following API keys accordingly (if you only use email login, only the `MONGOHQ_URL`, `SESSION_SECRET`, `MANDRILL_USER` and `MANDRILL_PASSWORD` fields are necessary. Keep in mind if you want to use more services you'll have to get your own API keys for those services. +Edit your `.env` file with the following API keys accordingly. If you only use email login, only the `MONGOHQ_URL`, `SESSION_SECRET`, `MANDRILL_USER` and `MANDRILL_PASSWORD` fields are necessary. Keep in mind if you want to use more services you'll have to get your own API keys for those services. If you only use a subset or no OAuth2 authentication methods, you have to remove them from ```server/passport-providers.js``` otherwise the server will complain of missing clientID at launch. ``` MONGOHQ_URL='mongodb://localhost:27017/freecodecamp' @@ -122,6 +122,8 @@ node seed/ gulp ``` +Note that you may need to run gulp before ```node seed/``` one time to create ```server/rev-manifest.json``` (on which the seeding scripts also depend). + License ------- From 90230ec907db1536af7386ac7ff2ffd0746f0db1 Mon Sep 17 00:00:00 2001 From: natac13 Date: Wed, 30 Sep 2015 05:13:13 -0400 Subject: [PATCH 015/592] fix test so it does not match code not in the answer --- seed/challenges/basic-javascript.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index 13c28c2021..5c15e74bf5 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -1491,7 +1491,7 @@ " }", " ", " if(slotOne !== undefined && slotTwo !== undefined && slotThree !== undefined){", - " $(\".logger\").html(slotOne);", + " $(\".logger\").text(slotOne);", " $(\".logger\").append(\" \" + slotTwo);", " $(\".logger\").append(\" \" + slotThree);", " }", From 2d6c91b51326c4b6c0fdb00f54604afa868485f5 Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Wed, 30 Sep 2015 23:01:56 +0100 Subject: [PATCH 016/592] Three complete. More to come --- seed/challenges/json-apis-and-ajax.json | 87 ++- .../json-apis-and-ajax.json | 535 ------------------ 2 files changed, 80 insertions(+), 542 deletions(-) delete mode 100644 seed/under-construction/json-apis-and-ajax.json diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index 8ece73714b..9f96865672 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -3,7 +3,7 @@ "order": 0.0065, "challenges": [ { - "id": "bad87fed1348bd9aeca08826", + "id": "bb000000000000000000000", "title": "Trigger on click Events with jQuery", "difficulty": 3.19, "description": [ @@ -53,15 +53,14 @@ "type": "waypoint" }, { - "id": "bad87fee1348bd9aebc08826", - "title": "Get Data from an URL Using jQuery", - "dashedName": "waypoint-get-data-from-a-url-using-jquery", - "difficulty": 3.21, + "id": "bb000000000000000000001", + "title": "Creating HTML from Data from an AJAX request Using jQuery", + "difficulty": 3.20, "description": [ "", "We are now going to request data from an external source. (a file on FCC for the purposes of this exercise) The request will load in the data an run the code in the function we provide the data to which is known as the callback.", "$(\"#getMessage\").on(\"click\", function() {", - "  $.getJSON(\"/json/cats.json?callback=?\", function( json ) {", + "  $.getJSON(\"/json/cats.json?callback=\", function( json ) {", "    //Code to run when request is complete", "    $(\".message\").html(JSON.stringify(json))", "  });", @@ -73,7 +72,7 @@ "assert(editor.match(/\\$\\s*?\\(\\s*?(\\\"|\\')\\#getMessage(\\\"|\\')\\s*?\\)\\s*?\\.\\s*?on\\s*?\\(\\s*?(\\\"|\\')click(\\\"|\\')\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have a click handler on the getMessage button to trigger the AJAX request')", "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi), 'You should have at least on closing set of brackets and parenthesis')", "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi) && editor.match(/\\,\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi) && editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi).length === editor.match(/\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi).length, 'Each callback function should have a closing set of brackets and parenthesis')", - "assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?\"\\\/json\\\/cats\\.json\\?callback\\=\\?\"\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file')", + "assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?\"\\\/json\\\/cats\\.json\\?callback\\=\"\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file')", "assert(editor.match(/\\$\\s*?\\(\\s*?\\\"\\.message\\\"\\s*?\\)\\s*?\\.\\s*?html\\s*?\\(\\s*?JSON\\s*?\\.\\s*?stringify\\s*?\\(\\s*?json\\s*?\\)\\s*?\\)/gi), 'Don\\'t forget to make the .html change the contents of the message box so that it contains the result of the getJSON')" ], "challengeSeed": [ @@ -111,6 +110,80 @@ ], "challengeType": 0, "type": "waypoint" + }, + { + "id": "bb000000000000000000002", + "title": "Convert json data to html", + "difficulty": 3.21, + "description": [ + "", + "Now that we have the data let's re-arrange it so that ", + "", + "", + "  json.map(function(val){", + "    ", + "    html = html + \"<div class = 'cat'>\"", + "    ", + "    for(var key in val){", + "      html = html + '<div class = \"' + key + '\">' + val[key] + '</div>';", + "  }", + "    ", + "    html = html + \"</div><br/>\"", + "    ", + "  });", + "", + "" + ], + "tests": [ + "assert($(\".message\").html() !== '', 'The message box should have something in it')", + "assert($(\".message div\").html() !== undefined, 'you should have made created some sort of view from the json data')" + ], + "challengeSeed": [ + "fccss", + " $(document).ready(function() {", + " ", + " $(\"#getMessage\").on(\"click\", function() {", + "   $.getJSON(\"/json/cats.json?callback=\", function( json ) {", + " ", + " var html = \"\";", + " ", + " //Add you code to modify the data here. It should add it to the html sting for use in the view", + " ", + " ", + " ", + " //Don't modify above here", + " ", + "     $(\".message\").html(html);", + " ", + "   });", + " });", + " ", + " });", + "fcces", + "", + "", + "", + "
      ", + "
      ", + "

      Cat Photo Finder

      ", + "
      ", + "
      ", + "
      ", + "
      ", + " The message will go here","
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      " + ], + "challengeType": 0, + "type": "waypoint" } ] } diff --git a/seed/under-construction/json-apis-and-ajax.json b/seed/under-construction/json-apis-and-ajax.json deleted file mode 100644 index ab12090b02..0000000000 --- a/seed/under-construction/json-apis-and-ajax.json +++ /dev/null @@ -1,535 +0,0 @@ -{ - "name": "JSON APIs and Ajax", - "order": 0.0065, - "challenges": [ - { - "id": "bad87fed1348bd9aeca08826", - "title": "Trigger on click Events with jQuery", - "difficulty": 3.19, - "description": [ - "With jQuery we are able to get data from APIs via Ajax", - "This data normally comes in the form of JSON", - "Let's get the Get Message button to set the text of a div", - "We will later use this to display the result of out API request", - "$(\"#getMessage\").on(\"click\", function(){", - "  $(\".message\").html(\"Here is the message\");", - "});" - ], - "tests": [ - "assert(editor.match(/\\$\\(\\s?\\\"\\#getMessage\\\"\\s?\\)\\.on\\s?\\(\\s?\\\"click\\\"\\,\\s?function\\s?\\(\\)\\s?\\{/gi), 'You should have bound the click event to the getMessage button')", - "assert(editor.match(/\\$\\(\\s?\\\"\\.message\\\"\\s?\\)\\.html\\(\\s?\\\"Here\\sis\\sthe\\smessage\\\"\\s?\\);/gi), 'You should set te value of the #message box to be the message given in the description')", - "assert(editor.match(/\\}\\);/gi) && editor.match(/\\}\\);/gi).length >= 2, 'Make sure that you close off all of your functions')" - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " ", - " });", - "fcces", - "", - "", - "", - "
      ", - "
      ", - "

      Cat Photo Finder

      ", - "
      ", - "
      ", - "
      ", - "
      ", - " The message will go here", - "
      ", - "
      ", - "
      ", - "
      ", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - { - "id": "bad87fee1348bd9aebc08726", - "title": "Learn JSON Syntax", - "description": [ - "JSON stands for \"JavaScript Object Notation\". It\"s how you create objects in JavaScript.", - "JSON is a series of \"key-value pairs\". Everything on the left of the colon (:) is the \"key\" you use to unlock the \"value\" on the right of the colon." - ], - "tests": [ - "assert(typeof data != \"undefined\", \"Whoops! It looks like you deleted the data variable!\");", - "assert(typeof getAnId != \"undefined\", \"Whoops! It looks like you deleted the getAnId function!\");", - "assert(data[0]['id'] === getAnId(), \"The duntion getFirstId should return the id of the first element in the array\");" - ], - "challengeSeed": [ - "fccss", - "var data = [", - " {", - " \"id\": 0,", - " \"imageLink\": \"http://rs611.pbsrc.com/albums/tt194/allypopper423/Funny-Cat-Green-Avacado.jpg~c200\",", - " \"codeNames\": [", - " \"Juggernaut\",", - " \"Mrs. Wallace\",", - " \"Buttercup\"", - " ]", - " },", - " {", - " \"id\": 1,", - " \"imageLink\": \"http://cdn.grumpycats.com/wp-content/uploads/2012/09/GC-Gravatar-copy.png\",", - " \"codeNames\": [", - " \"Oscar\",", - " \"Scrooge\",", - " \"Tyrion\"", - " ]", - " },", - " {", - " \"id\": 2,", - " \"imageLink\": \"http://www.kittenspet.com/wp-content/uploads/2012/08/cat_with_funny_face_3-200x200.jpg\",", - " \"codeNames\": [", - " \"The Doctor\",", - " \"Loki\",", - " \"Joker\"", - " ]", - " }", - "]", - "function getAnId(){", - " return();", - "}", - "fcces" - ], - "challengeType": 0, - "type": "waypoint" - }, - { - "id": "bad87fee1348bd9aeca08826", - "title": "Displaying JSON data in HTML", - "difficulty": 3.19, - "description": [ - "JSON stands for \"JavaScript Object Notation\". It\"s how you create objects in JavaScript.", - "JSON is a series of \"key-value pairs\". Everything on the left of the colon (:) is the \"key\" you use to unlock the \"value\" on the right of the colon." - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"#getMessage\").on(\"click\", function(){", - " $(\".message\").html(\"Here is the message\");", - " });", - " });", - "fcces", - "", - "", - "", - "
      ", - "
      ", - "

      Cat Photo Finder

      ", - "
      ", - "
      ", - "
      ", - "
      ", - " The message will go here", - "
      ", - "
      ", - "
      ", - "
      ", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad84fee1348bd9aecc48826", - "title": "Read Data from an Element Using jQuery", - "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, - "description": [ - "Let's make everything roll with rollOut." - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").on(\"click\", function() {", - " $(\"#click-me\").addClass(\"animated shake\");", - " });", - " });", - "fcces", - "", - "", - "", - "
      ", - "
      ", - "
      ", - " ", - "
      ", - "
      ", - "

      #check-me

      ", - "
      ", - " ", - " Is the checkbox checked?", - " ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad84fee1348bd9aecc38826", - "title": "Read Data from an Element Using jQuery", - "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, - "description": [ - "Let's make everything roll with rollOut." - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").on(\"click\", function() {", - " $(\"#click-me\").addClass(\"animated shake\");", - " $(\"#checked-state\").text(\"happy text\");", - " });", - " });", - "fcces", - "", - "", - "", - "
      ", - "
      ", - "
      ", - " ", - "
      ", - "
      ", - "

      #check-me

      ", - "
      ", - " ", - " Is the checkbox checked?", - " ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad84fee1348bd9aecc28826", - "title": "Read Data from an Element Using jQuery", - "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, - "description": [ - "Let's make everything roll with rollOut." - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").on(\"click\", function() {", - " $(\"#click-me\").addClass(\"animated shake\");", - " $(\"#checked-state\").text($(\"#check-me\").prop(\"checked\"));", - " });", - " });", - "fcces", - "", - "", - "", - "
      ", - "
      ", - "
      ", - " ", - "
      ", - "
      ", - "

      #check-me

      ", - "
      ", - " ", - " Is the checkbox checked?", - " ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad84fee1348bd9aecc18826", - "title": "Read Data from an Element Using jQuery", - "dashedName": "waypoint-read-data-from-an-element-using-jquery", - "difficulty": 3.17, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").on(\"click\", function() {", - " $(\"#click-me\").addClass(\"animated shake\");", - " $(\"#checked-state\").text($(\"#check-me\").prop(\"checked\"));", - " });", - " });", - "fcces", - "", - "", - "", - "
      ", - "
      ", - "
      ", - " ", - "
      ", - "
      ", - "

      #check-me

      ", - "
      ", - " ", - " Is the checkbox checked?", - " ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad87fee1348bd9aecc08826", - "title": "Trigger onHover Events with jQuery", - "dashedName": "waypoint-trigger-onhover-events-with-jquery", - "difficulty": 3.18, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad87fee1348bd9aebc08826", - "title": "Get Data from an URL Using jQuery", - "dashedName": "waypoint-get-data-from-a-url-using-jquery", - "difficulty": 3.21, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - "", - " $(document).ready(function() {", - "", - " $(\"#cat-button\").on(\"click\", function() {", - " $.getJSON(\"/json/cats.json\", function( json ) {", - "", - " });", - " });", - "", - " });", - "fcces", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad87fee1348bd9ae9c08826", - "title": "Loop through JSON Data Using jQuery", - "dashedName": "waypoint-loop-through-json-data-using-jquery", - "difficulty": 3.22, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - "", - " $(document).ready(function() {", - "", - " $(\"#cat-button\").on(\"click\", function() {", - " $.getJSON(\"/json/cats.json\", function( json ) {", - "", - " });", - " });", - "", - " });", - "fcces", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad88fee1348bd9ae8c08726", - "title": "Wire AJAX Call into a jQuery Click Event", - "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, - "description": [ - "" - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " var random = function() { return Math.floor(Math.random() * 3) }", - " $(document).ready(function() {", - "", - " $(\"#cat-button\").on(\"click\", function() {", - " $.getJSON(\"/json/cats.json\", function( json ) {", - "", - " });", - " });", - "", - " });", - "fcces", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad88fee1348bd9ae8c08626", - "title": "Wire AJAX Call into a jQuery Click Event", - "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, - "description": [ - "" - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " var random = function() { return Math.floor(Math.random() * 3) }", - " $(document).ready(function() {", - "", - " $(\"#cat-button\").on(\"click\", function() {", - " $.getJSON(\"/json/cats.json\", function( json ) {", - " var kitten = json[random()];", - " });", - " });", - "", - " });", - "fcces", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad88fee1348bd9ae8c08526", - "title": "Wire AJAX Call into a jQuery Click Event", - "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, - "description": [ - "" - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " var random = function() { return Math.floor(Math.random() * 3) }", - " $(document).ready(function() {", - "", - " $(\"#cat-button\").on(\"click\", function() {", - " $.getJSON(\"/json/cats.json\", function( json ) {", - " var kitten = json[random()];", - " $(\"\").appendTo(\"#output\");", - " });", - " });", - "", - " });", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - }, - - { - "id": "bad88fee1348bd9ae8c08426", - "title": "Wire AJAX Call into a jQuery Click Event", - "dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event", - "difficulty": 3.24, - "description": [ - "" - ], - "tests": [ - - ], - "challengeSeed": [ - "fccss", - " var random = function() { return Math.floor(Math.random() * 3) }", - " $(document).ready(function() {", - "", - " $(\"#cat-button\").on(\"click\", function() {", - " $.getJSON(\"/json/cats.json\", function( json ) {", - " var kitten = json[random()];", - " $(\"\").appendTo(\"#output\");", - " $(\"

      Code name: \" + kitten.codeNames[random()] + \"

      \").appendTo(\"#output\");", - " });", - " });", - "", - " });", - "fcces", - "
      ", - " ", - "
      ", - "
      ", - "
      " - ], - "challengeType": 0, - "type": "waypoint" - } - ] -} From 1b13ad2601452eb83364fd00f9c998a2d9f91802 Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Wed, 30 Sep 2015 23:23:58 +0100 Subject: [PATCH 017/592] Added the skeleton for the fourth challenge. Challenge three needs some refinement in the testing system --- seed/challenges/json-apis-and-ajax.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index 9f96865672..e826927a0d 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -113,7 +113,7 @@ }, { "id": "bb000000000000000000002", - "title": "Convert json data to html", + "title": "Convert JSON data to HTML", "difficulty": 3.21, "description": [ "", @@ -184,6 +184,25 @@ ], "challengeType": 0, "type": "waypoint" + }, + { + "id": "bb000000000000000000003", + "title": "Pre-filtering the JSON", + "difficulty": 3.22, + "description": [ + "", + "If we want to filter the data we have so that we are searching through results based on users inout. It is far more efficient to filter and display a copy of the data we have instead of requesting a new copy each time.", + "This means we should never hit API limits and it will make the process more efficient.", + "" + ], + "tests": [ + "/*be assertive!*/" + ], + "challengeSeed": [ + "TODO: get the result of the previous challenge" + ], + "challengeType": 0, + "type": "waypoint" } ] } From b2bf3ce391aa1427f5ba03e51208935fa0be7509 Mon Sep 17 00:00:00 2001 From: ahstro Date: Sat, 3 Oct 2015 11:23:41 +0200 Subject: [PATCH 018/592] Truncate a string: Minor typo The assert message said `1`, instead of the number `11` that was actually being used in the assertion. --- seed/challenges/basic-bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 931c157ce1..12da55a771 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -378,7 +378,7 @@ "truncate(\"A-tisket a-tasket A green and yellow basket\", 11, \"\");" ], "tests": [ - "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", 1) should return \"A-tisket...\".');", + "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", 11) should return \"A-tisket...\".');", "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: truncate(\"Peter Piper picked a peck of pickled peppers\", 14) should return \"Peter Piper...\".');", "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2) should return \"A-tisket a-tasket A green and yellow basket\".');" From 4e33b355b0e947b015cf8526e85a355b29b51388 Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Sat, 3 Oct 2015 23:59:54 +0100 Subject: [PATCH 019/592] 90% complete without QA or refined descriptions/tests --- seed/challenges/json-apis-and-ajax.json | 223 ++++++++++++++++++++++-- 1 file changed, 213 insertions(+), 10 deletions(-) diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index e826927a0d..fda516722e 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -4,6 +4,29 @@ "challenges": [ { "id": "bb000000000000000000000", + "title": "Understanding JSON", + "difficulty": 3.19, + "description": [ + "", + "JSON is a way of creating a file or a db record from a javascript object.", + "JSON works in the exact same way as javascript objects that you should be familiar with.", + "" + ], + "tests": [ + "assert(typeof json !== 'undefined')" + ], + "challengeSeed": [ + "var json = {", + " name: \"Happy Camper\"", + " age: 35", + " height: \"5ft 8\"", + "}" + ], + "challengeType": 0, + "type": "waypoint" + }, + { + "id": "bb000000000000000000001", "title": "Trigger on click Events with jQuery", "difficulty": 3.19, "description": [ @@ -53,7 +76,7 @@ "type": "waypoint" }, { - "id": "bb000000000000000000001", + "id": "bb000000000000000000002", "title": "Creating HTML from Data from an AJAX request Using jQuery", "difficulty": 3.20, "description": [ @@ -112,7 +135,7 @@ "type": "waypoint" }, { - "id": "bb000000000000000000002", + "id": "bb000000000000000000003", "title": "Convert JSON data to HTML", "difficulty": 3.21, "description": [ @@ -135,8 +158,7 @@ "" ], "tests": [ - "assert($(\".message\").html() !== '', 'The message box should have something in it')", - "assert($(\".message div\").html() !== undefined, 'you should have made created some sort of view from the json data')" + "assert($(\".message\").html() !== '', 'The message box should have something in it')" ], "challengeSeed": [ "fccss", @@ -149,10 +171,12 @@ " ", " //Add you code to modify the data here. It should add it to the html sting for use in the view", " ", - " ", - " ", " //Don't modify above here", " ", + " ", + " ", + " //Don't modify below here", + " ", "     $(\".message\").html(html);", " ", "   });", @@ -186,20 +210,199 @@ "type": "waypoint" }, { - "id": "bb000000000000000000003", + "id": "bb000000000000000000004", + "title": "render those images!", + "difficulty": 3.22, + "description": [ + "", + "instead of just placing everything in a div we should check if the value is an image.", + "If it is an image we should use it as an ima tag instead so that the image is rendered", + "", + "if(key === \"imageLink\"){", + "html = html + '<img class = \"' + key + '\"src = \"' + val[key] + '\">';", + "}", + "else{", + " html = html + '<div class = \"' + key + '\">' + val[key] + '</div>';", + "}", + "", + "" + ], + "tests": [ + "assert(editor.match(/imageLink/gi), 'You should have accessed the imageLink of each cat object')" + ], + "challengeSeed": [ + "fccss", + "$(document).ready(function() {", + " ", + " $(\"#getMessage\").on(\"click\", function() {", + "   $.getJSON(\"/json/cats.json?callback=\", function( json ) {", + " ", + " var html = \"\";", + " ", + " //Add you code to modify the data here. It should add it to the html sting for use in the view", + " ", + "  json.map(function(val){", + "", + " html = html + \"
      \"", + "", + "", + "", + " for(var key in val){", + "", + " //Don't modify above here", + " ", + " ", + " ", + " //Don't modify below here", + "", + " }", + " ", + " html = html + \"

      \"", + "", + " });", + " ", + " //Don't modify above here", + " ", + "     $(\".message\").html(html);", + " ", + "   });", + " });", + " ", + " });", + "fcces", + "", + "", + "", + "
      ", + "
      ", + "

      Cat Photo Finder

      ", + "
      ", + "
      ", + "
      ", + "
      ", + " The message will go here", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "" + ], + "challengeType": 0, + "type": "waypoint" + }, + { + "id": "bb000000000000000000005", "title": "Pre-filtering the JSON", "difficulty": 3.22, "description": [ "", - "If we want to filter the data we have so that we are searching through results based on users inout. It is far more efficient to filter and display a copy of the data we have instead of requesting a new copy each time.", "This means we should never hit API limits and it will make the process more efficient.", + "Let's try pre-filtering the json before we map it", + "We can use the pre-made filter method like this to remove the cat with the id of 1", + "", + "json = json.filter(function(val){", + " return(val.id !== 1);", + "});", + "", "" ], "tests": [ - "/*be assertive!*/" + "assert(editor.match(/filter/gi), 'You should be making use of the .filter method')" ], "challengeSeed": [ - "TODO: get the result of the previous challenge" + "fccss", + "$(document).ready(function() {", + " ", + " $(\"#getMessage\").on(\"click\", function() {", + "   $.getJSON(\"/json/cats.json?callback=\", function( json ) {", + " ", + " var html = \"\";", + " ", + " //Add you code to modify the data here. It should add it to the html sting for use in the view", + " ", + "  json.map(function(val){", + "", + "    val = \"\" ", + "", + " html = html + \"
      \"", + "", + " //Don't modify above here", + " ", + " ", + " ", + " //Don't modify below here", + "", + " for(var key in val){", + "", + " html = html + '
      ' + val[key] + '
      ';", + "", + " }", + "", + " ", + " html = html + \"

      \"", + "", + " });", + " ", + " //Don't modify above here", + " ", + "     $(\".message\").html(html);", + " ", + "   });", + " });", + " ", + " });", + "fcces", + "", + "", + "", + "
      ", + "
      ", + "

      Cat Photo Finder

      ", + "
      ", + "
      ", + "
      ", + "
      ", + " The message will go here", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "" + ], + "challengeType": 0, + "type": "waypoint" + }, + { + "id": "bb000000000000000000006", + "title": "Getting Geo-location data for use in APIs", + "difficulty": 3.19, + "description": [ + "", + "Be descriptive!" + ], + "tests": [ + "/*Be Assertive*/')" + ], + "challengeSeed": [ + "var json = {", + " name: \"Happy Camper\"", + " age: 35", + " height: \"5ft 8\"", + "}" ], "challengeType": 0, "type": "waypoint" From 89e1ebb952e1ce407b293acba40487196d1bb579 Mon Sep 17 00:00:00 2001 From: SaintPeter Date: Sat, 3 Oct 2015 19:56:10 -0700 Subject: [PATCH 020/592] New for loop waypoints and verbiage improvements --- seed/challenges/basic-javascript.json | 88 ++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index c10af0def1..2dbe909815 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -790,6 +790,14 @@ "description":[ "You can run the same code multiple times by using a loop.", "The most common type of JavaScript loop is called a \"for loop\" because it runs \"for\" a specific number of times.", + "", + "For loops are declared with three optional expressions seperated by semicolons:", + "for([initialization]; [condition]; [final-expression])", + "The initialization statement is executed one time only before the loop starts. It is typically used to define and setup your loop varaible.", + "The condition statement is evaluated at the beginning of every loop and will continue as long as it evalutes true. When condition is false at the start of the loop, the loop will stop executing. This means if condition starts as false, your loop will never execute.", + "The final-expression is executed at the end of each loop iteration, prior to the next condition check and is usually used to increment or decrement your loop counter.", + "", + "We'll initialize with i = 0 and loop while our condition i < 5 is true. We'll increment i by 1 each loop with i++ as our final-expression.", "var ourArray = [];", "for(var i = 0; i < 5; i++) {", "  ourArray.push(i);", @@ -798,7 +806,7 @@ "Let's try getting a for loop to work by pushing values to an array." ], "tests":[ - "assert(editor.getValue().match(/for/g), 'message: You should be using a for loop for this.');", + "assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a for loop for this.');", "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray should equal [0,1,2,3,4].');" ], "challengeSeed":[ @@ -821,6 +829,84 @@ "type": "waypoint", "challengeType": 1 }, + { + "id":"56104e9e514f539506016a5c", + "title": "Iterate Odd Numbers With a For Loop", + "difficulty":"9.9824", + "description":[ + "For loops don't have to iterate one at a time. By changing our final-expression, we can count by even numbers.", + "We'll start at i = 0 and loop while i < 10. We'll increment i by 2 each loop with i += 2.", + "var ourArray = [];", + "for(var i = 0; i < 10; i += 2) {", + "  ourArray.push(i);", + "}", + "ourArray will now contain [0,2,4,6,8] ", + "Let's change our initialization and final-expression so we can count by odd numbers." + ], + "tests":[ + "assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a for loop for this.');", + "assert.deepEqual(myArray, [1,3,5,7,9], 'message: myArray should equal [1,3,5,7,9].');" + ], + "challengeSeed":[ + "ourArray = [];", + "for(var i = 1; i < 10; i += 2){", + " ourArray.push(i);", + "}", + "var myArray = [];", + "", + "// Only change code below this line.", + "", + "// Push the odd numbers from one through nine to myArray using a \"for loop\" like above.", + "", + "// Only change code above this line.", + "// We use this function to show you the value of your variable in your output box.", + "// You'll learn about functions soon.", + "if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}", + "" + ], + "type": "waypoint", + "challengeType": 1 + }, + { + "id":"56105e7b514f539506016a5e", + "title": "Count Backwards With a For Loop", + "difficulty":"9.9824", + "description":[ + "A for loop can also count backwards, so long as we can define the right conditions.", + "", + "In order to count backwards by twos, we'll need to change our initialization, condition, and final-expression.", + "We'll start at i = 10 and loop while i > 0. We'll decrement i by 2 each loop with i -= 2.", + "var ourArray = [];", + "for(var i = 10; i > 0; i -= 2) {", + "  ourArray.push(i);", + "}", + "ourArray will now contain [10,8,6,4,2] ", + "Let's change our initialization and final-expression so we can count backward by twos for numbers." + ], + "tests":[ + "assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a for loop for this.');", + "assert.deepEqual(myArray, [9,7,5,3,1], 'message: myArray should equal [9,7,5,3,1].');" + ], + "challengeSeed":[ + "ourArray = [];", + "for(var i = 9; i > 0; i -= 2){", + " ourArray.push(i);", + "}", + "var myArray = [];", + "", + "// Only change code below this line.", + "", + "// Push the odd numbers from nine through one to myArray using a \"for loop\" like above.", + "", + "// Only change code above this line.", + "// We use this function to show you the value of your variable in your output box.", + "// You'll learn about functions soon.", + "if(typeof(myArray) !== \"undefined\"){(function(){return myArray;})();}", + "" + ], + "type": "waypoint", + "challengeType": 1 + }, { "id":"cf1111c1c11feddfaeb1bdef", "title": "Iterate with JavaScript While Loops", From fe3e94e69b5005d8c16dfac008a3e785065d5174 Mon Sep 17 00:00:00 2001 From: Abhisek Pattnaik Date: Mon, 21 Sep 2015 01:55:21 +0530 Subject: [PATCH 021/592] Modify tests for Bonfire - Where do I belong close FreeCodeCamp/FreeCodeCamp#3381 --- seed/challenges/basic-bonfires.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 931c157ce1..c81733da04 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -617,8 +617,8 @@ "assert(where([10, 20, 30, 40, 50], 35) === 3, 'message: where([10, 20, 30, 40, 50], 35) should return 3.');", "assert(where([10, 20, 30, 40, 50], 30) === 2, 'message: where([10, 20, 30, 40, 50], 30) should return 2.');", "assert(where([40, 60], 50) === 1, 'message: where([40, 60,], 50) should return 1.');", - "assert(where([5, 3, 20, 3], 3) === 0, 'message: where([5, 3, 20, 3], 3) should return 0.');", - "assert(where([2, 20, 10], 1) === 0, 'message: where([2, 20, 10], 1) should return 0.');", + "assert(where([5, 3, 20, 3], 5) === 2, 'message: where([5, 3, 20, 3], 5) should return 2.');", + "assert(where([2, 20, 10], 19) === 2, 'message: where([2, 20, 10], 19) should return 2.');", "assert(where([2, 5, 10], 15) === 3, 'message: where([2, 5, 10], 15) should return 3.');" ], "type": "bonfire", From e07941936759f6dc4da0f43ba4ccb94d4692f45c Mon Sep 17 00:00:00 2001 From: ahstro Date: Mon, 5 Oct 2015 18:01:28 +0200 Subject: [PATCH 022/592] Confirm the Ending: Add test case Add a test case that makes sure the user can't just check the last character or word. --- seed/challenges/basic-bonfires.json | 1 + 1 file changed, 1 insertion(+) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 931c157ce1..3e6b8aa1bc 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -307,6 +307,7 @@ "assert(end(\"Connor\", \"n\") === false, 'message: end(\"Connor\", \"n\") should return false.');", "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") === false, 'message: end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") should return false.');", "assert(end(\"He has to give me a new name\", \"name\") === true, 'message: end(\"He has to give me a new name\", \"name\") should return true.');", + "assert(end(\"He has to give me a new name\", \"me\") === true, 'message: end(\"He has to give me a new name\", \"me\") should return true.');", "assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") should return false.');" ], "MDNlinks": [ From c04832d61846db4131ad566feaac51495a2e8464 Mon Sep 17 00:00:00 2001 From: Florencia Tarditti Date: Mon, 5 Oct 2015 21:26:18 +0200 Subject: [PATCH 023/592] fix bootstrap fluid containers wording issue Closes #2467. --- seed/challenges/bootstrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json index d405871390..3982fe18d5 100644 --- a/seed/challenges/bootstrap.json +++ b/seed/challenges/bootstrap.json @@ -9,7 +9,7 @@ "Now let's go back to our Cat Photo App. This time, we'll style it using the popular Bootstrap responsive CSS framework.", "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", "With responsive design, there is no need to design a mobile version of your website. It will look good on devices with screens of any width.", - "You can add Bootstrap to any app just by including it with <link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/> at the top of your HTML. But we've gone ahead and automatically added it to your Cat Photo App for you.", + "You can add Bootstrap to any app just by including it with <link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/> at the top of your HTML. But we've added it for you to this page behind the scenes.", "To get started, we should nest all of our HTML in a div element with the class container-fluid." ], "tests": [ From 5b771e18e66eb53157acd1bc10d8d90ce4951e0a Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Mon, 5 Oct 2015 22:46:29 +0100 Subject: [PATCH 024/592] Finished the geolocation waypoint. Ready for QA and copy fixes --- seed/challenges/json-apis-and-ajax.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index fda516722e..cec38c8b65 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -392,10 +392,22 @@ "difficulty": 3.19, "description": [ "", - "Be descriptive!" + "We can access the users current location by using the built in navigator in the browser.", + "The navigator will get the users current longitude and latitude with a decent level of accuracy.", + "", + "if (navigator.geolocation) {", + " navigator.geolocation.getCurrentPosition(function(position){", + " // Do something in here with the coordinates!", + " ", + " console.log(\"latitiude\", position.coords.latitude);", + " console.log(\"longitude\", position.coords.longitude);", + " ", + " });", + "}", + "" ], "tests": [ - "/*Be Assertive*/')" + "assert(editor.match(/navigator\\.geolocation\\.getCurrentPosition/gi), 'you should make use of the navigator.geolocation to access the users current location')" ], "challengeSeed": [ "var json = {", From da09a7b650ab40b316dc42c64978dda76999b21b Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Mon, 5 Oct 2015 23:42:30 +0100 Subject: [PATCH 025/592] Brought in line with staging and added spoofigator! --- client/commonFramework.js | 14 ++++++++++++++ seed/challenges/json-apis-and-ajax.json | 25 +++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/client/commonFramework.js b/client/commonFramework.js index 8abcb6a9dc..ced143db58 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -481,6 +481,20 @@ function safeHTMLRun(test) { // add feuxQuery s = 'var document = \"\"; var $ = function() {return(new function() {this.add=function() {return(this);};this.addBack=function() {return(this);};this.addClass=function() {return(this);};this.after=function() {return(this);};this.ajaxComplete=function() {return(this);};this.ajaxError=function() {return(this);};this.ajaxSend=function() {return(this);};this.ajaxStart=function() {return(this);};this.ajaxStop=function() {return(this);};this.ajaxSuccess=function() {return(this);};this.andSelf=function() {return(this);};this.animate=function() {return(this);};this.append=function() {return(this);};this.appendTo=function() {return(this);};this.attr=function() {return(this);};this.before=function() {return(this);};this.bind=function() {return(this);};this.blur=function() {return(this);};this.callbacksadd=function() {return(this);};this.callbacksdisable=function() {return(this);};this.callbacksdisabled=function() {return(this);};this.callbacksempty=function() {return(this);};this.callbacksfire=function() {return(this);};this.callbacksfired=function() {return(this);};this.callbacksfireWith=function() {return(this);};this.callbackshas=function() {return(this);};this.callbackslock=function() {return(this);};this.callbackslocked=function() {return(this);};this.callbacksremove=function() {return(this);};this.change=function() {return(this);};this.children=function() {return(this);};this.clearQueue=function() {return(this);};this.click=function() {return(this);};this.clone=function() {return(this);};this.closest=function() {return(this);};this.contents=function() {return(this);};this.context=function() {return(this);};this.css=function() {return(this);};this.data=function() {return(this);};this.dblclick=function() {return(this);};this.delay=function() {return(this);};this.delegate=function() {return(this);};this.dequeue=function() {return(this);};this.detach=function() {return(this);};this.die=function() {return(this);};this.each=function() {return(this);};this.empty=function() {return(this);};this.end=function() {return(this);};this.eq=function() {return(this);};this.error=function() {return(this);};this.fadeIn=function() {return(this);};this.fadeOut=function() {return(this);};this.fadeTo=function() {return(this);};this.fadeToggle=function() {return(this);};this.filter=function() {return(this);};this.find=function() {return(this);};this.finish=function() {return(this);};this.first=function() {return(this);};this.focus=function() {return(this);};this.focusin=function() {return(this);};this.focusout=function() {return(this);};this.get=function() {return(this);};this.has=function() {return(this);};this.hasClass=function() {return(this);};this.height=function() {return(this);};this.hide=function() {return(this);};this.hover=function() {return(this);};this.html=function() {return(this);};this.index=function() {return(this);};this.innerHeight=function() {return(this);};this.innerWidth=function() {return(this);};this.insertAfter=function() {return(this);};this.insertBefore=function() {return(this);};this.is=function() {return(this);};this.jQuery=function() {return(this);};this.jquery=function() {return(this);};this.keydown=function() {return(this);};this.keypress=function() {return(this);};this.keyup=function() {return(this);};this.last=function() {return(this);};this.length=function() {return(this);};this.live=function() {return(this);};this.load=function() {return(this);};this.load=function() {return(this);};this.map=function() {return(this);};this.mousedown=function() {return(this);};this.mouseenter=function() {return(this);};this.mouseleave=function() {return(this);};this.mousemove=function() {return(this);};this.mouseout=function() {return(this);};this.mouseover=function() {return(this);};this.mouseup=function() {return(this);};this.next=function() {return(this);};this.nextAll=function() {return(this);};this.nextUntil=function() {return(this);};this.not=function() {return(this);};this.off=function() {return(this);};this.offset=function() {return(this);};this.offsetParent=function() {return(this);};this.on=function() {return(this);};this.one=function() {return(this);};this.outerHeight=function() {return(this);};this.outerWidth=function() {return(this);};this.parent=function() {return(this);};this.parents=function() {return(this);};this.parentsUntil=function() {return(this);};this.position=function() {return(this);};this.prepend=function() {return(this);};this.prependTo=function() {return(this);};this.prev=function() {return(this);};this.prevAll=function() {return(this);};this.prevUntil=function() {return(this);};this.promise=function() {return(this);};this.prop=function() {return(this);};this.pushStack=function() {return(this);};this.queue=function() {return(this);};this.ready=function() {return(this);};this.remove=function() {return(this);};this.removeAttr=function() {return(this);};this.removeClass=function() {return(this);};this.removeData=function() {return(this);};this.removeProp=function() {return(this);};this.replaceAll=function() {return(this);};this.replaceWith=function() {return(this);};this.resize=function() {return(this);};this.scroll=function() {return(this);};this.scrollLeft=function() {return(this);};this.scrollTop=function() {return(this);};this.select=function() {return(this);};this.selector=function() {return(this);};this.serialize=function() {return(this);};this.serializeArray=function() {return(this);};this.show=function() {return(this);};this.siblings=function() {return(this);};this.size=function() {return(this);};this.slice=function() {return(this);};this.slideDown=function() {return(this);};this.slideToggle=function() {return(this);};this.slideUp=function() {return(this);};this.stop=function() {return(this);};this.submit=function() {return(this);};this.text=function() {return(this);};this.toArray=function() {return(this);};this.toggle=function() {return(this);};this.toggle=function() {return(this);};this.toggleClass=function() {return(this);};this.trigger=function() {return(this);};this.triggerHandler=function() {return(this);};this.unbind=function() {return(this);};this.undelegate=function() {return(this);};this.unload=function() {return(this);};this.unwrap=function() {return(this);};this.val=function() {return(this);};this.width=function() {return(this);};this.wrap=function() {return(this);};this.wrapAll=function() {return(this);};this.wrapInner=function() {return(this);}});};$.ajax=function() {return($);};$.ajaxPrefilter=function() {return($);};$.ajaxSetup=function() {return($);};$.ajaxTransport=function() {return($);};$.boxModel=function() {return($);};$.browser=function() {return($);};$.Callbacks=function() {return($);};$.contains=function() {return($);};$.cssHooks=function() {return($);};$.cssNumber=function() {return($);};$.data=function() {return($);};$.Deferred=function() {return($);};$.dequeue=function() {return($);};$.each=function() {return($);};$.error=function() {return($);};$.extend=function() {return($);};$.fnextend=function() {return($);};$.fxinterval=function() {return($);};$.fxoff=function() {return($);};$.get=function() {return($);};$.getJSON=function() {return($);};$.getScript=function() {return($);};$.globalEval=function() {return($);};$.grep=function() {return($);};$.hasData=function() {return($);};$.holdReady=function() {return($);};$.inArray=function() {return($);};$.isArray=function() {return($);};$.isEmptyObject=function() {return($);};$.isFunction=function() {return($);};$.isNumeric=function() {return($);};$.isPlainObject=function() {return($);};$.isWindow=function() {return($);};$.isXMLDoc=function() {return($);};$.makeArray=function() {return($);};$.map=function() {return($);};$.merge=function() {return($);};$.noConflict=function() {return($);};$.noop=function() {return($);};$.now=function() {return($);};$.param=function() {return($);};$.parseHTML=function() {return($);};$.parseJSON=function() {return($);};$.parseXML=function() {return($);};$.post=function() {return($);};$.proxy=function() {return($);};$.queue=function() {return($);};$.removeData=function() {return($);};$.sub=function() {return($);};$.support=function() {return($);};$.trim=function() {return($);};$.type=function() {return($);};$.unique=function() {return($);};$.when=function() {return($);};$.always=function() {return($);};$.done=function() {return($);};$.fail=function() {return($);};$.isRejected=function() {return($);};$.isResolved=function() {return($);};$.notify=function() {return($);};$.notifyWith=function() {return($);};$.pipe=function() {return($);};$.progress=function() {return($);};$.promise=function() {return($);};$.reject=function() {return($);};$.rejectWith=function() {return($);};$.resolve=function() {return($);};$.resolveWith=function() {return($);};$.state=function() {return($);};$.then=function() {return($);};$.currentTarget=function() {return($);};$.data=function() {return($);};$.delegateTarget=function() {return($);};$.isDefaultPrevented=function() {return($);};$.isImmediatePropagationStopped=function() {return($);};$.isPropagationStopped=function() {return($);};$.metaKey=function() {return($);};$.namespace=function() {return($);};$.pageX=function() {return($);};$.pageY=function() {return($);};$.preventDefault=function() {return($);};$.relatedTarget=function() {return($);};$.result=function() {return($);};$.stopImmediatePropagation=function() {return($);};$.stopPropagation=function() {return($);};$.target=function() {return($);};$.timeStamp=function() {return($);};$.type=function() {return($);};$.which=function() {return($);};' + s; + // add spoofigator + + s = " var navigator = " + + "function(){" + + " this.geolocation=function(){" + + " this.getCurrentPosition=function(){" + + " this.coords = {latitude: \"\", longitude: \"\"};" + + " return(this);" + + " };" + + " return(this);" + + " };" + + " return(this);" + + "};" + s; + sandBox.submit(scopejQuery(s), function(cls, message) { if (cls) { console.log(message.error); diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index cec38c8b65..9ea8bfd0e8 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -396,13 +396,12 @@ "The navigator will get the users current longitude and latitude with a decent level of accuracy.", "", "if (navigator.geolocation) {", - " navigator.geolocation.getCurrentPosition(function(position){", - " // Do something in here with the coordinates!", - " ", - " console.log(\"latitiude\", position.coords.latitude);", - " console.log(\"longitude\", position.coords.longitude);", - " ", - " });", + "  navigator.geolocation.getCurrentPosition(function(position){", + "    // Do something in here with the coordinates!", + "    ", + "    $(\"#data\").html(\"latitiude\" + position.coords.latitude + \"longitude\" + position.coords.longitude);", + "    ", + "  });", "}", "" ], @@ -410,11 +409,13 @@ "assert(editor.match(/navigator\\.geolocation\\.getCurrentPosition/gi), 'you should make use of the navigator.geolocation to access the users current location')" ], "challengeSeed": [ - "var json = {", - " name: \"Happy Camper\"", - " age: 35", - " height: \"5ft 8\"", - "}" + "fccss", + "", + "fcces", + "
      ", + "

      You are here!

      ", + " ", + "
      " ], "challengeType": 0, "type": "waypoint" From c27e5bf6c425992b2f0afc64aa2efe8e20c2c83d Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 5 Oct 2015 21:57:15 -0700 Subject: [PATCH 026/592] start adding clementine challenge --- client/commonFramework.js | 8 +- seed/challenges/basejumps.json | 130 ++++++++++++++++++ .../front-end-development-certificate.json | 2 +- .../full-stack-development-certificate.json | 2 +- seed/challenges/getting-started.json | 42 +----- server/views/coursewares/showStep.jade | 5 +- 6 files changed, 140 insertions(+), 49 deletions(-) diff --git a/client/commonFramework.js b/client/commonFramework.js index fcb1ccc58d..01b81c7e98 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -849,15 +849,15 @@ common.init.push((function() { var nextStep = getNextStep($(stepClass)); $(this) .parent() - .addClass('animated fadeOutLeft') - .delay(700) + .addClass('animated fadeOutLeft fast-animation') + .delay(250) .queue(function(next) { $(this).addClass('hidden'); if (nextStep) { $(nextStep) .removeClass('hidden') - .addClass('animated slideInRight') - .delay(1000) + .addClass('animated slideInRight fast-animation') + .delay(500) .queue(function(next) { $(this).removeClass('slideInRight'); next(); diff --git a/seed/challenges/basejumps.json b/seed/challenges/basejumps.json index c0dc0a0ba3..d003b1b5bd 100644 --- a/seed/challenges/basejumps.json +++ b/seed/challenges/basejumps.json @@ -2,6 +2,136 @@ "name": "Full Stack JavaScript Projects", "order": 20, "challenges": [ + { + "id": "560add65cb82ac38a17513c1", + "title": "", + "challengeSeed": [], + "description": [ + [ + "", + "", + "", + "" + ], + [ + "", + "", + "Create an app from this github url: https://github.com/johnstonbl01/clementinejs-fcc.git", + "" + ], + [ + "", + "", + "Create a new GitHub app.", + "https://github.com/settings/applications/new" + ], + [ + "", + "", + "Return to c9.io, click the gear and click \"Show Hidden Files\"", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ], + [ + "", + "", + "", + "" + ] + ], + "type": "Waypoint", + "challengeType": 7, + "tests": [], + "nameCn": "", + "descriptionCn": [], + "nameFr": "", + "descriptionFr": [], + "nameRu": "", + "descriptionRu": [], + "nameEs": "", + "descriptionEs": [], + "namePt": "", + "descriptionPt": [] + }, + + { "id": "bd7158d8c443eddfaeb5bcef", "title": "Get Set for Basejumps", diff --git a/seed/challenges/front-end-development-certificate.json b/seed/challenges/front-end-development-certificate.json index 351809e702..65b98018c6 100644 --- a/seed/challenges/front-end-development-certificate.json +++ b/seed/challenges/front-end-development-certificate.json @@ -14,7 +14,7 @@ ], "description": [ [ - "http://i.imgur.com/luMkKst.jpg", + "http://i.imgur.com/syJxavV.jpg", "An image of our Front End Development Certificate", "This challenge will give you your verified Front End Development Certificate. Before we issue your certificate, we must verify that you have completed all of our basic and intermediate Bonfires, and all our basic and intermediate Ziplines. You must also accept our Academic Honesty Pledge. Click the button below to start this process.", "" diff --git a/seed/challenges/full-stack-development-certificate.json b/seed/challenges/full-stack-development-certificate.json index 7ae95c94e7..d383fc5a0f 100644 --- a/seed/challenges/full-stack-development-certificate.json +++ b/seed/challenges/full-stack-development-certificate.json @@ -15,7 +15,7 @@ ], "description": [ [ - "http://i.imgur.com/qXublEe.jpg", + "http://i.imgur.com/sKYQhdG.jpg", "An image of our Full Stack Development Certificate", "This challenge will give you your verified Full Stack Development Certificate. Before we issue your certificate, we must verify that you have completed all of Bonfires, Ziplines and Basejumps. You must also accept our Academic Honesty Pledge. Click the button below to start this process.", "" diff --git a/seed/challenges/getting-started.json b/seed/challenges/getting-started.json index c35c3541f8..bd4a752c84 100644 --- a/seed/challenges/getting-started.json +++ b/seed/challenges/getting-started.json @@ -32,7 +32,7 @@ "" ], [ - "http://i.imgur.com/q4IjuCL.jpg", + "http://i.imgur.com/sKYQhdG.jpg", "a screenshot of our Front End Development Certificate", "About half way through our curriculum, you'll earn a verified Front End Development Certificate. If you can finish our entire curriculum, you'll earn a verified Full Stack Development Certificate.", "" @@ -164,38 +164,6 @@ "namePt": "", "descriptionPt": [] }, - { - "id": "560add65cb82ac38a17513c1", - "title": "Try our Wiki and Camper News", - "challengeSeed": [], - "description": [ - [ - "http://i.imgur.com/DoOqkNW.gif", - "A gif showing how you can click the \"Wiki\" button in your upper-right corner to access the wiki.", - "Try this: Click the \"Wiki\" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki.", - "" - ], - [ - "http://i.imgur.com/nmSiMy1.gif", - "A gif showing how you can access our Camper News page and click the \"upvote\" button to upvote a story.", - "Click the \"News\" button in your upper right hand corner. You can browse links on Camper News and upvote ones that you enjoy.", - "" - ] - ], - "type": "Waypoint", - "challengeType": 7, - "tests": [], - "nameCn": "", - "descriptionCn": [], - "nameFr": "", - "descriptionFr": [], - "nameRu": "", - "descriptionRu": [], - "nameEs": "", - "descriptionEs": [], - "namePt": "", - "descriptionPt": [] - }, { "id": "560add71cb82ac38a17513c2", "title": "Join a Campsite in Your City", @@ -230,7 +198,7 @@ }, { "id": "560add8ccb82ac38a17513c3", - "title": "Join our Alumni Network and Commit to Your Goal", + "title": "Join our Alumni Network on LinkedIn", "challengeSeed": [], "description": [ [ @@ -238,12 +206,6 @@ "A gif showing how you can click the link below and fill in the necessary fields to add your Free Code Camp studies to your LinkedIn profile.", "You can add Free Code Camp to your LinkedIn education background. Set your graduation date as next year. For \"Degree\", type \"Full Stack Web Development\". For \"Field of study\", type \"Computer Software Engineering\". Then click \"Save Changes\".", "https://www.linkedin.com/profile/edit-education?school=Free+Code+Camp" - ], - [ - "", - "", - "Free Code Camp will always be free. If you want to feel more motivated to earn our certificates faster, we encourage you to instead donate each month to a nonprofit.", - "" ] ], "type": "Waypoint", diff --git a/server/views/coursewares/showStep.jade b/server/views/coursewares/showStep.jade index fa8f11431a..fb375a83d3 100644 --- a/server/views/coursewares/showStep.jade +++ b/server/views/coursewares/showStep.jade @@ -2,14 +2,13 @@ extends ../layout-wide block content .row .col-md-8.col-md-offset-2 - .jumbotron for step, index in description .thumbnail.challenge-step(class=index !== 0 ? 'hidden': '') img.gif-block.img-center.img-responsive.thumbnail(src='#{step[0]}' alt='#{step[1]}') .caption p.large-p= step[2] if step[3] - a.btn.btn-block.btn-primary.challenge-step-btn-action(id='#{index}' href='#{step[3]}' target='_blank') Go To Link + a.btn.btn-block.btn-primary.challenge-step-btn-action(id='#{index}' href='#{step[3]}' target='_blank') Open link in new tab if index + 1 === description.length .btn.btn-block.btn-primary.challenge-step-btn-finish(id='last' class=step[3] ? 'disabled' : '') Finish challenge else @@ -27,7 +26,7 @@ block content .spacer .row if (user) - #challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter) + #challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge else a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge script(src=rev('/js', 'commonFramework.js')) From 91708a33162e3cd2b4c2c0da164c14b74f2e3afa Mon Sep 17 00:00:00 2001 From: Logan Tegman Date: Mon, 5 Oct 2015 22:50:09 -0700 Subject: [PATCH 027/592] Fix Waypoint: Find White Space Explaination Changed text description to make it clear that `\s` is used to find all types of whitespace characters, not just `" "`. Closes #2838 --- seed/challenges/basic-javascript.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index 13c28c2021..213a5f745e 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -1081,10 +1081,11 @@ "title": "Find White Space with Regular Expressions", "difficulty":"9.986", "description":[ - "We can also use selectors like \\s to find spaces in a string.", + "We can also use selectors like \\s to find white space in a string.", + "The white space characters are \" \" (space), \\r (carriage return), \\n (newline), \\t (tab), \\f (form feed).", "It is used like this:", "/\\s+/g", - "Select all the spaces in the sentence string." + "Select all the white space characters in the sentence string." ], "tests":[ "assert(test === 7, 'Your RegEx should have found seven spaces in the testString.');", From 7a31cdd9224fed8b4fe84f1ffdb7594e3f599979 Mon Sep 17 00:00:00 2001 From: ahstro Date: Tue, 6 Oct 2015 10:27:29 +0200 Subject: [PATCH 028/592] 'Regular Expressions'-waypoint improvements * Remove unnecessary `i`-flag from tests and test messages, e.g. `/\s+/gi` => `/\s+/g` * Remove dupliate backslashes from regex test messages, e.g. `/\\s+/g` => `/\s+/g` The two backslashes were probably just an accident caused by how multiple escapes are necessary with the current way tests are handled. The `i`-flag was just unnecessary since its purpose is to ignore the case of alphabetic characters. --- seed/challenges/basic-javascript.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index c10af0def1..82a0430852 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -1039,7 +1039,7 @@ ], "tests":[ "assert(test === 2, 'message: Your RegEx should have found two numbers in the testString.');", - "assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'message: You should be using the following expression /\\\\d+/gi to find the numbers in the testString.');" + "assert(editor.getValue().match(/\\/\\\\d\\+\\//g), 'message: You should be using the following expression /\\d+/g to find the numbers in the testString.');" ], "challengeSeed":[ "var test = (function() {", @@ -1047,7 +1047,7 @@ "", " // Only change code below this line.", "", - " var expression = /.+/gi;", + " var expression = /.+/g;", "", " // Only change code above this line.", " // We use this function to show you the value of your variable in your output box.", @@ -1069,7 +1069,7 @@ ], "tests":[ "assert(test === 7, 'message: Your RegEx should have found seven spaces in the testString.');", - "assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'message: You should be using the following expression /\\\\s+/gi to find the spaces in the testString.');" + "assert(editor.getValue().match(/\\/\\\\s\\+\\//g), 'message: You should be using the following expression /\\s+/g to find the spaces in the testString.');" ], "challengeSeed":[ "var test = (function(){", @@ -1077,7 +1077,7 @@ "", " // Only change code below this line.", "", - " var expression = /.+/gi;", + " var expression = /.+/g;", "", " // Only change code above this line.", " // We use this function to show you the value of your variable in your output box.", @@ -1092,12 +1092,12 @@ "title": "Invert Regular Expression Matches with JavaScript", "difficulty":"9.987", "description":[ - "Use /\\S/gi to match everything that isn't a space in the string.", + "Use /\\S/g to match everything that isn't a space in the string.", "You can invert any match by using the uppercase version of the selector \\s versus \\S for example." ], "tests":[ "assert(test === 49, 'message: Your RegEx should have found forty nine non-space characters in the testString.');", - "assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'message: You should be using the following expression /\\\\S/gi to find non-space characters in the testString.');" + "assert(editor.getValue().match(/\\/\\\\S\\/g/g), 'message: You should be using the following expression /\\S/g to find non-space characters in the testString.');" ], "challengeSeed":[ "var test = (function(){", @@ -1105,7 +1105,7 @@ "", " // Only change code below this line.", "", - " var expression = /./gi;", + " var expression = /./g;", "", " // Only change code above this line.", " // We use this function to show you the value of your variable in your output box.", From a17687116e9b7bad14dee5c66aae7d5e19836122 Mon Sep 17 00:00:00 2001 From: Logan Tegman Date: Tue, 6 Oct 2015 08:45:21 -0700 Subject: [PATCH 029/592] Fix Waypoint: Find Whitespace spelling and grammar. --- seed/challenges/basic-javascript.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json index 213a5f745e..47790e5e0e 100644 --- a/seed/challenges/basic-javascript.json +++ b/seed/challenges/basic-javascript.json @@ -1078,14 +1078,14 @@ }, { "id":"cf1111c1c12feddfaeb8bdef", - "title": "Find White Space with Regular Expressions", + "title": "Find Whitespace with Regular Expressions", "difficulty":"9.986", "description":[ - "We can also use selectors like \\s to find white space in a string.", - "The white space characters are \" \" (space), \\r (carriage return), \\n (newline), \\t (tab), \\f (form feed).", + "We can also use selectors like \\s to find whitespace in a string.", + "The whitespace characters are \" \" (space), \\r (carriage return), \\n (newline), \\t (tab), and \\f (form feed).", "It is used like this:", "/\\s+/g", - "Select all the white space characters in the sentence string." + "Select all the whitespace characters in the sentence string." ], "tests":[ "assert(test === 7, 'Your RegEx should have found seven spaces in the testString.');", From 9f298cbe9409dbd49b427bb0a1855fd3b0df1930 Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Tue, 6 Oct 2015 21:47:29 +0100 Subject: [PATCH 030/592] Fixed tests --- seed/challenges/json-apis-and-ajax.json | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index 9ea8bfd0e8..de5feb033c 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -10,19 +10,18 @@ "", "JSON is a way of creating a file or a db record from a javascript object.", "JSON works in the exact same way as javascript objects that you should be familiar with.", - "" + "Lets add a string property to out object." ], "tests": [ - "assert(typeof json !== 'undefined')" + "assert(typeof json !== 'undefined' && Object.keys(json).length === 3 && typeof(json[Object.keys(json)[Object.keys(json).length-1]]) === 'string', 'message: You should have added a string value to your object.')" ], "challengeSeed": [ "var json = {", - " name: \"Happy Camper\"", - " age: 35", - " height: \"5ft 8\"", + " \"name\": \"Happy Camper\"", + " \"height\": \"160cm\"", "}" ], - "challengeType": 0, + "challengeType": 1, "type": "waypoint" }, { @@ -158,8 +157,8 @@ "" ], "tests": [ - "assert($(\".message\").html() !== '', 'The message box should have something in it')" - ], + "assert(/json\\.map/gi, 'The message box should have something in it')" + ], "challengeSeed": [ "fccss", " $(document).ready(function() {", From a6789b8511eca45f46e00393002b7231631a9c37 Mon Sep 17 00:00:00 2001 From: Gaurav Saxena Date: Tue, 6 Oct 2015 17:30:27 -0400 Subject: [PATCH 031/592] renamed -you- to -your- ; fixes #3607 - grammar bug --- seed/challenges/object-oriented-and-functional-programming.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json index 2d8c22f32d..2da91ee5a6 100644 --- a/seed/challenges/object-oriented-and-functional-programming.json +++ b/seed/challenges/object-oriented-and-functional-programming.json @@ -212,7 +212,7 @@ "});" ], "tests":[ - "assert(singleVal == 30, 'message: singleVal should have been set to the result of you reduce operation.');", + "assert(singleVal == 30, 'message: singleVal should have been set to the result of your reduce operation.');", "assert(editor.getValue().match(/\\.reduce\\(/gi), 'message: You should have made use of the reduce method.');" ], "challengeSeed":[ From a27aa2d9f62e373b689684724a17a485df1139f2 Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Tue, 6 Oct 2015 22:54:20 +0100 Subject: [PATCH 032/592] More test and copy fixes. Removed weird bugged challenge --- seed/challenges/json-apis-and-ajax.json | 64 ++++++++----------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index de5feb033c..c522e2441b 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -2,45 +2,23 @@ "name": "JSON APIs and Ajax", "order": 0.0065, "challenges": [ - { - "id": "bb000000000000000000000", - "title": "Understanding JSON", - "difficulty": 3.19, - "description": [ - "", - "JSON is a way of creating a file or a db record from a javascript object.", - "JSON works in the exact same way as javascript objects that you should be familiar with.", - "Lets add a string property to out object." - ], - "tests": [ - "assert(typeof json !== 'undefined' && Object.keys(json).length === 3 && typeof(json[Object.keys(json)[Object.keys(json).length-1]]) === 'string', 'message: You should have added a string value to your object.')" - ], - "challengeSeed": [ - "var json = {", - " \"name\": \"Happy Camper\"", - " \"height\": \"160cm\"", - "}" - ], - "challengeType": 1, - "type": "waypoint" - }, { "id": "bb000000000000000000001", "title": "Trigger on click Events with jQuery", "difficulty": 3.19, "description": [ - "With jQuery we are able to get data from APIs via Ajax", - "This data normally comes in the form of JSON", - "Let's get the Get Message button to set the text of a div", - "We will later use this to display the result of out API request", + "With jQuery we are able to get data from APIs via Ajax.", + "This data normally comes in the form of JSON.", + "Let's get the Get Message button to set the text of a div.", + "We will later use this to display the result of out API request.", "$(\"#getMessage\").on(\"click\", function(){", "  $(\".message\").html(\"Here is the message\");", "});" ], "tests": [ - "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\#getMessage(?:'|\")\\s*?\\)\\s*?\\.on\\s*?\\(\\s*?(?:'|\")click(?:'|\")\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have bound the click event to the getMessage button')", - "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\.message(?:'|\")\\s*?\\)\\s*?\\.html\\s*?\\(\\s*?(?:'|\")Here\\sis\\sthe\\smessage(?:'|\")\\s*?\\);/gi), 'You should set te value of the #message box to be the message given in the description')", - "assert(editor.match(/\\n*?\\s*?\\}\\n*?\\s*?\\);/gi) && editor.match(/\\n*?\\s*?\\}\\);/gi).length >= 2, 'Make sure that you close off all of your functions')" + "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\#getMessage(?:'|\")\\s*?\\)\\s*?\\.on\\s*?\\(\\s*?(?:'|\")click(?:'|\")\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have bound the click event to the getMessage button.')", + "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\.message(?:'|\")\\s*?\\)\\s*?\\.html\\s*?\\(\\s*?(?:'|\")Here\\sis\\sthe\\smessage(?:'|\")\\s*?\\);/gi), 'You should set te value of the #message box to be the message given in the description.')", + "assert(editor.match(/\\n*?\\s*?\\}\\n*?\\s*?\\);/gi) && editor.match(/\\n*?\\s*?\\}\\);/gi).length >= 2, 'Make sure that you close off all of your functions.')" ], "challengeSeed": [ "fccss", @@ -87,15 +65,15 @@ "    $(\".message\").html(JSON.stringify(json))", "  });", "});
      ", - "Let's make it so that the data sent from the request is appended to the .message div", + "Let's make it so that the data sent from the request is appended to the .message div.", "" ], "tests": [ - "assert(editor.match(/\\$\\s*?\\(\\s*?(\\\"|\\')\\#getMessage(\\\"|\\')\\s*?\\)\\s*?\\.\\s*?on\\s*?\\(\\s*?(\\\"|\\')click(\\\"|\\')\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have a click handler on the getMessage button to trigger the AJAX request')", - "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi), 'You should have at least on closing set of brackets and parenthesis')", - "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi) && editor.match(/\\,\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi) && editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi).length === editor.match(/\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi).length, 'Each callback function should have a closing set of brackets and parenthesis')", - "assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?\"\\\/json\\\/cats\\.json\\?callback\\=\"\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file')", - "assert(editor.match(/\\$\\s*?\\(\\s*?\\\"\\.message\\\"\\s*?\\)\\s*?\\.\\s*?html\\s*?\\(\\s*?JSON\\s*?\\.\\s*?stringify\\s*?\\(\\s*?json\\s*?\\)\\s*?\\)/gi), 'Don\\'t forget to make the .html change the contents of the message box so that it contains the result of the getJSON')" + "assert(editor.match(/\\$\\s*?\\(\\s*?(\\\"|\\')\\#getMessage(\\\"|\\')\\s*?\\)\\s*?\\.\\s*?on\\s*?\\(\\s*?(\\\"|\\')click(\\\"|\\')\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have a click handler on the getMessage button to trigger the AJAX request.')", + "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi), 'You should have at least on closing set of brackets and parenthesis.')", + "assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi) && editor.match(/\\,\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi) && editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi).length === editor.match(/\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi).length, 'Each callback function should have a closing set of brackets and parenthesis.')", + "assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?\"\\\/json\\\/cats\\.json\\?callback\\=\"\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file.')", + "assert(editor.match(/\\$\\s*?\\(\\s*?\\\"\\.message\\\"\\s*?\\)\\s*?\\.\\s*?html\\s*?\\(\\s*?JSON\\s*?\\.\\s*?stringify\\s*?\\(\\s*?json\\s*?\\)\\s*?\\)/gi), 'Don\\'t forget to make the .html change the contents of the message box so that it contains the result of the getJSON.')" ], "challengeSeed": [ "fccss", @@ -139,7 +117,7 @@ "difficulty": 3.21, "description": [ "", - "Now that we have the data let's re-arrange it so that ", + "Now that we have the data let's re-arrange it so that it can be displayed in a user friendly way.", "", "", "  json.map(function(val){", @@ -157,7 +135,7 @@ "" ], "tests": [ - "assert(/json\\.map/gi, 'The message box should have something in it')" + "assert(/json\\.map/gi, 'The message box should have something in it.')" ], "challengeSeed": [ "fccss", @@ -215,7 +193,7 @@ "description": [ "", "instead of just placing everything in a div we should check if the value is an image.", - "If it is an image we should use it as an ima tag instead so that the image is rendered", + "If it is an image we should use it as an ima tag instead so that the image is rendered.", "", "if(key === \"imageLink\"){", "html = html + '<img class = \"' + key + '\"src = \"' + val[key] + '\">';", @@ -227,7 +205,7 @@ "" ], "tests": [ - "assert(editor.match(/imageLink/gi), 'You should have accessed the imageLink of each cat object')" + "assert(editor.match(/imageLink/gi), 'You should have accessed the imageLink of each cat object.')" ], "challengeSeed": [ "fccss", @@ -303,8 +281,8 @@ "description": [ "", "This means we should never hit API limits and it will make the process more efficient.", - "Let's try pre-filtering the json before we map it", - "We can use the pre-made filter method like this to remove the cat with the id of 1", + "Let's try pre-filtering the json before we map it.", + "We can use the pre-made filter method like this to remove the cat with the id of 1.", "", "json = json.filter(function(val){", " return(val.id !== 1);", @@ -313,7 +291,7 @@ "" ], "tests": [ - "assert(editor.match(/filter/gi), 'You should be making use of the .filter method')" + "assert(editor.match(/filter/gi), 'You should be making use of the .filter method.')" ], "challengeSeed": [ "fccss", @@ -405,7 +383,7 @@ "" ], "tests": [ - "assert(editor.match(/navigator\\.geolocation\\.getCurrentPosition/gi), 'you should make use of the navigator.geolocation to access the users current location')" + "assert(editor.match(/navigator\\.geolocation\\.getCurrentPosition/gi), 'you should make use of the navigator.geolocation to access the users current location.')" ], "challengeSeed": [ "fccss", From 56b7b6f29bd8979f3e7cab5b3419ba8e2752b18a Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 6 Oct 2015 15:37:43 -0700 Subject: [PATCH 033/592] improve markup and titles of challenges --- seed/challenges/json-apis-and-ajax.json | 145 ++++++++---------------- 1 file changed, 46 insertions(+), 99 deletions(-) diff --git a/seed/challenges/json-apis-and-ajax.json b/seed/challenges/json-apis-and-ajax.json index c522e2441b..1148756772 100644 --- a/seed/challenges/json-apis-and-ajax.json +++ b/seed/challenges/json-apis-and-ajax.json @@ -5,11 +5,10 @@ { "id": "bb000000000000000000001", "title": "Trigger on click Events with jQuery", - "difficulty": 3.19, "description": [ "With jQuery we are able to get data from APIs via Ajax.", - "This data normally comes in the form of JSON.", - "Let's get the Get Message button to set the text of a div.", + "This data normally comes in the form of JSON.", + "Let's get the Get Message button to set the text of a div element.", "We will later use this to display the result of out API request.", "$(\"#getMessage\").on(\"click\", function(){", "  $(\".message\").html(\"Here is the message\");", @@ -33,13 +32,11 @@ "
      ", "

      Cat Photo Finder

      ", "
      ", - "
      ", "
      ", "
      ", " The message will go here", "
      ", "
      ", - "
      ", "
      ", "
      ", "
      \"", "", " });", " ", - " //Don't modify above here", - " ", "     $(\".message\").html(html);", " ", "   });", @@ -248,19 +214,15 @@ " });", "fcces", "", - "", - "", "
      ", "
      ", "

      Cat Photo Finder

      ", "
      ", - "
      ", "
      ", "
      ", " The message will go here", "
      ", "
      ", - "
      ", "
      ", "
      ", "
      \"", "", " });", " ", - " //Don't modify above here", - " ", "     $(\".message\").html(html);", " ", "   });", @@ -337,19 +293,16 @@ " });", "fcces", "", - "", "", "
      ", "
      ", "

      Cat Photo Finder

      ", "
      ", - "
      ", "
      ", "
      ", " The message will go here", "
      ", "
      ", - "
      ", "
      ", "
      ", " + +
      + + + + + +
      +

      Tell us about the position

      Date: Wed, 4 Nov 2015 14:23:42 -0800 Subject: [PATCH 349/592] Add logic to cert buttons --- common/app/routes/Jobs/components/NewJob.jsx | 28 +++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index 6dce6817c0..9697e420c4 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -114,7 +114,7 @@ export default contain({ url, logo, company, - isFrontEndCert, + isFrontEndCert = true, isFullStackCert, isHighlighted, isRemoteOk, @@ -171,7 +171,7 @@ export default contain({ } }); - if (!valid) { + if (!valid || !props.isFrontEndCert && !props.isFullStackCert ) { debug('form not valid'); return; } @@ -234,6 +234,18 @@ export default contain({ handleForm({ [name]: value }); }, + handleCertClick(name) { + const { jobActions: { handleForm } } = this.props; + const otherButton = name === 'isFrontEndCert' ? + 'isFullStackCert' : + 'isFrontEndCert'; + + handleForm({ + [name]: true, + [otherButton]: false + }); + }, + render() { const { position, @@ -275,7 +287,11 @@ export default contain({ xs={ 6 } xsOffset={ 3 }> - @@ -305,9 +307,11 @@ export default contain({ - ); - } - return null; - }, - - render: function() { - var isDescription = this.props.description && - this.props.description.length > 1; - - return ( -
      -

      { this.props.name }

      -

      -
      - Difficulty:  - { this._renderFlames() } -
      -

      - - - -
      -

      { this.props.brief }

      -
      - { this._renderMoreInfo(isDescription) } - { this._renderMoreInfoButton(isDescription) } -
      -
      - -
      -
      - -
      -
      - ); - } -}); - -module.exports = SidePanel; diff --git a/common/app/routes/Bonfires/executeBonfire.js b/common/app/routes/Bonfires/executeBonfire.js deleted file mode 100644 index 0d1795894a..0000000000 --- a/common/app/routes/Bonfires/executeBonfire.js +++ /dev/null @@ -1,27 +0,0 @@ -var debug = require('debug')('freecc:executebonfire'); -var { - addTests, - runTests, - testCode -} = require('../../utils'); - -module.exports = executeBonfire; - -function executeBonfire(userCode, tests, cb) { - - // TODO: move this into componentDidMount - // ga('send', 'event', 'Bonfire', 'ran-code', bonfireName); - var testSalt = Math.random(); - var { preppedCode, userTests } = addTests(userCode, tests, testSalt); - - debug('sending code to web worker for testing'); - testCode(preppedCode, function(err, data) { - if (err) { return cb(err); } - var results = runTests(userTests, data, testSalt); - debug('testing complete', results); - cb(null, { - output: data.output, - results - }); - }); -} diff --git a/common/app/routes/Bonfires/index.js b/common/app/routes/Bonfires/index.js deleted file mode 100644 index ec633552eb..0000000000 --- a/common/app/routes/Bonfires/index.js +++ /dev/null @@ -1,8 +0,0 @@ -/* -export default { - path: 'bonfires/(:bonfireName)' - getComponents(cb) { - // TODO(berks): add bonfire component - } -}; -*/ diff --git a/common/app/routes/Jobs/components/JobNotFound.jsx b/common/app/routes/Jobs/components/JobNotFound.jsx index b921dfd4dc..c4981d22f8 100644 --- a/common/app/routes/Jobs/components/JobNotFound.jsx +++ b/common/app/routes/Jobs/components/JobNotFound.jsx @@ -1,8 +1,8 @@ -import React, { createClass } from 'react'; +import React from 'react'; import { LinkContainer } from 'react-router-bootstrap'; import { Button, Row, Col, Panel } from 'react-bootstrap'; -export default createClass({ +export default React.createClass({ displayName: 'NoJobFound', render() { diff --git a/common/app/routes/Jobs/components/NewJob.jsx b/common/app/routes/Jobs/components/NewJob.jsx index 661ea70367..2d0bd08937 100644 --- a/common/app/routes/Jobs/components/NewJob.jsx +++ b/common/app/routes/Jobs/components/NewJob.jsx @@ -162,16 +162,16 @@ export default contain({ handleSubmit(e) { e.preventDefault(); - const props = this.props; + const pros = this.props; let valid = true; checkValidity.forEach((prop) => { // if value exist, check if it is valid - if (props[prop].value && props[prop].type !== 'boolean') { - valid = valid && !!props[prop].valid; + if (pros[prop].value && pros[prop].type !== 'boolean') { + valid = valid && !!pros[prop].valid; } }); - if (!valid || !props.isFrontEndCert && !props.isFullStackCert ) { + if (!valid || !pros.isFrontEndCert && !pros.isFullStackCert ) { debug('form not valid'); return; } diff --git a/common/app/routes/Jobs/components/TwitterBtn.jsx b/common/app/routes/Jobs/components/TwitterBtn.jsx index fb5f8edf12..7998353ffc 100644 --- a/common/app/routes/Jobs/components/TwitterBtn.jsx +++ b/common/app/routes/Jobs/components/TwitterBtn.jsx @@ -1,4 +1,4 @@ -import React, { createClass, PropTypes } from 'react'; +import React, { PropTypes } from 'react'; import { Button } from 'react-bootstrap'; const followLink = 'https://twitter.com/intent/follow?' + @@ -9,7 +9,7 @@ function commify(count) { return Number(count).toLocaleString('en'); } -export default createClass({ +export default React.createClass({ displayName: 'FollowButton', diff --git a/common/app/shared/displayCode/Display.jsx b/common/app/shared/displayCode/Display.jsx deleted file mode 100644 index 9eb60db8da..0000000000 --- a/common/app/shared/displayCode/Display.jsx +++ /dev/null @@ -1,51 +0,0 @@ -var React = require('react'), - Tailspin = require('tailspin'); - -var Editor = React.createClass({ - - propTypes: { - value: React.PropTypes.string - }, - - getDefaultProps: function() { - return { - value: [ - '/**', - '* Your output will go here.', - '* Console.log() -type statements', - '* will appear in your browser\'s', - '* DevTools JavaScript console.', - '**/' - ].join('\n') - }; - }, - - render: function() { - var value = this.props.value; - var options = { - lineNumbers: false, - lineWrapping: true, - mode: 'text', - readOnly: 'noCursor', - textAreaClassName: 'hide-textarea', - theme: 'monokai', - value: value - }; - - var config = { - setSize: ['100%', '100%'] - }; - - return ( -
      -
      - -
      -
      - ); - } -}); - -module.exports = Editor; diff --git a/common/app/shared/displayCode/index.js b/common/app/shared/displayCode/index.js deleted file mode 100644 index d3e3560174..0000000000 --- a/common/app/shared/displayCode/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./Display.jsx'); diff --git a/common/app/shared/editor/Editor.jsx b/common/app/shared/editor/Editor.jsx deleted file mode 100644 index 8e72f5d4a0..0000000000 --- a/common/app/shared/editor/Editor.jsx +++ /dev/null @@ -1,91 +0,0 @@ -var React = require('react'), - debug = require('debug')('freecc:comp:editor'), - jshint = require('jshint').JSHINT, - Tailspin = require('tailspin'); - -var Editor = React.createClass({ - - propTypes: { - onValueChange: React.PropTypes.func, - value: React.PropTypes.string - }, - - getDefaultProps: function() { - return { - value: 'console.log(\'freeCodeCamp is awesome\')' - }; - }, - - getInitialState: function() { - return { - value: this.props.value - }; - }, - - render: function() { - var options = { - autoCloseBrackets: true, - gutters: ['CodeMirror-lint-markers'], - lint: true, - linter: jshint, - lineNumbers: true, - lineWrapping: true, - mode: 'javascript', - matchBrackets: true, - runnable: true, - scrollbarStyle: 'null', - theme: 'monokai', - textAreaClassName: 'hide-textarea', - value: this.state.value, - onChange: e => { - this.setState({ value: e.target.value}); - if (typeof this.props.onValueChange === 'function') { - this.props.onValueChange(e.target.value); - } - } - }; - - var config = { - setSize: ['100%', 'auto'], - extraKeys: { - Tab: function(cm) { - debug('tab pressed'); - if (cm.somethingSelected()) { - cm.indentSelection('add'); - } else { - var spaces = new Array(cm.getOption('indentUnit') + 1).join(' '); - cm.replaceSelection(spaces); - } - }, - 'Shift-Tab': function(cm) { - debug('shift-tab pressed'); - if (cm.somethingSelected()) { - cm.indentSelection('subtract'); - } else { - var spaces = new Array(cm.getOption('indentUnit') + 1).join(' '); - cm.replaceSelection(spaces); - } - }, - 'Ctrl-Enter': function() { - debug('C-enter pressed'); - // execute bonfire action - return false; - } - } - }; - - return ( -
      -
      -
      - -
      -
      -
      - ); - } -}); - -module.exports = Editor; diff --git a/common/app/shared/editor/index.js b/common/app/shared/editor/index.js deleted file mode 100644 index 5e431fabff..0000000000 --- a/common/app/shared/editor/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./Editor.jsx'); diff --git a/package.json b/package.json index ef06329143..4e36abf74f 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "lint-server": "jsonlint -q server/*.json", "lint-resources": "jsonlint -q server/resources/*.json", "lint-utils": "jsonlint -q server/utils/*.json", - "lint-js": "eslint --ext=.js,.jsx server/ common/models common/utils config/", + "lint-js": "eslint --ext=.js,.jsx server/ common/ common/utils config/ client/", "lint-json": "npm run lint-server && npm run lint-nonprofits && npm run lint-challenges && npm run lint-resources && npm run lint-utils", "test-challenges": "babel-node seed/test-challenges.js | tnyan", "pretest": "npm run lint", From 085fc2fe72cc8085292cb47a4c2b8bedce009d42 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 5 Nov 2015 16:41:19 -0800 Subject: [PATCH 357/592] Fix loopback explorer issue --- package.json | 3 ++- server/boot/explorer.js | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 75db855279..537afc32fd 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "lodash": "^3.9.3", "loopback": "^2.22.0", "loopback-boot": "^2.13.0", + "loopback-component-explorer": "^2.1.1", "loopback-component-passport": "https://github.com/FreeCodeCamp/loopback-component-passport.git#feature/flashfailure", "loopback-connector-mongodb": "^1.10.0", "lusca": "~1.3.0", @@ -137,7 +138,7 @@ "envify": "^3.4.0", "istanbul": "^0.4.0", "jsonlint": "^1.6.2", - "loopback-explorer": "^2.0.2", + "loopback-component-explorer": "^2.1.1", "loopback-testing": "^1.1.0", "mocha": "~2.3.3", "multiline": "~1.0.1", diff --git a/server/boot/explorer.js b/server/boot/explorer.js index 955b23573d..4480abecc7 100644 --- a/server/boot/explorer.js +++ b/server/boot/explorer.js @@ -4,27 +4,26 @@ module.exports = function mountLoopBackExplorer(app) { } var explorer; try { - explorer = require('loopback-explorer'); + explorer = require('loopback-component-explorer'); } catch (err) { // Print the message only when the app was started via `app.listen()`. // Do not print any message when the project is used as a component. app.once('started', function() { console.log( - 'Run `npm install loopback-explorer` to enable the LoopBack explorer' + 'Run `npm install loopback-component-explorer` to enable ' + + 'the LoopBack explorer' ); }); return; } var restApiRoot = app.get('restApiRoot'); + var mountPath = '/explorer'; - var explorerApp = explorer(app, { basePath: restApiRoot }); - app.use('/explorer', explorerApp); + explorer(app, { basePath: restApiRoot, mountPath }); app.once('started', function() { var baseUrl = app.get('url').replace(/\/$/, ''); - // express 4.x (loopback 2.x) uses `mountpath` - // express 3.x (loopback 1.x) uses `route` - var explorerPath = explorerApp.mountpath || explorerApp.route; - console.log('Browse your REST API at %s%s', baseUrl, explorerPath); + + console.log('Browse your REST API at %s%s', baseUrl, mountPath); }); }; From 00fcdc9bc17bf5068313d7cc8d807e9fa9f4713a Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Thu, 5 Nov 2015 17:06:13 -0800 Subject: [PATCH 358/592] Fix news username query should be case insensitive --- server/boot/story.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/server/boot/story.js b/server/boot/story.js index 58a4c53fc4..ff20a9cd62 100755 --- a/server/boot/story.js +++ b/server/boot/story.js @@ -105,27 +105,6 @@ module.exports = function(app) { ); } - function userStories({ body: { search = '' } = {} }, res, next) { - if (!search || typeof search !== 'string') { - return res.sendStatus(404); - } - - return app.dataSources.db.connector - .collection('story') - .find({ - 'author.username': search.replace('$', '') - }) - .toArray(function(err, items) { - if (err) { - return next(err); - } - if (items && items.length !== 0) { - return res.json(items.sort(sortByRank)); - } - return res.sendStatus(404); - }); - } - function hot(req, res) { return res.render('stories/index', { title: 'Top Stories on Camper News', @@ -225,6 +204,27 @@ module.exports = function(app) { ); } + function userStories({ body: { search = '' } = {} }, res, next) { + if (!search || typeof search !== 'string') { + return res.sendStatus(404); + } + + return app.dataSources.db.connector + .collection('story') + .find({ + 'author.username': search.toLowerCase().replace('$', '') + }) + .toArray(function(err, items) { + if (err) { + return next(err); + } + if (items && items.length !== 0) { + return res.json(items.sort(sortByRank)); + } + return res.sendStatus(404); + }); + } + function getStories({ body: { search = '' } = {} }, res, next) { if (!search || typeof search !== 'string') { return res.sendStatus(404); From deb9bce3da849f7fe3706910ba7a71d58bcc4caa Mon Sep 17 00:00:00 2001 From: SaintPeter Date: Thu, 5 Nov 2015 22:02:55 -0800 Subject: [PATCH 359/592] Fixes typo in Join Strings with Join Waypoint --- seed/challenges/object-oriented-and-functional-programming.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/object-oriented-and-functional-programming.json b/seed/challenges/object-oriented-and-functional-programming.json index 6a6a1599e3..85c5cdc94b 100644 --- a/seed/challenges/object-oriented-and-functional-programming.json +++ b/seed/challenges/object-oriented-and-functional-programming.json @@ -410,7 +410,7 @@ "title":"Join Strings with .join", "description":[ "We can use the join method to join each element of an array into a string separated by whatever delimiter you provide as an argument.", - "The following is an example of using join to join all of the elements of an array into a string with all the elements seperated by word `Na`:", + "The following is an example of using join to join all of the elements of an array into a string with all the elements separated by word `Na`:", "var joinMe = [\"Na \", \"Na \", \"Na \", \"Na \", \"Batman!\"];", "var joinedString = joinMe.join(\"Na \");", "console.log(joinedString);", From 172b28c664caeb24221071b806af56f69d1c0421 Mon Sep 17 00:00:00 2001 From: Rex Schrader Date: Fri, 6 Nov 2015 10:26:56 -0800 Subject: [PATCH 360/592] Truncate String - add test, solution --- seed/challenges/basic-bonfires.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 505b91fd5e..6171cb94e4 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -410,12 +410,14 @@ "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: truncate(\"Peter Piper picked a peck of pickled peppers\", 14) should return \"Peter Piper...\".');", "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2) should return \"A-tisket a-tasket A green and yellow basket\".');", - "assert(truncate(\"A-\", 1) === \"A...\", 'message: truncate(\"A-\", 1) should return \"A...\".');" + "assert(truncate(\"A-\", 1) === \"A...\", 'message: truncate(\"A-\", 1) should return \"A...\".');", + "assert(truncate(\"Abolutely Longer\", 2) === \"Ab...\", 'message: truncate(\"Absolutely Longer\", 2) should return \"Ab...\".');" ], "MDNlinks": [ "String.slice()" ], "solutions": [ + "function truncate(str, num) {\n if(str.length > num ) {\n if(num > 3) {\n return str.slice(0, num - 3) + '...';\n } else {\n return str.slice(0,num) + '...';\n }\n } \n return str;\n}" ], "type": "bonfire", "challengeType": 5, From ef560ddb3ebb8b8f76df78d77030b7ced87b45e4 Mon Sep 17 00:00:00 2001 From: Faizaan Date: Sat, 7 Nov 2015 05:50:04 +0530 Subject: [PATCH 361/592] fixes #4062 --- seed/challenges/basic-bonfires.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 6171cb94e4..33adc629ec 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -367,6 +367,9 @@ "tests": [ "assert(repeat(\"*\", 3) === \"***\", 'message: repeat(\"*\", 3) should return \"***\".');", "assert(repeat(\"abc\", 3) === \"abcabcabc\", 'message: repeat(\"abc\", 3) should return \"abcabcabc\".');", + "assert(repeat(\"abc\", 4) === \"abcabcabcabc\", 'message: repeat(\"abc\", 4) should return \"abcabcabcabc\".');", + "assert(repeat(\"abc\", 1) === \"abc\", 'message: repeat(\"abc\", 1) should return \"abc\".');", + "assert(repeat(\"*\", 8) === \"********\", 'message: repeat(\"fcc\", 8) should return \"********\".');", "assert(repeat(\"abc\", -2) === \"\", 'message: repeat(\"abc\", -2) should return \"\".');" ], "MDNlinks": [ From 5dbfbfcf574de448ac72aefbb30813c8539d0262 Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Fri, 6 Nov 2015 16:35:57 -0800 Subject: [PATCH 362/592] Add head/tail to challenge spec. Lint EVERYTHING! --- client/commonFramework.js | 52 +- client/main.js | 1054 ++++++++++--------- common/models/challenge.json | 10 + seed/challenges/basic-javascript.json | 11 +- server/boot/challenge.js | 23 +- server/views/coursewares/showBonfire.jade | 39 +- server/views/coursewares/showHTML.jade | 35 +- server/views/coursewares/showJS.jade | 33 +- server/views/coursewares/showStep.jade | 3 +- server/views/coursewares/showVideo.jade | 15 +- server/views/partials/challenge-footer.jade | 5 + server/views/partials/challenge-modals.jade | 4 - server/views/partials/scripts.jade | 1 - server/views/stories/hot-stories.jade | 3 - server/views/stories/submit-story.jade | 10 +- 15 files changed, 724 insertions(+), 574 deletions(-) create mode 100644 server/views/partials/challenge-footer.jade diff --git a/client/commonFramework.js b/client/commonFramework.js index acbe741d4b..613f644c65 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -7,23 +7,25 @@ var common = (function() { init: [] }; - common.challengeName = common.challengeName || window.challenge_Name ? - window.challenge_Name : - ''; + common.challengeName = common.challengeName || window.challenge_Name || ''; - common.challengeType = common.challengeType || window.challengeType ? - window.challengeType : - 0; + common.challengeType = common.challengeType || window.challengeType || 0; common.challengeId = common.challengeId || window.challenge_Id; - common.challengeSeed = common.challengeSeed || window.challengeSeed ? - window.challengeSeed : - []; + common.challengeSeed = common.challengeSeed || window.challengeSeed || []; - common.seed = common.challengeSeed.reduce(function(seed, line) { - return seed + line + '\n'; - }, ''); + common.head = common.head || ''; + common.tail = common.tail || ''; + + common.convertSeed = function(seedData) { + seedData = seedData || []; + return seedData.reduce(function(seed, line) { + return seed + line + '\n'; + }, ''); + }; + + common.seed = common.convertSeed(common.challengeSeed); common.replaceScriptTags = function replaceScriptTags(value) { return value @@ -482,7 +484,7 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) { }(window.CodeMirror, window.emmetCodeMirror, common)); -var tests = tests || []; +var tests = common.tests || []; var libraryIncludes = " - - - - - - - - - - -

      CodeMirror Accessibility

      - -
      -

      - CodeMirror does not currently fully support screen reader software. Since CodeMirror does not use contentEditable internally, an extra effort must be made to provide this accessibility. -

      - -

      Analysis of Current Functionality

      -

      - CodeMirror uses a hidden textarea to accept input events, track user selections, provide copy/paste, etc. This has the benefit of some native input working correctly, but since the textarea is not a mirror of the content being entered, other things do not work. -

      -

      - Using NVDA, a screen reader for Windows, this is the behavior seen today with version 3.15 downloaded from http://codemirror.net/: -

      -
        -
      • Text based input works, as the input is being added directly into the hidden textarea
      • -
      • Selection works some of the time, as it populates the textarea with the current selection. It fails when the selection is over 100 lines or 1000 characters. In this case it replaces the character with a - and marks cm.display.inaccurateSelection for cleanup later
      • -
      • Cursor movement does not work. This is because the textarea is usually left empty, cleared out on regular intervals
      • -
      • - Entering / exiting the editor does not work. Although you can generally tab into the editor without a mouse, leaving the editor is tricky and I've had to resort to mouse usage to do this. Compare the following behavior with the normal textarea at the bottom of the page. - - The tab button's behavior is overriden as you would expect with a code editor, which makes it hard to leave the field. Perhaps a key like escape could be used to blur the editor? - - Here are some recommendataions from WAI-ARIA 1.0 Authoring Practices - Expected keyboard interaction with a rich text editor: - -
        -Optionally, if the developer wishes to provide the ability to insert a tab into the document, it is recommended one of the following methods be used. - -Provide indent and outdent buttons in the menu. Keyboard shortcuts to the buttons should be Control+M for indent and Control+Shift+M for outdent. -Provide a button in the menu to toggle the use of Tab between the two modes. If this button is used, then Control+M is recommended as a keyboard shortcut to toggle the button. -
        - - Please comment with suggestions on how to deal with this. Send me a message at bgrinstead@mozilla.com or @bgrins if you have any ideas. -
      • -
      - -

      Possible Solution

      -

      - A solution involves resetting the input value to the current line when the cursor location moves with an empty selection. Then, by calling input.setSelectionRange(from.ch, to.ch) the actual selection location is being moved, and NVDA is able to detect the changes. This value must stay in the textarea long enough for the screenreader to detect the change, but has to be cleared out quick enough for the next cursor movement to be read properly. The quick clearing out could be made unnecessary by setting the value of the textarea to CodeMirror.getValue(), however this causes some major performance bottlenecks (see below). -

      -

      - In addition, we do not clip the selection at any maximum limit to ensure that the selection is always consistent in the actual textarea. -

      -

      - Still not fixed: Entering / exiting the editor is still buggy. -

      - - -

      Implementation Considerations

      -

      - I had hoped that this could be structured as a plugin, and could avoid touching the CodeMirror internals, but that proved to not be possible. That said, it avoids large modifications to the readInput and resetInput functions, and could easily be hidden behind a property. View the changes in codemirror-accessible.js. -

      -

      - This still needs to be tested with more advanced CodeMirror features, like atomic markers and linked documents, and with other screen readers. Please let me know if you'd be able to help with testing these features or can give feedback with different screen readers. -

      - -

      Performance Considerations

      -

      - The downside is that this could potentially slow things down. The selection was intentionally clipped with a low limit, and every time the selection changes, we need to set the textarea value to the current line of the CodeMirror. Performance on very long lines with CodeMirror are a known issue, and copying / selecting this data into a textarea is an extra step (though probably not significant compared to text measuring). -

      -

      - Originally, I was setting the textarea's value to the entire content (which seems to be best for the screenreader), but there is a major impact is caused by the computation of the selectionRange in this case. Textareas setSelectionRange method takes an absolute start and end value, while CodeMirror operates on individual lines. So we need to count from 0 to currently selected line and add the length of each line to arrive there. -

      - -

      Demos

      -

      - This is working in the demo below. Compare the first CodeMirror (with the fix applied), the second CodeMirror (using the original version), and a normal textarea (at the bottom). -

      -

      - You can also see a video of the three options here: -

      - -
      - - - - - - - - - - - -
      -
      -

      - -
      - makes it easier to debug and see what is going on -
      - -
      - -

      CodeMirror With Accessibility Fix direct link

      -
      - -
      - -
      - -

      CodeMirror Original direct link

      -
      - -
      - -

      Normal Textarea direct link

      -
      - -
      - - - \ No newline at end of file diff --git a/public/js/lib/codemirror-accessible/javascript.js b/public/js/lib/codemirror-accessible/javascript.js deleted file mode 100755 index 905e76d953..0000000000 --- a/public/js/lib/codemirror-accessible/javascript.js +++ /dev/null @@ -1,482 +0,0 @@ -// TODO actually recognize syntax of TypeScript constructs - - -var opts= function(config, parserConfig) { - var indentUnit = config.indentUnit; - var statementIndent = parserConfig.statementIndent; - var jsonMode = parserConfig.json; - var isTS = parserConfig.typescript; - - // Tokenizer - - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}; - - var jsKeywords = { - "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), - "function": kw("function"), "catch": kw("catch"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "typeof": operator, "instanceof": operator, - "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this") - }; - - // Extend the 'normal' keywords with the TypeScript language extensions - if (isTS) { - var type = {type: "variable", style: "variable-3"}; - var tsKeywords = { - // object-like things - "interface": kw("interface"), - "class": kw("class"), - "extends": kw("extends"), - "constructor": kw("constructor"), - - // scope modifiers - "public": kw("public"), - "private": kw("private"), - "protected": kw("protected"), - "static": kw("static"), - - "super": kw("super"), - - // types - "string": type, "number": type, "bool": type, "any": type - }; - - for (var attr in tsKeywords) { - jsKeywords[attr] = tsKeywords[attr]; - } - } - - return jsKeywords; - }(); - - var isOperatorChar = /[+\-*&%=<>!?|~^]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; - escaped = !escaped && next == "\\"; - } - return escaped; - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - - function jsTokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") - return chain(stream, state, jsTokenString(ch)); - else if (/[\[\]{}\(\),;\:\.]/.test(ch)) - return ret(ch); - else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } - else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } - else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, jsTokenComment); - } - else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } - else if (state.lastType == "operator" || state.lastType == "keyword c" || - /^[\[{}\(,;:]$/.test(state.lastType)) { - nextUntilUnescaped(stream, "/"); - stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla - return ret("regexp", "string-2"); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - } - else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - else { - stream.eatWhile(/[\w\$_]/); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.lastType != ".") ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - - function jsTokenString(quote) { - return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = jsTokenBase; - return ret("string", "string"); - }; - } - - function jsTokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true}; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function register(varname) { - function inList(list) { - for (var v = list; v; v = v.next) - if (v.name == varname) return true; - return false; - } - var state = cx.state; - if (state.context) { - cx.marked = "def"; - if (inList(state.localVars)) return; - state.localVars = {name: varname, next: state.localVars}; - } else { - if (inList(state.globalVars)) return; - state.globalVars = {name: varname, next: state.globalVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: {name: "arguments"}}; - function pushcontext() { - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - cx.state.localVars = defaultVars; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - function pushlex(type, info) { - var result = function() { - var state = cx.state, indent = state.indented; - if (state.lexical.type == "stat") indent = state.lexical.indented; - state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - return function(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(arguments.callee); - }; - } - - function statement(type) { - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), block, poplex); - if (type == ";") return cont(); - if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse); - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), - poplex, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - return expressionInner(type, false); - } - function expressionNoComma(type) { - return expressionInner(type, true); - } - function expressionInner(type, noComma) { - var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; - if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "function") return cont(functiondef); - if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); - if (type == "operator") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), commasep(expressionNoComma, "]"), poplex, maybeop); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeop); - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - function maybeexpressionNoComma(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expressionNoComma); - } - - function maybeoperatorComma(type, value) { - if (type == ",") return cont(expression); - return maybeoperatorNoComma(type, value, false); - } - function maybeoperatorNoComma(type, value, noComma) { - var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; - var expr = noComma == false ? expression : expressionNoComma; - if (type == "operator") { - if (/\+\+|--/.test(value)) return cont(me); - if (value == "?") return cont(expression, expect(":"), expr); - return cont(expr); - } - if (type == ";") return; - if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me); - if (type == ".") return cont(property, me); - if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); - } - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperatorComma, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type, value) { - if (type == "variable") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(getterSetter); - } else if (type == "number" || type == "string") { - cx.marked = type + " property"; - } - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma); - } - function getterSetter(type) { - if (type == ":") return cont(expression); - if (type != "variable") return cont(expect(":"), expression); - cx.marked = "property"; - return cont(functiondef); - } - function commasep(what, end) { - function proceed(type) { - if (type == ",") { - var lex = cx.state.lexical; - if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; - return cont(what, proceed); - } - if (type == end) return cont(); - return cont(expect(end)); - } - return function(type) { - if (type == end) return cont(); - else return pass(what, proceed); - }; - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function maybetype(type) { - if (type == ":") return cont(typedef); - return pass(); - } - function typedef(type) { - if (type == "variable"){cx.marked = "variable-3"; return cont();} - return pass(); - } - function vardef1(type, value) { - if (type == "variable") { - register(value); - return isTS ? cont(maybetype, vardef2) : cont(vardef2); - } - return pass(); - } - function vardef2(type, value) { - if (value == "=") return cont(expressionNoComma, vardef2); - if (type == ",") return cont(vardef1); - } - function maybeelse(type, value) { - if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); - } - function forspec1(type) { - if (type == "var") return cont(vardef1, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybein); - return pass(expression, expect(";"), forspec2); - } - function formaybein(_type, value) { - if (value == "in") return cont(expression); - return cont(maybeoperatorComma, forspec2); - } - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in") return cont(expression); - return pass(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); - } - function functiondef(type, value) { - if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); - } - function funarg(type, value) { - if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();} - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: jsTokenBase, - lastType: null, - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - globalVars: parserConfig.globalVars, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (state.tokenize != jsTokenComment && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; - return parseJS(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize == jsTokenComment) return CodeMirror.Pass; - if (state.tokenize != jsTokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; - // Kludge to prevent 'maybelse' from blocking lexical scope pops - for (var i = state.cc.length - 1; i >= 0; --i) { - var c = state.cc[i]; - if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse || /^else\b/.test(textAfter)) break; - } - if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; - if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") - lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0); - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "form") return lexical.indented + indentUnit; - else if (type == "stat") - return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0); - else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricChars: ":{}", - blockCommentStart: jsonMode ? null : "/*", - blockCommentEnd: jsonMode ? null : "*/", - lineComment: jsonMode ? null : "//", - fold: "brace", - - helperType: jsonMode ? "json" : "javascript", - jsonMode: jsonMode - }; -}; - -CodeMirror.defineMode("javascript", opts ); -CodeMirrorOriginal.defineMode("javascript", opts ); -CodeMirror.defineMIME("text/javascript", "javascript"); -CodeMirror.defineMIME("text/ecmascript", "javascript"); -CodeMirror.defineMIME("application/javascript", "javascript"); -CodeMirror.defineMIME("application/ecmascript", "javascript"); -CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); -CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); -CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); diff --git a/public/js/lib/codemirror-accessible/stress.html b/public/js/lib/codemirror-accessible/stress.html deleted file mode 100755 index fba041a163..0000000000 --- a/public/js/lib/codemirror-accessible/stress.html +++ /dev/null @@ -1,749 +0,0 @@ - - - - - CodeMirror Accessible - - - - - - - - - - - - -

      CodeMirror Accessibility

      - -
      - -
      - This page is just an experiment. When you are are ready, you can click . Careful - this may be very slow. -
      - -
      - makes it easier to debug and see what is going on -
      - -
      - -

      CodeMirror With Accessibility Fix

      - - -
      - -

      CodeMirror Original

      -
      - -
      - -

      Normal Textarea

      -
      - -
      - - - \ No newline at end of file diff --git a/public/js/lib/codemirror/.gitattributes b/public/js/lib/codemirror/.gitattributes deleted file mode 100644 index f8bdd60f49..0000000000 --- a/public/js/lib/codemirror/.gitattributes +++ /dev/null @@ -1,8 +0,0 @@ -*.txt text -*.js text -*.html text -*.md text -*.json text -*.yml text -*.css text -*.svg text diff --git a/public/js/lib/codemirror/.gitignore b/public/js/lib/codemirror/.gitignore deleted file mode 100644 index b720b9be07..0000000000 --- a/public/js/lib/codemirror/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/node_modules -/npm-debug.log -test.html -.tern-* -*~ -*.swp -.idea -*.iml diff --git a/public/js/lib/codemirror/.travis.yml b/public/js/lib/codemirror/.travis.yml deleted file mode 100644 index baa0031d50..0000000000 --- a/public/js/lib/codemirror/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: - - 0.8 diff --git a/public/js/lib/codemirror/AUTHORS b/public/js/lib/codemirror/AUTHORS deleted file mode 100644 index afa3cc083a..0000000000 --- a/public/js/lib/codemirror/AUTHORS +++ /dev/null @@ -1,423 +0,0 @@ -List of CodeMirror contributors. Updated before every release. - -4r2r -Aaron Brooks -Abdelouahab -Abe Fettig -Adam Ahmed -Adam King -adanlobato -Adán Lobato -Adrian Aichner -aeroson -Ahmad Amireh -Ahmad M. Zawawi -ahoward -Akeksandr Motsjonov -Alberto González Palomo -Alberto Pose -Albert Xing -Alexander Pavlov -Alexander Schepanovski -Alexander Shvets -Alexander Solovyov -Alexandre Bique -alexey-k -Alex Piggott -Amsul -amuntean -Amy -Ananya Sen -anaran -AndersMad -Anders Nawroth -Anderson Mesquita -Andrea G -Andreas Reischuck -Andre von Houck -Andrey Fedorov -Andrey Klyuchnikov -Andrey Lushnikov -Andy Joslin -Andy Kimball -Andy Li -angelozerr -angelo.zerr@gmail.com -Ankit Ahuja -Ansel Santosa -Anthony Grimes -Anton Kovalyov -areos -as3boyan -AtomicPages LLC -Atul Bhouraskar -Aurelian Oancea -Bastian Müller -Bem Jones-Bey -benbro -Beni Cherniavsky-Paskin -Benjamin DeCoste -Ben Keen -Bernhard Sirlinger -Bert Chang -Billy Moon -binny -B Krishna Chaitanya -Blaine G -blukat29 -boomyjee -borawjm -Brandon Frohs -Brandon Wamboldt -Brett Zamir -Brian Grinstead -Brian Sletten -Bruce Mitchener -Chandra Sekhar Pydi -Charles Skelton -Cheah Chu Yeow -Chris Coyier -Chris Granger -Chris Houseknecht -Chris Morgan -Christian Oyarzun -Christopher Brown -ciaranj -CodeAnimal -ComFreek -Curtis Gagliardi -dagsta -daines -Dale Jung -Dan Bentley -Dan Heberden -Daniel, Dao Quang Minh -Daniele Di Sarli -Daniel Faust -Daniel Huigens -Daniel KJ -Daniel Neel -Daniel Parnell -Danny Yoo -darealshinji -Darius Roberts -Dave Myers -David Mignot -David Pathakjee -David Vázquez -deebugger -Deep Thought -Devon Carew -dignifiedquire -Dimage Sapelkin -domagoj412 -Dominator008 -Domizio Demichelis -Doug Wikle -Drew Bratcher -Drew Hintz -Drew Khoury -Dror BG -duralog -eborden -edsharp -ekhaled -Enam Mijbah Noor -Eric Allam -eustas -Fabien O'Carroll -Fabio Zendhi Nagao -Faiza Alsaied -Fauntleroy -fbuchinger -feizhang365 -Felipe Lalanne -Felix Raab -Filip Noetzel -flack -ForbesLindesay -Forbes Lindesay -Ford_Lawnmower -Frank Wiegand -Gabriel Gheorghian -Gabriel Horner -Gabriel Nahmias -galambalazs -Gautam Mehta -gekkoe -Gerard Braad -Gergely Hegykozi -Glenn Jorde -Glenn Ruehle -Golevka -Gordon Smith -Grant Skinner -greengiant -Gregory Koberger -Guillaume Massé -Guillaume Massé -Gustavo Rodrigues -Hakan Tunc -Hans Engel -Hardest -Hasan Karahan -Herculano Campos -Hiroyuki Makino -hitsthings -Hocdoc -Ian Beck -Ian Dickinson -Ian Wehrman -Ian Wetherbee -Ice White -ICHIKAWA, Yuji -ilvalle -Ingo Richter -Irakli Gozalishvili -Ivan Kurnosov -Jacob Lee -Jakob Miland -Jakub Vrana -Jakub Vrána -James Campos -James Thorne -Jamie Hill -Jan Jongboom -jankeromnes -Jan Keromnes -Jan Odvarko -Jan T. Sott -Jared Forsyth -Jason -Jason Barnabe -Jason Grout -Jason Johnston -Jason San Jose -Jason Siefken -Jaydeep Solanki -Jean Boussier -jeffkenton -Jeff Pickhardt -jem (graphite) -Jeremy Parmenter -Jochen Berger -Johan Ask -John Connor -John Lees-Miller -John Snelson -John Van Der Loo -Jonathan Malmaud -jongalloway -Jon Malmaud -Jon Sangster -Joost-Wim Boekesteijn -Joseph Pecoraro -Joshua Newman -Josh Watzman -jots -jsoojeon -Juan Benavides Romero -Jucovschi Constantin -Juho Vuori -Justin Hileman -jwallers@gmail.com -kaniga -Ken Newman -Ken Rockot -Kevin Sawicki -Kevin Ushey -Klaus Silveira -Koh Zi Han, Cliff -komakino -Konstantin Lopuhin -koops -ks-ifware -kubelsmieci -Lanfei -Lanny -Laszlo Vidacs -leaf corcoran -Leonid Khachaturov -Leon Sorokin -Leonya Khachaturov -Liam Newman -LM -lochel -Lorenzo Stoakes -Luciano Longo -Luke Stagner -lynschinzer -Maksim Lin -Maksym Taran -Malay Majithia -Manuel Rego Casasnovas -Marat Dreizin -Marcel Gerber -Marco Aurélio -Marco Munizaga -Marcus Bointon -Marijn Haverbeke -Mário Gonçalves -Mario Pietsch -Mark Lentczner -Marko Bonaci -Martin Balek -Martín Gaitán -Martin Hasoň -Mason Malone -Mateusz Paprocki -Mathias Bynens -mats cronqvist -Matthew Beale -Matthias Bussonnier -Matthias BUSSONNIER -Matt McDonald -Matt Pass -Matt Sacks -mauricio -Maximilian Hils -Maxim Kraev -Max Kirsch -Max Xiantu -mbarkhau -Metatheos -Micah Dubinko -Michael Lehenbauer -Michael Zhou -Mighty Guava -Miguel Castillo -Mike -Mike Brevoort -Mike Diaz -Mike Ivanov -Mike Kadin -MinRK -Miraculix87 -misfo -mloginov -Moritz Schwörer -mps -mtaran-google -Narciso Jaramillo -Nathan Williams -ndr -nerbert -nextrevision -nguillaumin -Ng Zhi An -Nicholas Bollweg -Nicholas Bollweg (Nick) -Nick Small -Niels van Groningen -nightwing -Nikita Beloglazov -Nikita Vasilyev -Nikolay Kostov -nilp0inter -Nisarg Jhaveri -nlwillia -Norman Rzepka -pablo -Page -Panupong Pasupat -paris -Patil Arpith -Patrick Stoica -Patrick Strawderman -Paul Garvin -Paul Ivanov -Pavel Feldman -Pavel Strashkin -Paweł Bartkiewicz -peteguhl -Peter Flynn -peterkroon -Peter Kroon -prasanthj -Prasanth J -Radek Piórkowski -Rahul -Randall Mason -Randy Burden -Randy Edmunds -Rasmus Erik Voel Jensen -Richard van der Meer -Richard Z.H. Wang -Robert Crossfield -Roberto Abdelkader Martínez Pérez -robertop23 -Robert Plummer -Ruslan Osmanov -Ryan Prior -sabaca -Samuel Ainsworth -sandeepshetty -Sander AKA Redsandro -santec -Sascha Peilicke -satchmorun -sathyamoorthi -SCLINIC\jdecker -Scott Aikin -Scott Goodhew -Sebastian Zaha -shaund -shaun gilchrist -Shawn A -sheopory -Shiv Deepak -Shmuel Englard -Shubham Jain -silverwind -snasa -soliton4 -sonson -spastorelli -srajanpaliwal -Stanislav Oaserele -Stas Kobzar -Stefan Borsje -Steffen Beyer -Steve O'Hara -stoskov -Taha Jahangir -Takuji Shimokawa -Tarmil -tfjgeorge -Thaddee Tyl -TheHowl -think -Thomas Dvornik -Thomas Schmid -Tim Alby -Tim Baumann -Timothy Farrell -Timothy Hatcher -TobiasBg -Tomas-A -Tomas Varaneckas -Tom Erik Støwer -Tom MacWright -Tony Jian -Travis Heppe -Triangle717 -twifkak -Vestimir Markov -vf -Vincent Woo -Volker Mische -wenli -Wesley Wiser -Will Binns-Smith -William Jamieson -William Stein -Willy -Wojtek Ptak -Xavier Mendez -Yassin N. Hassan -YNH Webdev -Yunchi Luo -Yuvi Panda -Zachary Dremann -zziuni -魏鹏刚 diff --git a/public/js/lib/codemirror/CONTRIBUTING.md b/public/js/lib/codemirror/CONTRIBUTING.md deleted file mode 100644 index c4296ce4d2..0000000000 --- a/public/js/lib/codemirror/CONTRIBUTING.md +++ /dev/null @@ -1,76 +0,0 @@ -# How to contribute - -- [Getting help](#getting-help-) -- [Submitting bug reports](#submitting-bug-reports-) -- [Contributing code](#contributing-code-) - -## Getting help - -Community discussion, questions, and informal bug reporting is done on the -[discuss.CodeMirror forum](http://discuss.codemirror.net). - -## Submitting bug reports - -The preferred way to report bugs is to use the -[GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before -reporting a bug, read these pointers. - -**Note:** The issue tracker is for *bugs*, not requests for help. Questions -should be asked on the -[discuss.CodeMirror forum](http://discuss.codemirror.net) instead. - -### Reporting bugs effectively - -- CodeMirror is maintained by volunteers. They don't owe you anything, so be - polite. Reports with an indignant or belligerent tone tend to be moved to the - bottom of the pile. - -- Include information about **the browser in which the problem occurred**. Even - if you tested several browsers, and the problem occurred in all of them, - mention this fact in the bug report. Also include browser version numbers and - the operating system that you're on. - -- Mention which release of CodeMirror you're using. Preferably, try also with - the current development snapshot, to ensure the problem has not already been - fixed. - -- Mention very precisely what went wrong. "X is broken" is not a good bug - report. What did you expect to happen? What happened instead? Describe the - exact steps a maintainer has to take to make the problem occur. We can not - fix something that we can not observe. - -- If the problem can not be reproduced in any of the demos included in the - CodeMirror distribution, please provide an HTML document that demonstrates - the problem. The best way to do this is to go to - [jsbin.com](http://jsbin.com/ihunin/edit), enter it there, press save, and - include the resulting link in your bug report. - -## Contributing code - -- Make sure you have a [GitHub Account](https://github.com/signup/free) -- Fork [CodeMirror](https://github.com/codemirror/CodeMirror/) - ([how to fork a repo](https://help.github.com/articles/fork-a-repo)) -- Make your changes -- If your changes are easy to test or likely to regress, add tests. - Tests for the core go into `test/test.js`, some modes have their own - test suite under `mode/XXX/test.js`. Feel free to add new test - suites to modes that don't have one yet (be sure to link the new - tests into `test/index.html`). -- Follow the general code style of the rest of the project (see - below). Run `bin/lint` to verify that the linter is happy. -- Make sure all tests pass. Visit `test/index.html` in your browser to - run them. -- Submit a pull request -([how to create a pull request](https://help.github.com/articles/fork-a-repo)) - -### Coding standards - -- 2 spaces per indentation level, no tabs. -- Include semicolons after statements. -- Note that the linter (`bin/lint`) which is run after each commit - complains about unused variables and functions. Prefix their names - with an underscore to muffle it. - -- CodeMirror does *not* follow JSHint or JSLint prescribed style. - Patches that try to 'fix' code to pass one of these linters will be - unceremoniously discarded. diff --git a/public/js/lib/codemirror/LICENSE b/public/js/lib/codemirror/LICENSE deleted file mode 100644 index d21bbea5a6..0000000000 --- a/public/js/lib/codemirror/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2014 by Marijn Haverbeke and others - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/public/js/lib/codemirror/README.md b/public/js/lib/codemirror/README.md deleted file mode 100644 index 42b06f7474..0000000000 --- a/public/js/lib/codemirror/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# CodeMirror -[![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror) -[![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror) - -CodeMirror is a JavaScript component that provides a code editor in -the browser. When a mode is available for the language you are coding -in, it will color your code, and optionally help with indentation. - -The project page is http://codemirror.net -The manual is at http://codemirror.net/doc/manual.html -The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md) diff --git a/public/js/lib/codemirror/addon/comment/comment.js b/public/js/lib/codemirror/addon/comment/comment.js deleted file mode 100644 index 2dd114d332..0000000000 --- a/public/js/lib/codemirror/addon/comment/comment.js +++ /dev/null @@ -1,183 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var noOptions = {}; - var nonWS = /[^\s\u00a0]/; - var Pos = CodeMirror.Pos; - - function firstNonWS(str) { - var found = str.search(nonWS); - return found == -1 ? 0 : found; - } - - CodeMirror.commands.toggleComment = function(cm) { - var minLine = Infinity, ranges = cm.listSelections(), mode = null; - for (var i = ranges.length - 1; i >= 0; i--) { - var from = ranges[i].from(), to = ranges[i].to(); - if (from.line >= minLine) continue; - if (to.line >= minLine) to = Pos(minLine, 0); - minLine = from.line; - if (mode == null) { - if (cm.uncomment(from, to)) mode = "un"; - else { cm.lineComment(from, to); mode = "line"; } - } else if (mode == "un") { - cm.uncomment(from, to); - } else { - cm.lineComment(from, to); - } - } - }; - - CodeMirror.defineExtension("lineComment", function(from, to, options) { - if (!options) options = noOptions; - var self = this, mode = self.getModeAt(from); - var commentString = options.lineComment || mode.lineComment; - if (!commentString) { - if (options.blockCommentStart || mode.blockCommentStart) { - options.fullLines = true; - self.blockComment(from, to, options); - } - return; - } - var firstLine = self.getLine(from.line); - if (firstLine == null) return; - var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1); - var pad = options.padding == null ? " " : options.padding; - var blankLines = options.commentBlankLines || from.line == to.line; - - self.operation(function() { - if (options.indent) { - var baseString = firstLine.slice(0, firstNonWS(firstLine)); - for (var i = from.line; i < end; ++i) { - var line = self.getLine(i), cut = baseString.length; - if (!blankLines && !nonWS.test(line)) continue; - if (line.slice(0, cut) != baseString) cut = firstNonWS(line); - self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut)); - } - } else { - for (var i = from.line; i < end; ++i) { - if (blankLines || nonWS.test(self.getLine(i))) - self.replaceRange(commentString + pad, Pos(i, 0)); - } - } - }); - }); - - CodeMirror.defineExtension("blockComment", function(from, to, options) { - if (!options) options = noOptions; - var self = this, mode = self.getModeAt(from); - var startString = options.blockCommentStart || mode.blockCommentStart; - var endString = options.blockCommentEnd || mode.blockCommentEnd; - if (!startString || !endString) { - if ((options.lineComment || mode.lineComment) && options.fullLines != false) - self.lineComment(from, to, options); - return; - } - - var end = Math.min(to.line, self.lastLine()); - if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end; - - var pad = options.padding == null ? " " : options.padding; - if (from.line > end) return; - - self.operation(function() { - if (options.fullLines != false) { - var lastLineHasText = nonWS.test(self.getLine(end)); - self.replaceRange(pad + endString, Pos(end)); - self.replaceRange(startString + pad, Pos(from.line, 0)); - var lead = options.blockCommentLead || mode.blockCommentLead; - if (lead != null) for (var i = from.line + 1; i <= end; ++i) - if (i != end || lastLineHasText) - self.replaceRange(lead + pad, Pos(i, 0)); - } else { - self.replaceRange(endString, to); - self.replaceRange(startString, from); - } - }); - }); - - CodeMirror.defineExtension("uncomment", function(from, to, options) { - if (!options) options = noOptions; - var self = this, mode = self.getModeAt(from); - var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); - - // Try finding line comments - var lineString = options.lineComment || mode.lineComment, lines = []; - var pad = options.padding == null ? " " : options.padding, didSomething; - lineComment: { - if (!lineString) break lineComment; - for (var i = start; i <= end; ++i) { - var line = self.getLine(i); - var found = line.indexOf(lineString); - if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1; - if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment; - if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment; - lines.push(line); - } - self.operation(function() { - for (var i = start; i <= end; ++i) { - var line = lines[i - start]; - var pos = line.indexOf(lineString), endPos = pos + lineString.length; - if (pos < 0) continue; - if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length; - didSomething = true; - self.replaceRange("", Pos(i, pos), Pos(i, endPos)); - } - }); - if (didSomething) return true; - } - - // Try block comments - var startString = options.blockCommentStart || mode.blockCommentStart; - var endString = options.blockCommentEnd || mode.blockCommentEnd; - if (!startString || !endString) return false; - var lead = options.blockCommentLead || mode.blockCommentLead; - var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end); - var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString); - if (close == -1 && start != end) { - endLine = self.getLine(--end); - close = endLine.lastIndexOf(endString); - } - if (open == -1 || close == -1 || - !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) || - !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1)))) - return false; - - // Avoid killing block comments completely outside the selection. - // Positions of the last startString before the start of the selection, and the first endString after it. - var lastStart = startLine.lastIndexOf(startString, from.ch); - var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length); - if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false; - // Positions of the first endString after the end of the selection, and the last startString before it. - firstEnd = endLine.indexOf(endString, to.ch); - var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch); - lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart; - if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false; - - self.operation(function() { - self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)), - Pos(end, close + endString.length)); - var openEnd = open + startString.length; - if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length; - self.replaceRange("", Pos(start, open), Pos(start, openEnd)); - if (lead) for (var i = start + 1; i <= end; ++i) { - var line = self.getLine(i), found = line.indexOf(lead); - if (found == -1 || nonWS.test(line.slice(0, found))) continue; - var foundEnd = found + lead.length; - if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length; - self.replaceRange("", Pos(i, found), Pos(i, foundEnd)); - } - }); - return true; - }); -}); diff --git a/public/js/lib/codemirror/addon/comment/continuecomment.js b/public/js/lib/codemirror/addon/comment/continuecomment.js deleted file mode 100644 index b11d51e6ca..0000000000 --- a/public/js/lib/codemirror/addon/comment/continuecomment.js +++ /dev/null @@ -1,85 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var modes = ["clike", "css", "javascript"]; - - for (var i = 0; i < modes.length; ++i) - CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "}); - - function continueComment(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), mode, inserts = []; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].head, token = cm.getTokenAt(pos); - if (token.type != "comment") return CodeMirror.Pass; - var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode; - if (!mode) mode = modeHere; - else if (mode != modeHere) return CodeMirror.Pass; - - var insert = null; - if (mode.blockCommentStart && mode.blockCommentContinue) { - var end = token.string.indexOf(mode.blockCommentEnd); - var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found; - if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) { - // Comment ended, don't continue it - } else if (token.string.indexOf(mode.blockCommentStart) == 0) { - insert = full.slice(0, token.start); - if (!/^\s*$/.test(insert)) { - insert = ""; - for (var j = 0; j < token.start; ++j) insert += " "; - } - } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 && - found + mode.blockCommentContinue.length > token.start && - /^\s*$/.test(full.slice(0, found))) { - insert = full.slice(0, found); - } - if (insert != null) insert += mode.blockCommentContinue; - } - if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) { - var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); - if (found > -1) { - insert = line.slice(0, found); - if (/\S/.test(insert)) insert = null; - else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0]; - } - } - if (insert == null) return CodeMirror.Pass; - inserts[i] = "\n" + insert; - } - - cm.operation(function() { - for (var i = ranges.length - 1; i >= 0; i--) - cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert"); - }); - } - - function continueLineCommentEnabled(cm) { - var opt = cm.getOption("continueComments"); - if (opt && typeof opt == "object") - return opt.continueLineComment !== false; - return true; - } - - CodeMirror.defineOption("continueComments", null, function(cm, val, prev) { - if (prev && prev != CodeMirror.Init) - cm.removeKeyMap("continueComment"); - if (val) { - var key = "Enter"; - if (typeof val == "string") - key = val; - else if (typeof val == "object" && val.key) - key = val.key; - var map = {name: "continueComment"}; - map[key] = continueComment; - cm.addKeyMap(map); - } - }); -}); diff --git a/public/js/lib/codemirror/addon/dialog/dialog.css b/public/js/lib/codemirror/addon/dialog/dialog.css deleted file mode 100644 index 2e7c0fc9b8..0000000000 --- a/public/js/lib/codemirror/addon/dialog/dialog.css +++ /dev/null @@ -1,32 +0,0 @@ -.CodeMirror-dialog { - position: absolute; - left: 0; right: 0; - background: white; - z-index: 15; - padding: .1em .8em; - overflow: hidden; - color: #333; -} - -.CodeMirror-dialog-top { - border-bottom: 1px solid #eee; - top: 0; -} - -.CodeMirror-dialog-bottom { - border-top: 1px solid #eee; - bottom: 0; -} - -.CodeMirror-dialog input { - border: none; - outline: none; - background: transparent; - width: 20em; - color: inherit; - font-family: monospace; -} - -.CodeMirror-dialog button { - font-size: 70%; -} diff --git a/public/js/lib/codemirror/addon/dialog/dialog.js b/public/js/lib/codemirror/addon/dialog/dialog.js deleted file mode 100644 index e0e8ad4eb7..0000000000 --- a/public/js/lib/codemirror/addon/dialog/dialog.js +++ /dev/null @@ -1,155 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Open simple dialogs on top of an editor. Relies on dialog.css. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - function dialogDiv(cm, template, bottom) { - var wrap = cm.getWrapperElement(); - var dialog; - dialog = wrap.appendChild(document.createElement("div")); - if (bottom) - dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; - else - dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; - - if (typeof template == "string") { - dialog.innerHTML = template; - } else { // Assuming it's a detached DOM element. - dialog.appendChild(template); - } - return dialog; - } - - function closeNotification(cm, newVal) { - if (cm.state.currentNotificationClose) - cm.state.currentNotificationClose(); - cm.state.currentNotificationClose = newVal; - } - - CodeMirror.defineExtension("openDialog", function(template, callback, options) { - if (!options) options = {}; - - closeNotification(this, null); - - var dialog = dialogDiv(this, template, options.bottom); - var closed = false, me = this; - function close(newVal) { - if (typeof newVal == 'string') { - inp.value = newVal; - } else { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - - if (options.onClose) options.onClose(dialog); - } - } - - var inp = dialog.getElementsByTagName("input")[0], button; - if (inp) { - if (options.value) { - inp.value = options.value; - inp.select(); - } - - if (options.onInput) - CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); - if (options.onKeyUp) - CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); - - CodeMirror.on(inp, "keydown", function(e) { - if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } - if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { - inp.blur(); - CodeMirror.e_stop(e); - close(); - } - if (e.keyCode == 13) callback(inp.value, e); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); - - inp.focus(); - } else if (button = dialog.getElementsByTagName("button")[0]) { - CodeMirror.on(button, "click", function() { - close(); - me.focus(); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); - - button.focus(); - } - return close; - }); - - CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { - closeNotification(this, null); - var dialog = dialogDiv(this, template, options && options.bottom); - var buttons = dialog.getElementsByTagName("button"); - var closed = false, me = this, blurring = 1; - function close() { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - } - buttons[0].focus(); - for (var i = 0; i < buttons.length; ++i) { - var b = buttons[i]; - (function(callback) { - CodeMirror.on(b, "click", function(e) { - CodeMirror.e_preventDefault(e); - close(); - if (callback) callback(me); - }); - })(callbacks[i]); - CodeMirror.on(b, "blur", function() { - --blurring; - setTimeout(function() { if (blurring <= 0) close(); }, 200); - }); - CodeMirror.on(b, "focus", function() { ++blurring; }); - } - }); - - /* - * openNotification - * Opens a notification, that can be closed with an optional timer - * (default 5000ms timer) and always closes on click. - * - * If a notification is opened while another is opened, it will close the - * currently opened one and open the new one immediately. - */ - CodeMirror.defineExtension("openNotification", function(template, options) { - closeNotification(this, close); - var dialog = dialogDiv(this, template, options && options.bottom); - var closed = false, doneTimer; - var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; - - function close() { - if (closed) return; - closed = true; - clearTimeout(doneTimer); - dialog.parentNode.removeChild(dialog); - } - - CodeMirror.on(dialog, 'click', function(e) { - CodeMirror.e_preventDefault(e); - close(); - }); - - if (duration) - doneTimer = setTimeout(close, duration); - - return close; - }); -}); diff --git a/public/js/lib/codemirror/addon/display/fullscreen.css b/public/js/lib/codemirror/addon/display/fullscreen.css deleted file mode 100644 index 437acd89be..0000000000 --- a/public/js/lib/codemirror/addon/display/fullscreen.css +++ /dev/null @@ -1,6 +0,0 @@ -.CodeMirror-fullscreen { - position: fixed; - top: 0; left: 0; right: 0; bottom: 0; - height: auto; - z-index: 9; -} diff --git a/public/js/lib/codemirror/addon/display/fullscreen.js b/public/js/lib/codemirror/addon/display/fullscreen.js deleted file mode 100644 index cd3673b96c..0000000000 --- a/public/js/lib/codemirror/addon/display/fullscreen.js +++ /dev/null @@ -1,41 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineOption("fullScreen", false, function(cm, val, old) { - if (old == CodeMirror.Init) old = false; - if (!old == !val) return; - if (val) setFullscreen(cm); - else setNormal(cm); - }); - - function setFullscreen(cm) { - var wrap = cm.getWrapperElement(); - cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, - width: wrap.style.width, height: wrap.style.height}; - wrap.style.width = ""; - wrap.style.height = "auto"; - wrap.className += " CodeMirror-fullscreen"; - document.documentElement.style.overflow = "hidden"; - cm.refresh(); - } - - function setNormal(cm) { - var wrap = cm.getWrapperElement(); - wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, ""); - document.documentElement.style.overflow = ""; - var info = cm.state.fullScreenRestore; - wrap.style.width = info.width; wrap.style.height = info.height; - window.scrollTo(info.scrollLeft, info.scrollTop); - cm.refresh(); - } -}); diff --git a/public/js/lib/codemirror/addon/display/panel.js b/public/js/lib/codemirror/addon/display/panel.js deleted file mode 100644 index 22c0453e8f..0000000000 --- a/public/js/lib/codemirror/addon/display/panel.js +++ /dev/null @@ -1,94 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - CodeMirror.defineExtension("addPanel", function(node, options) { - if (!this.state.panels) initPanels(this); - - var info = this.state.panels; - if (options && options.position == "bottom") - info.wrapper.appendChild(node); - else - info.wrapper.insertBefore(node, info.wrapper.firstChild); - var height = (options && options.height) || node.offsetHeight; - this._setSize(null, info.heightLeft -= height); - info.panels++; - return new Panel(this, node, options, height); - }); - - function Panel(cm, node, options, height) { - this.cm = cm; - this.node = node; - this.options = options; - this.height = height; - this.cleared = false; - } - - Panel.prototype.clear = function() { - if (this.cleared) return; - this.cleared = true; - var info = this.cm.state.panels; - this.cm._setSize(null, info.heightLeft += this.height); - info.wrapper.removeChild(this.node); - if (--info.panels == 0) removePanels(this.cm); - }; - - Panel.prototype.changed = function(height) { - var newHeight = height == null ? this.node.offsetHeight : height; - var info = this.cm.state.panels; - this.cm._setSize(null, info.height += (newHeight - this.height)); - this.height = newHeight; - }; - - function initPanels(cm) { - var wrap = cm.getWrapperElement(); - var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle; - var height = parseInt(style.height); - var info = cm.state.panels = { - setHeight: wrap.style.height, - heightLeft: height, - panels: 0, - wrapper: document.createElement("div") - }; - wrap.parentNode.insertBefore(info.wrapper, wrap); - var hasFocus = cm.hasFocus(); - info.wrapper.appendChild(wrap); - if (hasFocus) cm.focus(); - - cm._setSize = cm.setSize; - if (height != null) cm.setSize = function(width, newHeight) { - if (newHeight == null) return this._setSize(width, newHeight); - info.setHeight = newHeight; - if (typeof newHeight != "number") { - var px = /^(\d+\.?\d*)px$/.exec(newHeight); - if (px) { - newHeight = Number(px[1]); - } else { - info.wrapper.style.height = newHeight; - newHeight = info.wrapper.offsetHeight; - info.wrapper.style.height = ""; - } - } - cm._setSize(width, info.heightLeft += (newHeight - height)); - height = newHeight; - }; - } - - function removePanels(cm) { - var info = cm.state.panels; - cm.state.panels = null; - - var wrap = cm.getWrapperElement(); - info.wrapper.parentNode.replaceChild(wrap, info.wrapper); - wrap.style.height = info.setHeight; - cm.setSize = cm._setSize; - cm.setSize(); - } -}); diff --git a/public/js/lib/codemirror/addon/display/placeholder.js b/public/js/lib/codemirror/addon/display/placeholder.js deleted file mode 100644 index bb0c3931e4..0000000000 --- a/public/js/lib/codemirror/addon/display/placeholder.js +++ /dev/null @@ -1,58 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - CodeMirror.defineOption("placeholder", "", function(cm, val, old) { - var prev = old && old != CodeMirror.Init; - if (val && !prev) { - cm.on("blur", onBlur); - cm.on("change", onChange); - onChange(cm); - } else if (!val && prev) { - cm.off("blur", onBlur); - cm.off("change", onChange); - clearPlaceholder(cm); - var wrapper = cm.getWrapperElement(); - wrapper.className = wrapper.className.replace(" CodeMirror-empty", ""); - } - - if (val && !cm.hasFocus()) onBlur(cm); - }); - - function clearPlaceholder(cm) { - if (cm.state.placeholder) { - cm.state.placeholder.parentNode.removeChild(cm.state.placeholder); - cm.state.placeholder = null; - } - } - function setPlaceholder(cm) { - clearPlaceholder(cm); - var elt = cm.state.placeholder = document.createElement("pre"); - elt.style.cssText = "height: 0; overflow: visible"; - elt.className = "CodeMirror-placeholder"; - elt.appendChild(document.createTextNode(cm.getOption("placeholder"))); - cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild); - } - - function onBlur(cm) { - if (isEmpty(cm)) setPlaceholder(cm); - } - function onChange(cm) { - var wrapper = cm.getWrapperElement(), empty = isEmpty(cm); - wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : ""); - - if (empty) setPlaceholder(cm); - else clearPlaceholder(cm); - } - - function isEmpty(cm) { - return (cm.lineCount() === 1) && (cm.getLine(0) === ""); - } -}); diff --git a/public/js/lib/codemirror/addon/display/rulers.js b/public/js/lib/codemirror/addon/display/rulers.js deleted file mode 100644 index 13185d30b4..0000000000 --- a/public/js/lib/codemirror/addon/display/rulers.js +++ /dev/null @@ -1,64 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineOption("rulers", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - clearRulers(cm); - cm.off("refresh", refreshRulers); - } - if (val && val.length) { - setRulers(cm); - cm.on("refresh", refreshRulers); - } - }); - - function clearRulers(cm) { - for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) { - var node = cm.display.lineSpace.childNodes[i]; - if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className)) - node.parentNode.removeChild(node); - } - } - - function setRulers(cm) { - var val = cm.getOption("rulers"); - var cw = cm.defaultCharWidth(); - var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left; - var minH = cm.display.scroller.offsetHeight + 30; - for (var i = 0; i < val.length; i++) { - var elt = document.createElement("div"); - elt.className = "CodeMirror-ruler"; - var col, cls = null, conf = val[i]; - if (typeof conf == "number") { - col = conf; - } else { - col = conf.column; - if (conf.className) elt.className += " " + conf.className; - if (conf.color) elt.style.borderColor = conf.color; - if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle; - if (conf.width) elt.style.borderLeftWidth = conf.width; - cls = val[i].className; - } - elt.style.left = (left + col * cw) + "px"; - elt.style.top = "-50px"; - elt.style.bottom = "-20px"; - elt.style.minHeight = minH + "px"; - cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv); - } - } - - function refreshRulers(cm) { - clearRulers(cm); - setRulers(cm); - } -}); diff --git a/public/js/lib/codemirror/addon/edit/closebrackets.js b/public/js/lib/codemirror/addon/edit/closebrackets.js deleted file mode 100644 index f6b42f02d3..0000000000 --- a/public/js/lib/codemirror/addon/edit/closebrackets.js +++ /dev/null @@ -1,159 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var DEFAULT_BRACKETS = "()[]{}''\"\""; - var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; - var SPACE_CHAR_REGEX = /\s/; - - var Pos = CodeMirror.Pos; - - CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { - if (old != CodeMirror.Init && old) - cm.removeKeyMap("autoCloseBrackets"); - if (!val) return; - var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER; - if (typeof val == "string") pairs = val; - else if (typeof val == "object") { - if (val.pairs != null) pairs = val.pairs; - if (val.explode != null) explode = val.explode; - } - var map = buildKeymap(pairs); - if (explode) map.Enter = buildExplodeHandler(explode); - cm.addKeyMap(map); - }); - - function charsAround(cm, pos) { - var str = cm.getRange(Pos(pos.line, pos.ch - 1), - Pos(pos.line, pos.ch + 1)); - return str.length == 2 ? str : null; - } - - // Project the token type that will exists after the given char is - // typed, and use it to determine whether it would cause the start - // of a string token. - function enteringString(cm, pos, ch) { - var line = cm.getLine(pos.line); - var token = cm.getTokenAt(pos); - if (/\bstring2?\b/.test(token.type)) return false; - var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4); - stream.pos = stream.start = token.start; - for (;;) { - var type1 = cm.getMode().token(stream, token.state); - if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1); - stream.start = stream.pos; - } - } - - function buildKeymap(pairs) { - var map = { - name : "autoCloseBrackets", - Backspace: function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var around = charsAround(cm, ranges[i].head); - if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; - } - for (var i = ranges.length - 1; i >= 0; i--) { - var cur = ranges[i].head; - cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1)); - } - } - }; - var closingBrackets = ""; - for (var i = 0; i < pairs.length; i += 2) (function(left, right) { - closingBrackets += right; - map["'" + left + "'"] = function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), type, next; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], cur = range.head, curType; - var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); - if (!range.empty()) { - curType = "surround"; - } else if (left == right && next == right) { - if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left) - curType = "skipThree"; - else - curType = "skip"; - } else if (left == right && cur.ch > 1 && - cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left && - (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) { - curType = "addFour"; - } else if (left == '"' || left == "'") { - if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both"; - else return CodeMirror.Pass; - } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) { - curType = "both"; - } else { - return CodeMirror.Pass; - } - if (!type) type = curType; - else if (type != curType) return CodeMirror.Pass; - } - - cm.operation(function() { - if (type == "skip") { - cm.execCommand("goCharRight"); - } else if (type == "skipThree") { - for (var i = 0; i < 3; i++) - cm.execCommand("goCharRight"); - } else if (type == "surround") { - var sels = cm.getSelections(); - for (var i = 0; i < sels.length; i++) - sels[i] = left + sels[i] + right; - cm.replaceSelections(sels, "around"); - } else if (type == "both") { - cm.replaceSelection(left + right, null); - cm.execCommand("goCharLeft"); - } else if (type == "addFour") { - cm.replaceSelection(left + left + left + left, "before"); - cm.execCommand("goCharRight"); - } - }); - }; - if (left != right) map["'" + right + "'"] = function(cm) { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (!range.empty() || - cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right) - return CodeMirror.Pass; - } - cm.execCommand("goCharRight"); - }; - })(pairs.charAt(i), pairs.charAt(i + 1)); - return map; - } - - function buildExplodeHandler(pairs) { - return function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var around = charsAround(cm, ranges[i].head); - if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; - } - cm.operation(function() { - cm.replaceSelection("\n\n", null); - cm.execCommand("goCharLeft"); - ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var line = ranges[i].head.line; - cm.indentLine(line, null, true); - cm.indentLine(line + 1, null, true); - } - }); - }; - } -}); diff --git a/public/js/lib/codemirror/addon/edit/closetag.js b/public/js/lib/codemirror/addon/edit/closetag.js deleted file mode 100644 index a0bec7dd43..0000000000 --- a/public/js/lib/codemirror/addon/edit/closetag.js +++ /dev/null @@ -1,159 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Tag-closer extension for CodeMirror. - * - * This extension adds an "autoCloseTags" option that can be set to - * either true to get the default behavior, or an object to further - * configure its behavior. - * - * These are supported options: - * - * `whenClosing` (default true) - * Whether to autoclose when the '/' of a closing tag is typed. - * `whenOpening` (default true) - * Whether to autoclose the tag when the final '>' of an opening - * tag is typed. - * `dontCloseTags` (default is empty tags for HTML, none for XML) - * An array of tag names that should not be autoclosed. - * `indentTags` (default is block tags for HTML, none for XML) - * An array of tag names that should, when opened, cause a - * blank line to be added inside the tag, and the blank line and - * closing line to be indented. - * - * See demos/closetag.html for a usage example. - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../fold/xml-fold")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../fold/xml-fold"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) { - if (old != CodeMirror.Init && old) - cm.removeKeyMap("autoCloseTags"); - if (!val) return; - var map = {name: "autoCloseTags"}; - if (typeof val != "object" || val.whenClosing) - map["'/'"] = function(cm) { return autoCloseSlash(cm); }; - if (typeof val != "object" || val.whenOpening) - map["'>'"] = function(cm) { return autoCloseGT(cm); }; - cm.addKeyMap(map); - }); - - var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", - "source", "track", "wbr"]; - var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4", - "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"]; - - function autoCloseGT(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), replacements = []; - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var pos = ranges[i].head, tok = cm.getTokenAt(pos); - var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; - if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; - - var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; - var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); - var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); - - var tagName = state.tagName; - if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); - var lowerTagName = tagName.toLowerCase(); - // Don't process the '>' at the end of an end-tag or self-closing tag - if (!tagName || - tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || - tok.type == "tag" && state.type == "closeTag" || - tok.string.indexOf("/") == (tok.string.length - 1) || // match something like - dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || - closingTagExists(cm, tagName, pos, state, true)) - return CodeMirror.Pass; - - var indent = indentTags && indexOf(indentTags, lowerTagName) > -1; - replacements[i] = {indent: indent, - text: ">" + (indent ? "\n\n" : "") + "", - newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)}; - } - - for (var i = ranges.length - 1; i >= 0; i--) { - var info = replacements[i]; - cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert"); - var sel = cm.listSelections().slice(0); - sel[i] = {head: info.newPos, anchor: info.newPos}; - cm.setSelections(sel); - if (info.indent) { - cm.indentLine(info.newPos.line, null, true); - cm.indentLine(info.newPos.line + 1, null, true); - } - } - } - - function autoCloseSlash(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), replacements = []; - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var pos = ranges[i].head, tok = cm.getTokenAt(pos); - var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; - if (tok.type == "string" || tok.string.charAt(0) != "<" || - tok.start != pos.ch - 1) - return CodeMirror.Pass; - // Kludge to get around the fact that we are not in XML mode - // when completing in JS/CSS snippet in htmlmixed mode. Does not - // work for other XML embedded languages (there is no general - // way to go from a mixed mode to its current XML state). - if (inner.mode.name != "xml") { - if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript") - replacements[i] = "/script>"; - else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css") - replacements[i] = "/style>"; - else - return CodeMirror.Pass; - } else { - if (!state.context || !state.context.tagName || - closingTagExists(cm, state.context.tagName, pos, state)) - return CodeMirror.Pass; - replacements[i] = "/" + state.context.tagName + ">"; - } - } - cm.replaceSelections(replacements); - ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) - if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line) - cm.indentLine(ranges[i].head.line); - } - - function indexOf(collection, elt) { - if (collection.indexOf) return collection.indexOf(elt); - for (var i = 0, e = collection.length; i < e; ++i) - if (collection[i] == elt) return i; - return -1; - } - - // If xml-fold is loaded, we use its functionality to try and verify - // whether a given tag is actually unclosed. - function closingTagExists(cm, tagName, pos, state, newTag) { - if (!CodeMirror.scanForClosingTag) return false; - var end = Math.min(cm.lastLine() + 1, pos.line + 500); - var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end); - if (!nextClose || nextClose.tag != tagName) return false; - var cx = state.context; - // If the immediate wrapping context contains onCx instances of - // the same tag, a closing tag only exists if there are at least - // that many closing tags of that type following. - for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx; - pos = nextClose.to; - for (var i = 1; i < onCx; i++) { - var next = CodeMirror.scanForClosingTag(cm, pos, null, end); - if (!next || next.tag != tagName) return false; - pos = next.to; - } - return true; - } -}); diff --git a/public/js/lib/codemirror/addon/edit/continuelist.js b/public/js/lib/codemirror/addon/edit/continuelist.js deleted file mode 100644 index ca8d26751a..0000000000 --- a/public/js/lib/codemirror/addon/edit/continuelist.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/, - emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/, - unorderedListRE = /[*+-]\s/; - - CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), replacements = []; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].head, match; - var eolState = cm.getStateAfter(pos.line); - var inList = eolState.list !== false; - var inQuote = eolState.quote !== false; - - if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) { - cm.execCommand("newlineAndIndent"); - return; - } - if (cm.getLine(pos.line).match(emptyListRE)) { - cm.replaceRange("", { - line: pos.line, ch: 0 - }, { - line: pos.line, ch: pos.ch + 1 - }); - replacements[i] = "\n"; - - } else { - var indent = match[1], after = match[4]; - var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0 - ? match[2] - : (parseInt(match[3], 10) + 1) + "."; - - replacements[i] = "\n" + indent + bullet + after; - } - } - - cm.replaceSelections(replacements); - }; -}); diff --git a/public/js/lib/codemirror/addon/edit/matchbrackets.js b/public/js/lib/codemirror/addon/edit/matchbrackets.js deleted file mode 100644 index fa1ae030a5..0000000000 --- a/public/js/lib/codemirror/addon/edit/matchbrackets.js +++ /dev/null @@ -1,120 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && - (document.documentMode == null || document.documentMode < 8); - - var Pos = CodeMirror.Pos; - - var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; - - function findMatchingBracket(cm, where, strict, config) { - var line = cm.getLineHandle(where.line), pos = where.ch - 1; - var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; - if (!match) return null; - var dir = match.charAt(1) == ">" ? 1 : -1; - if (strict && (dir > 0) != (pos == where.ch)) return null; - var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); - - var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); - if (found == null) return null; - return {from: Pos(where.line, pos), to: found && found.pos, - match: found && found.ch == match.charAt(0), forward: dir > 0}; - } - - // bracketRegex is used to specify which type of bracket to scan - // should be a regexp, e.g. /[[\]]/ - // - // Note: If "where" is on an open bracket, then this bracket is ignored. - // - // Returns false when no bracket was found, null when it reached - // maxScanLines and gave up - function scanForBracket(cm, where, dir, style, config) { - var maxScanLen = (config && config.maxScanLineLength) || 10000; - var maxScanLines = (config && config.maxScanLines) || 1000; - - var stack = []; - var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; - var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) - : Math.max(cm.firstLine() - 1, where.line - maxScanLines); - for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { - var line = cm.getLine(lineNo); - if (!line) continue; - var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; - if (line.length > maxScanLen) continue; - if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); - for (; pos != end; pos += dir) { - var ch = line.charAt(pos); - if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { - var match = matching[ch]; - if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); - else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; - else stack.pop(); - } - } - } - return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; - } - - function matchBrackets(cm, autoclear, config) { - // Disable brace matching in long lines, since it'll cause hugely slow updates - var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; - var marks = [], ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); - if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { - var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; - marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); - if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) - marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); - } - } - - if (marks.length) { - // Kludge to work around the IE bug from issue #1193, where text - // input stops going to the textare whever this fires. - if (ie_lt8 && cm.state.focused) cm.display.input.focus(); - - var clear = function() { - cm.operation(function() { - for (var i = 0; i < marks.length; i++) marks[i].clear(); - }); - }; - if (autoclear) setTimeout(clear, 800); - else return clear; - } - } - - var currentlyHighlighted = null; - function doMatchBrackets(cm) { - cm.operation(function() { - if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} - currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); - }); - } - - CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) - cm.off("cursorActivity", doMatchBrackets); - if (val) { - cm.state.matchBrackets = typeof val == "object" ? val : {}; - cm.on("cursorActivity", doMatchBrackets); - } - }); - - CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); - CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){ - return findMatchingBracket(this, pos, strict, config); - }); - CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ - return scanForBracket(this, pos, dir, style, config); - }); -}); diff --git a/public/js/lib/codemirror/addon/edit/matchtags.js b/public/js/lib/codemirror/addon/edit/matchtags.js deleted file mode 100644 index fb1911a8db..0000000000 --- a/public/js/lib/codemirror/addon/edit/matchtags.js +++ /dev/null @@ -1,66 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../fold/xml-fold")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../fold/xml-fold"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineOption("matchTags", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - cm.off("cursorActivity", doMatchTags); - cm.off("viewportChange", maybeUpdateMatch); - clear(cm); - } - if (val) { - cm.state.matchBothTags = typeof val == "object" && val.bothTags; - cm.on("cursorActivity", doMatchTags); - cm.on("viewportChange", maybeUpdateMatch); - doMatchTags(cm); - } - }); - - function clear(cm) { - if (cm.state.tagHit) cm.state.tagHit.clear(); - if (cm.state.tagOther) cm.state.tagOther.clear(); - cm.state.tagHit = cm.state.tagOther = null; - } - - function doMatchTags(cm) { - cm.state.failedTagMatch = false; - cm.operation(function() { - clear(cm); - if (cm.somethingSelected()) return; - var cur = cm.getCursor(), range = cm.getViewport(); - range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to); - var match = CodeMirror.findMatchingTag(cm, cur, range); - if (!match) return; - if (cm.state.matchBothTags) { - var hit = match.at == "open" ? match.open : match.close; - if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"}); - } - var other = match.at == "close" ? match.open : match.close; - if (other) - cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"}); - else - cm.state.failedTagMatch = true; - }); - } - - function maybeUpdateMatch(cm) { - if (cm.state.failedTagMatch) doMatchTags(cm); - } - - CodeMirror.commands.toMatchingTag = function(cm) { - var found = CodeMirror.findMatchingTag(cm, cm.getCursor()); - if (found) { - var other = found.at == "close" ? found.open : found.close; - if (other) cm.extendSelection(other.to, other.from); - } - }; -}); diff --git a/public/js/lib/codemirror/addon/edit/trailingspace.js b/public/js/lib/codemirror/addon/edit/trailingspace.js deleted file mode 100644 index fa7b56be51..0000000000 --- a/public/js/lib/codemirror/addon/edit/trailingspace.js +++ /dev/null @@ -1,27 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { - if (prev == CodeMirror.Init) prev = false; - if (prev && !val) - cm.removeOverlay("trailingspace"); - else if (!prev && val) - cm.addOverlay({ - token: function(stream) { - for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} - if (i > stream.pos) { stream.pos = i; return null; } - stream.pos = l; - return "trailingspace"; - }, - name: "trailingspace" - }); - }); -}); diff --git a/public/js/lib/codemirror/addon/emmet/emmet.js b/public/js/lib/codemirror/addon/emmet/emmet.js deleted file mode 100644 index a5e8042fe8..0000000000 --- a/public/js/lib/codemirror/addon/emmet/emmet.js +++ /dev/null @@ -1,43080 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.emmetCodeMirror=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 && typeof pos !== "object") { - pos = { line: arguments[1], ch: arguments[2] }; - } - return cm.indexFromPos(pos); -} - -/** - * Converts charater index in text to CM’s internal object representation - * @param {CodeMirror} cm CodeMirror instance - * @param {Number} ix Character index in CM document - * @return {Object} - */ -function indexToPos(cm, ix) { - return cm.posFromIndex(ix); -} -},{"./emmet":2}],2:[function(require,module,exports){ -"use strict"; - -var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; - -var emmet = _interopRequire(require("emmet")); - -require("emmet/bundles/snippets"); - -require("emmet/bundles/caniuse"); - -module.exports = emmet; -},{"emmet":39,"emmet/bundles/caniuse":3,"emmet/bundles/snippets":4}],3:[function(require,module,exports){ -/** - * Bundler, used in builder script to statically - * include optimized caniuse.json into bundle - */ -var ciu = require('../lib/assets/caniuse'); -var db = require('../lib/caniuse.json'); -ciu.load(db, true); -},{"../lib/assets/caniuse":23,"../lib/caniuse.json":35}],4:[function(require,module,exports){ -/** - * Bundler, used in builder script to statically - * include snippets.json into bundle - */ -var res = require('../lib/assets/resources'); -var snippets = require('../lib/snippets.json'); -res.setVocabulary(snippets, 'system'); - -},{"../lib/assets/resources":31,"../lib/snippets.json":68}],5:[function(require,module,exports){ -/** - * HTML pair matching (balancing) actions - * @constructor - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var htmlMatcher = require('../assets/htmlMatcher'); - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var actionUtils = require('../utils/action'); - var range = require('../assets/range'); - var cssEditTree = require('../editTree/css'); - var cssSections = require('../utils/cssSections'); - var lastMatch = null; - - function last(arr) { - return arr[arr.length - 1]; - } - - function balanceHTML(editor, direction) { - var info = editorUtils.outputInfo(editor); - var content = info.content; - var sel = range(editor.getSelectionRange()); - - // validate previous match - if (lastMatch && !lastMatch.range.equal(sel)) { - lastMatch = null; - } - - if (lastMatch && sel.length()) { - if (direction == 'in') { - // user has previously selected tag and wants to move inward - if (lastMatch.type == 'tag' && !lastMatch.close) { - // unary tag was selected, can't move inward - return false; - } else { - if (lastMatch.range.equal(lastMatch.outerRange)) { - lastMatch.range = lastMatch.innerRange; - } else { - var narrowed = utils.narrowToNonSpace(content, lastMatch.innerRange); - lastMatch = htmlMatcher.find(content, narrowed.start + 1); - if (lastMatch && lastMatch.range.equal(sel) && lastMatch.outerRange.equal(sel)) { - lastMatch.range = lastMatch.innerRange; - } - } - } - } else { - if ( - !lastMatch.innerRange.equal(lastMatch.outerRange) - && lastMatch.range.equal(lastMatch.innerRange) - && sel.equal(lastMatch.range)) { - lastMatch.range = lastMatch.outerRange; - } else { - lastMatch = htmlMatcher.find(content, sel.start); - if (lastMatch && lastMatch.range.equal(sel) && lastMatch.innerRange.equal(sel)) { - lastMatch.range = lastMatch.outerRange; - } - } - } - } else { - lastMatch = htmlMatcher.find(content, sel.start); - } - - if (lastMatch) { - if (lastMatch.innerRange.equal(sel)) { - lastMatch.range = lastMatch.outerRange; - } - - if (!lastMatch.range.equal(sel)) { - editor.createSelection(lastMatch.range.start, lastMatch.range.end); - return true; - } - } - - lastMatch = null; - return false; - } - - function rangesForCSSRule(rule, pos) { - // find all possible ranges - var ranges = [rule.range(true)]; - - // braces content - ranges.push(rule.valueRange(true)); - - // find nested sections - var nestedSections = cssSections.nestedSectionsInRule(rule); - - // real content, e.g. from first property name to - // last property value - var items = rule.list(); - if (items.length || nestedSections.length) { - var start = Number.POSITIVE_INFINITY, end = -1; - if (items.length) { - start = items[0].namePosition(true); - end = last(items).range(true).end; - } - - if (nestedSections.length) { - if (nestedSections[0].start < start) { - start = nestedSections[0].start; - } - - if (last(nestedSections).end > end) { - end = last(nestedSections).end; - } - } - - ranges.push(range.create2(start, end)); - } - - ranges = ranges.concat(nestedSections); - - var prop = cssEditTree.propertyFromPosition(rule, pos) || items[0]; - if (prop) { - ranges.push(prop.range(true)); - var valueRange = prop.valueRange(true); - if (!prop.end()) { - valueRange._unterminated = true; - } - ranges.push(valueRange); - } - - return ranges; - } - - /** - * Returns all possible selection ranges for given caret position - * @param {String} content CSS content - * @param {Number} pos Caret position(where to start searching) - * @return {Array} - */ - function getCSSRanges(content, pos) { - var rule; - if (typeof content === 'string') { - var ruleRange = cssSections.matchEnclosingRule(content, pos); - if (ruleRange) { - rule = cssEditTree.parse(ruleRange.substring(content), { - offset: ruleRange.start - }); - } - } else { - // passed parsed CSS rule - rule = content; - } - - if (!rule) { - return null; - } - - // find all possible ranges - var ranges = rangesForCSSRule(rule, pos); - - // remove empty ranges - ranges = ranges.filter(function(item) { - return !!item.length; - }); - - return utils.unique(ranges, function(item) { - return item.valueOf(); - }); - } - - function balanceCSS(editor, direction) { - var info = editorUtils.outputInfo(editor); - var content = info.content; - var sel = range(editor.getSelectionRange()); - - var ranges = getCSSRanges(info.content, sel.start); - if (!ranges && sel.length()) { - // possible reason: user has already selected - // CSS rule from last match - try { - var rule = cssEditTree.parse(sel.substring(info.content), { - offset: sel.start - }); - ranges = getCSSRanges(rule, sel.start); - } catch(e) {} - } - - if (!ranges) { - return false; - } - - ranges = range.sort(ranges, true); - - // edge case: find match that equals current selection, - // in case if user moves inward after selecting full CSS rule - var bestMatch = utils.find(ranges, function(r) { - return r.equal(sel); - }); - - if (!bestMatch) { - bestMatch = utils.find(ranges, function(r) { - // Check for edge case: caret right after CSS value - // but it doesn‘t contains terminating semicolon. - // In this case we have to check full value range - return r._unterminated ? r.include(sel.start) : r.inside(sel.start); - }); - } - - if (!bestMatch) { - return false; - } - - // if best match equals to current selection, move index - // one position up or down, depending on direction - var bestMatchIx = ranges.indexOf(bestMatch); - if (bestMatch.equal(sel)) { - bestMatchIx += direction == 'out' ? 1 : -1; - } - - if (bestMatchIx < 0 || bestMatchIx >= ranges.length) { - if (bestMatchIx >= ranges.length && direction == 'out') { - pos = bestMatch.start - 1; - - var outerRanges = getCSSRanges(content, pos); - if (outerRanges) { - bestMatch = last(outerRanges.filter(function(r) { - return r.inside(pos); - })); - } - } else if (bestMatchIx < 0 && direction == 'in') { - bestMatch = null; - } else { - bestMatch = null; - } - } else { - bestMatch = ranges[bestMatchIx]; - } - - if (bestMatch) { - editor.createSelection(bestMatch.start, bestMatch.end); - return true; - } - - return false; - } - - return { - /** - * Find and select HTML tag pair - * @param {IEmmetEditor} editor Editor instance - * @param {String} direction Direction of pair matching: 'in' or 'out'. - * Default is 'out' - */ - balance: function(editor, direction) { - direction = String((direction || 'out').toLowerCase()); - var info = editorUtils.outputInfo(editor); - if (actionUtils.isSupportedCSS(info.syntax)) { - return balanceCSS(editor, direction); - } - - return balanceHTML(editor, direction); - }, - - balanceInwardAction: function(editor) { - return this.balance(editor, 'in'); - }, - - balanceOutwardAction: function(editor) { - return this.balance(editor, 'out'); - }, - - /** - * Moves caret to matching opening or closing tag - * @param {IEmmetEditor} editor - */ - goToMatchingPairAction: function(editor) { - var content = String(editor.getContent()); - var caretPos = editor.getCaretPos(); - - if (content.charAt(caretPos) == '<') - // looks like caret is outside of tag pair - caretPos++; - - var tag = htmlMatcher.tag(content, caretPos); - if (tag && tag.close) { // exclude unary tags - if (tag.open.range.inside(caretPos)) { - editor.setCaretPos(tag.close.range.start); - } else { - editor.setCaretPos(tag.open.range.start); - } - - return true; - } - - return false; - } - }; -}); -},{"../assets/htmlMatcher":26,"../assets/range":30,"../editTree/css":37,"../utils/action":70,"../utils/common":73,"../utils/cssSections":74,"../utils/editor":75}],6:[function(require,module,exports){ -/** - * Encodes/decodes image under cursor to/from base64 - * @param {IEmmetEditor} editor - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var file = require('../plugin/file'); - var base64 = require('../utils/base64'); - var actionUtils = require('../utils/action'); - var editorUtils = require('../utils/editor'); - - /** - * Test if text starts with token at pos - * position. If pos is omitted, search from beginning of text - * @param {String} token Token to test - * @param {String} text Where to search - * @param {Number} pos Position where to start search - * @return {Boolean} - * @since 0.65 - */ - function startsWith(token, text, pos) { - pos = pos || 0; - return text.charAt(pos) == token.charAt(0) && text.substr(pos, token.length) == token; - } - - /** - * Encodes image to base64 - * - * @param {IEmmetEditor} editor - * @param {String} imgPath Path to image - * @param {Number} pos Caret position where image is located in the editor - * @return {Boolean} - */ - function encodeToBase64(editor, imgPath, pos) { - var editorFile = editor.getFilePath(); - var defaultMimeType = 'application/octet-stream'; - - if (editorFile === null) { - throw "You should save your file before using this action"; - } - - // locate real image path - var realImgPath = file.locateFile(editorFile, imgPath); - if (realImgPath === null) { - throw "Can't find " + imgPath + ' file'; - } - - file.read(realImgPath, function(err, content) { - if (err) { - throw 'Unable to read ' + realImgPath + ': ' + err; - } - - var b64 = base64.encode(String(content)); - if (!b64) { - throw "Can't encode file content to base64"; - } - - b64 = 'data:' + (actionUtils.mimeTypes[String(file.getExt(realImgPath))] || defaultMimeType) + - ';base64,' + b64; - - editor.replaceContent('$0' + b64, pos, pos + imgPath.length); - }); - - return true; - } - - /** - * Decodes base64 string back to file. - * @param {IEmmetEditor} editor - * @param {String} data Base64-encoded file content - * @param {Number} pos Caret position where image is located in the editor - */ - function decodeFromBase64(editor, data, pos) { - // ask user to enter path to file - var filePath = String(editor.prompt('Enter path to file (absolute or relative)')); - if (!filePath) - return false; - - var absPath = file.createPath(editor.getFilePath(), filePath); - if (!absPath) { - throw "Can't save file"; - } - - file.save(absPath, base64.decode( data.replace(/^data\:.+?;.+?,/, '') )); - editor.replaceContent('$0' + filePath, pos, pos + data.length); - return true; - } - - return { - /** - * Action to encode or decode file to data:url - * @param {IEmmetEditor} editor Editor instance - * @param {String} syntax Current document syntax - * @param {String} profile Output profile name - * @return {Boolean} - */ - encodeDecodeDataUrlAction: function(editor) { - var data = String(editor.getSelection()); - var caretPos = editor.getCaretPos(); - var info = editorUtils.outputInfo(editor); - - if (!data) { - // no selection, try to find image bounds from current caret position - var text = info.content, m; - while (caretPos-- >= 0) { - if (startsWith('src=', text, caretPos)) { // found - if ((m = text.substr(caretPos).match(/^(src=(["'])?)([^'"<>\s]+)\1?/))) { - data = m[3]; - caretPos += m[1].length; - } - break; - } else if (startsWith('url(', text, caretPos)) { // found CSS url() pattern - if ((m = text.substr(caretPos).match(/^(url\((['"])?)([^'"\)\s]+)\1?/))) { - data = m[3]; - caretPos += m[1].length; - } - break; - } - } - } - - if (data) { - if (startsWith('data:', data)) { - return decodeFromBase64(editor, data, caretPos); - } else { - return encodeToBase64(editor, data, caretPos); - } - } - - return false; - } - }; -}); - -},{"../plugin/file":63,"../utils/action":70,"../utils/base64":71,"../utils/editor":75}],7:[function(require,module,exports){ -/** - * Move between next/prev edit points. 'Edit points' are places between tags - * and quotes of empty attributes in html - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - /** - * Search for new caret insertion point - * @param {IEmmetEditor} editor Editor instance - * @param {Number} inc Search increment: -1 — search left, 1 — search right - * @param {Number} offset Initial offset relative to current caret position - * @return {Number} Returns -1 if insertion point wasn't found - */ - function findNewEditPoint(editor, inc, offset) { - inc = inc || 1; - offset = offset || 0; - - var curPoint = editor.getCaretPos() + offset; - var content = String(editor.getContent()); - var maxLen = content.length; - var nextPoint = -1; - var reEmptyLine = /^\s+$/; - - function getLine(ix) { - var start = ix; - while (start >= 0) { - var c = content.charAt(start); - if (c == '\n' || c == '\r') - break; - start--; - } - - return content.substring(start, ix); - } - - while (curPoint <= maxLen && curPoint >= 0) { - curPoint += inc; - var curChar = content.charAt(curPoint); - var nextChar = content.charAt(curPoint + 1); - var prevChar = content.charAt(curPoint - 1); - - switch (curChar) { - case '"': - case '\'': - if (nextChar == curChar && prevChar == '=') { - // empty attribute - nextPoint = curPoint + 1; - } - break; - case '>': - if (nextChar == '<') { - // between tags - nextPoint = curPoint + 1; - } - break; - case '\n': - case '\r': - // empty line - if (reEmptyLine.test(getLine(curPoint - 1))) { - nextPoint = curPoint; - } - break; - } - - if (nextPoint != -1) - break; - } - - return nextPoint; - } - - return { - /** - * Move to previous edit point - * @param {IEmmetEditor} editor Editor instance - * @param {String} syntax Current document syntax - * @param {String} profile Output profile name - * @return {Boolean} - */ - previousEditPointAction: function(editor, syntax, profile) { - var curPos = editor.getCaretPos(); - var newPoint = findNewEditPoint(editor, -1); - - if (newPoint == curPos) - // we're still in the same point, try searching from the other place - newPoint = findNewEditPoint(editor, -1, -2); - - if (newPoint != -1) { - editor.setCaretPos(newPoint); - return true; - } - - return false; - }, - - /** - * Move to next edit point - * @param {IEmmetEditor} editor Editor instance - * @param {String} syntax Current document syntax - * @param {String} profile Output profile name - * @return {Boolean} - */ - nextEditPointAction: function(editor, syntax, profile) { - var newPoint = findNewEditPoint(editor, 1); - if (newPoint != -1) { - editor.setCaretPos(newPoint); - return true; - } - - return false; - } - }; -}); -},{}],8:[function(require,module,exports){ -/** - * Evaluates simple math expression under caret - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var actionUtils = require('../utils/action'); - var utils = require('../utils/common'); - var math = require('../utils/math'); - var range = require('../assets/range'); - - return { - /** - * Evaluates math expression under the caret - * @param {IEmmetEditor} editor - * @return {Boolean} - */ - evaluateMathAction: function(editor) { - var content = editor.getContent(); - var chars = '.+-*/\\'; - - /** @type Range */ - var sel = range(editor.getSelectionRange()); - if (!sel.length()) { - sel = actionUtils.findExpressionBounds(editor, function(ch) { - return utils.isNumeric(ch) || chars.indexOf(ch) != -1; - }); - } - - if (sel && sel.length()) { - var expr = sel.substring(content); - - // replace integral division: 11\2 => Math.round(11/2) - expr = expr.replace(/([\d\.\-]+)\\([\d\.\-]+)/g, 'round($1/$2)'); - - try { - var result = utils.prettifyNumber(math.evaluate(expr)); - editor.replaceContent(result, sel.start, sel.end); - editor.setCaretPos(sel.start + result.length); - return true; - } catch (e) {} - } - - return false; - } - }; -}); - -},{"../assets/range":30,"../utils/action":70,"../utils/common":73,"../utils/math":76}],9:[function(require,module,exports){ -/** - * 'Expand abbreviation' editor action: extracts abbreviation from current caret - * position and replaces it with formatted output. - *

      - * This behavior can be overridden with custom handlers which can perform - * different actions when 'Expand Abbreviation' action is called. - * For example, a CSS gradient handler that produces vendor-prefixed gradient - * definitions registers its own expand abbreviation handler. - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var handlerList = require('../assets/handlerList'); - var range = require('../assets/range'); - var prefs = require('../assets/preferences'); - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var actionUtils = require('../utils/action'); - var cssGradient = require('../resolver/cssGradient'); - var parser = require('../parser/abbreviation'); - - /** - * Search for abbreviation in editor from current caret position - * @param {IEmmetEditor} editor Editor instance - * @return {String} - */ - function findAbbreviation(editor) { - var r = range(editor.getSelectionRange()); - var content = String(editor.getContent()); - if (r.length()) { - // abbreviation is selected by user - return r.substring(content); - } - - // search for new abbreviation from current caret position - var curLine = editor.getCurrentLineRange(); - return actionUtils.extractAbbreviation(content.substring(curLine.start, r.start)); - } - - /** - * @type HandlerList List of registered handlers - */ - var handlers = handlerList.create(); - - // XXX setup default expand handlers - - /** - * Extracts abbreviation from current caret - * position and replaces it with formatted output - * @param {IEmmetEditor} editor Editor instance - * @param {String} syntax Syntax type (html, css, etc.) - * @param {String} profile Output profile name (html, xml, xhtml) - * @return {Boolean} Returns true if abbreviation was expanded - * successfully - */ - handlers.add(function(editor, syntax, profile) { - var caretPos = editor.getSelectionRange().end; - var abbr = findAbbreviation(editor); - - if (abbr) { - var content = parser.expand(abbr, { - syntax: syntax, - profile: profile, - contextNode: actionUtils.captureContext(editor) - }); - - if (content) { - var replaceFrom = caretPos - abbr.length; - var replaceTo = caretPos; - - // a special case for CSS: if editor already contains - // semicolon right after current caret position — replace it too - var cssSyntaxes = prefs.getArray('css.syntaxes'); - if (cssSyntaxes && ~cssSyntaxes.indexOf(syntax)) { - var curContent = editor.getContent(); - if (curContent.charAt(caretPos) == ';' && content.charAt(content.length - 1) == ';') { - replaceTo++; - } - } - - editor.replaceContent(content, replaceFrom, replaceTo); - return true; - } - } - - return false; - }, {order: -1}); - handlers.add(cssGradient.expandAbbreviationHandler.bind(cssGradient)); - - return { - /** - * The actual “Expand Abbreviation“ action routine - * @param {IEmmetEditor} editor Editor instance - * @param {String} syntax Current document syntax - * @param {String} profile Output profile name - * @return {Boolean} - */ - expandAbbreviationAction: function(editor, syntax, profile) { - var args = utils.toArray(arguments); - - // normalize incoming arguments - var info = editorUtils.outputInfo(editor, syntax, profile); - args[1] = info.syntax; - args[2] = info.profile; - - return handlers.exec(false, args); - }, - - /** - * A special case of “Expand Abbreviation“ action, invoked by Tab key. - * In this case if abbreviation wasn’t expanded successfully or there’s a selecetion, - * the current line/selection will be indented. - * @param {IEmmetEditor} editor Editor instance - * @param {String} syntax Current document syntax - * @param {String} profile Output profile name - * @return {Boolean} - */ - expandAbbreviationWithTabAction: function(editor, syntax, profile) { - var sel = editor.getSelection(); - var indent = '\t'; - - // if something is selected in editor, - // we should indent the selected content - if (sel) { - var selRange = range(editor.getSelectionRange()); - var content = utils.padString(sel, indent); - - editor.replaceContent(indent + '${0}', editor.getCaretPos()); - var replaceRange = range(editor.getCaretPos(), selRange.length()); - editor.replaceContent(content, replaceRange.start, replaceRange.end, true); - editor.createSelection(replaceRange.start, replaceRange.start + content.length); - return true; - } - - // nothing selected, try to expand - if (!this.expandAbbreviationAction(editor, syntax, profile)) { - editor.replaceContent(indent, editor.getCaretPos()); - } - - return true; - }, - - - _defaultHandler: function(editor, syntax, profile) { - var caretPos = editor.getSelectionRange().end; - var abbr = this.findAbbreviation(editor); - - if (abbr) { - var ctx = actionUtils.captureContext(editor); - var content = parser.expand(abbr, syntax, profile, ctx); - if (content) { - editor.replaceContent(content, caretPos - abbr.length, caretPos); - return true; - } - } - - return false; - }, - - /** - * Adds custom expand abbreviation handler. The passed function should - * return true if it was performed successfully, - * false otherwise. - * - * Added handlers will be called when 'Expand Abbreviation' is called - * in order they were added - * @memberOf expandAbbreviation - * @param {Function} fn - * @param {Object} options - */ - addHandler: function(fn, options) { - handlers.add(fn, options); - }, - - /** - * Removes registered handler - * @returns - */ - removeHandler: function(fn) { - handlers.remove(fn); - }, - - findAbbreviation: findAbbreviation - }; -}); -},{"../assets/handlerList":25,"../assets/preferences":28,"../assets/range":30,"../parser/abbreviation":55,"../resolver/cssGradient":65,"../utils/action":70,"../utils/common":73,"../utils/editor":75}],10:[function(require,module,exports){ -/** - * Increment/decrement number under cursor - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - var actionUtils = require('../utils/action'); - - /** - * Returns length of integer part of number - * @param {String} num - */ - function intLength(num) { - num = num.replace(/^\-/, ''); - if (~num.indexOf('.')) { - return num.split('.')[0].length; - } - - return num.length; - } - - return { - increment01Action: function(editor) { - return this.incrementNumber(editor, .1); - }, - - increment1Action: function(editor) { - return this.incrementNumber(editor, 1); - }, - - increment10Action: function(editor) { - return this.incrementNumber(editor, 10); - }, - - decrement01Action: function(editor) { - return this.incrementNumber(editor, -.1); - }, - - decrement1Action: function(editor) { - return this.incrementNumber(editor, -1); - }, - - decrement10Action: function(editor) { - return this.incrementNumber(editor, -10); - }, - - /** - * Default method to increment/decrement number under - * caret with given step - * @param {IEmmetEditor} editor - * @param {Number} step - * @return {Boolean} - */ - incrementNumber: function(editor, step) { - var hasSign = false; - var hasDecimal = false; - - var r = actionUtils.findExpressionBounds(editor, function(ch, pos, content) { - if (utils.isNumeric(ch)) - return true; - if (ch == '.') { - // make sure that next character is numeric too - if (!utils.isNumeric(content.charAt(pos + 1))) - return false; - - return hasDecimal ? false : hasDecimal = true; - } - if (ch == '-') - return hasSign ? false : hasSign = true; - - return false; - }); - - if (r && r.length()) { - var strNum = r.substring(String(editor.getContent())); - var num = parseFloat(strNum); - if (!isNaN(num)) { - num = utils.prettifyNumber(num + step); - - // do we have zero-padded number? - if (/^(\-?)0+[1-9]/.test(strNum)) { - var minus = ''; - if (RegExp.$1) { - minus = '-'; - num = num.substring(1); - } - - var parts = num.split('.'); - parts[0] = utils.zeroPadString(parts[0], intLength(strNum)); - num = minus + parts.join('.'); - } - - editor.replaceContent(num, r.start, r.end); - editor.createSelection(r.start, r.start + num.length); - return true; - } - } - - return false; - } - }; -}); -},{"../utils/action":70,"../utils/common":73}],11:[function(require,module,exports){ -/** - * Actions to insert line breaks. Some simple editors (like browser's - * <textarea>, for example) do not provide such simple things - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var prefs = require('../assets/preferences'); - var utils = require('../utils/common'); - var resources = require('../assets/resources'); - var htmlMatcher = require('../assets/htmlMatcher'); - var editorUtils = require('../utils/editor'); - - var xmlSyntaxes = ['html', 'xml', 'xsl']; - - // setup default preferences - prefs.define('css.closeBraceIndentation', '\n', - 'Indentation before closing brace of CSS rule. Some users prefere ' - + 'indented closing brace of CSS rule for better readability. ' - + 'This preference’s value will be automatically inserted before ' - + 'closing brace when user adds newline in newly created CSS rule ' - + '(e.g. when “Insert formatted linebreak” action will be performed ' - + 'in CSS file). If you’re such user, you may want to write put a value ' - + 'like \\n\\t in this preference.'); - - return { - /** - * Inserts newline character with proper indentation. This action is used in - * editors that doesn't have indentation control (like textarea element) to - * provide proper indentation for inserted newlines - * @param {IEmmetEditor} editor Editor instance - */ - insertLineBreakAction: function(editor) { - if (!this.insertLineBreakOnlyAction(editor)) { - var curPadding = editorUtils.getCurrentLinePadding(editor); - var content = String(editor.getContent()); - var caretPos = editor.getCaretPos(); - var len = content.length; - var nl = '\n'; - - // check out next line padding - var lineRange = editor.getCurrentLineRange(); - var nextPadding = ''; - - for (var i = lineRange.end + 1, ch; i < len; i++) { - ch = content.charAt(i); - if (ch == ' ' || ch == '\t') - nextPadding += ch; - else - break; - } - - if (nextPadding.length > curPadding.length) { - editor.replaceContent(nl + nextPadding, caretPos, caretPos, true); - } else { - editor.replaceContent(nl, caretPos); - } - } - - return true; - }, - - /** - * Inserts newline character with proper indentation in specific positions only. - * @param {IEmmetEditor} editor - * @return {Boolean} Returns true if line break was inserted - */ - insertLineBreakOnlyAction: function(editor) { - var info = editorUtils.outputInfo(editor); - var caretPos = editor.getCaretPos(); - var nl = '\n'; - var pad = '\t'; - - if (~xmlSyntaxes.indexOf(info.syntax)) { - // let's see if we're breaking newly created tag - var tag = htmlMatcher.tag(info.content, caretPos); - if (tag && !tag.innerRange.length()) { - editor.replaceContent(nl + pad + utils.getCaretPlaceholder() + nl, caretPos); - return true; - } - } else if (info.syntax == 'css') { - /** @type String */ - var content = info.content; - if (caretPos && content.charAt(caretPos - 1) == '{') { - var append = prefs.get('css.closeBraceIndentation'); - - var hasCloseBrace = content.charAt(caretPos) == '}'; - if (!hasCloseBrace) { - // do we really need special formatting here? - // check if this is really a newly created rule, - // look ahead for a closing brace - for (var i = caretPos, il = content.length, ch; i < il; i++) { - ch = content.charAt(i); - if (ch == '{') { - // ok, this is a new rule without closing brace - break; - } - - if (ch == '}') { - // not a new rule, just add indentation - append = ''; - hasCloseBrace = true; - break; - } - } - } - - if (!hasCloseBrace) { - append += '}'; - } - - // defining rule set - var insValue = nl + pad + utils.getCaretPlaceholder() + append; - editor.replaceContent(insValue, caretPos); - return true; - } - } - - return false; - } - }; -}); -},{"../assets/htmlMatcher":26,"../assets/preferences":28,"../assets/resources":31,"../utils/common":73,"../utils/editor":75}],12:[function(require,module,exports){ -/** - * Module describes and performs Emmet actions. The actions themselves are - * defined in actions folder - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - - // all registered actions - var actions = {}; - - // load all default actions - var actionModules = { - base64: require('./base64'), - editPoints: require('./editPoints'), - evaluateMath: require('./evaluateMath'), - expandAbbreviation: require('./expandAbbreviation'), - incrementDecrement: require('./incrementDecrement'), - lineBreaks: require('./lineBreaks'), - balance: require('./balance'), - mergeLines: require('./mergeLines'), - reflectCSSValue: require('./reflectCSSValue'), - removeTag: require('./removeTag'), - selectItem: require('./selectItem'), - selectLine: require('./selectLine'), - splitJoinTag: require('./splitJoinTag'), - toggleComment: require('./toggleComment'), - updateImageSize: require('./updateImageSize'), - wrapWithAbbreviation: require('./wrapWithAbbreviation'), - updateTag: require('./updateTag') - }; - - function addAction(name, fn, options) { - name = name.toLowerCase(); - options = options || {}; - - if (typeof options === 'string') { - options = {label: options}; - } - - if (!options.label) { - options.label = humanizeActionName(name); - } - - actions[name] = { - name: name, - fn: fn, - options: options - }; - } - - /** - * “Humanizes” action name, makes it more readable for people - * @param {String} name Action name (like 'expand_abbreviation') - * @return Humanized name (like 'Expand Abbreviation') - */ - function humanizeActionName(name) { - return utils.trim(name.charAt(0).toUpperCase() - + name.substring(1).replace(/_[a-z]/g, function(str) { - return ' ' + str.charAt(1).toUpperCase(); - })); - } - - var bind = function(name, method) { - var m = actionModules[name]; - return m[method].bind(m); - }; - - // XXX register default actions - addAction('encode_decode_data_url', bind('base64', 'encodeDecodeDataUrlAction'), 'Encode\\Decode data:URL image'); - addAction('prev_edit_point', bind('editPoints', 'previousEditPointAction'), 'Previous Edit Point'); - addAction('next_edit_point', bind('editPoints', 'nextEditPointAction'), 'Next Edit Point'); - addAction('evaluate_math_expression', bind('evaluateMath', 'evaluateMathAction'), 'Numbers/Evaluate Math Expression'); - addAction('expand_abbreviation_with_tab', bind('expandAbbreviation', 'expandAbbreviationWithTabAction'), {hidden: true}); - addAction('expand_abbreviation', bind('expandAbbreviation', 'expandAbbreviationAction'), 'Expand Abbreviation'); - addAction('insert_formatted_line_break_only', bind('lineBreaks', 'insertLineBreakOnlyAction'), {hidden: true}); - addAction('insert_formatted_line_break', bind('lineBreaks', 'insertLineBreakAction'), {hidden: true}); - addAction('balance_inward', bind('balance', 'balanceInwardAction'), 'Balance (inward)'); - addAction('balance_outward', bind('balance', 'balanceOutwardAction'), 'Balance (outward)'); - addAction('matching_pair', bind('balance', 'goToMatchingPairAction'), 'HTML/Go To Matching Tag Pair'); - addAction('merge_lines', bind('mergeLines', 'mergeLinesAction'), 'Merge Lines'); - addAction('reflect_css_value', bind('reflectCSSValue', 'reflectCSSValueAction'), 'CSS/Reflect Value'); - addAction('remove_tag', bind('removeTag', 'removeTagAction'), 'HTML/Remove Tag'); - addAction('select_next_item', bind('selectItem', 'selectNextItemAction'), 'Select Next Item'); - addAction('select_previous_item', bind('selectItem', 'selectPreviousItemAction'), 'Select Previous Item'); - addAction('split_join_tag', bind('splitJoinTag', 'splitJoinTagAction'), 'HTML/Split\\Join Tag Declaration'); - addAction('toggle_comment', bind('toggleComment', 'toggleCommentAction'), 'Toggle Comment'); - addAction('update_image_size', bind('updateImageSize', 'updateImageSizeAction'), 'Update Image Size'); - addAction('wrap_with_abbreviation', bind('wrapWithAbbreviation', 'wrapWithAbbreviationAction'), 'Wrap With Abbreviation'); - addAction('update_tag', bind('updateTag', 'updateTagAction'), 'HTML/Update Tag'); - - [1, -1, 10, -10, 0.1, -0.1].forEach(function(num) { - var prefix = num > 0 ? 'increment' : 'decrement'; - var suffix = String(Math.abs(num)).replace('.', '').substring(0, 2); - var actionId = prefix + '_number_by_' + suffix; - var actionMethod = prefix + suffix + 'Action'; - var actionLabel = 'Numbers/' + prefix.charAt(0).toUpperCase() + prefix.substring(1) + ' number by ' + Math.abs(num); - addAction(actionId, bind('incrementDecrement', actionMethod), actionLabel); - }); - - return { - /** - * Registers new action - * @param {String} name Action name - * @param {Function} fn Action function - * @param {Object} options Custom action options:
      - * label : (String) – Human-readable action name. - * May contain '/' symbols as submenu separators
      - * hidden : (Boolean) – Indicates whether action - * should be displayed in menu (getMenu() method) - */ - add: addAction, - - /** - * Returns action object - * @param {String} name Action name - * @returns {Object} - */ - get: function(name) { - return actions[name.toLowerCase()]; - }, - - /** - * Runs Emmet action. For list of available actions and their - * arguments see actions folder. - * @param {String} name Action name - * @param {Array} args Additional arguments. It may be array of arguments - * or inline arguments. The first argument should be IEmmetEditor instance - * @returns {Boolean} Status of performed operation, true - * means action was performed successfully. - * @example - * require('action/main').run('expand_abbreviation', editor); - * require('action/main').run('wrap_with_abbreviation', [editor, 'div']); - */ - run: function(name, args) { - if (!Array.isArray(args)) { - args = utils.toArray(arguments, 1); - } - - var action = this.get(name); - if (!action) { - throw new Error('Action "' + name + '" is not defined'); - } - - return action.fn.apply(action, args); - }, - - /** - * Returns all registered actions as object - * @returns {Object} - */ - getAll: function() { - return actions; - }, - - /** - * Returns all registered actions as array - * @returns {Array} - */ - getList: function() { - var all = this.getAll(); - return Object.keys(all).map(function(key) { - return all[key]; - }); - }, - - /** - * Returns actions list as structured menu. If action has label, - * it will be splitted by '/' symbol into submenus (for example: - * CSS/Reflect Value) and grouped with other items - * @param {Array} skipActions List of action identifiers that should be - * skipped from menu - * @returns {Array} - */ - getMenu: function(skipActions) { - var result = []; - skipActions = skipActions || []; - this.getList().forEach(function(action) { - if (action.options.hidden || ~skipActions.indexOf(action.name)) - return; - - var actionName = humanizeActionName(action.name); - var ctx = result; - if (action.options.label) { - var parts = action.options.label.split('/'); - actionName = parts.pop(); - - // create submenus, if needed - var menuName, submenu; - while ((menuName = parts.shift())) { - submenu = utils.find(ctx, function(item) { - return item.type == 'submenu' && item.name == menuName; - }); - - if (!submenu) { - submenu = { - name: menuName, - type: 'submenu', - items: [] - }; - ctx.push(submenu); - } - - ctx = submenu.items; - } - } - - ctx.push({ - type: 'action', - name: action.name, - label: actionName - }); - }); - - return result; - }, - - /** - * Returns action name associated with menu item title - * @param {String} title - * @returns {String} - */ - getActionNameForMenuTitle: function(title, menu) { - return utils.find(menu || this.getMenu(), function(val) { - if (val.type == 'action') { - if (val.label == title || val.name == title) { - return val.name; - } - } else { - return this.getActionNameForMenuTitle(title, val.items); - } - }, this); - } - }; -}); -},{"../utils/common":73,"./balance":5,"./base64":6,"./editPoints":7,"./evaluateMath":8,"./expandAbbreviation":9,"./incrementDecrement":10,"./lineBreaks":11,"./mergeLines":13,"./reflectCSSValue":14,"./removeTag":15,"./selectItem":16,"./selectLine":17,"./splitJoinTag":18,"./toggleComment":19,"./updateImageSize":20,"./updateTag":21,"./wrapWithAbbreviation":22}],13:[function(require,module,exports){ -/** - * Merges selected lines or lines between XHTML tag pairs - * @param {Function} require - * @param {Underscore} _ - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var htmlMatcher = require('../assets/htmlMatcher'); - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var range = require('../assets/range'); - - return { - mergeLinesAction: function(editor) { - var info = editorUtils.outputInfo(editor); - - var selection = range(editor.getSelectionRange()); - if (!selection.length()) { - // find matching tag - var pair = htmlMatcher.find(info.content, editor.getCaretPos()); - if (pair) { - selection = pair.outerRange; - } - } - - if (selection.length()) { - // got range, merge lines - var text = selection.substring(info.content); - var lines = utils.splitByLines(text); - - for (var i = 1; i < lines.length; i++) { - lines[i] = lines[i].replace(/^\s+/, ''); - } - - text = lines.join('').replace(/\s{2,}/, ' '); - var textLen = text.length; - text = utils.escapeText(text); - editor.replaceContent(text, selection.start, selection.end); - editor.createSelection(selection.start, selection.start + textLen); - - return true; - } - - return false; - } - }; -}); -},{"../assets/htmlMatcher":26,"../assets/range":30,"../utils/common":73,"../utils/editor":75}],14:[function(require,module,exports){ -/** - * Reflect CSS value: takes rule's value under caret and pastes it for the same - * rules with vendor prefixes - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var handlerList = require('../assets/handlerList'); - var prefs = require('../assets/preferences'); - var cssResolver = require('../resolver/css'); - var cssEditTree = require('../editTree/css'); - var utils = require('../utils/common'); - var actionUtils = require('../utils/action'); - var editorUtils = require('../utils/editor'); - var cssGradient = require('../resolver/cssGradient'); - - prefs.define('css.reflect.oldIEOpacity', false, 'Support IE6/7/8 opacity notation, e.g. filter:alpha(opacity=...).\ - Note that CSS3 and SVG also provides filter property so this option is disabled by default.') - - /** - * @type HandlerList List of registered handlers - */ - var handlers = handlerList.create(); - - function doCSSReflection(editor) { - var outputInfo = editorUtils.outputInfo(editor); - var caretPos = editor.getCaretPos(); - - var cssRule = cssEditTree.parseFromPosition(outputInfo.content, caretPos); - if (!cssRule) return; - - var property = cssRule.itemFromPosition(caretPos, true); - // no property under cursor, nothing to reflect - if (!property) return; - - var oldRule = cssRule.source; - var offset = cssRule.options.offset; - var caretDelta = caretPos - offset - property.range().start; - - handlers.exec(false, [property]); - - if (oldRule !== cssRule.source) { - return { - data: cssRule.source, - start: offset, - end: offset + oldRule.length, - caret: offset + property.range().start + caretDelta - }; - } - } - - /** - * Returns regexp that should match reflected CSS property names - * @param {String} name Current CSS property name - * @return {RegExp} - */ - function getReflectedCSSName(name) { - name = cssEditTree.baseName(name); - var vendorPrefix = '^(?:\\-\\w+\\-)?', m; - - if ((name == 'opacity' || name == 'filter') && prefs.get('css.reflect.oldIEOpacity')) { - return new RegExp(vendorPrefix + '(?:opacity|filter)$'); - } else if ((m = name.match(/^border-radius-(top|bottom)(left|right)/))) { - // Mozilla-style border radius - return new RegExp(vendorPrefix + '(?:' + name + '|border-' + m[1] + '-' + m[2] + '-radius)$'); - } else if ((m = name.match(/^border-(top|bottom)-(left|right)-radius/))) { - return new RegExp(vendorPrefix + '(?:' + name + '|border-radius-' + m[1] + m[2] + ')$'); - } - - return new RegExp(vendorPrefix + name + '$'); - } - - /** - * Reflects inner CSS properites in given value - * agains name‘s vendor prefix. In other words, it tries - * to modify `transform 0.2s linear` value for `-webkit-transition` - * property - * @param {String} name Reciever CSS property name - * @param {String} value New property value - * @return {String} - */ - function reflectValueParts(name, value) { - // detects and updates vendor-specific properties in value, - // e.g. -webkit-transition: -webkit-transform - - var reVendor = /^\-(\w+)\-/; - var propPrefix = reVendor.test(name) ? RegExp.$1.toLowerCase() : ''; - var parts = cssEditTree.findParts(value); - - parts.reverse(); - parts.forEach(function(part) { - var partValue = part.substring(value).replace(reVendor, ''); - var prefixes = cssResolver.vendorPrefixes(partValue); - if (prefixes) { - // if prefixes are not null then given value can - // be resolved against Can I Use database and may or - // may not contain prefixed variant - if (propPrefix && ~prefixes.indexOf(propPrefix)) { - partValue = '-' + propPrefix + '-' + partValue; - } - - value = utils.replaceSubstring(value, partValue, part); - } - }); - - return value; - } - - /** - * Reflects value from donor into receiver - * @param {CSSProperty} donor Donor CSS property from which value should - * be reflected - * @param {CSSProperty} receiver Property that should receive reflected - * value from donor - */ - function reflectValue(donor, receiver) { - var value = getReflectedValue(donor.name(), donor.value(), - receiver.name(), receiver.value()); - - value = reflectValueParts(receiver.name(), value); - receiver.value(value); - } - - /** - * Returns value that should be reflected for refName CSS property - * from curName property. This function is used for special cases, - * when the same result must be achieved with different properties for different - * browsers. For example: opаcity:0.5; → filter:alpha(opacity=50);

      - * - * This function does value conversion between different CSS properties - * - * @param {String} curName Current CSS property name - * @param {String} curValue Current CSS property value - * @param {String} refName Receiver CSS property's name - * @param {String} refValue Receiver CSS property's value - * @return {String} New value for receiver property - */ - function getReflectedValue(curName, curValue, refName, refValue) { - curName = cssEditTree.baseName(curName); - refName = cssEditTree.baseName(refName); - - if (curName == 'opacity' && refName == 'filter') { - return refValue.replace(/opacity=[^)]*/i, 'opacity=' + Math.floor(parseFloat(curValue) * 100)); - } else if (curName == 'filter' && refName == 'opacity') { - var m = curValue.match(/opacity=([^)]*)/i); - return m ? utils.prettifyNumber(parseInt(m[1], 10) / 100) : refValue; - } - - return curValue; - } - - module = module || {}; - module.exports = { - reflectCSSValueAction: function(editor) { - if (editor.getSyntax() != 'css') { - return false; - } - - return actionUtils.compoundUpdate(editor, doCSSReflection(editor)); - }, - - _defaultHandler: function(property) { - var reName = getReflectedCSSName(property.name()); - property.parent.list().forEach(function(p) { - if (reName.test(p.name())) { - reflectValue(property, p); - } - }); - }, - - /** - * Adds custom reflect handler. The passed function will receive matched - * CSS property (as CSSEditElement object) and should - * return true if it was performed successfully (handled - * reflection), false otherwise. - * @param {Function} fn - * @param {Object} options - */ - addHandler: function(fn, options) { - handlers.add(fn, options); - }, - - /** - * Removes registered handler - * @returns - */ - removeHandler: function(fn) { - handlers.remove(fn); - } - }; - - // XXX add default handlers - handlers.add(module.exports._defaultHandler.bind(module.exports), {order: -1}); - handlers.add(cssGradient.reflectValueHandler.bind(cssGradient)); - - return module.exports; -}); -},{"../assets/handlerList":25,"../assets/preferences":28,"../editTree/css":37,"../resolver/css":64,"../resolver/cssGradient":65,"../utils/action":70,"../utils/common":73,"../utils/editor":75}],15:[function(require,module,exports){ -/** - * Gracefully removes tag under cursor - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var htmlMatcher = require('../assets/htmlMatcher'); - - return { - removeTagAction: function(editor) { - var info = editorUtils.outputInfo(editor); - - // search for tag - var tag = htmlMatcher.tag(info.content, editor.getCaretPos()); - if (tag) { - if (!tag.close) { - // simply remove unary tag - editor.replaceContent(utils.getCaretPlaceholder(), tag.range.start, tag.range.end); - } else { - // remove tag and its newlines - /** @type Range */ - var tagContentRange = utils.narrowToNonSpace(info.content, tag.innerRange); - /** @type Range */ - var startLineBounds = utils.findNewlineBounds(info.content, tagContentRange.start); - var startLinePad = utils.getLinePadding(startLineBounds.substring(info.content)); - var tagContent = tagContentRange.substring(info.content); - - tagContent = utils.unindentString(tagContent, startLinePad); - editor.replaceContent(utils.getCaretPlaceholder() + utils.escapeText(tagContent), tag.outerRange.start, tag.outerRange.end); - } - - return true; - } - - return false; - } - }; -}); - -},{"../assets/htmlMatcher":26,"../utils/common":73,"../utils/editor":75}],16:[function(require,module,exports){ -/** - * Actions that use stream parsers and tokenizers for traversing: - * -- Search for next/previous items in HTML - * -- Search for next/previous items in CSS - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var range = require('../assets/range'); - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var actionUtils = require('../utils/action'); - var stringStream = require('../assets/stringStream'); - var xmlParser = require('../parser/xml'); - var cssEditTree = require('../editTree/css'); - var cssSections = require('../utils/cssSections'); - - var startTag = /^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/; - - /** - * Generic function for searching for items to select - * @param {IEmmetEditor} editor - * @param {Boolean} isBackward Search backward (search forward otherwise) - * @param {Function} extractFn Function that extracts item content - * @param {Function} rangeFn Function that search for next token range - */ - function findItem(editor, isBackward, extractFn, rangeFn) { - var content = editorUtils.outputInfo(editor).content; - - var contentLength = content.length; - var itemRange, rng; - /** @type Range */ - var prevRange = range(-1, 0); - /** @type Range */ - var sel = range(editor.getSelectionRange()); - - var searchPos = sel.start, loop = 100000; // endless loop protection - while (searchPos >= 0 && searchPos < contentLength && --loop > 0) { - if ( (itemRange = extractFn(content, searchPos, isBackward)) ) { - if (prevRange.equal(itemRange)) { - break; - } - - prevRange = itemRange.clone(); - rng = rangeFn(itemRange.substring(content), itemRange.start, sel.clone()); - - if (rng) { - editor.createSelection(rng.start, rng.end); - return true; - } else { - searchPos = isBackward ? itemRange.start : itemRange.end - 1; - } - } - - searchPos += isBackward ? -1 : 1; - } - - return false; - } - - // XXX HTML section - - /** - * Find next HTML item - * @param {IEmmetEditor} editor - */ - function findNextHTMLItem(editor) { - var isFirst = true; - return findItem(editor, false, function(content, searchPos){ - if (isFirst) { - isFirst = false; - return findOpeningTagFromPosition(content, searchPos); - } else { - return getOpeningTagFromPosition(content, searchPos); - } - }, function(tag, offset, selRange) { - return getRangeForHTMLItem(tag, offset, selRange, false); - }); - } - - /** - * Find previous HTML item - * @param {IEmmetEditor} editor - */ - function findPrevHTMLItem(editor) { - return findItem(editor, true, getOpeningTagFromPosition, function (tag, offset, selRange) { - return getRangeForHTMLItem(tag, offset, selRange, true); - }); - } - - /** - * Creates possible selection ranges for HTML tag - * @param {String} source Original HTML source for tokens - * @param {Array} tokens List of HTML tokens - * @returns {Array} - */ - function makePossibleRangesHTML(source, tokens, offset) { - offset = offset || 0; - var result = []; - var attrStart = -1, attrName = '', attrValue = '', attrValueRange, tagName; - tokens.forEach(function(tok) { - switch (tok.type) { - case 'tag': - tagName = source.substring(tok.start, tok.end); - if (/^<[\w\:\-]/.test(tagName)) { - // add tag name - result.push(range({ - start: tok.start + 1, - end: tok.end - })); - } - break; - case 'attribute': - attrStart = tok.start; - attrName = source.substring(tok.start, tok.end); - break; - - case 'string': - // attribute value - // push full attribute first - result.push(range(attrStart, tok.end - attrStart)); - - attrValueRange = range(tok); - attrValue = attrValueRange.substring(source); - - // is this a quoted attribute? - if (isQuote(attrValue.charAt(0))) - attrValueRange.start++; - - if (isQuote(attrValue.charAt(attrValue.length - 1))) - attrValueRange.end--; - - result.push(attrValueRange); - - if (attrName == 'class') { - result = result.concat(classNameRanges(attrValueRange.substring(source), attrValueRange.start)); - } - - break; - } - }); - - // offset ranges - result = result.filter(function(item) { - if (item.length()) { - item.shift(offset); - return true; - } - }); - - // remove duplicates - return utils.unique(result, function(item) { - return item.toString(); - }); - } - - /** - * Returns ranges of class names in "class" attribute value - * @param {String} className - * @returns {Array} - */ - function classNameRanges(className, offset) { - offset = offset || 0; - var result = []; - /** @type StringStream */ - var stream = stringStream.create(className); - - // skip whitespace - stream.eatSpace(); - stream.start = stream.pos; - - var ch; - while ((ch = stream.next())) { - if (/[\s\u00a0]/.test(ch)) { - result.push(range(stream.start + offset, stream.pos - stream.start - 1)); - stream.eatSpace(); - stream.start = stream.pos; - } - } - - result.push(range(stream.start + offset, stream.pos - stream.start)); - return result; - } - - /** - * Returns best HTML tag range match for current selection - * @param {String} tag Tag declaration - * @param {Number} offset Tag's position index inside content - * @param {Range} selRange Selection range - * @return {Range} Returns range if next item was found, null otherwise - */ - function getRangeForHTMLItem(tag, offset, selRange, isBackward) { - var ranges = makePossibleRangesHTML(tag, xmlParser.parse(tag), offset); - - if (isBackward) - ranges.reverse(); - - // try to find selected range - var curRange = utils.find(ranges, function(r) { - return r.equal(selRange); - }); - - if (curRange) { - var ix = ranges.indexOf(curRange); - if (ix < ranges.length - 1) - return ranges[ix + 1]; - - return null; - } - - // no selected range, find nearest one - if (isBackward) - // search backward - return utils.find(ranges, function(r) { - return r.start < selRange.start; - }); - - // search forward - // to deal with overlapping ranges (like full attribute definition - // and attribute value) let's find range under caret first - if (!curRange) { - var matchedRanges = ranges.filter(function(r) { - return r.inside(selRange.end); - }); - - if (matchedRanges.length > 1) - return matchedRanges[1]; - } - - - return utils.find(ranges, function(r) { - return r.end > selRange.end; - }); - } - - /** - * Search for opening tag in content, starting at specified position - * @param {String} html Where to search tag - * @param {Number} pos Character index where to start searching - * @return {Range} Returns range if valid opening tag was found, - * null otherwise - */ - function findOpeningTagFromPosition(html, pos) { - var tag; - while (pos >= 0) { - if ((tag = getOpeningTagFromPosition(html, pos))) - return tag; - pos--; - } - - return null; - } - - /** - * @param {String} html Where to search tag - * @param {Number} pos Character index where to start searching - * @return {Range} Returns range if valid opening tag was found, - * null otherwise - */ - function getOpeningTagFromPosition(html, pos) { - var m; - if (html.charAt(pos) == '<' && (m = html.substring(pos, html.length).match(startTag))) { - return range(pos, m[0]); - } - } - - function isQuote(ch) { - return ch == '"' || ch == "'"; - } - - /** - * Returns all ranges inside given rule, available for selection - * @param {CSSEditContainer} rule - * @return {Array} - */ - function findInnerRanges(rule) { - // rule selector - var ranges = [rule.nameRange(true)]; - - // find nested sections, keep selectors only - var nestedSections = cssSections.nestedSectionsInRule(rule); - nestedSections.forEach(function(section) { - ranges.push(range.create2(section.start, section._selectorEnd)); - }); - - // add full property ranges and values - rule.list().forEach(function(property) { - ranges = ranges.concat(makePossibleRangesCSS(property)); - }); - - ranges = range.sort(ranges); - - // optimize result: remove empty ranges and duplicates - ranges = ranges.filter(function(item) { - return !!item.length(); - }); - return utils.unique(ranges, function(item) { - return item.toString(); - }); - } - - /** - * Makes all possible selection ranges for specified CSS property - * @param {CSSProperty} property - * @returns {Array} - */ - function makePossibleRangesCSS(property) { - // find all possible ranges, sorted by position and size - var valueRange = property.valueRange(true); - var result = [property.range(true), valueRange]; - - // locate parts of complex values. - // some examples: - // – 1px solid red: 3 parts - // – arial, sans-serif: enumeration, 2 parts - // – url(image.png): function value part - var value = property.value(); - property.valueParts().forEach(function(r) { - // add absolute range - var clone = r.clone(); - result.push(clone.shift(valueRange.start)); - - /** @type StringStream */ - var stream = stringStream.create(r.substring(value)); - if (stream.match(/^[\w\-]+\(/, true)) { - // we have a function, find values in it. - // but first add function contents - stream.start = stream.pos; - stream.backUp(1); - stream.skipToPair('(', ')'); - stream.backUp(1); - var fnBody = stream.current(); - result.push(range(clone.start + stream.start, fnBody)); - - // find parts - cssEditTree.findParts(fnBody).forEach(function(part) { - result.push(range(clone.start + stream.start + part.start, part.substring(fnBody))); - }); - } - }); - - return result; - } - - /** - * Tries to find matched CSS property and nearest range for selection - * @param {CSSRule} rule - * @param {Range} selRange - * @param {Boolean} isBackward - * @returns {Range} - */ - function matchedRangeForCSSProperty(rule, selRange, isBackward) { - var ranges = findInnerRanges(rule); - if (isBackward) { - ranges.reverse(); - } - - // return next to selected range, if possible - var r = utils.find(ranges, function(item) { - return item.equal(selRange); - }); - - if (r) { - return ranges[ranges.indexOf(r) + 1]; - } - - // find matched and (possibly) overlapping ranges - var nested = ranges.filter(function(item) { - return item.inside(selRange.end); - }); - - if (nested.length) { - return nested.sort(function(a, b) { - return a.length() - b.length(); - })[0]; - } - - // return range next to caret - var test = - r = utils.find(ranges, isBackward - ? function(item) {return item.end < selRange.start;} - : function(item) {return item.end > selRange.start;} - ); - - if (!r) { - // can’t find anything, just pick first one - r = ranges[0]; - } - - return r; - } - - function findNextCSSItem(editor) { - return findItem(editor, false, cssSections.locateRule.bind(cssSections), getRangeForNextItemInCSS); - } - - function findPrevCSSItem(editor) { - return findItem(editor, true, cssSections.locateRule.bind(cssSections), getRangeForPrevItemInCSS); - } - - /** - * Returns range for item to be selected in CSS after current caret - * (selection) position - * @param {String} rule CSS rule declaration - * @param {Number} offset Rule's position index inside content - * @param {Range} selRange Selection range - * @return {Range} Returns range if next item was found, null otherwise - */ - function getRangeForNextItemInCSS(rule, offset, selRange) { - var tree = cssEditTree.parse(rule, { - offset: offset - }); - - return matchedRangeForCSSProperty(tree, selRange, false); - } - - /** - * Returns range for item to be selected in CSS before current caret - * (selection) position - * @param {String} rule CSS rule declaration - * @param {Number} offset Rule's position index inside content - * @param {Range} selRange Selection range - * @return {Range} Returns range if previous item was found, null otherwise - */ - function getRangeForPrevItemInCSS(rule, offset, selRange) { - var tree = cssEditTree.parse(rule, { - offset: offset - }); - - return matchedRangeForCSSProperty(tree, selRange, true); - } - - return { - selectNextItemAction: function(editor) { - if (actionUtils.isSupportedCSS(editor.getSyntax())) { - return findNextCSSItem(editor); - } else { - return findNextHTMLItem(editor); - } - }, - - selectPreviousItemAction: function(editor) { - if (actionUtils.isSupportedCSS(editor.getSyntax())) { - return findPrevCSSItem(editor); - } else { - return findPrevHTMLItem(editor); - } - } - }; -}); -},{"../assets/range":30,"../assets/stringStream":32,"../editTree/css":37,"../parser/xml":62,"../utils/action":70,"../utils/common":73,"../utils/cssSections":74,"../utils/editor":75}],17:[function(require,module,exports){ -/** - * Select current line (for simple editors like browser's <textarea>) - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - return { - selectLineAction: function(editor) { - var range = editor.getCurrentLineRange(); - editor.createSelection(range.start, range.end); - return true; - } - }; -}); -},{}],18:[function(require,module,exports){ -/** - * Splits or joins tag, e.g. transforms it into a short notation and vice versa:
      - * <div></div> → <div /> : join
      - * <div /> → <div></div> : split - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - var resources = require('../assets/resources'); - var matcher = require('../assets/htmlMatcher'); - var editorUtils = require('../utils/editor'); - var profile = require('../assets/profile'); - - /** - * @param {IEmmetEditor} editor - * @param {Object} profile - * @param {Object} tag - */ - function joinTag(editor, profile, tag) { - // empty closing slash is a nonsense for this action - var slash = profile.selfClosing() || ' /'; - var content = tag.open.range.substring(tag.source).replace(/\s*>$/, slash + '>'); - - var caretPos = editor.getCaretPos(); - - // update caret position - if (content.length + tag.outerRange.start < caretPos) { - caretPos = content.length + tag.outerRange.start; - } - - content = utils.escapeText(content); - editor.replaceContent(content, tag.outerRange.start, tag.outerRange.end); - editor.setCaretPos(caretPos); - return true; - } - - function splitTag(editor, profile, tag) { - var caretPos = editor.getCaretPos(); - - // define tag content depending on profile - var tagContent = (profile.tag_nl === true) ? '\n\t\n' : ''; - var content = tag.outerContent().replace(/\s*\/>$/, '>'); - caretPos = tag.outerRange.start + content.length; - content += tagContent + ''; - - content = utils.escapeText(content); - editor.replaceContent(content, tag.outerRange.start, tag.outerRange.end); - editor.setCaretPos(caretPos); - return true; - } - - return { - splitJoinTagAction: function(editor, profileName) { - var info = editorUtils.outputInfo(editor, null, profileName); - var curProfile = profile.get(info.profile); - - // find tag at current position - var tag = matcher.tag(info.content, editor.getCaretPos()); - if (tag) { - return tag.close - ? joinTag(editor, curProfile, tag) - : splitTag(editor, curProfile, tag); - } - - return false; - } - }; -}); -},{"../assets/htmlMatcher":26,"../assets/profile":29,"../assets/resources":31,"../utils/common":73,"../utils/editor":75}],19:[function(require,module,exports){ -/** - * Toggles HTML and CSS comments depending on current caret context. Unlike - * the same action in most editors, this action toggles comment on currently - * matched item—HTML tag or CSS selector—when nothing is selected. - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var prefs = require('../assets/preferences'); - var range = require('../assets/range'); - var utils = require('../utils/common'); - var actionUtils = require('../utils/action'); - var editorUtils = require('../utils/editor'); - var htmlMatcher = require('../assets/htmlMatcher'); - var cssEditTree = require('../editTree/css'); - - /** - * Toggle HTML comment on current selection or tag - * @param {IEmmetEditor} editor - * @return {Boolean} Returns true if comment was toggled - */ - function toggleHTMLComment(editor) { - /** @type Range */ - var r = range(editor.getSelectionRange()); - var info = editorUtils.outputInfo(editor); - - if (!r.length()) { - // no selection, find matching tag - var tag = htmlMatcher.tag(info.content, editor.getCaretPos()); - if (tag) { // found pair - r = tag.outerRange; - } - } - - return genericCommentToggle(editor, '', r); - } - - /** - * Simple CSS commenting - * @param {IEmmetEditor} editor - * @return {Boolean} Returns true if comment was toggled - */ - function toggleCSSComment(editor) { - /** @type Range */ - var rng = range(editor.getSelectionRange()); - var info = editorUtils.outputInfo(editor); - - if (!rng.length()) { - // no selection, try to get current rule - /** @type CSSRule */ - var rule = cssEditTree.parseFromPosition(info.content, editor.getCaretPos()); - if (rule) { - var property = cssItemFromPosition(rule, editor.getCaretPos()); - rng = property - ? property.range(true) - : range(rule.nameRange(true).start, rule.source); - } - } - - if (!rng.length()) { - // still no selection, get current line - rng = range(editor.getCurrentLineRange()); - utils.narrowToNonSpace(info.content, rng); - } - - return genericCommentToggle(editor, '/*', '*/', rng); - } - - /** - * Returns CSS property from rule that matches passed position - * @param {EditContainer} rule - * @param {Number} absPos - * @returns {EditElement} - */ - function cssItemFromPosition(rule, absPos) { - // do not use default EditContainer.itemFromPosition() here, because - // we need to make a few assumptions to make CSS commenting more reliable - var relPos = absPos - (rule.options.offset || 0); - var reSafeChar = /^[\s\n\r]/; - return utils.find(rule.list(), function(item) { - if (item.range().end === relPos) { - // at the end of property, but outside of it - // if there’s a space character at current position, - // use current property - return reSafeChar.test(rule.source.charAt(relPos)); - } - - return item.range().inside(relPos); - }); - } - - /** - * Search for nearest comment in str, starting from index from - * @param {String} text Where to search - * @param {Number} from Search start index - * @param {String} start_token Comment start string - * @param {String} end_token Comment end string - * @return {Range} Returns null if comment wasn't found - */ - function searchComment(text, from, startToken, endToken) { - var commentStart = -1; - var commentEnd = -1; - - var hasMatch = function(str, start) { - return text.substr(start, str.length) == str; - }; - - // search for comment start - while (from--) { - if (hasMatch(startToken, from)) { - commentStart = from; - break; - } - } - - if (commentStart != -1) { - // search for comment end - from = commentStart; - var contentLen = text.length; - while (contentLen >= from++) { - if (hasMatch(endToken, from)) { - commentEnd = from + endToken.length; - break; - } - } - } - - return (commentStart != -1 && commentEnd != -1) - ? range(commentStart, commentEnd - commentStart) - : null; - } - - /** - * Generic comment toggling routine - * @param {IEmmetEditor} editor - * @param {String} commentStart Comment start token - * @param {String} commentEnd Comment end token - * @param {Range} range Selection range - * @return {Boolean} - */ - function genericCommentToggle(editor, commentStart, commentEnd, range) { - var content = editorUtils.outputInfo(editor).content; - var caretPos = editor.getCaretPos(); - var newContent = null; - - /** - * Remove comment markers from string - * @param {Sting} str - * @return {String} - */ - function removeComment(str) { - return str - .replace(new RegExp('^' + utils.escapeForRegexp(commentStart) + '\\s*'), function(str){ - caretPos -= str.length; - return ''; - }).replace(new RegExp('\\s*' + utils.escapeForRegexp(commentEnd) + '$'), ''); - } - - // first, we need to make sure that this substring is not inside - // comment - var commentRange = searchComment(content, caretPos, commentStart, commentEnd); - if (commentRange && commentRange.overlap(range)) { - // we're inside comment, remove it - range = commentRange; - newContent = removeComment(range.substring(content)); - } else { - // should add comment - // make sure that there's no comment inside selection - newContent = commentStart + ' ' + - range.substring(content) - .replace(new RegExp(utils.escapeForRegexp(commentStart) + '\\s*|\\s*' + utils.escapeForRegexp(commentEnd), 'g'), '') + - ' ' + commentEnd; - - // adjust caret position - caretPos += commentStart.length + 1; - } - - // replace editor content - if (newContent !== null) { - newContent = utils.escapeText(newContent); - editor.setCaretPos(range.start); - editor.replaceContent(editorUtils.unindent(editor, newContent), range.start, range.end); - editor.setCaretPos(caretPos); - return true; - } - - return false; - } - - return { - /** - * Toggle comment on current editor's selection or HTML tag/CSS rule - * @param {IEmmetEditor} editor - */ - toggleCommentAction: function(editor) { - var info = editorUtils.outputInfo(editor); - if (actionUtils.isSupportedCSS(info.syntax)) { - // in case our editor is good enough and can recognize syntax from - // current token, we have to make sure that cursor is not inside - // 'style' attribute of html element - var caretPos = editor.getCaretPos(); - var tag = htmlMatcher.tag(info.content, caretPos); - if (tag && tag.open.range.inside(caretPos)) { - info.syntax = 'html'; - } - } - - var cssSyntaxes = prefs.getArray('css.syntaxes'); - if (~cssSyntaxes.indexOf(info.syntax)) { - return toggleCSSComment(editor); - } - - return toggleHTMLComment(editor); - } - }; -}); -},{"../assets/htmlMatcher":26,"../assets/preferences":28,"../assets/range":30,"../editTree/css":37,"../utils/action":70,"../utils/common":73,"../utils/editor":75}],20:[function(require,module,exports){ -/** - * Automatically updates image size attributes in HTML's <img> element or - * CSS rule - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var actionUtils = require('../utils/action'); - var xmlEditTree = require('../editTree/xml'); - var cssEditTree = require('../editTree/css'); - var base64 = require('../utils/base64'); - var file = require('../plugin/file'); - - /** - * Updates image size of <img src=""> tag - * @param {IEmmetEditor} editor - */ - function updateImageSizeHTML(editor) { - var offset = editor.getCaretPos(); - - // find tag from current caret position - var info = editorUtils.outputInfo(editor); - var xmlElem = xmlEditTree.parseFromPosition(info.content, offset, true); - if (xmlElem && (xmlElem.name() || '').toLowerCase() == 'img') { - getImageSizeForSource(editor, xmlElem.value('src'), function(size) { - if (size) { - var compoundData = xmlElem.range(true); - xmlElem.value('width', size.width); - xmlElem.value('height', size.height, xmlElem.indexOf('width') + 1); - - actionUtils.compoundUpdate(editor, utils.extend(compoundData, { - data: xmlElem.toString(), - caret: offset - })); - } - }); - } - } - - /** - * Updates image size of CSS property - * @param {IEmmetEditor} editor - */ - function updateImageSizeCSS(editor) { - var offset = editor.getCaretPos(); - - // find tag from current caret position - var info = editorUtils.outputInfo(editor); - var cssRule = cssEditTree.parseFromPosition(info.content, offset, true); - if (cssRule) { - // check if there is property with image under caret - var prop = cssRule.itemFromPosition(offset, true), m; - if (prop && (m = /url\((["']?)(.+?)\1\)/i.exec(prop.value() || ''))) { - getImageSizeForSource(editor, m[2], function(size) { - if (size) { - var compoundData = cssRule.range(true); - cssRule.value('width', size.width + 'px'); - cssRule.value('height', size.height + 'px', cssRule.indexOf('width') + 1); - - actionUtils.compoundUpdate(editor, utils.extend(compoundData, { - data: cssRule.toString(), - caret: offset - })); - } - }); - } - } - } - - /** - * Returns image dimensions for source - * @param {IEmmetEditor} editor - * @param {String} src Image source (path or data:url) - */ - function getImageSizeForSource(editor, src, callback) { - var fileContent; - if (src) { - // check if it is data:url - if (/^data:/.test(src)) { - fileContent = base64.decode( src.replace(/^data\:.+?;.+?,/, '') ); - return callback(actionUtils.getImageSize(fileContent)); - } - - var absPath = file.locateFile(editor.getFilePath(), src); - if (absPath === null) { - throw "Can't find " + src + ' file'; - } - - file.read(absPath, function(err, content) { - if (err) { - throw 'Unable to read ' + absPath + ': ' + err; - } - - content = String(content); - callback(actionUtils.getImageSize(content)); - }); - } - } - - return { - updateImageSizeAction: function(editor) { - // this action will definitely won’t work in SASS dialect, - // but may work in SCSS or LESS - if (actionUtils.isSupportedCSS(editor.getSyntax())) { - updateImageSizeCSS(editor); - } else { - updateImageSizeHTML(editor); - } - - return true; - } - }; -}); -},{"../editTree/css":37,"../editTree/xml":38,"../plugin/file":63,"../utils/action":70,"../utils/base64":71,"../utils/common":73,"../utils/editor":75}],21:[function(require,module,exports){ -/** - * Update Tag action: allows users to update existing HTML tags and add/remove - * attributes or even tag name - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var xmlEditTree = require('../editTree/xml'); - var editorUtils = require('../utils/editor'); - var actionUtils = require('../utils/action'); - var utils = require('../utils/common'); - var parser = require('../parser/abbreviation'); - - function updateAttributes(tag, abbrNode, ix) { - var classNames = (abbrNode.attribute('class') || '').split(/\s+/g); - if (ix) { - classNames.push('+' + abbrNode.name()); - } - - var r = function(str) { - return utils.replaceCounter(str, abbrNode.counter); - }; - - // update class - classNames.forEach(function(className) { - if (!className) { - return; - } - - className = r(className); - var ch = className.charAt(0); - if (ch == '+') { - tag.addClass(className.substr(1)); - } else if (ch == '-') { - tag.removeClass(className.substr(1)); - } else { - tag.value('class', className); - } - }); - - // update attributes - abbrNode.attributeList().forEach(function(attr) { - if (attr.name.toLowerCase() == 'class') { - return; - } - - var ch = attr.name.charAt(0); - if (ch == '+') { - var attrName = attr.name.substr(1); - var tagAttr = tag.get(attrName); - if (tagAttr) { - tagAttr.value(tagAttr.value() + r(attr.value)); - } else { - tag.value(attrName, r(attr.value)); - } - } else if (ch == '-') { - tag.remove(attr.name.substr(1)); - } else { - tag.value(attr.name, r(attr.value)); - } - }); - } - - return { - /** - * Matches HTML tag under caret and updates its definition - * according to given abbreviation - * @param {IEmmetEditor} Editor instance - * @param {String} abbr Abbreviation to update with - */ - updateTagAction: function(editor, abbr) { - abbr = abbr || editor.prompt("Enter abbreviation"); - - if (!abbr) { - return false; - } - - var content = editor.getContent(); - var ctx = actionUtils.captureContext(editor); - var tag = this.getUpdatedTag(abbr, ctx, content); - - if (!tag) { - // nothing to update - return false; - } - - // check if tag name was updated - if (tag.name() != ctx.name && ctx.match.close) { - editor.replaceContent('', ctx.match.close.range.start, ctx.match.close.range.end, true); - } - - editor.replaceContent(tag.source, ctx.match.open.range.start, ctx.match.open.range.end, true); - return true; - }, - - /** - * Returns XMLEditContainer node with updated tag structure - * of existing tag context. - * This data can be used to modify existing tag - * @param {String} abbr Abbreviation - * @param {Object} ctx Tag to be updated (captured with `htmlMatcher`) - * @param {String} content Original editor content - * @return {XMLEditContainer} - */ - getUpdatedTag: function(abbr, ctx, content, options) { - if (!ctx) { - // nothing to update - return null; - } - - var tree = parser.parse(abbr, options || {}); - - // for this action some characters in abbreviation has special - // meaning. For example, `.-c2` means “remove `c2` class from - // element” and `.+c3` means “append class `c3` to exising one. - // - // But `.+c3` abbreviation will actually produce two elements: - //
      and . Thus, we have to walk on each element - // of parsed tree and use their definitions to update current element - var tag = xmlEditTree.parse(ctx.match.open.range.substring(content), { - offset: ctx.match.outerRange.start - }); - - tree.children.forEach(function(node, i) { - updateAttributes(tag, node, i); - }); - - // if tag name was resolved by implicit tag name resolver, - // then user omitted it in abbreviation and wants to keep - // original tag name - var el = tree.children[0]; - if (!el.data('nameResolved')) { - tag.name(el.name()); - } - - return tag; - } - }; -}); -},{"../editTree/xml":38,"../parser/abbreviation":55,"../utils/action":70,"../utils/common":73,"../utils/editor":75}],22:[function(require,module,exports){ -/** - * Action that wraps content with abbreviation. For convenience, action is - * defined as reusable module - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var range = require('../assets/range'); - var htmlMatcher = require('../assets/htmlMatcher'); - var utils = require('../utils/common'); - var editorUtils = require('../utils/editor'); - var actionUtils = require('../utils/action'); - var parser = require('../parser/abbreviation'); - - return { - /** - * Wraps content with abbreviation - * @param {IEmmetEditor} Editor instance - * @param {String} abbr Abbreviation to wrap with - * @param {String} syntax Syntax type (html, css, etc.) - * @param {String} profile Output profile name (html, xml, xhtml) - */ - wrapWithAbbreviationAction: function(editor, abbr, syntax, profile) { - var info = editorUtils.outputInfo(editor, syntax, profile); - abbr = abbr || editor.prompt("Enter abbreviation"); - - if (!abbr) { - return null; - } - - abbr = String(abbr); - - var r = range(editor.getSelectionRange()); - - if (!r.length()) { - // no selection, find tag pair - var match = htmlMatcher.tag(info.content, r.start); - if (!match) { // nothing to wrap - return false; - } - - r = utils.narrowToNonSpace(info.content, match.range); - } - - var newContent = utils.escapeText(r.substring(info.content)); - var result = parser.expand(abbr, { - pastedContent: editorUtils.unindent(editor, newContent), - syntax: info.syntax, - profile: info.profile, - contextNode: actionUtils.captureContext(editor) - }); - - if (result) { - editor.replaceContent(result, r.start, r.end); - return true; - } - - return false; - } - }; -}); -},{"../assets/htmlMatcher":26,"../assets/range":30,"../parser/abbreviation":55,"../utils/action":70,"../utils/common":73,"../utils/editor":75}],23:[function(require,module,exports){ -/** - * Parsed resources (snippets, abbreviations, variables, etc.) for Emmet. - * Contains convenient method to get access for snippets with respect of - * inheritance. Also provides ability to store data in different vocabularies - * ('system' and 'user') for fast and safe resource update - * @author Sergey Chikuyonok (serge.che@gmail.com) - * @link http://chikuyonok.ru - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var prefs = require('./preferences'); - var utils = require('../utils/common'); - - prefs.define('caniuse.enabled', true, 'Enable support of Can I Use database. When enabled,\ - CSS abbreviation resolver will look at Can I Use database first before detecting\ - CSS properties that should be resolved'); - - prefs.define('caniuse.vendors', 'all', 'A comma-separated list vendor identifiers\ - (as described in Can I Use database) that should be supported\ - when resolving vendor-prefixed properties. Set value to all\ - to support all available properties'); - - prefs.define('caniuse.era', 'e-2', 'Browser era, as defined in Can I Use database.\ - Examples: e0 (current version), e1 (near future)\ - e-2 (2 versions back) and so on.'); - - var cssSections = { - 'border-image': ['border-image'], - 'css-boxshadow': ['box-shadow'], - 'css3-boxsizing': ['box-sizing'], - 'multicolumn': ['column-width', 'column-count', 'columns', 'column-gap', 'column-rule-color', 'column-rule-style', 'column-rule-width', 'column-rule', 'column-span', 'column-fill'], - 'border-radius': ['border-radius', 'border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius'], - 'transforms2d': ['transform'], - 'css-hyphens': ['hyphens'], - 'css-transitions': ['transition', 'transition-property', 'transition-duration', 'transition-timing-function', 'transition-delay'], - 'font-feature': ['font-feature-settings'], - 'css-animation': ['animation', 'animation-name', 'animation-duration', 'animation-timing-function', 'animation-iteration-count', 'animation-direction', 'animation-play-state', 'animation-delay', 'animation-fill-mode', '@keyframes'], - 'css-gradients': ['linear-gradient'], - 'css-masks': ['mask-image', 'mask-source-type', 'mask-repeat', 'mask-position', 'mask-clip', 'mask-origin', 'mask-size', 'mask', 'mask-type', 'mask-box-image-source', 'mask-box-image-slice', 'mask-box-image-width', 'mask-box-image-outset', 'mask-box-image-repeat', 'mask-box-image', 'clip-path', 'clip-rule'], - 'css-featurequeries': ['@supports'], - 'flexbox': ['flex', 'inline-flex', 'flex-direction', 'flex-wrap', 'flex-flow', 'order', 'flex'], - 'calc': ['calc'], - 'object-fit': ['object-fit', 'object-position'], - 'css-grid': ['grid', 'inline-grid', 'grid-template-rows', 'grid-template-columns', 'grid-template-areas', 'grid-template', 'grid-auto-rows', 'grid-auto-columns', ' grid-auto-flow', 'grid-auto-position', 'grid', ' grid-row-start', 'grid-column-start', 'grid-row-end', 'grid-column-end', 'grid-column', 'grid-row', 'grid-area', 'justify-self', 'justify-items', 'align-self', 'align-items'], - 'css-repeating-gradients': ['repeating-linear-gradient'], - 'css-filters': ['filter'], - 'user-select-none': ['user-select'], - 'intrinsic-width': ['min-content', 'max-content', 'fit-content', 'fill-available'], - 'css3-tabsize': ['tab-size'] - }; - - /** @type {Object} The Can I Use database for CSS */ - var cssDB = null; - /** @type {Object} A list of available vendors (browsers) and their prefixes */ - var vendorsDB = null; - var erasDB = null; - - function intersection(arr1, arr2) { - var result = []; - var smaller = arr1, larger = arr2; - if (smaller.length > larger.length) { - smaller = arr2; - larger = arr1; - } - larger.forEach(function(item) { - if (~smaller.indexOf(item)) { - result.push(item); - } - }); - return result; - } - - /** - * Parses raw Can I Use database for better lookups - * @param {String} data Raw database - * @param {Boolean} optimized Pass `true` if given `data` is already optimized - * @return {Object} - */ - function parseDB(data, optimized) { - if (typeof data == 'string') { - data = JSON.parse(data); - } - - if (!optimized) { - data = optimize(data); - } - - vendorsDB = data.vendors; - cssDB = data.css; - erasDB = data.era; - } - - /** - * Extract required data only from CIU database - * @param {Object} data Raw Can I Use database - * @return {Object} Optimized database - */ - function optimize(data) { - if (typeof data == 'string') { - data = JSON.parse(data); - } - - return { - vendors: parseVendors(data), - css: parseCSS(data), - era: parseEra(data) - }; - } - - /** - * Parses vendor data - * @param {Object} data - * @return {Object} - */ - function parseVendors(data) { - var out = {}; - Object.keys(data.agents).forEach(function(name) { - var agent = data.agents[name]; - out[name] = { - prefix: agent.prefix, - versions: agent.versions - }; - }); - return out; - } - - /** - * Parses CSS data from Can I Use raw database - * @param {Object} data - * @return {Object} - */ - function parseCSS(data) { - var out = {}; - var cssCategories = data.cats.CSS; - Object.keys(data.data).forEach(function(name) { - var section = data.data[name]; - if (name in cssSections) { - cssSections[name].forEach(function(kw) { - out[kw] = section.stats; - }); - } - }); - - return out; - } - - /** - * Parses era data from Can I Use raw database - * @param {Object} data - * @return {Array} - */ - function parseEra(data) { - // some runtimes (like Mozilla Rhino) does not preserves - // key order so we have to sort values manually - return Object.keys(data.eras).sort(function(a, b) { - return parseInt(a.substr(1)) - parseInt(b.substr(1)); - }); - } - - /** - * Returs list of supported vendors, depending on user preferences - * @return {Array} - */ - function getVendorsList() { - var allVendors = Object.keys(vendorsDB); - var vendors = prefs.getArray('caniuse.vendors'); - if (!vendors || vendors[0] == 'all') { - return allVendors; - } - - return intersection(allVendors, vendors); - } - - /** - * Returns size of version slice as defined by era identifier - * @return {Number} - */ - function getVersionSlice() { - var era = prefs.get('caniuse.era'); - var ix = erasDB.indexOf(era); - if (!~ix) { - ix = erasDB.indexOf('e-2'); - } - - return ix; - } - - // try to load caniuse database - // hide it from Require.JS parser - var db = null; - (function(r) { - if (typeof define === 'undefined' || !define.amd) { - try { - var fs = r('fs'); - var path = r('path'); - db = fs.readFileSync(path.join(__dirname, '../caniuse.json'), {encoding: 'utf8'}); - } catch(e) {} - } - })(require); - - if (db) { - parseDB(db); - } - - return { - load: parseDB, - optimize: optimize, - - /** - * Resolves prefixes for given property - * @param {String} property A property to resolve. It can start with `@` symbol - * (CSS section, like `@keyframes`) or `:` (CSS value, like `flex`) - * @return {Array} Array of resolved prefixes or null - * if prefixes can't be resolved. Empty array means property has no vendor - * prefixes - */ - resolvePrefixes: function(property) { - if (!prefs.get('caniuse.enabled') || !cssDB || !(property in cssDB)) { - return null; - } - - var prefixes = []; - var propStats = cssDB[property]; - var versions = getVersionSlice(); - - getVendorsList().forEach(function(vendor) { - var vendorVesions = vendorsDB[vendor].versions.slice(versions); - for (var i = 0, v; i < vendorVesions.length; i++) { - v = vendorVesions[i]; - if (!v) { - continue; - } - - if (~propStats[vendor][v].indexOf('x')) { - prefixes.push(vendorsDB[vendor].prefix); - break; - } - } - }); - - return utils.unique(prefixes).sort(function(a, b) { - return b.length - a.length; - }); - } - }; -}); -},{"../utils/common":73,"./preferences":28}],24:[function(require,module,exports){ -/** - * Module that contains factories for element types used by Emmet - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var factories = {}; - var reAttrs = /([@\!]?)([\w\-:]+)\s*=\s*(['"])(.*?)\3/g; - - // register resource references - function commonFactory(value) { - return {data: value}; - } - - module = module || {}; - module.exports = { - /** - * Create new element factory - * @param {String} name Element identifier - * @param {Function} factory Function that produces element of specified - * type. The object generated by this factory is automatically - * augmented with type property pointing to element - * name - * @memberOf elements - */ - add: function(name, factory) { - var that = this; - factories[name] = function() { - var elem = factory.apply(that, arguments); - if (elem) - elem.type = name; - - return elem; - }; - }, - - /** - * Returns factory for specified name - * @param {String} name - * @returns {Function} - */ - get: function(name) { - return factories[name]; - }, - - /** - * Creates new element with specified type - * @param {String} name - * @returns {Object} - */ - create: function(name) { - var args = [].slice.call(arguments, 1); - var factory = this.get(name); - return factory ? factory.apply(this, args) : null; - }, - - /** - * Check if passed element is of specified type - * @param {Object} elem - * @param {String} type - * @returns {Boolean} - */ - is: function(elem, type) { - return this.type(elem) === type; - }, - - /** - * Returns type of element - * @param {Object} elem - * @return {String} - */ - type: function(elem) { - return elem && elem.type; - } - }; - - /** - * Element factory - * @param {String} elementName Name of output element - * @param {String} attrs Attributes definition. You may also pass - * Array where each contains object with name - * and value properties, or Object - * @param {Boolean} isEmpty Is expanded element should be empty - */ - module.exports.add('element', function(elementName, attrs, isEmpty) { - var ret = { - name: elementName, - is_empty: !!isEmpty - }; - - if (attrs) { - ret.attributes = []; - if (Array.isArray(attrs)) { - ret.attributes = attrs; - } else if (typeof attrs === 'string') { - var m; - while ((m = reAttrs.exec(attrs))) { - ret.attributes.push({ - name: m[2], - value: m[4], - isDefault: m[1] == '@', - isImplied: m[1] == '!' - }); - } - } else { - ret.attributes = Object.keys(attrs).map(function(name) { - return { - name: name, - value: attrs[name] - }; - }); - } - } - - return ret; - }); - - module.exports.add('snippet', commonFactory); - module.exports.add('reference', commonFactory); - module.exports.add('empty', function() { - return {}; - }); - - return module.exports; -}); -},{}],25:[function(require,module,exports){ -/** - * Utility module that provides ordered storage of function handlers. - * Many Emmet modules' functionality can be extended/overridden by custom - * function. This modules provides unified storage of handler functions, their - * management and execution - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - - /** - * @type HandlerList - * @constructor - */ - function HandlerList() { - this._list = []; - } - - HandlerList.prototype = { - /** - * Adds function handler - * @param {Function} fn Handler - * @param {Object} options Handler options. Possible values are:

      - * order : (Number) – order in handler list. Handlers - * with higher order value will be executed earlier. - */ - add: function(fn, options) { - // TODO hack for stable sort, remove after fixing `list()` - var order = this._list.length; - if (options && 'order' in options) { - order = options.order * 10000; - } - this._list.push(utils.extend({}, options, {order: order, fn: fn})); - }, - - /** - * Removes handler from list - * @param {Function} fn - */ - remove: function(fn) { - var item = utils.find(this._list, function(item) { - return item.fn === fn; - }); - if (item) { - this._list.splice(this._list.indexOf(item), 1); - } - }, - - /** - * Returns ordered list of handlers. By default, handlers - * with the same order option returned in reverse order, - * i.e. the latter function was added into the handlers list, the higher - * it will be in the returned array - * @returns {Array} - */ - list: function() { - // TODO make stable sort - return this._list.sort(function(a, b) { - return b.order - a.order; - }); - }, - - /** - * Returns ordered list of handler functions - * @returns {Array} - */ - listFn: function() { - return this.list().map(function(item) { - return item.fn; - }); - }, - - /** - * Executes handler functions in their designated order. If function - * returns skipVal, meaning that function was unable to - * handle passed args, the next function will be executed - * and so on. - * @param {Object} skipValue If function returns this value, execute - * next handler. - * @param {Array} args Arguments to pass to handler function - * @returns {Boolean} Whether any of registered handlers performed - * successfully - */ - exec: function(skipValue, args) { - args = args || []; - var result = null; - utils.find(this.list(), function(h) { - result = h.fn.apply(h, args); - if (result !== skipValue) { - return true; - } - }); - - return result; - } - }; - - return { - /** - * Factory method that produces HandlerList instance - * @returns {HandlerList} - * @memberOf handlerList - */ - create: function() { - return new HandlerList(); - } - }; -}); -},{"../utils/common":73}],26:[function(require,module,exports){ -/** - * HTML matcher: takes string and searches for HTML tag pairs for given position - * - * Unlike “classic” matchers, it parses content from the specified - * position, not from the start, so it may work even outside HTML documents - * (for example, inside strings of programming languages like JavaScript, Python - * etc.) - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var range = require('./range'); - - // Regular Expressions for parsing tags and attributes - var reOpenTag = /^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/; - var reCloseTag = /^<\/([\w\:\-]+)[^>]*>/; - - function openTag(i, match) { - return { - name: match[1], - selfClose: !!match[3], - /** @type Range */ - range: range(i, match[0]), - type: 'open' - }; - } - - function closeTag(i, match) { - return { - name: match[1], - /** @type Range */ - range: range(i, match[0]), - type: 'close' - }; - } - - function comment(i, match) { - return { - /** @type Range */ - range: range(i, typeof match == 'number' ? match - i : match[0]), - type: 'comment' - }; - } - - /** - * Creates new tag matcher session - * @param {String} text - */ - function createMatcher(text) { - var memo = {}, m; - return { - /** - * Test if given position matches opening tag - * @param {Number} i - * @returns {Object} Matched tag object - */ - open: function(i) { - var m = this.matches(i); - return m && m.type == 'open' ? m : null; - }, - - /** - * Test if given position matches closing tag - * @param {Number} i - * @returns {Object} Matched tag object - */ - close: function(i) { - var m = this.matches(i); - return m && m.type == 'close' ? m : null; - }, - - /** - * Matches either opening or closing tag for given position - * @param i - * @returns - */ - matches: function(i) { - var key = 'p' + i; - - if (!(key in memo)) { - memo[key] = false; - if (text.charAt(i) == '<') { - var substr = text.slice(i); - if ((m = substr.match(reOpenTag))) { - memo[key] = openTag(i, m); - } else if ((m = substr.match(reCloseTag))) { - memo[key] = closeTag(i, m); - } - } - } - - return memo[key]; - }, - - /** - * Returns original text - * @returns {String} - */ - text: function() { - return text; - }, - - clean: function() { - memo = text = m = null; - } - }; - } - - function matches(text, pos, pattern) { - return text.substring(pos, pos + pattern.length) == pattern; - } - - /** - * Search for closing pair of opening tag - * @param {Object} open Open tag instance - * @param {Object} matcher Matcher instance - */ - function findClosingPair(open, matcher) { - var stack = [], tag = null; - var text = matcher.text(); - - for (var pos = open.range.end, len = text.length; pos < len; pos++) { - if (matches(text, pos, '')) { - pos = j + 3; - break; - } - } - } - - if ((tag = matcher.matches(pos))) { - if (tag.type == 'open' && !tag.selfClose) { - stack.push(tag.name); - } else if (tag.type == 'close') { - if (!stack.length) { // found valid pair? - return tag.name == open.name ? tag : null; - } - - // check if current closing tag matches previously opened one - if (stack[stack.length - 1] == tag.name) { - stack.pop(); - } else { - var found = false; - while (stack.length && !found) { - var last = stack.pop(); - if (last == tag.name) { - found = true; - } - } - - if (!stack.length && !found) { - return tag.name == open.name ? tag : null; - } - } - } - - pos = tag.range.end - 1; - } - } - } - - return { - /** - * Main function: search for tag pair in text for given - * position - * @memberOf htmlMatcher - * @param {String} text - * @param {Number} pos - * @returns {Object} - */ - find: function(text, pos) { - var matcher = createMatcher(text); - var open = null, close = null; - var j, jl; - - for (var i = pos; i >= 0; i--) { - if ((open = matcher.open(i))) { - // found opening tag - if (open.selfClose) { - if (open.range.cmp(pos, 'lt', 'gt')) { - // inside self-closing tag, found match - break; - } - - // outside self-closing tag, continue - continue; - } - - close = findClosingPair(open, matcher); - if (close) { - // found closing tag. - var r = range.create2(open.range.start, close.range.end); - if (r.contains(pos)) { - break; - } - } else if (open.range.contains(pos)) { - // we inside empty HTML tag like
      - break; - } - - open = null; - } else if (matches(text, i, '-->')) { - // skip back to comment start - for (j = i - 1; j >= 0; j--) { - if (matches(text, j, '-->')) { - // found another comment end, do nothing - break; - } else if (matches(text, j, '')) { - j += 3; - break; - } - } - - open = comment(i, j); - break; - } - } - - matcher.clean(); - - if (open) { - var outerRange = null; - var innerRange = null; - - if (close) { - outerRange = range.create2(open.range.start, close.range.end); - innerRange = range.create2(open.range.end, close.range.start); - } else { - outerRange = innerRange = range.create2(open.range.start, open.range.end); - } - - if (open.type == 'comment') { - // adjust positions of inner range for comment - var _c = outerRange.substring(text); - innerRange.start += _c.length - _c.replace(/^<\!--\s*/, '').length; - innerRange.end -= _c.length - _c.replace(/\s*-->$/, '').length; - } - - return { - open: open, - close: close, - type: open.type == 'comment' ? 'comment' : 'tag', - innerRange: innerRange, - innerContent: function() { - return this.innerRange.substring(text); - }, - outerRange: outerRange, - outerContent: function() { - return this.outerRange.substring(text); - }, - range: !innerRange.length() || !innerRange.cmp(pos, 'lte', 'gte') ? outerRange : innerRange, - content: function() { - return this.range.substring(text); - }, - source: text - }; - } - }, - - /** - * The same as find() method, but restricts matched result - * to tag type - * @param {String} text - * @param {Number} pos - * @returns {Object} - */ - tag: function(text, pos) { - var result = this.find(text, pos); - if (result && result.type == 'tag') { - return result; - } - } - }; -}); -},{"./range":30}],27:[function(require,module,exports){ -/** - * Simple logger for Emmet - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - return { - log: function() { - if (typeof console != 'undefined' && console.log) { - console.log.apply(console, arguments); - } - } - } -}) -},{}],28:[function(require,module,exports){ -/** - * Common module's preferences storage. This module - * provides general storage for all module preferences, their description and - * default values.

      - * - * This module can also be used to list all available properties to create - * UI for updating properties - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - - var preferences = {}; - var defaults = {}; - var _dbgDefaults = null; - var _dbgPreferences = null; - - function toBoolean(val) { - if (typeof val === 'string') { - val = val.toLowerCase(); - return val == 'yes' || val == 'true' || val == '1'; - } - - return !!val; - } - - function isValueObj(obj) { - return typeof obj === 'object' - && !Array.isArray(obj) - && 'value' in obj - && Object.keys(obj).length < 3; - } - - return { - /** - * Creates new preference item with default value - * @param {String} name Preference name. You can also pass object - * with many options - * @param {Object} value Preference default value - * @param {String} description Item textual description - * @memberOf preferences - */ - define: function(name, value, description) { - var prefs = name; - if (typeof name === 'string') { - prefs = {}; - prefs[name] = { - value: value, - description: description - }; - } - - Object.keys(prefs).forEach(function(k) { - var v = prefs[k]; - defaults[k] = isValueObj(v) ? v : {value: v}; - }); - }, - - /** - * Updates preference item value. Preference value should be defined - * first with define method. - * @param {String} name Preference name. You can also pass object - * with many options - * @param {Object} value Preference default value - * @memberOf preferences - */ - set: function(name, value) { - var prefs = name; - if (typeof name === 'string') { - prefs = {}; - prefs[name] = value; - } - - Object.keys(prefs).forEach(function(k) { - var v = prefs[k]; - if (!(k in defaults)) { - throw new Error('Property "' + k + '" is not defined. You should define it first with `define` method of current module'); - } - - // do not set value if it equals to default value - if (v !== defaults[k].value) { - // make sure we have value of correct type - switch (typeof defaults[k].value) { - case 'boolean': - v = toBoolean(v); - break; - case 'number': - v = parseInt(v + '', 10) || 0; - break; - default: // convert to string - if (v !== null) { - v += ''; - } - } - - preferences[k] = v; - } else if (k in preferences) { - delete preferences[k]; - } - }); - }, - - /** - * Returns preference value - * @param {String} name - * @returns {String} Returns undefined if preference is - * not defined - */ - get: function(name) { - if (name in preferences) { - return preferences[name]; - } - - if (name in defaults) { - return defaults[name].value; - } - - return void 0; - }, - - /** - * Returns comma-separated preference value as array of values - * @param {String} name - * @returns {Array} Returns undefined if preference is - * not defined, null if string cannot be converted to array - */ - getArray: function(name) { - var val = this.get(name); - if (typeof val === 'undefined' || val === null || val === '') { - return null; - } - - val = val.split(',').map(utils.trim); - if (!val.length) { - return null; - } - - return val; - }, - - /** - * Returns comma and colon-separated preference value as dictionary - * @param {String} name - * @returns {Object} - */ - getDict: function(name) { - var result = {}; - this.getArray(name).forEach(function(val) { - var parts = val.split(':'); - result[parts[0]] = parts[1]; - }); - - return result; - }, - - /** - * Returns description of preference item - * @param {String} name Preference name - * @returns {Object} - */ - description: function(name) { - return name in defaults ? defaults[name].description : void 0; - }, - - /** - * Completely removes specified preference(s) - * @param {String} name Preference name (or array of names) - */ - remove: function(name) { - if (!Array.isArray(name)) { - name = [name]; - } - - name.forEach(function(key) { - if (key in preferences) { - delete preferences[key]; - } - - if (key in defaults) { - delete defaults[key]; - } - }); - }, - - /** - * Returns sorted list of all available properties - * @returns {Array} - */ - list: function() { - return Object.keys(defaults).sort().map(function(key) { - return { - name: key, - value: this.get(key), - type: typeof defaults[key].value, - description: defaults[key].description - }; - }, this); - }, - - /** - * Loads user-defined preferences from JSON - * @param {Object} json - * @returns - */ - load: function(json) { - Object.keys(json).forEach(function(key) { - this.set(key, json[key]); - }, this); - }, - - /** - * Returns hash of user-modified preferences - * @returns {Object} - */ - exportModified: function() { - return utils.extend({}, preferences); - }, - - /** - * Reset to defaults - * @returns - */ - reset: function() { - preferences = {}; - }, - - /** - * For unit testing: use empty storage - */ - _startTest: function() { - _dbgDefaults = defaults; - _dbgPreferences = preferences; - defaults = {}; - preferences = {}; - }, - - /** - * For unit testing: restore original storage - */ - _stopTest: function() { - defaults = _dbgDefaults; - preferences = _dbgPreferences; - } - }; -}); -},{"../utils/common":73}],29:[function(require,module,exports){ -/** - * Output profile module. - * Profile defines how XHTML output data should look like - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - var resources = require('./resources'); - var prefs = require('./preferences'); - - prefs.define('profile.allowCompactBoolean', true, - 'This option can be used to globally disable compact form of boolean ' + - 'attribues (attributes where name and value are equal). With compact' + - 'form enabled, HTML tags can be outputted as <div contenteditable> ' + - 'instead of <div contenteditable="contenteditable">'); - - prefs.define('profile.booleanAttributes', '^contenteditable|seamless$', - 'A regular expression for attributes that should be boolean by default.' + - 'If attribute name matches this expression, you don’t have to write dot ' + - 'after attribute name in Emmet abbreviation to mark it as boolean.'); - - var profiles = {}; - - var defaultProfile = { - tag_case: 'asis', - attr_case: 'asis', - attr_quotes: 'double', - - // Each tag on new line - tag_nl: 'decide', - - // With tag_nl === true, defines if leaf node (e.g. node with no children) - // should have formatted line breaks - tag_nl_leaf: false, - - place_cursor: true, - - // Indent tags - indent: true, - - // How many inline elements should be to force line break - // (set to 0 to disable) - inline_break: 3, - - // Produce compact notation of boolean attribues: - // attributes where name and value are equal. - // With this option enabled, HTML filter will - // produce
      instead of
      - compact_bool: false, - - // Use self-closing style for writing empty elements, e.g.
      or
      - self_closing_tag: 'xhtml', - - // Profile-level output filters, re-defines syntax filters - filters: '', - - // Additional filters applied to abbreviation. - // Unlike "filters", this preference doesn't override default filters - // but add the instead every time given profile is chosen - extraFilters: '' - }; - - /** - * @constructor - * @type OutputProfile - * @param {Object} options - */ - function OutputProfile(options) { - utils.extend(this, defaultProfile, options); - } - - OutputProfile.prototype = { - /** - * Transforms tag name case depending on current profile settings - * @param {String} name String to transform - * @returns {String} - */ - tagName: function(name) { - return stringCase(name, this.tag_case); - }, - - /** - * Transforms attribute name case depending on current profile settings - * @param {String} name String to transform - * @returns {String} - */ - attributeName: function(name) { - return stringCase(name, this.attr_case); - }, - - /** - * Returns quote character for current profile - * @returns {String} - */ - attributeQuote: function() { - return this.attr_quotes == 'single' ? "'" : '"'; - }, - - /** - * Returns self-closing tag symbol for current profile - * @returns {String} - */ - selfClosing: function() { - if (this.self_closing_tag == 'xhtml') - return ' /'; - - if (this.self_closing_tag === true) - return '/'; - - return ''; - }, - - /** - * Returns cursor token based on current profile settings - * @returns {String} - */ - cursor: function() { - return this.place_cursor ? utils.getCaretPlaceholder() : ''; - }, - - /** - * Check if attribute with given name is boolean, - * e.g. written as `contenteditable` instead of - * `contenteditable="contenteditable"` - * @param {String} name Attribute name - * @return {Boolean} - */ - isBoolean: function(name, value) { - if (name == value) { - return true; - } - - var boolAttrs = prefs.get('profile.booleanAttributes'); - if (!value && boolAttrs) { - boolAttrs = new RegExp(boolAttrs, 'i'); - return boolAttrs.test(name); - } - - return false; - }, - - /** - * Check if compact boolean attribute record is - * allowed for current profile - * @return {Boolean} - */ - allowCompactBoolean: function() { - return this.compact_bool && prefs.get('profile.allowCompactBoolean'); - } - }; - - /** - * Helper function that converts string case depending on - * caseValue - * @param {String} str String to transform - * @param {String} caseValue Case value: can be lower, - * upper and leave - * @returns {String} - */ - function stringCase(str, caseValue) { - switch (String(caseValue || '').toLowerCase()) { - case 'lower': - return str.toLowerCase(); - case 'upper': - return str.toUpperCase(); - } - - return str; - } - - /** - * Creates new output profile - * @param {String} name Profile name - * @param {Object} options Profile options - */ - function createProfile(name, options) { - return profiles[name.toLowerCase()] = new OutputProfile(options); - } - - function createDefaultProfiles() { - createProfile('xhtml'); - createProfile('html', {self_closing_tag: false, compact_bool: true}); - createProfile('xml', {self_closing_tag: true, tag_nl: true}); - createProfile('plain', {tag_nl: false, indent: false, place_cursor: false}); - createProfile('line', {tag_nl: false, indent: false, extraFilters: 's'}); - createProfile('css', {tag_nl: true}); - createProfile('css_line', {tag_nl: false}); - } - - createDefaultProfiles(); - - return { - /** - * Creates new output profile and adds it into internal dictionary - * @param {String} name Profile name - * @param {Object} options Profile options - * @memberOf emmet.profile - * @returns {Object} New profile - */ - create: function(name, options) { - if (arguments.length == 2) - return createProfile(name, options); - else - // create profile object only - return new OutputProfile(utils.defaults(name || {}, defaultProfile)); - }, - - /** - * Returns profile by its name. If profile wasn't found, returns - * 'plain' profile - * @param {String} name Profile name. Might be profile itself - * @param {String} syntax. Optional. Current editor syntax. If defined, - * profile is searched in resources first, then in predefined profiles - * @returns {Object} - */ - get: function(name, syntax) { - if (!name && syntax) { - // search in user resources first - var profile = resources.findItem(syntax, 'profile'); - if (profile) { - name = profile; - } - } - - if (!name) { - return profiles.plain; - } - - if (name instanceof OutputProfile) { - return name; - } - - if (typeof name === 'string' && name.toLowerCase() in profiles) { - return profiles[name.toLowerCase()]; - } - - return this.create(name); - }, - - /** - * Deletes profile with specified name - * @param {String} name Profile name - */ - remove: function(name) { - name = (name || '').toLowerCase(); - if (name in profiles) - delete profiles[name]; - }, - - /** - * Resets all user-defined profiles - */ - reset: function() { - profiles = {}; - createDefaultProfiles(); - }, - - /** - * Helper function that converts string case depending on - * caseValue - * @param {String} str String to transform - * @param {String} caseValue Case value: can be lower, - * upper and leave - * @returns {String} - */ - stringCase: stringCase - }; -}); -},{"../utils/common":73,"./preferences":28,"./resources":31}],30:[function(require,module,exports){ -/** - * Helper module to work with ranges - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - function cmp(a, b, op) { - switch (op) { - case 'eq': - case '==': - return a === b; - case 'lt': - case '<': - return a < b; - case 'lte': - case '<=': - return a <= b; - case 'gt': - case '>': - return a > b; - case 'gte': - case '>=': - return a >= b; - } - } - - - /** - * @type Range - * @constructor - * @param {Object} start - * @param {Number} len - */ - function Range(start, len) { - if (typeof start === 'object' && 'start' in start) { - // create range from object stub - this.start = Math.min(start.start, start.end); - this.end = Math.max(start.start, start.end); - } else if (Array.isArray(start)) { - this.start = start[0]; - this.end = start[1]; - } else { - len = typeof len === 'string' ? len.length : +len; - this.start = start; - this.end = start + len; - } - } - - Range.prototype = { - length: function() { - return Math.abs(this.end - this.start); - }, - - /** - * Returns true if passed range is equals to current one - * @param {Range} range - * @returns {Boolean} - */ - equal: function(range) { - return this.cmp(range, 'eq', 'eq'); -// return this.start === range.start && this.end === range.end; - }, - - /** - * Shifts indexes position with passed delta - * @param {Number} delta - * @returns {Range} range itself - */ - shift: function(delta) { - this.start += delta; - this.end += delta; - return this; - }, - - /** - * Check if two ranges are overlapped - * @param {Range} range - * @returns {Boolean} - */ - overlap: function(range) { - return range.start <= this.end && range.end >= this.start; - }, - - /** - * Finds intersection of two ranges - * @param {Range} range - * @returns {Range} null if ranges does not overlap - */ - intersection: function(range) { - if (this.overlap(range)) { - var start = Math.max(range.start, this.start); - var end = Math.min(range.end, this.end); - return new Range(start, end - start); - } - - return null; - }, - - /** - * Returns the union of the thow ranges. - * @param {Range} range - * @returns {Range} null if ranges are not overlapped - */ - union: function(range) { - if (this.overlap(range)) { - var start = Math.min(range.start, this.start); - var end = Math.max(range.end, this.end); - return new Range(start, end - start); - } - - return null; - }, - - /** - * Returns a Boolean value that indicates whether a specified position - * is in a given range. - * @param {Number} loc - */ - inside: function(loc) { - return this.cmp(loc, 'lte', 'gt'); -// return this.start <= loc && this.end > loc; - }, - - /** - * Returns a Boolean value that indicates whether a specified position - * is in a given range, but not equals bounds. - * @param {Number} loc - */ - contains: function(loc) { - return this.cmp(loc, 'lt', 'gt'); - }, - - /** - * Check if current range completely includes specified one - * @param {Range} r - * @returns {Boolean} - */ - include: function(r) { - return this.cmp(r, 'lte', 'gte'); -// return this.start <= r.start && this.end >= r.end; - }, - - /** - * Low-level comparision method - * @param {Number} loc - * @param {String} left Left comparison operator - * @param {String} right Right comaprison operator - */ - cmp: function(loc, left, right) { - var a, b; - if (loc instanceof Range) { - a = loc.start; - b = loc.end; - } else { - a = b = loc; - } - - return cmp(this.start, a, left || '<=') && cmp(this.end, b, right || '>'); - }, - - /** - * Returns substring of specified str for current range - * @param {String} str - * @returns {String} - */ - substring: function(str) { - return this.length() > 0 - ? str.substring(this.start, this.end) - : ''; - }, - - /** - * Creates copy of current range - * @returns {Range} - */ - clone: function() { - return new Range(this.start, this.length()); - }, - - /** - * @returns {Array} - */ - toArray: function() { - return [this.start, this.end]; - }, - - toString: function() { - return this.valueOf(); - }, - - valueOf: function() { - return '{' + this.start + ', ' + this.length() + '}'; - } - }; - - /** - * Creates new range object instance - * @param {Object} start Range start or array with 'start' and 'end' - * as two first indexes or object with 'start' and 'end' properties - * @param {Number} len Range length or string to produce range from - * @returns {Range} - */ - module.exports = function(start, len) { - if (typeof start == 'undefined' || start === null) - return null; - - if (start instanceof Range) - return start; - - if (typeof start == 'object' && 'start' in start && 'end' in start) { - len = start.end - start.start; - start = start.start; - } - - return new Range(start, len); - }; - - module.exports.create = module.exports; - - module.exports.isRange = function(val) { - return val instanceof Range; - }; - - /** - * Range object factory, the same as this.create() - * but last argument represents end of range, not length - * @returns {Range} - */ - module.exports.create2 = function(start, end) { - if (typeof start === 'number' && typeof end === 'number') { - end -= start; - } - - return this.create(start, end); - }; - - /** - * Helper function that sorts ranges in order as they - * appear in text - * @param {Array} ranges - * @return {Array} - */ - module.exports.sort = function(ranges, reverse) { - ranges = ranges.sort(function(a, b) { - if (a.start === b.start) { - return b.end - a.end; - } - - return a.start - b.start; - }); - - reverse && ranges.reverse(); - return ranges; - }; - - return module.exports; -}); -},{}],31:[function(require,module,exports){ -/** - * Parsed resources (snippets, abbreviations, variables, etc.) for Emmet. - * Contains convenient method to get access for snippets with respect of - * inheritance. Also provides ability to store data in different vocabularies - * ('system' and 'user') for fast and safe resource update - * @author Sergey Chikuyonok (serge.che@gmail.com) - * @link http://chikuyonok.ru - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var handlerList = require('./handlerList'); - var utils = require('../utils/common'); - var elements = require('./elements'); - var logger = require('../assets/logger'); - var stringScore = require('../vendor/stringScore'); - var cssResolver = require('../resolver/css'); - - var VOC_SYSTEM = 'system'; - var VOC_USER = 'user'; - - var cache = {}; - - /** Regular expression for XML tag matching */ - var reTag = /^<(\w+\:?[\w\-]*)((?:\s+[@\!]?[\w\:\-]+\s*=\s*(['"]).*?\3)*)\s*(\/?)>/; - - var systemSettings = {}; - var userSettings = {}; - - /** @type HandlerList List of registered abbreviation resolvers */ - var resolvers = handlerList.create(); - - function each(obj, fn) { - if (!obj) { - return; - } - - Object.keys(obj).forEach(function(key) { - fn(obj[key], key); - }); - } - - /** - * Normalizes caret plceholder in passed text: replaces | character with - * default caret placeholder - * @param {String} text - * @returns {String} - */ - function normalizeCaretPlaceholder(text) { - return utils.replaceUnescapedSymbol(text, '|', utils.getCaretPlaceholder()); - } - - function parseItem(name, value, type) { - value = normalizeCaretPlaceholder(value); - - if (type == 'snippets') { - return elements.create('snippet', value); - } - - if (type == 'abbreviations') { - return parseAbbreviation(name, value); - } - } - - /** - * Parses single abbreviation - * @param {String} key Abbreviation name - * @param {String} value Abbreviation value - * @return {Object} - */ - function parseAbbreviation(key, value) { - key = utils.trim(key); - var m; - if ((m = reTag.exec(value))) { - return elements.create('element', m[1], m[2], m[4] == '/'); - } else { - // assume it's reference to another abbreviation - return elements.create('reference', value); - } - } - - /** - * Normalizes snippet key name for better fuzzy search - * @param {String} str - * @returns {String} - */ - function normalizeName(str) { - return str.replace(/:$/, '').replace(/:/g, '-'); - } - - function expandSnippetsDefinition(snippets) { - var out = {}; - each(snippets, function(val, key) { - var items = key.split('|'); - // do not use iterators for better performance - for (var i = items.length - 1; i >= 0; i--) { - out[items[i]] = val; - } - }); - - return out; - } - - utils.extend(exports, { - /** - * Sets new unparsed data for specified settings vocabulary - * @param {Object} data - * @param {String} type Vocabulary type ('system' or 'user') - * @memberOf resources - */ - setVocabulary: function(data, type) { - cache = {}; - - // sections like "snippets" and "abbreviations" could have - // definitions like `"f|fs": "fieldset"` which is the same as distinct - // "f" and "fs" keys both equals to "fieldset". - // We should parse these definitions first - var voc = {}; - each(data, function(section, syntax) { - var _section = {}; - each(section, function(subsection, name) { - if (name == 'abbreviations' || name == 'snippets') { - subsection = expandSnippetsDefinition(subsection); - } - _section[name] = subsection; - }); - - voc[syntax] = _section; - }); - - - if (type == VOC_SYSTEM) { - systemSettings = voc; - } else { - userSettings = voc; - } - }, - - /** - * Returns resource vocabulary by its name - * @param {String} name Vocabulary name ('system' or 'user') - * @return {Object} - */ - getVocabulary: function(name) { - return name == VOC_SYSTEM ? systemSettings : userSettings; - }, - - /** - * Returns resource (abbreviation, snippet, etc.) matched for passed - * abbreviation - * @param {AbbreviationNode} node - * @param {String} syntax - * @returns {Object} - */ - getMatchedResource: function(node, syntax) { - return resolvers.exec(null, utils.toArray(arguments)) - || this.findSnippet(syntax, node.name()); - }, - - /** - * Returns variable value - * @return {String} - */ - getVariable: function(name) { - return (this.getSection('variables') || {})[name]; - }, - - /** - * Store runtime variable in user storage - * @param {String} name Variable name - * @param {String} value Variable value - */ - setVariable: function(name, value){ - var voc = this.getVocabulary('user') || {}; - if (!('variables' in voc)) - voc.variables = {}; - - voc.variables[name] = value; - this.setVocabulary(voc, 'user'); - }, - - /** - * Check if there are resources for specified syntax - * @param {String} syntax - * @return {Boolean} - */ - hasSyntax: function(syntax) { - return syntax in this.getVocabulary(VOC_USER) - || syntax in this.getVocabulary(VOC_SYSTEM); - }, - - /** - * Registers new abbreviation resolver. - * @param {Function} fn Abbreviation resolver which will receive - * abbreviation as first argument and should return parsed abbreviation - * object if abbreviation has handled successfully, null - * otherwise - * @param {Object} options Options list as described in - * {@link HandlerList#add()} method - */ - addResolver: function(fn, options) { - resolvers.add(fn, options); - }, - - removeResolver: function(fn) { - resolvers.remove(fn); - }, - - /** - * Returns actual section data, merged from both - * system and user data - * @param {String} name Section name (syntax) - * @param {String} ...args Subsections - * @returns - */ - getSection: function(name) { - if (!name) - return null; - - if (!(name in cache)) { - cache[name] = utils.deepMerge({}, systemSettings[name], userSettings[name]); - } - - var data = cache[name], subsections = utils.toArray(arguments, 1), key; - while (data && (key = subsections.shift())) { - if (key in data) { - data = data[key]; - } else { - return null; - } - } - - return data; - }, - - /** - * Recursively searches for a item inside top level sections (syntaxes) - * with respect of `extends` attribute - * @param {String} topSection Top section name (syntax) - * @param {String} subsection Inner section name - * @returns {Object} - */ - findItem: function(topSection, subsection) { - var data = this.getSection(topSection); - while (data) { - if (subsection in data) - return data[subsection]; - - data = this.getSection(data['extends']); - } - }, - - /** - * Recursively searches for a snippet definition inside syntax section. - * Definition is searched inside `snippets` and `abbreviations` - * subsections - * @param {String} syntax Top-level section name (syntax) - * @param {String} name Snippet name - * @returns {Object} - */ - findSnippet: function(syntax, name, memo) { - if (!syntax || !name) - return null; - - memo = memo || []; - - var names = [name]; - // create automatic aliases to properties with colons, - // e.g. pos-a == pos:a - if (~name.indexOf('-')) { - names.push(name.replace(/\-/g, ':')); - } - - var data = this.getSection(syntax), matchedItem = null; - ['snippets', 'abbreviations'].some(function(sectionName) { - var data = this.getSection(syntax, sectionName); - if (data) { - return names.some(function(n) { - if (data[n]) { - return matchedItem = parseItem(n, data[n], sectionName); - } - }); - } - }, this); - - memo.push(syntax); - if (!matchedItem && data['extends'] && !~memo.indexOf(data['extends'])) { - // try to find item in parent syntax section - return this.findSnippet(data['extends'], name, memo); - } - - return matchedItem; - }, - - /** - * Performs fuzzy search of snippet definition - * @param {String} syntax Top-level section name (syntax) - * @param {String} name Snippet name - * @returns - */ - fuzzyFindSnippet: function(syntax, name, minScore) { - var result = this.fuzzyFindMatches(syntax, name, minScore)[0]; - if (result) { - return result.value.parsedValue; - } - }, - - fuzzyFindMatches: function(syntax, name, minScore) { - minScore = minScore || 0.3; - name = normalizeName(name); - var snippets = this.getAllSnippets(syntax); - - return Object.keys(snippets) - .map(function(key) { - var value = snippets[key]; - return { - key: key, - score: stringScore.score(value.nk, name, 0.1), - value: value - }; - }) - .filter(function(item) { - return item.score >= minScore; - }) - .sort(function(a, b) { - return a.score - b.score; - }) - .reverse(); - }, - - /** - * Returns plain dictionary of all available abbreviations and snippets - * for specified syntax with respect of inheritance - * @param {String} syntax - * @returns {Object} - */ - getAllSnippets: function(syntax) { - var cacheKey = 'all-' + syntax; - if (!cache[cacheKey]) { - var stack = [], sectionKey = syntax; - var memo = []; - - do { - var section = this.getSection(sectionKey); - if (!section) - break; - - ['snippets', 'abbreviations'].forEach(function(sectionName) { - var stackItem = {}; - each(section[sectionName] || null, function(v, k) { - stackItem[k] = { - nk: normalizeName(k), - value: v, - parsedValue: parseItem(k, v, sectionName), - type: sectionName - }; - }); - - stack.push(stackItem); - }); - - memo.push(sectionKey); - sectionKey = section['extends']; - } while (sectionKey && !~memo.indexOf(sectionKey)); - - - cache[cacheKey] = utils.extend.apply(utils, stack.reverse()); - } - - return cache[cacheKey]; - }, - - /** - * Returns newline character - * @returns {String} - */ - getNewline: function() { - var nl = this.getVariable('newline'); - return typeof nl === 'string' ? nl : '\n'; - }, - - /** - * Sets new newline character that will be used in output - * @param {String} str - */ - setNewline: function(str) { - this.setVariable('newline', str); - this.setVariable('nl', str); - } - }); - - // XXX add default resolvers - exports.addResolver(cssResolver.resolve.bind(cssResolver)); - - // try to load snippets - // hide it from Require.JS parser - (function(r) { - if (typeof define === 'undefined' || !define.amd) { - try { - var fs = r('fs'); - var path = r('path'); - - var defaultSnippets = fs.readFileSync(path.join(__dirname, '../snippets.json'), {encoding: 'utf8'}); - exports.setVocabulary(JSON.parse(defaultSnippets), VOC_SYSTEM); - } catch (e) {} - } - })(require); - - - return exports; -}); -},{"../assets/logger":27,"../resolver/css":64,"../utils/common":73,"../vendor/stringScore":79,"./elements":24,"./handlerList":25}],32:[function(require,module,exports){ -/** - * A trimmed version of CodeMirror's StringStream module for string parsing - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - /** - * @type StringStream - * @constructor - * @param {String} string Assuming that bound string should be - * immutable - */ - function StringStream(string) { - this.pos = this.start = 0; - this.string = string; - this._length = string.length; - } - - StringStream.prototype = { - /** - * Returns true only if the stream is at the end of the line. - * @returns {Boolean} - */ - eol: function() { - return this.pos >= this._length; - }, - - /** - * Returns true only if the stream is at the start of the line - * @returns {Boolean} - */ - sol: function() { - return this.pos === 0; - }, - - /** - * Returns the next character in the stream without advancing it. - * Will return undefined at the end of the line. - * @returns {String} - */ - peek: function() { - return this.string.charAt(this.pos); - }, - - /** - * Returns the next character in the stream and advances it. - * Also returns undefined when no more characters are available. - * @returns {String} - */ - next: function() { - if (this.pos < this._length) - return this.string.charAt(this.pos++); - }, - - /** - * match can be a character, a regular expression, or a function that - * takes a character and returns a boolean. If the next character in the - * stream 'matches' the given argument, it is consumed and returned. - * Otherwise, undefined is returned. - * @param {Object} match - * @returns {String} - */ - eat: function(match) { - var ch = this.string.charAt(this.pos), ok; - if (typeof match == "string") - ok = ch == match; - else - ok = ch && (match.test ? match.test(ch) : match(ch)); - - if (ok) { - ++this.pos; - return ch; - } - }, - - /** - * Repeatedly calls eat with the given argument, until it - * fails. Returns true if any characters were eaten. - * @param {Object} match - * @returns {Boolean} - */ - eatWhile: function(match) { - var start = this.pos; - while (this.eat(match)) {} - return this.pos > start; - }, - - /** - * Shortcut for eatWhile when matching white-space. - * @returns {Boolean} - */ - eatSpace: function() { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) - ++this.pos; - return this.pos > start; - }, - - /** - * Moves the position to the end of the line. - */ - skipToEnd: function() { - this.pos = this._length; - }, - - /** - * Skips to the next occurrence of the given character, if found on the - * current line (doesn't advance the stream if the character does not - * occur on the line). Returns true if the character was found. - * @param {String} ch - * @returns {Boolean} - */ - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) { - this.pos = found; - return true; - } - }, - - /** - * Skips to close character which is pair to open - * character, considering possible pair nesting. This function is used - * to consume pair of characters, like opening and closing braces - * @param {String} open - * @param {String} close - * @returns {Boolean} Returns true if pair was successfully - * consumed - */ - skipToPair: function(open, close, skipString) { - var braceCount = 0, ch; - var pos = this.pos, len = this._length; - while (pos < len) { - ch = this.string.charAt(pos++); - if (ch == open) { - braceCount++; - } else if (ch == close) { - braceCount--; - if (braceCount < 1) { - this.pos = pos; - return true; - } - } else if (skipString && (ch == '"' || ch == "'")) { - this.skipString(ch); - } - } - - return false; - }, - - /** - * A helper function which, in case of either single or - * double quote was found in current position, skips entire - * string (quoted value) - * @return {Boolean} Wether quoted string was skipped - */ - skipQuoted: function(noBackup) { - var ch = this.string.charAt(noBackup ? this.pos : this.pos - 1); - if (ch === '"' || ch === "'") { - if (noBackup) { - this.pos++; - } - return this.skipString(ch); - } - }, - - /** - * A custom function to skip string literal, e.g. a "double-quoted" - * or 'single-quoted' value - * @param {String} quote An opening quote - * @return {Boolean} - */ - skipString: function(quote) { - var pos = this.pos, len = this._length, ch; - while (pos < len) { - ch = this.string.charAt(pos++); - if (ch == '\\') { - continue; - } else if (ch == quote) { - this.pos = pos; - return true; - } - } - - return false; - }, - - /** - * Backs up the stream n characters. Backing it up further than the - * start of the current token will cause things to break, so be careful. - * @param {Number} n - */ - backUp : function(n) { - this.pos -= n; - }, - - /** - * Act like a multi-character eat—if consume is true or - * not given—or a look-ahead that doesn't update the stream position—if - * it is false. pattern can be either a string or a - * regular expression starting with ^. When it is a string, - * caseInsensitive can be set to true to make the match - * case-insensitive. When successfully matching a regular expression, - * the returned value will be the array returned by match, - * in case you need to extract matched groups. - * - * @param {RegExp} pattern - * @param {Boolean} consume - * @param {Boolean} caseInsensitive - * @returns - */ - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = caseInsensitive - ? function(str) {return str.toLowerCase();} - : function(str) {return str;}; - - if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { - if (consume !== false) - this.pos += pattern.length; - return true; - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && consume !== false) - this.pos += match[0].length; - return match; - } - }, - - /** - * Get the string between the start of the current token and the - * current stream position. - * @returns {String} - */ - current: function(backUp) { - return this.string.slice(this.start, this.pos - (backUp ? 1 : 0)); - } - }; - - module.exports = function(string) { - return new StringStream(string); - }; - - /** @deprecated */ - module.exports.create = module.exports; - return module.exports; -}); -},{}],33:[function(require,module,exports){ -/** - * Utility module for handling tabstops tokens generated by Emmet's - * "Expand Abbreviation" action. The main extract method will take - * raw text (for example: ${0} some ${1:text}), find all tabstops - * occurrences, replace them with tokens suitable for your editor of choice and - * return object with processed text and list of found tabstops and their ranges. - * For sake of portability (Objective-C/Java) the tabstops list is a plain - * sorted array with plain objects. - * - * Placeholders with the same are meant to be linked in your editor. - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - var utils = require('../utils/common'); - var stringStream = require('./stringStream'); - var resources = require('./resources'); - - /** - * Global placeholder value, automatically incremented by - * variablesResolver() function - */ - var startPlaceholderNum = 100; - var tabstopIndex = 0; - - var defaultOptions = { - replaceCarets: false, - escape: function(ch) { - return '\\' + ch; - }, - tabstop: function(data) { - return data.token; - }, - variable: function(data) { - return data.token; - } - }; - - return { - /** - * Main function that looks for a tabstops in provided text - * and returns a processed version of text with expanded - * placeholders and list of tabstops found. - * @param {String} text Text to process - * @param {Object} options List of processor options:
      - * - * replaceCarets : Boolean — replace all default - * caret placeholders (like {%::emmet-caret::%}) with ${0:caret}
      - * - * escape : Function — function that handle escaped - * characters (mostly '$'). By default, it returns the character itself - * to be displayed as is in output, but sometimes you will use - * extract method as intermediate solution for further - * processing and want to keep character escaped. Thus, you should override - * escape method to return escaped symbol (e.g. '\\$')
      - * - * tabstop : Function – a tabstop handler. Receives - * a single argument – an object describing token: its position, number - * group, placeholder and token itself. Should return a replacement - * string that will appear in final output - * - * variable : Function – variable handler. Receives - * a single argument – an object describing token: its position, name - * and original token itself. Should return a replacement - * string that will appear in final output - * - * @returns {Object} Object with processed text property - * and array of tabstops found - * @memberOf tabStops - */ - extract: function(text, options) { - // prepare defaults - var placeholders = {carets: ''}; - var marks = []; - - options = utils.extend({}, defaultOptions, options, { - tabstop: function(data) { - var token = data.token; - var ret = ''; - if (data.placeholder == 'cursor') { - marks.push({ - start: data.start, - end: data.start + token.length, - group: 'carets', - value: '' - }); - } else { - // unify placeholder value for single group - if ('placeholder' in data) - placeholders[data.group] = data.placeholder; - - if (data.group in placeholders) - ret = placeholders[data.group]; - - marks.push({ - start: data.start, - end: data.start + token.length, - group: data.group, - value: ret - }); - } - - return token; - } - }); - - if (options.replaceCarets) { - text = text.replace(new RegExp( utils.escapeForRegexp( utils.getCaretPlaceholder() ), 'g'), '${0:cursor}'); - } - - // locate tabstops and unify group's placeholders - text = this.processText(text, options); - - // now, replace all tabstops with placeholders - var buf = '', lastIx = 0; - var tabStops = marks.map(function(mark) { - buf += text.substring(lastIx, mark.start); - - var pos = buf.length; - var ph = placeholders[mark.group] || ''; - - buf += ph; - lastIx = mark.end; - - return { - group: mark.group, - start: pos, - end: pos + ph.length - }; - }); - - buf += text.substring(lastIx); - - return { - text: buf, - tabstops: tabStops.sort(function(a, b) { - return a.start - b.start; - }) - }; - }, - - /** - * Text processing routine. Locates escaped characters and tabstops and - * replaces them with values returned by handlers defined in - * options - * @param {String} text - * @param {Object} options See extract method options - * description - * @returns {String} - */ - processText: function(text, options) { - options = utils.extend({}, defaultOptions, options); - - var buf = ''; - /** @type StringStream */ - var stream = stringStream.create(text); - var ch, m, a; - - while ((ch = stream.next())) { - if (ch == '\\' && !stream.eol()) { - // handle escaped character - buf += options.escape(stream.next()); - continue; - } - - a = ch; - - if (ch == '$') { - // looks like a tabstop - stream.start = stream.pos - 1; - - if ((m = stream.match(/^[0-9]+/))) { - // it's $N - a = options.tabstop({ - start: buf.length, - group: stream.current().substr(1), - token: stream.current() - }); - } else if ((m = stream.match(/^\{([a-z_\-][\w\-]*)\}/))) { - // ${variable} - a = options.variable({ - start: buf.length, - name: m[1], - token: stream.current() - }); - } else if ((m = stream.match(/^\{([0-9]+)(:.+?)?\}/, false))) { - // ${N:value} or ${N} placeholder - // parse placeholder, including nested ones - stream.skipToPair('{', '}'); - - var obj = { - start: buf.length, - group: m[1], - token: stream.current() - }; - - var placeholder = obj.token.substring(obj.group.length + 2, obj.token.length - 1); - - if (placeholder) { - obj.placeholder = placeholder.substr(1); - } - - a = options.tabstop(obj); - } - } - - buf += a; - } - - return buf; - }, - - /** - * Upgrades tabstops in output node in order to prevent naming conflicts - * @param {AbbreviationNode} node - * @param {Number} offset Tab index offset - * @returns {Number} Maximum tabstop index in element - */ - upgrade: function(node, offset) { - var maxNum = 0; - var options = { - tabstop: function(data) { - var group = parseInt(data.group, 10); - if (group > maxNum) maxNum = group; - - if (data.placeholder) - return '${' + (group + offset) + ':' + data.placeholder + '}'; - else - return '${' + (group + offset) + '}'; - } - }; - - ['start', 'end', 'content'].forEach(function(p) { - node[p] = this.processText(node[p], options); - }, this); - - return maxNum; - }, - - /** - * Helper function that produces a callback function for - * replaceVariables() method from {@link utils} - * module. This callback will replace variable definitions (like - * ${var_name}) with their value defined in resource module, - * or outputs tabstop with variable name otherwise. - * @param {AbbreviationNode} node Context node - * @returns {Function} - */ - variablesResolver: function(node) { - var placeholderMemo = {}; - return function(str, varName) { - // do not mark `child` variable as placeholder – it‘s a reserved - // variable name - if (varName == 'child') { - return str; - } - - if (varName == 'cursor') { - return utils.getCaretPlaceholder(); - } - - var attr = node.attribute(varName); - if (typeof attr !== 'undefined' && attr !== str) { - return attr; - } - - var varValue = resources.getVariable(varName); - if (varValue) { - return varValue; - } - - // output as placeholder - if (!placeholderMemo[varName]) { - placeholderMemo[varName] = startPlaceholderNum++; - } - - return '${' + placeholderMemo[varName] + ':' + varName + '}'; - }; - }, - - /** - * Replace variables like ${var} in string - * @param {String} str - * @param {Object} vars Variable set (defaults to variables defined in - * snippets.json) or variable resolver (Function) - * @return {String} - */ - replaceVariables: function(str, vars) { - vars = vars || {}; - var resolver = typeof vars === 'function' ? vars : function(str, p1) { - return p1 in vars ? vars[p1] : null; - }; - - return this.processText(str, { - variable: function(data) { - var newValue = resolver(data.token, data.name, data); - if (newValue === null) { - // try to find variable in resources - newValue = resources.getVariable(data.name); - } - - if (newValue === null || typeof newValue === 'undefined') - // nothing found, return token itself - newValue = data.token; - return newValue; - } - }); - }, - - /** - * Resets global tabstop index. When parsed tree is converted to output - * string (AbbreviationNode.toString()), all tabstops - * defined in snippets and elements are upgraded in order to prevent - * naming conflicts of nested. For example, ${1} of a node - * should not be linked with the same placehilder of the child node. - * By default, AbbreviationNode.toString() automatically - * upgrades tabstops of the same index for each node and writes maximum - * tabstop index into the tabstopIndex variable. To keep - * this variable at reasonable value, it is recommended to call - * resetTabstopIndex() method each time you expand variable - * @returns - */ - resetTabstopIndex: function() { - tabstopIndex = 0; - startPlaceholderNum = 100; - }, - - /** - * Output processor for abbreviation parser that will upgrade tabstops - * of parsed node in order to prevent tabstop index conflicts - */ - abbrOutputProcessor: function(text, node, type) { - var maxNum = 0; - var that = this; - - var tsOptions = { - tabstop: function(data) { - var group = parseInt(data.group, 10); - if (group === 0) - return '${0}'; - - if (group > maxNum) maxNum = group; - if (data.placeholder) { - // respect nested placeholders - var ix = group + tabstopIndex; - var placeholder = that.processText(data.placeholder, tsOptions); - return '${' + ix + ':' + placeholder + '}'; - } else { - return '${' + (group + tabstopIndex) + '}'; - } - } - }; - - // upgrade tabstops - text = this.processText(text, tsOptions); - - // resolve variables - text = this.replaceVariables(text, this.variablesResolver(node)); - - tabstopIndex += maxNum + 1; - return text; - } - }; -}); -},{"../utils/common":73,"./resources":31,"./stringStream":32}],34:[function(require,module,exports){ -/** - * Helper class for convenient token iteration - */ -if (typeof module === 'object' && typeof define !== 'function') { - var define = function (factory) { - module.exports = factory(require, exports, module); - }; -} - -define(function(require, exports, module) { - /** - * @type TokenIterator - * @param {Array} tokens - * @type TokenIterator - * @constructor - */ - function TokenIterator(tokens) { - /** @type Array */ - this.tokens = tokens; - this._position = 0; - this.reset(); - } - - TokenIterator.prototype = { - next: function() { - if (this.hasNext()) { - var token = this.tokens[++this._i]; - this._position = token.start; - return token; - } else { - this._i = this._il; - } - - return null; - }, - - current: function() { - return this.tokens[this._i]; - }, - - peek: function() { - return this.tokens[this._i + i]; - }, - - position: function() { - return this._position; - }, - - hasNext: function() { - return this._i < this._il - 1; - }, - - reset: function() { - this._i = 0; - this._il = this.tokens.length; - }, - - item: function() { - return this.tokens[this._i]; - }, - - itemNext: function() { - return this.tokens[this._i + 1]; - }, - - itemPrev: function() { - return this.tokens[this._i - 1]; - }, - - nextUntil: function(type, callback) { - var token; - var test = typeof type == 'string' - ? function(t){return t.type == type;} - : type; - - while ((token = this.next())) { - if (callback) - callback.call(this, token); - if (test.call(this, token)) - break; - } - } - }; - - return { - create: function(tokens) { - return new TokenIterator(tokens); - } - }; -}); -},{}],35:[function(require,module,exports){ -module.exports={ - "eras": { - "e-26": "26 versions back", - "e-25": "25 versions back", - "e-24": "24 versions back", - "e-23": "23 versions back", - "e-22": "22 versions back", - "e-21": "21 versions back", - "e-20": "20 versions back", - "e-19": "19 versions back", - "e-18": "18 versions back", - "e-17": "17 versions back", - "e-16": "16 versions back", - "e-15": "15 versions back", - "e-14": "14 versions back", - "e-13": "13 versions back", - "e-12": "12 versions back", - "e-11": "11 versions back", - "e-10": "10 versions back", - "e-9": "9 versions back", - "e-8": "8 versions back", - "e-7": "7 versions back", - "e-6": "6 versions back", - "e-5": "5 versions back", - "e-4": "4 versions back", - "e-3": "3 versions back", - "e-2": "2 versions back", - "e-1": "Previous version", - "e0": "Current", - "e1": "Near future", - "e2": "Farther future" - }, - "agents": { - "ie": { - "browser": "IE", - "abbr": "IE", - "prefix": "ms", - "type": "desktop", - "usage_global": { - "10": 10.7866, - "11": 0.114751, - "5.5": 0.009298, - "6": 0.204912, - "7": 0.508182, - "8": 8.31124, - "9": 5.21297 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "5.5", "6", "7", "8", "9", "10", "11", null, null], - "current_version": "" - }, - "firefox": { - "browser": "Firefox", - "abbr": "FF", - "prefix": "moz", - "type": "desktop", - "usage_global": { - "10": 0.112406, - "11": 0.088319, - "12": 0.208754, - "13": 0.096348, - "14": 0.096348, - "15": 0.136493, - "16": 0.264957, - "17": 0.192696, - "18": 0.112406, - "19": 0.128464, - "2": 0.016058, - "20": 0.16058, - "21": 0.216783, - "22": 0.256928, - "23": 0.907277, - "24": 11.0318, - "25": 0.529914, - "26": 0.016058, - "27": 0.016058, - "3": 0.088319, - "3.5": 0.040145, - "3.6": 0.305102, - "4": 0.072261, - "5": 0.048174, - "6": 0.048174, - "7": 0.040145, - "8": 0.072261, - "9": 0.056203 - }, - "versions": [null, "2", "3", "3.5", "3.6", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27"], - "current_version": "" - }, - "chrome": { - "browser": "Chrome", - "abbr": "Chr.", - "prefix": "webkit", - "type": "desktop", - "usage_global": { - "10": 0.048174, - "11": 0.112406, - "12": 0.064232, - "13": 0.056203, - "14": 0.056203, - "15": 0.072261, - "16": 0.048174, - "17": 0.040145, - "18": 0.08029, - "19": 0.040145, - "20": 0.040145, - "21": 0.48174, - "22": 0.248899, - "23": 0.216783, - "24": 0.200725, - "25": 0.361305, - "26": 0.353276, - "27": 0.369334, - "28": 0.610204, - "29": 5.08236, - "30": 24.6089, - "31": 0.16058, - "32": 0.064232, - "4": 0.024087, - "5": 0.024087, - "6": 0.032116, - "7": 0.024087, - "8": 0.032116, - "9": 0.024087 - }, - "versions": ["4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"], - "current_version": "" - }, - "safari": { - "browser": "Safari", - "abbr": "Saf.", - "prefix": "webkit", - "type": "desktop", - "usage_global": { - "3.1": 0, - "3.2": 0.008692, - "4": 0.104377, - "5": 0.305102, - "5.1": 1.28464, - "6": 2.04739, - "6.1": 0.064232, - "7": 0.16058 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "3.1", "3.2", "4", "5", "5.1", "6", "6.1", "7", null, null], - "current_version": "" - }, - "opera": { - "browser": "Opera", - "abbr": "Op.", - "prefix": "o", - "type": "desktop", - "usage_global": { - "10.0-10.1": 0.016058, - "10.5": 0.008392, - "10.6": 0.008029, - "11": 0.008219, - "11.1": 0.008219, - "11.5": 0.016058, - "11.6": 0.032116, - "12": 0.040145, - "12.1": 0.48174, - "15": 0.032116, - "16": 0.104377, - "17": 0.16058, - "18": 0, - "9.5-9.6": 0.008219 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, "9.5-9.6", "10.0-10.1", "10.5", "10.6", "11", "11.1", "11.5", "11.6", "12", "12.1", "15", "16", "17", "18", null], - "current_version": "", - "prefix_exceptions": { - "15": "webkit", - "16": "webkit", - "17": "webkit", - "18": "webkit" - } - }, - "ios_saf": { - "browser": "iOS Safari", - "abbr": "iOS", - "prefix": "webkit", - "type": "mobile", - "usage_global": { - "3.2": 0.00400113, - "4.0-4.1": 0.00800226, - "4.2-4.3": 0.0280079, - "5.0-5.1": 0.28408, - "6.0-6.1": 1.15633, - "7.0": 2.52071 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "3.2", "4.0-4.1", "4.2-4.3", "5.0-5.1", "6.0-6.1", "7.0", null, null], - "current_version": "" - }, - "op_mini": { - "browser": "Opera Mini", - "abbr": "O.Mini", - "prefix": "o", - "type": "mobile", - "usage_global": { - "5.0-7.0": 4.58374 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "5.0-7.0", null, null], - "current_version": "" - }, - "android": { - "browser": "Android Browser", - "abbr": "And.", - "prefix": "webkit", - "type": "mobile", - "usage_global": { - "2.1": 0.0251229, - "2.2": 0.0854178, - "2.3": 1.32146, - "3": 0.00502458, - "4": 0.994867, - "4.1": 1.87417, - "4.2-4.3": 0.743638, - "4.4": 0 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "2.1", "2.2", "2.3", "3", "4", "4.1", "4.2-4.3", "4.4", null], - "current_version": "" - }, - "op_mob": { - "browser": "Opera Mobile", - "abbr": "O.Mob", - "prefix": "o", - "type": "mobile", - "usage_global": { - "0": 0, - "10": 0, - "11.5": 0.00726525, - "12": 0.0363263, - "12.1": 0.101714 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "10", null, null, "11.5", "12", "12.1", "0", null, null], - "current_version": "16", - "prefix_exceptions": { - "0": "webkit" - } - }, - "bb": { - "browser": "Blackberry Browser", - "abbr": "BB", - "prefix": "webkit", - "type": "mobile", - "usage_global": { - "10": 0, - "7": 0.141419 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "7", "10", null, null], - "current_version": "" - }, - "and_chr": { - "browser": "Chrome for Android", - "abbr": "Chr/And.", - "prefix": "webkit", - "type": "mobile", - "usage_global": { - "0": 1.38176 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "0", null, null], - "current_version": "30" - }, - "and_ff": { - "browser": "Firefox for Android", - "abbr": "FF/And.", - "prefix": "moz", - "type": "mobile", - "usage_global": { - "0": 0.070956 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "0", null, null], - "current_version": "25" - }, - "ie_mob": { - "browser": "IE Mobile", - "abbr": "IE.Mob", - "prefix": "ms", - "type": "mobile", - "usage_global": { - "10": 0.205595 - }, - "versions": [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "10", null, null], - "current_version": "" - } - }, - "statuses": { - "rec": "Recommendation", - "pr": "Proposed Recommendation", - "cr": "Candidate Recommendation", - "wd": "Working Draft", - "other": "Other", - "unoff": "Unofficial / Note" - }, - "cats": { - "CSS": ["CSS", "CSS2", "CSS3"], - "HTML5": ["Canvas", "HTML5"], - "JS API": ["JS API"], - "Other": ["PNG", "Other", "DOM"], - "SVG": ["SVG"] - }, - "updated": 1383587152, - "data": { - "png-alpha": { - "title": "PNG alpha transparency", - "description": "Semi-transparent areas in PNG files", - "spec": "http://www.w3.org/TR/PNG/", - "status": "rec", - "links": [{ - "url": "http://dillerdesign.com/experiment/DD_belatedPNG/", - "title": "Workaround for IE6" - }, { - "url": "http://en.wikipedia.org/wiki/Portable_Network_Graphics", - "title": "Wikipedia" - }], - "categories": ["PNG"], - "stats": { - "ie": { - "5.5": "n", - "6": "p", - "7": "y", - "8": "y", - "9": "y", - "10": "y", - "11": "y" - }, - "firefox": { - "2": "y", - "3": "y", - "3.5": "y", - "3.6": "y", - "4": "y", - "5": "y", - "6": "y", - "7": "y", - "8": "y", - "9": "y", - "10": "y", - "11": "y", - "12": "y", - "13": "y", - "14": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y", - "19": "y", - "20": "y", - "21": "y", - "22": "y", - "23": "y", - "24": "y", - "25": "y", - "26": "y", - "27": "y" - }, - "chrome": { - "4": "y", - "5": "y", - "6": "y", - "7": "y", - "8": "y", - "9": "y", - "10": "y", - "11": "y", - "12": "y", - "13": "y", - "14": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y", - "19": "y", - "20": "y", - "21": "y", - "22": "y", - "23": "y", - "24": "y", - "25": "y", - "26": "y", - "27": "y", - "28": "y", - "29": "y", - "30": "y", - "31": "y", - "32": "y" - }, - "safari": { - "3.1": "y", - "3.2": "y", - "4": "y", - "5": "y", - "5.1": "y", - "6": "y", - "6.1": "y", - "7": "y" - }, - "opera": { - "9": "y", - "9.5-9.6": "y", - "10.0-10.1": "y", - "10.5": "y", - "10.6": "y", - "11": "y", - "11.1": "y", - "11.5": "y", - "11.6": "y", - "12": "y", - "12.1": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y" - }, - "ios_saf": { - "3.2": "y", - "4.0-4.1": "y", - "4.2-4.3": "y", - "5.0-5.1": "y", - "6.0-6.1": "y", - "7.0": "y" - }, - "op_mini": { - "5.0-7.0": "y" - }, - "android": { - "2.1": "y", - "2.2": "y", - "2.3": "y", - "3": "y", - "4": "y", - "4.1": "y", - "4.2-4.3": "y", - "4.4": "y" - }, - "bb": { - "7": "y", - "10": "y" - }, - "op_mob": { - "10": "y", - "11": "y", - "11.1": "y", - "11.5": "y", - "12": "y", - "12.1": "y", - "0": "y" - }, - "and_chr": { - "0": "y" - }, - "and_ff": { - "0": "y" - }, - "ie_mob": { - "10": "y" - } - }, - "notes": "IE6 does support full transparency in 8-bit PNGs, which can sometimes be an alternative to 24-bit PNGs.", - "usage_perc_y": 94.36, - "usage_perc_a": 0, - "ucprefix": false, - "parent": "", - "keywords": "" - }, - "apng": { - "title": "Animated PNG (APNG)", - "description": "Like animated GIFs, but allowing 24-bit colors and alpha transparency", - "spec": "https://wiki.mozilla.org/APNG_Specification", - "status": "unoff", - "links": [{ - "url": "http://en.wikipedia.org/wiki/APNG", - "title": "Wikipedia" - }, { - "url": "https://github.com/davidmz/apng-canvas", - "title": "Polyfill using canvas" - }, { - "url": "https://chrome.google.com/webstore/detail/ehkepjiconegkhpodgoaeamnpckdbblp", - "title": "Chrome extension providing support" - }, { - "url": "http://www.truekolor.net/learn-how-to-create-an-animated-png/", - "title": "APNG tutorial" - }], - "categories": ["PNG"], - "stats": { - "ie": { - "5.5": "n", - "6": "n", - "7": "n", - "8": "n", - "9": "n", - "10": "n", - "11": "n" - }, - "firefox": { - "2": "n", - "3": "y", - "3.5": "y", - "3.6": "y", - "4": "y", - "5": "y", - "6": "y", - "7": "y", - "8": "y", - "9": "y", - "10": "y", - "11": "y", - "12": "y", - "13": "y", - "14": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y", - "19": "y", - "20": "y", - "21": "y", - "22": "y", - "23": "y", - "24": "y", - "25": "y", - "26": "y", - "27": "y" - }, - "chrome": { - "4": "n", - "5": "n", - "6": "n", - "7": "n", - "8": "n", - "9": "n", - "10": "n", - "11": "n", - "12": "n", - "13": "n", - "14": "n", - "15": "n", - "16": "n", - "17": "n", - "18": "n", - "19": "n", - "20": "n", - "21": "n", - "22": "n", - "23": "n", - "24": "n", - "25": "n", - "26": "n", - "27": "n", - "28": "n", - "29": "n", - "30": "n", - "31": "n", - "32": "n" - }, - "safari": { - "3.1": "n", - "3.2": "n", - "4": "n", - "5": "n", - "5.1": "n", - "6": "n", - "6.1": "n", - "7": "n" - }, - "opera": { - "9": "n", - "9.5-9.6": "y", - "10.0-10.1": "y", - "10.5": "y", - "10.6": "y", - "11": "y", - "11.1": "y", - "11.5": "y", - "11.6": "y", - "12": "y", - "12.1": "y", - "15": "n", - "16": "n", - "17": "n", - "18": "n" - }, - "ios_saf": { - "3.2": "n", - "4.0-4.1": "n", - "4.2-4.3": "n", - "5.0-5.1": "n", - "6.0-6.1": "n", - "7.0": "n" - }, - "op_mini": { - "5.0-7.0": "n" - }, - "android": { - "2.1": "n", - "2.2": "n", - "2.3": "n", - "3": "n", - "4": "n", - "4.1": "n", - "4.2-4.3": "n", - "4.4": "n" - }, - "bb": { - "7": "n", - "10": "n" - }, - "op_mob": { - "10": "y", - "11": "y", - "11.1": "y", - "11.5": "y", - "12": "y", - "12.1": "y", - "0": "n" - }, - "and_chr": { - "0": "n" - }, - "and_ff": { - "0": "y" - }, - "ie_mob": { - "10": "n" - } - }, - "notes": "Where support for APNG is missing, only the first frame is displayed", - "usage_perc_y": 16.19, - "usage_perc_a": 0, - "ucprefix": false, - "parent": "", - "keywords": "" - }, - "video": { - "title": "Video element", - "description": "Method of playing videos on webpages (without requiring a plug-in)", - "spec": "http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#video", - "status": "wd", - "links": [{ - "url": "https://raw.github.com/phiggins42/has.js/master/detect/video.js#video", - "title": "has.js test" - }, { - "url": "http://webmproject.org", - "title": "WebM format information" - }, { - "url": "http://docs.webplatform.org/wiki/html/elements/video", - "title": "WebPlatform Docs" - }, { - "url": "http://camendesign.co.uk/code/video_for_everybody", - "title": "Video for Everybody" - }, { - "url": "http://diveinto.org/html5/video.html", - "title": "Video on the Web - includes info on Android support" - }, { - "url": "http://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-audio/", - "title": "Detailed article on video/audio elements" - }], - "categories": ["HTML5"], - "stats": { - "ie": { - "5.5": "n", - "6": "n", - "7": "n", - "8": "n", - "9": "y", - "10": "y", - "11": "y" - }, - "firefox": { - "2": "n", - "3": "n", - "3.5": "y", - "3.6": "y", - "4": "y", - "5": "y", - "6": "y", - "7": "y", - "8": "y", - "9": "y", - "10": "y", - "11": "y", - "12": "y", - "13": "y", - "14": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y", - "19": "y", - "20": "y", - "21": "y", - "22": "y", - "23": "y", - "24": "y", - "25": "y", - "26": "y", - "27": "y" - }, - "chrome": { - "4": "y", - "5": "y", - "6": "y", - "7": "y", - "8": "y", - "9": "y", - "10": "y", - "11": "y", - "12": "y", - "13": "y", - "14": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y", - "19": "y", - "20": "y", - "21": "y", - "22": "y", - "23": "y", - "24": "y", - "25": "y", - "26": "y", - "27": "y", - "28": "y", - "29": "y", - "30": "y", - "31": "y", - "32": "y" - }, - "safari": { - "3.1": "n", - "3.2": "n", - "4": "y", - "5": "y", - "5.1": "y", - "6": "y", - "6.1": "y", - "7": "y" - }, - "opera": { - "9": "n", - "9.5-9.6": "n", - "10.0-10.1": "n", - "10.5": "y", - "10.6": "y", - "11": "y", - "11.1": "y", - "11.5": "y", - "11.6": "y", - "12": "y", - "12.1": "y", - "15": "y", - "16": "y", - "17": "y", - "18": "y" - }, - "ios_saf": { - "3.2": "y", - "4.0-4.1": "y", - "4.2-4.3": "y", - "5.0-5.1": "y", - "6.0-6.1": "y", - "7.0": "y" - }, - "op_mini": { - "5.0-7.0": "n" - }, - "android": { - "2.1": "a", - "2.2": "a", - "2.3": "y", - "3": "y", - "4": "y", - "4.1": "y", - "4.2-4.3": "y", - "4.4": "y" - }, - "bb": { - "7": "y", - "10": "y" - }, - "op_mob": { - "10": "n", - "11": "y", - "11.1": "y", - "11.5": "y", - "12": "y", - "12.1": "y", - "0": "y" - }, - "and_chr": { - "0": "y" - }, - "and_ff": { - "0": "y" - }, - "ie_mob": { - "10": "y" - } - }, - "notes": "Different browsers have support for different video formats, see sub-features for details. \r\n\r\nThe Android browser (before 2.3) requires specific handling to run the video element.", - "usage_perc_y": 80.71, - "usage_perc_a": 0.11, - "ucprefix": false, - "parent": "", - "keywords": "
      ]", - "[link ]", - "[tag&bracket <][tag div][tag&bracket >]", - "[tag&bracket ]"); - -})(); diff --git a/public/js/lib/codemirror/mode/meta.js b/public/js/lib/codemirror/mode/meta.js deleted file mode 100644 index fcaed98e2d..0000000000 --- a/public/js/lib/codemirror/mode/meta.js +++ /dev/null @@ -1,165 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.modeInfo = [ - {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]}, - {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk"}, - {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]}, - {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "hpp", "h++"], alias: ["cpp"]}, - {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]}, - {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]}, - {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj"]}, - {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]}, - {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]}, - {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher"}, - {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]}, - {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]}, - {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]}, - {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]}, - {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]}, - {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]}, - {name: "Django", mime: "text/x-django", mode: "django"}, - {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile"}, - {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]}, - {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]}, - {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"}, - {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]}, - {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]}, - {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]}, - {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]}, - {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]}, - {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]}, - {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]}, - {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]}, - {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]}, - {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm"}, - {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]}, - {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]}, - {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]}, - {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]}, - {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]}, - {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]}, - {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]}, - {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]}, - {name: "HTTP", mime: "message/http", mode: "http"}, - {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]}, - {name: "Jade", mime: "text/x-jade", mode: "jade", ext: ["jade"]}, - {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]}, - {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]}, - {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"], - mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]}, - {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]}, - {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", alias: ["jsonld"]}, - {name: "Jinja2", mime: "null", mode: "jinja2"}, - {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]}, - {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]}, - {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]}, - {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]}, - {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]}, - {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]}, - {name: "mIRC", mime: "text/mirc", mode: "mirc"}, - {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"}, - {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]}, - {name: "MS SQL", mime: "text/x-mssql", mode: "sql"}, - {name: "MySQL", mime: "text/x-mysql", mode: "sql"}, - {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx"}, - {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]}, - {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]}, - {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]}, - {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]}, - {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]}, - {name: "PEG.js", mime: "null", mode: "pegjs"}, - {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]}, - {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]}, - {name: "Pig", mime: "text/x-pig", mode: "pig"}, - {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]}, - {name: "PLSQL", mime: "text/x-plsql", mode: "sql"}, - {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]}, - {name: "Python", mime: "text/x-python", mode: "python", ext: ["py", "pyw"]}, - {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]}, - {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]}, - {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r"], alias: ["rscript"]}, - {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]}, - {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"}, - {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]}, - {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]}, - {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]}, - {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]}, - {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]}, - {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]}, - {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]}, - {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]}, - {name: "Sieve", mime: "application/sieve", mode: "sieve"}, - {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim"}, - {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]}, - {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]}, - {name: "SmartyMixed", mime: "text/x-smarty", mode: "smartymixed"}, - {name: "Solr", mime: "text/x-solr", mode: "solr"}, - {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]}, - {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]}, - {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]}, - {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]}, - {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"}, - {name: "sTeX", mime: "text/x-stex", mode: "stex"}, - {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]}, - {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]}, - {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]}, - {name: "Textile", mime: "text/x-textile", mode: "textile"}, - {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"}, - {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"}, - {name: "TOML", mime: "text/x-toml", mode: "toml"}, - {name: "Tornado", mime: "text/x-tornado", mode: "tornado"}, - {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]}, - {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]}, - {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]}, - {name: "VBScript", mime: "text/vbscript", mode: "vbscript"}, - {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]}, - {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]}, - {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]}, - {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]}, - {name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml"], alias: ["yml"]}, - {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]} - ]; - // Ensure all modes have a mime property for backwards compatibility - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.mimes) info.mime = info.mimes[0]; - } - - CodeMirror.findModeByMIME = function(mime) { - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.mime == mime) return info; - if (info.mimes) for (var j = 0; j < info.mimes.length; j++) - if (info.mimes[j] == mime) return info; - } - }; - - CodeMirror.findModeByExtension = function(ext) { - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.ext) for (var j = 0; j < info.ext.length; j++) - if (info.ext[j] == ext) return info; - } - }; - - CodeMirror.findModeByName = function(name) { - name = name.toLowerCase(); - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.name.toLowerCase() == name) return info; - if (info.alias) for (var j = 0; j < info.alias.length; j++) - if (info.alias[j].toLowerCase() == name) return info; - } - }; -}); diff --git a/public/js/lib/codemirror/mode/xml/index.html b/public/js/lib/codemirror/mode/xml/index.html deleted file mode 100644 index 7149f06b2a..0000000000 --- a/public/js/lib/codemirror/mode/xml/index.html +++ /dev/null @@ -1,57 +0,0 @@ - - -CodeMirror: XML mode - - - - - - - - - -
      -

      XML mode

      -
      - -

      The XML mode supports two configuration parameters:

      -
      -
      htmlMode (boolean)
      -
      This switches the mode to parse HTML instead of XML. This - means attributes do not have to be quoted, and some elements - (such as br) do not require a closing tag.
      -
      alignCDATA (boolean)
      -
      Setting this to true will force the opening tag of CDATA - blocks to not be indented.
      -
      - -

      MIME types defined: application/xml, text/html.

      -
      diff --git a/public/js/lib/codemirror/mode/xml/test.js b/public/js/lib/codemirror/mode/xml/test.js deleted file mode 100644 index f48156b517..0000000000 --- a/public/js/lib/codemirror/mode/xml/test.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml"; - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); } - - MT("matching", - "[tag&bracket <][tag top][tag&bracket >]", - " text", - " [tag&bracket <][tag inner][tag&bracket />]", - "[tag&bracket ]"); - - MT("nonmatching", - "[tag&bracket <][tag top][tag&bracket >]", - " [tag&bracket <][tag inner][tag&bracket />]", - " [tag&bracket ]"); - - MT("doctype", - "[meta ]", - "[tag&bracket <][tag top][tag&bracket />]"); - - MT("cdata", - "[tag&bracket <][tag top][tag&bracket >]", - " [atom ]", - "[tag&bracket ]"); - - // HTML tests - mode = CodeMirror.getMode({indentUnit: 2}, "text/html"); - - MT("selfclose", - "[tag&bracket <][tag html][tag&bracket >]", - " [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]", - "[tag&bracket ]"); - - MT("list", - "[tag&bracket <][tag ol][tag&bracket >]", - " [tag&bracket <][tag li][tag&bracket >]one", - " [tag&bracket <][tag li][tag&bracket >]two", - "[tag&bracket ]"); - - MT("valueless", - "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]"); - - MT("pThenArticle", - "[tag&bracket <][tag p][tag&bracket >]", - " foo", - "[tag&bracket <][tag article][tag&bracket >]bar"); - -})(); diff --git a/public/js/lib/codemirror/mode/xml/xml.js b/public/js/lib/codemirror/mode/xml/xml.js deleted file mode 100644 index 2f3b8f87a0..0000000000 --- a/public/js/lib/codemirror/mode/xml/xml.js +++ /dev/null @@ -1,384 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("xml", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; - var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; - if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; - - var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, - 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, - 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, - 'track': true, 'wbr': true, 'menuitem': true}, - implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, - 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, - 'th': true, 'tr': true}, - contextGrabbers: { - 'dd': {'dd': true, 'dt': true}, - 'dt': {'dd': true, 'dt': true}, - 'li': {'li': true}, - 'option': {'option': true, 'optgroup': true}, - 'optgroup': {'optgroup': true}, - 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, - 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, - 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, - 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, - 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, - 'rp': {'rp': true, 'rt': true}, - 'rt': {'rp': true, 'rt': true}, - 'tbody': {'tbody': true, 'tfoot': true}, - 'td': {'td': true, 'th': true}, - 'tfoot': {'tbody': true}, - 'th': {'td': true, 'th': true}, - 'thead': {'tbody': true, 'tfoot': true}, - 'tr': {'tr': true} - }, - doNotIndent: {"pre": true}, - allowUnquoted: true, - allowMissing: true, - caseFold: true - } : { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false, - caseFold: false - }; - var alignCDATA = parserConfig.alignCDATA; - - // Return variables for tokenizers - var type, setStyle; - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - - var ch = stream.next(); - if (ch == "<") { - if (stream.eat("!")) { - if (stream.eat("[")) { - if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); - else return null; - } else if (stream.match("--")) { - return chain(inBlock("comment", "-->")); - } else if (stream.match("DOCTYPE", true, true)) { - stream.eatWhile(/[\w\._\-]/); - return chain(doctype(1)); - } else { - return null; - } - } else if (stream.eat("?")) { - stream.eatWhile(/[\w\._\-]/); - state.tokenize = inBlock("meta", "?>"); - return "meta"; - } else { - type = stream.eat("/") ? "closeTag" : "openTag"; - state.tokenize = inTag; - return "tag bracket"; - } - } else if (ch == "&") { - var ok; - if (stream.eat("#")) { - if (stream.eat("x")) { - ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); - } else { - ok = stream.eatWhile(/[\d]/) && stream.eat(";"); - } - } else { - ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); - } - return ok ? "atom" : "error"; - } else { - stream.eatWhile(/[^&<]/); - return null; - } - } - - function inTag(stream, state) { - var ch = stream.next(); - if (ch == ">" || (ch == "/" && stream.eat(">"))) { - state.tokenize = inText; - type = ch == ">" ? "endTag" : "selfcloseTag"; - return "tag bracket"; - } else if (ch == "=") { - type = "equals"; - return null; - } else if (ch == "<") { - state.tokenize = inText; - state.state = baseState; - state.tagName = state.tagStart = null; - var next = state.tokenize(stream, state); - return next ? next + " tag error" : "tag error"; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - state.stringStartCol = stream.column(); - return state.tokenize(stream, state); - } else { - stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/); - return "word"; - } - } - - function inAttribute(quote) { - var closure = function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inTag; - break; - } - } - return "string"; - }; - closure.isInAttribute = true; - return closure; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - return style; - }; - } - function doctype(depth) { - return function(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch == "<") { - state.tokenize = doctype(depth + 1); - return state.tokenize(stream, state); - } else if (ch == ">") { - if (depth == 1) { - state.tokenize = inText; - break; - } else { - state.tokenize = doctype(depth - 1); - return state.tokenize(stream, state); - } - } - } - return "meta"; - }; - } - - function Context(state, tagName, startOfLine) { - this.prev = state.context; - this.tagName = tagName; - this.indent = state.indented; - this.startOfLine = startOfLine; - if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) - this.noIndent = true; - } - function popContext(state) { - if (state.context) state.context = state.context.prev; - } - function maybePopContext(state, nextTagName) { - var parentTagName; - while (true) { - if (!state.context) { - return; - } - parentTagName = state.context.tagName; - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || - !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { - return; - } - popContext(state); - } - } - - function baseState(type, stream, state) { - if (type == "openTag") { - state.tagStart = stream.column(); - return tagNameState; - } else if (type == "closeTag") { - return closeTagNameState; - } else { - return baseState; - } - } - function tagNameState(type, stream, state) { - if (type == "word") { - state.tagName = stream.current(); - setStyle = "tag"; - return attrState; - } else { - setStyle = "error"; - return tagNameState; - } - } - function closeTagNameState(type, stream, state) { - if (type == "word") { - var tagName = stream.current(); - if (state.context && state.context.tagName != tagName && - Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName)) - popContext(state); - if (state.context && state.context.tagName == tagName) { - setStyle = "tag"; - return closeState; - } else { - setStyle = "tag error"; - return closeStateErr; - } - } else { - setStyle = "error"; - return closeStateErr; - } - } - - function closeState(type, _stream, state) { - if (type != "endTag") { - setStyle = "error"; - return closeState; - } - popContext(state); - return baseState; - } - function closeStateErr(type, stream, state) { - setStyle = "error"; - return closeState(type, stream, state); - } - - function attrState(type, _stream, state) { - if (type == "word") { - setStyle = "attribute"; - return attrEqState; - } else if (type == "endTag" || type == "selfcloseTag") { - var tagName = state.tagName, tagStart = state.tagStart; - state.tagName = state.tagStart = null; - if (type == "selfcloseTag" || - Kludges.autoSelfClosers.hasOwnProperty(tagName)) { - maybePopContext(state, tagName); - } else { - maybePopContext(state, tagName); - state.context = new Context(state, tagName, tagStart == state.indented); - } - return baseState; - } - setStyle = "error"; - return attrState; - } - function attrEqState(type, stream, state) { - if (type == "equals") return attrValueState; - if (!Kludges.allowMissing) setStyle = "error"; - return attrState(type, stream, state); - } - function attrValueState(type, stream, state) { - if (type == "string") return attrContinuedState; - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} - setStyle = "error"; - return attrState(type, stream, state); - } - function attrContinuedState(type, stream, state) { - if (type == "string") return attrContinuedState; - return attrState(type, stream, state); - } - - return { - startState: function() { - return {tokenize: inText, - state: baseState, - indented: 0, - tagName: null, tagStart: null, - context: null}; - }, - - token: function(stream, state) { - if (!state.tagName && stream.sol()) - state.indented = stream.indentation(); - - if (stream.eatSpace()) return null; - type = null; - var style = state.tokenize(stream, state); - if ((style || type) && style != "comment") { - setStyle = null; - state.state = state.state(type || style, stream, state); - if (setStyle) - style = setStyle == "error" ? style + " error" : setStyle; - } - return style; - }, - - indent: function(state, textAfter, fullLine) { - var context = state.context; - // Indent multi-line strings (e.g. css). - if (state.tokenize.isInAttribute) { - if (state.tagStart == state.indented) - return state.stringStartCol + 1; - else - return state.indented + indentUnit; - } - if (context && context.noIndent) return CodeMirror.Pass; - if (state.tokenize != inTag && state.tokenize != inText) - return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; - // Indent the starts of attribute names. - if (state.tagName) { - if (multilineTagIndentPastTag) - return state.tagStart + state.tagName.length + 2; - else - return state.tagStart + indentUnit * multilineTagIndentFactor; - } - if (alignCDATA && /$/, - blockCommentStart: "", - - configuration: parserConfig.htmlMode ? "html" : "xml", - helperType: parserConfig.htmlMode ? "html" : "xml" - }; -}); - -CodeMirror.defineMIME("text/xml", "xml"); -CodeMirror.defineMIME("application/xml", "xml"); -if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) - CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); - -}); diff --git a/public/js/lib/codemirror/mode/yaml/index.html b/public/js/lib/codemirror/mode/yaml/index.html deleted file mode 100644 index be9b632368..0000000000 --- a/public/js/lib/codemirror/mode/yaml/index.html +++ /dev/null @@ -1,80 +0,0 @@ - - -CodeMirror: YAML mode - - - - - - - - - -
      -

      YAML mode

      -
      - - -

      MIME types defined: text/x-yaml.

      - -
      diff --git a/public/js/lib/codemirror/mode/yaml/yaml.js b/public/js/lib/codemirror/mode/yaml/yaml.js deleted file mode 100644 index b7015e599c..0000000000 --- a/public/js/lib/codemirror/mode/yaml/yaml.js +++ /dev/null @@ -1,117 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("yaml", function() { - - var cons = ['true', 'false', 'on', 'off', 'yes', 'no']; - var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i'); - - return { - token: function(stream, state) { - var ch = stream.peek(); - var esc = state.escaped; - state.escaped = false; - /* comments */ - if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) { - stream.skipToEnd(); - return "comment"; - } - - if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/)) - return "string"; - - if (state.literal && stream.indentation() > state.keyCol) { - stream.skipToEnd(); return "string"; - } else if (state.literal) { state.literal = false; } - if (stream.sol()) { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - /* document start */ - if(stream.match(/---/)) { return "def"; } - /* document end */ - if (stream.match(/\.\.\./)) { return "def"; } - /* array list item */ - if (stream.match(/\s*-\s+/)) { return 'meta'; } - } - /* inline pairs/lists */ - if (stream.match(/^(\{|\}|\[|\])/)) { - if (ch == '{') - state.inlinePairs++; - else if (ch == '}') - state.inlinePairs--; - else if (ch == '[') - state.inlineList++; - else - state.inlineList--; - return 'meta'; - } - - /* list seperator */ - if (state.inlineList > 0 && !esc && ch == ',') { - stream.next(); - return 'meta'; - } - /* pairs seperator */ - if (state.inlinePairs > 0 && !esc && ch == ',') { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - stream.next(); - return 'meta'; - } - - /* start of value of a pair */ - if (state.pairStart) { - /* block literals */ - if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; }; - /* references */ - if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; } - /* numbers */ - if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; } - if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; } - /* keywords */ - if (stream.match(keywordRegex)) { return 'keyword'; } - } - - /* pairs (associative arrays) -> key */ - if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) { - state.pair = true; - state.keyCol = stream.indentation(); - return "atom"; - } - if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; } - - /* nothing found, continue */ - state.pairStart = false; - state.escaped = (ch == '\\'); - stream.next(); - return null; - }, - startState: function() { - return { - pair: false, - pairStart: false, - keyCol: 0, - inlinePairs: 0, - inlineList: 0, - literal: false, - escaped: false - }; - } - }; -}); - -CodeMirror.defineMIME("text/x-yaml", "yaml"); - -}); diff --git a/public/js/lib/codemirror/package.json b/public/js/lib/codemirror/package.json deleted file mode 100644 index f934a08e02..0000000000 --- a/public/js/lib/codemirror/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "codemirror", - "version":"4.10.0", - "main": "lib/codemirror.js", - "description": "In-browser code editing made bearable", - "licenses": [{"type": "MIT", - "url": "http://codemirror.net/LICENSE"}], - "directories": {"lib": "./lib"}, - "scripts": {"test": "node ./test/run.js"}, - "devDependencies": {"node-static": "0.6.0", - "phantomjs": "1.9.2-5"}, - "bugs": "http://github.com/codemirror/CodeMirror/issues", - "keywords": ["JavaScript", "CodeMirror", "Editor"], - "homepage": "http://codemirror.net", - "maintainers":[{"name": "Marijn Haverbeke", - "email": "marijnh@gmail.com", - "web": "http://marijnhaverbeke.nl"}], - "repository": {"type": "git", - "url": "https://github.com/codemirror/CodeMirror.git"} -} diff --git a/public/js/lib/codemirror/test/comment_test.js b/public/js/lib/codemirror/test/comment_test.js deleted file mode 100644 index 8bd3959ee9..0000000000 --- a/public/js/lib/codemirror/test/comment_test.js +++ /dev/null @@ -1,100 +0,0 @@ -namespace = "comment_"; - -(function() { - function test(name, mode, run, before, after) { - return testCM(name, function(cm) { - run(cm); - eq(cm.getValue(), after); - }, {value: before, mode: mode}); - } - - var simpleProg = "function foo() {\n return bar;\n}"; - var inlineBlock = "foo(/* bar */ true);"; - var inlineBlocks = "foo(/* bar */ true, /* baz */ false);"; - var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"]; - - test("block", "javascript", function(cm) { - cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"}); - }, simpleProg + "\n", "/* function foo() {\n * return bar;\n * }\n */"); - - test("blockToggle", "javascript", function(cm) { - cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); - cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); - }, simpleProg, simpleProg); - - test("blockToggle2", "javascript", function(cm) { - cm.setCursor({line: 0, ch: 7 /* inside the block comment */}); - cm.execCommand("toggleComment"); - }, inlineBlock, "foo(bar true);"); - - // This test should work but currently fails. - // test("blockToggle3", "javascript", function(cm) { - // cm.setCursor({line: 0, ch: 7 /* inside the first block comment */}); - // cm.execCommand("toggleComment"); - // }, inlineBlocks, "foo(bar true, /* baz */ false);"); - - test("line", "javascript", function(cm) { - cm.lineComment(Pos(1, 1), Pos(1, 1)); - }, simpleProg, "function foo() {\n// return bar;\n}"); - - test("lineToggle", "javascript", function(cm) { - cm.lineComment(Pos(0, 0), Pos(2, 1)); - cm.uncomment(Pos(0, 0), Pos(2, 1)); - }, simpleProg, simpleProg); - - test("fallbackToBlock", "css", function(cm) { - cm.lineComment(Pos(0, 0), Pos(2, 1)); - }, "html {\n border: none;\n}", "/* html {\n border: none;\n} */"); - - test("fallbackToLine", "ruby", function(cm) { - cm.blockComment(Pos(0, 0), Pos(1)); - }, "def blah()\n return hah\n", "# def blah()\n# return hah\n"); - - test("ignoreExternalBlockComments", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, inlineBlocks, "// " + inlineBlocks); - - test("ignoreExternalBlockComments2", "javascript", function(cm) { - cm.setCursor({line: 0, ch: null /* eol */}); - cm.execCommand("toggleComment"); - }, inlineBlocks, "// " + inlineBlocks); - - test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) { - cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1}); - cm.execCommand("toggleComment"); - }, multiLineInlineBlock.join("\n"), ["// " + multiLineInlineBlock[0], - "// " + multiLineInlineBlock[1], - multiLineInlineBlock[2]].join("\n")); - - test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) { - cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1}); - cm.execCommand("toggleComment"); - }, multiLineInlineBlock.join("\n"), [multiLineInlineBlock[0], - "// " + multiLineInlineBlock[1], - "// " + multiLineInlineBlock[2]].join("\n")); - - test("commentRange", "javascript", function(cm) { - cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false}); - }, simpleProg, "function foo() {\n /*return bar;*/\n}"); - - test("indented", "javascript", function(cm) { - cm.lineComment(Pos(1, 0), Pos(2), {indent: true}); - }, simpleProg, "function foo() {\n // return bar;\n // }"); - - test("singleEmptyLine", "javascript", function(cm) { - cm.setCursor(1); - cm.execCommand("toggleComment"); - }, "a;\n\nb;", "a;\n// \nb;"); - - test("dontMessWithStrings", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "console.log(\"/*string*/\");", "// console.log(\"/*string*/\");"); - - test("dontMessWithStrings2", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "console.log(\"// string\");", "// console.log(\"// string\");"); - - test("dontMessWithStrings3", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "// console.log(\"// string\");", "console.log(\"// string\");"); -})(); diff --git a/public/js/lib/codemirror/test/doc_test.js b/public/js/lib/codemirror/test/doc_test.js deleted file mode 100644 index 5f242f658d..0000000000 --- a/public/js/lib/codemirror/test/doc_test.js +++ /dev/null @@ -1,371 +0,0 @@ -(function() { - // A minilanguage for instantiating linked CodeMirror instances and Docs - function instantiateSpec(spec, place, opts) { - var names = {}, pos = 0, l = spec.length, editors = []; - while (spec) { - var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/); - var name = m[1], isDoc = m[2], cur; - if (m[3]) { - cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]})); - } else { - var other = m[5]; - if (!names.hasOwnProperty(other)) { - names[other] = editors.length; - editors.push(CodeMirror(place, opts)); - } - var doc = editors[names[other]].linkedDoc({ - sharedHist: !m[4], - from: m[6] ? Number(m[6]) : null, - to: m[7] ? Number(m[7]) : null - }); - cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc})); - } - names[name] = editors.length; - editors.push(cur); - spec = spec.slice(m[0].length); - } - return editors; - } - - function clone(obj, props) { - if (!obj) return; - clone.prototype = obj; - var inst = new clone(); - if (props) for (var n in props) if (props.hasOwnProperty(n)) - inst[n] = props[n]; - return inst; - } - - function eqAll(val) { - var end = arguments.length, msg = null; - if (typeof arguments[end-1] == "string") - msg = arguments[--end]; - if (i == end) throw new Error("No editors provided to eqAll"); - for (var i = 1; i < end; ++i) - eq(arguments[i].getValue(), val, msg) - } - - function testDoc(name, spec, run, opts, expectFail) { - if (!opts) opts = {}; - - return test("doc_" + name, function() { - var place = document.getElementById("testground"); - var editors = instantiateSpec(spec, place, opts); - var successful = false; - - try { - run.apply(null, editors); - successful = true; - } finally { - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - for (var i = 0; i < editors.length; ++i) - if (editors[i] instanceof CodeMirror) - place.removeChild(editors[i].getWrapperElement()); - } - } - }, expectFail); - } - - var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); - - function testBasic(a, b) { - eqAll("x", a, b); - a.setValue("hey"); - eqAll("hey", a, b); - b.setValue("wow"); - eqAll("wow", a, b); - a.replaceRange("u\nv\nw", Pos(0, 3)); - b.replaceRange("i", Pos(0, 4)); - b.replaceRange("j", Pos(2, 1)); - eqAll("wowui\nv\nwj", a, b); - } - - testDoc("basic", "A='x' B 0, "not at left"); - is(pos.top > 0, "not at top"); - }); - - testDoc("copyDoc", "A='u'", function(a) { - var copy = a.getDoc().copy(true); - a.setValue("foo"); - copy.setValue("bar"); - var old = a.swapDoc(copy); - eq(a.getValue(), "bar"); - a.undo(); - eq(a.getValue(), "u"); - a.swapDoc(old); - eq(a.getValue(), "foo"); - eq(old.historySize().undo, 1); - eq(old.copy(false).historySize().undo, 0); - }); - - testDoc("docKeepsMode", "A='1+1'", function(a) { - var other = CodeMirror.Doc("hi", "text/x-markdown"); - a.setOption("mode", "text/javascript"); - var old = a.swapDoc(other); - eq(a.getOption("mode"), "text/x-markdown"); - eq(a.getMode().name, "markdown"); - a.swapDoc(old); - eq(a.getOption("mode"), "text/javascript"); - eq(a.getMode().name, "javascript"); - }); - - testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) { - eq(b.getValue(), "2\n3"); - eq(b.firstLine(), 1); - b.setCursor(Pos(4)); - eqPos(b.getCursor(), Pos(2, 1)); - a.replaceRange("-1\n0\n", Pos(0, 0)); - eq(b.firstLine(), 3); - eqPos(b.getCursor(), Pos(4, 1)); - a.undo(); - eqPos(b.getCursor(), Pos(2, 1)); - b.replaceRange("oyoy\n", Pos(2, 0)); - eq(a.getValue(), "1\n2\noyoy\n3\n4\n5"); - b.undo(); - eq(a.getValue(), "1\n2\n3\n4\n5"); - }); - - testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) { - a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1)); - eq(b.firstLine(), 2); - eq(b.lineCount(), 2); - eq(b.getValue(), "z3\n44"); - a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1)); - eq(b.firstLine(), 2); - eq(b.getValue(), "z3\n4q"); - eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5"); - a.execCommand("selectAll"); - a.replaceSelection("!"); - eqAll("!", a, b); - }); - - - testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B 500){ - totalTime = 0; - delay = 50; - } - setTimeout(function(){step(i + 1);}, delay); - } else { // Quit tests - running = false; - return null; - } - } - step(0); -} - -function label(str, msg) { - if (msg) return str + " (" + msg + ")"; - return str; -} -function eq(a, b, msg) { - if (a != b) throw new Failure(label(a + " != " + b, msg)); -} -function near(a, b, margin, msg) { - if (Math.abs(a - b) > margin) - throw new Failure(label(a + " is not close to " + b + " (" + margin + ")", msg)); -} -function eqPos(a, b, msg) { - function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; } - if (a == b) return; - if (a == null) throw new Failure(label("comparing null to " + str(b), msg)); - if (b == null) throw new Failure(label("comparing " + str(a) + " to null", msg)); - if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg)); -} -function is(a, msg) { - if (!a) throw new Failure(label("assertion failed", msg)); -} - -function countTests() { - if (!filters.length) return tests.length; - var sum = 0; - for (var i = 0; i < tests.length; ++i) { - var name = tests[i].name; - for (var j = 0; j < filters.length; j++) { - if (name.match(filters[j])) { - ++sum; - break; - } - } - } - return sum; -} - -function parseTestFilter(s) { - if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i"); - else return new RegExp(s, "i"); -} diff --git a/public/js/lib/codemirror/test/emacs_test.js b/public/js/lib/codemirror/test/emacs_test.js deleted file mode 100644 index ccbd6ce491..0000000000 --- a/public/js/lib/codemirror/test/emacs_test.js +++ /dev/null @@ -1,141 +0,0 @@ -(function() { - "use strict"; - - var Pos = CodeMirror.Pos; - namespace = "emacs_"; - - var eventCache = {}; - function fakeEvent(keyName) { - var event = eventCache[key]; - if (event) return event; - - var ctrl, shift, alt; - var key = keyName.replace(/\w+-/g, function(type) { - if (type == "Ctrl-") ctrl = true; - else if (type == "Alt-") alt = true; - else if (type == "Shift-") shift = true; - return ""; - }); - var code; - for (var c in CodeMirror.keyNames) - if (CodeMirror.keyNames[c] == key) { code = c; break; } - if (c == null) throw new Error("Unknown key: " + key); - - return eventCache[keyName] = { - type: "keydown", keyCode: code, ctrlKey: ctrl, shiftKey: shift, altKey: alt, - preventDefault: function(){}, stopPropagation: function(){} - }; - } - - function sim(name, start /*, actions... */) { - var keys = Array.prototype.slice.call(arguments, 2); - testCM(name, function(cm) { - for (var i = 0; i < keys.length; ++i) { - var cur = keys[i]; - if (cur instanceof Pos) cm.setCursor(cur); - else if (cur.call) cur(cm); - else cm.triggerOnKeyDown(fakeEvent(cur)); - } - }, {keyMap: "emacs", value: start, mode: "javascript"}); - } - - function at(line, ch) { return function(cm) { eqPos(cm.getCursor(), Pos(line, ch)); }; } - function txt(str) { return function(cm) { eq(cm.getValue(), str); }; } - - sim("motionHSimple", "abc", "Ctrl-F", "Ctrl-F", "Ctrl-B", at(0, 1)); - sim("motionHMulti", "abcde", - "Ctrl-4", "Ctrl-F", at(0, 4), "Ctrl--", "Ctrl-2", "Ctrl-F", at(0, 2), - "Ctrl-5", "Ctrl-B", at(0, 0)); - - sim("motionHWord", "abc. def ghi", - "Alt-F", at(0, 3), "Alt-F", at(0, 8), - "Ctrl-B", "Alt-B", at(0, 5), "Alt-B", at(0, 0)); - sim("motionHWordMulti", "abc. def ghi ", - "Ctrl-3", "Alt-F", at(0, 12), "Ctrl-2", "Alt-B", at(0, 5), - "Ctrl--", "Alt-B", at(0, 8)); - - sim("motionVSimple", "a\nb\nc\n", "Ctrl-N", "Ctrl-N", "Ctrl-P", at(1, 0)); - sim("motionVMulti", "a\nb\nc\nd\ne\n", - "Ctrl-2", "Ctrl-N", at(2, 0), "Ctrl-F", "Ctrl--", "Ctrl-N", at(1, 1), - "Ctrl--", "Ctrl-3", "Ctrl-P", at(4, 1)); - - sim("killYank", "abc\ndef\nghi", - "Ctrl-F", "Ctrl-Space", "Ctrl-N", "Ctrl-N", "Ctrl-W", "Ctrl-E", "Ctrl-Y", - txt("ahibc\ndef\ng")); - sim("killRing", "abcdef", - "Ctrl-Space", "Ctrl-F", "Ctrl-W", "Ctrl-Space", "Ctrl-F", "Ctrl-W", - "Ctrl-Y", "Alt-Y", - txt("acdef")); - sim("copyYank", "abcd", - "Ctrl-Space", "Ctrl-E", "Alt-W", "Ctrl-Y", - txt("abcdabcd")); - - sim("killLineSimple", "foo\nbar", "Ctrl-F", "Ctrl-K", txt("f\nbar")); - sim("killLineEmptyLine", "foo\n \nbar", "Ctrl-N", "Ctrl-K", txt("foo\nbar")); - sim("killLineMulti", "foo\nbar\nbaz", - "Ctrl-F", "Ctrl-F", "Ctrl-K", "Ctrl-K", "Ctrl-K", "Ctrl-A", "Ctrl-Y", - txt("o\nbarfo\nbaz")); - - sim("moveByParagraph", "abc\ndef\n\n\nhij\nklm\n\n", - "Ctrl-F", "Ctrl-Down", at(2, 0), "Ctrl-Down", at(6, 0), - "Ctrl-N", "Ctrl-Up", at(3, 0), "Ctrl-Up", at(0, 0), - Pos(1, 2), "Ctrl-Down", at(2, 0), Pos(4, 2), "Ctrl-Up", at(3, 0)); - sim("moveByParagraphMulti", "abc\n\ndef\n\nhij\n\nklm", - "Ctrl-U", "2", "Ctrl-Down", at(3, 0), - "Shift-Alt-.", "Ctrl-3", "Ctrl-Up", at(1, 0)); - - sim("moveBySentence", "sentence one! sentence\ntwo\n\nparagraph two", - "Alt-E", at(0, 13), "Alt-E", at(1, 3), "Ctrl-F", "Alt-A", at(0, 13)); - - sim("moveByExpr", "function foo(a, b) {}", - "Ctrl-Alt-F", at(0, 8), "Ctrl-Alt-F", at(0, 12), "Ctrl-Alt-F", at(0, 18), - "Ctrl-Alt-B", at(0, 12), "Ctrl-Alt-B", at(0, 9)); - sim("moveByExprMulti", "foo bar baz bug", - "Ctrl-2", "Ctrl-Alt-F", at(0, 7), - "Ctrl--", "Ctrl-Alt-F", at(0, 4), - "Ctrl--", "Ctrl-2", "Ctrl-Alt-B", at(0, 11)); - sim("delExpr", "var x = [\n a,\n b\n c\n];", - Pos(0, 8), "Ctrl-Alt-K", txt("var x = ;"), "Ctrl-/", - Pos(4, 1), "Ctrl-Alt-Backspace", txt("var x = ;")); - sim("delExprMulti", "foo bar baz", - "Ctrl-2", "Ctrl-Alt-K", txt(" baz"), - "Ctrl-/", "Ctrl-E", "Ctrl-2", "Ctrl-Alt-Backspace", txt("foo ")); - - sim("justOneSpace", "hi bye ", - Pos(0, 4), "Alt-Space", txt("hi bye "), - Pos(0, 4), "Alt-Space", txt("hi b ye "), - "Ctrl-A", "Alt-Space", "Ctrl-E", "Alt-Space", txt(" hi b ye ")); - - sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar")) - - sim("transposeChar", "abcd\ne", - "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3), - "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4), - "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 0)); - - sim("manipWordCase", "foo BAR bAZ", - "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"), - "Ctrl-A", "Alt-U", "Alt-L", "Alt-C", txt("FOO bar Baz")); - sim("manipWordCaseMulti", "foo Bar bAz", - "Ctrl-2", "Alt-U", txt("FOO BAR bAz"), - "Ctrl-A", "Ctrl-3", "Alt-C", txt("Foo Bar Baz")); - - sim("upExpr", "foo {\n bar[];\n baz(blah);\n}", - Pos(2, 7), "Ctrl-Alt-U", at(2, 5), "Ctrl-Alt-U", at(0, 4)); - sim("transposeExpr", "do foo[bar] dah", - Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah")); - - sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F", - "Ctrl-G", "Ctrl-W", txt("abcde")); - - sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde")); - sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde")); - - testCM("save", function(cm) { - var saved = false; - CodeMirror.commands.save = function(cm) { saved = cm.getValue(); }; - cm.triggerOnKeyDown(fakeEvent("Ctrl-X")); - cm.triggerOnKeyDown(fakeEvent("Ctrl-S")); - is(saved, "hi"); - }, {value: "hi", keyMap: "emacs"}); -})(); diff --git a/public/js/lib/codemirror/test/index.html b/public/js/lib/codemirror/test/index.html deleted file mode 100644 index 89f4e378c3..0000000000 --- a/public/js/lib/codemirror/test/index.html +++ /dev/null @@ -1,236 +0,0 @@ - - -CodeMirror: Test Suite - - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      Test Suite

      - -

      A limited set of programmatic sanity tests for CodeMirror.

      - -
      -
      Ran 0 of 0 tests
      -
      -

      Please enable JavaScript...

      -
      - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      diff --git a/public/js/lib/codemirror/test/lint/acorn.js b/public/js/lib/codemirror/test/lint/acorn.js deleted file mode 100644 index 0f11931752..0000000000 --- a/public/js/lib/codemirror/test/lint/acorn.js +++ /dev/null @@ -1,1782 +0,0 @@ -// Acorn is a tiny, fast JavaScript parser written in JavaScript. -// -// Acorn was written by Marijn Haverbeke and released under an MIT -// license. The Unicode regexps (for identifiers and whitespace) were -// taken from [Esprima](http://esprima.org) by Ariya Hidayat. -// -// Git repositories for Acorn are available at -// -// http://marijnhaverbeke.nl/git/acorn -// https://github.com/marijnh/acorn.git -// -// Please use the [github bug tracker][ghbt] to report issues. -// -// [ghbt]: https://github.com/marijnh/acorn/issues -// -// This file defines the main parser interface. The library also comes -// with a [error-tolerant parser][dammit] and an -// [abstract syntax tree walker][walk], defined in other files. -// -// [dammit]: acorn_loose.js -// [walk]: util/walk.js - -(function(root, mod) { - if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS - if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD - mod(root.acorn || (root.acorn = {})); // Plain browser env -})(this, function(exports) { - "use strict"; - - exports.version = "0.4.1"; - - // The main exported interface (under `self.acorn` when in the - // browser) is a `parse` function that takes a code string and - // returns an abstract syntax tree as specified by [Mozilla parser - // API][api], with the caveat that the SpiderMonkey-specific syntax - // (`let`, `yield`, inline XML, etc) is not recognized. - // - // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API - - var options, input, inputLen, sourceFile; - - exports.parse = function(inpt, opts) { - input = String(inpt); inputLen = input.length; - setOptions(opts); - initTokenState(); - return parseTopLevel(options.program); - }; - - // A second optional argument can be given to further configure - // the parser process. These options are recognized: - - var defaultOptions = exports.defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3 or 5. This - // influences support for strict mode, the set of reserved words, and - // support for getters and setter. - ecmaVersion: 5, - // Turn on `strictSemicolons` to prevent the parser from doing - // automatic semicolon insertion. - strictSemicolons: false, - // When `allowTrailingCommas` is false, the parser will not allow - // trailing commas in array and object literals. - allowTrailingCommas: true, - // By default, reserved words are not enforced. Enable - // `forbidReserved` to enforce them. When this option has the - // value "everywhere", reserved words and keywords can also not be - // used as property names. - forbidReserved: false, - // When enabled, a return at the top level is not considered an - // error. - allowReturnOutsideFunction: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. Note that you are not allowed to call the - // parser from the callback—that will corrupt its internal state. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `locations` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // This value, if given, is stored in every node, whether - // `locations` is on or off. - directSourceFile: null - }; - - function setOptions(opts) { - options = opts || {}; - for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt)) - options[opt] = defaultOptions[opt]; - sourceFile = options.sourceFile || null; - } - - // The `getLineInfo` function is mostly useful when the - // `locations` option is off (for performance reasons) and you - // want to find the line/column position for a given character - // offset. `input` should be the code string that the offset refers - // into. - - var getLineInfo = exports.getLineInfo = function(input, offset) { - for (var line = 1, cur = 0;;) { - lineBreak.lastIndex = cur; - var match = lineBreak.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; - } else break; - } - return {line: line, column: offset - cur}; - }; - - // Acorn is organized as a tokenizer and a recursive-descent parser. - // The `tokenize` export provides an interface to the tokenizer. - // Because the tokenizer is optimized for being efficiently used by - // the Acorn parser itself, this interface is somewhat crude and not - // very modular. Performing another parse or call to `tokenize` will - // reset the internal state, and invalidate existing tokenizers. - - exports.tokenize = function(inpt, opts) { - input = String(inpt); inputLen = input.length; - setOptions(opts); - initTokenState(); - - var t = {}; - function getToken(forceRegexp) { - lastEnd = tokEnd; - readToken(forceRegexp); - t.start = tokStart; t.end = tokEnd; - t.startLoc = tokStartLoc; t.endLoc = tokEndLoc; - t.type = tokType; t.value = tokVal; - return t; - } - getToken.jumpTo = function(pos, reAllowed) { - tokPos = pos; - if (options.locations) { - tokCurLine = 1; - tokLineStart = lineBreak.lastIndex = 0; - var match; - while ((match = lineBreak.exec(input)) && match.index < pos) { - ++tokCurLine; - tokLineStart = match.index + match[0].length; - } - } - tokRegexpAllowed = reAllowed; - skipSpace(); - }; - return getToken; - }; - - // State is kept in (closure-)global variables. We already saw the - // `options`, `input`, and `inputLen` variables above. - - // The current position of the tokenizer in the input. - - var tokPos; - - // The start and end offsets of the current token. - - var tokStart, tokEnd; - - // When `options.locations` is true, these hold objects - // containing the tokens start and end line/column pairs. - - var tokStartLoc, tokEndLoc; - - // The type and value of the current token. Token types are objects, - // named by variables against which they can be compared, and - // holding properties that describe them (indicating, for example, - // the precedence of an infix operator, and the original name of a - // keyword token). The kind of value that's held in `tokVal` depends - // on the type of the token. For literals, it is the literal value, - // for operators, the operator name, and so on. - - var tokType, tokVal; - - // Interal state for the tokenizer. To distinguish between division - // operators and regular expressions, it remembers whether the last - // token was one that is allowed to be followed by an expression. - // (If it is, a slash is probably a regexp, if it isn't it's a - // division operator. See the `parseStatement` function for a - // caveat.) - - var tokRegexpAllowed; - - // When `options.locations` is true, these are used to keep - // track of the current line, and know when a new line has been - // entered. - - var tokCurLine, tokLineStart; - - // These store the position of the previous token, which is useful - // when finishing a node and assigning its `end` position. - - var lastStart, lastEnd, lastEndLoc; - - // This is the parser's state. `inFunction` is used to reject - // `return` statements outside of functions, `labels` to verify that - // `break` and `continue` have somewhere to jump to, and `strict` - // indicates whether strict mode is on. - - var inFunction, labels, strict; - - // This function is used to raise exceptions on parse errors. It - // takes an offset integer (into the current `input`) to indicate - // the location of the error, attaches the position to the end - // of the error message, and then raises a `SyntaxError` with that - // message. - - function raise(pos, message) { - var loc = getLineInfo(input, pos); - message += " (" + loc.line + ":" + loc.column + ")"; - var err = new SyntaxError(message); - err.pos = pos; err.loc = loc; err.raisedAt = tokPos; - throw err; - } - - // Reused empty array added for node fields that are always empty. - - var empty = []; - - // ## Token types - - // The assignment of fine-grained, information-carrying type objects - // allows the tokenizer to store the information it has about a - // token in a way that is very cheap for the parser to look up. - - // All token type variables start with an underscore, to make them - // easy to recognize. - - // These are the general types. The `type` property is only used to - // make them recognizeable when debugging. - - var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"}; - var _name = {type: "name"}, _eof = {type: "eof"}; - - // Keyword tokens. The `keyword` property (also used in keyword-like - // operators) indicates that the token originated from an - // identifier-like word, which is used when parsing property names. - // - // The `beforeExpr` property is used to disambiguate between regular - // expressions and divisions. It is set on all token types that can - // be followed by an expression (thus, a slash after them would be a - // regular expression). - // - // `isLoop` marks a keyword as starting a loop, which is important - // to know when parsing a label, in order to allow or disallow - // continue jumps to that label. - - var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"}; - var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"}; - var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true}; - var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"}; - var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"}; - var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; - var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; - var _this = {keyword: "this"}; - - // The keywords that denote values. - - var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true}; - var _false = {keyword: "false", atomValue: false}; - - // Some keywords are treated as regular operators. `in` sometimes - // (when parsing `for`) needs to be tested against specifically, so - // we assign a variable name to it for quick comparing. - - var _in = {keyword: "in", binop: 7, beforeExpr: true}; - - // Map keyword names to token types. - - var keywordTypes = {"break": _break, "case": _case, "catch": _catch, - "continue": _continue, "debugger": _debugger, "default": _default, - "do": _do, "else": _else, "finally": _finally, "for": _for, - "function": _function, "if": _if, "return": _return, "switch": _switch, - "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with, - "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, - "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, - "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, - "void": {keyword: "void", prefix: true, beforeExpr: true}, - "delete": {keyword: "delete", prefix: true, beforeExpr: true}}; - - // Punctuation token types. Again, the `type` property is purely for debugging. - - var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true}; - var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"}; - var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; - var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true}; - - // Operators. These carry several kinds of properties to help the - // parser use them properly (the presence of these properties is - // what categorizes them as operators). - // - // `binop`, when present, specifies that this operator is a binary - // operator, and will refer to its precedence. - // - // `prefix` and `postfix` mark the operator as a prefix or postfix - // unary operator. `isUpdate` specifies that the node produced by - // the operator should be of type UpdateExpression rather than - // simply UnaryExpression (`++` and `--`). - // - // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as - // binary operators with a very low precedence, that should result - // in AssignmentExpression nodes. - - var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true}; - var _assign = {isAssign: true, beforeExpr: true}; - var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true}; - var _logicalOR = {binop: 1, beforeExpr: true}; - var _logicalAND = {binop: 2, beforeExpr: true}; - var _bitwiseOR = {binop: 3, beforeExpr: true}; - var _bitwiseXOR = {binop: 4, beforeExpr: true}; - var _bitwiseAND = {binop: 5, beforeExpr: true}; - var _equality = {binop: 6, beforeExpr: true}; - var _relational = {binop: 7, beforeExpr: true}; - var _bitShift = {binop: 8, beforeExpr: true}; - var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; - var _multiplyModulo = {binop: 10, beforeExpr: true}; - - // Provide access to the token types for external users of the - // tokenizer. - - exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR, - parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, - dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof, - num: _num, regexp: _regexp, string: _string}; - for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; - - // This is a trick taken from Esprima. It turns out that, on - // non-Chrome browsers, to check whether a string is in a set, a - // predicate containing a big ugly `switch` statement is faster than - // a regular expression, and on Chrome the two are about on par. - // This function uses `eval` (non-lexical) to produce such a - // predicate from a space-separated string of words. - // - // It starts by sorting the words by length. - - function makePredicate(words) { - words = words.split(" "); - var f = "", cats = []; - out: for (var i = 0; i < words.length; ++i) { - for (var j = 0; j < cats.length; ++j) - if (cats[j][0].length == words[i].length) { - cats[j].push(words[i]); - continue out; - } - cats.push([words[i]]); - } - function compareTo(arr) { - if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; - f += "switch(str){"; - for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; - f += "return true}return false;"; - } - - // When there are more than three length categories, an outer - // switch first dispatches on the lengths, to save on comparisons. - - if (cats.length > 3) { - cats.sort(function(a, b) {return b.length - a.length;}); - f += "switch(str.length){"; - for (var i = 0; i < cats.length; ++i) { - var cat = cats[i]; - f += "case " + cat[0].length + ":"; - compareTo(cat); - } - f += "}"; - - // Otherwise, simply generate a flat `switch` statement. - - } else { - compareTo(words); - } - return new Function("str", f); - } - - // The ECMAScript 3 reserved word list. - - var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"); - - // ECMAScript 5 reserved words. - - var isReservedWord5 = makePredicate("class enum extends super const export import"); - - // The additional reserved words in strict mode. - - var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield"); - - // The forbidden variable names in strict mode. - - var isStrictBadIdWord = makePredicate("eval arguments"); - - // And the keywords. - - var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"); - - // ## Character categories - - // Big ugly regular expressions that match characters in the - // whitespace, identifier, and identifier-start categories. These - // are only applied when a character is found to actually have a - // code point above 128. - - var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; - var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; - var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; - var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); - var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - - // Whether a single character denotes a newline. - - var newline = /[\n\r\u2028\u2029]/; - - // Matches a whole line break (where CRLF is considered a single - // line break). Used to count lines. - - var lineBreak = /\r\n|[\n\r\u2028\u2029]/g; - - // Test whether a given character code starts an identifier. - - var isIdentifierStart = exports.isIdentifierStart = function(code) { - if (code < 65) return code === 36; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123)return true; - return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - }; - - // Test whether a given character is part of an identifier. - - var isIdentifierChar = exports.isIdentifierChar = function(code) { - if (code < 48) return code === 36; - if (code < 58) return true; - if (code < 65) return false; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123)return true; - return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - }; - - // ## Tokenizer - - // These are used when `options.locations` is on, for the - // `tokStartLoc` and `tokEndLoc` properties. - - function line_loc_t() { - this.line = tokCurLine; - this.column = tokPos - tokLineStart; - } - - // Reset the token state. Used at the start of a parse. - - function initTokenState() { - tokCurLine = 1; - tokPos = tokLineStart = 0; - tokRegexpAllowed = true; - skipSpace(); - } - - // Called at the end of every token. Sets `tokEnd`, `tokVal`, and - // `tokRegexpAllowed`, and skips the space after the token, so that - // the next one's `tokStart` will point at the right position. - - function finishToken(type, val) { - tokEnd = tokPos; - if (options.locations) tokEndLoc = new line_loc_t; - tokType = type; - skipSpace(); - tokVal = val; - tokRegexpAllowed = type.beforeExpr; - } - - function skipBlockComment() { - var startLoc = options.onComment && options.locations && new line_loc_t; - var start = tokPos, end = input.indexOf("*/", tokPos += 2); - if (end === -1) raise(tokPos - 2, "Unterminated comment"); - tokPos = end + 2; - if (options.locations) { - lineBreak.lastIndex = start; - var match; - while ((match = lineBreak.exec(input)) && match.index < tokPos) { - ++tokCurLine; - tokLineStart = match.index + match[0].length; - } - } - if (options.onComment) - options.onComment(true, input.slice(start + 2, end), start, tokPos, - startLoc, options.locations && new line_loc_t); - } - - function skipLineComment() { - var start = tokPos; - var startLoc = options.onComment && options.locations && new line_loc_t; - var ch = input.charCodeAt(tokPos+=2); - while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { - ++tokPos; - ch = input.charCodeAt(tokPos); - } - if (options.onComment) - options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, - startLoc, options.locations && new line_loc_t); - } - - // Called at the start of the parse and after every token. Skips - // whitespace and comments, and. - - function skipSpace() { - while (tokPos < inputLen) { - var ch = input.charCodeAt(tokPos); - if (ch === 32) { // ' ' - ++tokPos; - } else if (ch === 13) { - ++tokPos; - var next = input.charCodeAt(tokPos); - if (next === 10) { - ++tokPos; - } - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else if (ch === 10 || ch === 8232 || ch === 8233) { - ++tokPos; - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } else if (ch > 8 && ch < 14) { - ++tokPos; - } else if (ch === 47) { // '/' - var next = input.charCodeAt(tokPos + 1); - if (next === 42) { // '*' - skipBlockComment(); - } else if (next === 47) { // '/' - skipLineComment(); - } else break; - } else if (ch === 160) { // '\xa0' - ++tokPos; - } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++tokPos; - } else { - break; - } - } - } - - // ### Token reading - - // This is the function that is called to fetch the next token. It - // is somewhat obscure, because it works in character codes rather - // than characters, and because operator parsing has been inlined - // into it. - // - // All in the name of speed. - // - // The `forceRegexp` parameter is used in the one case where the - // `tokRegexpAllowed` trick does not work. See `parseStatement`. - - function readToken_dot() { - var next = input.charCodeAt(tokPos + 1); - if (next >= 48 && next <= 57) return readNumber(true); - ++tokPos; - return finishToken(_dot); - } - - function readToken_slash() { // '/' - var next = input.charCodeAt(tokPos + 1); - if (tokRegexpAllowed) {++tokPos; return readRegexp();} - if (next === 61) return finishOp(_assign, 2); - return finishOp(_slash, 1); - } - - function readToken_mult_modulo() { // '%*' - var next = input.charCodeAt(tokPos + 1); - if (next === 61) return finishOp(_assign, 2); - return finishOp(_multiplyModulo, 1); - } - - function readToken_pipe_amp(code) { // '|&' - var next = input.charCodeAt(tokPos + 1); - if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2); - if (next === 61) return finishOp(_assign, 2); - return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1); - } - - function readToken_caret() { // '^' - var next = input.charCodeAt(tokPos + 1); - if (next === 61) return finishOp(_assign, 2); - return finishOp(_bitwiseXOR, 1); - } - - function readToken_plus_min(code) { // '+-' - var next = input.charCodeAt(tokPos + 1); - if (next === code) { - if (next == 45 && input.charCodeAt(tokPos + 2) == 62 && - newline.test(input.slice(lastEnd, tokPos))) { - // A `-->` line comment - tokPos += 3; - skipLineComment(); - skipSpace(); - return readToken(); - } - return finishOp(_incDec, 2); - } - if (next === 61) return finishOp(_assign, 2); - return finishOp(_plusMin, 1); - } - - function readToken_lt_gt(code) { // '<>' - var next = input.charCodeAt(tokPos + 1); - var size = 1; - if (next === code) { - size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; - if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); - return finishOp(_bitShift, size); - } - if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && - input.charCodeAt(tokPos + 3) == 45) { - // `", lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("scrollVerticallyAndHorizontally", function(cm) { - cm.setSize(100, 100); - addDoc(cm, 40, 40); - cm.setCursor(39); - var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0]; - is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one"); - var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect(); - var editorBox = wrap.getBoundingClientRect(); - is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight, - "bottom line visible"); -}, {lineNumbers: true}); - -testCM("moveVstuck", function(cm) { - var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight; - var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n"; - cm.setValue(val); - for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) { - cm.setSize(w); - if (lines.offsetHeight <= 3.5 * h0) break; - } - cm.setCursor(Pos(0, val.length - 1)); - cm.moveV(-1, "line"); - eqPos(cm.getCursor(), Pos(0, 26)); -}, {lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("collapseOnMove", function(cm) { - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goLineUp"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goPageDown"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(2, 4)); - cm.execCommand("goLineUp"); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goCharLeft"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(0, 1)); -}, {value: "aaaaa\nb\nccccc"}); - -testCM("clickTab", function(cm) { - var p0 = cm.charCoords(Pos(0, 0)); - eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0)); - eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1)); -}, {value: "\t\n\n", lineWrapping: true, tabSize: 8}); - -testCM("verticalScroll", function(cm) { - cm.setSize(100, 200); - cm.setValue("foo\nbar\nbaz\n"); - var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth; - cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0)); - is(sc.scrollWidth > baseWidth, "scrollbar present"); - cm.replaceRange("foo", Pos(0, 0), Pos(0)); - if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone"); - cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0)); - cm.replaceRange("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh", Pos(1, 0), Pos(1)); - is(sc.scrollWidth > baseWidth, "present again"); - var curWidth = sc.scrollWidth; - cm.replaceRange("foo", Pos(0, 0), Pos(0)); - is(sc.scrollWidth < curWidth, "scrollbar smaller"); - is(sc.scrollWidth > baseWidth, "but still present"); -}); - -testCM("extraKeys", function(cm) { - var outcome; - function fakeKey(expected, code, props) { - if (typeof code == "string") code = code.charCodeAt(0); - var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}}; - if (props) for (var n in props) e[n] = props[n]; - outcome = null; - cm.triggerOnKeyDown(e); - eq(outcome, expected); - } - CodeMirror.commands.testCommand = function() {outcome = "tc";}; - CodeMirror.commands.goTestCommand = function() {outcome = "gtc";}; - cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";}, - "X": function() {outcome = "x";}, - "Ctrl-Alt-U": function() {outcome = "cau";}, - "End": "testCommand", - "Home": "goTestCommand", - "Tab": false}); - fakeKey(null, "U"); - fakeKey("cau", "U", {ctrlKey: true, altKey: true}); - fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true}); - fakeKey("x", "X"); - fakeKey("sx", "X", {shiftKey: true}); - fakeKey("tc", 35); - fakeKey(null, 35, {shiftKey: true}); - fakeKey("gtc", 36); - fakeKey("gtc", 36, {shiftKey: true}); - fakeKey(null, 9); -}, null, window.opera && mac); - -testCM("wordMovementCommands", function(cm) { - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 12)); - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 9)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 24)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(1, 9)); - cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(1, 13)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(2, 0)); -}, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"}); - -testCM("groupMovementCommands", function(cm) { - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 10)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 15)); - cm.setCursor(Pos(0, 17)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 16)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 14)); - cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 20)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 2)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 5)); - cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 20)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 16)); -}, {value: "booo ba---quux. ffff\n abc d"}); - -testCM("groupsAndWhitespace", function(cm) { - var positions = [Pos(0, 0), Pos(0, 2), Pos(0, 5), Pos(0, 9), Pos(0, 11), - Pos(1, 0), Pos(1, 2), Pos(1, 5)]; - for (var i = 1; i < positions.length; i++) { - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), positions[i]); - } - for (var i = positions.length - 2; i >= 0; i--) { - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), i == 2 ? Pos(0, 6) : positions[i]); - } -}, {value: " foo +++ \n bar"}); - -testCM("charMovementCommands", function(cm) { - cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goCharRight"); cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.setCursor(Pos(1, 0)); - cm.execCommand("goColumnLeft"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goColumnRight"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(1, 5)); - cm.execCommand("goLineStartSmart"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineStartSmart"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.setCursor(Pos(2, 0)); - cm.execCommand("goCharRight"); cm.execCommand("goColumnRight"); - eqPos(cm.getCursor(), Pos(2, 0)); -}, {value: "line1\n ine2\n"}); - -testCM("verticalMovementCommands", function(cm) { - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goLineDown"); - if (!phantom) // This fails in PhantomJS, though not in a real Webkit - eqPos(cm.getCursor(), Pos(1, 0)); - cm.setCursor(Pos(1, 12)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 5)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(3, 0)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(2, 5)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 12)); - cm.execCommand("goPageDown"); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.execCommand("goPageDown"); cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.execCommand("goPageUp"); - eqPos(cm.getCursor(), Pos(0, 0)); -}, {value: "line1\nlong long line2\nline3\n\nline5\n"}); - -testCM("verticalMovementCommandsWrapping", function(cm) { - cm.setSize(120); - cm.setCursor(Pos(0, 5)); - cm.execCommand("goLineDown"); - eq(cm.getCursor().line, 0); - is(cm.getCursor().ch > 5, "moved beyond wrap"); - for (var i = 0; ; ++i) { - is(i < 20, "no endless loop"); - cm.execCommand("goLineDown"); - var cur = cm.getCursor(); - if (cur.line == 1) eq(cur.ch, 5); - if (cur.line == 2) { eq(cur.ch, 1); break; } - } -}, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk", - lineWrapping: true}); - -testCM("rtlMovement", function(cm) { - forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج", - "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق", - ""], function(line) { - var inv = line.charAt(0) == "خ"; - cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart"); - var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0]; - var cursor = cursors.firstChild; - var prevX = cursor.offsetLeft, prevY = cursor.offsetTop; - for (var i = 0; i <= line.length; ++i) { - cm.execCommand("goCharRight"); - cursor = cursors.firstChild; - if (i == line.length) is(cursor.offsetTop > prevY, "next line"); - else is(cursor.offsetLeft > prevX, "moved right"); - prevX = cursor.offsetLeft; prevY = cursor.offsetTop; - } - cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd"); - prevX = cursors.firstChild.offsetLeft; - for (var i = 0; i < line.length; ++i) { - cm.execCommand("goCharLeft"); - cursor = cursors.firstChild; - is(cursor.offsetLeft < prevX, "moved left"); - prevX = cursor.offsetLeft; - } - }); -}, null, ie_lt9); - -// Verify that updating a line clears its bidi ordering -testCM("bidiUpdate", function(cm) { - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("خحج", "start"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 4)); -}, {value: "abcd\n"}); - -testCM("movebyTextUnit", function(cm) { - cm.setValue("בְּרֵאשִ\nééé́\n"); - cm.execCommand("goLineEnd"); - for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goCharRight"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 4)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 7)); -}); - -testCM("lineChangeEvents", function(cm) { - addDoc(cm, 3, 5); - var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"]; - for (var i = 0; i < 5; ++i) { - CodeMirror.on(cm.getLineHandle(i), "delete", function(i) { - return function() {log.push("del " + i);}; - }(i)); - CodeMirror.on(cm.getLineHandle(i), "change", function(i) { - return function() {log.push("ch " + i);}; - }(i)); - } - cm.replaceRange("x", Pos(0, 1)); - cm.replaceRange("xy", Pos(1, 1), Pos(2)); - cm.replaceRange("foo\nbar", Pos(0, 1)); - cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount())); - eq(log.length, want.length, "same length"); - for (var i = 0; i < log.length; ++i) - eq(log[i], want[i]); -}); - -testCM("scrollEntirelyToRight", function(cm) { - if (phantom) return; - addDoc(cm, 500, 2); - cm.setCursor(Pos(0, 500)); - var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0]; - is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left); -}); - -testCM("lineWidgets", function(cm) { - addDoc(cm, 500, 3); - var last = cm.charCoords(Pos(2, 0)); - var node = document.createElement("div"); - node.innerHTML = "hi"; - var widget = cm.addLineWidget(1, node); - is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space"); - cm.setCursor(Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); -}); - -testCM("lineWidgetFocus", function(cm) { - var place = document.getElementById("testground"); - place.className = "offscreen"; - try { - addDoc(cm, 500, 10); - var node = document.createElement("input"); - var widget = cm.addLineWidget(1, node); - node.focus(); - eq(document.activeElement, node); - cm.replaceRange("new stuff", Pos(1, 0)); - eq(document.activeElement, node); - } finally { - place.className = ""; - } -}); - -testCM("lineWidgetCautiousRedraw", function(cm) { - var node = document.createElement("div"); - node.innerHTML = "hahah"; - var w = cm.addLineWidget(0, node); - var redrawn = false; - w.on("redraw", function() { redrawn = true; }); - cm.replaceSelection("0"); - is(!redrawn); -}, {value: "123\n456"}); - - -var knownScrollbarWidth; -function scrollbarWidth(measure) { - if (knownScrollbarWidth != null) return knownScrollbarWidth; - var div = document.createElement('div'); - div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll"; - document.body.appendChild(div); - knownScrollbarWidth = div.offsetHeight - div.clientHeight; - document.body.removeChild(div); - return knownScrollbarWidth || 0; -} - -testCM("lineWidgetChanged", function(cm) { - addDoc(cm, 2, 300); - var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2; - cm.setOption('lineNumbers', true); - cm.setSize(600, cm.defaultTextHeight() * 50); - cm.scrollTo(null, cm.heightAtLine(125, "local")); - - var expectedWidgetHeight = 60; - var expectedLinesInWidget = 3; - function w() { - var node = document.createElement("div"); - // we use these children with just under half width of the line to check measurements are made with correct width - // when placed in the measure div. - // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test. - // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test. - // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right. - // It may also be worthwhile to check this for non-coverGutter widgets. - // Visually: - // Good: - // | ------------- display width ------------- | - // | ------- widget-width when measured ------ | - // | | -- under-half -- | | -- under-half -- | | - // | | --- over-half --- | | - // | | --- over-half --- | | - // Height: measured as 3 lines, same as it will be when actually displayed - - // Bad (too narrow): - // | ------------- display width ------------- | - // | ------ widget-width when measured ----- | < -- uh oh - // | | -- under-half -- | | - // | | -- under-half -- | | < -- when measured, shoved to next line - // | | --- over-half --- | | - // | | --- over-half --- | | - // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines! - - // Bad (too wide): - // | ------------- display width ------------- | - // | -------- widget-width when measured ------- | < -- uh oh - // | | -- under-half -- | | -- under-half -- | | - // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line - // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines! - - var barelyUnderHalfWidthHtml = '
      '; - var barelyOverHalfWidthHtml = '
      '; - node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml); - node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;"; - return node; - } - var info0 = cm.getScrollInfo(); - var w0 = cm.addLineWidget(0, w(), { coverGutter: true }); - var w150 = cm.addLineWidget(150, w(), { coverGutter: true }); - var w300 = cm.addLineWidget(300, w(), { coverGutter: true }); - var info1 = cm.getScrollInfo(); - eq(info0.height + (3 * expectedWidgetHeight), info1.height); - eq(info0.top + expectedWidgetHeight, info1.top); - expectedWidgetHeight = 12; - w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px"; - w0.changed(); w150.changed(); w300.changed(); - var info2 = cm.getScrollInfo(); - eq(info0.height + (3 * expectedWidgetHeight), info2.height); - eq(info0.top + expectedWidgetHeight, info2.top); -}); - -testCM("getLineNumber", function(cm) { - addDoc(cm, 2, 20); - var h1 = cm.getLineHandle(1); - eq(cm.getLineNumber(h1), 1); - cm.replaceRange("hi\nbye\n", Pos(0, 0)); - eq(cm.getLineNumber(h1), 3); - cm.setValue(""); - eq(cm.getLineNumber(h1), null); -}); - -testCM("jumpTheGap", function(cm) { - if (phantom) return; - var longLine = "abcdef ghiklmnop qrstuvw xyz "; - longLine += longLine; longLine += longLine; longLine += longLine; - cm.replaceRange(longLine, Pos(2, 0), Pos(2)); - cm.setSize("200px", null); - cm.getWrapperElement().style.lineHeight = 2; - cm.refresh(); - cm.setCursor(Pos(0, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineDown"); - eq(cm.getCursor().line, 2); - is(cm.getCursor().ch > 1); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); - var node = document.createElement("div"); - node.innerHTML = "hi"; node.style.height = "30px"; - cm.addLineWidget(0, node); - cm.addLineWidget(1, node.cloneNode(true), {above: true}); - cm.setCursor(Pos(0, 2)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(1, 2)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 2)); -}, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"}); - -testCM("addLineClass", function(cm) { - function cls(line, text, bg, wrap, gutter) { - var i = cm.lineInfo(line); - eq(i.textClass, text); - eq(i.bgClass, bg); - eq(i.wrapClass, wrap); - if (typeof i.handle.gutterClass !== 'undefined') { - eq(i.handle.gutterClass, gutter); - } - } - cm.addLineClass(0, "text", "foo"); - cm.addLineClass(0, "text", "bar"); - cm.addLineClass(1, "background", "baz"); - cm.addLineClass(1, "wrap", "foo"); - cm.addLineClass(1, "gutter", "gutter-class"); - cls(0, "foo bar", null, null, null); - cls(1, null, "baz", "foo", "gutter-class"); - var lines = cm.display.lineDiv; - eq(byClassName(lines, "foo").length, 2); - eq(byClassName(lines, "bar").length, 1); - eq(byClassName(lines, "baz").length, 1); - eq(byClassName(lines, "gutter-class").length, 1); - cm.removeLineClass(0, "text", "foo"); - cls(0, "bar", null, null, null); - cm.removeLineClass(0, "text", "foo"); - cls(0, "bar", null, null, null); - cm.removeLineClass(0, "text", "bar"); - cls(0, null, null, null); - - cm.addLineClass(1, "wrap", "quux"); - cls(1, null, "baz", "foo quux", "gutter-class"); - cm.removeLineClass(1, "wrap"); - cls(1, null, "baz", null, "gutter-class"); - cm.removeLineClass(1, "gutter", "gutter-class"); - eq(byClassName(lines, "gutter-class").length, 0); - cls(1, null, "baz", null, null); - - cm.addLineClass(1, "gutter", "gutter-class"); - cls(1, null, "baz", null, "gutter-class"); - cm.removeLineClass(1, "gutter", "gutter-class"); - cls(1, null, "baz", null, null); - -}, {value: "hohoho\n", lineNumbers: true}); - -testCM("atomicMarker", function(cm) { - addDoc(cm, 10, 10); - function atom(ll, cl, lr, cr, li, ri) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), - {atomic: true, inclusiveLeft: li, inclusiveRight: ri}); - } - var m = atom(0, 1, 0, 5); - cm.setCursor(Pos(0, 1)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 1)); - m.clear(); - m = atom(0, 0, 0, 5, true); - eqPos(cm.getCursor(), Pos(0, 5), "pushed out"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - m.clear(); - m = atom(8, 4, 9, 10, false, true); - cm.setCursor(Pos(9, 8)); - eqPos(cm.getCursor(), Pos(8, 4), "set"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(8, 4), "char right"); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(8, 4), "line down"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(8, 3)); - m.clear(); - m = atom(1, 1, 3, 8); - cm.setCursor(Pos(0, 0)); - cm.setCursor(Pos(2, 0)); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("delCharBefore"); - eq(cm.getValue().length, 80, "del chunk"); - m = atom(3, 0, 5, 5); - cm.setCursor(Pos(3, 0)); - cm.execCommand("delWordAfter"); - eq(cm.getValue().length, 53, "del chunk"); -}); - -testCM("selectionBias", function(cm) { - cm.markText(Pos(0, 1), Pos(0, 3), {atomic: true}); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 3)); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 2), null, {bias: -1}); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 4)); - cm.setCursor(Pos(0, 2), null, {bias: 1}); - eqPos(cm.getCursor(), Pos(0, 3)); -}, {value: "12345"}); - -testCM("selectionHomeEnd", function(cm) { - cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true}); - cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true}); - cm.setCursor(Pos(1, 2)); - cm.execCommand("goLineStart"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(1, 3)); -}, {value: "ab\ncdef\ngh"}); - -testCM("readOnlyMarker", function(cm) { - function mark(ll, cl, lr, cr, at) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), - {readOnly: true, atomic: at}); - } - var m = mark(0, 1, 0, 4); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi", "end"); - eqPos(cm.getCursor(), Pos(0, 2)); - eq(cm.getLine(0), "abcde"); - cm.execCommand("selectAll"); - cm.replaceSelection("oops", "around"); - eq(cm.getValue(), "oopsbcd"); - cm.undo(); - eqPos(m.find().from, Pos(0, 1)); - eqPos(m.find().to, Pos(0, 4)); - m.clear(); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi", "around"); - eq(cm.getLine(0), "abhicde"); - eqPos(cm.getCursor(), Pos(0, 4)); - m = mark(0, 2, 2, 2, true); - cm.setSelection(Pos(1, 1), Pos(2, 4)); - cm.replaceSelection("t", "end"); - eqPos(cm.getCursor(), Pos(2, 3)); - eq(cm.getLine(2), "klto"); - cm.execCommand("goCharLeft"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.setSelection(Pos(0, 1), Pos(0, 3)); - cm.replaceSelection("xx", "around"); - eqPos(cm.getCursor(), Pos(0, 3)); - eq(cm.getLine(0), "axxhicde"); -}, {value: "abcde\nfghij\nklmno\n"}); - -testCM("dirtyBit", function(cm) { - eq(cm.isClean(), true); - cm.replaceSelection("boo", null, "test"); - eq(cm.isClean(), false); - cm.undo(); - eq(cm.isClean(), true); - cm.replaceSelection("boo", null, "test"); - cm.replaceSelection("baz", null, "test"); - cm.undo(); - eq(cm.isClean(), false); - cm.markClean(); - eq(cm.isClean(), true); - cm.undo(); - eq(cm.isClean(), false); - cm.redo(); - eq(cm.isClean(), true); -}); - -testCM("changeGeneration", function(cm) { - cm.replaceSelection("x"); - var softGen = cm.changeGeneration(); - cm.replaceSelection("x"); - cm.undo(); - eq(cm.getValue(), ""); - is(!cm.isClean(softGen)); - cm.replaceSelection("x"); - var hardGen = cm.changeGeneration(true); - cm.replaceSelection("x"); - cm.undo(); - eq(cm.getValue(), "x"); - is(cm.isClean(hardGen)); -}); - -testCM("addKeyMap", function(cm) { - function sendKey(code) { - cm.triggerOnKeyDown({type: "keydown", keyCode: code, - preventDefault: function(){}, stopPropagation: function(){}}); - } - - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 1)); - var test = 0; - var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }} - cm.addKeyMap(map1); - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 1)); - eq(test, 1); - cm.addKeyMap(map2, true); - sendKey(39); - eq(test, 2); - cm.removeKeyMap(map1); - sendKey(39); - eq(test, 12); - cm.removeKeyMap(map2); - sendKey(39); - eq(test, 12); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"}); - sendKey(39); - eq(test, 55); - cm.removeKeyMap("mymap"); - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 3)); -}, {value: "abc"}); - -testCM("findPosH", function(cm) { - forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1}, - {from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true}, - {from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"}, - {from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"}, - {from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true}, - {from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"}, - {from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"}, - {from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"}, - {from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"}, - {from: Pos(1, 15), to: Pos(1, 10), by: -5}, - {from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"}, - {from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true}, - {from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true}, - {from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) { - var r = cm.findPosH(t.from, t.by, t.unit || "char"); - eqPos(r, t.to); - eq(!!r.hitSide, !!t.hitSide); - }); -}, {value: "line one\nline two.something.other\n"}); - -testCM("beforeChange", function(cm) { - cm.on("beforeChange", function(cm, change) { - var text = []; - for (var i = 0; i < change.text.length; ++i) - text.push(change.text[i].replace(/\s/g, "_")); - change.update(null, null, text); - }); - cm.setValue("hello, i am a\nnew document\n"); - eq(cm.getValue(), "hello,_i_am_a\nnew_document\n"); - CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) { - if (change.from.line == 0) change.cancel(); - }); - cm.setValue("oops"); // Canceled - eq(cm.getValue(), "hello,_i_am_a\nnew_document\n"); - cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0)); - eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey"); -}, {value: "abcdefghijk"}); - -testCM("beforeChangeUndo", function(cm) { - cm.replaceRange("hi", Pos(0, 0), Pos(0)); - cm.replaceRange("bye", Pos(0, 0), Pos(0)); - eq(cm.historySize().undo, 2); - cm.on("beforeChange", function(cm, change) { - is(!change.update); - change.cancel(); - }); - cm.undo(); - eq(cm.historySize().undo, 0); - eq(cm.getValue(), "bye\ntwo"); -}, {value: "one\ntwo"}); - -testCM("beforeSelectionChange", function(cm) { - function notAtEnd(cm, pos) { - var len = cm.getLine(pos.line).length; - if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1); - return pos; - } - cm.on("beforeSelectionChange", function(cm, obj) { - obj.update([{anchor: notAtEnd(cm, obj.ranges[0].anchor), - head: notAtEnd(cm, obj.ranges[0].head)}]); - }); - - addDoc(cm, 10, 10); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(0, 9)); - cm.execCommand("selectAll"); - eqPos(cm.getCursor("start"), Pos(0, 0)); - eqPos(cm.getCursor("end"), Pos(9, 9)); -}); - -testCM("change_removedText", function(cm) { - cm.setValue("abc\ndef"); - - var removedText = []; - cm.on("change", function(cm, change) { - removedText.push(change.removed); - }); - - cm.operation(function() { - cm.replaceRange("xyz", Pos(0, 0), Pos(1,1)); - cm.replaceRange("123", Pos(0,0)); - }); - - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "abc\nd"); - eq(removedText[1].join("\n"), ""); - - var removedText = []; - cm.undo(); - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "123"); - eq(removedText[1].join("\n"), "xyz"); - - var removedText = []; - cm.redo(); - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "abc\nd"); - eq(removedText[1].join("\n"), ""); -}); - -testCM("lineStyleFromMode", function(cm) { - CodeMirror.defineMode("test_mode", function() { - return {token: function(stream) { - if (stream.match(/^\[[^\]]*\]/)) return " line-brackets "; - if (stream.match(/^\([^\)]*\)/)) return " line-background-parens "; - if (stream.match(/^<[^>]*>/)) return " span line-line line-background-bg "; - stream.match(/^\s+|^\S+/); - }}; - }); - cm.setOption("mode", "test_mode"); - var bracketElts = byClassName(cm.getWrapperElement(), "brackets"); - eq(bracketElts.length, 1, "brackets count"); - eq(bracketElts[0].nodeName, "PRE"); - is(!/brackets.*brackets/.test(bracketElts[0].className)); - var parenElts = byClassName(cm.getWrapperElement(), "parens"); - eq(parenElts.length, 1, "parens count"); - eq(parenElts[0].nodeName, "DIV"); - is(!/parens.*parens/.test(parenElts[0].className)); - eq(parenElts[0].parentElement.nodeName, "DIV"); - - eq(byClassName(cm.getWrapperElement(), "bg").length, 1); - eq(byClassName(cm.getWrapperElement(), "line").length, 1); - var spanElts = byClassName(cm.getWrapperElement(), "cm-span"); - eq(spanElts.length, 2); - is(/^\s*cm-span\s*$/.test(spanElts[0].className)); -}, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: "}); - -testCM("lineStyleFromBlankLine", function(cm) { - CodeMirror.defineMode("lineStyleFromBlankLine_mode", function() { - return {token: function(stream) { stream.skipToEnd(); return "comment"; }, - blankLine: function() { return "line-blank"; }}; - }); - cm.setOption("mode", "lineStyleFromBlankLine_mode"); - var blankElts = byClassName(cm.getWrapperElement(), "blank"); - eq(blankElts.length, 1); - eq(blankElts[0].nodeName, "PRE"); - cm.replaceRange("x", Pos(1, 0)); - blankElts = byClassName(cm.getWrapperElement(), "blank"); - eq(blankElts.length, 0); -}, {value: "foo\n\nbar"}); - -CodeMirror.registerHelper("xxx", "a", "A"); -CodeMirror.registerHelper("xxx", "b", "B"); -CodeMirror.defineMode("yyy", function() { - return { - token: function(stream) { stream.skipToEnd(); }, - xxx: ["a", "b", "q"] - }; -}); -CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C"); - -testCM("helpers", function(cm) { - cm.setOption("mode", "yyy"); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B"); - cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}}); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C"); - cm.setOption("mode", "javascript"); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), ""); -}); - -testCM("selectionHistory", function(cm) { - for (var i = 0; i < 3; i++) { - cm.setExtending(true); - cm.execCommand("goCharRight"); - cm.setExtending(false); - cm.execCommand("goCharRight"); - cm.execCommand("goCharRight"); - } - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "c"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "b"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "c"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 6)); -}, {value: "a b c d"}); - -testCM("selectionChangeReducesRedo", function(cm) { - cm.replaceSelection("X"); - cm.execCommand("goCharRight"); - cm.undoSelection(); - cm.execCommand("selectAll"); - cm.undoSelection(); - eq(cm.getValue(), "Xabc"); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.undoSelection(); - eq(cm.getValue(), "abc"); -}, {value: "abc"}); - -testCM("selectionHistoryNonOverlapping", function(cm) { - cm.setSelection(Pos(0, 0), Pos(0, 1)); - cm.setSelection(Pos(0, 2), Pos(0, 3)); - cm.execCommand("undoSelection"); - eqPos(cm.getCursor("anchor"), Pos(0, 0)); - eqPos(cm.getCursor("head"), Pos(0, 1)); -}, {value: "1234"}); - -testCM("cursorMotionSplitsHistory", function(cm) { - cm.replaceSelection("a"); - cm.execCommand("goCharRight"); - cm.replaceSelection("b"); - cm.replaceSelection("c"); - cm.undo(); - eq(cm.getValue(), "a1234"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.undo(); - eq(cm.getValue(), "1234"); - eqPos(cm.getCursor(), Pos(0, 0)); -}, {value: "1234"}); - -testCM("selChangeInOperationDoesNotSplit", function(cm) { - for (var i = 0; i < 4; i++) { - cm.operation(function() { - cm.replaceSelection("x"); - cm.setCursor(Pos(0, cm.getCursor().ch - 1)); - }); - } - eqPos(cm.getCursor(), Pos(0, 0)); - eq(cm.getValue(), "xxxxa"); - cm.undo(); - eq(cm.getValue(), "a"); -}, {value: "a"}); - -testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) { - cm.replaceSelection("U", null, "foo"); - cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "foo"}); - cm.undoSelection(); - eq(cm.getValue(), "a"); - cm.replaceSelection("V", null, "foo"); - cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "bar"}); - cm.undoSelection(); - eq(cm.getValue(), "Va"); -}, {value: "a"}); - -testCM("getTokenAt", function(cm) { - var tokPlus = cm.getTokenAt(Pos(0, 2)); - eq(tokPlus.type, "operator"); - eq(tokPlus.string, "+"); - var toks = cm.getLineTokens(0); - eq(toks.length, 3); - forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) { - eq(toks[i].type, expect[0]); - eq(toks[i].string, expect[1]); - }); -}, {value: "1+2", mode: "javascript"}); - -testCM("getTokenTypeAt", function(cm) { - eq(cm.getTokenTypeAt(Pos(0, 0)), "number"); - eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); - cm.addOverlay({ - token: function(stream) { - if (stream.match("foo")) return "foo"; - else stream.next(); - } - }); - eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1); - eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); -}, {value: "1 + 'foo'", mode: "javascript"}); - -testCM("resizeLineWidget", function(cm) { - addDoc(cm, 200, 3); - var widget = document.createElement("pre"); - widget.innerHTML = "imwidget"; - widget.style.background = "yellow"; - cm.addLineWidget(1, widget, {noHScroll: true}); - cm.setSize(40); - is(widget.parentNode.offsetWidth < 42); -}); - -testCM("combinedOperations", function(cm) { - var place = document.getElementById("testground"); - var other = CodeMirror(place, {value: "123"}); - try { - cm.operation(function() { - cm.addLineClass(0, "wrap", "foo"); - other.addLineClass(0, "wrap", "foo"); - }); - eq(byClassName(cm.getWrapperElement(), "foo").length, 1); - eq(byClassName(other.getWrapperElement(), "foo").length, 1); - cm.operation(function() { - cm.removeLineClass(0, "wrap", "foo"); - other.removeLineClass(0, "wrap", "foo"); - }); - eq(byClassName(cm.getWrapperElement(), "foo").length, 0); - eq(byClassName(other.getWrapperElement(), "foo").length, 0); - } finally { - place.removeChild(other.getWrapperElement()); - } -}, {value: "abc"}); - -testCM("eventOrder", function(cm) { - var seen = []; - cm.on("change", function() { - if (!seen.length) cm.replaceSelection("."); - seen.push("change"); - }); - cm.on("cursorActivity", function() { - cm.replaceSelection("!"); - seen.push("activity"); - }); - cm.replaceSelection("/"); - eq(seen.join(","), "change,change,activity,change"); -}); - -test("core_rmClass", function() { - var node = document.createElement("div"); - node.className = "foo-bar baz-quux yadda"; - CodeMirror.rmClass(node, "quux"); - eq(node.className, "foo-bar baz-quux yadda"); - CodeMirror.rmClass(node, "baz-quux"); - eq(node.className, "foo-bar yadda"); - CodeMirror.rmClass(node, "yadda"); - eq(node.className, "foo-bar"); - CodeMirror.rmClass(node, "foo-bar"); - eq(node.className, ""); - node.className = " foo "; - CodeMirror.rmClass(node, "foo"); - eq(node.className, ""); -}); - -test("core_addClass", function() { - var node = document.createElement("div"); - CodeMirror.addClass(node, "a"); - eq(node.className, "a"); - CodeMirror.addClass(node, "a"); - eq(node.className, "a"); - CodeMirror.addClass(node, "b"); - eq(node.className, "a b"); - CodeMirror.addClass(node, "a"); - CodeMirror.addClass(node, "b"); - eq(node.className, "a b"); -}); diff --git a/public/js/lib/codemirror/test/vim_test.js b/public/js/lib/codemirror/test/vim_test.js deleted file mode 100644 index 6262dab0c1..0000000000 --- a/public/js/lib/codemirror/test/vim_test.js +++ /dev/null @@ -1,3768 +0,0 @@ -CodeMirror.Vim.suppressErrorLogging = true; - -var code = '' + -' wOrd1 (#%\n' + -' word3] \n' + -'aopop pop 0 1 2 3 4\n' + -' (a) [b] {c} \n' + -'int getchar(void) {\n' + -' static char buf[BUFSIZ];\n' + -' static char *bufp = buf;\n' + -' if (n == 0) { /* buffer is empty */\n' + -' n = read(0, buf, sizeof buf);\n' + -' bufp = buf;\n' + -' }\n' + -'\n' + -' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + -' \n' + -'}\n'; - -var lines = (function() { - lineText = code.split('\n'); - var ret = []; - for (var i = 0; i < lineText.length; i++) { - ret[i] = { - line: i, - length: lineText[i].length, - lineText: lineText[i], - textStart: /^\s*/.exec(lineText[i])[0].length - }; - } - return ret; -})(); -var endOfDocument = makeCursor(lines.length - 1, - lines[lines.length - 1].length); -var wordLine = lines[0]; -var bigWordLine = lines[1]; -var charLine = lines[2]; -var bracesLine = lines[3]; -var seekBraceLine = lines[4]; - -var word1 = { - start: { line: wordLine.line, ch: 1 }, - end: { line: wordLine.line, ch: 5 } -}; -var word2 = { - start: { line: wordLine.line, ch: word1.end.ch + 2 }, - end: { line: wordLine.line, ch: word1.end.ch + 4 } -}; -var word3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 5 } -}; -var bigWord1 = word1; -var bigWord2 = word2; -var bigWord3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 7 } -}; -var bigWord4 = { - start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, - end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } -}; - -var oChars = [ { line: charLine.line, ch: 1 }, - { line: charLine.line, ch: 3 }, - { line: charLine.line, ch: 7 } ]; -var pChars = [ { line: charLine.line, ch: 2 }, - { line: charLine.line, ch: 4 }, - { line: charLine.line, ch: 6 }, - { line: charLine.line, ch: 8 } ]; -var numChars = [ { line: charLine.line, ch: 10 }, - { line: charLine.line, ch: 12 }, - { line: charLine.line, ch: 14 }, - { line: charLine.line, ch: 16 }, - { line: charLine.line, ch: 18 }]; -var parens1 = { - start: { line: bracesLine.line, ch: 1 }, - end: { line: bracesLine.line, ch: 3 } -}; -var squares1 = { - start: { line: bracesLine.line, ch: 5 }, - end: { line: bracesLine.line, ch: 7 } -}; -var curlys1 = { - start: { line: bracesLine.line, ch: 9 }, - end: { line: bracesLine.line, ch: 11 } -}; -var seekOutside = { - start: { line: seekBraceLine.line, ch: 1 }, - end: { line: seekBraceLine.line, ch: 16 } -}; -var seekInside = { - start: { line: seekBraceLine.line, ch: 14 }, - end: { line: seekBraceLine.line, ch: 11 } -}; - -function copyCursor(cur) { - return { ch: cur.ch, line: cur.line }; -} - -function forEach(arr, func) { - for (var i = 0; i < arr.length; i++) { - func(arr[i], i, arr); - } -} - -function testVim(name, run, opts, expectedFail) { - var vimOpts = { - lineNumbers: true, - vimMode: true, - showCursorWhenSelecting: true, - value: code - }; - for (var prop in opts) { - if (opts.hasOwnProperty(prop)) { - vimOpts[prop] = opts[prop]; - } - } - return test('vim_' + name, function() { - var place = document.getElementById("testground"); - var cm = CodeMirror(place, vimOpts); - var vim = CodeMirror.Vim.maybeInitVimState_(cm); - - function doKeysFn(cm) { - return function(args) { - if (args instanceof Array) { - arguments = args; - } - for (var i = 0; i < arguments.length; i++) { - CodeMirror.Vim.handleKey(cm, arguments[i]); - } - } - } - function doInsertModeKeysFn(cm) { - return function(args) { - if (args instanceof Array) { arguments = args; } - function executeHandler(handler) { - if (typeof handler == 'string') { - CodeMirror.commands[handler](cm); - } else { - handler(cm); - } - return true; - } - for (var i = 0; i < arguments.length; i++) { - var key = arguments[i]; - // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); - // Record for insert mode. - if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { - var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; - if (lastChange) { - lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); - } - } - } - } - } - function doExFn(cm) { - return function(command) { - cm.openDialog = helpers.fakeOpenDialog(command); - helpers.doKeys(':'); - } - } - function assertCursorAtFn(cm) { - return function(line, ch) { - var pos; - if (ch == null && typeof line.line == 'number') { - pos = line; - } else { - pos = makeCursor(line, ch); - } - eqPos(pos, cm.getCursor()); - } - } - function fakeOpenDialog(result) { - return function(text, callback) { - return callback(result); - } - } - function fakeOpenNotification(matcher) { - return function(text) { - matcher(text); - } - } - var helpers = { - doKeys: doKeysFn(cm), - // Warning: Only emulates keymap events, not character insertions. Use - // replaceRange to simulate character insertions. - // Keys are in CodeMirror format, NOT vim format. - doInsertModeKeys: doInsertModeKeysFn(cm), - doEx: doExFn(cm), - assertCursorAt: assertCursorAtFn(cm), - fakeOpenDialog: fakeOpenDialog, - fakeOpenNotification: fakeOpenNotification, - getRegisterController: function() { - return CodeMirror.Vim.getRegisterController(); - } - } - CodeMirror.Vim.resetVimGlobalState_(); - var successful = false; - var savedOpenNotification = cm.openNotification; - try { - run(cm, vim, helpers); - successful = true; - } finally { - cm.openNotification = savedOpenNotification; - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - place.removeChild(cm.getWrapperElement()); - } - } - }, expectedFail); -}; -testVim('qq@q', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); -}, { value: ' '}); -testVim('@@', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); - helpers.doKeys('@', '@'); - helpers.assertCursorAt(0,6); -}, { value: ' '}); -var jumplistScene = ''+ - 'word\n'+ - '(word)\n'+ - '{word\n'+ - 'word.\n'+ - '\n'+ - 'word search\n'+ - '}word\n'+ - 'word\n'+ - 'word\n'; -function testJumplist(name, keys, endPos, startPos, dialog) { - endPos = makeCursor(endPos[0], endPos[1]); - startPos = makeCursor(startPos[0], startPos[1]); - testVim(name, function(cm, vim, helpers) { - CodeMirror.Vim.resetVimGlobalState_(); - if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); - cm.setCursor(startPos); - helpers.doKeys.apply(null, keys); - helpers.assertCursorAt(endPos); - }, {value: jumplistScene}); -}; -testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); -testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); -testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); -testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); -testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); -testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); -testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); -testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); -testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); -testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); -testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); -testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); -testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); -testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); -testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); -testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); -testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); -testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [0,2], [0,2]); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [1,0], [0,2]); - -/** - * @param name Name of the test - * @param keys An array of keys or a string with a single key to simulate. - * @param endPos The expected end position of the cursor. - * @param startPos The position the cursor should start at, defaults to 0, 0. - */ -function testMotion(name, keys, endPos, startPos) { - testVim(name, function(cm, vim, helpers) { - if (!startPos) { - startPos = { line: 0, ch: 0 }; - } - cm.setCursor(startPos); - helpers.doKeys(keys); - helpers.assertCursorAt(endPos); - }); -}; - -function makeCursor(line, ch) { - return { line: line, ch: ch }; -}; - -function offsetCursor(cur, offsetLine, offsetCh) { - return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; -}; - -// Motion tests -testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); -testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); -testMotion('h', 'h', makeCursor(0, 0), word1.start); -testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); -testMotion('l', 'l', makeCursor(0, 1)); -testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); -testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); -testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); -testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); -testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); -testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('w', 'w', word1.start); -testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); -testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); -testMotion('w_repeat', ['2', 'w'], word2.start); -testMotion('w_wrap', ['w'], word3.start, word2.start); -testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); -testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); -testMotion('W', 'W', bigWord1.start); -testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); -testMotion('e', 'e', word1.end); -testMotion('e_repeat', ['2', 'e'], word2.end); -testMotion('e_wrap', 'e', word3.end, word2.end); -testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); -testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); -testMotion('b', 'b', word3.start, word3.end); -testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); -testMotion('b_wrap', 'b', word2.start, word3.start); -testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); -testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); -testMotion('ge', ['g', 'e'], word2.end, word3.end); -testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); -testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); -testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), - makeCursor(0, 0)); -testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); -testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), - makeCursor(3, 1)); -testMotion('gg_repeat', ['3', 'g', 'g'], - makeCursor(lines[2].line, lines[2].textStart)); -testMotion('G', 'G', - makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), - makeCursor(3, 1)); -testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, - lines[2].textStart)); -// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. -testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); -testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); -testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); -testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); -testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); -testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); -testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), - makeCursor(0, 3)); -testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); -testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); -testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); -testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), - makeCursor(charLine.line, 0)); -testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), - pChars[0]); -testMotion('F', ['F', 'p'], pChars[0], pChars[1]); -testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); -testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); -testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); -testMotion('%_parens', ['%'], parens1.end, parens1.start); -testMotion('%_squares', ['%'], squares1.end, squares1.start); -testMotion('%_braces', ['%'], curlys1.end, curlys1.start); -testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); -testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); -testVim('%_seek_skip', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,9); -}, {value:'01234"("()'}); -testVim('%_skip_string', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,4); - cm.setCursor(0,2); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(")")'}); -(')') -testVim('%_skip_comment', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,6); - cm.setCursor(0,3); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(/*)*/)'}); -// Make sure that moving down after going to the end of a line always leaves you -// at the end of a line, but preserves the offset in other cases -testVim('Changing lines after Eol operation', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['$']); - helpers.doKeys(['j']); - // After moving to Eol and then down, we should be at Eol of line 2 - helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); - helpers.doKeys(['j']); - // After moving down, we should be at Eol of line 3 - helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); - helpers.doKeys(['h']); - helpers.doKeys(['j']); - // After moving back one space and then down, since line 4 is shorter than line 2, we should - // be at Eol of line 2 - 1 - helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); - helpers.doKeys(['j']); - helpers.doKeys(['j']); - // After moving down again, since line 3 has enough characters, we should be back to the - // same place we were at on line 1 - helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); -}); -//making sure gj and gk recover from clipping -testVim('gj_gk_clipping', function(cm,vim,helpers){ - cm.setCursor(0, 1); - helpers.doKeys('g','j','g','j'); - helpers.assertCursorAt(2, 1); - helpers.doKeys('g','k','g','k'); - helpers.assertCursorAt(0, 1); -},{value: 'line 1\n\nline 2'}); -//testing a mix of j/k and gj/gk -testVim('j_k_and_gj_gk', function(cm,vim,helpers){ - cm.setSize(120); - cm.setCursor(0, 0); - //go to the last character on the first line - helpers.doKeys('$'); - //move up/down on the column within the wrapped line - //side-effect: cursor is not locked to eol anymore - helpers.doKeys('g','k'); - var cur=cm.getCursor(); - eq(cur.line,0); - is((cur.ch<176),'gk didn\'t move cursor back (1)'); - helpers.doKeys('g','j'); - helpers.assertCursorAt(0, 176); - //should move to character 177 on line 2 (j/k preserve character index within line) - helpers.doKeys('j'); - //due to different line wrapping, the cursor can be on a different screen-x now - //gj and gk preserve screen-x on movement, much like moveV - helpers.doKeys('3','g','k'); - cur=cm.getCursor(); - eq(cur.line,1); - is((cur.ch<176),'gk didn\'t move cursor back (2)'); - helpers.doKeys('g','j','2','g','j'); - //should return to the same character-index - helpers.doKeys('k'); - helpers.assertCursorAt(0, 176); -},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); -testVim('gj_gk', function(cm, vim, helpers) { - if (phantom) return; - cm.setSize(120); - // Test top of document edge case. - cm.setCursor(0, 4); - helpers.doKeys('g', 'j'); - helpers.doKeys('10', 'g', 'k'); - helpers.assertCursorAt(0, 4); - - // Test moving down preserves column position. - helpers.doKeys('g', 'j'); - var pos1 = cm.getCursor(); - var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; - helpers.doKeys('g', 'j'); - helpers.assertCursorAt(expectedPos2); - - // Move to the last character - cm.setCursor(0, 0); - // Move left to reset HSPos - helpers.doKeys('h'); - // Test bottom of document edge case. - helpers.doKeys('100', 'g', 'j'); - var endingPos = cm.getCursor(); - is(endingPos != 0, 'gj should not be on wrapped line 0'); - var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); - var endingCharCoords = cm.charCoords(endingPos); - is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); -},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); -testVim('}', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(1, 0); - cm.setCursor(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(4, 0); - cm.setCursor(0, 0); - helpers.doKeys('6', '}'); - helpers.assertCursorAt(5, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('{', function(cm, vim, helpers) { - cm.setCursor(5, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - cm.setCursor(5, 0); - helpers.doKeys('2', '{'); - helpers.assertCursorAt(1, 0); - cm.setCursor(5, 0); - helpers.doKeys('6', '{'); - helpers.assertCursorAt(0, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('paragraph motions', function(cm, vim, helpers) { - cm.setCursor(10, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(7, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(16, 0); - - cm.setCursor(9, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(6, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(7, 0); - - // ip inside empty space - cm.setCursor(10, 0); - helpers.doKeys('v', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(12, 0), cm.getCursor('head')); - helpers.doKeys('i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('2', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // should switch to visualLine mode - cm.setCursor(14, 0); - helpers.doKeys('', 'v', 'i', 'p'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(14, 0); - helpers.doKeys('', 'V', 'i', 'p'); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // ap inside empty space - cm.setCursor(10, 0); - helpers.doKeys('', 'v', 'a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(13, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(13, 0), cm.getCursor('anchor')); - eqPos(Pos(14, 0), cm.getCursor('head')); - - cm.setCursor(16, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(14, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(0, 0), cm.getCursor('anchor')); - eqPos(Pos(4, 0), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('d', 'i', 'p'); - var register = helpers.getRegisterController().getRegister(); - eq('a\na\n', register.toString()); - is(register.linewise); - helpers.doKeys('3', 'j', 'p'); - helpers.doKeys('y', 'i', 'p'); - is(register.linewise); - eq('b\na\na\nc\n', register.toString()); -}, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' }); - -// Operator tests -testVim('dl', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'l'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dl_eol', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('d', 'l'); - eq(' word1', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 6); -}, { value: ' word1 ' }); -testVim('dl_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('2', 'd', 'l'); - eq('ord1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' w', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dh', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'h'); - eq(' wrd1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('o', register.toString()); - is(!register.linewise); - eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dj', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dj_end_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dk', function(cm, vim, helpers) { - var curStart = makeCursor(1, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dk_start_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dw_space', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dw_word', function(cm, vim, helpers) { - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq(' word2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 word2' }); -testVim('dw_only_word', function(cm, vim, helpers) { - // Test that if there is only 1 word left, dw deletes till the end of the - // line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1 ' }); -testVim('dw_eol', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2' }); -testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line and it is followed by multiple newlines. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \n\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n\nword2' }); -testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq(' \nword', cm.getValue()); -}, { value: '\n \nword' }); -testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('word', cm.getValue()); -}, { value: '\nword' }); -testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \n', cm.getValue()); -}, { value: ' \n \n' }); -testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n\n', cm.getValue()); -}, { value: ' \n\n' }); -testVim('dw_word_whitespace_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \nword2', cm.getValue()); -}, { value: 'word1\n \nword2'}) -testVim('dw_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'w'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('dw_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - cm.setCursor(0, 1); - helpers.doKeys('d', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2' }); -testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('\n\n', cm.getValue()); -}, { value: 'word\n\n' }); -testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('d', 'e'); - eq('wor', cm.getValue()); -}, { value: 'word\n\n\n' }); -testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('', cm.getValue()); -}, { value: ' \n\n\n' }); -testVim('de_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'e'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('db_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\n\n', cm.getValue()); -}, { value: '\n\n\n' }); -testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\nword', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('d', 'b'); - eq('\n\nd', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('db_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'b'); - eq('abc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('dge_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - // Note: In real VIM the result should be '', but it's not quite consistent, - // since 2 newlines are deleted. But in the similar case of word\n\n, only - // 1 newline is deleted. We'll diverge from VIM's behavior since it's much - // easier this way. - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - eq('wor\n', cm.getValue()); -}, { value: 'word\n\n'}); -testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'g', 'e'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('dge_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'g', 'e'); - eq('bc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('d_inclusive', function(cm, vim, helpers) { - // Assert that when inclusive is set, the character the cursor is on gets - // deleted too. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'e'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('d_reverse', function(cm, vim, helpers) { - // Test that deleting in reverse works. - cm.setCursor(1, 0); - helpers.doKeys('d', 'b'); - eq(' word2 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\n', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2 ' }); -testVim('dd', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 1, ch: 0 }); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[1].textStart); -}); -testVim('dd_prefix_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('2', 'd', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_motion_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('d', '2', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 6; - helpers.doKeys('2', 'd', '3', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[6].textStart); -}); -testVim('dd_lastline', function(cm, vim, helpers) { - cm.setCursor(cm.lineCount(), 0); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - helpers.assertCursorAt(cm.lineCount() - 1, 0); -}); -testVim('dd_only_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var expectedRegister = cm.getValue() + "\n"; - helpers.doKeys('d','d'); - eq(1, cm.lineCount()); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedRegister, register.toString()); -}, { value: "thisistheonlyline" }); -// Yank commands should behave the exact same as d commands, expect that nothing -// gets deleted. -testVim('yw_repeat', function(cm, vim, helpers) { - // Assert that yw does yank newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('y', '2', 'w'); - eq(' word1\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('yy_multiply_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount(); - helpers.doKeys('2', 'y', '3', 'y'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eqPos(curStart, cm.getCursor()); -}); -// Change commands behave like d commands except that it also enters insert -// mode. In addition, when the change is linewise, an additional newline is -// inserted so that insert mode starts on that line. -testVim('cw', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('c', '2', 'w'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); -}, { value: 'word1 word2 word3'}); -testVim('cw_repeat', function(cm, vim, helpers) { - // Assert that cw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('c', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2' }); -testVim('cc_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 5; - helpers.doKeys('2', 'c', '3', 'c'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('cc_should_not_append_to_document', function(cm, vim, helpers) { - var expectedLineCount = cm.lineCount(); - cm.setCursor(cm.lastLine(), 0); - helpers.doKeys('c', 'c'); - eq(expectedLineCount, cm.lineCount()); -}); -function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; -} -testVim('c_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); - var replacement = fillArray('hello', 3); - cm.replaceSelections(replacement); - eq('1hello\n5hello\nahellofg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(2, 3); - helpers.doKeys('', '2', 'k', 'h', 'C'); - replacement = fillArray('world', 3); - cm.replaceSelections(replacement); - eq('1hworld\n5hworld\nahworld', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('c_visual_block_replay', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = fillArray('fo', 3); - cm.replaceSelections(replacement); - eq('1fo4\n5fo8\nafodefg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - eq('foo4\nfoo8\nfoodefg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -testVim('d_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'd'); - eq('1\n5\nafg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('D_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'D'); - eq('1\n5\na', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -// Swapcase commands edit in place and do not modify registers. -testVim('g~w_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('g', '~', '2', 'w'); - eq(' WORD1\nWORD2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('g~g~', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedLineCount = cm.lineCount(); - var expectedValue = cm.getValue().toUpperCase(); - helpers.doKeys('2', 'g', '~', '3', 'g', '~'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); -testVim('gu_and_gU', function(cm, vim, helpers) { - var curStart = makeCursor(0, 7); - var value = cm.getValue(); - cm.setCursor(curStart); - helpers.doKeys('2', 'g', 'U', 'w'); - eq(cm.getValue(), 'wa wb xX WC wd'); - eqPos(curStart, cm.getCursor()); - helpers.doKeys('2', 'g', 'u', 'w'); - eq(cm.getValue(), value); - - helpers.doKeys('2', 'g', 'U', 'B'); - eq(cm.getValue(), 'wa WB Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - cm.setCursor(makeCursor(0, 4)); - helpers.doKeys('g', 'u', 'i', 'w'); - eq(cm.getValue(), 'wa wb Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - // TODO: support gUgU guu - // eqPos(makeCursor(0, 0), cm.getCursor()); - - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); -}, { value: 'wa wb xx wc wd' }); -testVim('visual_block_~', function(cm, vim, helpers) { - cm.setCursor(1, 1); - helpers.doKeys('', 'l', 'l', 'j', '~'); - helpers.assertCursorAt(1, 1); - eq('hello\nwoRLd\naBCDe', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', '~'); - helpers.assertCursorAt(2, 0); - eq('hello\nwoRLd\nAbcDe', cm.getValue()); -},{value: 'hello\nwOrld\nabcde' }); -testVim('._swapCase_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'j', 'l', '~'); - cm.setCursor(0, 3); - helpers.doKeys('.'); - eq('HelLO\nWorLd\nAbcdE', cm.getValue()); -},{value: 'hEllo\nwOrlD\naBcDe' }); -testVim('._delete_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'x'); - eq('ive\ne\nsome\nsugar', cm.getValue()); - helpers.doKeys('.'); - eq('ve\n\nsome\nsugar', cm.getValue()); - helpers.doKeys('j', 'j', '.'); - eq('ve\n\nome\nugar', cm.getValue()); - helpers.doKeys('u', '', '.'); - eq('ve\n\nme\ngar', cm.getValue()); -},{value: 'give\nme\nsome\nsugar' }); -testVim('>{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('>', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('>>', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('2', '>', '>'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('<{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('<', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); -testVim('<<', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('2', '<', '<'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); - -// Edit tests -function testEdit(name, before, pos, edit, after) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, edit.split('')); - eq(after, cm.getValue()); - }, {value: before}); -} - -// These Delete tests effectively cover word-wise Change, Visual & Yank. -// Tabs are used as differentiated whitespace to catch edge cases. -// Normal word: -testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); -testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); -testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); -testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); -testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); -testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); -testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); -testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); -testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); -testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); -testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); -testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); -testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); -testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); -// Big word: -testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); -testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); -testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); -testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); -testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); -testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); -// Deleting text objects -// Open and close on same line -testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); -testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); -testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); -testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); -testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); - -testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); -testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); -testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); -testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); - -testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); -testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); -testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); -testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); - -// delete around and inner b. -testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); - -// delete around and inner B. -testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); -testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); - -testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); -testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); -testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); -testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); -testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); -testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); - -// Open and close on different lines, equally indented -testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); -testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); - -// open and close on diff lines, open indented less than close -testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); - -// open and close on diff lines, open indented more than close -testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); -testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); -testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); -testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); - -function testSelection(name, before, pos, keys, sel) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, keys.split('')); - eq(sel, cm.getSelection()); - }, {value: before}); -} -testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); -testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); -testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); -testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); -testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); -testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); -testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); -testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); -testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); - -testVim('mouse_select', function(cm, vim, helpers) { - cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); - is(cm.state.vim.visualMode); - is(!cm.state.vim.visualLine); - is(!cm.state.vim.visualBlock); - helpers.doKeys(''); - is(!cm.somethingSelected()); - helpers.doKeys('g', 'v'); - eq('cd', cm.getSelection()); -}, {value: 'abcdef'}); - -// Operator-motion tests -testVim('D', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('D'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('C', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('C'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2\n word3' }); -testVim('Y', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('Y'); - eq(' word1\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('~', function(cm, vim, helpers) { - helpers.doKeys('3', '~'); - eq('ABCdefg', cm.getValue()); - helpers.assertCursorAt(0, 3); -}, { value: 'abcdefg' }); - -// Action tests -testVim('ctrl-a', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-9', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-7', cm.getValue()); -}, {value: '-10'}); -testVim('ctrl-x', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-1', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-3', cm.getValue()); -}, {value: '0'}); -testVim('/ search forward', function(cm, vim, helpers) { - forEach(['', ''], function(key) { - cm.setCursor(0, 0); - helpers.doKeys(key); - helpers.assertCursorAt(0, 5); - helpers.doKeys('l'); - helpers.doKeys(key); - helpers.assertCursorAt(0, 10); - cm.setCursor(0, 11); - helpers.doKeys(key); - helpers.assertCursorAt(0, 11); - }); -}, {value: '__jmp1 jmp2 jmp'}); -testVim('a', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 2); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('a_eol', function(cm, vim, helpers) { - cm.setCursor(0, lines[0].length - 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_endOfSelectedArea', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'j', 'l'); - helpers.doKeys('A'); - helpers.assertCursorAt(1, 2); - eq('vim-insert', cm.getOption('keyMap')); -}, {value: 'foo\nbar'}); -testVim('i', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('i'); - helpers.assertCursorAt(0, 1); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('i_repeat', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttest', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: '' }); -testVim('i_repeat_delete', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('2', 'i'); - cm.replaceRange('z', cm.getCursor()); - helpers.doInsertModeKeys('Backspace', 'Backspace'); - helpers.doKeys(''); - eq('abe', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'abcde' }); -testVim('A', function(cm, vim, helpers) { - helpers.doKeys('A'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('testhello\nmehello\npleahellose', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - // TODO this doesn't work yet - // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('I', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('I'); - helpers.assertCursorAt(0, lines[0].textStart); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('I_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'I'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttestblah', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: 'blah' }); -testVim('I_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('hellotest\nhellome\nhelloplease', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('o', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('o'); - eq('word1\n\nword2', cm.getValue()); - helpers.assertCursorAt(1, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('o_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('3', 'o'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('\ntest\ntest\ntest', cm.getValue()); - helpers.assertCursorAt(3, 3); -}, { value: '' }); -testVim('O', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('O'); - eq('\nword1\nword2', cm.getValue()); - helpers.assertCursorAt(0, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('J', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('J'); - var expectedValue = 'word1 word2\nword3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('J_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('3', 'J'); - var expectedValue = 'word1 word2 word3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('p', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('"', 'a', 'p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_wrong_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('p'); - eq('___', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: '___' }); -testVim('p_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_lastline', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\n def', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\ndef', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_with_tab_indents', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true}); -testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); -testVim('[p', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys('[', 'p'); - eq(' abc\n def\n ___', cm.getValue()); -}, { value: ' ___' }); -testVim('P', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('P'); - eq('_abc\ndef__', cm.getValue()); - helpers.assertCursorAt(1, 3); -}, { value: '___' }); -testVim('P_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'P'); - eq(' a\nd\n a\nd\n___', cm.getValue()); - helpers.assertCursorAt(0, 2); -}, { value: '___' }); -testVim('r', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'r', 'u'); - eq('wuuuet\nanother', cm.getValue(),'3r failed'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 4); - helpers.doKeys('v', 'j', 'h', 'r', ''); - eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); -}, { value: 'wordet\nanother' }); -testVim('r_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); - eq('1lll\n5lll\nalllefg', cm.getValue()); - helpers.doKeys('', 'l', 'j', 'r', ''); - eq('1 l\n5 l\nalllefg', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('o'); - helpers.doKeys(''); - cm.replaceRange('\t\t', cm.getCursor()); - helpers.doKeys('', 'h', 'h', 'r', 'r'); - eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('R', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('R'); - helpers.assertCursorAt(0, 1); - eq('vim-replace', cm.getOption('keyMap')); - is(cm.state.overwrite, 'Setting overwrite state failed'); -}); -testVim('mark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(2, 2); - cm.setCursor(2, 0); - cm.replaceRange(' h', cm.getCursor()); - cm.setCursor(0, 0); - helpers.doKeys('\'', 't'); - helpers.assertCursorAt(2, 3); -}); -testVim('jumpToMark_next', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(0, 0); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 4); -}); -testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(4, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(4, 0); -}); -testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 1); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '`'); - helpers.assertCursorAt(0, 0); - var actual = cm.getLine(0); - var expected = 'pop pop 0 1 2 3 4'; - eq(actual, expected, "Deleting while jumping to the next mark failed."); -}); -testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '\''); - helpers.assertCursorAt(0, 1); - var actual = cm.getLine(0); - var expected = ' (a) [b] {c} ' - eq(actual, expected, "Deleting while jumping to the next mark line failed."); -}); -testVim('jumpToMark_prev', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(4, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(4, 0); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { - cm.setCursor(4, 4); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 6); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('delmark_single', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 't'); - helpers.doEx('delmarks t'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(0, 0); -}); -testVim('delmark_range', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b-d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks bcd'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi_space', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b c d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_all', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks a b-de'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(0, 0); -}); -testVim('visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l'); - helpers.assertCursorAt(0, 4); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('d'); - eq('15', cm.getValue()); -}, { value: '12345' }); -testVim('visual_yank', function(cm, vim, helpers) { - helpers.doKeys('v', '3', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('p'); - eq('aa te test for yank', cm.getValue()); -}, { value: 'a test for yank' }) -testVim('visual_w', function(cm, vim, helpers) { - helpers.doKeys('v', 'w'); - eq(cm.getSelection(), 'motion t'); -}, { value: 'motion test'}); -testVim('visual_initial_selection', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v'); - cm.getSelection('n'); -}, { value: 'init'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'l', 'h', 'h'); - cm.getSelection('ro'); -}, { value: 'cross'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'h', 'l', 'l'); - cm.getSelection('os'); -}, { value: 'cross'}); -testVim('visual_crossover_up', function(cm, vim, helpers) { - cm.setCursor(3, 2); - helpers.doKeys('v', 'j', 'k', 'k'); - eqPos(Pos(2, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); - helpers.doKeys('k'); - eqPos(Pos(1, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_crossover_down', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('v', 'k', 'j', 'j'); - eqPos(Pos(2, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); - helpers.doKeys('j'); - eqPos(Pos(3, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_exit', function(cm, vim, helpers) { - helpers.doKeys('', 'l', 'j', 'j', ''); - eqPos(cm.getCursor('anchor'), cm.getCursor('head')); - eq(vim.visualMode, false); -}, { value: 'hello\nworld\nfoo' }); -testVim('visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); - eq(' 4\n 5', cm.getValue()); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_block_move_to_eol', function(cm, vim, helpers) { - // moveToEol should move all block cursors to end of line - cm.setCursor(0, 0); - helpers.doKeys('', 'G', '$'); - var selections = cm.getSelections().join(); - eq("123,45,6", selections); -}, {value: '123\n45\n6'}); -testVim('visual_block_different_line_lengths', function(cm, vim, helpers) { - // test the block selection with lines of different length - // i.e. extending the selection - // till the end of the longest line. - helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); - helpers.doKeys('d', 'd', 'd', 'd'); - eq('', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) { - // check for left side selection in case - // of moving up to a shorter line. - cm.replaceRange('', cm.getCursor()); - cm.setCursor(3, 4); - helpers.doKeys('', 'l', 'k', 'k', 'd'); - eq('hello world\n{\ntis\nsa!', cm.getValue()); -}, {value: 'hello world\n{\nthis is\nsparta!'}); -testVim('visual_block_corners', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', '2', 'l', 'k'); - // circle around the anchor - // and check the selections - var selections = cm.getSelections(); - eq('345891', selections.join('')); - helpers.doKeys('4', 'h'); - selections = cm.getSelections(); - eq('123678', selections.join('')); - helpers.doKeys('j', 'j'); - selections = cm.getSelections(); - eq('678abc', selections.join('')); - helpers.doKeys('4', 'l'); - selections = cm.getSelections(); - eq('891cde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_mode_switch', function(cm, vim, helpers) { - // switch between visual modes - cm.setCursor(1, 1); - // blockwise to characterwise visual - helpers.doKeys('', 'j', 'l', 'v'); - selections = cm.getSelections(); - eq('7891\nabc', selections.join('')); - // characterwise to blockwise - helpers.doKeys(''); - selections = cm.getSelections(); - eq('78bc', selections.join('')); - // blockwise to linewise visual - helpers.doKeys('V'); - selections = cm.getSelections(); - eq('67891\nabcde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { - // visual block with long and short lines - cm.setCursor(0, 3); - helpers.doKeys('', 'j', 'j', 'j'); - var selections = cm.getSelections().join(); - eq('4,,d,b', selections); - helpers.doKeys('3', 'k'); - selections = cm.getSelections().join(); - eq('4', selections); - helpers.doKeys('5', 'j', 'k'); - selections = cm.getSelections().join(""); - eq(10, selections.length); -}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); -testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3' , 'l', ''); - eqPos(makeCursor(0, 3), cm.getCursor()); - helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); - eq(cm.getSelections().join(), "3456,,cdef"); - helpers.doKeys('4' , 'h'); - eq(cm.getSelections().join(), "23,8,bc"); - helpers.doKeys('2' , 'l'); - eq(cm.getSelections().join(), "34,,cd"); -}, {value: '123456\n78\nabcdefg\nfoobar'}); - -testVim('visual_marks', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); - // Test visual mode marks - cm.setCursor(2, 1); - helpers.doKeys('\'', '<'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('\'', '>'); - helpers.assertCursorAt(2, 0); -}); -testVim('visual_join', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); - eq(' 1 2 3\n 4\n 5', cm.getValue()); - is(!vim.visualMode); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_blank', function(cm, vim, helpers) { - helpers.doKeys('v', 'k'); - eq(vim.visualMode, true); -}, { value: '\n' }); -testVim('reselect_visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); - helpers.assertCursorAt(0, 5); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'l', 'l', 'p'); - eq('123456\n2345\nbar', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('g', 'v'); - // here the fake cursor is at (1, 3) - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', 'g', 'v'); - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); - eqPos(makeCursor(2, 0), cm.getCursor('anchor')); - eq('123456\n2345\nbar', cm.getValue()); -}, { value: '123456\nfoo\nbar' }); -testVim('reselect_visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); - eq('foo\nand\nbar', cm.getValue()); - cm.setCursor(1, 0); - helpers.doKeys('V', 'y', 'j'); - helpers.doKeys('V', 'p' , 'g', 'v', 'd'); - eq('foo\nand', cm.getValue()); -}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); -testVim('reselect_visual_block', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', 'k', 'h', ''); - cm.setCursor(2, 1); - helpers.doKeys('v', 'l', 'g', 'v'); - eqPos(Pos(1, 2), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - // Ensure selection is done with visual block mode rather than one - // continuous range. - eq(cm.getSelections().join(''), '23oo') - helpers.doKeys('g', 'v'); - eqPos(Pos(2, 1), vim.sel.anchor); - eqPos(Pos(2, 2), vim.sel.head); - helpers.doKeys(''); - // Ensure selection of deleted range - cm.setCursor(1, 1); - helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); - eq(cm.getSelections().join(''), 'or'); -}, { value: '123456\nfoo\nbar' }); -testVim('s_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('s'); - helpers.doKeys(''); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('s_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 's'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('o_visual', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys('v','l','l','l','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('v','v','j','j','j','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('O'); - helpers.doKeys('l','l') - helpers.assertCursorAt(3, 3); - helpers.doKeys('d'); - eq('p',cm.getValue()); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('o_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('','3','j','l','l', 'o'); - eqPos(Pos(3, 3), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - helpers.doKeys('O'); - eqPos(Pos(3, 1), vim.sel.anchor); - eqPos(Pos(0, 3), vim.sel.head); - helpers.doKeys('o'); - eqPos(Pos(0, 3), vim.sel.anchor); - eqPos(Pos(3, 1), vim.sel.head); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('changeCase_visual', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('U'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('u'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('l', 'l', 'l', '.'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('j', '@', 'a'); - helpers.assertCursorAt(1, 0); - cm.setCursor(3, 0); - helpers.doKeys('V', 'U', 'j', '.'); - eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); -testVim('changeCase_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 1); - helpers.doKeys('', 'k', 'k', 'h', 'U'); - eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); - cm.setCursor(0, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); - // check when last line is shorter. - cm.setCursor(2, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); -testVim('visual_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p'); - helpers.assertCursorAt(1, 5); - eq('this is a\nunithitest for visual paste', cm.getValue()); - cm.setCursor(0, 0); - // in case of pasting whole line - helpers.doKeys('y', 'y'); - cm.setCursor(1, 6); - helpers.doKeys('v', 'l', 'l', 'l', 'p'); - helpers.assertCursorAt(2, 0); - eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); -}, { value: 'this is a\nunit test for visual paste'}); - -// This checks the contents of the register used to paste the text -testVim('v_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'p'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+register/.test(text)); - }); -}, { value: 'register contents\nare not erased'}); -testVim('S_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(1, 0); - eq('aa\n\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); -testVim('blockwise_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'l', 'y'); - cm.setCursor(0, 2); - // paste one char after the current cursor position - helpers.doKeys('p'); - eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('v', '4', 'l', 'y'); - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'p'); - eq('helheelhelo\norwold\noofo\narba', cm.getValue()); -}, { value: 'hello\nworld\nfoo\nbar'}); -testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { - // extend short lines in case of different line lengths. - cm.setCursor(0, 0); - helpers.doKeys('', 'j', 'j', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('p'); - eq('hellho\nfoo f\nbar b', cm.getValue()); -}, { value: 'hello\nfoo\nbar'}); -testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'x'); - cm.setCursor(0, 0); - helpers.doKeys('P'); - eq('cut\nand\npaste\nme', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); -testVim('blockwise_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', '"', 'a', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('"', 'a', 'p'); - eq('foobfar\nhellho\nworlwd', cm.getValue()); -}, { value: 'foobar\nhello\nworld'}); -testVim('blockwise_paste_last_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'y'); - cm.setCursor(3, 0); - helpers.doKeys('p'); - eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); - -testVim('S_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 'j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); - -testVim('/ and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('N'); - helpers.assertCursorAt(0, 11); - - cm.setCursor(0, 0); - helpers.doKeys('2', '/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_case', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('Match'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_2_pcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', true); - cm.openDialog = helpers.fakeOpenDialog('(word){2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_2_nopcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('?_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('? and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('N'); - helpers.assertCursorAt(1, 6); - - cm.setCursor(0, 0); - helpers.doKeys('2', '?'); - helpers.assertCursorAt(0, 11); -}, { value: 'match nope match \n nope Match' }); -testVim('*', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); - - cm.setCursor(0, 9); - helpers.doKeys('2', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_no_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 0); -}, { value: ' \n match \n' }); -testVim('*_symbol', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(1, 0); -}, { value: ' /}\n/} match \n' }); -testVim('#', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); - - cm.setCursor(0, 9); - helpers.doKeys('2', '#'); - helpers.assertCursorAt(0, 22); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_seek', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('#', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('g*', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '*'); - helpers.assertCursorAt(0, 18); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('g#', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '#'); - helpers.assertCursorAt(0, 0); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '#'); - helpers.assertCursorAt(1, 0); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('macro_insert', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '0', 'i'); - cm.replaceRange('foo', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q', '@', 'a'); - eq('foofoo', cm.getValue()); -}, { value: ''}); -testVim('macro_insert_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '$', 'a'); - cm.replaceRange('larry.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('a'); - cm.replaceRange('curly.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('a'); - cm.replaceRange('moe.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('@', 'a'); - // At this point, the most recent edit should be the 2nd insert change - // inside the macro, i.e. "curly.". - helpers.doKeys('.'); - eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); -}, { value: ''}); -testVim('macro_space', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', ''); - helpers.assertCursorAt(0, 2); - helpers.doKeys('q', 'a', '', '', 'q'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 8); -}, { value: 'one line of text.'}); -testVim('macro_t_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 't', 'e', 'q'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('l', '@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('l', ';'); - helpers.assertCursorAt(0, 12); -}, { value: 'one line of text.'}); -testVim('macro_f_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'b', 'f', 'e', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'b'); - helpers.assertCursorAt(0, 7); - helpers.doKeys(';'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_slash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'c'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'c'); - helpers.assertCursorAt(0, 7); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_multislash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'd'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('t'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 12); - helpers.doKeys('@', 'd'); - helpers.assertCursorAt(0, 15); -}, { value: 'one line of text to rule them all.'}); -testVim('macro_parens', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', 'i'); - cm.replaceRange('(', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('e', 'a'); - cm.replaceRange(')', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('w', '@', 'z'); - helpers.doKeys('w', '@', 'z'); - eq('(see) (spot) (run)', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_overwrite', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', '0', 'i'); - cm.replaceRange('I ', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e'); - // Now replace the macro with something else. - helpers.doKeys('q', 'z', 'a'); - cm.replaceRange('.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e', '@', 'z'); - helpers.doKeys('e', '@', 'z'); - eq('I see. spot. run.', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_search_f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'f', ' '); - helpers.assertCursorAt(0,3); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,3); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('macro_search_2f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '2', 'f', ' '); - helpers.assertCursorAt(0,9); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,9); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('yank_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'b', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo/.test(text)); - is(/b\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+oo\nar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foobar/.test(text)); - is(/"\s+foobar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('macro_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'i'); - cm.replaceRange('gangnam', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('q', 'b', 'o'); - cm.replaceRange('style', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+i/.test(text)); - is(/b\s+o/.test(text)); - }); - helpers.doKeys(':'); -}, { value: ''}); -testVim('._register', function(cm,vim,helpers) { - cm.setCursor(0,0); - helpers.doKeys('i'); - cm.replaceRange('foo',cm.getCursor()); - helpers.doKeys(''); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\.\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim(':_register', function(cm,vim,helpers) { - helpers.doEx('bar'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/:\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register_escape', function(cm, vim, helpers) { - // Check that the register is restored if the user escapes rather than confirms. - cm.openDialog = helpers.fakeOpenDialog('waldo'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var KEYCODES = { - f: 70, - o: 79, - Esc: 27 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - onKeyUp = options.onKeyUp; - }; - var close = function() {}; - helpers.doKeys('/'); - // Fake some keyboard events coming in. - onKeyDown({keyCode: KEYCODES.f}, '', close); - onKeyUp({keyCode: KEYCODES.f}, '', close); - onKeyDown({keyCode: KEYCODES.o}, 'f', close); - onKeyUp({keyCode: KEYCODES.o}, 'f', close); - onKeyDown({keyCode: KEYCODES.o}, 'fo', close); - onKeyUp({keyCode: KEYCODES.o}, 'fo', close); - onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/waldo/.test(text)); - is(!/foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('foo'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\/\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('this'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('search'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('history'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var query = ''; - var keyCodes = { - Up: 38, - Down: 40 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') query = newVal; - } - helpers.doKeys('/'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'checks'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'history'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'search'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'this'); - onKeyDown({keyCode: keyCodes.Down}, query, close); - onKeyUp({keyCode: keyCodes.Down}, query, close); - eq(query, 'search'); -}, {value: ''}); -testVim('exCommand_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('registers'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('sort'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('map'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('invalid'); - helpers.doKeys(':'); - var onKeyDown; - var onKeyUp; - var input = ''; - var keyCodes = { - Up: 38, - Down: 40, - s: 115 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys(':'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'invalid'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'map'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'registers'); - onKeyDown({keyCode: keyCodes.s}, '', close); - input = 's'; - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); -}, {value: ''}); -testVim('.', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('.'); - eq('5 6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('3', '.'); - eq('6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._insert', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('testestt', cm.getValue()); - helpers.assertCursorAt(0, 6); -}, { value: ''}); -testVim('._insert_repeat', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - cm.setCursor(0, 4); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('testesttestt', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._repeat_insert', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('te', cm.getCursor()); - cm.setCursor(0, 2); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('tetettetetee', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._insert_o', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - cm.setCursor(1, 1); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('\nz\nz', cm.getValue()); - helpers.assertCursorAt(2, 0); -}, { value: ''}); -testVim('._insert_o_repeat', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 0); - helpers.doKeys('2', '.'); - eq('\nz\nz\nz', cm.getValue()); - helpers.assertCursorAt(3, 0); -}, { value: ''}); -testVim('._insert_o_indent', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 2); - helpers.doKeys('.'); - eq('{\n z\n z', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '{'}); -testVim('._insert_cw', function(cm, vim, helpers) { - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 3); - helpers.doKeys('2', 'l'); - helpers.doKeys('.'); - eq('test test word3', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._insert_cw_repeat', function(cm, vim, helpers) { - // For some reason, repeat cw in desktop VIM will does not repeat insert mode - // changes. Will conform to that behavior. - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 4); - helpers.doKeys('l'); - helpers.doKeys('2', '.'); - eq('test test', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._delete', function(cm, vim, helpers) { - cm.setCursor(0, 5); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('zace', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zabcde'}); -testVim('._delete_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('zzce', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zzabcde'}); -testVim('._visual_>', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('V', 'j', '>'); - cm.setCursor(2, 0) - helpers.doKeys('.'); - eq(' 1\n 2\n 3\n 4', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '1\n2\n3\n4'}); -testVim('f;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F;', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('F', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx6x8x'}); -testVim('t;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '0xx3xx678x'}); -testVim('f,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('f', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F,', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('F', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('t,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('t', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(3, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T,', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('T', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx67xx'}); -testVim('fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('td,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Td,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('012340123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'P'); - eq('012345678456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('012345678945678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('012340123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('01230123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'p'); - eq('01234567895678', cm.getValue()); -}, { value: '0123456789'}); -testVim('Ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('01234567895678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('01230123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('HML', function(cm, vim, helpers) { - var lines = 35; - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(120, 0); - helpers.doKeys('H'); - helpers.assertCursorAt(86, 2); - helpers.doKeys('L'); - helpers.assertCursorAt(120, 4); - helpers.doKeys('M'); - helpers.assertCursorAt(103,4); -}, { value: (function(){ - var lines = new Array(100); - var upper = ' xx\n'; - var lower = ' xx\n'; - upper = lines.join(upper); - lower = lines.join(lower); - return upper + lower; -})()}); - -var zVals = []; -forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ - var lineNum = 250; - var lines = 35; - testVim(e, function(cm, vim, helpers) { - var k1 = e[0]; - var k2 = e.substring(1); - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(lineNum, 0); - helpers.doKeys(k1, k2); - zVals[idx] = cm.getScrollInfo().top; - }, { value: (function(){ - return new Array(500).join('\n'); - })()}); -}); -testVim('zb', function(cm, vim, helpers){ - eq(zVals[2], zVals[5]); -}); - -var moveTillCharacterSandbox = - 'The quick brown fox \n' - 'jumped over the lazy dog.' -testVim('moveTillCharacter', function(cm, vim, helpers){ - cm.setCursor(0, 0); - // Search for the 'q'. - cm.openDialog = helpers.fakeOpenDialog('q'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); - // Jump to just before the first o in the list. - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick brown fox \n', cm.getValue()); - // Delete that one character. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick bown fox \n', cm.getValue()); - // Delete everything until the next 'o'. - helpers.doKeys('.'); - eq('The quick box \n', cm.getValue()); - // An unmatched character should have no effect. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('q'); - eq('The quick box \n', cm.getValue()); - // Matches should only be possible on single lines. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('z'); - eq('The quick box \n', cm.getValue()); - // After all that, the search for 'q' should still be active, so the 'N' command - // can run it again in reverse. Use that to delete everything back to the 'q'. - helpers.doKeys('d'); - helpers.doKeys('N'); - eq('The ox \n', cm.getValue()); - eq(4, cm.getCursor().ch); -}, { value: moveTillCharacterSandbox}); -testVim('searchForPipe', function(cm, vim, helpers){ - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(0, 0); - // Search for the '|'. - cm.openDialog = helpers.fakeOpenDialog('|'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); -}, { value: 'this|that'}); - - -var scrollMotionSandbox = - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; -testVim('scrollMotion', function(cm, vim, helpers){ - var prevCursor, prevScrollInfo; - cm.setCursor(0, 0); - // ctrl-y at the top of the file should have no effect. - helpers.doKeys(''); - eq(0, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(1, cm.getCursor().line); - is(prevScrollInfo.top < cm.getScrollInfo().top); - // Jump to the end of the sandbox. - cm.setCursor(1000, 0); - prevCursor = cm.getCursor(); - // ctrl-e at the bottom of the file should have no effect. - helpers.doKeys(''); - eq(prevCursor.line, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(prevCursor.line - 1, cm.getCursor().line); - is(prevScrollInfo.top > cm.getScrollInfo().top); -}, { value: scrollMotionSandbox}); - -var squareBracketMotionSandbox = ''+ - '({\n'+//0 - ' ({\n'+//11 - ' /*comment {\n'+//2 - ' */(\n'+//3 - '#else \n'+//4 - ' /* )\n'+//5 - '#if }\n'+//6 - ' )}*/\n'+//7 - ')}\n'+//8 - '{}\n'+//9 - '#else {{\n'+//10 - '{}\n'+//11 - '}\n'+//12 - '{\n'+//13 - '#endif\n'+//14 - '}\n'+//15 - '}\n'+//16 - '#else';//17 -testVim('[[, ]]', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(9,0); - helpers.doKeys('2', ']', ']'); - helpers.assertCursorAt(13,0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(13,0); - helpers.doKeys('2', '[', '['); - helpers.assertCursorAt(9,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[], ][', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(12,0); - helpers.doKeys('2', ']', '['); - helpers.assertCursorAt(16,0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(16,0); - helpers.doKeys('2', '[', ']'); - helpers.assertCursorAt(12,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[{, ]}', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(2,12); - helpers.doKeys('2', '[', '{'); - helpers.assertCursorAt(0,1); - cm.setCursor(4, 10); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(6,11); - helpers.doKeys('2', ']', '}'); - helpers.assertCursorAt(8,1); - cm.setCursor(0,1); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(8,1); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(0,1); -}, { value: squareBracketMotionSandbox}); -testVim('[(, ])', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '('); - helpers.assertCursorAt(3,14); - helpers.doKeys('2', '[', '('); - helpers.assertCursorAt(0,0); - cm.setCursor(4, 10); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(5,11); - helpers.doKeys('2', ']', ')'); - helpers.assertCursorAt(8,0); - helpers.doKeys('[', '('); - helpers.assertCursorAt(0,0); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(8,0); -}, { value: squareBracketMotionSandbox}); -testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { - forEach(['*', '/'], function(key){ - cm.setCursor(7, 0); - helpers.doKeys('2', '[', key); - helpers.assertCursorAt(2,2); - helpers.doKeys('2', ']', key); - helpers.assertCursorAt(7,5); - }); -}, { value: squareBracketMotionSandbox}); -testVim('[#, ]#', function(cm, vim, helpers) { - cm.setCursor(10, 3); - helpers.doKeys('2', '[', '#'); - helpers.assertCursorAt(4,0); - helpers.doKeys('5', ']', '#'); - helpers.assertCursorAt(17,0); - cm.setCursor(10, 3); - helpers.doKeys(']', '#'); - helpers.assertCursorAt(14,0); -}, { value: squareBracketMotionSandbox}); -testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { - cm.setCursor(11, 0); - helpers.doKeys('[', 'm'); - helpers.assertCursorAt(10,7); - helpers.doKeys('4', '[', 'm'); - helpers.assertCursorAt(1,3); - helpers.doKeys('5', ']', 'm'); - helpers.assertCursorAt(11,0); - helpers.doKeys('[', 'M'); - helpers.assertCursorAt(9,1); - helpers.doKeys('3', ']', 'M'); - helpers.assertCursorAt(15,0); - helpers.doKeys('5', '[', 'M'); - helpers.assertCursorAt(7,3); -}, { value: squareBracketMotionSandbox}); - -// Ex mode tests -testVim('ex_go_to_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('4'); - helpers.assertCursorAt(3, 0); -}, { value: 'a\nb\nc\nd\ne\n'}); -testVim('ex_write', function(cm, vim, helpers) { - var tmp = CodeMirror.commands.save; - var written; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Test that w, wr, wri ... write all trigger :write. - var command = 'write'; - for (var i = 1; i < command.length; i++) { - written = false; - actualCm = null; - helpers.doEx(command.substring(0, i)); - eq(written, true); - eq(actualCm, cm); - } - CodeMirror.commands.save = tmp; -}); -testVim('ex_sort', function(cm, vim, helpers) { - helpers.doEx('sort'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_reverse', function(cm, vim, helpers) { - helpers.doEx('sort!'); - eq('d\nc\nb\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_range', function(cm, vim, helpers) { - helpers.doEx('2,3sort'); - eq('b\nc\nd\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_oneline', function(cm, vim, helpers) { - helpers.doEx('2sort'); - // Expect no change. - eq('b\nd\nc\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { - helpers.doEx('sort i'); - eq('a\nb\nc\nd\nZ', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_unique', function(cm, vim, helpers) { - helpers.doEx('sort u'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\na\na\nd\na\nc\na'}); -testVim('ex_sort_decimal', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('d3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\nz-9'}); -testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('.9\n6\n s5\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_hex', function(cm, vim, helpers) { - helpers.doEx('sort x'); - eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n&0xB\n.9'}); -testVim('ex_sort_octal', function(cm, vim, helpers) { - helpers.doEx('sort o'); - eq('.8\n.9\nd3\n s5\n6', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\n.8'}); -testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('y\nz\nc1\nb2\na3', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('a3\nb2\nc1\nz\ny', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -// test for :global command -testVim('ex_global', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('g/one/s//two'); - eq('two two\n two two\n two two', cm.getValue()); - helpers.doEx('1,2g/two/s//one'); - eq('one one\n one one\n two two', cm.getValue()); -}, {value: 'one one\n one one\n one one'}); -testVim('ex_global_confirm', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var onKeyDown; - var openDialogSave = cm.openDialog; - var KEYCODES = { - a: 65, - n: 78, - q: 81, - y: 89 - }; - // Intercept the ex command, 'global' - cm.openDialog = function(template, callback, options) { - // Intercept the prompt for the embedded ex command, 'substitute' - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - callback('g/one/s//two/gc'); - }; - helpers.doKeys(':'); - var close = function() {}; - onKeyDown({keyCode: KEYCODES.n}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - onKeyDown({keyCode: KEYCODES.a}, '', close); - onKeyDown({keyCode: KEYCODES.q}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); -}, {value: 'one one\n one one\n one one\n one one\n one one'}); -// Basic substitute tests. -testVim('ex_substitute_same_line', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('s/one/two/g'); - eq('one one\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_full_file', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('%s/one/two/g'); - eq('two two\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_input_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('1,3s/\\d/0/g'); - eq('0\n0\n0\n4', cm.getValue()); -}, { value: '1\n2\n3\n4' }); -testVim('ex_substitute_visual_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - // Set last visual mode selection marks '< and '> at lines 2 and 4 - helpers.doKeys('V', '2', 'j', 'v'); - helpers.doEx('\'<,\'>s/\\d/0/g'); - eq('1\n0\n0\n0\n5', cm.getValue()); -}, { value: '1\n2\n3\n4\n5' }); -testVim('ex_substitute_empty_query', function(cm, vim, helpers) { - // If the query is empty, use last query. - cm.setCursor(1, 0); - cm.openDialog = helpers.fakeOpenDialog('1'); - helpers.doKeys('/'); - helpers.doEx('s//b/g'); - eq('abb ab2 ab3', cm.getValue()); -}, { value: 'a11 a12 a13' }); -testVim('ex_substitute_javascript', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(1, 0); - // Throw all the things that javascript likes to treat as special values - // into the replace part. All should be literal (this is VIM). - helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') - eq('a $$ $\' $` $& 0 b', cm.getValue()); -}, { value: 'a 0 b' }); -testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { - cm.setCursor(0, 0); - helpers.doEx('s/a/b/g'); - cm.setCursor(1, 0); - helpers.doEx('s'); - eq('b b\nb a', cm.getValue()); -}, {value: 'a a\na a'}); - -// More complex substitute tests that test both pcre and nopcre options. -function testSubstitute(name, options) { - testVim(name + '_pcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', true); - helpers.doEx(options.expr); - eq(options.expectedValue, cm.getValue()); - }, options); - // If no noPcreExpr is defined, assume that it's the same as the expr. - var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; - testVim(name + '_nopcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', false); - helpers.doEx(noPcreExpr); - eq(options.expectedValue, cm.getValue()); - }, options); -} -testSubstitute('ex_substitute_capture', { - value: 'a11 a12 a13', - expectedValue: 'a1111 a1212 a1313', - // $n is a backreference - expr: 's/(\\d+)/$1$1/g', - // \n is a backreference. - noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); -testSubstitute('ex_substitute_capture2', { - value: 'a 0 b', - expectedValue: 'a $00 b', - expr: 's/(\\d+)/$$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a11 a12 a13', - expectedValue: 'a$1$1 a$1$1 a$1$1', - expr: 's/(\\d+)/$$1$$1/g', - noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); -testSubstitute('ex_substitute_nocapture2', { - value: 'a 0 b', - expectedValue: 'a $10 b', - expr: 's/(\\d+)/$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a b c', - expectedValue: 'a $ c', - expr: 's/b/$$/', - noPcreExpr: 's/b/$/'}); -testSubstitute('ex_substitute_slash_regex', { - value: 'one/two \n three/four', - expectedValue: 'one|two \n three|four', - expr: '%s/\\//|'}); -testSubstitute('ex_substitute_pipe_regex', { - value: 'one|two \n three|four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\|/,/', - noPcreExpr: '%s/|/,/'}); -testSubstitute('ex_substitute_or_regex', { - value: 'one|two \n three|four', - expectedValue: 'ana|twa \n thraa|faar', - expr: '%s/o|e|u/a/g', - noPcreExpr: '%s/o\\|e\\|u/a/g'}); -testSubstitute('ex_substitute_or_word_regex', { - value: 'one|two \n three|four', - expectedValue: 'five|five \n three|four', - expr: '%s/(one|two)/five/g', - noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); -testSubstitute('ex_substitute_backslashslash_regex', { - value: 'one\\two \n three\\four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\\\/,'}); -testSubstitute('ex_substitute_slash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one/two \n three/four', - expr: '%s/,/\\/'}); -testSubstitute('ex_substitute_backslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\two \n three\\four', - expr: '%s/,/\\\\/g'}); -testSubstitute('ex_substitute_multibackslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. - expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. -testSubstitute('ex_substitute_braces_word', { - value: 'ababab abb ab{2}', - expectedValue: 'ab abb ab{2}', - expr: '%s/(ab){2}//g', - noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_range', { - value: 'a aa aaa aaaa', - expectedValue: 'a a', - expr: '%s/a{2,3}//g', - noPcreExpr: '%s/a\\{2,3\\}//g'}); -testSubstitute('ex_substitute_braces_literal', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab abb ', - expr: '%s/ab\\{2\\}//g', - noPcreExpr: '%s/ab{2}//g'}); -testSubstitute('ex_substitute_braces_char', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_no_escape', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2}//g'}); -testSubstitute('ex_substitute_count', { - value: '1\n2\n3\n4', - expectedValue: '1\n0\n0\n4', - expr: 's/\\d/0/i 2'}); -testSubstitute('ex_substitute_count_with_range', { - value: '1\n2\n3\n4', - expectedValue: '1\n2\n0\n0', - expr: '1,3s/\\d/0/ 3'}); -testSubstitute('ex_substitute_not_global', { - value: 'aaa\nbaa\ncaa', - expectedValue: 'xaa\nbxa\ncxa', - expr: '%s/a/x/'}); -function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { - testVim(name, function(cm, vim, helpers) { - var savedOpenDialog = cm.openDialog; - var savedKeyName = CodeMirror.keyName; - var onKeyDown; - var recordedCallback; - var closed = true; // Start out closed, set false on second openDialog. - function close() { - closed = true; - } - // First openDialog should save callback. - cm.openDialog = function(template, callback, options) { - recordedCallback = callback; - } - // Do first openDialog. - helpers.doKeys(':'); - // Second openDialog should save keyDown handler. - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - closed = false; - }; - // Return the command to Vim and trigger second openDialog. - recordedCallback(command); - // The event should really use keyCode, but here just mock it out and use - // key and replace keyName to just return key. - CodeMirror.keyName = function (e) { return e.key; } - keys = keys.toUpperCase(); - for (var i = 0; i < keys.length; i++) { - is(!closed); - onKeyDown({ key: keys.charAt(i) }, '', close); - } - try { - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(finalPos); - is(closed); - } catch(e) { - throw e - } finally { - // Restore overriden functions. - CodeMirror.keyName = savedKeyName; - cm.openDialog = savedOpenDialog; - } - }, { value: initialValue }); -}; -testSubstituteConfirm('ex_substitute_confirm_emptydoc', - '%s/x/b/c', '', '', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_nomatch', - '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_accept', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_random_keys', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_some', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_accept_then_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_quit', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_last', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_oneline', - '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_range_accept', - '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_some', - '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_all', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_last', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); -//:noh should clear highlighting of search-results but allow to resume search through n -testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.doEx('noh'); - eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); -}, { value: 'match nope match \n nope Match' }); -testVim('set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - CodeMirror.Vim.setOption('testoption', '5'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', false); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - helpers.doEx('set testoption=22'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set notestoption'); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set non-string. - CodeMirror.Vim.setOption('testoption', true); - fail(); - } catch (expected) {}; - try { - // Test fail to set 'notestoption' - CodeMirror.Vim.setOption('notestoption', 'b'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', 'c'); - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set 'notestoption' - helpers.doEx('set notestoption=b'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set testoption=c') - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -// TODO: Reset key maps after each test. -testVim('ex_map_key2key', function(cm, vim, helpers) { - helpers.doEx('map a x'); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_unmap_key2key', function(cm, vim, helpers) { - helpers.doEx('unmap a'); - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { - try { - helpers.doEx('unmap a'); - fail(); - } catch (expected) {} - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { - helpers.doEx('map ; :'); - var dialogOpened = false; - cm.openDialog = function() { - dialogOpened = true; - } - helpers.doKeys(';'); - eq(dialogOpened, true); -}); -testVim('ex_map_ex2key:', function(cm, vim, helpers) { - helpers.doEx('map :del x'); - helpers.doEx('del'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_map_ex2ex', function(cm, vim, helpers) { - helpers.doEx('map :del :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doEx('del'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2ex', function(cm, vim, helpers) { - helpers.doEx('map a :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doKeys('a'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { - CodeMirror.Vim.map('b', ':w', 'visual'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Mapping should not work in normal mode. - helpers.doKeys('b'); - eq(written, false); - // Mapping should work in visual mode. - helpers.doKeys('v', 'b'); - eq(written, true); - eq(actualCm, cm); - - CodeMirror.commands.save = tmp; -}); -testVim('ex_imap', function(cm, vim, helpers) { - CodeMirror.Vim.map('jk', '', 'insert'); - helpers.doKeys('i'); - is(vim.insertMode); - helpers.doKeys('j', 'k'); - is(!vim.insertMode); -}) - -// Testing registration of functions as ex-commands and mapping to -keys -testVim('ex_api_test', function(cm, vim, helpers) { - var res=false; - var val='from'; - CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ - if(params.args)val=params.args[0]; - else res=true; - }); - helpers.doEx(':ext to'); - eq(val,'to','Defining ex-command failed'); - CodeMirror.Vim.map('',':ext'); - helpers.doKeys('',''); - is(res,'Mapping to key failed'); -}); -// For now, this test needs to be last because it messes up : for future tests. -testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { - helpers.doEx('map : x'); - helpers.doKeys(':'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); - -// Test event handlers -testVim('beforeSelectionChange', function(cm, vim, helpers) { - cm.setCursor(0, 100); - eqPos(cm.getCursor('head'), cm.getCursor('anchor')); -}, { value: 'abc' }); - - diff --git a/public/js/lib/codemirror/theme/3024-day.css b/public/js/lib/codemirror/theme/3024-day.css deleted file mode 100644 index 3c01c2bf58..0000000000 --- a/public/js/lib/codemirror/theme/3024-day.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: 3024 day - Author: Jan T. Sott (http://github.com/idleberg) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;} -.cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;} - -.cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;} -.cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; } -.cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; } -.cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;} - -.cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;} - -.cm-s-3024-day span.cm-comment {color: #cdab53;} -.cm-s-3024-day span.cm-atom {color: #a16a94;} -.cm-s-3024-day span.cm-number {color: #a16a94;} - -.cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute {color: #01a252;} -.cm-s-3024-day span.cm-keyword {color: #db2d20;} -.cm-s-3024-day span.cm-string {color: #fded02;} - -.cm-s-3024-day span.cm-variable {color: #01a252;} -.cm-s-3024-day span.cm-variable-2 {color: #01a0e4;} -.cm-s-3024-day span.cm-def {color: #e8bbd0;} -.cm-s-3024-day span.cm-bracket {color: #3a3432;} -.cm-s-3024-day span.cm-tag {color: #db2d20;} -.cm-s-3024-day span.cm-link {color: #a16a94;} -.cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;} - -.cm-s-3024-day .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important;} diff --git a/public/js/lib/codemirror/theme/3024-night.css b/public/js/lib/codemirror/theme/3024-night.css deleted file mode 100644 index 631757fc47..0000000000 --- a/public/js/lib/codemirror/theme/3024-night.css +++ /dev/null @@ -1,37 +0,0 @@ -/* - - Name: 3024 night - Author: Jan T. Sott (http://github.com/idleberg) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;} -.cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;} -.cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;} -.cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; } -.cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; } -.cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;} - -.cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;} - -.cm-s-3024-night span.cm-comment {color: #cdab53;} -.cm-s-3024-night span.cm-atom {color: #a16a94;} -.cm-s-3024-night span.cm-number {color: #a16a94;} - -.cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute {color: #01a252;} -.cm-s-3024-night span.cm-keyword {color: #db2d20;} -.cm-s-3024-night span.cm-string {color: #fded02;} - -.cm-s-3024-night span.cm-variable {color: #01a252;} -.cm-s-3024-night span.cm-variable-2 {color: #01a0e4;} -.cm-s-3024-night span.cm-def {color: #e8bbd0;} -.cm-s-3024-night span.cm-bracket {color: #d6d5d4;} -.cm-s-3024-night span.cm-tag {color: #db2d20;} -.cm-s-3024-night span.cm-link {color: #a16a94;} -.cm-s-3024-night span.cm-error {background: #db2d20; color: #807d7c;} - -.cm-s-3024-night .CodeMirror-activeline-background {background: #2F2F2F !important;} -.cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/ambiance-mobile.css b/public/js/lib/codemirror/theme/ambiance-mobile.css deleted file mode 100644 index 88d332e1a7..0000000000 --- a/public/js/lib/codemirror/theme/ambiance-mobile.css +++ /dev/null @@ -1,5 +0,0 @@ -.cm-s-ambiance.CodeMirror { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} diff --git a/public/js/lib/codemirror/theme/ambiance.css b/public/js/lib/codemirror/theme/ambiance.css deleted file mode 100644 index c844566eac..0000000000 --- a/public/js/lib/codemirror/theme/ambiance.css +++ /dev/null @@ -1,77 +0,0 @@ -/* ambiance theme for codemirror */ - -/* Color scheme */ - -.cm-s-ambiance .cm-keyword { color: #cda869; } -.cm-s-ambiance .cm-atom { color: #CF7EA9; } -.cm-s-ambiance .cm-number { color: #78CF8A; } -.cm-s-ambiance .cm-def { color: #aac6e3; } -.cm-s-ambiance .cm-variable { color: #ffb795; } -.cm-s-ambiance .cm-variable-2 { color: #eed1b3; } -.cm-s-ambiance .cm-variable-3 { color: #faded3; } -.cm-s-ambiance .cm-property { color: #eed1b3; } -.cm-s-ambiance .cm-operator {color: #fa8d6a;} -.cm-s-ambiance .cm-comment { color: #555; font-style:italic; } -.cm-s-ambiance .cm-string { color: #8f9d6a; } -.cm-s-ambiance .cm-string-2 { color: #9d937c; } -.cm-s-ambiance .cm-meta { color: #D2A8A1; } -.cm-s-ambiance .cm-qualifier { color: yellow; } -.cm-s-ambiance .cm-builtin { color: #9999cc; } -.cm-s-ambiance .cm-bracket { color: #24C2C7; } -.cm-s-ambiance .cm-tag { color: #fee4ff } -.cm-s-ambiance .cm-attribute { color: #9B859D; } -.cm-s-ambiance .cm-header {color: blue;} -.cm-s-ambiance .cm-quote { color: #24C2C7; } -.cm-s-ambiance .cm-hr { color: pink; } -.cm-s-ambiance .cm-link { color: #F4C20B; } -.cm-s-ambiance .cm-special { color: #FF9D00; } -.cm-s-ambiance .cm-error { color: #AF2018; } - -.cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; } -.cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; } - -.cm-s-ambiance .CodeMirror-selected { - background: rgba(255, 255, 255, 0.15); -} -.cm-s-ambiance.CodeMirror-focused .CodeMirror-selected { - background: rgba(255, 255, 255, 0.10); -} - -/* Editor styling */ - -.cm-s-ambiance.CodeMirror { - line-height: 1.40em; - color: #E6E1DC; - background-color: #202020; - -webkit-box-shadow: inset 0 0 10px black; - -moz-box-shadow: inset 0 0 10px black; - box-shadow: inset 0 0 10px black; -} - -.cm-s-ambiance .CodeMirror-gutters { - background: #3D3D3D; - border-right: 1px solid #4D4D4D; - box-shadow: 0 10px 20px black; -} - -.cm-s-ambiance .CodeMirror-linenumber { - text-shadow: 0px 1px 1px #4d4d4d; - color: #111; - padding: 0 5px; -} - -.cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; } -.cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; } - -.cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor { - border-left: 1px solid #7991E8; -} - -.cm-s-ambiance .CodeMirror-activeline-background { - background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031); -} - -.cm-s-ambiance.CodeMirror, -.cm-s-ambiance .CodeMirror-gutters { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC"); -} diff --git a/public/js/lib/codemirror/theme/base16-dark.css b/public/js/lib/codemirror/theme/base16-dark.css deleted file mode 100644 index a46abdbbbd..0000000000 --- a/public/js/lib/codemirror/theme/base16-dark.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Name: Base16 Default Dark - Author: Chris Kempson (http://chriskempson.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;} -.cm-s-base16-dark div.CodeMirror-selected {background: #303030 !important;} -.cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;} -.cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; } -.cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; } -.cm-s-base16-dark .CodeMirror-linenumber {color: #505050;} -.cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;} - -.cm-s-base16-dark span.cm-comment {color: #8f5536;} -.cm-s-base16-dark span.cm-atom {color: #aa759f;} -.cm-s-base16-dark span.cm-number {color: #aa759f;} - -.cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute {color: #90a959;} -.cm-s-base16-dark span.cm-keyword {color: #ac4142;} -.cm-s-base16-dark span.cm-string {color: #f4bf75;} - -.cm-s-base16-dark span.cm-variable {color: #90a959;} -.cm-s-base16-dark span.cm-variable-2 {color: #6a9fb5;} -.cm-s-base16-dark span.cm-def {color: #d28445;} -.cm-s-base16-dark span.cm-bracket {color: #e0e0e0;} -.cm-s-base16-dark span.cm-tag {color: #ac4142;} -.cm-s-base16-dark span.cm-link {color: #aa759f;} -.cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;} - -.cm-s-base16-dark .CodeMirror-activeline-background {background: #202020 !important;} -.cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/base16-light.css b/public/js/lib/codemirror/theme/base16-light.css deleted file mode 100644 index 12ff2eb06f..0000000000 --- a/public/js/lib/codemirror/theme/base16-light.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Name: Base16 Default Light - Author: Chris Kempson (http://chriskempson.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;} -.cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;} -.cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;} -.cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; } -.cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; } -.cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;} -.cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;} - -.cm-s-base16-light span.cm-comment {color: #8f5536;} -.cm-s-base16-light span.cm-atom {color: #aa759f;} -.cm-s-base16-light span.cm-number {color: #aa759f;} - -.cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute {color: #90a959;} -.cm-s-base16-light span.cm-keyword {color: #ac4142;} -.cm-s-base16-light span.cm-string {color: #f4bf75;} - -.cm-s-base16-light span.cm-variable {color: #90a959;} -.cm-s-base16-light span.cm-variable-2 {color: #6a9fb5;} -.cm-s-base16-light span.cm-def {color: #d28445;} -.cm-s-base16-light span.cm-bracket {color: #202020;} -.cm-s-base16-light span.cm-tag {color: #ac4142;} -.cm-s-base16-light span.cm-link {color: #aa759f;} -.cm-s-base16-light span.cm-error {background: #ac4142; color: #505050;} - -.cm-s-base16-light .CodeMirror-activeline-background {background: #DDDCDC !important;} -.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/blackboard.css b/public/js/lib/codemirror/theme/blackboard.css deleted file mode 100644 index d7a2dc9695..0000000000 --- a/public/js/lib/codemirror/theme/blackboard.css +++ /dev/null @@ -1,30 +0,0 @@ -/* Port of TextMate's Blackboard theme */ - -.cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; } -.cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; } -.cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; } -.cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; } -.cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; } -.cm-s-blackboard .CodeMirror-linenumber { color: #888; } -.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; } - -.cm-s-blackboard .cm-keyword { color: #FBDE2D; } -.cm-s-blackboard .cm-atom { color: #D8FA3C; } -.cm-s-blackboard .cm-number { color: #D8FA3C; } -.cm-s-blackboard .cm-def { color: #8DA6CE; } -.cm-s-blackboard .cm-variable { color: #FF6400; } -.cm-s-blackboard .cm-operator { color: #FBDE2D;} -.cm-s-blackboard .cm-comment { color: #AEAEAE; } -.cm-s-blackboard .cm-string { color: #61CE3C; } -.cm-s-blackboard .cm-string-2 { color: #61CE3C; } -.cm-s-blackboard .cm-meta { color: #D8FA3C; } -.cm-s-blackboard .cm-builtin { color: #8DA6CE; } -.cm-s-blackboard .cm-tag { color: #8DA6CE; } -.cm-s-blackboard .cm-attribute { color: #8DA6CE; } -.cm-s-blackboard .cm-header { color: #FF6400; } -.cm-s-blackboard .cm-hr { color: #AEAEAE; } -.cm-s-blackboard .cm-link { color: #8DA6CE; } -.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; } - -.cm-s-blackboard .CodeMirror-activeline-background {background: #3C3636 !important;} -.cm-s-blackboard .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important} \ No newline at end of file diff --git a/public/js/lib/codemirror/theme/cobalt.css b/public/js/lib/codemirror/theme/cobalt.css deleted file mode 100644 index 47440531a0..0000000000 --- a/public/js/lib/codemirror/theme/cobalt.css +++ /dev/null @@ -1,23 +0,0 @@ -.cm-s-cobalt.CodeMirror { background: #002240; color: white; } -.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; } -.cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; } -.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-cobalt span.cm-comment { color: #08f; } -.cm-s-cobalt span.cm-atom { color: #845dc4; } -.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; } -.cm-s-cobalt span.cm-keyword { color: #ffee80; } -.cm-s-cobalt span.cm-string { color: #3ad900; } -.cm-s-cobalt span.cm-meta { color: #ff9d00; } -.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; } -.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; } -.cm-s-cobalt span.cm-bracket { color: #d8d8d8; } -.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; } -.cm-s-cobalt span.cm-link { color: #845dc4; } -.cm-s-cobalt span.cm-error { color: #9d1e15; } - -.cm-s-cobalt .CodeMirror-activeline-background {background: #002D57 !important;} -.cm-s-cobalt .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important} diff --git a/public/js/lib/codemirror/theme/eclipse.css b/public/js/lib/codemirror/theme/eclipse.css deleted file mode 100644 index 317218e3d2..0000000000 --- a/public/js/lib/codemirror/theme/eclipse.css +++ /dev/null @@ -1,23 +0,0 @@ -.cm-s-eclipse span.cm-meta {color: #FF1717;} -.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; } -.cm-s-eclipse span.cm-atom {color: #219;} -.cm-s-eclipse span.cm-number {color: #164;} -.cm-s-eclipse span.cm-def {color: #00f;} -.cm-s-eclipse span.cm-variable {color: black;} -.cm-s-eclipse span.cm-variable-2 {color: #0000C0;} -.cm-s-eclipse span.cm-variable-3 {color: #0000C0;} -.cm-s-eclipse span.cm-property {color: black;} -.cm-s-eclipse span.cm-operator {color: black;} -.cm-s-eclipse span.cm-comment {color: #3F7F5F;} -.cm-s-eclipse span.cm-string {color: #2A00FF;} -.cm-s-eclipse span.cm-string-2 {color: #f50;} -.cm-s-eclipse span.cm-qualifier {color: #555;} -.cm-s-eclipse span.cm-builtin {color: #30a;} -.cm-s-eclipse span.cm-bracket {color: #cc7;} -.cm-s-eclipse span.cm-tag {color: #170;} -.cm-s-eclipse span.cm-attribute {color: #00c;} -.cm-s-eclipse span.cm-link {color: #219;} -.cm-s-eclipse span.cm-error {color: #f00;} - -.cm-s-eclipse .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-eclipse .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} diff --git a/public/js/lib/codemirror/theme/elegant.css b/public/js/lib/codemirror/theme/elegant.css deleted file mode 100644 index dd7df7b73c..0000000000 --- a/public/js/lib/codemirror/theme/elegant.css +++ /dev/null @@ -1,13 +0,0 @@ -.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;} -.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;} -.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;} -.cm-s-elegant span.cm-variable {color: black;} -.cm-s-elegant span.cm-variable-2 {color: #b11;} -.cm-s-elegant span.cm-qualifier {color: #555;} -.cm-s-elegant span.cm-keyword {color: #730;} -.cm-s-elegant span.cm-builtin {color: #30a;} -.cm-s-elegant span.cm-link {color: #762;} -.cm-s-elegant span.cm-error {background-color: #fdd;} - -.cm-s-elegant .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-elegant .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} diff --git a/public/js/lib/codemirror/theme/erlang-dark.css b/public/js/lib/codemirror/theme/erlang-dark.css deleted file mode 100644 index ff47d7f8de..0000000000 --- a/public/js/lib/codemirror/theme/erlang-dark.css +++ /dev/null @@ -1,32 +0,0 @@ -.cm-s-erlang-dark.CodeMirror { background: #002240; color: white; } -.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; } -.cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-erlang-dark .CodeMirror-guttermarker { color: white; } -.cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-erlang-dark span.cm-atom { color: #f133f1; } -.cm-s-erlang-dark span.cm-attribute { color: #ff80e1; } -.cm-s-erlang-dark span.cm-bracket { color: #ff9d00; } -.cm-s-erlang-dark span.cm-builtin { color: #eaa; } -.cm-s-erlang-dark span.cm-comment { color: #77f; } -.cm-s-erlang-dark span.cm-def { color: #e7a; } -.cm-s-erlang-dark span.cm-keyword { color: #ffee80; } -.cm-s-erlang-dark span.cm-meta { color: #50fefe; } -.cm-s-erlang-dark span.cm-number { color: #ffd0d0; } -.cm-s-erlang-dark span.cm-operator { color: #d55; } -.cm-s-erlang-dark span.cm-property { color: #ccc; } -.cm-s-erlang-dark span.cm-qualifier { color: #ccc; } -.cm-s-erlang-dark span.cm-quote { color: #ccc; } -.cm-s-erlang-dark span.cm-special { color: #ffbbbb; } -.cm-s-erlang-dark span.cm-string { color: #3ad900; } -.cm-s-erlang-dark span.cm-string-2 { color: #ccc; } -.cm-s-erlang-dark span.cm-tag { color: #9effff; } -.cm-s-erlang-dark span.cm-variable { color: #50fe50; } -.cm-s-erlang-dark span.cm-variable-2 { color: #e0e; } -.cm-s-erlang-dark span.cm-variable-3 { color: #ccc; } -.cm-s-erlang-dark span.cm-error { color: #9d1e15; } - -.cm-s-erlang-dark .CodeMirror-activeline-background {background: #013461 !important;} -.cm-s-erlang-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/public/js/lib/codemirror/theme/lesser-dark.css b/public/js/lib/codemirror/theme/lesser-dark.css deleted file mode 100644 index a782474739..0000000000 --- a/public/js/lib/codemirror/theme/lesser-dark.css +++ /dev/null @@ -1,45 +0,0 @@ -/* -http://lesscss.org/ dark theme -Ported to CodeMirror by Peter Kroon -*/ -.cm-s-lesser-dark { - line-height: 1.3em; -} -.cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; } -.cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/ -.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; } -.cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/ - -.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/ - -.cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; } -.cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; } -.cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-lesser-dark .CodeMirror-linenumber { color: #777; } - -.cm-s-lesser-dark span.cm-keyword { color: #599eff; } -.cm-s-lesser-dark span.cm-atom { color: #C2B470; } -.cm-s-lesser-dark span.cm-number { color: #B35E4D; } -.cm-s-lesser-dark span.cm-def {color: white;} -.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; } -.cm-s-lesser-dark span.cm-variable-2 { color: #669199; } -.cm-s-lesser-dark span.cm-variable-3 { color: white; } -.cm-s-lesser-dark span.cm-property {color: #92A75C;} -.cm-s-lesser-dark span.cm-operator {color: #92A75C;} -.cm-s-lesser-dark span.cm-comment { color: #666; } -.cm-s-lesser-dark span.cm-string { color: #BCD279; } -.cm-s-lesser-dark span.cm-string-2 {color: #f50;} -.cm-s-lesser-dark span.cm-meta { color: #738C73; } -.cm-s-lesser-dark span.cm-qualifier {color: #555;} -.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; } -.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; } -.cm-s-lesser-dark span.cm-tag { color: #669199; } -.cm-s-lesser-dark span.cm-attribute {color: #00c;} -.cm-s-lesser-dark span.cm-header {color: #a0a;} -.cm-s-lesser-dark span.cm-quote {color: #090;} -.cm-s-lesser-dark span.cm-hr {color: #999;} -.cm-s-lesser-dark span.cm-link {color: #00c;} -.cm-s-lesser-dark span.cm-error { color: #9d1e15; } - -.cm-s-lesser-dark .CodeMirror-activeline-background {background: #3C3A3A !important;} -.cm-s-lesser-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/public/js/lib/codemirror/theme/mbo.css b/public/js/lib/codemirror/theme/mbo.css deleted file mode 100644 index 0ad6360b50..0000000000 --- a/public/js/lib/codemirror/theme/mbo.css +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************/ -/* Based on mbonaci's Brackets mbo theme */ -/* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */ -/* Create your own: http://tmtheme-editor.herokuapp.com */ -/****************************************************************/ - -.cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffec;} -.cm-s-mbo div.CodeMirror-selected {background: #716C62 !important;} -.cm-s-mbo .CodeMirror-gutters {background: #4e4e4e; border-right: 0px;} -.cm-s-mbo .CodeMirror-guttermarker { color: white; } -.cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; } -.cm-s-mbo .CodeMirror-linenumber {color: #dadada;} -.cm-s-mbo .CodeMirror-cursor {border-left: 1px solid #ffffec !important;} - -.cm-s-mbo span.cm-comment {color: #95958a;} -.cm-s-mbo span.cm-atom {color: #00a8c6;} -.cm-s-mbo span.cm-number {color: #00a8c6;} - -.cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute {color: #9ddfe9;} -.cm-s-mbo span.cm-keyword {color: #ffb928;} -.cm-s-mbo span.cm-string {color: #ffcf6c;} -.cm-s-mbo span.cm-string.cm-property {color: #ffffec;} - -.cm-s-mbo span.cm-variable {color: #ffffec;} -.cm-s-mbo span.cm-variable-2 {color: #00a8c6;} -.cm-s-mbo span.cm-def {color: #ffffec;} -.cm-s-mbo span.cm-bracket {color: #fffffc; font-weight: bold;} -.cm-s-mbo span.cm-tag {color: #9ddfe9;} -.cm-s-mbo span.cm-link {color: #f54b07;} -.cm-s-mbo span.cm-error {border-bottom: #636363; color: #ffffec;} -.cm-s-mbo span.cm-qualifier {color: #ffffec;} - -.cm-s-mbo .CodeMirror-activeline-background {background: #494b41 !important;} -.cm-s-mbo .CodeMirror-matchingbracket {color: #222 !important;} -.cm-s-mbo .CodeMirror-matchingtag {background: rgba(255, 255, 255, .37);} diff --git a/public/js/lib/codemirror/theme/mdn-like.css b/public/js/lib/codemirror/theme/mdn-like.css deleted file mode 100644 index 81b21772d2..0000000000 --- a/public/js/lib/codemirror/theme/mdn-like.css +++ /dev/null @@ -1,44 +0,0 @@ -/* - MDN-LIKE Theme - Mozilla - Ported to CodeMirror by Peter Kroon - Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues - GitHub: @peterkroon - - The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation - -*/ -.cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; } -.cm-s-mdn-like .CodeMirror-selected { background: #cfc !important; } - -.cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; } -.cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; margin-left: 3px; } -div.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; } - -.cm-s-mdn-like .cm-keyword { color: #6262FF; } -.cm-s-mdn-like .cm-atom { color: #F90; } -.cm-s-mdn-like .cm-number { color: #ca7841; } -.cm-s-mdn-like .cm-def { color: #8DA6CE; } -.cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; } -.cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; } - -.cm-s-mdn-like .cm-variable { color: #07a; } -.cm-s-mdn-like .cm-property { color: #905; } -.cm-s-mdn-like .cm-qualifier { color: #690; } - -.cm-s-mdn-like .cm-operator { color: #cda869; } -.cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; } -.cm-s-mdn-like .cm-string { color:#07a; font-style:italic; } -.cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/ -.cm-s-mdn-like .cm-meta { color: #000; } /*?*/ -.cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/ -.cm-s-mdn-like .cm-tag { color: #997643; } -.cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/ -.cm-s-mdn-like .cm-header { color: #FF6400; } -.cm-s-mdn-like .cm-hr { color: #AEAEAE; } -.cm-s-mdn-like .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } -.cm-s-mdn-like .cm-error { border-bottom: 1px solid red; } - -div.cm-s-mdn-like .CodeMirror-activeline-background {background: #efefff;} -div.cm-s-mdn-like span.CodeMirror-matchingbracket {outline:1px solid grey; color: inherit;} - -.cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAAAyCAYAAAAp8UeFAAAHvklEQVR42s2b63bcNgyEQZCSHCdt2vd/0tWF7I+Q6XgMXiTtuvU5Pl57ZQKkKHzEAOtF5KeIJBGJ8uvL599FRFREZhFx8DeXv8trn68RuGaC8TRfo3SNp9dlDDHedyLyTUTeRWStXKPZrjtpZxaRw5hPqozRs1N8/enzIiQRWcCgy4MUA0f+XWliDhyL8Lfyvx7ei/Ae3iQFHyw7U/59pQVIMEEPEz0G7XiwdRjzSfC3UTtz9vchIntxvry5iMgfIhJoEflOz2CQr3F5h/HfeFe+GTdLaKcu9L8LTeQb/R/7GgbsfKedyNdoHsN31uRPWrfZ5wsj/NzzRQHuToIdU3ahwnsKPxXCjJITuOsi7XLc7SG/v5GdALs7wf8JjTFiB5+QvTEfRyGOfX3Lrx8wxyQi3sNq46O7QahQiCsRFgqddjBouVEHOKDgXAQHD9gJCr5sMKkEdjwsarG/ww3BMHBU7OBjXnzdyY7SfCxf5/z6ATccrwlKuwC/jhznnPF4CgVzhhVf4xp2EixcBActO75iZ8/fM9zAs2OMzKdslgXWJ9XG8PQoOAMA5fGcsvORgv0doBXyHrCwfLJAOwo71QLNkb8n2Pl6EWiR7OCibtkPaz4Kc/0NNAze2gju3zOwekALDaCFPI5vjPFmgGY5AZqyGEvH1x7QfIb8YtxMnA/b+QQ0aQDAwc6JMFg8CbQZ4qoYEEHbRwNojuK3EHwd7VALSgq+MNDKzfT58T8qdpADrgW0GmgcAS1lhzztJmkAzcPNOQbsWEALBDSlMKUG0Eq4CLAQWvEVQ9WU57gZJwZtgPO3r9oBTQ9WO8TjqXINx8R0EYpiZEUWOF3FxkbJkgU9B2f41YBrIj5ZfsQa0M5kTgiAAqM3ShXLgu8XMqcrQBvJ0CL5pnTsfMB13oB8athpAq2XOQmcGmoACCLydx7nToa23ATaSIY2ichfOdPTGxlasXMLaL0MLZAOwAKIM+y8CmicobGdCcbbK9DzN+yYGVoNNI5iUKTMyYOjPse4A8SM1MmcXgU0toOq1yO/v8FOxlASyc7TgeYaAMBJHcY1CcCwGI/TK4AmDbDyKYBBtFUkRwto8gygiQEaByFgJ00BH2M8JWwQS1nafDXQCidWyOI8AcjDCSjCLk8ngObuAm3JAHAdubAmOaK06V8MNEsKPJOhobSprwQa6gD7DclRQdqcwL4zxqgBrQcabUiBLclRDKAlWp+etPkBaNMA0AKlrHwTdEByZAA4GM+SNluSY6wAzcMNewxmgig5Ks0nkrSpBvSaQHMdKTBAnLojOdYyGpQ254602ZILPdTD1hdlggdIm74jbTp8vDwF5ZYUeLWGJpWsh6XNyXgcYwVoJQTEhhTYkxzZjiU5npU2TaB979TQehlaAVq4kaGpiPwwwLkYUuBbQwocyQTv1tA0+1UFWoJF3iv1oq+qoSk8EQdJmwHkziIF7oOZk14EGitibAdjLYYK78H5vZOhtWpoI0ATGHs0Q8OMb4Ey+2bU2UYztCtA0wFAs7TplGLRVQCcqaFdGSPCeTI1QNIC52iWNzof6Uib7xjEp07mNNoUYmVosVItHrHzRlLgBn9LFyRHaQCtVUMbtTNhoXWiTOO9k/V8BdAc1Oq0ArSQs6/5SU0hckNy9NnXqQY0PGYo5dWJ7nINaN6o958FWin27aBaWRka1r5myvLOAm0j30eBJqCxHLReVclxhxOEN2JfDWjxBtAC7MIH1fVaGdoOp4qJYDgKtKPSFNID2gSnGldrCqkFZ+5UeQXQBIRrSwocbdZYQT/2LwRahBPBXoHrB8nxaGROST62DKUbQOMMzZIC9abkuELfQzQALWTnDNAm8KHWFOJgJ5+SHIvTPcmx1xQyZRhNL5Qci689aXMEaN/uNIWkEwDAvFpOZmgsBaaGnbs1NPa1Jm32gBZAIh1pCtG7TSH4aE0y1uVY4uqoFPisGlpP2rSA5qTecWn5agK6BzSpgAyD+wFaqhnYoSZ1Vwr8CmlTQbrcO3ZaX0NAEyMbYaAlyquFoLKK3SPby9CeVUPThrSJmkCAE0CrKUQadi4DrdSlWhmah0YL9z9vClH59YGbHx1J8VZTyAjQepJjmXwAKTDQI3omc3p1U4gDUf6RfcdYfrUp5ClAi2J3Ba6UOXGo+K+bQrjjssitG2SJzshaLwMtXgRagUNpYYoVkMSBLM+9GGiJZMvduG6DRZ4qc04DMPtQQxOjEtACmhO7K1AbNbQDEggZyJwscFpAGwENhoBeUwh3bWolhe8BTYVKxQEWrSUn/uhcM5KhvUu/+eQu0Lzhi+VrK0PrZZNDQKs9cpYUuFYgMVpD4/NxenJTiMCNqdUEUf1qZWjppLT5qSkkUZbCwkbZMSuVnu80hfSkzRbQeqCZSAh6huR4VtoM2gHAlLf72smuWgE+VV7XpE25Ab2WFDgyhnSuKbs4GuGzCjR+tIoUuMFg3kgcWKLTwRqanJQ2W00hAsenfaApRC42hbCvK1SlE0HtE9BGgneJO+ELamitD1YjjOYnNYVcraGhtKkW0EqVVeDx733I2NH581k1NNxNLG0i0IJ8/NjVaOZ0tYZ2Vtr0Xv7tPV3hkWp9EFkgS/J0vosngTaSoaG06WHi+xObQkaAdlbanP8B2+2l0f90LmUAAAAASUVORK5CYII=); } diff --git a/public/js/lib/codemirror/theme/midnight.css b/public/js/lib/codemirror/theme/midnight.css deleted file mode 100644 index 4567d29399..0000000000 --- a/public/js/lib/codemirror/theme/midnight.css +++ /dev/null @@ -1,45 +0,0 @@ -/* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */ - -/**/ -.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; } -.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; } - -/**/ -.cm-s-midnight .CodeMirror-activeline-background {background: #253540 !important;} - -.cm-s-midnight.CodeMirror { - background: #0F192A; - color: #D1EDFF; -} - -.cm-s-midnight.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;} - -.cm-s-midnight div.CodeMirror-selected {background: #314D67 !important;} -.cm-s-midnight .CodeMirror-gutters {background: #0F192A; border-right: 1px solid;} -.cm-s-midnight .CodeMirror-guttermarker { color: white; } -.cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-midnight .CodeMirror-linenumber {color: #D0D0D0;} -.cm-s-midnight .CodeMirror-cursor { - border-left: 1px solid #F8F8F0 !important; -} - -.cm-s-midnight span.cm-comment {color: #428BDD;} -.cm-s-midnight span.cm-atom {color: #AE81FF;} -.cm-s-midnight span.cm-number {color: #D1EDFF;} - -.cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute {color: #A6E22E;} -.cm-s-midnight span.cm-keyword {color: #E83737;} -.cm-s-midnight span.cm-string {color: #1DC116;} - -.cm-s-midnight span.cm-variable {color: #FFAA3E;} -.cm-s-midnight span.cm-variable-2 {color: #FFAA3E;} -.cm-s-midnight span.cm-def {color: #4DD;} -.cm-s-midnight span.cm-bracket {color: #D1EDFF;} -.cm-s-midnight span.cm-tag {color: #449;} -.cm-s-midnight span.cm-link {color: #AE81FF;} -.cm-s-midnight span.cm-error {background: #F92672; color: #F8F8F0;} - -.cm-s-midnight .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/public/js/lib/codemirror/theme/monokai.css b/public/js/lib/codemirror/theme/monokai.css deleted file mode 100644 index 8ac80e7ac2..0000000000 --- a/public/js/lib/codemirror/theme/monokai.css +++ /dev/null @@ -1,31 +0,0 @@ -/* Based on Sublime Text's Monokai theme */ - -.cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2; height: auto;} -.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;} -.cm-s-monokai .CodeMirror-gutters {background: #272822; border-right: 0px;} -.cm-s-monokai .CodeMirror-guttermarker { color: white; } -.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-monokai .CodeMirror-linenumber {color: #d0d0d0;} -.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;} - -.cm-s-monokai span.cm-comment {color: #75715e;} -.cm-s-monokai span.cm-atom {color: #ae81ff;} -.cm-s-monokai span.cm-number {color: #ae81ff;} - -.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;} -.cm-s-monokai span.cm-keyword {color: #f92672;} -.cm-s-monokai span.cm-string {color: #e6db74;} - -.cm-s-monokai span.cm-variable {color: #a6e22e;} -.cm-s-monokai span.cm-variable-2 {color: #9effff;} -.cm-s-monokai span.cm-def {color: #fd971f;} -.cm-s-monokai span.cm-bracket {color: #f8f8f2;} -.cm-s-monokai span.cm-tag {color: #f92672;} -.cm-s-monokai span.cm-link {color: #ae81ff;} -.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;} - -.cm-s-monokai .CodeMirror-activeline-background {background: #373831 !important;} -.cm-s-monokai .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/public/js/lib/codemirror/theme/neat.css b/public/js/lib/codemirror/theme/neat.css deleted file mode 100644 index 115083b812..0000000000 --- a/public/js/lib/codemirror/theme/neat.css +++ /dev/null @@ -1,12 +0,0 @@ -.cm-s-neat span.cm-comment { color: #a86; } -.cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; } -.cm-s-neat span.cm-string { color: #a22; } -.cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; } -.cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; } -.cm-s-neat span.cm-variable { color: black; } -.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; } -.cm-s-neat span.cm-meta {color: #555;} -.cm-s-neat span.cm-link { color: #3a3; } - -.cm-s-neat .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-neat .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} diff --git a/public/js/lib/codemirror/theme/neo.css b/public/js/lib/codemirror/theme/neo.css deleted file mode 100644 index cecaaf2801..0000000000 --- a/public/js/lib/codemirror/theme/neo.css +++ /dev/null @@ -1,43 +0,0 @@ -/* neo theme for codemirror */ - -/* Color scheme */ - -.cm-s-neo.CodeMirror { - background-color:#ffffff; - color:#2e383c; - line-height:1.4375; -} -.cm-s-neo .cm-comment {color:#75787b} -.cm-s-neo .cm-keyword, .cm-s-neo .cm-property {color:#1d75b3} -.cm-s-neo .cm-atom,.cm-s-neo .cm-number {color:#75438a} -.cm-s-neo .cm-node,.cm-s-neo .cm-tag {color:#9c3328} -.cm-s-neo .cm-string {color:#b35e14} -.cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier {color:#047d65} - - -/* Editor styling */ - -.cm-s-neo pre { - padding:0; -} - -.cm-s-neo .CodeMirror-gutters { - border:none; - border-right:10px solid transparent; - background-color:transparent; -} - -.cm-s-neo .CodeMirror-linenumber { - padding:0; - color:#e0e2e5; -} - -.cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; } -.cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; } - -.cm-s-neo div.CodeMirror-cursor { - width: auto; - border: 0; - background: rgba(155,157,162,0.37); - z-index: 1; -} diff --git a/public/js/lib/codemirror/theme/night.css b/public/js/lib/codemirror/theme/night.css deleted file mode 100644 index a0bf8cfa78..0000000000 --- a/public/js/lib/codemirror/theme/night.css +++ /dev/null @@ -1,26 +0,0 @@ -/* Loosely based on the Midnight Textmate theme */ - -.cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; } -.cm-s-night div.CodeMirror-selected { background: #447 !important; } -.cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-night .CodeMirror-guttermarker { color: white; } -.cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; } -.cm-s-night .CodeMirror-linenumber { color: #f8f8f8; } -.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-night span.cm-comment { color: #6900a1; } -.cm-s-night span.cm-atom { color: #845dc4; } -.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; } -.cm-s-night span.cm-keyword { color: #599eff; } -.cm-s-night span.cm-string { color: #37f14a; } -.cm-s-night span.cm-meta { color: #7678e2; } -.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; } -.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; } -.cm-s-night span.cm-bracket { color: #8da6ce; } -.cm-s-night span.cm-comment { color: #6900a1; } -.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; } -.cm-s-night span.cm-link { color: #845dc4; } -.cm-s-night span.cm-error { color: #9d1e15; } - -.cm-s-night .CodeMirror-activeline-background {background: #1C005A !important;} -.cm-s-night .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/public/js/lib/codemirror/theme/paraiso-dark.css b/public/js/lib/codemirror/theme/paraiso-dark.css deleted file mode 100644 index 53dcdf7a2a..0000000000 --- a/public/js/lib/codemirror/theme/paraiso-dark.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Name: Paraíso (Dark) - Author: Jan T. Sott - - Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) - -*/ - -.cm-s-paraiso-dark.CodeMirror {background: #2f1e2e; color: #b9b6b0;} -.cm-s-paraiso-dark div.CodeMirror-selected {background: #41323f !important;} -.cm-s-paraiso-dark .CodeMirror-gutters {background: #2f1e2e; border-right: 0px;} -.cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; } -.cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; } -.cm-s-paraiso-dark .CodeMirror-linenumber {color: #776e71;} -.cm-s-paraiso-dark .CodeMirror-cursor {border-left: 1px solid #8d8687 !important;} - -.cm-s-paraiso-dark span.cm-comment {color: #e96ba8;} -.cm-s-paraiso-dark span.cm-atom {color: #815ba4;} -.cm-s-paraiso-dark span.cm-number {color: #815ba4;} - -.cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute {color: #48b685;} -.cm-s-paraiso-dark span.cm-keyword {color: #ef6155;} -.cm-s-paraiso-dark span.cm-string {color: #fec418;} - -.cm-s-paraiso-dark span.cm-variable {color: #48b685;} -.cm-s-paraiso-dark span.cm-variable-2 {color: #06b6ef;} -.cm-s-paraiso-dark span.cm-def {color: #f99b15;} -.cm-s-paraiso-dark span.cm-bracket {color: #b9b6b0;} -.cm-s-paraiso-dark span.cm-tag {color: #ef6155;} -.cm-s-paraiso-dark span.cm-link {color: #815ba4;} -.cm-s-paraiso-dark span.cm-error {background: #ef6155; color: #8d8687;} - -.cm-s-paraiso-dark .CodeMirror-activeline-background {background: #4D344A !important;} -.cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/paraiso-light.css b/public/js/lib/codemirror/theme/paraiso-light.css deleted file mode 100644 index 07ca325978..0000000000 --- a/public/js/lib/codemirror/theme/paraiso-light.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Name: Paraíso (Light) - Author: Jan T. Sott - - Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) - -*/ - -.cm-s-paraiso-light.CodeMirror {background: #e7e9db; color: #41323f;} -.cm-s-paraiso-light div.CodeMirror-selected {background: #b9b6b0 !important;} -.cm-s-paraiso-light .CodeMirror-gutters {background: #e7e9db; border-right: 0px;} -.cm-s-paraiso-light .CodeMirror-guttermarker { color: black; } -.cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; } -.cm-s-paraiso-light .CodeMirror-linenumber {color: #8d8687;} -.cm-s-paraiso-light .CodeMirror-cursor {border-left: 1px solid #776e71 !important;} - -.cm-s-paraiso-light span.cm-comment {color: #e96ba8;} -.cm-s-paraiso-light span.cm-atom {color: #815ba4;} -.cm-s-paraiso-light span.cm-number {color: #815ba4;} - -.cm-s-paraiso-light span.cm-property, .cm-s-paraiso-light span.cm-attribute {color: #48b685;} -.cm-s-paraiso-light span.cm-keyword {color: #ef6155;} -.cm-s-paraiso-light span.cm-string {color: #fec418;} - -.cm-s-paraiso-light span.cm-variable {color: #48b685;} -.cm-s-paraiso-light span.cm-variable-2 {color: #06b6ef;} -.cm-s-paraiso-light span.cm-def {color: #f99b15;} -.cm-s-paraiso-light span.cm-bracket {color: #41323f;} -.cm-s-paraiso-light span.cm-tag {color: #ef6155;} -.cm-s-paraiso-light span.cm-link {color: #815ba4;} -.cm-s-paraiso-light span.cm-error {background: #ef6155; color: #776e71;} - -.cm-s-paraiso-light .CodeMirror-activeline-background {background: #CFD1C4 !important;} -.cm-s-paraiso-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/pastel-on-dark.css b/public/js/lib/codemirror/theme/pastel-on-dark.css deleted file mode 100644 index 7992ac7d2d..0000000000 --- a/public/js/lib/codemirror/theme/pastel-on-dark.css +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Pastel On Dark theme ported from ACE editor - * @license MIT - * @copyright AtomicPages LLC 2014 - * @author Dennis Thompson, AtomicPages LLC - * @version 1.1 - * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme - */ - -.cm-s-pastel-on-dark.CodeMirror { - background: #2c2827; - color: #8F938F; - line-height: 1.5; - font-size: 14px; -} -.cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2) !important; } -.cm-s-pastel-on-dark .CodeMirror-gutters { - background: #34302f; - border-right: 0px; - padding: 0 3px; -} -.cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; } -.cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; } -.cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; } -.cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; } -.cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; } -.cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; } -.cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; } -.cm-s-pastel-on-dark span.cm-property { color: #8F938F; } -.cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; } -.cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; } -.cm-s-pastel-on-dark span.cm-string { color: #66A968; } -.cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; } -.cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; } -.cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; } -.cm-s-pastel-on-dark span.cm-def { color: #757aD8; } -.cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; } -.cm-s-pastel-on-dark span.cm-tag { color: #C1C144; } -.cm-s-pastel-on-dark span.cm-link { color: #ae81ff; } -.cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; } -.cm-s-pastel-on-dark span.cm-error { - background: #757aD8; - color: #f8f8f0; -} -.cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031) !important; } -.cm-s-pastel-on-dark .CodeMirror-matchingbracket { - border: 1px solid rgba(255,255,255,0.25); - color: #8F938F !important; - margin: -1px -1px 0 -1px; -} diff --git a/public/js/lib/codemirror/theme/rubyblue.css b/public/js/lib/codemirror/theme/rubyblue.css deleted file mode 100644 index 5349838940..0000000000 --- a/public/js/lib/codemirror/theme/rubyblue.css +++ /dev/null @@ -1,23 +0,0 @@ -.cm-s-rubyblue.CodeMirror { background: #112435; color: white; } -.cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; } -.cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; } -.cm-s-rubyblue .CodeMirror-guttermarker { color: white; } -.cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; } -.cm-s-rubyblue .CodeMirror-linenumber { color: white; } -.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; } -.cm-s-rubyblue span.cm-atom { color: #F4C20B; } -.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; } -.cm-s-rubyblue span.cm-keyword { color: #F0F; } -.cm-s-rubyblue span.cm-string { color: #F08047; } -.cm-s-rubyblue span.cm-meta { color: #F0F; } -.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; } -.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; } -.cm-s-rubyblue span.cm-bracket { color: #F0F; } -.cm-s-rubyblue span.cm-link { color: #F4C20B; } -.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; } -.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; } -.cm-s-rubyblue span.cm-error { color: #AF2018; } - -.cm-s-rubyblue .CodeMirror-activeline-background {background: #173047 !important;} diff --git a/public/js/lib/codemirror/theme/solarized.css b/public/js/lib/codemirror/theme/solarized.css deleted file mode 100644 index 07ef406804..0000000000 --- a/public/js/lib/codemirror/theme/solarized.css +++ /dev/null @@ -1,165 +0,0 @@ -/* -Solarized theme for code-mirror -http://ethanschoonover.com/solarized -*/ - -/* -Solarized color pallet -http://ethanschoonover.com/solarized/img/solarized-palette.png -*/ - -.solarized.base03 { color: #002b36; } -.solarized.base02 { color: #073642; } -.solarized.base01 { color: #586e75; } -.solarized.base00 { color: #657b83; } -.solarized.base0 { color: #839496; } -.solarized.base1 { color: #93a1a1; } -.solarized.base2 { color: #eee8d5; } -.solarized.base3 { color: #fdf6e3; } -.solarized.solar-yellow { color: #b58900; } -.solarized.solar-orange { color: #cb4b16; } -.solarized.solar-red { color: #dc322f; } -.solarized.solar-magenta { color: #d33682; } -.solarized.solar-violet { color: #6c71c4; } -.solarized.solar-blue { color: #268bd2; } -.solarized.solar-cyan { color: #2aa198; } -.solarized.solar-green { color: #859900; } - -/* Color scheme for code-mirror */ - -.cm-s-solarized { - line-height: 1.45em; - color-profile: sRGB; - rendering-intent: auto; -} -.cm-s-solarized.cm-s-dark { - color: #839496; - background-color: #002b36; - text-shadow: #002b36 0 1px; -} -.cm-s-solarized.cm-s-light { - background-color: #fdf6e3; - color: #657b83; - text-shadow: #eee8d5 0 1px; -} - -.cm-s-solarized .CodeMirror-widget { - text-shadow: none; -} - - -.cm-s-solarized .cm-keyword { color: #cb4b16 } -.cm-s-solarized .cm-atom { color: #d33682; } -.cm-s-solarized .cm-number { color: #d33682; } -.cm-s-solarized .cm-def { color: #2aa198; } - -.cm-s-solarized .cm-variable { color: #268bd2; } -.cm-s-solarized .cm-variable-2 { color: #b58900; } -.cm-s-solarized .cm-variable-3 { color: #6c71c4; } - -.cm-s-solarized .cm-property { color: #2aa198; } -.cm-s-solarized .cm-operator {color: #6c71c4;} - -.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; } - -.cm-s-solarized .cm-string { color: #859900; } -.cm-s-solarized .cm-string-2 { color: #b58900; } - -.cm-s-solarized .cm-meta { color: #859900; } -.cm-s-solarized .cm-qualifier { color: #b58900; } -.cm-s-solarized .cm-builtin { color: #d33682; } -.cm-s-solarized .cm-bracket { color: #cb4b16; } -.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; } -.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; } -.cm-s-solarized .cm-tag { color: #93a1a1 } -.cm-s-solarized .cm-attribute { color: #2aa198; } -.cm-s-solarized .cm-header { color: #586e75; } -.cm-s-solarized .cm-quote { color: #93a1a1; } -.cm-s-solarized .cm-hr { - color: transparent; - border-top: 1px solid #586e75; - display: block; -} -.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; } -.cm-s-solarized .cm-special { color: #6c71c4; } -.cm-s-solarized .cm-em { - color: #999; - text-decoration: underline; - text-decoration-style: dotted; -} -.cm-s-solarized .cm-strong { color: #eee; } -.cm-s-solarized .cm-error, -.cm-s-solarized .cm-invalidchar { - color: #586e75; - border-bottom: 1px dotted #dc322f; -} - -.cm-s-solarized.cm-s-dark .CodeMirror-selected { - background: #073642; -} - -.cm-s-solarized.cm-s-light .CodeMirror-selected { - background: #eee8d5; -} - -/* Editor styling */ - - - -/* Little shadow on the view-port of the buffer view */ -.cm-s-solarized.CodeMirror { - -moz-box-shadow: inset 7px 0 12px -6px #000; - -webkit-box-shadow: inset 7px 0 12px -6px #000; - box-shadow: inset 7px 0 12px -6px #000; -} - -/* Gutter border and some shadow from it */ -.cm-s-solarized .CodeMirror-gutters { - border-right: 1px solid; -} - -/* Gutter colors and line number styling based of color scheme (dark / light) */ - -/* Dark */ -.cm-s-solarized.cm-s-dark .CodeMirror-gutters { - background-color: #002b36; - border-color: #00232c; -} - -.cm-s-solarized.cm-s-dark .CodeMirror-linenumber { - text-shadow: #021014 0 -1px; -} - -/* Light */ -.cm-s-solarized.cm-s-light .CodeMirror-gutters { - background-color: #fdf6e3; - border-color: #eee8d5; -} - -/* Common */ -.cm-s-solarized .CodeMirror-linenumber { - color: #586e75; - padding: 0 5px; -} -.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; } -.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; } -.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; } - -.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text { - color: #586e75; -} - -.cm-s-solarized .CodeMirror-lines .CodeMirror-cursor { - border-left: 1px solid #819090; -} - -/* -Active line. Negative margin compensates left padding of the text in the -view-port -*/ -.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background { - background: rgba(255, 255, 255, 0.10); -} -.cm-s-solarized.cm-s-light .CodeMirror-activeline-background { - background: rgba(0, 0, 0, 0.10); -} diff --git a/public/js/lib/codemirror/theme/the-matrix.css b/public/js/lib/codemirror/theme/the-matrix.css deleted file mode 100644 index 01474ca94d..0000000000 --- a/public/js/lib/codemirror/theme/the-matrix.css +++ /dev/null @@ -1,28 +0,0 @@ -.cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; } -.cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D !important; } -.cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; } -.cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; } -.cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; } -.cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; } -.cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00 !important; } - -.cm-s-the-matrix span.cm-keyword {color: #008803; font-weight: bold;} -.cm-s-the-matrix span.cm-atom {color: #3FF;} -.cm-s-the-matrix span.cm-number {color: #FFB94F;} -.cm-s-the-matrix span.cm-def {color: #99C;} -.cm-s-the-matrix span.cm-variable {color: #F6C;} -.cm-s-the-matrix span.cm-variable-2 {color: #C6F;} -.cm-s-the-matrix span.cm-variable-3 {color: #96F;} -.cm-s-the-matrix span.cm-property {color: #62FFA0;} -.cm-s-the-matrix span.cm-operator {color: #999} -.cm-s-the-matrix span.cm-comment {color: #CCCCCC;} -.cm-s-the-matrix span.cm-string {color: #39C;} -.cm-s-the-matrix span.cm-meta {color: #C9F;} -.cm-s-the-matrix span.cm-qualifier {color: #FFF700;} -.cm-s-the-matrix span.cm-builtin {color: #30a;} -.cm-s-the-matrix span.cm-bracket {color: #cc7;} -.cm-s-the-matrix span.cm-tag {color: #FFBD40;} -.cm-s-the-matrix span.cm-attribute {color: #FFF700;} -.cm-s-the-matrix span.cm-error {color: #FF0000;} - -.cm-s-the-matrix .CodeMirror-activeline-background {background: #040;} diff --git a/public/js/lib/codemirror/theme/tomorrow-night-bright.css b/public/js/lib/codemirror/theme/tomorrow-night-bright.css deleted file mode 100644 index decb82d3e0..0000000000 --- a/public/js/lib/codemirror/theme/tomorrow-night-bright.css +++ /dev/null @@ -1,35 +0,0 @@ -/* - - Name: Tomorrow Night - Bright - Author: Chris Kempson - - Port done by Gerard Braad - -*/ - -.cm-s-tomorrow-night-bright.CodeMirror {background: #000000; color: #eaeaea;} -.cm-s-tomorrow-night-bright div.CodeMirror-selected {background: #424242 !important;} -.cm-s-tomorrow-night-bright .CodeMirror-gutters {background: #000000; border-right: 0px;} -.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; } -.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-tomorrow-night-bright .CodeMirror-linenumber {color: #424242;} -.cm-s-tomorrow-night-bright .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;} - -.cm-s-tomorrow-night-bright span.cm-comment {color: #d27b53;} -.cm-s-tomorrow-night-bright span.cm-atom {color: #a16a94;} -.cm-s-tomorrow-night-bright span.cm-number {color: #a16a94;} - -.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute {color: #99cc99;} -.cm-s-tomorrow-night-bright span.cm-keyword {color: #d54e53;} -.cm-s-tomorrow-night-bright span.cm-string {color: #e7c547;} - -.cm-s-tomorrow-night-bright span.cm-variable {color: #b9ca4a;} -.cm-s-tomorrow-night-bright span.cm-variable-2 {color: #7aa6da;} -.cm-s-tomorrow-night-bright span.cm-def {color: #e78c45;} -.cm-s-tomorrow-night-bright span.cm-bracket {color: #eaeaea;} -.cm-s-tomorrow-night-bright span.cm-tag {color: #d54e53;} -.cm-s-tomorrow-night-bright span.cm-link {color: #a16a94;} -.cm-s-tomorrow-night-bright span.cm-error {background: #d54e53; color: #6A6A6A;} - -.cm-s-tomorrow-night-bright .CodeMirror-activeline-background {background: #2a2a2a !important;} -.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/tomorrow-night-eighties.css b/public/js/lib/codemirror/theme/tomorrow-night-eighties.css deleted file mode 100644 index 841413546c..0000000000 --- a/public/js/lib/codemirror/theme/tomorrow-night-eighties.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Name: Tomorrow Night - Eighties - Author: Chris Kempson - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-tomorrow-night-eighties.CodeMirror {background: #000000; color: #CCCCCC;} -.cm-s-tomorrow-night-eighties div.CodeMirror-selected {background: #2D2D2D !important;} -.cm-s-tomorrow-night-eighties .CodeMirror-gutters {background: #000000; border-right: 0px;} -.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; } -.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-tomorrow-night-eighties .CodeMirror-linenumber {color: #515151;} -.cm-s-tomorrow-night-eighties .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;} - -.cm-s-tomorrow-night-eighties span.cm-comment {color: #d27b53;} -.cm-s-tomorrow-night-eighties span.cm-atom {color: #a16a94;} -.cm-s-tomorrow-night-eighties span.cm-number {color: #a16a94;} - -.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute {color: #99cc99;} -.cm-s-tomorrow-night-eighties span.cm-keyword {color: #f2777a;} -.cm-s-tomorrow-night-eighties span.cm-string {color: #ffcc66;} - -.cm-s-tomorrow-night-eighties span.cm-variable {color: #99cc99;} -.cm-s-tomorrow-night-eighties span.cm-variable-2 {color: #6699cc;} -.cm-s-tomorrow-night-eighties span.cm-def {color: #f99157;} -.cm-s-tomorrow-night-eighties span.cm-bracket {color: #CCCCCC;} -.cm-s-tomorrow-night-eighties span.cm-tag {color: #f2777a;} -.cm-s-tomorrow-night-eighties span.cm-link {color: #a16a94;} -.cm-s-tomorrow-night-eighties span.cm-error {background: #f2777a; color: #6A6A6A;} - -.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background {background: #343600 !important;} -.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/public/js/lib/codemirror/theme/twilight.css b/public/js/lib/codemirror/theme/twilight.css deleted file mode 100644 index 9ca50576d8..0000000000 --- a/public/js/lib/codemirror/theme/twilight.css +++ /dev/null @@ -1,30 +0,0 @@ -.cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/ -.cm-s-twilight .CodeMirror-selected { background: #323232 !important; } /**/ - -.cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; } -.cm-s-twilight .CodeMirror-guttermarker { color: white; } -.cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; } -.cm-s-twilight .CodeMirror-linenumber { color: #aaa; } -.cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-twilight .cm-keyword { color: #f9ee98; } /**/ -.cm-s-twilight .cm-atom { color: #FC0; } -.cm-s-twilight .cm-number { color: #ca7841; } /**/ -.cm-s-twilight .cm-def { color: #8DA6CE; } -.cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/ -.cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def { color: #607392; } /**/ -.cm-s-twilight .cm-operator { color: #cda869; } /**/ -.cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/ -.cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/ -.cm-s-twilight .cm-string-2 { color:#bd6b18 } /*?*/ -.cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/ -.cm-s-twilight .cm-builtin { color: #cda869; } /*?*/ -.cm-s-twilight .cm-tag { color: #997643; } /**/ -.cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/ -.cm-s-twilight .cm-header { color: #FF6400; } -.cm-s-twilight .cm-hr { color: #AEAEAE; } -.cm-s-twilight .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } /**/ -.cm-s-twilight .cm-error { border-bottom: 1px solid red; } - -.cm-s-twilight .CodeMirror-activeline-background {background: #27282E !important;} -.cm-s-twilight .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/public/js/lib/codemirror/theme/vibrant-ink.css b/public/js/lib/codemirror/theme/vibrant-ink.css deleted file mode 100644 index 5177282325..0000000000 --- a/public/js/lib/codemirror/theme/vibrant-ink.css +++ /dev/null @@ -1,32 +0,0 @@ -/* Taken from the popular Visual Studio Vibrant Ink Schema */ - -.cm-s-vibrant-ink.CodeMirror { background: black; color: white; } -.cm-s-vibrant-ink .CodeMirror-selected { background: #35493c !important; } - -.cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; } -.cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-vibrant-ink .cm-keyword { color: #CC7832; } -.cm-s-vibrant-ink .cm-atom { color: #FC0; } -.cm-s-vibrant-ink .cm-number { color: #FFEE98; } -.cm-s-vibrant-ink .cm-def { color: #8DA6CE; } -.cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D } -.cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D } -.cm-s-vibrant-ink .cm-operator { color: #888; } -.cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; } -.cm-s-vibrant-ink .cm-string { color: #A5C25C } -.cm-s-vibrant-ink .cm-string-2 { color: red } -.cm-s-vibrant-ink .cm-meta { color: #D8FA3C; } -.cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-tag { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-header { color: #FF6400; } -.cm-s-vibrant-ink .cm-hr { color: #AEAEAE; } -.cm-s-vibrant-ink .cm-link { color: blue; } -.cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; } - -.cm-s-vibrant-ink .CodeMirror-activeline-background {background: #27282E !important;} -.cm-s-vibrant-ink .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/public/js/lib/codemirror/theme/xq-dark.css b/public/js/lib/codemirror/theme/xq-dark.css deleted file mode 100644 index 116eccf21b..0000000000 --- a/public/js/lib/codemirror/theme/xq-dark.css +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright (C) 2011 by MarkLogic Corporation -Author: Mike Brevoort - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -.cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-selected { background: #27007A !important; } -.cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; } -.cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-xq-dark span.cm-keyword {color: #FFBD40;} -.cm-s-xq-dark span.cm-atom {color: #6C8CD5;} -.cm-s-xq-dark span.cm-number {color: #164;} -.cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;} -.cm-s-xq-dark span.cm-variable {color: #FFF;} -.cm-s-xq-dark span.cm-variable-2 {color: #EEE;} -.cm-s-xq-dark span.cm-variable-3 {color: #DDD;} -.cm-s-xq-dark span.cm-property {} -.cm-s-xq-dark span.cm-operator {} -.cm-s-xq-dark span.cm-comment {color: gray;} -.cm-s-xq-dark span.cm-string {color: #9FEE00;} -.cm-s-xq-dark span.cm-meta {color: yellow;} -.cm-s-xq-dark span.cm-qualifier {color: #FFF700;} -.cm-s-xq-dark span.cm-builtin {color: #30a;} -.cm-s-xq-dark span.cm-bracket {color: #cc7;} -.cm-s-xq-dark span.cm-tag {color: #FFBD40;} -.cm-s-xq-dark span.cm-attribute {color: #FFF700;} -.cm-s-xq-dark span.cm-error {color: #f00;} - -.cm-s-xq-dark .CodeMirror-activeline-background {background: #27282E !important;} -.cm-s-xq-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} \ No newline at end of file diff --git a/public/js/lib/codemirror/theme/xq-light.css b/public/js/lib/codemirror/theme/xq-light.css deleted file mode 100644 index 20b5c79614..0000000000 --- a/public/js/lib/codemirror/theme/xq-light.css +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright (C) 2011 by MarkLogic Corporation -Author: Mike Brevoort - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -.cm-s-xq-light span.cm-keyword {line-height: 1em; font-weight: bold; color: #5A5CAD; } -.cm-s-xq-light span.cm-atom {color: #6C8CD5;} -.cm-s-xq-light span.cm-number {color: #164;} -.cm-s-xq-light span.cm-def {text-decoration:underline;} -.cm-s-xq-light span.cm-variable {color: black; } -.cm-s-xq-light span.cm-variable-2 {color:black;} -.cm-s-xq-light span.cm-variable-3 {color: black; } -.cm-s-xq-light span.cm-property {} -.cm-s-xq-light span.cm-operator {} -.cm-s-xq-light span.cm-comment {color: #0080FF; font-style: italic;} -.cm-s-xq-light span.cm-string {color: red;} -.cm-s-xq-light span.cm-meta {color: yellow;} -.cm-s-xq-light span.cm-qualifier {color: grey} -.cm-s-xq-light span.cm-builtin {color: #7EA656;} -.cm-s-xq-light span.cm-bracket {color: #cc7;} -.cm-s-xq-light span.cm-tag {color: #3F7F7F;} -.cm-s-xq-light span.cm-attribute {color: #7F007F;} -.cm-s-xq-light span.cm-error {color: #f00;} - -.cm-s-xq-light .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-xq-light .CodeMirror-matchingbracket {outline:1px solid grey;color:black !important;background:yellow;} \ No newline at end of file diff --git a/public/js/lib/codemirror/theme/zenburn.css b/public/js/lib/codemirror/theme/zenburn.css deleted file mode 100644 index f817198af0..0000000000 --- a/public/js/lib/codemirror/theme/zenburn.css +++ /dev/null @@ -1,37 +0,0 @@ -/** - * " - * Using Zenburn color palette from the Emacs Zenburn Theme - * https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el - * - * Also using parts of https://github.com/xavi/coderay-lighttable-theme - * " - * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css - */ - -.cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; } -.cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; } -.cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white !important; } -.cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; } -.cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; } -.cm-s-zenburn span.cm-comment { color: #7f9f7f; } -.cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; } -.cm-s-zenburn span.cm-atom { color: #bfebbf; } -.cm-s-zenburn span.cm-def { color: #dcdccc; } -.cm-s-zenburn span.cm-variable { color: #dfaf8f; } -.cm-s-zenburn span.cm-variable-2 { color: #dcdccc; } -.cm-s-zenburn span.cm-string { color: #cc9393; } -.cm-s-zenburn span.cm-string-2 { color: #cc9393; } -.cm-s-zenburn span.cm-number { color: #dcdccc; } -.cm-s-zenburn span.cm-tag { color: #93e0e3; } -.cm-s-zenburn span.cm-property { color: #dfaf8f; } -.cm-s-zenburn span.cm-attribute { color: #dfaf8f; } -.cm-s-zenburn span.cm-qualifier { color: #7cb8bb; } -.cm-s-zenburn span.cm-meta { color: #f0dfaf; } -.cm-s-zenburn span.cm-header { color: #f0efd0; } -.cm-s-zenburn span.cm-operator { color: #f0efd0; } -.cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; } -.cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; } -.cm-s-zenburn .CodeMirror-activeline { background: #000000; } -.cm-s-zenburn .CodeMirror-activeline-background { background: #000000; } -.cm-s-zenburn .CodeMirror-selected { background: #545454; } -.cm-s-zenburn .CodeMirror-focused .CodeMirror-selected { background: #4f4f4f; } diff --git a/public/js/lib/jquery-2.1.1.min.js b/public/js/lib/jquery-2.1.1.min.js deleted file mode 100644 index e5ace116b6..0000000000 --- a/public/js/lib/jquery-2.1.1.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.1",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
      ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b) -},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("